Commit bee925db9a77a5736596dcf6f91d0879f5ee915b
Committed by
David S. Miller
1 parent
b3ccfbe409
Exists in
master
and in
4 other branches
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. |
net/caif/Makefile
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 | -} |
net/caif/caif_dev.c
... | ... | @@ -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, ¶m); | |
334 | - if (ret) | |
335 | - return ret; | |
336 | - /* Hook up the adaptation layer. */ | |
337 | - return cfcnfg_add_adaptation_layer(cfg, ¶m, | |
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); |
net/caif/cfcnfg.c
... | ... | @@ -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, ¶m); | |
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, ¶m, 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); |
net/caif/chnl_net.c
... | ... | @@ -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 |