diff options
Diffstat (limited to 'net/can/af_can.c')
| -rw-r--r-- | net/can/af_can.c | 144 |
1 files changed, 48 insertions, 96 deletions
diff --git a/net/can/af_can.c b/net/can/af_can.c index 606832115674..702be5a2c956 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
| @@ -77,8 +77,8 @@ static int stats_timer __read_mostly = 1; | |||
| 77 | module_param(stats_timer, int, S_IRUGO); | 77 | module_param(stats_timer, int, S_IRUGO); |
| 78 | MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)"); | 78 | MODULE_PARM_DESC(stats_timer, "enable timer for statistics (default:on)"); |
| 79 | 79 | ||
| 80 | HLIST_HEAD(can_rx_dev_list); | 80 | /* receive filters subscribed for 'all' CAN devices */ |
| 81 | static struct dev_rcv_lists can_rx_alldev_list; | 81 | struct dev_rcv_lists can_rx_alldev_list; |
| 82 | static DEFINE_SPINLOCK(can_rcvlists_lock); | 82 | static DEFINE_SPINLOCK(can_rcvlists_lock); |
| 83 | 83 | ||
| 84 | static struct kmem_cache *rcv_cache __read_mostly; | 84 | static struct kmem_cache *rcv_cache __read_mostly; |
| @@ -114,7 +114,8 @@ static void can_sock_destruct(struct sock *sk) | |||
| 114 | skb_queue_purge(&sk->sk_receive_queue); | 114 | skb_queue_purge(&sk->sk_receive_queue); |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | static int can_create(struct net *net, struct socket *sock, int protocol) | 117 | static int can_create(struct net *net, struct socket *sock, int protocol, |
| 118 | int kern) | ||
| 118 | { | 119 | { |
| 119 | struct sock *sk; | 120 | struct sock *sk; |
| 120 | struct can_proto *cp; | 121 | struct can_proto *cp; |
| @@ -125,7 +126,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol) | |||
| 125 | if (protocol < 0 || protocol >= CAN_NPROTO) | 126 | if (protocol < 0 || protocol >= CAN_NPROTO) |
| 126 | return -EINVAL; | 127 | return -EINVAL; |
| 127 | 128 | ||
| 128 | if (net != &init_net) | 129 | if (!net_eq(net, &init_net)) |
| 129 | return -EAFNOSUPPORT; | 130 | return -EAFNOSUPPORT; |
| 130 | 131 | ||
| 131 | #ifdef CONFIG_MODULES | 132 | #ifdef CONFIG_MODULES |
| @@ -160,11 +161,6 @@ static int can_create(struct net *net, struct socket *sock, int protocol) | |||
| 160 | goto errout; | 161 | goto errout; |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | if (cp->capability >= 0 && !capable(cp->capability)) { | ||
| 164 | err = -EPERM; | ||
| 165 | goto errout; | ||
| 166 | } | ||
| 167 | |||
| 168 | sock->ops = cp->ops; | 164 | sock->ops = cp->ops; |
| 169 | 165 | ||
| 170 | sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot); | 166 | sk = sk_alloc(net, PF_CAN, GFP_KERNEL, cp->prot); |
| @@ -296,28 +292,10 @@ EXPORT_SYMBOL(can_send); | |||
| 296 | 292 | ||
| 297 | static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev) | 293 | static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev) |
| 298 | { | 294 | { |
| 299 | struct dev_rcv_lists *d = NULL; | 295 | if (!dev) |
| 300 | struct hlist_node *n; | 296 | return &can_rx_alldev_list; |
| 301 | 297 | else | |
| 302 | /* | 298 | return (struct dev_rcv_lists *)dev->ml_priv; |
| 303 | * find receive list for this device | ||
| 304 | * | ||
| 305 | * The hlist_for_each_entry*() macros curse through the list | ||
| 306 | * using the pointer variable n and set d to the containing | ||
| 307 | * struct in each list iteration. Therefore, after list | ||
| 308 | * iteration, d is unmodified when the list is empty, and it | ||
| 309 | * points to last list element, when the list is non-empty | ||
| 310 | * but no match in the loop body is found. I.e. d is *not* | ||
| 311 | * NULL when no match is found. We can, however, use the | ||
| 312 | * cursor variable n to decide if a match was found. | ||
| 313 | */ | ||
| 314 | |||
| 315 | hlist_for_each_entry_rcu(d, n, &can_rx_dev_list, list) { | ||
| 316 | if (d->dev == dev) | ||
| 317 | break; | ||
| 318 | } | ||
| 319 | |||
| 320 | return n ? d : NULL; | ||
| 321 | } | 299 | } |
| 322 | 300 | ||
| 323 | /** | 301 | /** |
| @@ -379,8 +357,8 @@ static struct hlist_head *find_rcv_list(canid_t *can_id, canid_t *mask, | |||
| 379 | return &d->rx[RX_ALL]; | 357 | return &d->rx[RX_ALL]; |
| 380 | 358 | ||
| 381 | /* extra filterlists for the subscription of a single non-RTR can_id */ | 359 | /* extra filterlists for the subscription of a single non-RTR can_id */ |
| 382 | if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS) | 360 | if (((*mask & CAN_EFF_RTR_FLAGS) == CAN_EFF_RTR_FLAGS) && |
| 383 | && !(*can_id & CAN_RTR_FLAG)) { | 361 | !(*can_id & CAN_RTR_FLAG)) { |
| 384 | 362 | ||
| 385 | if (*can_id & CAN_EFF_FLAG) { | 363 | if (*can_id & CAN_EFF_FLAG) { |
| 386 | if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) { | 364 | if (*mask == (CAN_EFF_MASK | CAN_EFF_RTR_FLAGS)) { |
| @@ -437,6 +415,9 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, | |||
| 437 | 415 | ||
| 438 | /* insert new receiver (dev,canid,mask) -> (func,data) */ | 416 | /* insert new receiver (dev,canid,mask) -> (func,data) */ |
| 439 | 417 | ||
| 418 | if (dev && dev->type != ARPHRD_CAN) | ||
| 419 | return -ENODEV; | ||
| 420 | |||
| 440 | r = kmem_cache_alloc(rcv_cache, GFP_KERNEL); | 421 | r = kmem_cache_alloc(rcv_cache, GFP_KERNEL); |
| 441 | if (!r) | 422 | if (!r) |
| 442 | return -ENOMEM; | 423 | return -ENOMEM; |
| @@ -472,16 +453,6 @@ int can_rx_register(struct net_device *dev, canid_t can_id, canid_t mask, | |||
| 472 | EXPORT_SYMBOL(can_rx_register); | 453 | EXPORT_SYMBOL(can_rx_register); |
| 473 | 454 | ||
| 474 | /* | 455 | /* |
| 475 | * can_rx_delete_device - rcu callback for dev_rcv_lists structure removal | ||
| 476 | */ | ||
| 477 | static void can_rx_delete_device(struct rcu_head *rp) | ||
| 478 | { | ||
| 479 | struct dev_rcv_lists *d = container_of(rp, struct dev_rcv_lists, rcu); | ||
| 480 | |||
| 481 | kfree(d); | ||
| 482 | } | ||
| 483 | |||
| 484 | /* | ||
| 485 | * can_rx_delete_receiver - rcu callback for single receiver entry removal | 456 | * can_rx_delete_receiver - rcu callback for single receiver entry removal |
| 486 | */ | 457 | */ |
| 487 | static void can_rx_delete_receiver(struct rcu_head *rp) | 458 | static void can_rx_delete_receiver(struct rcu_head *rp) |
| @@ -510,6 +481,9 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, | |||
| 510 | struct hlist_node *next; | 481 | struct hlist_node *next; |
| 511 | struct dev_rcv_lists *d; | 482 | struct dev_rcv_lists *d; |
| 512 | 483 | ||
| 484 | if (dev && dev->type != ARPHRD_CAN) | ||
| 485 | return; | ||
| 486 | |||
| 513 | spin_lock(&can_rcvlists_lock); | 487 | spin_lock(&can_rcvlists_lock); |
| 514 | 488 | ||
| 515 | d = find_dev_rcv_lists(dev); | 489 | d = find_dev_rcv_lists(dev); |
| @@ -529,8 +503,8 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, | |||
| 529 | */ | 503 | */ |
| 530 | 504 | ||
| 531 | hlist_for_each_entry_rcu(r, next, rl, list) { | 505 | hlist_for_each_entry_rcu(r, next, rl, list) { |
| 532 | if (r->can_id == can_id && r->mask == mask | 506 | if (r->can_id == can_id && r->mask == mask && |
| 533 | && r->func == func && r->data == data) | 507 | r->func == func && r->data == data) |
| 534 | break; | 508 | break; |
| 535 | } | 509 | } |
| 536 | 510 | ||
| @@ -545,7 +519,6 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, | |||
| 545 | "dev %s, id %03X, mask %03X\n", | 519 | "dev %s, id %03X, mask %03X\n", |
| 546 | DNAME(dev), can_id, mask); | 520 | DNAME(dev), can_id, mask); |
| 547 | r = NULL; | 521 | r = NULL; |
| 548 | d = NULL; | ||
| 549 | goto out; | 522 | goto out; |
| 550 | } | 523 | } |
| 551 | 524 | ||
| @@ -556,10 +529,10 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, | |||
| 556 | can_pstats.rcv_entries--; | 529 | can_pstats.rcv_entries--; |
| 557 | 530 | ||
| 558 | /* remove device structure requested by NETDEV_UNREGISTER */ | 531 | /* remove device structure requested by NETDEV_UNREGISTER */ |
| 559 | if (d->remove_on_zero_entries && !d->entries) | 532 | if (d->remove_on_zero_entries && !d->entries) { |
| 560 | hlist_del_rcu(&d->list); | 533 | kfree(d); |
| 561 | else | 534 | dev->ml_priv = NULL; |
| 562 | d = NULL; | 535 | } |
| 563 | 536 | ||
| 564 | out: | 537 | out: |
| 565 | spin_unlock(&can_rcvlists_lock); | 538 | spin_unlock(&can_rcvlists_lock); |
| @@ -567,10 +540,6 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask, | |||
| 567 | /* schedule the receiver item for deletion */ | 540 | /* schedule the receiver item for deletion */ |
| 568 | if (r) | 541 | if (r) |
| 569 | call_rcu(&r->rcu, can_rx_delete_receiver); | 542 | call_rcu(&r->rcu, can_rx_delete_receiver); |
| 570 | |||
| 571 | /* schedule the device structure for deletion */ | ||
| 572 | if (d) | ||
| 573 | call_rcu(&d->rcu, can_rx_delete_device); | ||
| 574 | } | 543 | } |
| 575 | EXPORT_SYMBOL(can_rx_unregister); | 544 | EXPORT_SYMBOL(can_rx_unregister); |
| 576 | 545 | ||
| @@ -784,48 +753,35 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, | |||
| 784 | 753 | ||
| 785 | case NETDEV_REGISTER: | 754 | case NETDEV_REGISTER: |
| 786 | 755 | ||
| 787 | /* | 756 | /* create new dev_rcv_lists for this device */ |
| 788 | * create new dev_rcv_lists for this device | ||
| 789 | * | ||
| 790 | * N.B. zeroing the struct is the correct initialization | ||
| 791 | * for the embedded hlist_head structs. | ||
| 792 | * Another list type, e.g. list_head, would require | ||
| 793 | * explicit initialization. | ||
| 794 | */ | ||
| 795 | |||
| 796 | d = kzalloc(sizeof(*d), GFP_KERNEL); | 757 | d = kzalloc(sizeof(*d), GFP_KERNEL); |
| 797 | if (!d) { | 758 | if (!d) { |
| 798 | printk(KERN_ERR | 759 | printk(KERN_ERR |
| 799 | "can: allocation of receive list failed\n"); | 760 | "can: allocation of receive list failed\n"); |
| 800 | return NOTIFY_DONE; | 761 | return NOTIFY_DONE; |
| 801 | } | 762 | } |
| 802 | d->dev = dev; | 763 | BUG_ON(dev->ml_priv); |
| 803 | 764 | dev->ml_priv = d; | |
| 804 | spin_lock(&can_rcvlists_lock); | ||
| 805 | hlist_add_head_rcu(&d->list, &can_rx_dev_list); | ||
| 806 | spin_unlock(&can_rcvlists_lock); | ||
| 807 | 765 | ||
| 808 | break; | 766 | break; |
| 809 | 767 | ||
| 810 | case NETDEV_UNREGISTER: | 768 | case NETDEV_UNREGISTER: |
| 811 | spin_lock(&can_rcvlists_lock); | 769 | spin_lock(&can_rcvlists_lock); |
| 812 | 770 | ||
| 813 | d = find_dev_rcv_lists(dev); | 771 | d = dev->ml_priv; |
| 814 | if (d) { | 772 | if (d) { |
| 815 | if (d->entries) { | 773 | if (d->entries) |
| 816 | d->remove_on_zero_entries = 1; | 774 | d->remove_on_zero_entries = 1; |
| 817 | d = NULL; | 775 | else { |
| 818 | } else | 776 | kfree(d); |
| 819 | hlist_del_rcu(&d->list); | 777 | dev->ml_priv = NULL; |
| 778 | } | ||
| 820 | } else | 779 | } else |
| 821 | printk(KERN_ERR "can: notifier: receive list not " | 780 | printk(KERN_ERR "can: notifier: receive list not " |
| 822 | "found for dev %s\n", dev->name); | 781 | "found for dev %s\n", dev->name); |
| 823 | 782 | ||
| 824 | spin_unlock(&can_rcvlists_lock); | 783 | spin_unlock(&can_rcvlists_lock); |
| 825 | 784 | ||
| 826 | if (d) | ||
| 827 | call_rcu(&d->rcu, can_rx_delete_device); | ||
| 828 | |||
| 829 | break; | 785 | break; |
| 830 | } | 786 | } |
| 831 | 787 | ||
| @@ -842,7 +798,7 @@ static struct packet_type can_packet __read_mostly = { | |||
| 842 | .func = can_rcv, | 798 | .func = can_rcv, |
| 843 | }; | 799 | }; |
| 844 | 800 | ||
| 845 | static struct net_proto_family can_family_ops __read_mostly = { | 801 | static const struct net_proto_family can_family_ops = { |
| 846 | .family = PF_CAN, | 802 | .family = PF_CAN, |
| 847 | .create = can_create, | 803 | .create = can_create, |
| 848 | .owner = THIS_MODULE, | 804 | .owner = THIS_MODULE, |
| @@ -857,21 +813,13 @@ static __init int can_init(void) | |||
| 857 | { | 813 | { |
| 858 | printk(banner); | 814 | printk(banner); |
| 859 | 815 | ||
| 816 | memset(&can_rx_alldev_list, 0, sizeof(can_rx_alldev_list)); | ||
| 817 | |||
| 860 | rcv_cache = kmem_cache_create("can_receiver", sizeof(struct receiver), | 818 | rcv_cache = kmem_cache_create("can_receiver", sizeof(struct receiver), |
| 861 | 0, 0, NULL); | 819 | 0, 0, NULL); |
| 862 | if (!rcv_cache) | 820 | if (!rcv_cache) |
| 863 | return -ENOMEM; | 821 | return -ENOMEM; |
| 864 | 822 | ||
| 865 | /* | ||
| 866 | * Insert can_rx_alldev_list for reception on all devices. | ||
| 867 | * This struct is zero initialized which is correct for the | ||
| 868 | * embedded hlist heads, the dev pointer, and the entries counter. | ||
| 869 | */ | ||
| 870 | |||
| 871 | spin_lock(&can_rcvlists_lock); | ||
| 872 | hlist_add_head_rcu(&can_rx_alldev_list.list, &can_rx_dev_list); | ||
| 873 | spin_unlock(&can_rcvlists_lock); | ||
| 874 | |||
| 875 | if (stats_timer) { | 823 | if (stats_timer) { |
| 876 | /* the statistics are updated every second (timer triggered) */ | 824 | /* the statistics are updated every second (timer triggered) */ |
| 877 | setup_timer(&can_stattimer, can_stat_update, 0); | 825 | setup_timer(&can_stattimer, can_stat_update, 0); |
| @@ -891,8 +839,7 @@ static __init int can_init(void) | |||
| 891 | 839 | ||
| 892 | static __exit void can_exit(void) | 840 | static __exit void can_exit(void) |
| 893 | { | 841 | { |
| 894 | struct dev_rcv_lists *d; | 842 | struct net_device *dev; |
| 895 | struct hlist_node *n, *next; | ||
| 896 | 843 | ||
| 897 | if (stats_timer) | 844 | if (stats_timer) |
| 898 | del_timer(&can_stattimer); | 845 | del_timer(&can_stattimer); |
| @@ -904,14 +851,19 @@ static __exit void can_exit(void) | |||
| 904 | unregister_netdevice_notifier(&can_netdev_notifier); | 851 | unregister_netdevice_notifier(&can_netdev_notifier); |
| 905 | sock_unregister(PF_CAN); | 852 | sock_unregister(PF_CAN); |
| 906 | 853 | ||
| 907 | /* remove can_rx_dev_list */ | 854 | /* remove created dev_rcv_lists from still registered CAN devices */ |
| 908 | spin_lock(&can_rcvlists_lock); | 855 | rcu_read_lock(); |
| 909 | hlist_del(&can_rx_alldev_list.list); | 856 | for_each_netdev_rcu(&init_net, dev) { |
| 910 | hlist_for_each_entry_safe(d, n, next, &can_rx_dev_list, list) { | 857 | if (dev->type == ARPHRD_CAN && dev->ml_priv){ |
| 911 | hlist_del(&d->list); | 858 | |
| 912 | kfree(d); | 859 | struct dev_rcv_lists *d = dev->ml_priv; |
| 860 | |||
| 861 | BUG_ON(d->entries); | ||
| 862 | kfree(d); | ||
| 863 | dev->ml_priv = NULL; | ||
| 864 | } | ||
| 913 | } | 865 | } |
| 914 | spin_unlock(&can_rcvlists_lock); | 866 | rcu_read_unlock(); |
| 915 | 867 | ||
| 916 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 868 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
| 917 | 869 | ||
