* 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
return n ? d : NULL;
}
+#endif
/**
* find_rcv_list - determine optimal filterlist inside device filter struct
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:
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);
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);