Blame view

net/caif/cfsrvl.c 5.51 KB
b482cd205   Sjur Braendeland   net-caif: add CAI...
1
2
3
4
5
  /*
   * Copyright (C) ST-Ericsson AB 2010
   * Author:	Sjur Brendeland/sjur.brandeland@stericsson.com
   * License terms: GNU General Public License (GPL) version 2
   */
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
6
  #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
b482cd205   Sjur Braendeland   net-caif: add CAI...
7
8
9
10
  #include <linux/kernel.h>
  #include <linux/types.h>
  #include <linux/errno.h>
  #include <linux/slab.h>
43e369210   sjur.brandeland@stericsson.com   caif: Move refcou...
11
  #include <linux/module.h>
b482cd205   Sjur Braendeland   net-caif: add CAI...
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  #include <net/caif/caif_layer.h>
  #include <net/caif/cfsrvl.h>
  #include <net/caif/cfpkt.h>
  
  #define SRVL_CTRL_PKT_SIZE 1
  #define SRVL_FLOW_OFF 0x81
  #define SRVL_FLOW_ON  0x80
  #define SRVL_SET_PIN  0x82
  #define SRVL_CTRL_PKT_SIZE 1
  
  #define container_obj(layr) container_of(layr, struct cfsrvl, layer)
  
  static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl,
  				int phyid)
  {
  	struct cfsrvl *service = container_obj(layr);
b1c74247b   Sjur Braendeland   caif: Bugfix not ...
28

43e369210   sjur.brandeland@stericsson.com   caif: Move refcou...
29
30
  	if (layr->up == NULL || layr->up->ctrlcmd == NULL)
  		return;
b1c74247b   Sjur Braendeland   caif: Bugfix not ...
31

b482cd205   Sjur Braendeland   net-caif: add CAI...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
  	switch (ctrl) {
  	case CAIF_CTRLCMD_INIT_RSP:
  		service->open = true;
  		layr->up->ctrlcmd(layr->up, ctrl, phyid);
  		break;
  	case CAIF_CTRLCMD_DEINIT_RSP:
  	case CAIF_CTRLCMD_INIT_FAIL_RSP:
  		service->open = false;
  		layr->up->ctrlcmd(layr->up, ctrl, phyid);
  		break;
  	case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND:
  		if (phyid != service->dev_info.id)
  			break;
  		if (service->modem_flow_on)
  			layr->up->ctrlcmd(layr->up,
  					  CAIF_CTRLCMD_FLOW_OFF_IND, phyid);
  		service->phy_flow_on = false;
  		break;
  	case _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND:
  		if (phyid != service->dev_info.id)
  			return;
  		if (service->modem_flow_on) {
  			layr->up->ctrlcmd(layr->up,
  					   CAIF_CTRLCMD_FLOW_ON_IND,
  					   phyid);
  		}
  		service->phy_flow_on = true;
  		break;
  	case CAIF_CTRLCMD_FLOW_OFF_IND:
  		if (service->phy_flow_on) {
  			layr->up->ctrlcmd(layr->up,
  					  CAIF_CTRLCMD_FLOW_OFF_IND, phyid);
  		}
  		service->modem_flow_on = false;
  		break;
  	case CAIF_CTRLCMD_FLOW_ON_IND:
  		if (service->phy_flow_on) {
  			layr->up->ctrlcmd(layr->up,
  					  CAIF_CTRLCMD_FLOW_ON_IND, phyid);
  		}
  		service->modem_flow_on = true;
  		break;
  	case _CAIF_CTRLCMD_PHYIF_DOWN_IND:
  		/* In case interface is down, let's fake a remove shutdown */
  		layr->up->ctrlcmd(layr->up,
  				CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND, phyid);
  		break;
  	case CAIF_CTRLCMD_REMOTE_SHUTDOWN_IND:
  		layr->up->ctrlcmd(layr->up, ctrl, phyid);
  		break;
  	default:
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
83
84
  		pr_warn("Unexpected ctrl in cfsrvl (%d)
  ", ctrl);
b482cd205   Sjur Braendeland   net-caif: add CAI...
85
86
87
88
89
90
91
92
93
94
  		/* We have both modem and phy flow on, send flow on */
  		layr->up->ctrlcmd(layr->up, ctrl, phyid);
  		service->phy_flow_on = true;
  		break;
  	}
  }
  
  static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl)
  {
  	struct cfsrvl *service = container_obj(layr);
b1c74247b   Sjur Braendeland   caif: Bugfix not ...
95

b482cd205   Sjur Braendeland   net-caif: add CAI...
96
97
98
  	caif_assert(layr != NULL);
  	caif_assert(layr->dn != NULL);
  	caif_assert(layr->dn->transmit != NULL);
b1c74247b   Sjur Braendeland   caif: Bugfix not ...
99
100
101
  
  	if (!service->supports_flowctrl)
  		return 0;
b482cd205   Sjur Braendeland   net-caif: add CAI...
102
103
104
105
106
107
108
  	switch (ctrl) {
  	case CAIF_MODEMCMD_FLOW_ON_REQ:
  		{
  			struct cfpkt *pkt;
  			struct caif_payload_info *info;
  			u8 flow_on = SRVL_FLOW_ON;
  			pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
7ac2ed0ce   Joe Perches   caif: Remove OOM ...
109
  			if (!pkt)
b482cd205   Sjur Braendeland   net-caif: add CAI...
110
  				return -ENOMEM;
b482cd205   Sjur Braendeland   net-caif: add CAI...
111
112
  
  			if (cfpkt_add_head(pkt, &flow_on, 1) < 0) {
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
113
114
  				pr_err("Packet is erroneous!
  ");
b482cd205   Sjur Braendeland   net-caif: add CAI...
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
  				cfpkt_destroy(pkt);
  				return -EPROTO;
  			}
  			info = cfpkt_info(pkt);
  			info->channel_id = service->layer.id;
  			info->hdr_len = 1;
  			info->dev_info = &service->dev_info;
  			return layr->dn->transmit(layr->dn, pkt);
  		}
  	case CAIF_MODEMCMD_FLOW_OFF_REQ:
  		{
  			struct cfpkt *pkt;
  			struct caif_payload_info *info;
  			u8 flow_off = SRVL_FLOW_OFF;
  			pkt = cfpkt_create(SRVL_CTRL_PKT_SIZE);
7ac2ed0ce   Joe Perches   caif: Remove OOM ...
130
  			if (!pkt)
638e628a6   Sjur Braendeland   caif: Bugfix - ha...
131
  				return -ENOMEM;
638e628a6   Sjur Braendeland   caif: Bugfix - ha...
132

b482cd205   Sjur Braendeland   net-caif: add CAI...
133
  			if (cfpkt_add_head(pkt, &flow_off, 1) < 0) {
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
134
135
  				pr_err("Packet is erroneous!
  ");
b482cd205   Sjur Braendeland   net-caif: add CAI...
136
137
138
139
140
141
142
143
144
145
146
147
148
149
  				cfpkt_destroy(pkt);
  				return -EPROTO;
  			}
  			info = cfpkt_info(pkt);
  			info->channel_id = service->layer.id;
  			info->hdr_len = 1;
  			info->dev_info = &service->dev_info;
  			return layr->dn->transmit(layr->dn, pkt);
  		}
  	default:
  	  break;
  	}
  	return -EINVAL;
  }
43e369210   sjur.brandeland@stericsson.com   caif: Move refcou...
150
  static void cfsrvl_release(struct cflayer *layer)
a7da1f55a   Sjur Braendeland   caif: Bugfix - RF...
151
  {
43e369210   sjur.brandeland@stericsson.com   caif: Move refcou...
152
  	struct cfsrvl *service = container_of(layer, struct cfsrvl, layer);
a7da1f55a   Sjur Braendeland   caif: Bugfix - RF...
153
154
  	kfree(service);
  }
b482cd205   Sjur Braendeland   net-caif: add CAI...
155
  void cfsrvl_init(struct cfsrvl *service,
b1c74247b   Sjur Braendeland   caif: Bugfix not ...
156
157
158
159
  			u8 channel_id,
  			struct dev_info *dev_info,
  			bool supports_flowctrl
  			)
b482cd205   Sjur Braendeland   net-caif: add CAI...
160
161
162
163
164
165
166
167
168
  {
  	caif_assert(offsetof(struct cfsrvl, layer) == 0);
  	service->open = false;
  	service->modem_flow_on = true;
  	service->phy_flow_on = true;
  	service->layer.id = channel_id;
  	service->layer.ctrlcmd = cfservl_ctrlcmd;
  	service->layer.modemcmd = cfservl_modemcmd;
  	service->dev_info = *dev_info;
b1c74247b   Sjur Braendeland   caif: Bugfix not ...
169
  	service->supports_flowctrl = supports_flowctrl;
a7da1f55a   Sjur Braendeland   caif: Bugfix - RF...
170
  	service->release = cfsrvl_release;
5b2086567   Sjur Braendeland   caif: Add referen...
171
  }
b482cd205   Sjur Braendeland   net-caif: add CAI...
172
173
174
175
176
177
178
179
180
181
182
183
  bool cfsrvl_ready(struct cfsrvl *service, int *err)
  {
  	if (service->open && service->modem_flow_on && service->phy_flow_on)
  		return true;
  	if (!service->open) {
  		*err = -ENOTCONN;
  		return false;
  	}
  	caif_assert(!(service->modem_flow_on && service->phy_flow_on));
  	*err = -EAGAIN;
  	return false;
  }
43e369210   sjur.brandeland@stericsson.com   caif: Move refcou...
184

b482cd205   Sjur Braendeland   net-caif: add CAI...
185
186
187
188
189
190
191
192
193
194
195
  u8 cfsrvl_getphyid(struct cflayer *layer)
  {
  	struct cfsrvl *servl = container_obj(layer);
  	return servl->dev_info.id;
  }
  
  bool cfsrvl_phyid_match(struct cflayer *layer, int phyid)
  {
  	struct cfsrvl *servl = container_obj(layer);
  	return servl->dev_info.id == phyid;
  }
43e369210   sjur.brandeland@stericsson.com   caif: Move refcou...
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
  
  void caif_free_client(struct cflayer *adap_layer)
  {
  	struct cfsrvl *servl;
  	if (adap_layer == NULL || adap_layer->dn == NULL)
  		return;
  	servl = container_obj(adap_layer->dn);
  	servl->release(&servl->layer);
  }
  EXPORT_SYMBOL(caif_free_client);
  
  void caif_client_register_refcnt(struct cflayer *adapt_layer,
  					void (*hold)(struct cflayer *lyr),
  					void (*put)(struct cflayer *lyr))
  {
  	struct cfsrvl *service;
  	service = container_of(adapt_layer->dn, struct cfsrvl, layer);
  
  	WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL);
  	service->hold = hold;
  	service->put = put;
  }
  EXPORT_SYMBOL(caif_client_register_refcnt);