Commit bee925db9a77a5736596dcf6f91d0879f5ee915b

Authored by sjur.brandeland@stericsson.com
Committed by David S. Miller
1 parent b3ccfbe409

caif: prepare support for namespaces

Use struct net to reference CAIF configuration object instead of static variables.
Refactor functions caif_connect_client, caif_disconnect_client and squach
files cfcnfg.c and caif_config_utils.

Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

Showing 8 changed files with 176 additions and 261 deletions Side-by-side Diff

include/net/caif/caif_dev.h
... ... @@ -11,6 +11,7 @@
11 11 #include <net/caif/cfcnfg.h>
12 12 #include <linux/caif/caif_socket.h>
13 13 #include <linux/if.h>
  14 +#include <linux/net.h>
14 15  
15 16 /**
16 17 * struct caif_param - CAIF parameters.
17 18  
18 19  
19 20  
... ... @@ -62,17 +63,19 @@
62 63 * E.g. CAIF Socket will call this function for each socket it connects
63 64 * and have one client_layer instance for each socket.
64 65 */
65   -int caif_connect_client(struct caif_connect_request *conn_req,
  66 +int caif_connect_client(struct net *net,
  67 + struct caif_connect_request *conn_req,
66 68 struct cflayer *client_layer, int *ifindex,
67 69 int *headroom, int *tailroom);
68 70  
69 71 /**
70 72 * caif_disconnect_client - Disconnects a client from the CAIF stack.
71 73 *
72   - * @client_layer: Client layer to be removed.
  74 + * @client_layer: Client layer to be disconnected.
73 75 */
74   -int caif_disconnect_client(struct cflayer *client_layer);
  76 +int caif_disconnect_client(struct net *net, struct cflayer *client_layer);
75 77  
  78 +
76 79 /**
77 80 * caif_client_register_refcnt - register ref-count functions provided by client.
78 81 *
... ... @@ -90,21 +93,6 @@
90 93 void caif_client_register_refcnt(struct cflayer *adapt_layer,
91 94 void (*hold)(struct cflayer *lyr),
92 95 void (*put)(struct cflayer *lyr));
93   -/**
94   - * caif_connect_req_to_link_param - Translate configuration parameters
95   - * from socket format to internal format.
96   - * @cnfg: Pointer to configuration handler
97   - * @con_req: Configuration parameters supplied in function
98   - * caif_connect_client
99   - * @channel_setup_param: Parameters supplied to the CAIF Core stack for
100   - * setting up channels.
101   - *
102   - */
103   -
104   -int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
105   - struct caif_connect_request *con_req,
106   - struct cfctrl_link_param *setup_param);
107   -
108 96 /**
109 97 * caif_free_client - Free memory used to manage the client in the CAIF Stack.
110 98 *
include/net/caif/cfcnfg.h
... ... @@ -46,6 +46,12 @@
46 46 };
47 47  
48 48 /**
  49 + * cfcnfg_create() - Get the CAIF configuration object given network.
  50 + * @net: Network for the CAIF configuration object.
  51 + */
  52 +struct cfcnfg *get_cfcnfg(struct net *net);
  53 +
  54 +/**
49 55 * cfcnfg_create() - Create the CAIF configuration object.
50 56 */
51 57 struct cfcnfg *cfcnfg_create(void);
52 58  
53 59  
... ... @@ -65,17 +71,15 @@
65 71 * @dev: Pointer to link layer device
66 72 * @phy_layer: Specify the physical layer. The transmit function
67 73 * MUST be set in the structure.
68   - * @phyid: The assigned physical ID for this layer, used in
69   - * cfcnfg_add_adapt_layer to specify PHY for the link.
70 74 * @pref: The phy (link layer) preference.
71 75 * @fcs: Specify if checksum is used in CAIF Framing Layer.
72   - * @stx: Specify if Start Of Frame extension is used.
  76 + * @stx: Specify if Start Of Frame eXtention is used.
73 77 */
74 78  
75 79 void
76 80 cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
77 81 struct net_device *dev, struct cflayer *phy_layer,
78   - u16 *phyid, enum cfcnfg_phy_preference pref,
  82 + enum cfcnfg_phy_preference pref,
79 83 bool fcs, bool stx);
80 84  
81 85 /**
... ... @@ -86,65 +90,6 @@
86 90 * @phy_layer: Adaptation layer to be removed.
87 91 */
88 92 int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer);
89   -
90   -/**
91   - * cfcnfg_disconn_adapt_layer - Disconnects an adaptation layer.
92   - *
93   - * @cnfg: Pointer to a CAIF configuration object, created by
94   - * cfcnfg_create().
95   - * @adap_layer: Adaptation layer to be removed.
96   - */
97   -int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg,
98   - struct cflayer *adap_layer);
99   -
100   -/**
101   - * cfcnfg_release_adap_layer - Used by client to release the adaptation layer.
102   - *
103   - * @adap_layer: Adaptation layer.
104   - */
105   -void cfcnfg_release_adap_layer(struct cflayer *adap_layer);
106   -
107   -/**
108   - * cfcnfg_add_adaptation_layer - Add an adaptation layer to the CAIF stack.
109   - *
110   - * The adaptation Layer is where the interface to application or higher-level
111   - * driver functionality is implemented.
112   - *
113   - * @cnfg: Pointer to a CAIF configuration object, created by
114   - * cfcnfg_create().
115   - * @param: Link setup parameters.
116   - * @adap_layer: Specify the adaptation layer; the receive and
117   - * flow-control functions MUST be set in the structure.
118   - * @ifindex: Link layer interface index used for this connection.
119   - * @proto_head: Protocol head-space needed by CAIF protocol,
120   - * excluding link layer.
121   - * @proto_tail: Protocol tail-space needed by CAIF protocol,
122   - * excluding link layer.
123   - */
124   -int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
125   - struct cfctrl_link_param *param,
126   - struct cflayer *adap_layer,
127   - int *ifindex,
128   - int *proto_head,
129   - int *proto_tail);
130   -
131   -/**
132   - * cfcnfg_get_phyid() - Get physical ID, given type.
133   - * Returns one of the physical interfaces matching the given type.
134   - * Zero if no match is found.
135   - * @cnfg: Configuration object
136   - * @phy_pref: Caif Link Layer preference
137   - */
138   -struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
139   - enum cfcnfg_phy_preference phy_pref);
140   -
141   -/**
142   - * cfcnfg_get_id_from_ifi() - Get the Physical Identifier of ifindex,
143   - * it matches caif physical id with the kernel interface id.
144   - * @cnfg: Configuration object
145   - * @ifi: ifindex obtained from socket.c bindtodevice.
146   - */
147   -int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi);
148 93  
149 94 /**
150 95 * cfcnfg_set_phy_state() - Set the state of the physical interface device.
... ... @@ -5,7 +5,7 @@
5 5 cffrml.o cfveil.o cfdbgl.o\
6 6 cfserl.o cfdgml.o \
7 7 cfrfml.o cfvidl.o cfutill.o \
8   - cfsrvl.o cfpkt_skbuff.o caif_config_util.o
  8 + cfsrvl.o cfpkt_skbuff.o
9 9  
10 10 obj-$(CONFIG_CAIF) += caif.o
11 11 obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o
net/caif/caif_config_util.c
1   -/*
2   - * Copyright (C) ST-Ericsson AB 2010
3   - * Author: Sjur Brendeland sjur.brandeland@stericsson.com
4   - * License terms: GNU General Public License (GPL) version 2
5   - */
6   -
7   -#include <linux/module.h>
8   -#include <linux/spinlock.h>
9   -#include <net/caif/cfctrl.h>
10   -#include <net/caif/cfcnfg.h>
11   -#include <net/caif/caif_dev.h>
12   -
13   -int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
14   - struct caif_connect_request *s,
15   - struct cfctrl_link_param *l)
16   -{
17   - struct dev_info *dev_info;
18   - enum cfcnfg_phy_preference pref;
19   - int res;
20   -
21   - memset(l, 0, sizeof(*l));
22   - /* In caif protocol low value is high priority */
23   - l->priority = CAIF_PRIO_MAX - s->priority + 1;
24   -
25   - if (s->ifindex != 0){
26   - res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex);
27   - if (res < 0)
28   - return res;
29   - l->phyid = res;
30   - }
31   - else {
32   - switch (s->link_selector) {
33   - case CAIF_LINK_HIGH_BANDW:
34   - pref = CFPHYPREF_HIGH_BW;
35   - break;
36   - case CAIF_LINK_LOW_LATENCY:
37   - pref = CFPHYPREF_LOW_LAT;
38   - break;
39   - default:
40   - return -EINVAL;
41   - }
42   - dev_info = cfcnfg_get_phyid(cnfg, pref);
43   - if (dev_info == NULL)
44   - return -ENODEV;
45   - l->phyid = dev_info->id;
46   - }
47   - switch (s->protocol) {
48   - case CAIFPROTO_AT:
49   - l->linktype = CFCTRL_SRV_VEI;
50   - if (s->sockaddr.u.at.type == CAIF_ATTYPE_PLAIN)
51   - l->chtype = 0x02;
52   - else
53   - l->chtype = s->sockaddr.u.at.type;
54   - l->endpoint = 0x00;
55   - break;
56   - case CAIFPROTO_DATAGRAM:
57   - l->linktype = CFCTRL_SRV_DATAGRAM;
58   - l->chtype = 0x00;
59   - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
60   - break;
61   - case CAIFPROTO_DATAGRAM_LOOP:
62   - l->linktype = CFCTRL_SRV_DATAGRAM;
63   - l->chtype = 0x03;
64   - l->endpoint = 0x00;
65   - l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
66   - break;
67   - case CAIFPROTO_RFM:
68   - l->linktype = CFCTRL_SRV_RFM;
69   - l->u.datagram.connid = s->sockaddr.u.rfm.connection_id;
70   - strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
71   - sizeof(l->u.rfm.volume)-1);
72   - l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0;
73   - break;
74   - case CAIFPROTO_UTIL:
75   - l->linktype = CFCTRL_SRV_UTIL;
76   - l->endpoint = 0x00;
77   - l->chtype = 0x00;
78   - strncpy(l->u.utility.name, s->sockaddr.u.util.service,
79   - sizeof(l->u.utility.name)-1);
80   - l->u.utility.name[sizeof(l->u.utility.name)-1] = 0;
81   - caif_assert(sizeof(l->u.utility.name) > 10);
82   - l->u.utility.paramlen = s->param.size;
83   - if (l->u.utility.paramlen > sizeof(l->u.utility.params))
84   - l->u.utility.paramlen = sizeof(l->u.utility.params);
85   -
86   - memcpy(l->u.utility.params, s->param.data,
87   - l->u.utility.paramlen);
88   -
89   - break;
90   - case CAIFPROTO_DEBUG:
91   - l->linktype = CFCTRL_SRV_DBG;
92   - l->endpoint = s->sockaddr.u.dbg.service;
93   - l->chtype = s->sockaddr.u.dbg.type;
94   - break;
95   - default:
96   - return -EINVAL;
97   - }
98   - return 0;
99   -}
... ... @@ -21,7 +21,6 @@
21 21 #include <net/net_namespace.h>
22 22 #include <net/pkt_sched.h>
23 23 #include <net/caif/caif_device.h>
24   -#include <net/caif/caif_dev.h>
25 24 #include <net/caif/caif_layer.h>
26 25 #include <net/caif/cfpkt.h>
27 26 #include <net/caif/cfcnfg.h>
28 27  
29 28  
... ... @@ -43,12 +42,22 @@
43 42 };
44 43  
45 44 struct caif_net {
  45 + struct cfcnfg *cfg;
46 46 struct caif_device_entry_list caifdevs;
47 47 };
48 48  
49 49 static int caif_net_id;
50   -static struct cfcnfg *cfg;
51 50  
  51 +struct cfcnfg *get_cfcnfg(struct net *net)
  52 +{
  53 + struct caif_net *caifn;
  54 + BUG_ON(!net);
  55 + caifn = net_generic(net, caif_net_id);
  56 + BUG_ON(!caifn);
  57 + return caifn->cfg;
  58 +}
  59 +EXPORT_SYMBOL(get_cfcnfg);
  60 +
52 61 static struct caif_device_entry_list *caif_device_list(struct net *net)
53 62 {
54 63 struct caif_net *caifn;
55 64  
... ... @@ -191,12 +200,17 @@
191 200 struct caif_dev_common *caifdev;
192 201 enum cfcnfg_phy_preference pref;
193 202 enum cfcnfg_phy_type phy_type;
  203 + struct cfcnfg *cfg;
194 204 struct caif_device_entry_list *caifdevs =
195 205 caif_device_list(dev_net(dev));
196 206  
197 207 if (dev->type != ARPHRD_CAIF)
198 208 return 0;
199 209  
  210 + cfg = get_cfcnfg(dev_net(dev));
  211 + if (cfg == NULL)
  212 + return 0;
  213 +
200 214 switch (what) {
201 215 case NETDEV_REGISTER:
202 216 caifd = caif_device_alloc(dev);
... ... @@ -235,7 +249,6 @@
235 249 phy_type,
236 250 dev,
237 251 &caifd->layer,
238   - 0,
239 252 pref,
240 253 caifdev->use_fcs,
241 254 caifdev->use_stx);
242 255  
243 256  
... ... @@ -323,35 +336,20 @@
323 336 .priority = 0,
324 337 };
325 338  
326   -int caif_connect_client(struct caif_connect_request *conn_req,
327   - struct cflayer *client_layer, int *ifindex,
328   - int *headroom, int *tailroom)
329   -{
330   - struct cfctrl_link_param param;
331   - int ret;
332   -
333   - ret = caif_connect_req_to_link_param(cfg, conn_req, &param);
334   - if (ret)
335   - return ret;
336   - /* Hook up the adaptation layer. */
337   - return cfcnfg_add_adaptation_layer(cfg, &param,
338   - client_layer, ifindex,
339   - headroom, tailroom);
340   -}
341   -EXPORT_SYMBOL(caif_connect_client);
342   -
343   -int caif_disconnect_client(struct cflayer *adap_layer)
344   -{
345   - return cfcnfg_disconn_adapt_layer(cfg, adap_layer);
346   -}
347   -EXPORT_SYMBOL(caif_disconnect_client);
348   -
349 339 /* Per-namespace Caif devices handling */
350 340 static int caif_init_net(struct net *net)
351 341 {
352 342 struct caif_net *caifn = net_generic(net, caif_net_id);
  343 + BUG_ON(!caifn);
353 344 INIT_LIST_HEAD(&caifn->caifdevs.list);
354 345 mutex_init(&caifn->caifdevs.lock);
  346 +
  347 + caifn->cfg = cfcnfg_create();
  348 + if (!caifn->cfg) {
  349 + pr_warn("can't create cfcnfg\n");
  350 + return -ENOMEM;
  351 + }
  352 +
355 353 return 0;
356 354 }
357 355  
358 356  
... ... @@ -360,10 +358,17 @@
360 358 struct caif_device_entry *caifd, *tmp;
361 359 struct caif_device_entry_list *caifdevs =
362 360 caif_device_list(net);
  361 + struct cfcnfg *cfg;
363 362  
364 363 rtnl_lock();
365 364 mutex_lock(&caifdevs->lock);
366 365  
  366 + cfg = get_cfcnfg(net);
  367 + if (cfg == NULL) {
  368 + mutex_unlock(&caifdevs->lock);
  369 + return;
  370 + }
  371 +
367 372 list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) {
368 373 int i = 0;
369 374 list_del_rcu(&caifd->list);
370 375  
... ... @@ -382,8 +387,8 @@
382 387 free_percpu(caifd->pcpu_refcnt);
383 388 kfree(caifd);
384 389 }
  390 + cfcnfg_remove(cfg);
385 391  
386   -
387 392 mutex_unlock(&caifdevs->lock);
388 393 rtnl_unlock();
389 394 }
390 395  
391 396  
392 397  
393 398  
394 399  
395 400  
... ... @@ -400,32 +405,22 @@
400 405 {
401 406 int result;
402 407  
403   - cfg = cfcnfg_create();
404   - if (!cfg) {
405   - pr_warn("can't create cfcnfg\n");
406   - goto err_cfcnfg_create_failed;
407   - }
408 408 result = register_pernet_device(&caif_net_ops);
409 409  
410   - if (result) {
411   - kfree(cfg);
412   - cfg = NULL;
  410 + if (result)
413 411 return result;
414   - }
415   - dev_add_pack(&caif_packet_type);
  412 +
416 413 register_netdevice_notifier(&caif_device_notifier);
  414 + dev_add_pack(&caif_packet_type);
417 415  
418 416 return result;
419   -err_cfcnfg_create_failed:
420   - return -ENODEV;
421 417 }
422 418  
423 419 static void __exit caif_device_exit(void)
424 420 {
425   - dev_remove_pack(&caif_packet_type);
426 421 unregister_pernet_device(&caif_net_ops);
427 422 unregister_netdevice_notifier(&caif_device_notifier);
428   - cfcnfg_remove(cfg);
  423 + dev_remove_pack(&caif_packet_type);
429 424 }
430 425  
431 426 module_init(caif_device_init);
net/caif/caif_socket.c
... ... @@ -810,7 +810,7 @@
810 810 sk->sk_state == CAIF_DISCONNECTED);
811 811 if (sk->sk_shutdown & SHUTDOWN_MASK) {
812 812 /* Allow re-connect after SHUTDOWN_IND */
813   - caif_disconnect_client(&cf_sk->layer);
  813 + caif_disconnect_client(sock_net(sk), &cf_sk->layer);
814 814 break;
815 815 }
816 816 /* No reconnect on a seqpacket socket */
... ... @@ -851,7 +851,7 @@
851 851 dbfs_atomic_inc(&cnt.num_connect_req);
852 852 cf_sk->layer.receive = caif_sktrecv_cb;
853 853  
854   - err = caif_connect_client(&cf_sk->conn_req,
  854 + err = caif_connect_client(sock_net(sk), &cf_sk->conn_req,
855 855 &cf_sk->layer, &ifindex, &headroom, &tailroom);
856 856  
857 857 if (err < 0) {
... ... @@ -949,7 +949,7 @@
949 949  
950 950 if (cf_sk->sk.sk_socket->state == SS_CONNECTED ||
951 951 cf_sk->sk.sk_socket->state == SS_CONNECTING)
952   - res = caif_disconnect_client(&cf_sk->layer);
  952 + res = caif_disconnect_client(sock_net(sk), &cf_sk->layer);
953 953  
954 954 cf_sk->sk.sk_socket->state = SS_DISCONNECTING;
955 955 wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP);
... ... @@ -150,7 +150,7 @@
150 150 {
151 151 }
152 152  
153   -struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
  153 +static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg,
154 154 enum cfcnfg_phy_preference phy_pref)
155 155 {
156 156 /* Try to match with specified preference */
... ... @@ -171,7 +171,7 @@
171 171 return NULL;
172 172 }
173 173  
174   -int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi)
  174 +static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi)
175 175 {
176 176 struct cfcnfg_phyinfo *phy;
177 177  
178 178  
... ... @@ -181,11 +181,12 @@
181 181 return -ENODEV;
182 182 }
183 183  
184   -int cfcnfg_disconn_adapt_layer(struct cfcnfg *cfg, struct cflayer *adap_layer)
  184 +int caif_disconnect_client(struct net *net, struct cflayer *adap_layer)
185 185 {
186 186 u8 channel_id = 0;
187 187 int ret = 0;
188 188 struct cflayer *servl = NULL;
  189 + struct cfcnfg *cfg = get_cfcnfg(net);
189 190  
190 191 caif_assert(adap_layer != NULL);
191 192  
192 193  
... ... @@ -217,15 +218,8 @@
217 218 return ret;
218 219  
219 220 }
220   -EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer);
  221 +EXPORT_SYMBOL(caif_disconnect_client);
221 222  
222   -void cfcnfg_release_adap_layer(struct cflayer *adap_layer)
223   -{
224   - if (adap_layer->dn)
225   - cfsrvl_put(adap_layer->dn);
226   -}
227   -EXPORT_SYMBOL(cfcnfg_release_adap_layer);
228   -
229 223 static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id)
230 224 {
231 225 }
232 226  
233 227  
... ... @@ -238,19 +232,109 @@
238 232 [CFCTRL_SRV_DBG] = 3,
239 233 };
240 234  
241   -int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg,
242   - struct cfctrl_link_param *param,
243   - struct cflayer *adap_layer,
244   - int *ifindex,
  235 +
  236 +static int caif_connect_req_to_link_param(struct cfcnfg *cnfg,
  237 + struct caif_connect_request *s,
  238 + struct cfctrl_link_param *l)
  239 +{
  240 + struct dev_info *dev_info;
  241 + enum cfcnfg_phy_preference pref;
  242 + int res;
  243 +
  244 + memset(l, 0, sizeof(*l));
  245 + /* In caif protocol low value is high priority */
  246 + l->priority = CAIF_PRIO_MAX - s->priority + 1;
  247 +
  248 + if (s->ifindex != 0) {
  249 + res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex);
  250 + if (res < 0)
  251 + return res;
  252 + l->phyid = res;
  253 + } else {
  254 + switch (s->link_selector) {
  255 + case CAIF_LINK_HIGH_BANDW:
  256 + pref = CFPHYPREF_HIGH_BW;
  257 + break;
  258 + case CAIF_LINK_LOW_LATENCY:
  259 + pref = CFPHYPREF_LOW_LAT;
  260 + break;
  261 + default:
  262 + return -EINVAL;
  263 + }
  264 + dev_info = cfcnfg_get_phyid(cnfg, pref);
  265 + if (dev_info == NULL)
  266 + return -ENODEV;
  267 + l->phyid = dev_info->id;
  268 + }
  269 + switch (s->protocol) {
  270 + case CAIFPROTO_AT:
  271 + l->linktype = CFCTRL_SRV_VEI;
  272 + l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3;
  273 + l->chtype = s->sockaddr.u.at.type & 0x3;
  274 + break;
  275 + case CAIFPROTO_DATAGRAM:
  276 + l->linktype = CFCTRL_SRV_DATAGRAM;
  277 + l->chtype = 0x00;
  278 + l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
  279 + break;
  280 + case CAIFPROTO_DATAGRAM_LOOP:
  281 + l->linktype = CFCTRL_SRV_DATAGRAM;
  282 + l->chtype = 0x03;
  283 + l->endpoint = 0x00;
  284 + l->u.datagram.connid = s->sockaddr.u.dgm.connection_id;
  285 + break;
  286 + case CAIFPROTO_RFM:
  287 + l->linktype = CFCTRL_SRV_RFM;
  288 + l->u.datagram.connid = s->sockaddr.u.rfm.connection_id;
  289 + strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume,
  290 + sizeof(l->u.rfm.volume)-1);
  291 + l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0;
  292 + break;
  293 + case CAIFPROTO_UTIL:
  294 + l->linktype = CFCTRL_SRV_UTIL;
  295 + l->endpoint = 0x00;
  296 + l->chtype = 0x00;
  297 + strncpy(l->u.utility.name, s->sockaddr.u.util.service,
  298 + sizeof(l->u.utility.name)-1);
  299 + l->u.utility.name[sizeof(l->u.utility.name)-1] = 0;
  300 + caif_assert(sizeof(l->u.utility.name) > 10);
  301 + l->u.utility.paramlen = s->param.size;
  302 + if (l->u.utility.paramlen > sizeof(l->u.utility.params))
  303 + l->u.utility.paramlen = sizeof(l->u.utility.params);
  304 +
  305 + memcpy(l->u.utility.params, s->param.data,
  306 + l->u.utility.paramlen);
  307 +
  308 + break;
  309 + case CAIFPROTO_DEBUG:
  310 + l->linktype = CFCTRL_SRV_DBG;
  311 + l->endpoint = s->sockaddr.u.dbg.service;
  312 + l->chtype = s->sockaddr.u.dbg.type;
  313 + break;
  314 + default:
  315 + return -EINVAL;
  316 + }
  317 + return 0;
  318 +}
  319 +
  320 +int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
  321 + struct cflayer *adap_layer, int *ifindex,
245 322 int *proto_head,
246 323 int *proto_tail)
247 324 {
248 325 struct cflayer *frml;
249 326 struct cfcnfg_phyinfo *phy;
250 327 int err;
  328 + struct cfctrl_link_param param;
  329 + struct cfcnfg *cfg = get_cfcnfg(net);
  330 + caif_assert(cfg != NULL);
251 331  
252 332 rcu_read_lock();
253   - phy = cfcnfg_get_phyinfo_rcu(cnfg, param->phyid);
  333 + err = caif_connect_req_to_link_param(cfg, conn_req, &param);
  334 + if (err)
  335 + goto unlock;
  336 +
  337 + phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid);
254 338 if (!phy) {
255 339 err = -ENODEV;
256 340 goto unlock;
257 341  
258 342  
259 343  
260 344  
261 345  
262 346  
... ... @@ -276,28 +360,29 @@
276 360 pr_err("Specified PHY type does not exist!\n");
277 361 goto unlock;
278 362 }
279   - caif_assert(param->phyid == phy->id);
  363 + caif_assert(param.phyid == phy->id);
280 364 caif_assert(phy->frm_layer->id ==
281   - param->phyid);
  365 + param.phyid);
282 366 caif_assert(phy->phy_layer->id ==
283   - param->phyid);
  367 + param.phyid);
284 368  
285 369 *ifindex = phy->ifindex;
286 370 *proto_tail = 2;
287 371 *proto_head =
288   - protohead[param->linktype] + (phy->use_stx ? 1 : 0);
289 372  
  373 + protohead[param.linktype] + (phy->use_stx ? 1 : 0);
  374 +
290 375 rcu_read_unlock();
291 376  
292 377 /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */
293   - cfctrl_enum_req(cnfg->ctrl, param->phyid);
294   - return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer);
  378 + cfctrl_enum_req(cfg->ctrl, param.phyid);
  379 + return cfctrl_linkup_request(cfg->ctrl, &param, adap_layer);
295 380  
296 381 unlock:
297 382 rcu_read_unlock();
298 383 return err;
299 384 }
300   -EXPORT_SYMBOL(cfcnfg_add_adaptation_layer);
  385 +EXPORT_SYMBOL(caif_connect_client);
301 386  
302 387 static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id,
303 388 struct cflayer *adapt_layer)
... ... @@ -389,7 +474,7 @@
389 474 void
390 475 cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
391 476 struct net_device *dev, struct cflayer *phy_layer,
392   - u16 *phy_id, enum cfcnfg_phy_preference pref,
  477 + enum cfcnfg_phy_preference pref,
393 478 bool fcs, bool stx)
394 479 {
395 480 struct cflayer *frml;
396 481  
397 482  
398 483  
399 484  
... ... @@ -512,23 +597,26 @@
512 597 phyid = phy_layer->id;
513 598 phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid);
514 599  
515   - if (phyinfo == NULL)
  600 + if (phyinfo == NULL) {
  601 + mutex_unlock(&cnfg->lock);
516 602 return 0;
  603 + }
517 604 caif_assert(phyid == phyinfo->id);
518 605 caif_assert(phy_layer == phyinfo->phy_layer);
519 606 caif_assert(phy_layer->id == phyid);
520 607 caif_assert(phyinfo->frm_layer->id == phyid);
521 608  
  609 + list_del_rcu(&phyinfo->node);
  610 + synchronize_rcu();
  611 +
522 612 /* Fail if reference count is not zero */
523 613 if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) {
524 614 pr_info("Wait for device inuse\n");
  615 + list_add_rcu(&phyinfo->node, &cnfg->phys);
525 616 mutex_unlock(&cnfg->lock);
526 617 return -EAGAIN;
527 618 }
528 619  
529   - list_del_rcu(&phyinfo->node);
530   - synchronize_rcu();
531   -
532 620 frml = phyinfo->frm_layer;
533 621 frml_dn = frml->dn;
534 622 cffrml_set_uplayer(frml, NULL);
... ... @@ -538,8 +626,6 @@
538 626 layer_set_dn(frml_dn, NULL);
539 627 }
540 628 layer_set_up(phy_layer, NULL);
541   -
542   -
543 629  
544 630 if (phyinfo->phy_layer != frml_dn)
545 631 kfree(frml_dn);
... ... @@ -20,7 +20,6 @@
20 20 #include <linux/caif/if_caif.h>
21 21 #include <net/rtnetlink.h>
22 22 #include <net/caif/caif_layer.h>
23   -#include <net/caif/cfcnfg.h>
24 23 #include <net/caif/cfpkt.h>
25 24 #include <net/caif/caif_dev.h>
26 25  
... ... @@ -270,8 +269,9 @@
270 269  
271 270 if (priv->state != CAIF_CONNECTING) {
272 271 priv->state = CAIF_CONNECTING;
273   - result = caif_connect_client(&priv->conn_req, &priv->chnl,
274   - &llifindex, &headroom, &tailroom);
  272 + result = caif_connect_client(dev_net(dev), &priv->conn_req,
  273 + &priv->chnl, &llifindex,
  274 + &headroom, &tailroom);
275 275 if (result != 0) {
276 276 pr_debug("err: "
277 277 "Unable to register and open device,"
... ... @@ -327,7 +327,7 @@
327 327  
328 328 if (result == 0) {
329 329 pr_debug("connect timeout\n");
330   - caif_disconnect_client(&priv->chnl);
  330 + caif_disconnect_client(dev_net(dev), &priv->chnl);
331 331 priv->state = CAIF_DISCONNECTED;
332 332 pr_debug("state disconnected\n");
333 333 result = -ETIMEDOUT;
... ... @@ -343,7 +343,7 @@
343 343 return 0;
344 344  
345 345 error:
346   - caif_disconnect_client(&priv->chnl);
  346 + caif_disconnect_client(dev_net(dev), &priv->chnl);
347 347 priv->state = CAIF_DISCONNECTED;
348 348 pr_debug("state disconnected\n");
349 349 return result;
... ... @@ -357,7 +357,7 @@
357 357 ASSERT_RTNL();
358 358 priv = netdev_priv(dev);
359 359 priv->state = CAIF_DISCONNECTED;
360   - caif_disconnect_client(&priv->chnl);
  360 + caif_disconnect_client(dev_net(dev), &priv->chnl);
361 361 return 0;
362 362 }
363 363