diff options
author | Oliver Hartkopp <oliver@hartkopp.net> | 2009-01-06 14:07:54 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-01-06 14:07:54 -0500 |
commit | 1fa17d4ba43d7e5aab5e90777b07da06524f6748 (patch) | |
tree | ebe8704bd84c51d29c17a8425b496a13b4935dc5 | |
parent | 98658bc9dc37cfb7c3bf5585ca73ce44aeb05c9e (diff) |
can: omit unneeded skb_clone() calls
The AF_CAN core delivered always cloned sk_buffs to the AF_CAN
protocols, although this was _only_ needed by the can-raw protocol.
With this (additionally documented) change, the AF_CAN core calls the
callback functions of the registered AF_CAN protocols with the original
(uncloned) sk_buff pointer and let's the can-raw protocol do the
skb_clone() itself which omits all unneeded skb_clone() calls for other
AF_CAN protocols.
Signed-off-by: Oliver Hartkopp <oliver@hartkopp.net>
Signed-off-by: Urs Thuermann <urs.thuermann@volkswagen.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | include/linux/can/core.h | 2 | ||||
-rw-r--r-- | net/can/af_can.c | 15 | ||||
-rw-r--r-- | net/can/bcm.c | 12 | ||||
-rw-r--r-- | net/can/raw.c | 15 |
4 files changed, 22 insertions, 22 deletions
diff --git a/include/linux/can/core.h b/include/linux/can/core.h index f50785ad4781..25085cbadcfc 100644 --- a/include/linux/can/core.h +++ b/include/linux/can/core.h | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <linux/skbuff.h> | 19 | #include <linux/skbuff.h> |
20 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
21 | 21 | ||
22 | #define CAN_VERSION "20081130" | 22 | #define CAN_VERSION "20090105" |
23 | 23 | ||
24 | /* increment this number each time you change some user-space interface */ | 24 | /* increment this number each time you change some user-space interface */ |
25 | #define CAN_ABI_VERSION "8" | 25 | #define CAN_ABI_VERSION "8" |
diff --git a/net/can/af_can.c b/net/can/af_can.c index 3dadb338addd..fa417ca6cbe6 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -414,6 +414,12 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, | |||
414 | * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can | 414 | * The filter can be inverted (CAN_INV_FILTER bit set in can_id) or it can |
415 | * filter for error frames (CAN_ERR_FLAG bit set in mask). | 415 | * filter for error frames (CAN_ERR_FLAG bit set in mask). |
416 | * | 416 | * |
417 | * The provided pointer to the sk_buff is guaranteed to be valid as long as | ||
418 | * the callback function is running. The callback function must *not* free | ||
419 | * the given sk_buff while processing it's task. When the given sk_buff is | ||
420 | * needed after the end of the callback function it must be cloned inside | ||
421 | * the callback function with skb_clone(). | ||
422 | * | ||
417 | * Return: | 423 | * Return: |
418 | * 0 on success | 424 | * 0 on success |
419 | * -ENOMEM on missing cache mem to create subscription entry | 425 | * -ENOMEM on missing cache mem to create subscription entry |
@@ -569,13 +575,8 @@ EXPORT_SYMBOL(can_rx_unregister); | |||
569 | 575 | ||
570 | static inline void deliver(struct sk_buff *skb, struct receiver *r) | 576 | static inline void deliver(struct sk_buff *skb, struct receiver *r) |
571 | { | 577 | { |
572 | struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); | 578 | r->func(skb, r->data); |
573 | 579 | r->matches++; | |
574 | if (clone) { | ||
575 | clone->sk = skb->sk; | ||
576 | r->func(clone, r->data); | ||
577 | r->matches++; | ||
578 | } | ||
579 | } | 580 | } |
580 | 581 | ||
581 | static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb) | 582 | static int can_rcv_filter(struct dev_rcv_lists *d, struct sk_buff *skb) |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 6248ae2502c7..1649c8ab2c2f 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -633,7 +633,7 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) | |||
633 | hrtimer_cancel(&op->timer); | 633 | hrtimer_cancel(&op->timer); |
634 | 634 | ||
635 | if (op->can_id != rxframe->can_id) | 635 | if (op->can_id != rxframe->can_id) |
636 | goto rx_freeskb; | 636 | return; |
637 | 637 | ||
638 | /* save rx timestamp */ | 638 | /* save rx timestamp */ |
639 | op->rx_stamp = skb->tstamp; | 639 | op->rx_stamp = skb->tstamp; |
@@ -645,19 +645,19 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) | |||
645 | if (op->flags & RX_RTR_FRAME) { | 645 | if (op->flags & RX_RTR_FRAME) { |
646 | /* send reply for RTR-request (placed in op->frames[0]) */ | 646 | /* send reply for RTR-request (placed in op->frames[0]) */ |
647 | bcm_can_tx(op); | 647 | bcm_can_tx(op); |
648 | goto rx_freeskb; | 648 | return; |
649 | } | 649 | } |
650 | 650 | ||
651 | if (op->flags & RX_FILTER_ID) { | 651 | if (op->flags & RX_FILTER_ID) { |
652 | /* the easiest case */ | 652 | /* the easiest case */ |
653 | bcm_rx_update_and_send(op, &op->last_frames[0], rxframe); | 653 | bcm_rx_update_and_send(op, &op->last_frames[0], rxframe); |
654 | goto rx_freeskb_starttimer; | 654 | goto rx_starttimer; |
655 | } | 655 | } |
656 | 656 | ||
657 | if (op->nframes == 1) { | 657 | if (op->nframes == 1) { |
658 | /* simple compare with index 0 */ | 658 | /* simple compare with index 0 */ |
659 | bcm_rx_cmp_to_index(op, 0, rxframe); | 659 | bcm_rx_cmp_to_index(op, 0, rxframe); |
660 | goto rx_freeskb_starttimer; | 660 | goto rx_starttimer; |
661 | } | 661 | } |
662 | 662 | ||
663 | if (op->nframes > 1) { | 663 | if (op->nframes > 1) { |
@@ -678,10 +678,8 @@ static void bcm_rx_handler(struct sk_buff *skb, void *data) | |||
678 | } | 678 | } |
679 | } | 679 | } |
680 | 680 | ||
681 | rx_freeskb_starttimer: | 681 | rx_starttimer: |
682 | bcm_rx_starttimer(op); | 682 | bcm_rx_starttimer(op); |
683 | rx_freeskb: | ||
684 | kfree_skb(skb); | ||
685 | } | 683 | } |
686 | 684 | ||
687 | /* | 685 | /* |
diff --git a/net/can/raw.c b/net/can/raw.c index 27aab63df467..0703cba4bf9f 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -99,13 +99,14 @@ static void raw_rcv(struct sk_buff *skb, void *data) | |||
99 | struct raw_sock *ro = raw_sk(sk); | 99 | struct raw_sock *ro = raw_sk(sk); |
100 | struct sockaddr_can *addr; | 100 | struct sockaddr_can *addr; |
101 | 101 | ||
102 | if (!ro->recv_own_msgs) { | 102 | /* check the received tx sock reference */ |
103 | /* check the received tx sock reference */ | 103 | if (!ro->recv_own_msgs && skb->sk == sk) |
104 | if (skb->sk == sk) { | 104 | return; |
105 | kfree_skb(skb); | 105 | |
106 | return; | 106 | /* clone the given skb to be able to enqueue it into the rcv queue */ |
107 | } | 107 | skb = skb_clone(skb, GFP_ATOMIC); |
108 | } | 108 | if (!skb) |
109 | return; | ||
109 | 110 | ||
110 | /* | 111 | /* |
111 | * Put the datagram to the queue so that raw_recvmsg() can | 112 | * Put the datagram to the queue so that raw_recvmsg() can |