xref: /openbmc/linux/kernel/notifier.c (revision 13dfd97a341a5cf9d15f415dd469f45e971ef12a)
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)) {
275abb065dSBorislav Petkov 			WARN(1, "notifier callback %ps already registered",
285abb065dSBorislav Petkov 			     n->notifier_call);
295abb065dSBorislav 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  *
1385abb065dSBorislav 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 
207*13dfd97aSDmitry Osipenko /**
208*13dfd97aSDmitry Osipenko  *	atomic_notifier_call_chain_is_empty - Check whether notifier chain is empty
209*13dfd97aSDmitry Osipenko  *	@nh: Pointer to head of the atomic notifier chain
210*13dfd97aSDmitry Osipenko  *
211*13dfd97aSDmitry Osipenko  *	Checks whether notifier chain is empty.
212*13dfd97aSDmitry Osipenko  *
213*13dfd97aSDmitry Osipenko  *	Returns true is notifier chain is empty, false otherwise.
214*13dfd97aSDmitry Osipenko  */
215*13dfd97aSDmitry Osipenko bool atomic_notifier_call_chain_is_empty(struct atomic_notifier_head *nh)
216*13dfd97aSDmitry Osipenko {
217*13dfd97aSDmitry Osipenko 	return !rcu_access_pointer(nh->head);
218*13dfd97aSDmitry Osipenko }
219*13dfd97aSDmitry Osipenko 
220fe9d4f57SAlexey Dobriyan /*
221fe9d4f57SAlexey Dobriyan  *	Blocking notifier chain routines.  All access to the chain is
222fe9d4f57SAlexey Dobriyan  *	synchronized by an rwsem.
223fe9d4f57SAlexey Dobriyan  */
224fe9d4f57SAlexey Dobriyan 
225fe9d4f57SAlexey Dobriyan /**
226fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_register - Add notifier to a blocking notifier chain
227fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
228fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
229fe9d4f57SAlexey Dobriyan  *
230fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a blocking notifier chain.
231fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
232fe9d4f57SAlexey Dobriyan  *
2335abb065dSBorislav Petkov  *	Returns 0 on success, %-EEXIST on error.
234fe9d4f57SAlexey Dobriyan  */
235fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
236fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
237fe9d4f57SAlexey Dobriyan {
238fe9d4f57SAlexey Dobriyan 	int ret;
239fe9d4f57SAlexey Dobriyan 
240fe9d4f57SAlexey Dobriyan 	/*
241fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
242fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
243fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
244fe9d4f57SAlexey Dobriyan 	 */
245fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
246fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
247fe9d4f57SAlexey Dobriyan 
248fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
249fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
250fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
251fe9d4f57SAlexey Dobriyan 	return ret;
252fe9d4f57SAlexey Dobriyan }
253fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
254fe9d4f57SAlexey Dobriyan 
255fe9d4f57SAlexey Dobriyan /**
256fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
257fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
258fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
259fe9d4f57SAlexey Dobriyan  *
260fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a blocking notifier chain.
261fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
262fe9d4f57SAlexey Dobriyan  *
263fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
264fe9d4f57SAlexey Dobriyan  */
265fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
266fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
267fe9d4f57SAlexey Dobriyan {
268fe9d4f57SAlexey Dobriyan 	int ret;
269fe9d4f57SAlexey Dobriyan 
270fe9d4f57SAlexey Dobriyan 	/*
271fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
272fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
273fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
274fe9d4f57SAlexey Dobriyan 	 */
275fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
276fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
277fe9d4f57SAlexey Dobriyan 
278fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
279fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
280fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
281fe9d4f57SAlexey Dobriyan 	return ret;
282fe9d4f57SAlexey Dobriyan }
283fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
284fe9d4f57SAlexey Dobriyan 
28570d93298SPeter Zijlstra int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh,
28670d93298SPeter Zijlstra 		unsigned long val_up, unsigned long val_down, void *v)
28770d93298SPeter Zijlstra {
28870d93298SPeter Zijlstra 	int ret = NOTIFY_DONE;
28970d93298SPeter Zijlstra 
29070d93298SPeter Zijlstra 	/*
29170d93298SPeter Zijlstra 	 * We check the head outside the lock, but if this access is
29270d93298SPeter Zijlstra 	 * racy then it does not matter what the result of the test
29370d93298SPeter Zijlstra 	 * is, we re-check the list after having taken the lock anyway:
29470d93298SPeter Zijlstra 	 */
29570d93298SPeter Zijlstra 	if (rcu_access_pointer(nh->head)) {
29670d93298SPeter Zijlstra 		down_read(&nh->rwsem);
29770d93298SPeter Zijlstra 		ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v);
29870d93298SPeter Zijlstra 		up_read(&nh->rwsem);
29970d93298SPeter Zijlstra 	}
30070d93298SPeter Zijlstra 	return ret;
30170d93298SPeter Zijlstra }
30270d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust);
30370d93298SPeter Zijlstra 
304fe9d4f57SAlexey Dobriyan /**
30570d93298SPeter Zijlstra  *	blocking_notifier_call_chain - Call functions in a blocking notifier chain
306fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
307fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
308fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
309fe9d4f57SAlexey Dobriyan  *
310fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
311fe9d4f57SAlexey Dobriyan  *	run in a process context, so they are allowed to block.
312fe9d4f57SAlexey Dobriyan  *
313fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
314fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
315fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
316fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
317fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
318fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
319fe9d4f57SAlexey Dobriyan  */
32070d93298SPeter Zijlstra int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
32170d93298SPeter Zijlstra 		unsigned long val, void *v)
322fe9d4f57SAlexey Dobriyan {
323fe9d4f57SAlexey Dobriyan 	int ret = NOTIFY_DONE;
324fe9d4f57SAlexey Dobriyan 
325fe9d4f57SAlexey Dobriyan 	/*
326fe9d4f57SAlexey Dobriyan 	 * We check the head outside the lock, but if this access is
327fe9d4f57SAlexey Dobriyan 	 * racy then it does not matter what the result of the test
328fe9d4f57SAlexey Dobriyan 	 * is, we re-check the list after having taken the lock anyway:
329fe9d4f57SAlexey Dobriyan 	 */
3308857563bSPaul E. McKenney 	if (rcu_access_pointer(nh->head)) {
331fe9d4f57SAlexey Dobriyan 		down_read(&nh->rwsem);
33270d93298SPeter Zijlstra 		ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
333fe9d4f57SAlexey Dobriyan 		up_read(&nh->rwsem);
334fe9d4f57SAlexey Dobriyan 	}
335fe9d4f57SAlexey Dobriyan 	return ret;
336fe9d4f57SAlexey Dobriyan }
337fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
338fe9d4f57SAlexey Dobriyan 
339fe9d4f57SAlexey Dobriyan /*
340fe9d4f57SAlexey Dobriyan  *	Raw notifier chain routines.  There is no protection;
341fe9d4f57SAlexey Dobriyan  *	the caller must provide it.  Use at your own risk!
342fe9d4f57SAlexey Dobriyan  */
343fe9d4f57SAlexey Dobriyan 
344fe9d4f57SAlexey Dobriyan /**
345fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_register - Add notifier to a raw notifier chain
346fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
347fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
348fe9d4f57SAlexey Dobriyan  *
349fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a raw notifier chain.
350fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
351fe9d4f57SAlexey Dobriyan  *
3525abb065dSBorislav Petkov  *	Returns 0 on success, %-EEXIST on error.
353fe9d4f57SAlexey Dobriyan  */
354fe9d4f57SAlexey Dobriyan int raw_notifier_chain_register(struct raw_notifier_head *nh,
355fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
356fe9d4f57SAlexey Dobriyan {
357fe9d4f57SAlexey Dobriyan 	return notifier_chain_register(&nh->head, n);
358fe9d4f57SAlexey Dobriyan }
359fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
360fe9d4f57SAlexey Dobriyan 
361fe9d4f57SAlexey Dobriyan /**
362fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
363fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
364fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
365fe9d4f57SAlexey Dobriyan  *
366fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a raw notifier chain.
367fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
368fe9d4f57SAlexey Dobriyan  *
369fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
370fe9d4f57SAlexey Dobriyan  */
371fe9d4f57SAlexey Dobriyan int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
372fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
373fe9d4f57SAlexey Dobriyan {
374fe9d4f57SAlexey Dobriyan 	return notifier_chain_unregister(&nh->head, n);
375fe9d4f57SAlexey Dobriyan }
376fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
377fe9d4f57SAlexey Dobriyan 
37870d93298SPeter Zijlstra int raw_notifier_call_chain_robust(struct raw_notifier_head *nh,
37970d93298SPeter Zijlstra 		unsigned long val_up, unsigned long val_down, void *v)
38070d93298SPeter Zijlstra {
38170d93298SPeter Zijlstra 	return notifier_call_chain_robust(&nh->head, val_up, val_down, v);
38270d93298SPeter Zijlstra }
38370d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust);
38470d93298SPeter Zijlstra 
385fe9d4f57SAlexey Dobriyan /**
38670d93298SPeter Zijlstra  *	raw_notifier_call_chain - Call functions in a raw notifier chain
387fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
388fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
389fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
390fe9d4f57SAlexey Dobriyan  *
391fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
392fe9d4f57SAlexey Dobriyan  *	run in an undefined context.
393fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
394fe9d4f57SAlexey Dobriyan  *
395fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
396fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
397fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
398fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
399fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
400fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
401fe9d4f57SAlexey Dobriyan  */
402fe9d4f57SAlexey Dobriyan int raw_notifier_call_chain(struct raw_notifier_head *nh,
403fe9d4f57SAlexey Dobriyan 		unsigned long val, void *v)
404fe9d4f57SAlexey Dobriyan {
40570d93298SPeter Zijlstra 	return notifier_call_chain(&nh->head, val, v, -1, NULL);
406fe9d4f57SAlexey Dobriyan }
407fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
408fe9d4f57SAlexey Dobriyan 
40983fe27eaSPranith Kumar #ifdef CONFIG_SRCU
410fe9d4f57SAlexey Dobriyan /*
411fe9d4f57SAlexey Dobriyan  *	SRCU notifier chain routines.    Registration and unregistration
412fe9d4f57SAlexey Dobriyan  *	use a mutex, and call_chain is synchronized by SRCU (no locks).
413fe9d4f57SAlexey Dobriyan  */
414fe9d4f57SAlexey Dobriyan 
415fe9d4f57SAlexey Dobriyan /**
416fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
417fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
418fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
419fe9d4f57SAlexey Dobriyan  *
420fe9d4f57SAlexey Dobriyan  *	Adds a notifier to an SRCU notifier chain.
421fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
422fe9d4f57SAlexey Dobriyan  *
4235abb065dSBorislav Petkov  *	Returns 0 on success, %-EEXIST on error.
424fe9d4f57SAlexey Dobriyan  */
425fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
426fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
427fe9d4f57SAlexey Dobriyan {
428fe9d4f57SAlexey Dobriyan 	int ret;
429fe9d4f57SAlexey Dobriyan 
430fe9d4f57SAlexey Dobriyan 	/*
431fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
432fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
433fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
434fe9d4f57SAlexey Dobriyan 	 */
435fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
436fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
437fe9d4f57SAlexey Dobriyan 
438fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
439fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
440fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
441fe9d4f57SAlexey Dobriyan 	return ret;
442fe9d4f57SAlexey Dobriyan }
443fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
444fe9d4f57SAlexey Dobriyan 
445fe9d4f57SAlexey Dobriyan /**
446fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
447fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
448fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
449fe9d4f57SAlexey Dobriyan  *
450fe9d4f57SAlexey Dobriyan  *	Removes a notifier from an SRCU notifier chain.
451fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
452fe9d4f57SAlexey Dobriyan  *
453fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
454fe9d4f57SAlexey Dobriyan  */
455fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
456fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
457fe9d4f57SAlexey Dobriyan {
458fe9d4f57SAlexey Dobriyan 	int ret;
459fe9d4f57SAlexey Dobriyan 
460fe9d4f57SAlexey Dobriyan 	/*
461fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
462fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
463fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
464fe9d4f57SAlexey Dobriyan 	 */
465fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
466fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
467fe9d4f57SAlexey Dobriyan 
468fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
469fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
470fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
471fe9d4f57SAlexey Dobriyan 	synchronize_srcu(&nh->srcu);
472fe9d4f57SAlexey Dobriyan 	return ret;
473fe9d4f57SAlexey Dobriyan }
474fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
475fe9d4f57SAlexey Dobriyan 
476fe9d4f57SAlexey Dobriyan /**
47770d93298SPeter Zijlstra  *	srcu_notifier_call_chain - Call functions in an SRCU notifier chain
478fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
479fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
480fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
481fe9d4f57SAlexey Dobriyan  *
482fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
483fe9d4f57SAlexey Dobriyan  *	run in a process context, so they are allowed to block.
484fe9d4f57SAlexey Dobriyan  *
485fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
486fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
487fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
488fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
489fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
490fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
491fe9d4f57SAlexey Dobriyan  */
49270d93298SPeter Zijlstra int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
49370d93298SPeter Zijlstra 		unsigned long val, void *v)
494fe9d4f57SAlexey Dobriyan {
495fe9d4f57SAlexey Dobriyan 	int ret;
496fe9d4f57SAlexey Dobriyan 	int idx;
497fe9d4f57SAlexey Dobriyan 
498fe9d4f57SAlexey Dobriyan 	idx = srcu_read_lock(&nh->srcu);
49970d93298SPeter Zijlstra 	ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
500fe9d4f57SAlexey Dobriyan 	srcu_read_unlock(&nh->srcu, idx);
501fe9d4f57SAlexey Dobriyan 	return ret;
502fe9d4f57SAlexey Dobriyan }
503fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
504fe9d4f57SAlexey Dobriyan 
505fe9d4f57SAlexey Dobriyan /**
506fe9d4f57SAlexey Dobriyan  *	srcu_init_notifier_head - Initialize an SRCU notifier head
507fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the srcu notifier chain
508fe9d4f57SAlexey Dobriyan  *
509fe9d4f57SAlexey Dobriyan  *	Unlike other sorts of notifier heads, SRCU notifier heads require
510fe9d4f57SAlexey Dobriyan  *	dynamic initialization.  Be sure to call this routine before
511fe9d4f57SAlexey Dobriyan  *	calling any of the other SRCU notifier routines for this head.
512fe9d4f57SAlexey Dobriyan  *
513fe9d4f57SAlexey Dobriyan  *	If an SRCU notifier head is deallocated, it must first be cleaned
514fe9d4f57SAlexey Dobriyan  *	up by calling srcu_cleanup_notifier_head().  Otherwise the head's
515fe9d4f57SAlexey Dobriyan  *	per-cpu data (used by the SRCU mechanism) will leak.
516fe9d4f57SAlexey Dobriyan  */
517fe9d4f57SAlexey Dobriyan void srcu_init_notifier_head(struct srcu_notifier_head *nh)
518fe9d4f57SAlexey Dobriyan {
519fe9d4f57SAlexey Dobriyan 	mutex_init(&nh->mutex);
520fe9d4f57SAlexey Dobriyan 	if (init_srcu_struct(&nh->srcu) < 0)
521fe9d4f57SAlexey Dobriyan 		BUG();
522fe9d4f57SAlexey Dobriyan 	nh->head = NULL;
523fe9d4f57SAlexey Dobriyan }
524fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
525fe9d4f57SAlexey Dobriyan 
52683fe27eaSPranith Kumar #endif /* CONFIG_SRCU */
52783fe27eaSPranith Kumar 
528fe9d4f57SAlexey Dobriyan static ATOMIC_NOTIFIER_HEAD(die_chain);
529fe9d4f57SAlexey Dobriyan 
530b40a2cb6SMasami Hiramatsu int notrace notify_die(enum die_val val, const char *str,
531fe9d4f57SAlexey Dobriyan 	       struct pt_regs *regs, long err, int trap, int sig)
532fe9d4f57SAlexey Dobriyan {
533fe9d4f57SAlexey Dobriyan 	struct die_args args = {
534fe9d4f57SAlexey Dobriyan 		.regs	= regs,
535fe9d4f57SAlexey Dobriyan 		.str	= str,
536fe9d4f57SAlexey Dobriyan 		.err	= err,
537fe9d4f57SAlexey Dobriyan 		.trapnr	= trap,
538fe9d4f57SAlexey Dobriyan 		.signr	= sig,
539fe9d4f57SAlexey Dobriyan 
540fe9d4f57SAlexey Dobriyan 	};
5415778077dSLinus Torvalds 	RCU_LOCKDEP_WARN(!rcu_is_watching(),
542e727c7d7SAndy Lutomirski 			   "notify_die called but RCU thinks we're quiescent");
543fe9d4f57SAlexey Dobriyan 	return atomic_notifier_call_chain(&die_chain, val, &args);
544fe9d4f57SAlexey Dobriyan }
545b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notify_die);
546fe9d4f57SAlexey Dobriyan 
547fe9d4f57SAlexey Dobriyan int register_die_notifier(struct notifier_block *nb)
548fe9d4f57SAlexey Dobriyan {
549fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_register(&die_chain, nb);
550fe9d4f57SAlexey Dobriyan }
551fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(register_die_notifier);
552fe9d4f57SAlexey Dobriyan 
553fe9d4f57SAlexey Dobriyan int unregister_die_notifier(struct notifier_block *nb)
554fe9d4f57SAlexey Dobriyan {
555fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_unregister(&die_chain, nb);
556fe9d4f57SAlexey Dobriyan }
557fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(unregister_die_notifier);
558