diff options
Diffstat (limited to 'net/can/af_can.c')
-rw-r--r-- | net/can/af_can.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/net/can/af_can.c b/net/can/af_can.c index 1108079d934f..5488e4a6ccd0 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -445,6 +445,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, | |||
445 | * @func: callback function on filter match | 445 | * @func: callback function on filter match |
446 | * @data: returned parameter for callback function | 446 | * @data: returned parameter for callback function |
447 | * @ident: string for calling module identification | 447 | * @ident: string for calling module identification |
448 | * @sk: socket pointer (might be NULL) | ||
448 | * | 449 | * |
449 | * Description: | 450 | * Description: |
450 | * Invokes the callback function with the received sk_buff and the given | 451 | * Invokes the callback function with the received sk_buff and the given |
@@ -468,7 +469,7 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, | |||
468 | */ | 469 | */ |
469 | int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, | 470 | int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, |
470 | void (*func)(struct sk_buff *, void *), void *data, | 471 | void (*func)(struct sk_buff *, void *), void *data, |
471 | char *ident) | 472 | char *ident, struct sock *sk) |
472 | { | 473 | { |
473 | struct receiver *r; | 474 | struct receiver *r; |
474 | struct hlist_head *rl; | 475 | struct hlist_head *rl; |
@@ -496,6 +497,7 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, | |||
496 | r->func = func; | 497 | r->func = func; |
497 | r->data = data; | 498 | r->data = data; |
498 | r->ident = ident; | 499 | r->ident = ident; |
500 | r->sk = sk; | ||
499 | 501 | ||
500 | hlist_add_head_rcu(&r->list, rl); | 502 | hlist_add_head_rcu(&r->list, rl); |
501 | d->entries++; | 503 | d->entries++; |
@@ -520,8 +522,11 @@ EXPORT_SYMBOL(can_rx_register); | |||
520 | static void can_rx_delete_receiver(struct rcu_head *rp) | 522 | static void can_rx_delete_receiver(struct rcu_head *rp) |
521 | { | 523 | { |
522 | struct receiver *r = container_of(rp, struct receiver, rcu); | 524 | struct receiver *r = container_of(rp, struct receiver, rcu); |
525 | struct sock *sk = r->sk; | ||
523 | 526 | ||
524 | kmem_cache_free(rcv_cache, r); | 527 | kmem_cache_free(rcv_cache, r); |
528 | if (sk) | ||
529 | sock_put(sk); | ||
525 | } | 530 | } |
526 | 531 | ||
527 | /** | 532 | /** |
@@ -596,8 +601,11 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, | |||
596 | spin_unlock(&can_rcvlists_lock); | 601 | spin_unlock(&can_rcvlists_lock); |
597 | 602 | ||
598 | /* schedule the receiver item for deletion */ | 603 | /* schedule the receiver item for deletion */ |
599 | if (r) | 604 | if (r) { |
605 | if (r->sk) | ||
606 | sock_hold(r->sk); | ||
600 | call_rcu(&r->rcu, can_rx_delete_receiver); | 607 | call_rcu(&r->rcu, can_rx_delete_receiver); |
608 | } | ||
601 | } | 609 | } |
602 | EXPORT_SYMBOL(can_rx_unregister); | 610 | EXPORT_SYMBOL(can_rx_unregister); |
603 | 611 | ||