Merge git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net
[linux-2.6-microblaze.git] / include / linux / netdevice.h
index 0c79d9e..d126e36 100644 (file)
@@ -1842,6 +1842,11 @@ enum netdev_priv_flags {
  *     @udp_tunnel_nic:        UDP tunnel offload state
  *     @xdp_state:             stores info on attached XDP BPF programs
  *
+ *     @nested_level:  Used as as a parameter of spin_lock_nested() of
+ *                     dev->addr_list_lock.
+ *     @unlink_list:   As netif_addr_lock() can be called recursively,
+ *                     keep a list of interfaces to be deleted.
+ *
  *     FIXME: cleanup struct net_device such that network protocol info
  *     moves out.
  */
@@ -1946,6 +1951,7 @@ struct net_device {
        unsigned short          type;
        unsigned short          hard_header_len;
        unsigned char           min_header_len;
+       unsigned char           name_assign_type;
 
        unsigned short          needed_headroom;
        unsigned short          needed_tailroom;
@@ -1956,21 +1962,28 @@ struct net_device {
        unsigned char           addr_len;
        unsigned char           upper_level;
        unsigned char           lower_level;
+
        unsigned short          neigh_priv_len;
        unsigned short          dev_id;
        unsigned short          dev_port;
        spinlock_t              addr_list_lock;
-       unsigned char           name_assign_type;
-       bool                    uc_promisc;
+
        struct netdev_hw_addr_list      uc;
        struct netdev_hw_addr_list      mc;
        struct netdev_hw_addr_list      dev_addrs;
 
 #ifdef CONFIG_SYSFS
        struct kset             *queues_kset;
+#endif
+#ifdef CONFIG_LOCKDEP
+       struct list_head        unlink_list;
 #endif
        unsigned int            promiscuity;
        unsigned int            allmulti;
+       bool                    uc_promisc;
+#ifdef CONFIG_LOCKDEP
+       unsigned char           nested_level;
+#endif
 
 
        /* Protocol-specific pointers */
@@ -4281,17 +4294,23 @@ static inline void netif_tx_disable(struct net_device *dev)
 
 static inline void netif_addr_lock(struct net_device *dev)
 {
-       spin_lock(&dev->addr_list_lock);
-}
+       unsigned char nest_level = 0;
 
-static inline void netif_addr_lock_nested(struct net_device *dev)
-{
-       spin_lock_nested(&dev->addr_list_lock, dev->lower_level);
+#ifdef CONFIG_LOCKDEP
+       nest_level = dev->nested_level;
+#endif
+       spin_lock_nested(&dev->addr_list_lock, nest_level);
 }
 
 static inline void netif_addr_lock_bh(struct net_device *dev)
 {
-       spin_lock_bh(&dev->addr_list_lock);
+       unsigned char nest_level = 0;
+
+#ifdef CONFIG_LOCKDEP
+       nest_level = dev->nested_level;
+#endif
+       local_bh_disable();
+       spin_lock_nested(&dev->addr_list_lock, nest_level);
 }
 
 static inline void netif_addr_unlock(struct net_device *dev)
@@ -4476,12 +4495,38 @@ extern int              dev_rx_weight;
 extern int             dev_tx_weight;
 extern int             gro_normal_batch;
 
+enum {
+       NESTED_SYNC_IMM_BIT,
+       NESTED_SYNC_TODO_BIT,
+};
+
+#define __NESTED_SYNC_BIT(bit) ((u32)1 << (bit))
+#define __NESTED_SYNC(name)    __NESTED_SYNC_BIT(NESTED_SYNC_ ## name ## _BIT)
+
+#define NESTED_SYNC_IMM                __NESTED_SYNC(IMM)
+#define NESTED_SYNC_TODO       __NESTED_SYNC(TODO)
+
+struct netdev_nested_priv {
+       unsigned char flags;
+       void *data;
+};
+
 bool netdev_has_upper_dev(struct net_device *dev, struct net_device *upper_dev);
 struct net_device *netdev_upper_get_next_dev_rcu(struct net_device *dev,
                                                     struct list_head **iter);
 struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
                                                     struct list_head **iter);
 
+#ifdef CONFIG_LOCKDEP
+static LIST_HEAD(net_unlink_list);
+
+static inline void net_unlink_todo(struct net_device *dev)
+{
+       if (list_empty(&dev->unlink_list))
+               list_add_tail(&dev->unlink_list, &net_unlink_list);
+}
+#endif
+
 /* iterate through upper list, must be called under RCU read lock */
 #define netdev_for_each_upper_dev_rcu(dev, updev, iter) \
        for (iter = &(dev)->adj_list.upper, \
@@ -4491,8 +4536,8 @@ struct net_device *netdev_all_upper_get_next_dev_rcu(struct net_device *dev,
 
 int netdev_walk_all_upper_dev_rcu(struct net_device *dev,
                                  int (*fn)(struct net_device *upper_dev,
-                                           void *data),
-                                 void *data);
+                                           struct netdev_nested_priv *priv),
+                                 struct netdev_nested_priv *priv);
 
 bool netdev_has_upper_dev_all_rcu(struct net_device *dev,
                                  struct net_device *upper_dev);
@@ -4529,12 +4574,12 @@ struct net_device *netdev_next_lower_dev_rcu(struct net_device *dev,
                                             struct list_head **iter);
 int netdev_walk_all_lower_dev(struct net_device *dev,
                              int (*fn)(struct net_device *lower_dev,
-                                       void *data),
-                             void *data);
+                                       struct netdev_nested_priv *priv),
+                             struct netdev_nested_priv *priv);
 int netdev_walk_all_lower_dev_rcu(struct net_device *dev,
                                  int (*fn)(struct net_device *lower_dev,
-                                           void *data),
-                                 void *data);
+                                           struct netdev_nested_priv *priv),
+                                 struct netdev_nested_priv *priv);
 
 void *netdev_adjacent_get_private(struct list_head *adj_list);
 void *netdev_lower_get_first_private_rcu(struct net_device *dev);