This patch removes the old method of allocating the per device protocol specific memory via a netdevice_notifier. This had the drawback, that the allocation can fail, leading to a lot of null pointer checks in the code. This also makes the live cycle management of this memory quite complicated. This patch switches from the allocating the struct can_dev_rcv_lists in a NETDEV_REGISTER call to using the dev->ml_priv, which is allocated by the driver since the previous patch.
Unified · Split
| @@ -746,6 +746,8 @@ struct net_device *alloc_candev_mqs(int sizeof_priv, unsigned int echo_skb_max, · 745 unmodified lines | ||
| 746 | 746 | priv = netdev_priv(dev); |
| 747 | 747 | priv->dev = dev; |
| 748 | 748 | |
| 749 | + dev->ml_priv = (void *)priv + ALIGN(sizeof_priv, NETDEV_ALIGN); | |
| 750 | + | |
| 749 | 751 | if (echo_skb_max) { |
| 750 | 752 | priv->echo_skb_max = echo_skb_max; |
| 751 | 753 | priv->echo_skb = (void *)priv + |
| @@ -536,6 +536,7 @@ static struct slcan *slc_alloc(void) · 535 unmodified lines | ||
| 536 | 536 | |
| 537 | 537 | dev->base_addr = i; |
| 538 | 538 | sl = netdev_priv(dev); |
| 539 | + dev->ml_priv = (void *)sl + ALIGN(sizeof(*sl), NETDEV_ALIGN); | |
| 539 | 540 | |
| 540 | 541 | /* Initialize channel control data */ |
| 541 | 542 | sl->magic = SLCAN_MAGIC; |
| @@ -153,6 +153,7 @@ static void vcan_setup(struct net_device *dev) · 152 unmodified lines | ||
| 153 | 153 | dev->addr_len = 0; |
| 154 | 154 | dev->tx_queue_len = 0; |
| 155 | 155 | dev->flags = IFF_NOARP; |
| 156 | + dev->ml_priv = netdev_priv(dev); | |
| 156 | 157 | |
| 157 | 158 | /* set flags according to driver capabilities */ |
| 158 | 159 | if (echo) |
| @@ -147,6 +147,7 @@ static void vxcan_setup(struct net_device *dev) · 146 unmodified lines | ||
| 147 | 147 | dev->flags = (IFF_NOARP|IFF_ECHO); |
| 148 | 148 | dev->netdev_ops = &vxcan_netdev_ops; |
| 149 | 149 | dev->needs_free_netdev = true; |
| 150 | + dev->ml_priv = netdev_priv(dev) + ALIGN(sizeof(struct vxcan_priv), NETDEV_ALIGN); | |
| 150 | 151 | } |
| 151 | 152 | |
| 152 | 153 | /* forward declaration for rtnl_create_link() */ |
| @@ -55,7 +55,6 @@ struct can_dev_rcv_lists { · 54 unmodified lines | ||
| 55 | 55 | struct hlist_head rx[RX_MAX]; |
| 56 | 56 | struct hlist_head rx_sff[CAN_SFF_RCV_ARRAY_SZ]; |
| 57 | 57 | struct hlist_head rx_eff[CAN_EFF_RCV_ARRAY_SZ]; |
| 58 | − int remove_on_zero_entries; | |
| 59 | 58 | int entries; |
| 60 | 59 | }; |
| 61 | 60 | |
| @@ -302,10 +302,12 @@ EXPORT_SYMBOL(can_send); · 301 unmodified lines | ||
| 302 | 302 | static struct can_dev_rcv_lists *can_dev_rcv_lists_find(struct net *net, |
| 303 | 303 | struct net_device *dev) |
| 304 | 304 | { |
| 305 | − if (!dev) | |
| 305 | + if (dev) { | |
| 306 | + struct can_ml_priv *ml_priv = dev->ml_priv; | |
| 307 | + return &ml_priv->dev_rcv_lists; | |
| 308 | + } else { | |
| 306 | 309 | return net->can.rx_alldev_list; |
| 307 | − else | |
| 308 | − return (struct can_dev_rcv_lists *)dev->ml_priv; | |
| 310 | + } | |
| 309 | 311 | } |
| 310 | 312 | |
| 311 | 313 | /** |
| @@ -561,12 +563,6 @@ void can_rx_unregister(struct net *net, struct net_device *dev, canid_t can_id, · 249 unmodified lines | ||
| 561 | 563 | if (rcv_lists_stats->rcv_entries > 0) |
| 562 | 564 | rcv_lists_stats->rcv_entries--; |
| 563 | 565 | |
| 564 | − /* remove device structure requested by NETDEV_UNREGISTER */ | |
| 565 | − if (dev_rcv_lists->remove_on_zero_entries && !dev_rcv_lists->entries) { | |
| 566 | − kfree(dev_rcv_lists); | |
| 567 | − dev->ml_priv = NULL; | |
| 568 | − } | |
| 569 | − | |
| 570 | 566 | out: |
| 571 | 567 | spin_unlock(&net->can.rcvlists_lock); |
| 572 | 568 | |
| @@ -788,41 +784,14 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg, · 215 unmodified lines | ||
| 788 | 784 | void *ptr) |
| 789 | 785 | { |
| 790 | 786 | struct net_device *dev = netdev_notifier_info_to_dev(ptr); |
| 791 | − struct can_dev_rcv_lists *dev_rcv_lists; | |
| 792 | 787 | |
| 793 | 788 | if (dev->type != ARPHRD_CAN) |
| 794 | 789 | return NOTIFY_DONE; |
| 795 | 790 | |
| 796 | 791 | switch (msg) { |
| 797 | 792 | case NETDEV_REGISTER: |
| 798 | − | |
| 799 | − /* create new dev_rcv_lists for this device */ | |
| 800 | − dev_rcv_lists = kzalloc(sizeof(*dev_rcv_lists), GFP_KERNEL); | |
| 801 | − if (!dev_rcv_lists) | |
| 802 | − return NOTIFY_DONE; | |
| 803 | − BUG_ON(dev->ml_priv); | |
| 804 | − dev->ml_priv = dev_rcv_lists; | |
| 805 | − | |
| 806 | − break; | |
| 807 | − | |
| 808 | − case NETDEV_UNREGISTER: | |
| 809 | − spin_lock(&dev_net(dev)->can.rcvlists_lock); | |
| 810 | − | |
| 811 | − dev_rcv_lists = dev->ml_priv; | |
| 812 | − if (dev_rcv_lists) { | |
| 813 | − if (dev_rcv_lists->entries) | |
| 814 | − dev_rcv_lists->remove_on_zero_entries = 1; | |
| 815 | − else { | |
| 816 | − kfree(dev_rcv_lists); | |
| 817 | − dev->ml_priv = NULL; | |
| 818 | − } | |
| 819 | − } else { | |
| 820 | − pr_err("can: notifier: receive list not found for dev %s\n", | |
| 821 | − dev->name); | |
| 822 | − } | |
| 823 | − | |
| 824 | − spin_unlock(&dev_net(dev)->can.rcvlists_lock); | |
| 825 | − | |
| 793 | + WARN(!dev->ml_priv, | |
| 794 | + "No CAN mid layer private allocated, please fix your driver and use alloc_candev()!\n"); | |
| 826 | 795 | break; |
| 827 | 796 | } |
| 828 | 797 | |