Branch data Line data Source code
1 : : /* SPDX-License-Identifier: GPL-2.0 */
2 : : /*
3 : : * Routines to manage notifier chains for passing status changes to any
4 : : * interested routines. We need this instead of hard coded call lists so
5 : : * that modules can poke their nose into the innards. The network devices
6 : : * needed them so here they are for the rest of you.
7 : : *
8 : : * Alan Cox <Alan.Cox@linux.org>
9 : : */
10 : :
11 : : #ifndef _LINUX_NOTIFIER_H
12 : : #define _LINUX_NOTIFIER_H
13 : : #include <linux/errno.h>
14 : : #include <linux/mutex.h>
15 : : #include <linux/rwsem.h>
16 : : #include <linux/srcu.h>
17 : :
18 : : /*
19 : : * Notifier chains are of four types:
20 : : *
21 : : * Atomic notifier chains: Chain callbacks run in interrupt/atomic
22 : : * context. Callouts are not allowed to block.
23 : : * Blocking notifier chains: Chain callbacks run in process context.
24 : : * Callouts are allowed to block.
25 : : * Raw notifier chains: There are no restrictions on callbacks,
26 : : * registration, or unregistration. All locking and protection
27 : : * must be provided by the caller.
28 : : * SRCU notifier chains: A variant of blocking notifier chains, with
29 : : * the same restrictions.
30 : : *
31 : : * atomic_notifier_chain_register() may be called from an atomic context,
32 : : * but blocking_notifier_chain_register() and srcu_notifier_chain_register()
33 : : * must be called from a process context. Ditto for the corresponding
34 : : * _unregister() routines.
35 : : *
36 : : * atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),
37 : : * and srcu_notifier_chain_unregister() _must not_ be called from within
38 : : * the call chain.
39 : : *
40 : : * SRCU notifier chains are an alternative form of blocking notifier chains.
41 : : * They use SRCU (Sleepable Read-Copy Update) instead of rw-semaphores for
42 : : * protection of the chain links. This means there is _very_ low overhead
43 : : * in srcu_notifier_call_chain(): no cache bounces and no memory barriers.
44 : : * As compensation, srcu_notifier_chain_unregister() is rather expensive.
45 : : * SRCU notifier chains should be used when the chain will be called very
46 : : * often but notifier_blocks will seldom be removed.
47 : : */
48 : :
49 : : struct notifier_block;
50 : :
51 : : typedef int (*notifier_fn_t)(struct notifier_block *nb,
52 : : unsigned long action, void *data);
53 : :
54 : : struct notifier_block {
55 : : notifier_fn_t notifier_call;
56 : : struct notifier_block __rcu *next;
57 : : int priority;
58 : : };
59 : :
60 : : struct atomic_notifier_head {
61 : : spinlock_t lock;
62 : : struct notifier_block __rcu *head;
63 : : };
64 : :
65 : : struct blocking_notifier_head {
66 : : struct rw_semaphore rwsem;
67 : : struct notifier_block __rcu *head;
68 : : };
69 : :
70 : : struct raw_notifier_head {
71 : : struct notifier_block __rcu *head;
72 : : };
73 : :
74 : : struct srcu_notifier_head {
75 : : struct mutex mutex;
76 : : struct srcu_struct srcu;
77 : : struct notifier_block __rcu *head;
78 : : };
79 : :
80 : : #define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \
81 : : spin_lock_init(&(name)->lock); \
82 : : (name)->head = NULL; \
83 : : } while (0)
84 : : #define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \
85 : : init_rwsem(&(name)->rwsem); \
86 : : (name)->head = NULL; \
87 : : } while (0)
88 : : #define RAW_INIT_NOTIFIER_HEAD(name) do { \
89 : : (name)->head = NULL; \
90 : : } while (0)
91 : :
92 : : /* srcu_notifier_heads must be cleaned up dynamically */
93 : : extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
94 : : #define srcu_cleanup_notifier_head(name) \
95 : : cleanup_srcu_struct(&(name)->srcu);
96 : :
97 : : #define ATOMIC_NOTIFIER_INIT(name) { \
98 : : .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
99 : : .head = NULL }
100 : : #define BLOCKING_NOTIFIER_INIT(name) { \
101 : : .rwsem = __RWSEM_INITIALIZER((name).rwsem), \
102 : : .head = NULL }
103 : : #define RAW_NOTIFIER_INIT(name) { \
104 : : .head = NULL }
105 : :
106 : : #define SRCU_NOTIFIER_INIT(name, pcpu) \
107 : : { \
108 : : .mutex = __MUTEX_INITIALIZER(name.mutex), \
109 : : .head = NULL, \
110 : : .srcu = __SRCU_STRUCT_INIT(name.srcu, pcpu), \
111 : : }
112 : :
113 : : #define ATOMIC_NOTIFIER_HEAD(name) \
114 : : struct atomic_notifier_head name = \
115 : : ATOMIC_NOTIFIER_INIT(name)
116 : : #define BLOCKING_NOTIFIER_HEAD(name) \
117 : : struct blocking_notifier_head name = \
118 : : BLOCKING_NOTIFIER_INIT(name)
119 : : #define RAW_NOTIFIER_HEAD(name) \
120 : : struct raw_notifier_head name = \
121 : : RAW_NOTIFIER_INIT(name)
122 : :
123 : : #ifdef CONFIG_TREE_SRCU
124 : : #define _SRCU_NOTIFIER_HEAD(name, mod) \
125 : : static DEFINE_PER_CPU(struct srcu_data, name##_head_srcu_data); \
126 : : mod struct srcu_notifier_head name = \
127 : : SRCU_NOTIFIER_INIT(name, name##_head_srcu_data)
128 : :
129 : : #else
130 : : #define _SRCU_NOTIFIER_HEAD(name, mod) \
131 : : mod struct srcu_notifier_head name = \
132 : : SRCU_NOTIFIER_INIT(name, name)
133 : :
134 : : #endif
135 : :
136 : : #define SRCU_NOTIFIER_HEAD(name) \
137 : : _SRCU_NOTIFIER_HEAD(name, /* not static */)
138 : :
139 : : #define SRCU_NOTIFIER_HEAD_STATIC(name) \
140 : : _SRCU_NOTIFIER_HEAD(name, static)
141 : :
142 : : #ifdef __KERNEL__
143 : :
144 : : extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
145 : : struct notifier_block *nb);
146 : : extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
147 : : struct notifier_block *nb);
148 : : extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
149 : : struct notifier_block *nb);
150 : : extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
151 : : struct notifier_block *nb);
152 : :
153 : : extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
154 : : struct notifier_block *nb);
155 : : extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
156 : : struct notifier_block *nb);
157 : : extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
158 : : struct notifier_block *nb);
159 : : extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
160 : : struct notifier_block *nb);
161 : :
162 : : extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
163 : : unsigned long val, void *v);
164 : : extern int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
165 : : unsigned long val, void *v, int nr_to_call, int *nr_calls);
166 : : extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
167 : : unsigned long val, void *v);
168 : : extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
169 : : unsigned long val, void *v, int nr_to_call, int *nr_calls);
170 : : extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
171 : : unsigned long val, void *v);
172 : : extern int __raw_notifier_call_chain(struct raw_notifier_head *nh,
173 : : unsigned long val, void *v, int nr_to_call, int *nr_calls);
174 : : extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
175 : : unsigned long val, void *v);
176 : : extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
177 : : unsigned long val, void *v, int nr_to_call, int *nr_calls);
178 : :
179 : : #define NOTIFY_DONE 0x0000 /* Don't care */
180 : : #define NOTIFY_OK 0x0001 /* Suits me */
181 : : #define NOTIFY_STOP_MASK 0x8000 /* Don't call further */
182 : : #define NOTIFY_BAD (NOTIFY_STOP_MASK|0x0002)
183 : : /* Bad/Veto action */
184 : : /*
185 : : * Clean way to return from the notifier and stop further calls.
186 : : */
187 : : #define NOTIFY_STOP (NOTIFY_OK|NOTIFY_STOP_MASK)
188 : :
189 : : /* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
190 : 168 : static inline int notifier_from_errno(int err)
191 : : {
192 [ - + ]: 168 : if (err)
193 : 0 : return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
194 : :
195 : : return NOTIFY_OK;
196 : : }
197 : :
198 : : /* Restore (negative) errno value from notify return value. */
199 : 980 : static inline int notifier_to_errno(int ret)
200 : : {
201 : 980 : ret &= ~NOTIFY_STOP_MASK;
202 [ - + - + : 980 : return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
- - - - -
- - - - -
- - - - -
- - + - +
- - - - -
- - - ]
203 : : }
204 : :
205 : : /*
206 : : * Declared notifiers so far. I can imagine quite a few more chains
207 : : * over time (eg laptop power reset chains, reboot chain (to clean
208 : : * device units up), device [un]mount chain, module load/unload chain,
209 : : * low memory chain, screenblank chain (for plug in modular screenblankers)
210 : : * VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
211 : : */
212 : :
213 : : /* CPU notfiers are defined in include/linux/cpu.h. */
214 : :
215 : : /* netdevice notifiers are defined in include/linux/netdevice.h */
216 : :
217 : : /* reboot notifiers are defined in include/linux/reboot.h. */
218 : :
219 : : /* Hibernation and suspend events are defined in include/linux/suspend.h. */
220 : :
221 : : /* Virtual Terminal events are defined in include/linux/vt.h. */
222 : :
223 : : #define NETLINK_URELEASE 0x0001 /* Unicast netlink socket released */
224 : :
225 : : /* Console keyboard events.
226 : : * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
227 : : * KBD_KEYSYM. */
228 : : #define KBD_KEYCODE 0x0001 /* Keyboard keycode, called before any other */
229 : : #define KBD_UNBOUND_KEYCODE 0x0002 /* Keyboard keycode which is not bound to any other */
230 : : #define KBD_UNICODE 0x0003 /* Keyboard unicode */
231 : : #define KBD_KEYSYM 0x0004 /* Keyboard keysym */
232 : : #define KBD_POST_KEYSYM 0x0005 /* Called after keyboard keysym interpretation */
233 : :
234 : : extern struct blocking_notifier_head reboot_notifier_list;
235 : :
236 : : #endif /* __KERNEL__ */
237 : : #endif /* _LINUX_NOTIFIER_H */
|