diff options
author | Wolfgang Grandegger <wg@grandegger.com> | 2009-10-20 03:08:01 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-20 03:08:01 -0400 |
commit | 7b6856a0296a8f187bb88ba31fa83a08abba7966 (patch) | |
tree | 0afbcc9291eeb368e4e4616b6eed9062df646de0 /drivers/net/can/dev.c | |
parent | 0eae750e6019a93643063924209c1daf9cb9b4a7 (diff) |
can: provide library functions for skb allocation
This patch makes the private functions alloc_can_skb() and
alloc_can_err_skb() of the at91_can driver public and adapts all
drivers to use these. While making the patch I realized, that
the skb's are *not* setup consistently. It's now done as shown
below:
skb->protocol = htons(ETH_P_CAN);
skb->pkt_type = PACKET_BROADCAST;
skb->ip_summed = CHECKSUM_UNNECESSARY;
*cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame));
memset(*cf, 0, sizeof(struct can_frame));
The frame is zeroed out to avoid uninitialized data to be passed to
user space. Some drivers or library code did not set "pkt_type" or
"ip_summed". Also, "__constant_htons()" should not be used for
runtime invocations, as pointed out by David Miller.
Signed-off-by: Wolfgang Grandegger <wg@grandegger.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/can/dev.c')
-rw-r--r-- | drivers/net/can/dev.c | 42 |
1 files changed, 35 insertions, 7 deletions
diff --git a/drivers/net/can/dev.c b/drivers/net/can/dev.c index 39b99f57c265..c3db111d2ff5 100644 --- a/drivers/net/can/dev.c +++ b/drivers/net/can/dev.c | |||
@@ -366,17 +366,12 @@ void can_restart(unsigned long data) | |||
366 | can_flush_echo_skb(dev); | 366 | can_flush_echo_skb(dev); |
367 | 367 | ||
368 | /* send restart message upstream */ | 368 | /* send restart message upstream */ |
369 | skb = dev_alloc_skb(sizeof(struct can_frame)); | 369 | skb = alloc_can_err_skb(dev, &cf); |
370 | if (skb == NULL) { | 370 | if (skb == NULL) { |
371 | err = -ENOMEM; | 371 | err = -ENOMEM; |
372 | goto restart; | 372 | goto restart; |
373 | } | 373 | } |
374 | skb->dev = dev; | 374 | cf->can_id |= CAN_ERR_RESTARTED; |
375 | skb->protocol = htons(ETH_P_CAN); | ||
376 | cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | ||
377 | memset(cf, 0, sizeof(struct can_frame)); | ||
378 | cf->can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; | ||
379 | cf->can_dlc = CAN_ERR_DLC; | ||
380 | 375 | ||
381 | netif_rx(skb); | 376 | netif_rx(skb); |
382 | 377 | ||
@@ -449,6 +444,39 @@ static void can_setup(struct net_device *dev) | |||
449 | dev->features = NETIF_F_NO_CSUM; | 444 | dev->features = NETIF_F_NO_CSUM; |
450 | } | 445 | } |
451 | 446 | ||
447 | struct sk_buff *alloc_can_skb(struct net_device *dev, struct can_frame **cf) | ||
448 | { | ||
449 | struct sk_buff *skb; | ||
450 | |||
451 | skb = netdev_alloc_skb(dev, sizeof(struct can_frame)); | ||
452 | if (unlikely(!skb)) | ||
453 | return NULL; | ||
454 | |||
455 | skb->protocol = htons(ETH_P_CAN); | ||
456 | skb->pkt_type = PACKET_BROADCAST; | ||
457 | skb->ip_summed = CHECKSUM_UNNECESSARY; | ||
458 | *cf = (struct can_frame *)skb_put(skb, sizeof(struct can_frame)); | ||
459 | memset(*cf, 0, sizeof(struct can_frame)); | ||
460 | |||
461 | return skb; | ||
462 | } | ||
463 | EXPORT_SYMBOL_GPL(alloc_can_skb); | ||
464 | |||
465 | struct sk_buff *alloc_can_err_skb(struct net_device *dev, struct can_frame **cf) | ||
466 | { | ||
467 | struct sk_buff *skb; | ||
468 | |||
469 | skb = alloc_can_skb(dev, cf); | ||
470 | if (unlikely(!skb)) | ||
471 | return NULL; | ||
472 | |||
473 | (*cf)->can_id = CAN_ERR_FLAG; | ||
474 | (*cf)->can_dlc = CAN_ERR_DLC; | ||
475 | |||
476 | return skb; | ||
477 | } | ||
478 | EXPORT_SYMBOL_GPL(alloc_can_err_skb); | ||
479 | |||
452 | /* | 480 | /* |
453 | * Allocate and setup space for the CAN network device | 481 | * Allocate and setup space for the CAN network device |
454 | */ | 482 | */ |