aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsjur.brandeland@stericsson.com <sjur.brandeland@stericsson.com>2011-11-30 04:22:47 -0500
committerDavid S. Miller <davem@davemloft.net>2011-11-30 23:30:48 -0500
commit7c18d2205ea76eef9674e59e1ecae4f332a53e9e (patch)
tree2d6ed4be50e52408b8806ca67f0bd6fb15362efa
parent200c5a3b387c415e49639ee0f6de37804522b745 (diff)
caif: Restructure how link caif link layer enroll
Enrolling CAIF link layers are refactored. Signed-off-by: Sjur Brændeland <sjur.brandeland@stericsson.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--include/net/caif/caif_dev.h21
-rw-r--r--include/net/caif/cfcnfg.h9
-rw-r--r--net/caif/caif_dev.c145
-rw-r--r--net/caif/cfcnfg.c47
4 files changed, 132 insertions, 90 deletions
diff --git a/include/net/caif/caif_dev.h b/include/net/caif/caif_dev.h
index c011281d92c0..ef2dd9438bb1 100644
--- a/include/net/caif/caif_dev.h
+++ b/include/net/caif/caif_dev.h
@@ -9,6 +9,7 @@
9 9
10#include <net/caif/caif_layer.h> 10#include <net/caif/caif_layer.h>
11#include <net/caif/cfcnfg.h> 11#include <net/caif/cfcnfg.h>
12#include <net/caif/caif_device.h>
12#include <linux/caif/caif_socket.h> 13#include <linux/caif/caif_socket.h>
13#include <linux/if.h> 14#include <linux/if.h>
14#include <linux/net.h> 15#include <linux/net.h>
@@ -104,4 +105,24 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer,
104 */ 105 */
105void caif_free_client(struct cflayer *adap_layer); 106void caif_free_client(struct cflayer *adap_layer);
106 107
108/**
109 * struct caif_enroll_dev - Enroll a net-device as a CAIF Link layer
110 * @dev: Network device to enroll.
111 * @caifdev: Configuration information from CAIF Link Layer
112 * @link_support: Link layer support layer
113 * @head_room: Head room needed by link support layer
114 * @layer: Lowest layer in CAIF stack
115 * @rcv_fun: Receive function for CAIF stack.
116 *
117 * This function enroll a CAIF link layer into CAIF Stack and
118 * expects the interface to be able to handle CAIF payload.
119 * The link_support layer is used to add any Link Layer specific
120 * framing.
121 */
122void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
123 struct cflayer *link_support, int head_room,
124 struct cflayer **layer, int (**rcv_func)(
125 struct sk_buff *, struct net_device *,
126 struct packet_type *, struct net_device *));
127
107#endif /* CAIF_DEV_H_ */ 128#endif /* CAIF_DEV_H_ */
diff --git a/include/net/caif/cfcnfg.h b/include/net/caif/cfcnfg.h
index 3e93a4a4b677..a421723e986f 100644
--- a/include/net/caif/cfcnfg.h
+++ b/include/net/caif/cfcnfg.h
@@ -72,15 +72,16 @@ void cfcnfg_remove(struct cfcnfg *cfg);
72 * @phy_layer: Specify the physical layer. The transmit function 72 * @phy_layer: Specify the physical layer. The transmit function
73 * MUST be set in the structure. 73 * MUST be set in the structure.
74 * @pref: The phy (link layer) preference. 74 * @pref: The phy (link layer) preference.
75 * @link_support: Protocol implementation for link layer specific protocol.
75 * @fcs: Specify if checksum is used in CAIF Framing Layer. 76 * @fcs: Specify if checksum is used in CAIF Framing Layer.
76 * @stx: Specify if Start Of Frame eXtention is used. 77 * @head_room: Head space needed by link specific protocol.
77 */ 78 */
78
79void 79void
80cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, 80cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
81 struct net_device *dev, struct cflayer *phy_layer, 81 struct net_device *dev, struct cflayer *phy_layer,
82 enum cfcnfg_phy_preference pref, 82 enum cfcnfg_phy_preference pref,
83 bool fcs, bool stx); 83 struct cflayer *link_support,
84 bool fcs, int head_room);
84 85
85/** 86/**
86 * cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack. 87 * cfcnfg_del_phy_layer - Deletes an phy layer from the CAIF stack.
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c
index f1fa1f6e658d..70034c017825 100644
--- a/net/caif/caif_dev.c
+++ b/net/caif/caif_dev.c
@@ -24,6 +24,7 @@
24#include <net/caif/caif_layer.h> 24#include <net/caif/caif_layer.h>
25#include <net/caif/cfpkt.h> 25#include <net/caif/cfpkt.h>
26#include <net/caif/cfcnfg.h> 26#include <net/caif/cfcnfg.h>
27#include <net/caif/cfserl.h>
27 28
28MODULE_LICENSE("GPL"); 29MODULE_LICENSE("GPL");
29 30
@@ -53,7 +54,8 @@ struct cfcnfg *get_cfcnfg(struct net *net)
53 struct caif_net *caifn; 54 struct caif_net *caifn;
54 BUG_ON(!net); 55 BUG_ON(!net);
55 caifn = net_generic(net, caif_net_id); 56 caifn = net_generic(net, caif_net_id);
56 BUG_ON(!caifn); 57 if (!caifn)
58 return NULL;
57 return caifn->cfg; 59 return caifn->cfg;
58} 60}
59EXPORT_SYMBOL(get_cfcnfg); 61EXPORT_SYMBOL(get_cfcnfg);
@@ -63,7 +65,8 @@ static struct caif_device_entry_list *caif_device_list(struct net *net)
63 struct caif_net *caifn; 65 struct caif_net *caifn;
64 BUG_ON(!net); 66 BUG_ON(!net);
65 caifn = net_generic(net, caif_net_id); 67 caifn = net_generic(net, caif_net_id);
66 BUG_ON(!caifn); 68 if (!caifn)
69 return NULL;
67 return &caifn->caifdevs; 70 return &caifn->caifdevs;
68} 71}
69 72
@@ -92,7 +95,8 @@ static struct caif_device_entry *caif_device_alloc(struct net_device *dev)
92 struct caif_device_entry *caifd; 95 struct caif_device_entry *caifd;
93 96
94 caifdevs = caif_device_list(dev_net(dev)); 97 caifdevs = caif_device_list(dev_net(dev));
95 BUG_ON(!caifdevs); 98 if (!caifdevs)
99 return NULL;
96 100
97 caifd = kzalloc(sizeof(*caifd), GFP_KERNEL); 101 caifd = kzalloc(sizeof(*caifd), GFP_KERNEL);
98 if (!caifd) 102 if (!caifd)
@@ -112,7 +116,9 @@ static struct caif_device_entry *caif_get(struct net_device *dev)
112 struct caif_device_entry_list *caifdevs = 116 struct caif_device_entry_list *caifdevs =
113 caif_device_list(dev_net(dev)); 117 caif_device_list(dev_net(dev));
114 struct caif_device_entry *caifd; 118 struct caif_device_entry *caifd;
115 BUG_ON(!caifdevs); 119 if (!caifdevs)
120 return NULL;
121
116 list_for_each_entry_rcu(caifd, &caifdevs->list, list) { 122 list_for_each_entry_rcu(caifd, &caifdevs->list, list) {
117 if (caifd->netdev == dev) 123 if (caifd->netdev == dev)
118 return caifd; 124 return caifd;
@@ -129,6 +135,8 @@ static int transmit(struct cflayer *layer, struct cfpkt *pkt)
129 135
130 skb = cfpkt_tonative(pkt); 136 skb = cfpkt_tonative(pkt);
131 skb->dev = caifd->netdev; 137 skb->dev = caifd->netdev;
138 skb_reset_network_header(skb);
139 skb->protocol = htons(ETH_P_CAIF);
132 140
133 err = dev_queue_xmit(skb); 141 err = dev_queue_xmit(skb);
134 if (err > 0) 142 if (err > 0)
@@ -172,7 +180,10 @@ static int receive(struct sk_buff *skb, struct net_device *dev,
172 180
173 /* Release reference to stack upwards */ 181 /* Release reference to stack upwards */
174 caifd_put(caifd); 182 caifd_put(caifd);
175 return 0; 183
184 if (err != 0)
185 err = NET_RX_DROP;
186 return err;
176} 187}
177 188
178static struct packet_type caif_packet_type __read_mostly = { 189static struct packet_type caif_packet_type __read_mostly = {
@@ -203,6 +214,55 @@ static void dev_flowctrl(struct net_device *dev, int on)
203 caifd_put(caifd); 214 caifd_put(caifd);
204} 215}
205 216
217void caif_enroll_dev(struct net_device *dev, struct caif_dev_common *caifdev,
218 struct cflayer *link_support, int head_room,
219 struct cflayer **layer, int (**rcv_func)(
220 struct sk_buff *, struct net_device *,
221 struct packet_type *, struct net_device *))
222{
223 struct caif_device_entry *caifd;
224 enum cfcnfg_phy_preference pref;
225 struct cfcnfg *cfg = get_cfcnfg(dev_net(dev));
226 struct caif_device_entry_list *caifdevs;
227
228 caifdevs = caif_device_list(dev_net(dev));
229 if (!cfg || !caifdevs)
230 return;
231 caifd = caif_device_alloc(dev);
232 if (!caifd)
233 return;
234 *layer = &caifd->layer;
235
236 switch (caifdev->link_select) {
237 case CAIF_LINK_HIGH_BANDW:
238 pref = CFPHYPREF_HIGH_BW;
239 break;
240 case CAIF_LINK_LOW_LATENCY:
241 pref = CFPHYPREF_LOW_LAT;
242 break;
243 default:
244 pref = CFPHYPREF_HIGH_BW;
245 break;
246 }
247 mutex_lock(&caifdevs->lock);
248 list_add_rcu(&caifd->list, &caifdevs->list);
249
250 strncpy(caifd->layer.name, dev->name,
251 sizeof(caifd->layer.name) - 1);
252 caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0;
253 caifd->layer.transmit = transmit;
254 cfcnfg_add_phy_layer(cfg,
255 dev,
256 &caifd->layer,
257 pref,
258 link_support,
259 caifdev->use_fcs,
260 head_room);
261 mutex_unlock(&caifdevs->lock);
262 if (rcv_func)
263 *rcv_func = receive;
264}
265
206/* notify Caif of device events */ 266/* notify Caif of device events */
207static int caif_device_notify(struct notifier_block *me, unsigned long what, 267static int caif_device_notify(struct notifier_block *me, unsigned long what,
208 void *arg) 268 void *arg)
@@ -210,62 +270,40 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what,
210 struct net_device *dev = arg; 270 struct net_device *dev = arg;
211 struct caif_device_entry *caifd = NULL; 271 struct caif_device_entry *caifd = NULL;
212 struct caif_dev_common *caifdev; 272 struct caif_dev_common *caifdev;
213 enum cfcnfg_phy_preference pref;
214 enum cfcnfg_phy_type phy_type;
215 struct cfcnfg *cfg; 273 struct cfcnfg *cfg;
274 struct cflayer *layer, *link_support;
275 int head_room = 0;
216 struct caif_device_entry_list *caifdevs; 276 struct caif_device_entry_list *caifdevs;
217 277
218 if (dev->type != ARPHRD_CAIF)
219 return 0;
220
221 cfg = get_cfcnfg(dev_net(dev)); 278 cfg = get_cfcnfg(dev_net(dev));
222 if (cfg == NULL) 279 caifdevs = caif_device_list(dev_net(dev));
280 if (!cfg || !caifdevs)
223 return 0; 281 return 0;
224 282
225 caifdevs = caif_device_list(dev_net(dev)); 283 caifd = caif_get(dev);
284 if (caifd == NULL && dev->type != ARPHRD_CAIF)
285 return 0;
226 286
227 switch (what) { 287 switch (what) {
228 case NETDEV_REGISTER: 288 case NETDEV_REGISTER:
229 caifd = caif_device_alloc(dev); 289 if (caifd != NULL)
230 if (!caifd) 290 break;
231 return 0;
232 291
233 caifdev = netdev_priv(dev); 292 caifdev = netdev_priv(dev);
234 caifdev->flowctrl = dev_flowctrl;
235 293
236 caifd->layer.transmit = transmit; 294 link_support = NULL;
237 295 if (caifdev->use_frag) {
238 if (caifdev->use_frag) 296 head_room = 1;
239 phy_type = CFPHYTYPE_FRAG; 297 link_support = cfserl_create(dev->ifindex,
240 else 298 CFPHYTYPE_FRAG, caifdev->use_stx);
241 phy_type = CFPHYTYPE_CAIF; 299 if (!link_support) {
242 300 pr_warn("Out of memory\n");
243 switch (caifdev->link_select) { 301 break;
244 case CAIF_LINK_HIGH_BANDW: 302 }
245 pref = CFPHYPREF_HIGH_BW;
246 break;
247 case CAIF_LINK_LOW_LATENCY:
248 pref = CFPHYPREF_LOW_LAT;
249 break;
250 default:
251 pref = CFPHYPREF_HIGH_BW;
252 break;
253 } 303 }
254 strncpy(caifd->layer.name, dev->name, 304 caif_enroll_dev(dev, caifdev, link_support, head_room,
255 sizeof(caifd->layer.name) - 1); 305 &layer, NULL);
256 caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0; 306 caifdev->flowctrl = dev_flowctrl;
257
258 mutex_lock(&caifdevs->lock);
259 list_add_rcu(&caifd->list, &caifdevs->list);
260
261 cfcnfg_add_phy_layer(cfg,
262 phy_type,
263 dev,
264 &caifd->layer,
265 pref,
266 caifdev->use_fcs,
267 caifdev->use_stx);
268 mutex_unlock(&caifdevs->lock);
269 break; 307 break;
270 308
271 case NETDEV_UP: 309 case NETDEV_UP:
@@ -371,17 +409,14 @@ static void caif_exit_net(struct net *net)
371 struct caif_device_entry *caifd, *tmp; 409 struct caif_device_entry *caifd, *tmp;
372 struct caif_device_entry_list *caifdevs = 410 struct caif_device_entry_list *caifdevs =
373 caif_device_list(net); 411 caif_device_list(net);
374 struct cfcnfg *cfg; 412 struct cfcnfg *cfg = get_cfcnfg(net);
413
414 if (!cfg || !caifdevs)
415 return;
375 416
376 rtnl_lock(); 417 rtnl_lock();
377 mutex_lock(&caifdevs->lock); 418 mutex_lock(&caifdevs->lock);
378 419
379 cfg = get_cfcnfg(net);
380 if (cfg == NULL) {
381 mutex_unlock(&caifdevs->lock);
382 return;
383 }
384
385 list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) { 420 list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) {
386 int i = 0; 421 int i = 0;
387 list_del_rcu(&caifd->list); 422 list_del_rcu(&caifd->list);
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c
index 00523ecc4ced..598aafb4cb51 100644
--- a/net/caif/cfcnfg.c
+++ b/net/caif/cfcnfg.c
@@ -45,8 +45,8 @@ struct cfcnfg_phyinfo {
45 /* Interface index */ 45 /* Interface index */
46 int ifindex; 46 int ifindex;
47 47
48 /* Use Start of frame extension */ 48 /* Protocol head room added for CAIF link layer */
49 bool use_stx; 49 int head_room;
50 50
51 /* Use Start of frame checksum */ 51 /* Use Start of frame checksum */
52 bool use_fcs; 52 bool use_fcs;
@@ -187,11 +187,11 @@ int caif_disconnect_client(struct net *net, struct cflayer *adap_layer)
187 if (channel_id != 0) { 187 if (channel_id != 0) {
188 struct cflayer *servl; 188 struct cflayer *servl;
189 servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); 189 servl = cfmuxl_remove_uplayer(cfg->mux, channel_id);
190 cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
190 if (servl != NULL) 191 if (servl != NULL)
191 layer_set_up(servl, NULL); 192 layer_set_up(servl, NULL);
192 } else 193 } else
193 pr_debug("nothing to disconnect\n"); 194 pr_debug("nothing to disconnect\n");
194 cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer);
195 195
196 /* Do RCU sync before initiating cleanup */ 196 /* Do RCU sync before initiating cleanup */
197 synchronize_rcu(); 197 synchronize_rcu();
@@ -350,9 +350,7 @@ int caif_connect_client(struct net *net, struct caif_connect_request *conn_req,
350 350
351 *ifindex = phy->ifindex; 351 *ifindex = phy->ifindex;
352 *proto_tail = 2; 352 *proto_tail = 2;
353 *proto_head = 353 *proto_head = protohead[param.linktype] + phy->head_room;
354
355 protohead[param.linktype] + (phy->use_stx ? 1 : 0);
356 354
357 rcu_read_unlock(); 355 rcu_read_unlock();
358 356
@@ -460,13 +458,13 @@ unlock:
460} 458}
461 459
462void 460void
463cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, 461cfcnfg_add_phy_layer(struct cfcnfg *cnfg,
464 struct net_device *dev, struct cflayer *phy_layer, 462 struct net_device *dev, struct cflayer *phy_layer,
465 enum cfcnfg_phy_preference pref, 463 enum cfcnfg_phy_preference pref,
466 bool fcs, bool stx) 464 struct cflayer *link_support,
465 bool fcs, int head_room)
467{ 466{
468 struct cflayer *frml; 467 struct cflayer *frml;
469 struct cflayer *phy_driver = NULL;
470 struct cfcnfg_phyinfo *phyinfo = NULL; 468 struct cfcnfg_phyinfo *phyinfo = NULL;
471 int i; 469 int i;
472 u8 phyid; 470 u8 phyid;
@@ -482,26 +480,13 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type,
482 goto got_phyid; 480 goto got_phyid;
483 } 481 }
484 pr_warn("Too many CAIF Link Layers (max 6)\n"); 482 pr_warn("Too many CAIF Link Layers (max 6)\n");
485 goto out_err; 483 goto out;
486 484
487got_phyid: 485got_phyid:
488 phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC); 486 phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC);
489 if (!phyinfo) 487 if (!phyinfo)
490 goto out_err; 488 goto out_err;
491 489
492 switch (phy_type) {
493 case CFPHYTYPE_FRAG:
494 phy_driver =
495 cfserl_create(CFPHYTYPE_FRAG, phyid, stx);
496 if (!phy_driver)
497 goto out_err;
498 break;
499 case CFPHYTYPE_CAIF:
500 phy_driver = NULL;
501 break;
502 default:
503 goto out_err;
504 }
505 phy_layer->id = phyid; 490 phy_layer->id = phyid;
506 phyinfo->pref = pref; 491 phyinfo->pref = pref;
507 phyinfo->id = phyid; 492 phyinfo->id = phyid;
@@ -509,7 +494,7 @@ got_phyid:
509 phyinfo->dev_info.dev = dev; 494 phyinfo->dev_info.dev = dev;
510 phyinfo->phy_layer = phy_layer; 495 phyinfo->phy_layer = phy_layer;
511 phyinfo->ifindex = dev->ifindex; 496 phyinfo->ifindex = dev->ifindex;
512 phyinfo->use_stx = stx; 497 phyinfo->head_room = head_room;
513 phyinfo->use_fcs = fcs; 498 phyinfo->use_fcs = fcs;
514 499
515 frml = cffrml_create(phyid, fcs); 500 frml = cffrml_create(phyid, fcs);
@@ -519,23 +504,23 @@ got_phyid:
519 phyinfo->frm_layer = frml; 504 phyinfo->frm_layer = frml;
520 layer_set_up(frml, cnfg->mux); 505 layer_set_up(frml, cnfg->mux);
521 506
522 if (phy_driver != NULL) { 507 if (link_support != NULL) {
523 phy_driver->id = phyid; 508 link_support->id = phyid;
524 layer_set_dn(frml, phy_driver); 509 layer_set_dn(frml, link_support);
525 layer_set_up(phy_driver, frml); 510 layer_set_up(link_support, frml);
526 layer_set_dn(phy_driver, phy_layer); 511 layer_set_dn(link_support, phy_layer);
527 layer_set_up(phy_layer, phy_driver); 512 layer_set_up(phy_layer, link_support);
528 } else { 513 } else {
529 layer_set_dn(frml, phy_layer); 514 layer_set_dn(frml, phy_layer);
530 layer_set_up(phy_layer, frml); 515 layer_set_up(phy_layer, frml);
531 } 516 }
532 517
533 list_add_rcu(&phyinfo->node, &cnfg->phys); 518 list_add_rcu(&phyinfo->node, &cnfg->phys);
519out:
534 mutex_unlock(&cnfg->lock); 520 mutex_unlock(&cnfg->lock);
535 return; 521 return;
536 522
537out_err: 523out_err:
538 kfree(phy_driver);
539 kfree(phyinfo); 524 kfree(phyinfo);
540 mutex_unlock(&cnfg->lock); 525 mutex_unlock(&cnfg->lock);
541} 526}