Blame view

net/caif/cfcnfg.c 14.2 KB
af873fcec   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
2
3
  /*
   * Copyright (C) ST-Ericsson AB 2010
26ee65e68   sjur.brandeland@stericsson.com   caif: Remove my b...
4
   * Author:	Sjur Brendeland
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
5
   */
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
6
7
  
  #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
8
9
  #include <linux/kernel.h>
  #include <linux/stddef.h>
6c5799069   Stephen Rothwell   net-caif: using k...
10
  #include <linux/slab.h>
2aa40aef9   Sjur Braendeland   caif: Use link la...
11
  #include <linux/netdevice.h>
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
12
  #include <linux/module.h>
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
13
14
15
16
17
18
19
20
  #include <net/caif/caif_layer.h>
  #include <net/caif/cfpkt.h>
  #include <net/caif/cfcnfg.h>
  #include <net/caif/cfctrl.h>
  #include <net/caif/cfmuxl.h>
  #include <net/caif/cffrml.h>
  #include <net/caif/cfserl.h>
  #include <net/caif/cfsrvl.h>
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
21
  #include <net/caif/caif_dev.h>
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
22
23
24
25
26
27
28
  
  #define container_obj(layr) container_of(layr, struct cfcnfg, layer)
  
  /* Information about CAIF physical interfaces held by Config Module in order
   * to manage physical interfaces
   */
  struct cfcnfg_phyinfo {
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
29
30
  	struct list_head node;
  	bool up;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
31
32
33
34
35
36
37
38
  	/* Pointer to the layer below the MUX (framing layer) */
  	struct cflayer *frm_layer;
  	/* Pointer to the lowest actual physical layer */
  	struct cflayer *phy_layer;
  	/* Unique identifier of the physical interface */
  	unsigned int id;
  	/* Preference of the physical in interface */
  	enum cfcnfg_phy_preference pref;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
39
40
  	/* Information about the physical device */
  	struct dev_info dev_info;
2aa40aef9   Sjur Braendeland   caif: Use link la...
41
42
43
  
  	/* Interface index */
  	int ifindex;
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
44
45
  	/* Protocol head room added for CAIF link layer */
  	int head_room;
2aa40aef9   Sjur Braendeland   caif: Use link la...
46
47
48
  
  	/* Use Start of frame checksum */
  	bool use_fcs;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
49
50
51
52
53
54
  };
  
  struct cfcnfg {
  	struct cflayer layer;
  	struct cflayer *ctrl;
  	struct cflayer *mux;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
55
56
  	struct list_head phys;
  	struct mutex lock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
57
  };
e539d83cc   Sjur Braendeland   caif: Rename func...
58
  static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
59
60
  			      enum cfctrl_srv serv, u8 phyid,
  			      struct cflayer *adapt_layer);
8d545c8f9   Sjur Braendeland   caif: Disconnect ...
61
  static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id);
e539d83cc   Sjur Braendeland   caif: Rename func...
62
  static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
63
  			      struct cflayer *adapt_layer);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
64
65
66
67
68
69
70
  static void cfctrl_resp_func(void);
  static void cfctrl_enum_resp(void);
  
  struct cfcnfg *cfcnfg_create(void)
  {
  	struct cfcnfg *this;
  	struct cfctrl_rsp *resp;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
71
72
  
  	might_sleep();
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
73
  	/* Initiate this layer */
49afa55b5   Julia Lawall   net/caif: Use kza...
74
  	this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC);
7ac2ed0ce   Joe Perches   caif: Remove OOM ...
75
  	if (!this)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
76
  		return NULL;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
77
78
79
80
81
82
83
84
85
86
  	this->mux = cfmuxl_create();
  	if (!this->mux)
  		goto out_of_mem;
  	this->ctrl = cfctrl_create();
  	if (!this->ctrl)
  		goto out_of_mem;
  	/* Initiate response functions */
  	resp = cfctrl_get_respfuncs(this->ctrl);
  	resp->enum_rsp = cfctrl_enum_resp;
  	resp->linkerror_ind = cfctrl_resp_func;
e539d83cc   Sjur Braendeland   caif: Rename func...
87
  	resp->linkdestroy_rsp = cfcnfg_linkdestroy_rsp;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
88
89
90
91
  	resp->sleep_rsp = cfctrl_resp_func;
  	resp->wake_rsp = cfctrl_resp_func;
  	resp->restart_rsp = cfctrl_resp_func;
  	resp->radioset_rsp = cfctrl_resp_func;
e539d83cc   Sjur Braendeland   caif: Rename func...
92
93
  	resp->linksetup_rsp = cfcnfg_linkup_rsp;
  	resp->reject_rsp = cfcnfg_reject_rsp;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
94
  	INIT_LIST_HEAD(&this->phys);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
95
96
97
98
  
  	cfmuxl_set_uplayer(this->mux, this->ctrl, 0);
  	layer_set_dn(this->ctrl, this->mux);
  	layer_set_up(this->ctrl, this);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
99
  	mutex_init(&this->lock);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
100
101
  	return this;
  out_of_mem:
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
102
  	synchronize_rcu();
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
103
104
105
106
107
  	kfree(this->mux);
  	kfree(this->ctrl);
  	kfree(this);
  	return NULL;
  }
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
108
109
110
  
  void cfcnfg_remove(struct cfcnfg *cfg)
  {
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
111
  	might_sleep();
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
112
  	if (cfg) {
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
113
  		synchronize_rcu();
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
114
  		kfree(cfg->mux);
c85c2951d   sjur.brandeland@stericsson.com   caif: Handle dev_...
115
  		cfctrl_remove(cfg->ctrl);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
116
117
118
119
120
121
122
  		kfree(cfg);
  	}
  }
  
  static void cfctrl_resp_func(void)
  {
  }
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
123
  static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo_rcu(struct cfcnfg *cnfg,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
124
  						     u8 phyid)
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
125
126
127
128
129
130
131
132
  {
  	struct cfcnfg_phyinfo *phy;
  
  	list_for_each_entry_rcu(phy, &cnfg->phys, node)
  		if (phy->id == phyid)
  			return phy;
  	return NULL;
  }
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
133
134
135
  static void cfctrl_enum_resp(void)
  {
  }
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
136
  static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
137
138
  				  enum cfcnfg_phy_preference phy_pref)
  {
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
139
  	/* Try to match with specified preference */
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
140
141
142
143
144
145
146
  	struct cfcnfg_phyinfo *phy;
  
  	list_for_each_entry_rcu(phy, &cnfg->phys, node) {
  		if (phy->up && phy->pref == phy_pref &&
  				phy->frm_layer != NULL)
  
  			return &phy->dev_info;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
147
  	}
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
148
149
150
151
  	/* Otherwise just return something */
  	list_for_each_entry_rcu(phy, &cnfg->phys, node)
  		if (phy->up)
  			return &phy->dev_info;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
152

15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
153
154
  	return NULL;
  }
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
155
  static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
156
  {
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
157
158
159
160
161
  	struct cfcnfg_phyinfo *phy;
  
  	list_for_each_entry_rcu(phy, &cnfg->phys, node)
  		if (phy->ifindex == ifi && phy->up)
  			return phy->id;
f2527ec43   AndrĂ© Carvalho de Matos   caif: Bugfix for ...
162
  	return -ENODEV;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
163
  }
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
164
  int caif_disconnect_client(struct net *net, struct cflayer *adap_layer)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
165
  {
54e90fb5c   sjur.brandeland@stericsson.com   caif: Fixes freez...
166
  	u8 channel_id;
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
167
  	struct cfcnfg *cfg = get_cfcnfg(net);
01a859014   Dan Carpenter   caif: checking th...
168

15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
169
  	caif_assert(adap_layer != NULL);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
170
  	cfctrl_cancel_req(cfg->ctrl, adap_layer);
54e90fb5c   sjur.brandeland@stericsson.com   caif: Fixes freez...
171
172
173
174
  	channel_id = adap_layer->id;
  	if (channel_id != 0) {
  		struct cflayer *servl;
  		servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
175
  		cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
54e90fb5c   sjur.brandeland@stericsson.com   caif: Fixes freez...
176
177
178
179
180
  		if (servl != NULL)
  			layer_set_up(servl, NULL);
  	} else
  		pr_debug("nothing to disconnect
  ");
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
181
182
183
  
  	/* Do RCU sync before initiating cleanup */
  	synchronize_rcu();
8d545c8f9   Sjur Braendeland   caif: Disconnect ...
184
185
  	if (adap_layer->ctrlcmd != NULL)
  		adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0);
54e90fb5c   sjur.brandeland@stericsson.com   caif: Fixes freez...
186
  	return 0;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
187
188
  
  }
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
189
  EXPORT_SYMBOL(caif_disconnect_client);
5b2086567   Sjur Braendeland   caif: Add referen...
190

8d545c8f9   Sjur Braendeland   caif: Disconnect ...
191
  static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
192
  {
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
193
  }
73d6ac633   Stephen Hemminger   caif: code cleanup
194
  static const int protohead[CFCTRL_SRV_MASK] = {
2aa40aef9   Sjur Braendeland   caif: Use link la...
195
196
197
198
199
200
  	[CFCTRL_SRV_VEI] = 4,
  	[CFCTRL_SRV_DATAGRAM] = 7,
  	[CFCTRL_SRV_UTIL] = 4,
  	[CFCTRL_SRV_RFM] = 3,
  	[CFCTRL_SRV_DBG] = 3,
  };
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
201
202
  
  static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
203
204
  					  struct caif_connect_request *s,
  					  struct cfctrl_link_param *l)
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
  {
  	struct dev_info *dev_info;
  	enum cfcnfg_phy_preference pref;
  	int res;
  
  	memset(l, 0, sizeof(*l));
  	/* In caif protocol low value is high priority */
  	l->priority = CAIF_PRIO_MAX - s->priority + 1;
  
  	if (s->ifindex != 0) {
  		res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex);
  		if (res < 0)
  			return res;
  		l->phyid = res;
  	} else {
  		switch (s->link_selector) {
  		case CAIF_LINK_HIGH_BANDW:
  			pref = CFPHYPREF_HIGH_BW;
  			break;
  		case CAIF_LINK_LOW_LATENCY:
  			pref = CFPHYPREF_LOW_LAT;
  			break;
  		default:
  			return -EINVAL;
  		}
  		dev_info = cfcnfg_get_phyid(cnfg, pref);
  		if (dev_info == NULL)
  			return -ENODEV;
  		l->phyid = dev_info->id;
  	}
  	switch (s->protocol) {
  	case CAIFPROTO_AT:
  		l->linktype = CFCTRL_SRV_VEI;
  		l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3;
  		l->chtype = s->sockaddr.u.at.type & 0x3;
  		break;
  	case CAIFPROTO_DATAGRAM:
  		l->linktype = CFCTRL_SRV_DATAGRAM;
  		l->chtype = 0x00;
  		l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
  		break;
  	case CAIFPROTO_DATAGRAM_LOOP:
  		l->linktype = CFCTRL_SRV_DATAGRAM;
  		l->chtype = 0x03;
  		l->endpoint = 0x00;
  		l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
  		break;
  	case CAIFPROTO_RFM:
  		l->linktype = CFCTRL_SRV_RFM;
  		l->u.datagram.connid = s->sockaddr.u.rfm.connection_id;
3dc2fa475   Xiongfeng Wang   net: caif: use st...
255
256
  		strlcpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
  			sizeof(l->u.rfm.volume));
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
257
258
259
260
261
  		break;
  	case CAIFPROTO_UTIL:
  		l->linktype = CFCTRL_SRV_UTIL;
  		l->endpoint = 0x00;
  		l->chtype = 0x00;
3dc2fa475   Xiongfeng Wang   net: caif: use st...
262
263
  		strlcpy(l->u.utility.name, s->sockaddr.u.util.service,
  			sizeof(l->u.utility.name));
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
  		caif_assert(sizeof(l->u.utility.name) > 10);
  		l->u.utility.paramlen = s->param.size;
  		if (l->u.utility.paramlen > sizeof(l->u.utility.params))
  			l->u.utility.paramlen = sizeof(l->u.utility.params);
  
  		memcpy(l->u.utility.params, s->param.data,
  		       l->u.utility.paramlen);
  
  		break;
  	case CAIFPROTO_DEBUG:
  		l->linktype = CFCTRL_SRV_DBG;
  		l->endpoint = s->sockaddr.u.dbg.service;
  		l->chtype = s->sockaddr.u.dbg.type;
  		break;
  	default:
  		return -EINVAL;
  	}
  	return 0;
  }
  
  int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
  			struct cflayer *adap_layer, int *ifindex,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
286
  			int *proto_head, int *proto_tail)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
287
288
  {
  	struct cflayer *frml;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
289
290
  	struct cfcnfg_phyinfo *phy;
  	int err;
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
291
292
  	struct cfctrl_link_param param;
  	struct cfcnfg *cfg = get_cfcnfg(net);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
293
294
  
  	rcu_read_lock();
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
295
296
297
298
299
  	err = caif_connect_req_to_link_param(cfg, conn_req, &param);
  	if (err)
  		goto unlock;
  
  	phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
300
301
302
303
304
  	if (!phy) {
  		err = -ENODEV;
  		goto unlock;
  	}
  	err = -EINVAL;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
305
  	if (adap_layer == NULL) {
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
306
307
  		pr_err("adap_layer is zero
  ");
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
308
  		goto unlock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
309
310
  	}
  	if (adap_layer->receive == NULL) {
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
311
312
  		pr_err("adap_layer->receive is NULL
  ");
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
313
  		goto unlock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
314
315
  	}
  	if (adap_layer->ctrlcmd == NULL) {
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
316
317
  		pr_err("adap_layer->ctrlcmd == NULL
  ");
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
318
  		goto unlock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
319
  	}
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
320
321
322
  
  	err = -ENODEV;
  	frml = phy->frm_layer;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
323
  	if (frml == NULL) {
b31fa5bad   Joe Perches   net/caif: Use pr_fmt
324
325
  		pr_err("Specified PHY type does not exist!
  ");
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
326
  		goto unlock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
327
  	}
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
328
  	caif_assert(param.phyid == phy->id);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
329
  	caif_assert(phy->frm_layer->id ==
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
330
  		     param.phyid);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
331
  	caif_assert(phy->phy_layer->id ==
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
332
  		     param.phyid);
2aa40aef9   Sjur Braendeland   caif: Use link la...
333

f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
334
335
  	*ifindex = phy->ifindex;
  	*proto_tail = 2;
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
336
  	*proto_head = protohead[param.linktype] + phy->head_room;
2aa40aef9   Sjur Braendeland   caif: Use link la...
337

f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
338
  	rcu_read_unlock();
2aa40aef9   Sjur Braendeland   caif: Use link la...
339

15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
340
  	/* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
341
342
  	cfctrl_enum_req(cfg->ctrl, param.phyid);
  	return cfctrl_linkup_request(cfg->ctrl, &param, adap_layer);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
343
344
345
346
  
  unlock:
  	rcu_read_unlock();
  	return err;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
347
  }
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
348
  EXPORT_SYMBOL(caif_connect_client);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
349

e539d83cc   Sjur Braendeland   caif: Rename func...
350
  static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
351
  			      struct cflayer *adapt_layer)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
352
353
354
355
356
357
358
  {
  	if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
  		adapt_layer->ctrlcmd(adapt_layer,
  				     CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
  }
  
  static void
e539d83cc   Sjur Braendeland   caif: Rename func...
359
  cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv,
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
360
  		  u8 phyid, struct cflayer *adapt_layer)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
361
362
363
364
  {
  	struct cfcnfg *cnfg = container_obj(layer);
  	struct cflayer *servicel = NULL;
  	struct cfcnfg_phyinfo *phyinfo;
2aa40aef9   Sjur Braendeland   caif: Use link la...
365
  	struct net_device *netdev;
54e90fb5c   sjur.brandeland@stericsson.com   caif: Fixes freez...
366
367
368
369
370
371
372
373
  	if (channel_id == 0) {
  		pr_warn("received channel_id zero
  ");
  		if (adapt_layer != NULL && adapt_layer->ctrlcmd != NULL)
  			adapt_layer->ctrlcmd(adapt_layer,
  						CAIF_CTRLCMD_INIT_FAIL_RSP, 0);
  		return;
  	}
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
374
  	rcu_read_lock();
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
375
  	if (adapt_layer == NULL) {
b09edbd07   Colin Ian King   net caif: insert ...
376
377
  		pr_debug("link setup response but no client exist, send linkdown back
  ");
8d545c8f9   Sjur Braendeland   caif: Disconnect ...
378
  		cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
379
  		goto unlock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
380
381
382
383
  	}
  
  	caif_assert(cnfg != NULL);
  	caif_assert(phyid != 0);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
384
385
386
  
  	phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
  	if (phyinfo == NULL) {
b09edbd07   Colin Ian King   net caif: insert ...
387
388
  		pr_err("ERROR: Link Layer Device disappeared while connecting
  ");
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
389
390
391
392
  		goto unlock;
  	}
  
  	caif_assert(phyinfo != NULL);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
393
394
395
  	caif_assert(phyinfo->id == phyid);
  	caif_assert(phyinfo->phy_layer != NULL);
  	caif_assert(phyinfo->phy_layer->id == phyid);
e539d83cc   Sjur Braendeland   caif: Rename func...
396
  	adapt_layer->id = channel_id;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
397
398
399
  
  	switch (serv) {
  	case CFCTRL_SRV_VEI:
e539d83cc   Sjur Braendeland   caif: Rename func...
400
  		servicel = cfvei_create(channel_id, &phyinfo->dev_info);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
401
402
  		break;
  	case CFCTRL_SRV_DATAGRAM:
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
403
404
  		servicel = cfdgml_create(channel_id,
  					&phyinfo->dev_info);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
405
406
  		break;
  	case CFCTRL_SRV_RFM:
2aa40aef9   Sjur Braendeland   caif: Use link la...
407
  		netdev = phyinfo->dev_info.dev;
a7da1f55a   Sjur Braendeland   caif: Bugfix - RF...
408
  		servicel = cfrfml_create(channel_id, &phyinfo->dev_info,
2aa40aef9   Sjur Braendeland   caif: Use link la...
409
  						netdev->mtu);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
410
411
  		break;
  	case CFCTRL_SRV_UTIL:
e539d83cc   Sjur Braendeland   caif: Rename func...
412
  		servicel = cfutill_create(channel_id, &phyinfo->dev_info);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
413
414
  		break;
  	case CFCTRL_SRV_VIDEO:
e539d83cc   Sjur Braendeland   caif: Rename func...
415
  		servicel = cfvidl_create(channel_id, &phyinfo->dev_info);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
416
417
  		break;
  	case CFCTRL_SRV_DBG:
e539d83cc   Sjur Braendeland   caif: Rename func...
418
  		servicel = cfdbgl_create(channel_id, &phyinfo->dev_info);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
419
420
  		break;
  	default:
b09edbd07   Colin Ian King   net caif: insert ...
421
422
  		pr_err("Protocol error. Link setup response - unknown channel type
  ");
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
423
  		goto unlock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
424
  	}
7ac2ed0ce   Joe Perches   caif: Remove OOM ...
425
  	if (!servicel)
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
426
  		goto unlock;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
427
  	layer_set_dn(servicel, cnfg->mux);
e539d83cc   Sjur Braendeland   caif: Rename func...
428
  	cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
429
430
  	layer_set_up(servicel, adapt_layer);
  	layer_set_dn(adapt_layer, servicel);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
431
432
  
  	rcu_read_unlock();
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
433
  	servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
434
435
436
  	return;
  unlock:
  	rcu_read_unlock();
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
437
438
439
  }
  
  void
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
440
  cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
2aa40aef9   Sjur Braendeland   caif: Use link la...
441
  		     struct net_device *dev, struct cflayer *phy_layer,
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
442
  		     enum cfcnfg_phy_preference pref,
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
443
444
  		     struct cflayer *link_support,
  		     bool fcs, int head_room)
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
445
446
  {
  	struct cflayer *frml;
5bb20ed86   Dan Carpenter   caif: add error h...
447
  	struct cfcnfg_phyinfo *phyinfo = NULL;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
448
  	int i;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
449
  	u8 phyid;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
450

f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
451
  	mutex_lock(&cnfg->lock);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
452

f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
453
454
455
456
457
458
459
  	/* CAIF protocol allow maximum 6 link-layers */
  	for (i = 0; i < 7; i++) {
  		phyid = (dev->ifindex + i) & 0x7;
  		if (phyid == 0)
  			continue;
  		if (cfcnfg_get_phyinfo_rcu(cnfg, phyid) == NULL)
  			goto got_phyid;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
460
  	}
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
461
462
  	pr_warn("Too many CAIF Link Layers (max 6)
  ");
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
463
  	goto out;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
464
465
466
  
  got_phyid:
  	phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
5bb20ed86   Dan Carpenter   caif: add error h...
467
468
  	if (!phyinfo)
  		goto out_err;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
469

f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
470
471
472
473
474
475
476
  	phy_layer->id = phyid;
  	phyinfo->pref = pref;
  	phyinfo->id = phyid;
  	phyinfo->dev_info.id = phyid;
  	phyinfo->dev_info.dev = dev;
  	phyinfo->phy_layer = phy_layer;
  	phyinfo->ifindex = dev->ifindex;
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
477
  	phyinfo->head_room = head_room;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
478
  	phyinfo->use_fcs = fcs;
2aa40aef9   Sjur Braendeland   caif: Use link la...
479

f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
480
  	frml = cffrml_create(phyid, fcs);
5bb20ed86   Dan Carpenter   caif: add error h...
481
482
  	if (!frml)
  		goto out_err;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
483
  	phyinfo->frm_layer = frml;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
484
  	layer_set_up(frml, cnfg->mux);
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
485
486
487
488
489
490
  	if (link_support != NULL) {
  		link_support->id = phyid;
  		layer_set_dn(frml, link_support);
  		layer_set_up(link_support, frml);
  		layer_set_dn(link_support, phy_layer);
  		layer_set_up(phy_layer, link_support);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
491
492
493
494
  	} else {
  		layer_set_dn(frml, phy_layer);
  		layer_set_up(phy_layer, frml);
  	}
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
495
496
  
  	list_add_rcu(&phyinfo->node, &cnfg->phys);
7c18d2205   sjur.brandeland@stericsson.com   caif: Restructure...
497
  out:
5bb20ed86   Dan Carpenter   caif: add error h...
498
499
500
501
  	mutex_unlock(&cnfg->lock);
  	return;
  
  out_err:
5bb20ed86   Dan Carpenter   caif: add error h...
502
  	kfree(phyinfo);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
503
  	mutex_unlock(&cnfg->lock);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
504
505
  }
  EXPORT_SYMBOL(cfcnfg_add_phy_layer);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
506
  int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer,
3bffc475f   Silviu-Mihai Popescu   CAIF: fix indenta...
507
  			 bool up)
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
  {
  	struct cfcnfg_phyinfo *phyinfo;
  
  	rcu_read_lock();
  	phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phy_layer->id);
  	if (phyinfo == NULL) {
  		rcu_read_unlock();
  		return -ENODEV;
  	}
  
  	if (phyinfo->up == up) {
  		rcu_read_unlock();
  		return 0;
  	}
  	phyinfo->up = up;
  
  	if (up) {
  		cffrml_hold(phyinfo->frm_layer);
  		cfmuxl_set_dnlayer(cnfg->mux, phyinfo->frm_layer,
  					phy_layer->id);
  	} else {
  		cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id);
  		cffrml_put(phyinfo->frm_layer);
  	}
  
  	rcu_read_unlock();
  	return 0;
  }
  EXPORT_SYMBOL(cfcnfg_set_phy_state);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
537
538
539
540
  int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer)
  {
  	struct cflayer *frml, *frml_dn;
  	u16 phyid;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
541
542
543
544
545
  	struct cfcnfg_phyinfo *phyinfo;
  
  	might_sleep();
  
  	mutex_lock(&cnfg->lock);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
546
  	phyid = phy_layer->id;
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
547
  	phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
548
549
  	if (phyinfo == NULL) {
  		mutex_unlock(&cnfg->lock);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
550
  		return 0;
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
551
  	}
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
552
553
  	caif_assert(phyid == phyinfo->id);
  	caif_assert(phy_layer == phyinfo->phy_layer);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
554
  	caif_assert(phy_layer->id == phyid);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
555
  	caif_assert(phyinfo->frm_layer->id == phyid);
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
556
557
  	list_del_rcu(&phyinfo->node);
  	synchronize_rcu();
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
558
559
560
561
  	/* Fail if reference count is not zero */
  	if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) {
  		pr_info("Wait for device inuse
  ");
bee925db9   sjur.brandeland@stericsson.com   caif: prepare sup...
562
  		list_add_rcu(&phyinfo->node, &cnfg->phys);
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
563
564
565
  		mutex_unlock(&cnfg->lock);
  		return -EAGAIN;
  	}
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
566
  	frml = phyinfo->frm_layer;
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
567
568
569
  	frml_dn = frml->dn;
  	cffrml_set_uplayer(frml, NULL);
  	cffrml_set_dnlayer(frml, NULL);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
570
571
572
  	if (phy_layer != frml_dn) {
  		layer_set_up(frml_dn, NULL);
  		layer_set_dn(frml_dn, NULL);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
573
574
  	}
  	layer_set_up(phy_layer, NULL);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
575

f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
576
577
  	if (phyinfo->phy_layer != frml_dn)
  		kfree(frml_dn);
cb3cb423a   sjur.brandeland@stericsson.com   caif: Add ref-cou...
578
  	cffrml_free(frml);
f36214408   sjur.brandeland@stericsson.com   caif: Use RCU and...
579
580
  	kfree(phyinfo);
  	mutex_unlock(&cnfg->lock);
15c9ac0c8   Sjur Braendeland   net-caif: add CAI...
581
582
583
  	return 0;
  }
  EXPORT_SYMBOL(cfcnfg_del_phy_layer);