| 1 |
|
| 2 |
|
| 3 | #ifndef _NET_NETDEV_LOCK_H
|
| 4 | #define _NET_NETDEV_LOCK_H
|
| 5 |
|
| 6 | #include <linux/lockdep.h>
|
| 7 | #include <linux/netdevice.h>
|
| 8 | #include <linux/rtnetlink.h>
|
| 9 |
|
| 10 | static inline bool netdev_trylock(struct net_device *dev)
|
| 11 | {
|
| 12 | return mutex_trylock(&dev->lock);
|
| 13 | }
|
| 14 |
|
| 15 | static inline void netdev_assert_locked(const struct net_device *dev)
|
| 16 | {
|
| 17 | lockdep_assert_held(&dev->lock);
|
| 18 | }
|
| 19 |
|
| 20 | static inline void
|
| 21 | netdev_assert_locked_or_invisible(const struct net_device *dev)
|
| 22 | {
|
| 23 | if (dev->reg_state == NETREG_REGISTERED ||
|
| 24 | dev->reg_state == NETREG_UNREGISTERING)
|
| 25 | netdev_assert_locked(dev);
|
| 26 | }
|
| 27 |
|
| 28 | static inline bool netdev_need_ops_lock(const struct net_device *dev)
|
| 29 | {
|
| 30 | bool ret = dev->request_ops_lock || !!dev->queue_mgmt_ops;
|
| 31 |
|
| 32 | #if IS_ENABLED(CONFIG_NET_SHAPER)
|
| 33 | ret |= !!dev->netdev_ops->net_shaper_ops;
|
| 34 | #endif
|
| 35 |
|
| 36 | return ret;
|
| 37 | }
|
| 38 |
|
| 39 | static inline void netdev_lock_ops(struct net_device *dev)
|
| 40 | {
|
| 41 | if (netdev_need_ops_lock(dev))
|
| 42 | netdev_lock(dev);
|
| 43 | }
|
| 44 |
|
| 45 | static inline void netdev_unlock_ops(struct net_device *dev)
|
| 46 | {
|
| 47 | if (netdev_need_ops_lock(dev))
|
| 48 | netdev_unlock(dev);
|
| 49 | }
|
| 50 |
|
| 51 | static inline void netdev_lock_ops_to_full(struct net_device *dev)
|
| 52 | {
|
| 53 | if (netdev_need_ops_lock(dev))
|
| 54 | netdev_assert_locked(dev);
|
| 55 | else
|
| 56 | netdev_lock(dev);
|
| 57 | }
|
| 58 |
|
| 59 | static inline void netdev_unlock_full_to_ops(struct net_device *dev)
|
| 60 | {
|
| 61 | if (netdev_need_ops_lock(dev))
|
| 62 | netdev_assert_locked(dev);
|
| 63 | else
|
| 64 | netdev_unlock(dev);
|
| 65 | }
|
| 66 |
|
| 67 | static inline void netdev_assert_locked_ops_compat(const struct net_device *dev)
|
| 68 | {
|
| 69 | if (netdev_need_ops_lock(dev))
|
| 70 | lockdep_assert_held(&dev->lock);
|
| 71 | else
|
| 72 | ASSERT_RTNL();
|
| 73 | }
|
| 74 |
|
| 75 | static inline void
|
| 76 | netdev_assert_locked_ops_compat_or_invisible(const struct net_device *dev)
|
| 77 | {
|
| 78 | if (dev->reg_state == NETREG_REGISTERED ||
|
| 79 | dev->reg_state == NETREG_UNREGISTERING)
|
| 80 | netdev_assert_locked_ops_compat(dev);
|
| 81 | }
|
| 82 |
|
| 83 | static inline void netdev_assert_locked_ops(const struct net_device *dev)
|
| 84 | {
|
| 85 | if (netdev_need_ops_lock(dev))
|
| 86 | netdev_assert_locked(dev);
|
| 87 | }
|
| 88 |
|
| 89 | static inline void netdev_lock_ops_compat(struct net_device *dev)
|
| 90 | {
|
| 91 | if (netdev_need_ops_lock(dev))
|
| 92 | netdev_lock(dev);
|
| 93 | else
|
| 94 | rtnl_lock();
|
| 95 | }
|
| 96 |
|
| 97 | static inline void netdev_unlock_ops_compat(struct net_device *dev)
|
| 98 | {
|
| 99 | if (netdev_need_ops_lock(dev))
|
| 100 | netdev_unlock(dev);
|
| 101 | else
|
| 102 | rtnl_unlock();
|
| 103 | }
|
| 104 |
|
| 105 |
|
| 106 | static inline int netdev_is_locked_ops_compat(const struct net_device *dev)
|
| 107 | {
|
| 108 | if (netdev_need_ops_lock(dev))
|
| 109 | return lockdep_is_held(&dev->lock);
|
| 110 | return lockdep_rtnl_is_held();
|
| 111 | }
|
| 112 |
|
| 113 | static inline int netdev_lock_cmp_fn(const struct lockdep_map *a,
|
| 114 | const struct lockdep_map *b)
|
| 115 | {
|
| 116 | if (a == b)
|
| 117 | return 0;
|
| 118 |
|
| 119 | |
| 120 | * the exact order doesn't matter.
|
| 121 | * Note that upper devices don't lock their ops, so nesting
|
| 122 | * mostly happens in batched device removal for now.
|
| 123 |
|
| 124 | return lockdep_rtnl_is_held() ? -1 : 1;
|
| 125 | }
|
| 126 |
|
| 127 | #define netdev_lockdep_set_classes(dev) \
|
| 128 | { \
|
| 129 | static struct lock_class_key qdisc_tx_busylock_key; \
|
| 130 | static struct lock_class_key qdisc_xmit_lock_key; \
|
| 131 | static struct lock_class_key dev_addr_list_lock_key; \
|
| 132 | static struct lock_class_key dev_instance_lock_key; \
|
| 133 | unsigned int i; \
|
| 134 | \
|
| 135 | (dev)->qdisc_tx_busylock = &qdisc_tx_busylock_key; \
|
| 136 | lockdep_set_class(&(dev)->addr_list_lock, \
|
| 137 | &dev_addr_list_lock_key); \
|
| 138 | lockdep_set_class(&(dev)->lock, \
|
| 139 | &dev_instance_lock_key); \
|
| 140 | lock_set_cmp_fn(&dev->lock, netdev_lock_cmp_fn, NULL); \
|
| 141 | for (i = 0; i < (dev)->num_tx_queues; i++) \
|
| 142 | lockdep_set_class(&(dev)->_tx[i]._xmit_lock, \
|
| 143 | &qdisc_xmit_lock_key); \
|
| 144 | }
|
| 145 |
|
| 146 | #define netdev_lock_dereference(p, dev) \
|
| 147 | rcu_dereference_protected(p, lockdep_is_held(&(dev)->lock))
|
| 148 |
|
| 149 | #define netdev_ops_lock_dereference(p, dev) \
|
| 150 | rcu_dereference_protected(p, netdev_is_locked_ops_compat(dev))
|
| 151 |
|
| 152 | int netdev_debug_event(struct notifier_block *nb, unsigned long event,
|
| 153 | void *ptr);
|
| 154 |
|
| 155 | #endif
|