Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

sjur.brandeland@stericsson.com and committed by
David S. Miller
7c18d220 200c5a3b

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