]> rtime.felk.cvut.cz Git - socketcan-devel.git/commitdiff
Consistently clean up the reference dev->ml_priv when the device receiver list is...
authorhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Sun, 24 Jan 2010 21:35:06 +0000 (21:35 +0000)
committerhartkopp <hartkopp@030b6a49-0b11-0410-94ab-b0dab22257f2>
Sun, 24 Jan 2010 21:35:06 +0000 (21:35 +0000)
Cleanly separate find_dev_rcv_lists() function for 2.6.26+ as we do not need the fallback.

git-svn-id: svn://svn.berlios.de//socketcan/trunk@1119 030b6a49-0b11-0410-94ab-b0dab22257f2

kernel/2.6/net/can/af_can.c

index 5f3713214cef245ec0a918381d3c64b3d41913f8..14dbba5b51aa70ce25c9a6ab9ce45c7ba5567175 100644 (file)
@@ -373,33 +373,34 @@ EXPORT_SYMBOL(can_send);
  * af_can rx path
  */
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
 static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
 {
-       struct dev_rcv_lists *d = NULL;
-       struct hlist_node *n;
-
-       /* find receive list for this device */
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
        /*
+        * find receive list for this device
+        *
         * Since 2.6.26 a new "midlevel private" ml_priv pointer has been
         * introduced in struct net_device. We use this pointer to omit the
         * linear walk through the can_rx_dev_list. A similar speedup has been
         * queued for 2.6.34 mainline but using the new netdev_rcu lists.
+        * Therefore the can_rx_dev_list is still needed (e.g. in proc.c)
         */
 
        /* dev == NULL is the indicator for the 'all' filterlist */
        if (!dev)
                return &can_rx_alldev_list;
-
-       /* do not search in rcu list when we have a direct reference */
-       if (dev->ml_priv)
+       else
                return (struct dev_rcv_lists *)dev->ml_priv;
-
-       /* fall back to standard behaviour */
-#endif
+}
+#else
+static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
+{
+       struct dev_rcv_lists *d = NULL;
+       struct hlist_node *n;
 
        /*
+        * find receive list for this device
+        *
         * The hlist_for_each_entry*() macros curse through the list
         * using the pointer variable n and set d to the containing
         * struct in each list iteration.  Therefore, after list
@@ -417,6 +418,7 @@ static struct dev_rcv_lists *find_dev_rcv_lists(struct net_device *dev)
 
        return n ? d : NULL;
 }
+#endif
 
 /**
  * find_rcv_list - determine optimal filterlist inside device filter struct
@@ -654,9 +656,12 @@ void can_rx_unregister(struct net_device *dev, canid_t can_id, canid_t mask,
                can_pstats.rcv_entries--;
 
        /* remove device structure requested by NETDEV_UNREGISTER */
-       if (d->remove_on_zero_entries && !d->entries)
+       if (d->remove_on_zero_entries && !d->entries) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+               dev->ml_priv = NULL;
+#endif
                hlist_del_rcu(&d->list);
-       else
+       else
                d = NULL;
 
  out:
@@ -934,6 +939,7 @@ static int can_notifier(struct notifier_block *nb, unsigned long msg,
 
                spin_lock(&can_rcvlists_lock);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+               BUG_ON(dev->ml_priv);
                dev->ml_priv = d;
 #endif
                hlist_add_head_rcu(&d->list, &can_rx_dev_list);
@@ -1056,6 +1062,10 @@ static __exit void can_exit(void)
        hlist_del(&can_rx_alldev_list.list);
        hlist_for_each_entry_safe(d, n, next, &can_rx_dev_list, list) {
                hlist_del(&d->list);
+               BUG_ON(d->entries);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+               d->dev->ml_priv = NULL;
+#endif
                kfree(d);
        }
        spin_unlock(&can_rcvlists_lock);