xref: /openbmc/linux/kernel/notifier.c (revision 5abb065dca7301de90b7c44bbcdc378e49e4d362)
1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2fe9d4f57SAlexey Dobriyan #include <linux/kdebug.h>
3fe9d4f57SAlexey Dobriyan #include <linux/kprobes.h>
49984de1aSPaul Gortmaker #include <linux/export.h>
5fe9d4f57SAlexey Dobriyan #include <linux/notifier.h>
6fe9d4f57SAlexey Dobriyan #include <linux/rcupdate.h>
7fe9d4f57SAlexey Dobriyan #include <linux/vmalloc.h>
8c166f23cSAdrian Bunk #include <linux/reboot.h>
9fe9d4f57SAlexey Dobriyan 
10fe9d4f57SAlexey Dobriyan /*
11fe9d4f57SAlexey Dobriyan  *	Notifier list for kernel code which wants to be called
12fe9d4f57SAlexey Dobriyan  *	at shutdown. This is used to stop any idling DMA operations
13fe9d4f57SAlexey Dobriyan  *	and the like.
14fe9d4f57SAlexey Dobriyan  */
15fe9d4f57SAlexey Dobriyan BLOCKING_NOTIFIER_HEAD(reboot_notifier_list);
16fe9d4f57SAlexey Dobriyan 
17fe9d4f57SAlexey Dobriyan /*
18fe9d4f57SAlexey Dobriyan  *	Notifier chain core routines.  The exported routines below
19fe9d4f57SAlexey Dobriyan  *	are layered on top of these, with appropriate locking added.
20fe9d4f57SAlexey Dobriyan  */
21fe9d4f57SAlexey Dobriyan 
22fe9d4f57SAlexey Dobriyan static int notifier_chain_register(struct notifier_block **nl,
23fe9d4f57SAlexey Dobriyan 				   struct notifier_block *n)
24fe9d4f57SAlexey Dobriyan {
25fe9d4f57SAlexey Dobriyan 	while ((*nl) != NULL) {
261a50cb80SXiaoming Ni 		if (unlikely((*nl) == n)) {
27*5abb065dSBorislav Petkov 			WARN(1, "notifier callback %ps already registered",
28*5abb065dSBorislav Petkov 			     n->notifier_call);
29*5abb065dSBorislav Petkov 			return -EEXIST;
301a50cb80SXiaoming Ni 		}
31fe9d4f57SAlexey Dobriyan 		if (n->priority > (*nl)->priority)
32fe9d4f57SAlexey Dobriyan 			break;
33fe9d4f57SAlexey Dobriyan 		nl = &((*nl)->next);
34fe9d4f57SAlexey Dobriyan 	}
35fe9d4f57SAlexey Dobriyan 	n->next = *nl;
36fe9d4f57SAlexey Dobriyan 	rcu_assign_pointer(*nl, n);
37fe9d4f57SAlexey Dobriyan 	return 0;
38fe9d4f57SAlexey Dobriyan }
39fe9d4f57SAlexey Dobriyan 
40fe9d4f57SAlexey Dobriyan static int notifier_chain_unregister(struct notifier_block **nl,
41fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
42fe9d4f57SAlexey Dobriyan {
43fe9d4f57SAlexey Dobriyan 	while ((*nl) != NULL) {
44fe9d4f57SAlexey Dobriyan 		if ((*nl) == n) {
45fe9d4f57SAlexey Dobriyan 			rcu_assign_pointer(*nl, n->next);
46fe9d4f57SAlexey Dobriyan 			return 0;
47fe9d4f57SAlexey Dobriyan 		}
48fe9d4f57SAlexey Dobriyan 		nl = &((*nl)->next);
49fe9d4f57SAlexey Dobriyan 	}
50fe9d4f57SAlexey Dobriyan 	return -ENOENT;
51fe9d4f57SAlexey Dobriyan }
52fe9d4f57SAlexey Dobriyan 
53fe9d4f57SAlexey Dobriyan /**
54fe9d4f57SAlexey Dobriyan  * notifier_call_chain - Informs the registered notifiers about an event.
55fe9d4f57SAlexey Dobriyan  *	@nl:		Pointer to head of the blocking notifier chain
56fe9d4f57SAlexey Dobriyan  *	@val:		Value passed unmodified to notifier function
57fe9d4f57SAlexey Dobriyan  *	@v:		Pointer passed unmodified to notifier function
58fe9d4f57SAlexey Dobriyan  *	@nr_to_call:	Number of notifier functions to be called. Don't care
59fe9d4f57SAlexey Dobriyan  *			value of this parameter is -1.
60fe9d4f57SAlexey Dobriyan  *	@nr_calls:	Records the number of notifications sent. Don't care
61fe9d4f57SAlexey Dobriyan  *			value of this field is NULL.
62fe9d4f57SAlexey Dobriyan  *	@returns:	notifier_call_chain returns the value returned by the
63fe9d4f57SAlexey Dobriyan  *			last notifier function called.
64fe9d4f57SAlexey Dobriyan  */
65b40a2cb6SMasami Hiramatsu static int notifier_call_chain(struct notifier_block **nl,
66fe9d4f57SAlexey Dobriyan 			       unsigned long val, void *v,
67fe9d4f57SAlexey Dobriyan 			       int nr_to_call, int *nr_calls)
68fe9d4f57SAlexey Dobriyan {
69fe9d4f57SAlexey Dobriyan 	int ret = NOTIFY_DONE;
70fe9d4f57SAlexey Dobriyan 	struct notifier_block *nb, *next_nb;
71fe9d4f57SAlexey Dobriyan 
72d11c563dSPaul E. McKenney 	nb = rcu_dereference_raw(*nl);
73fe9d4f57SAlexey Dobriyan 
74fe9d4f57SAlexey Dobriyan 	while (nb && nr_to_call) {
75d11c563dSPaul E. McKenney 		next_nb = rcu_dereference_raw(nb->next);
761b2439dbSArjan van de Ven 
771b2439dbSArjan van de Ven #ifdef CONFIG_DEBUG_NOTIFIERS
78ab7476cfSArjan van de Ven 		if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
791b2439dbSArjan van de Ven 			WARN(1, "Invalid notifier called!");
801b2439dbSArjan van de Ven 			nb = next_nb;
811b2439dbSArjan van de Ven 			continue;
821b2439dbSArjan van de Ven 		}
831b2439dbSArjan van de Ven #endif
84fe9d4f57SAlexey Dobriyan 		ret = nb->notifier_call(nb, val, v);
85fe9d4f57SAlexey Dobriyan 
86fe9d4f57SAlexey Dobriyan 		if (nr_calls)
87fe9d4f57SAlexey Dobriyan 			(*nr_calls)++;
88fe9d4f57SAlexey Dobriyan 
893e6dadedSViresh Kumar 		if (ret & NOTIFY_STOP_MASK)
90fe9d4f57SAlexey Dobriyan 			break;
91fe9d4f57SAlexey Dobriyan 		nb = next_nb;
92fe9d4f57SAlexey Dobriyan 		nr_to_call--;
93fe9d4f57SAlexey Dobriyan 	}
94fe9d4f57SAlexey Dobriyan 	return ret;
95fe9d4f57SAlexey Dobriyan }
96b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notifier_call_chain);
97fe9d4f57SAlexey Dobriyan 
9870d93298SPeter Zijlstra /**
9970d93298SPeter Zijlstra  * notifier_call_chain_robust - Inform the registered notifiers about an event
10070d93298SPeter Zijlstra  *                              and rollback on error.
10170d93298SPeter Zijlstra  * @nl:		Pointer to head of the blocking notifier chain
10270d93298SPeter Zijlstra  * @val_up:	Value passed unmodified to the notifier function
10370d93298SPeter Zijlstra  * @val_down:	Value passed unmodified to the notifier function when recovering
10470d93298SPeter Zijlstra  *              from an error on @val_up
10570d93298SPeter Zijlstra  * @v		Pointer passed unmodified to the notifier function
10670d93298SPeter Zijlstra  *
10770d93298SPeter Zijlstra  * NOTE:	It is important the @nl chain doesn't change between the two
10870d93298SPeter Zijlstra  *		invocations of notifier_call_chain() such that we visit the
10970d93298SPeter Zijlstra  *		exact same notifier callbacks; this rules out any RCU usage.
11070d93298SPeter Zijlstra  *
11170d93298SPeter Zijlstra  * Returns:	the return value of the @val_up call.
11270d93298SPeter Zijlstra  */
11370d93298SPeter Zijlstra static int notifier_call_chain_robust(struct notifier_block **nl,
11470d93298SPeter Zijlstra 				     unsigned long val_up, unsigned long val_down,
11570d93298SPeter Zijlstra 				     void *v)
11670d93298SPeter Zijlstra {
11770d93298SPeter Zijlstra 	int ret, nr = 0;
11870d93298SPeter Zijlstra 
11970d93298SPeter Zijlstra 	ret = notifier_call_chain(nl, val_up, v, -1, &nr);
12070d93298SPeter Zijlstra 	if (ret & NOTIFY_STOP_MASK)
12170d93298SPeter Zijlstra 		notifier_call_chain(nl, val_down, v, nr-1, NULL);
12270d93298SPeter Zijlstra 
12370d93298SPeter Zijlstra 	return ret;
12470d93298SPeter Zijlstra }
12570d93298SPeter Zijlstra 
126fe9d4f57SAlexey Dobriyan /*
127fe9d4f57SAlexey Dobriyan  *	Atomic notifier chain routines.  Registration and unregistration
128fe9d4f57SAlexey Dobriyan  *	use a spinlock, and call_chain is synchronized by RCU (no locks).
129fe9d4f57SAlexey Dobriyan  */
130fe9d4f57SAlexey Dobriyan 
131fe9d4f57SAlexey Dobriyan /**
132fe9d4f57SAlexey Dobriyan  *	atomic_notifier_chain_register - Add notifier to an atomic notifier chain
133fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
134fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
135fe9d4f57SAlexey Dobriyan  *
136fe9d4f57SAlexey Dobriyan  *	Adds a notifier to an atomic notifier chain.
137fe9d4f57SAlexey Dobriyan  *
138*5abb065dSBorislav Petkov  *	Returns 0 on success, %-EEXIST on error.
139fe9d4f57SAlexey Dobriyan  */
140fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
141fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
142fe9d4f57SAlexey Dobriyan {
143fe9d4f57SAlexey Dobriyan 	unsigned long flags;
144fe9d4f57SAlexey Dobriyan 	int ret;
145fe9d4f57SAlexey Dobriyan 
146fe9d4f57SAlexey Dobriyan 	spin_lock_irqsave(&nh->lock, flags);
147fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
148fe9d4f57SAlexey Dobriyan 	spin_unlock_irqrestore(&nh->lock, flags);
149fe9d4f57SAlexey Dobriyan 	return ret;
150fe9d4f57SAlexey Dobriyan }
151fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
152fe9d4f57SAlexey Dobriyan 
153fe9d4f57SAlexey Dobriyan /**
154fe9d4f57SAlexey Dobriyan  *	atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
155fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
156fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
157fe9d4f57SAlexey Dobriyan  *
158fe9d4f57SAlexey Dobriyan  *	Removes a notifier from an atomic notifier chain.
159fe9d4f57SAlexey Dobriyan  *
160fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
161fe9d4f57SAlexey Dobriyan  */
162fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
163fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
164fe9d4f57SAlexey Dobriyan {
165fe9d4f57SAlexey Dobriyan 	unsigned long flags;
166fe9d4f57SAlexey Dobriyan 	int ret;
167fe9d4f57SAlexey Dobriyan 
168fe9d4f57SAlexey Dobriyan 	spin_lock_irqsave(&nh->lock, flags);
169fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
170fe9d4f57SAlexey Dobriyan 	spin_unlock_irqrestore(&nh->lock, flags);
171fe9d4f57SAlexey Dobriyan 	synchronize_rcu();
172fe9d4f57SAlexey Dobriyan 	return ret;
173fe9d4f57SAlexey Dobriyan }
174fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
175fe9d4f57SAlexey Dobriyan 
176fe9d4f57SAlexey Dobriyan /**
17770d93298SPeter Zijlstra  *	atomic_notifier_call_chain - Call functions in an atomic notifier chain
178fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
179fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
180fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
181fe9d4f57SAlexey Dobriyan  *
182fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
183fe9d4f57SAlexey Dobriyan  *	run in an atomic context, so they must not block.
184fe9d4f57SAlexey Dobriyan  *	This routine uses RCU to synchronize with changes to the chain.
185fe9d4f57SAlexey Dobriyan  *
186fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
187fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
188fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
189fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
190fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
191fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
192fe9d4f57SAlexey Dobriyan  */
19370d93298SPeter Zijlstra int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
19470d93298SPeter Zijlstra 			       unsigned long val, void *v)
195fe9d4f57SAlexey Dobriyan {
196fe9d4f57SAlexey Dobriyan 	int ret;
197fe9d4f57SAlexey Dobriyan 
198fe9d4f57SAlexey Dobriyan 	rcu_read_lock();
19970d93298SPeter Zijlstra 	ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
200fe9d4f57SAlexey Dobriyan 	rcu_read_unlock();
201fe9d4f57SAlexey Dobriyan 
20270d93298SPeter Zijlstra 	return ret;
203fe9d4f57SAlexey Dobriyan }
204fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
205b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(atomic_notifier_call_chain);
206fe9d4f57SAlexey Dobriyan 
207fe9d4f57SAlexey Dobriyan /*
208fe9d4f57SAlexey Dobriyan  *	Blocking notifier chain routines.  All access to the chain is
209fe9d4f57SAlexey Dobriyan  *	synchronized by an rwsem.
210fe9d4f57SAlexey Dobriyan  */
211fe9d4f57SAlexey Dobriyan 
212fe9d4f57SAlexey Dobriyan /**
213fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_register - Add notifier to a blocking notifier chain
214fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
215fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
216fe9d4f57SAlexey Dobriyan  *
217fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a blocking notifier chain.
218fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
219fe9d4f57SAlexey Dobriyan  *
220*5abb065dSBorislav Petkov  *	Returns 0 on success, %-EEXIST on error.
221fe9d4f57SAlexey Dobriyan  */
222fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
223fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
224fe9d4f57SAlexey Dobriyan {
225fe9d4f57SAlexey Dobriyan 	int ret;
226fe9d4f57SAlexey Dobriyan 
227fe9d4f57SAlexey Dobriyan 	/*
228fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
229fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
230fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
231fe9d4f57SAlexey Dobriyan 	 */
232fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
233fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
234fe9d4f57SAlexey Dobriyan 
235fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
236fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
237fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
238fe9d4f57SAlexey Dobriyan 	return ret;
239fe9d4f57SAlexey Dobriyan }
240fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
241fe9d4f57SAlexey Dobriyan 
242fe9d4f57SAlexey Dobriyan /**
243fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
244fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
245fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
246fe9d4f57SAlexey Dobriyan  *
247fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a blocking notifier chain.
248fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
249fe9d4f57SAlexey Dobriyan  *
250fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
251fe9d4f57SAlexey Dobriyan  */
252fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
253fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
254fe9d4f57SAlexey Dobriyan {
255fe9d4f57SAlexey Dobriyan 	int ret;
256fe9d4f57SAlexey Dobriyan 
257fe9d4f57SAlexey Dobriyan 	/*
258fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
259fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
260fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
261fe9d4f57SAlexey Dobriyan 	 */
262fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
263fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
264fe9d4f57SAlexey Dobriyan 
265fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
266fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
267fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
268fe9d4f57SAlexey Dobriyan 	return ret;
269fe9d4f57SAlexey Dobriyan }
270fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
271fe9d4f57SAlexey Dobriyan 
27270d93298SPeter Zijlstra int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh,
27370d93298SPeter Zijlstra 		unsigned long val_up, unsigned long val_down, void *v)
27470d93298SPeter Zijlstra {
27570d93298SPeter Zijlstra 	int ret = NOTIFY_DONE;
27670d93298SPeter Zijlstra 
27770d93298SPeter Zijlstra 	/*
27870d93298SPeter Zijlstra 	 * We check the head outside the lock, but if this access is
27970d93298SPeter Zijlstra 	 * racy then it does not matter what the result of the test
28070d93298SPeter Zijlstra 	 * is, we re-check the list after having taken the lock anyway:
28170d93298SPeter Zijlstra 	 */
28270d93298SPeter Zijlstra 	if (rcu_access_pointer(nh->head)) {
28370d93298SPeter Zijlstra 		down_read(&nh->rwsem);
28470d93298SPeter Zijlstra 		ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v);
28570d93298SPeter Zijlstra 		up_read(&nh->rwsem);
28670d93298SPeter Zijlstra 	}
28770d93298SPeter Zijlstra 	return ret;
28870d93298SPeter Zijlstra }
28970d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust);
29070d93298SPeter Zijlstra 
291fe9d4f57SAlexey Dobriyan /**
29270d93298SPeter Zijlstra  *	blocking_notifier_call_chain - Call functions in a blocking notifier chain
293fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
294fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
295fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
296fe9d4f57SAlexey Dobriyan  *
297fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
298fe9d4f57SAlexey Dobriyan  *	run in a process context, so they are allowed to block.
299fe9d4f57SAlexey Dobriyan  *
300fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
301fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
302fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
303fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
304fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
305fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
306fe9d4f57SAlexey Dobriyan  */
30770d93298SPeter Zijlstra int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
30870d93298SPeter Zijlstra 		unsigned long val, void *v)
309fe9d4f57SAlexey Dobriyan {
310fe9d4f57SAlexey Dobriyan 	int ret = NOTIFY_DONE;
311fe9d4f57SAlexey Dobriyan 
312fe9d4f57SAlexey Dobriyan 	/*
313fe9d4f57SAlexey Dobriyan 	 * We check the head outside the lock, but if this access is
314fe9d4f57SAlexey Dobriyan 	 * racy then it does not matter what the result of the test
315fe9d4f57SAlexey Dobriyan 	 * is, we re-check the list after having taken the lock anyway:
316fe9d4f57SAlexey Dobriyan 	 */
3178857563bSPaul E. McKenney 	if (rcu_access_pointer(nh->head)) {
318fe9d4f57SAlexey Dobriyan 		down_read(&nh->rwsem);
31970d93298SPeter Zijlstra 		ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
320fe9d4f57SAlexey Dobriyan 		up_read(&nh->rwsem);
321fe9d4f57SAlexey Dobriyan 	}
322fe9d4f57SAlexey Dobriyan 	return ret;
323fe9d4f57SAlexey Dobriyan }
324fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
325fe9d4f57SAlexey Dobriyan 
326fe9d4f57SAlexey Dobriyan /*
327fe9d4f57SAlexey Dobriyan  *	Raw notifier chain routines.  There is no protection;
328fe9d4f57SAlexey Dobriyan  *	the caller must provide it.  Use at your own risk!
329fe9d4f57SAlexey Dobriyan  */
330fe9d4f57SAlexey Dobriyan 
331fe9d4f57SAlexey Dobriyan /**
332fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_register - Add notifier to a raw notifier chain
333fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
334fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
335fe9d4f57SAlexey Dobriyan  *
336fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a raw notifier chain.
337fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
338fe9d4f57SAlexey Dobriyan  *
339*5abb065dSBorislav Petkov  *	Returns 0 on success, %-EEXIST on error.
340fe9d4f57SAlexey Dobriyan  */
341fe9d4f57SAlexey Dobriyan int raw_notifier_chain_register(struct raw_notifier_head *nh,
342fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
343fe9d4f57SAlexey Dobriyan {
344fe9d4f57SAlexey Dobriyan 	return notifier_chain_register(&nh->head, n);
345fe9d4f57SAlexey Dobriyan }
346fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
347fe9d4f57SAlexey Dobriyan 
348fe9d4f57SAlexey Dobriyan /**
349fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
350fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
351fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
352fe9d4f57SAlexey Dobriyan  *
353fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a raw notifier chain.
354fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
355fe9d4f57SAlexey Dobriyan  *
356fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
357fe9d4f57SAlexey Dobriyan  */
358fe9d4f57SAlexey Dobriyan int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
359fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
360fe9d4f57SAlexey Dobriyan {
361fe9d4f57SAlexey Dobriyan 	return notifier_chain_unregister(&nh->head, n);
362fe9d4f57SAlexey Dobriyan }
363fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
364fe9d4f57SAlexey Dobriyan 
36570d93298SPeter Zijlstra int raw_notifier_call_chain_robust(struct raw_notifier_head *nh,
36670d93298SPeter Zijlstra 		unsigned long val_up, unsigned long val_down, void *v)
36770d93298SPeter Zijlstra {
36870d93298SPeter Zijlstra 	return notifier_call_chain_robust(&nh->head, val_up, val_down, v);
36970d93298SPeter Zijlstra }
37070d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust);
37170d93298SPeter Zijlstra 
372fe9d4f57SAlexey Dobriyan /**
37370d93298SPeter Zijlstra  *	raw_notifier_call_chain - Call functions in a raw notifier chain
374fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
375fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
376fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
377fe9d4f57SAlexey Dobriyan  *
378fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
379fe9d4f57SAlexey Dobriyan  *	run in an undefined context.
380fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
381fe9d4f57SAlexey Dobriyan  *
382fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
383fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
384fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
385fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
386fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
387fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
388fe9d4f57SAlexey Dobriyan  */
389fe9d4f57SAlexey Dobriyan int raw_notifier_call_chain(struct raw_notifier_head *nh,
390fe9d4f57SAlexey Dobriyan 		unsigned long val, void *v)
391fe9d4f57SAlexey Dobriyan {
39270d93298SPeter Zijlstra 	return notifier_call_chain(&nh->head, val, v, -1, NULL);
393fe9d4f57SAlexey Dobriyan }
394fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
395fe9d4f57SAlexey Dobriyan 
39683fe27eaSPranith Kumar #ifdef CONFIG_SRCU
397fe9d4f57SAlexey Dobriyan /*
398fe9d4f57SAlexey Dobriyan  *	SRCU notifier chain routines.    Registration and unregistration
399fe9d4f57SAlexey Dobriyan  *	use a mutex, and call_chain is synchronized by SRCU (no locks).
400fe9d4f57SAlexey Dobriyan  */
401fe9d4f57SAlexey Dobriyan 
402fe9d4f57SAlexey Dobriyan /**
403fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
404fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
405fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
406fe9d4f57SAlexey Dobriyan  *
407fe9d4f57SAlexey Dobriyan  *	Adds a notifier to an SRCU notifier chain.
408fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
409fe9d4f57SAlexey Dobriyan  *
410*5abb065dSBorislav Petkov  *	Returns 0 on success, %-EEXIST on error.
411fe9d4f57SAlexey Dobriyan  */
412fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
413fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
414fe9d4f57SAlexey Dobriyan {
415fe9d4f57SAlexey Dobriyan 	int ret;
416fe9d4f57SAlexey Dobriyan 
417fe9d4f57SAlexey Dobriyan 	/*
418fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
419fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
420fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
421fe9d4f57SAlexey Dobriyan 	 */
422fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
423fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
424fe9d4f57SAlexey Dobriyan 
425fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
426fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
427fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
428fe9d4f57SAlexey Dobriyan 	return ret;
429fe9d4f57SAlexey Dobriyan }
430fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
431fe9d4f57SAlexey Dobriyan 
432fe9d4f57SAlexey Dobriyan /**
433fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
434fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
435fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
436fe9d4f57SAlexey Dobriyan  *
437fe9d4f57SAlexey Dobriyan  *	Removes a notifier from an SRCU notifier chain.
438fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
439fe9d4f57SAlexey Dobriyan  *
440fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
441fe9d4f57SAlexey Dobriyan  */
442fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
443fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
444fe9d4f57SAlexey Dobriyan {
445fe9d4f57SAlexey Dobriyan 	int ret;
446fe9d4f57SAlexey Dobriyan 
447fe9d4f57SAlexey Dobriyan 	/*
448fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
449fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
450fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
451fe9d4f57SAlexey Dobriyan 	 */
452fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
453fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
454fe9d4f57SAlexey Dobriyan 
455fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
456fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
457fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
458fe9d4f57SAlexey Dobriyan 	synchronize_srcu(&nh->srcu);
459fe9d4f57SAlexey Dobriyan 	return ret;
460fe9d4f57SAlexey Dobriyan }
461fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
462fe9d4f57SAlexey Dobriyan 
463fe9d4f57SAlexey Dobriyan /**
46470d93298SPeter Zijlstra  *	srcu_notifier_call_chain - Call functions in an SRCU notifier chain
465fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
466fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
467fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
468fe9d4f57SAlexey Dobriyan  *
469fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
470fe9d4f57SAlexey Dobriyan  *	run in a process context, so they are allowed to block.
471fe9d4f57SAlexey Dobriyan  *
472fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
473fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
474fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
475fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
476fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
477fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
478fe9d4f57SAlexey Dobriyan  */
47970d93298SPeter Zijlstra int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
48070d93298SPeter Zijlstra 		unsigned long val, void *v)
481fe9d4f57SAlexey Dobriyan {
482fe9d4f57SAlexey Dobriyan 	int ret;
483fe9d4f57SAlexey Dobriyan 	int idx;
484fe9d4f57SAlexey Dobriyan 
485fe9d4f57SAlexey Dobriyan 	idx = srcu_read_lock(&nh->srcu);
48670d93298SPeter Zijlstra 	ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
487fe9d4f57SAlexey Dobriyan 	srcu_read_unlock(&nh->srcu, idx);
488fe9d4f57SAlexey Dobriyan 	return ret;
489fe9d4f57SAlexey Dobriyan }
490fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
491fe9d4f57SAlexey Dobriyan 
492fe9d4f57SAlexey Dobriyan /**
493fe9d4f57SAlexey Dobriyan  *	srcu_init_notifier_head - Initialize an SRCU notifier head
494fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the srcu notifier chain
495fe9d4f57SAlexey Dobriyan  *
496fe9d4f57SAlexey Dobriyan  *	Unlike other sorts of notifier heads, SRCU notifier heads require
497fe9d4f57SAlexey Dobriyan  *	dynamic initialization.  Be sure to call this routine before
498fe9d4f57SAlexey Dobriyan  *	calling any of the other SRCU notifier routines for this head.
499fe9d4f57SAlexey Dobriyan  *
500fe9d4f57SAlexey Dobriyan  *	If an SRCU notifier head is deallocated, it must first be cleaned
501fe9d4f57SAlexey Dobriyan  *	up by calling srcu_cleanup_notifier_head().  Otherwise the head's
502fe9d4f57SAlexey Dobriyan  *	per-cpu data (used by the SRCU mechanism) will leak.
503fe9d4f57SAlexey Dobriyan  */
504fe9d4f57SAlexey Dobriyan void srcu_init_notifier_head(struct srcu_notifier_head *nh)
505fe9d4f57SAlexey Dobriyan {
506fe9d4f57SAlexey Dobriyan 	mutex_init(&nh->mutex);
507fe9d4f57SAlexey Dobriyan 	if (init_srcu_struct(&nh->srcu) < 0)
508fe9d4f57SAlexey Dobriyan 		BUG();
509fe9d4f57SAlexey Dobriyan 	nh->head = NULL;
510fe9d4f57SAlexey Dobriyan }
511fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
512fe9d4f57SAlexey Dobriyan 
51383fe27eaSPranith Kumar #endif /* CONFIG_SRCU */
51483fe27eaSPranith Kumar 
515fe9d4f57SAlexey Dobriyan static ATOMIC_NOTIFIER_HEAD(die_chain);
516fe9d4f57SAlexey Dobriyan 
517b40a2cb6SMasami Hiramatsu int notrace notify_die(enum die_val val, const char *str,
518fe9d4f57SAlexey Dobriyan 	       struct pt_regs *regs, long err, int trap, int sig)
519fe9d4f57SAlexey Dobriyan {
520fe9d4f57SAlexey Dobriyan 	struct die_args args = {
521fe9d4f57SAlexey Dobriyan 		.regs	= regs,
522fe9d4f57SAlexey Dobriyan 		.str	= str,
523fe9d4f57SAlexey Dobriyan 		.err	= err,
524fe9d4f57SAlexey Dobriyan 		.trapnr	= trap,
525fe9d4f57SAlexey Dobriyan 		.signr	= sig,
526fe9d4f57SAlexey Dobriyan 
527fe9d4f57SAlexey Dobriyan 	};
5285778077dSLinus Torvalds 	RCU_LOCKDEP_WARN(!rcu_is_watching(),
529e727c7d7SAndy Lutomirski 			   "notify_die called but RCU thinks we're quiescent");
530fe9d4f57SAlexey Dobriyan 	return atomic_notifier_call_chain(&die_chain, val, &args);
531fe9d4f57SAlexey Dobriyan }
532b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notify_die);
533fe9d4f57SAlexey Dobriyan 
534fe9d4f57SAlexey Dobriyan int register_die_notifier(struct notifier_block *nb)
535fe9d4f57SAlexey Dobriyan {
536fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_register(&die_chain, nb);
537fe9d4f57SAlexey Dobriyan }
538fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(register_die_notifier);
539fe9d4f57SAlexey Dobriyan 
540fe9d4f57SAlexey Dobriyan int unregister_die_notifier(struct notifier_block *nb)
541fe9d4f57SAlexey Dobriyan {
542fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_unregister(&die_chain, nb);
543fe9d4f57SAlexey Dobriyan }
544fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(unregister_die_notifier);
545