diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/can/dev.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/can/dev.c')
-rw-r--r-- | drivers/net/can/dev.c | 85 |
1 files changed, 71 insertions, 14 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 2868fe842a41..d0f8c7e67e7d 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -19,6 +19,7 @@ | |||
19 | 19 | ||
20 | #include <linux/module.h> | 20 | #include <linux/module.h> |
21 | #include <linux/kernel.h> | 21 | #include <linux/kernel.h> |
22 | #include <linux/slab.h> | ||
22 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
23 | #include <linux/if_arp.h> | 24 | #include <linux/if_arp.h> |
24 | #include <linux/can.h> | 25 | #include <linux/can.h> |
@@ -245,7 +246,7 @@ static void can_flush_echo_skb(struct net_device *dev) | |||
245 | struct net_device_stats *stats = &dev->stats; | 246 | struct net_device_stats *stats = &dev->stats; |
246 | int i; | 247 | int i; |
247 | 248 | ||
248 | for (i = 0; i < CAN_ECHO_SKB_MAX; i++) { | 249 | for (i = 0; i < priv->echo_skb_max; i++) { |
249 | if (priv->echo_skb[i]) { | 250 | if (priv->echo_skb[i]) { |
250 | kfree_skb(priv->echo_skb[i]); | 251 | kfree_skb(priv->echo_skb[i]); |
251 | priv->echo_skb[i] = NULL; | 252 | priv->echo_skb[i] = NULL; |
@@ -262,10 +263,13 @@ static void can_flush_echo_skb(struct net_device *dev) | |||
262 | * of the device driver. The driver must protect access to | 263 | * of the device driver. The driver must protect access to |
263 | * priv->echo_skb, if necessary. | 264 | * priv->echo_skb, if necessary. |
264 | */ | 265 | */ |
265 | void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, int idx) | 266 | void can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, |
267 | unsigned int idx) | ||
266 | { | 268 | { |
267 | struct can_priv *priv = netdev_priv(dev); | 269 | struct can_priv *priv = netdev_priv(dev); |
268 | 270 | ||
271 | BUG_ON(idx >= priv->echo_skb_max); | ||
272 | |||
269 | /* check flag whether this packet has to be looped back */ | 273 | /* check flag whether this packet has to be looped back */ |
270 | if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) { | 274 | if (!(dev->flags & IFF_ECHO) || skb->pkt_type != PACKET_LOOPBACK) { |
271 | kfree_skb(skb); | 275 | kfree_skb(skb); |
@@ -311,10 +315,12 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb); | |||
311 | * is handled in the device driver. The driver must protect | 315 | * is handled in the device driver. The driver must protect |
312 | * access to priv->echo_skb, if necessary. | 316 | * access to priv->echo_skb, if necessary. |
313 | */ | 317 | */ |
314 | void can_get_echo_skb(struct net_device *dev, int idx) | 318 | void can_get_echo_skb(struct net_device *dev, unsigned int idx) |
315 | { | 319 | { |
316 | struct can_priv *priv = netdev_priv(dev); | 320 | struct can_priv *priv = netdev_priv(dev); |
317 | 321 | ||
322 | BUG_ON(idx >= priv->echo_skb_max); | ||
323 | |||
318 | if (priv->echo_skb[idx]) { | 324 | if (priv->echo_skb[idx]) { |
319 | netif_rx(priv->echo_skb[idx]); | 325 | netif_rx(priv->echo_skb[idx]); |
320 | priv->echo_skb[idx] = NULL; | 326 | priv->echo_skb[idx] = NULL; |
@@ -327,10 +333,12 @@ EXPORT_SYMBOL_GPL(can_get_echo_skb); | |||
327 | * | 333 | * |
328 | * The function is typically called when TX failed. | 334 | * The function is typically called when TX failed. |
329 | */ | 335 | */ |
330 | void can_free_echo_skb(struct net_device *dev, int idx) | 336 | void can_free_echo_skb(struct net_device *dev, unsigned int idx) |
331 | { | 337 | { |
332 | struct can_priv *priv = netdev_priv(dev); | 338 | struct can_priv *priv = netdev_priv(dev); |
333 | 339 | ||
340 | BUG_ON(idx >= priv->echo_skb_max); | ||
341 | |||
334 | if (priv->echo_skb[idx]) { | 342 | if (priv->echo_skb[idx]) { |
335 | kfree_skb(priv->echo_skb[idx]); | 343 | kfree_skb(priv->echo_skb[idx]); |
336 | priv->echo_skb[idx] = NULL; | 344 | priv->echo_skb[idx] = NULL; |
@@ -359,17 +367,12 @@ void can_restart(unsigned long data) | |||
359 | can_flush_echo_skb(dev); | 367 | can_flush_echo_skb(dev); |
360 | 368 | ||
361 | /* send restart message upstream */ | 369 | /* send restart message upstream */ |
362 | skb = dev_alloc_skb(sizeof(struct can_frame)); | 370 | skb = alloc_can_err_skb(dev, &cf); |
363 | if (skb == NULL) { | 371 | if (skb == NULL) { |
364 | err = -ENOMEM; | 372 | err = -ENOMEM; |
365 | goto restart; | 373 | goto restart; |
366 | } | 374 | } |
367 | skb->dev = dev; | 375 | cf->can_id |= CAN_ERR_RESTARTED; |
368 | skb->protocol = htons(ETH_P_CAN); | ||
369 | cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | ||
370 | memset(cf, 0, sizeof(struct can_frame)); | ||
371 | cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; | ||
372 | cf->can_dlc = CAN_ERR_DLC; | ||
373 | 376 | ||
374 | netif_rx(skb); | 377 | netif_rx(skb); |
375 | 378 | ||
@@ -442,20 +445,66 @@ static void can_setup(struct net_device *dev) | |||
442 | dev->features = NETIF_F_NO_CSUM; | 445 | dev->features = NETIF_F_NO_CSUM; |
443 | } | 446 | } |
444 | 447 | ||
448 | struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) | ||
449 | { | ||
450 | struct sk_buff *skb; | ||
451 | |||
452 | skb = netdev_alloc_skb(dev, sizeof(struct can_frame)); | ||
453 | if (unlikely(!skb)) | ||
454 | return NULL; | ||
455 | |||
456 | skb->protocol = htons(ETH_P_CAN); | ||
457 | skb->pkt_type = PACKET_BROADCAST; | ||
458 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
459 | *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | ||
460 | memset(*cf, 0, sizeof(struct can_frame)); | ||
461 | |||
462 | return skb; | ||
463 | } | ||
464 | EXPORT_SYMBOL_GPL(alloc_can_skb); | ||
465 | |||
466 | struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf) | ||
467 | { | ||
468 | struct sk_buff *skb; | ||
469 | |||
470 | skb = alloc_can_skb(dev, cf); | ||
471 | if (unlikely(!skb)) | ||
472 | return NULL; | ||
473 | |||
474 | (*cf)->can_id = CAN_ERR_FLAG; | ||
475 | (*cf)->can_dlc = CAN_ERR_DLC; | ||
476 | |||
477 | return skb; | ||
478 | } | ||
479 | EXPORT_SYMBOL_GPL(alloc_can_err_skb); | ||
480 | |||
445 | /* | 481 | /* |
446 | * Allocate and setup space for the CAN network device | 482 | * Allocate and setup space for the CAN network device |
447 | */ | 483 | */ |
448 | struct net_device *alloc_candev(int sizeof_priv) | 484 | struct net_device *alloc_candev(int sizeof_priv, unsigned int echo_skb_max) |
449 | { | 485 | { |
450 | struct net_device *dev; | 486 | struct net_device *dev; |
451 | struct can_priv *priv; | 487 | struct can_priv *priv; |
488 | int size; | ||
452 | 489 | ||
453 | dev = alloc_netdev(sizeof_priv, "can%d", can_setup); | 490 | if (echo_skb_max) |
491 | size = ALIGN(sizeof_priv, sizeof(struct sk_buff *)) + | ||
492 | echo_skb_max * sizeof(struct sk_buff *); | ||
493 | else | ||
494 | size = sizeof_priv; | ||
495 | |||
496 | dev = alloc_netdev(size, "can%d", can_setup); | ||
454 | if (!dev) | 497 | if (!dev) |
455 | return NULL; | 498 | return NULL; |
456 | 499 | ||
457 | priv = netdev_priv(dev); | 500 | priv = netdev_priv(dev); |
458 | 501 | ||
502 | if (echo_skb_max) { | ||
503 | priv->echo_skb_max = echo_skb_max; | ||
504 | priv->echo_skb = (void *)priv + | ||
505 | ALIGN(sizeof_priv, sizeof(struct sk_buff *)); | ||
506 | } | ||
507 | |||
459 | priv->state = CAN_STATE_STOPPED; | 508 | priv->state = CAN_STATE_STOPPED; |
460 | 509 | ||
461 | init_timer(&priv->restart_timer); | 510 | init_timer(&priv->restart_timer); |
@@ -526,6 +575,7 @@ static const struct nla_policy can_policy[IFLA_CAN_MAX + 1] = { | |||
526 | [IFLA_CAN_BITTIMING_CONST] | 575 | [IFLA_CAN_BITTIMING_CONST] |
527 | = { .len = sizeof(struct can_bittiming_const) }, | 576 | = { .len = sizeof(struct can_bittiming_const) }, |
528 | [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, | 577 | [IFLA_CAN_CLOCK] = { .len = sizeof(struct can_clock) }, |
578 | [IFLA_CAN_BERR_COUNTER] = { .len = sizeof(struct can_berr_counter) }, | ||
529 | }; | 579 | }; |
530 | 580 | ||
531 | static int can_changelink(struct net_device *dev, | 581 | static int can_changelink(struct net_device *dev, |
@@ -544,6 +594,8 @@ static int can_changelink(struct net_device *dev, | |||
544 | if (dev->flags & IFF_UP) | 594 | if (dev->flags & IFF_UP) |
545 | return -EBUSY; | 595 | return -EBUSY; |
546 | cm = nla_data(data[IFLA_CAN_CTRLMODE]); | 596 | cm = nla_data(data[IFLA_CAN_CTRLMODE]); |
597 | if (cm->flags & ~priv->ctrlmode_supported) | ||
598 | return -EOPNOTSUPP; | ||
547 | priv->ctrlmode &= ~cm->mask; | 599 | priv->ctrlmode &= ~cm->mask; |
548 | priv->ctrlmode |= cm->flags; | 600 | priv->ctrlmode |= cm->flags; |
549 | } | 601 | } |
@@ -599,6 +651,8 @@ static size_t can_get_size(const struct net_device *dev) | |||
599 | size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ | 651 | size += nla_total_size(sizeof(u32)); /* IFLA_CAN_RESTART_MS */ |
600 | size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ | 652 | size += sizeof(struct can_bittiming); /* IFLA_CAN_BITTIMING */ |
601 | size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ | 653 | size += sizeof(struct can_clock); /* IFLA_CAN_CLOCK */ |
654 | if (priv->do_get_berr_counter) /* IFLA_CAN_BERR_COUNTER */ | ||
655 | size += sizeof(struct can_berr_counter); | ||
602 | if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ | 656 | if (priv->bittiming_const) /* IFLA_CAN_BITTIMING_CONST */ |
603 | size += sizeof(struct can_bittiming_const); | 657 | size += sizeof(struct can_bittiming_const); |
604 | 658 | ||
@@ -609,6 +663,7 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
609 | { | 663 | { |
610 | struct can_priv *priv = netdev_priv(dev); | 664 | struct can_priv *priv = netdev_priv(dev); |
611 | struct can_ctrlmode cm = {.flags = priv->ctrlmode}; | 665 | struct can_ctrlmode cm = {.flags = priv->ctrlmode}; |
666 | struct can_berr_counter bec; | ||
612 | enum can_state state = priv->state; | 667 | enum can_state state = priv->state; |
613 | 668 | ||
614 | if (priv->do_get_state) | 669 | if (priv->do_get_state) |
@@ -619,6 +674,8 @@ static int can_fill_info(struct sk_buff *skb, const struct net_device *dev) | |||
619 | NLA_PUT(skb, IFLA_CAN_BITTIMING, | 674 | NLA_PUT(skb, IFLA_CAN_BITTIMING, |
620 | sizeof(priv->bittiming), &priv->bittiming); | 675 | sizeof(priv->bittiming), &priv->bittiming); |
621 | NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock); | 676 | NLA_PUT(skb, IFLA_CAN_CLOCK, sizeof(cm), &priv->clock); |
677 | if (priv->do_get_berr_counter && !priv->do_get_berr_counter(dev, &bec)) | ||
678 | NLA_PUT(skb, IFLA_CAN_BERR_COUNTER, sizeof(bec), &bec); | ||
622 | if (priv->bittiming_const) | 679 | if (priv->bittiming_const) |
623 | NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST, | 680 | NLA_PUT(skb, IFLA_CAN_BITTIMING_CONST, |
624 | sizeof(*priv->bittiming_const), priv->bittiming_const); | 681 | sizeof(*priv->bittiming_const), priv->bittiming_const); |
@@ -647,7 +704,7 @@ nla_put_failure: | |||
647 | return -EMSGSIZE; | 704 | return -EMSGSIZE; |
648 | } | 705 | } |
649 | 706 | ||
650 | static int can_newlink(struct net_device *dev, | 707 | static int can_newlink(struct net *src_net, struct net_device *dev, |
651 | struct nlattr *tb[], struct nlattr *data[]) | 708 | struct nlattr *tb[], struct nlattr *data[]) |
652 | { | 709 | { |
653 | return -EOPNOTSUPP; | 710 | return -EOPNOTSUPP; |