projects/linux·blob uaccess-cleanups · refs

155 lines · 3.8 KiB

1/* SPDX-License-Identifier: GPL-2.0-or-later */
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
10static inline bool netdev_trylock(struct net_device *dev)
11{
12 return mutex_trylock(&dev->lock);
13}
14
15static inline void netdev_assert_locked(const struct net_device *dev)
16{
17 lockdep_assert_held(&dev->lock);
18}
19
20static inline void
21netdev_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
28static 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
39static inline void netdev_lock_ops(struct net_device *dev)
40{
41 if (netdev_need_ops_lock(dev))
42 netdev_lock(dev);
43}
44
45static inline void netdev_unlock_ops(struct net_device *dev)
46{
47 if (netdev_need_ops_lock(dev))
48 netdev_unlock(dev);
49}
50
51static 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
59static 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
67static 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
75static inline void
76netdev_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
83static 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
89static 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
97static 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/* Matching "ops protected" category from netdevice.h */
106static 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
113static 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 /* Allow locking multiple devices only under rtnl_lock,
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
152int netdev_debug_event(struct notifier_block *nb, unsigned long event,
153 void *ptr);
154
155#endif