Blame view

include/linux/notifier.h 7.72 KB
b24413180   Greg Kroah-Hartman   License cleanup: ...
1
  /* SPDX-License-Identifier: GPL-2.0 */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
2
3
4
5
6
7
8
9
10
11
12
13
  /*
   *	Routines to manage notifier chains for passing status changes to any
   *	interested routines. We need this instead of hard coded call lists so
   *	that modules can poke their nose into the innards. The network devices
   *	needed them so here they are for the rest of you.
   *
   *				Alan Cox <Alan.Cox@linux.org>
   */
   
  #ifndef _LINUX_NOTIFIER_H
  #define _LINUX_NOTIFIER_H
  #include <linux/errno.h>
e041c6834   Alan Stern   [PATCH] Notifier ...
14
15
  #include <linux/mutex.h>
  #include <linux/rwsem.h>
eabc06940   Alan Stern   [PATCH] Add SRCU-...
16
  #include <linux/srcu.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
17

e041c6834   Alan Stern   [PATCH] Notifier ...
18
  /*
eabc06940   Alan Stern   [PATCH] Add SRCU-...
19
   * Notifier chains are of four types:
e041c6834   Alan Stern   [PATCH] Notifier ...
20
21
22
23
24
25
26
27
   *
   *	Atomic notifier chains: Chain callbacks run in interrupt/atomic
   *		context. Callouts are not allowed to block.
   *	Blocking notifier chains: Chain callbacks run in process context.
   *		Callouts are allowed to block.
   *	Raw notifier chains: There are no restrictions on callbacks,
   *		registration, or unregistration.  All locking and protection
   *		must be provided by the caller.
eabc06940   Alan Stern   [PATCH] Add SRCU-...
28
29
   *	SRCU notifier chains: A variant of blocking notifier chains, with
   *		the same restrictions.
e041c6834   Alan Stern   [PATCH] Notifier ...
30
31
   *
   * atomic_notifier_chain_register() may be called from an atomic context,
eabc06940   Alan Stern   [PATCH] Add SRCU-...
32
33
34
   * but blocking_notifier_chain_register() and srcu_notifier_chain_register()
   * must be called from a process context.  Ditto for the corresponding
   * _unregister() routines.
e041c6834   Alan Stern   [PATCH] Notifier ...
35
   *
eabc06940   Alan Stern   [PATCH] Add SRCU-...
36
37
38
39
40
41
42
43
44
45
46
47
48
   * atomic_notifier_chain_unregister(), blocking_notifier_chain_unregister(),
   * and srcu_notifier_chain_unregister() _must not_ be called from within
   * the call chain.
   *
   * SRCU notifier chains are an alternative form of blocking notifier chains.
   * They use SRCU (Sleepable Read-Copy Update) instead of rw-semaphores for
   * protection of the chain links.  This means there is _very_ low overhead
   * in srcu_notifier_call_chain(): no cache bounces and no memory barriers.
   * As compensation, srcu_notifier_chain_unregister() is rather expensive.
   * SRCU notifier chains should be used when the chain will be called very
   * often but notifier_blocks will seldom be removed.  Also, SRCU notifier
   * chains are slightly more difficult to use because they require special
   * runtime initialization.
e041c6834   Alan Stern   [PATCH] Notifier ...
49
   */
27d50c7ee   Thomas Gleixner   rcu: Make CPU_DYI...
50
  struct notifier_block;
f02c69680   Andrew Morton   include/linux/mem...
51
52
  typedef	int (*notifier_fn_t)(struct notifier_block *nb,
  			unsigned long action, void *data);
e041c6834   Alan Stern   [PATCH] Notifier ...
53
  struct notifier_block {
f02c69680   Andrew Morton   include/linux/mem...
54
  	notifier_fn_t notifier_call;
374a8e0dc   Arnd Bergmann   notifiers: __rcu ...
55
  	struct notifier_block __rcu *next;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
56
57
  	int priority;
  };
e041c6834   Alan Stern   [PATCH] Notifier ...
58
59
  struct atomic_notifier_head {
  	spinlock_t lock;
374a8e0dc   Arnd Bergmann   notifiers: __rcu ...
60
  	struct notifier_block __rcu *head;
e041c6834   Alan Stern   [PATCH] Notifier ...
61
62
63
64
  };
  
  struct blocking_notifier_head {
  	struct rw_semaphore rwsem;
374a8e0dc   Arnd Bergmann   notifiers: __rcu ...
65
  	struct notifier_block __rcu *head;
e041c6834   Alan Stern   [PATCH] Notifier ...
66
67
68
  };
  
  struct raw_notifier_head {
374a8e0dc   Arnd Bergmann   notifiers: __rcu ...
69
  	struct notifier_block __rcu *head;
e041c6834   Alan Stern   [PATCH] Notifier ...
70
  };
eabc06940   Alan Stern   [PATCH] Add SRCU-...
71
72
73
  struct srcu_notifier_head {
  	struct mutex mutex;
  	struct srcu_struct srcu;
374a8e0dc   Arnd Bergmann   notifiers: __rcu ...
74
  	struct notifier_block __rcu *head;
eabc06940   Alan Stern   [PATCH] Add SRCU-...
75
  };
e041c6834   Alan Stern   [PATCH] Notifier ...
76
77
78
79
80
81
82
83
84
85
86
  #define ATOMIC_INIT_NOTIFIER_HEAD(name) do {	\
  		spin_lock_init(&(name)->lock);	\
  		(name)->head = NULL;		\
  	} while (0)
  #define BLOCKING_INIT_NOTIFIER_HEAD(name) do {	\
  		init_rwsem(&(name)->rwsem);	\
  		(name)->head = NULL;		\
  	} while (0)
  #define RAW_INIT_NOTIFIER_HEAD(name) do {	\
  		(name)->head = NULL;		\
  	} while (0)
eabc06940   Alan Stern   [PATCH] Add SRCU-...
87
88
89
90
  /* srcu_notifier_heads must be initialized and cleaned up dynamically */
  extern void srcu_init_notifier_head(struct srcu_notifier_head *nh);
  #define srcu_cleanup_notifier_head(name)	\
  		cleanup_srcu_struct(&(name)->srcu);
e041c6834   Alan Stern   [PATCH] Notifier ...
91
  #define ATOMIC_NOTIFIER_INIT(name) {				\
e4d919188   Ingo Molnar   [PATCH] lockdep: ...
92
  		.lock = __SPIN_LOCK_UNLOCKED(name.lock),	\
e041c6834   Alan Stern   [PATCH] Notifier ...
93
94
95
96
97
98
  		.head = NULL }
  #define BLOCKING_NOTIFIER_INIT(name) {				\
  		.rwsem = __RWSEM_INITIALIZER((name).rwsem),	\
  		.head = NULL }
  #define RAW_NOTIFIER_INIT(name)	{				\
  		.head = NULL }
eabc06940   Alan Stern   [PATCH] Add SRCU-...
99
  /* srcu_notifier_heads cannot be initialized statically */
e041c6834   Alan Stern   [PATCH] Notifier ...
100
101
102
103
104
105
106
107
108
109
  
  #define ATOMIC_NOTIFIER_HEAD(name)				\
  	struct atomic_notifier_head name =			\
  		ATOMIC_NOTIFIER_INIT(name)
  #define BLOCKING_NOTIFIER_HEAD(name)				\
  	struct blocking_notifier_head name =			\
  		BLOCKING_NOTIFIER_INIT(name)
  #define RAW_NOTIFIER_HEAD(name)					\
  	struct raw_notifier_head name =				\
  		RAW_NOTIFIER_INIT(name)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
110
111
  
  #ifdef __KERNEL__
6f7cc11aa   Gautham R Shenoy   Extend notifier_c...
112
113
114
115
116
117
118
119
  extern int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
  		struct notifier_block *nb);
  extern int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
  		struct notifier_block *nb);
  extern int raw_notifier_chain_register(struct raw_notifier_head *nh,
  		struct notifier_block *nb);
  extern int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
  		struct notifier_block *nb);
6546bc427   Nadia Derbey   ipc: re-enable ms...
120
121
122
  extern int blocking_notifier_chain_cond_register(
  		struct blocking_notifier_head *nh,
  		struct notifier_block *nb);
6f7cc11aa   Gautham R Shenoy   Extend notifier_c...
123
124
125
126
127
128
129
130
131
132
  extern int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
  		struct notifier_block *nb);
  extern int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
  		struct notifier_block *nb);
  extern int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
  		struct notifier_block *nb);
  extern int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
  		struct notifier_block *nb);
  
  extern int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
e041c6834   Alan Stern   [PATCH] Notifier ...
133
  		unsigned long val, void *v);
6f7cc11aa   Gautham R Shenoy   Extend notifier_c...
134
135
136
  extern int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
  	unsigned long val, void *v, int nr_to_call, int *nr_calls);
  extern int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
e041c6834   Alan Stern   [PATCH] Notifier ...
137
  		unsigned long val, void *v);
6f7cc11aa   Gautham R Shenoy   Extend notifier_c...
138
139
140
  extern int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
  	unsigned long val, void *v, int nr_to_call, int *nr_calls);
  extern int raw_notifier_call_chain(struct raw_notifier_head *nh,
e041c6834   Alan Stern   [PATCH] Notifier ...
141
  		unsigned long val, void *v);
6f7cc11aa   Gautham R Shenoy   Extend notifier_c...
142
143
144
  extern int __raw_notifier_call_chain(struct raw_notifier_head *nh,
  	unsigned long val, void *v, int nr_to_call, int *nr_calls);
  extern int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
eabc06940   Alan Stern   [PATCH] Add SRCU-...
145
  		unsigned long val, void *v);
6f7cc11aa   Gautham R Shenoy   Extend notifier_c...
146
147
  extern int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
  	unsigned long val, void *v, int nr_to_call, int *nr_calls);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
148
149
150
151
  
  #define NOTIFY_DONE		0x0000		/* Don't care */
  #define NOTIFY_OK		0x0001		/* Suits me */
  #define NOTIFY_STOP_MASK	0x8000		/* Don't call further */
e041c6834   Alan Stern   [PATCH] Notifier ...
152
153
  #define NOTIFY_BAD		(NOTIFY_STOP_MASK|0x0002)
  						/* Bad/Veto action */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
154
155
156
157
  /*
   * Clean way to return from the notifier and stop further calls.
   */
  #define NOTIFY_STOP		(NOTIFY_OK|NOTIFY_STOP_MASK)
fcc5a03ac   Herbert Xu   [NET]: Allow netd...
158
159
160
  /* Encapsulate (negative) errno value (in particular, NOTIFY_BAD <=> EPERM). */
  static inline int notifier_from_errno(int err)
  {
b957e043e   Akinobu Mita   notifier: change ...
161
162
163
164
  	if (err)
  		return NOTIFY_STOP_MASK | (NOTIFY_OK - err);
  
  	return NOTIFY_OK;
fcc5a03ac   Herbert Xu   [NET]: Allow netd...
165
166
167
168
169
170
171
172
  }
  
  /* Restore (negative) errno value from notify return value. */
  static inline int notifier_to_errno(int ret)
  {
  	ret &= ~NOTIFY_STOP_MASK;
  	return ret > NOTIFY_OK ? NOTIFY_OK - ret : 0;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
173
174
175
176
177
178
179
180
  /*
   *	Declared notifiers so far. I can imagine quite a few more chains
   *	over time (eg laptop power reset chains, reboot chain (to clean 
   *	device units up), device [un]mount chain, module load/unload chain,
   *	low memory chain, screenblank chain (for plug in modular screenblankers) 
   *	VC switch chains (for loadable kernel svgalib VC switch helpers) etc...
   */
   
80f1ff97d   Amerigo Wang   notifiers: cpu: m...
181
  /* CPU notfiers are defined in include/linux/cpu.h. */
dcfe1421c   Amerigo Wang   notifiers: net: m...
182
  /* netdevice notifiers are defined in include/linux/netdevice.h */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
183

c5f41752f   Amerigo Wang   notifiers: sys: m...
184
  /* reboot notifiers are defined in include/linux/reboot.h. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
185

35eb6db11   Amerigo Wang   notifiers: pm: mo...
186
  /* Hibernation and suspend events are defined in include/linux/suspend.h. */
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
187

a376d3d67   Amerigo Wang   notifiers: vt: mo...
188
  /* Virtual Terminal events are defined in include/linux/vt.h. */
35eb6db11   Amerigo Wang   notifiers: pm: mo...
189
  #define NETLINK_URELEASE	0x0001	/* Unicast netlink socket released */
b10d91174   Rafael J. Wysocki   PM: introduce hib...
190

41ab4396e   Samuel Thibault   Console keyboard ...
191
192
193
194
195
196
197
198
  /* Console keyboard events.
   * Note: KBD_KEYCODE is always sent before KBD_UNBOUND_KEYCODE, KBD_UNICODE and
   * KBD_KEYSYM. */
  #define KBD_KEYCODE		0x0001 /* Keyboard keycode, called before any other */
  #define KBD_UNBOUND_KEYCODE	0x0002 /* Keyboard keycode which is not bound to any other */
  #define KBD_UNICODE		0x0003 /* Keyboard unicode */
  #define KBD_KEYSYM		0x0004 /* Keyboard keysym */
  #define KBD_POST_KEYSYM		0x0005 /* Called after keyboard keysym interpretation */
fe9d4f576   Alexey Dobriyan   Add kernel/notifi...
199
  extern struct blocking_notifier_head reboot_notifier_list;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
200
201
  #endif /* __KERNEL__ */
  #endif /* _LINUX_NOTIFIER_H */