xref: /openbmc/linux/kernel/notifier.c (revision 70d932985757fbe978024db313001218e9f8fe5c)
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)) {
271a50cb80SXiaoming Ni 			WARN(1, "double register detected");
281a50cb80SXiaoming Ni 			return 0;
291a50cb80SXiaoming Ni 		}
30fe9d4f57SAlexey Dobriyan 		if (n->priority > (*nl)->priority)
31fe9d4f57SAlexey Dobriyan 			break;
32fe9d4f57SAlexey Dobriyan 		nl = &((*nl)->next);
33fe9d4f57SAlexey Dobriyan 	}
34fe9d4f57SAlexey Dobriyan 	n->next = *nl;
35fe9d4f57SAlexey Dobriyan 	rcu_assign_pointer(*nl, n);
36fe9d4f57SAlexey Dobriyan 	return 0;
37fe9d4f57SAlexey Dobriyan }
38fe9d4f57SAlexey Dobriyan 
39fe9d4f57SAlexey Dobriyan static int notifier_chain_unregister(struct notifier_block **nl,
40fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
41fe9d4f57SAlexey Dobriyan {
42fe9d4f57SAlexey Dobriyan 	while ((*nl) != NULL) {
43fe9d4f57SAlexey Dobriyan 		if ((*nl) == n) {
44fe9d4f57SAlexey Dobriyan 			rcu_assign_pointer(*nl, n->next);
45fe9d4f57SAlexey Dobriyan 			return 0;
46fe9d4f57SAlexey Dobriyan 		}
47fe9d4f57SAlexey Dobriyan 		nl = &((*nl)->next);
48fe9d4f57SAlexey Dobriyan 	}
49fe9d4f57SAlexey Dobriyan 	return -ENOENT;
50fe9d4f57SAlexey Dobriyan }
51fe9d4f57SAlexey Dobriyan 
52fe9d4f57SAlexey Dobriyan /**
53fe9d4f57SAlexey Dobriyan  * notifier_call_chain - Informs the registered notifiers about an event.
54fe9d4f57SAlexey Dobriyan  *	@nl:		Pointer to head of the blocking notifier chain
55fe9d4f57SAlexey Dobriyan  *	@val:		Value passed unmodified to notifier function
56fe9d4f57SAlexey Dobriyan  *	@v:		Pointer passed unmodified to notifier function
57fe9d4f57SAlexey Dobriyan  *	@nr_to_call:	Number of notifier functions to be called. Don't care
58fe9d4f57SAlexey Dobriyan  *			value of this parameter is -1.
59fe9d4f57SAlexey Dobriyan  *	@nr_calls:	Records the number of notifications sent. Don't care
60fe9d4f57SAlexey Dobriyan  *			value of this field is NULL.
61fe9d4f57SAlexey Dobriyan  *	@returns:	notifier_call_chain returns the value returned by the
62fe9d4f57SAlexey Dobriyan  *			last notifier function called.
63fe9d4f57SAlexey Dobriyan  */
64b40a2cb6SMasami Hiramatsu static int notifier_call_chain(struct notifier_block **nl,
65fe9d4f57SAlexey Dobriyan 			       unsigned long val, void *v,
66fe9d4f57SAlexey Dobriyan 			       int nr_to_call, int *nr_calls)
67fe9d4f57SAlexey Dobriyan {
68fe9d4f57SAlexey Dobriyan 	int ret = NOTIFY_DONE;
69fe9d4f57SAlexey Dobriyan 	struct notifier_block *nb, *next_nb;
70fe9d4f57SAlexey Dobriyan 
71d11c563dSPaul E. McKenney 	nb = rcu_dereference_raw(*nl);
72fe9d4f57SAlexey Dobriyan 
73fe9d4f57SAlexey Dobriyan 	while (nb && nr_to_call) {
74d11c563dSPaul E. McKenney 		next_nb = rcu_dereference_raw(nb->next);
751b2439dbSArjan van de Ven 
761b2439dbSArjan van de Ven #ifdef CONFIG_DEBUG_NOTIFIERS
77ab7476cfSArjan van de Ven 		if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
781b2439dbSArjan van de Ven 			WARN(1, "Invalid notifier called!");
791b2439dbSArjan van de Ven 			nb = next_nb;
801b2439dbSArjan van de Ven 			continue;
811b2439dbSArjan van de Ven 		}
821b2439dbSArjan van de Ven #endif
83fe9d4f57SAlexey Dobriyan 		ret = nb->notifier_call(nb, val, v);
84fe9d4f57SAlexey Dobriyan 
85fe9d4f57SAlexey Dobriyan 		if (nr_calls)
86fe9d4f57SAlexey Dobriyan 			(*nr_calls)++;
87fe9d4f57SAlexey Dobriyan 
883e6dadedSViresh Kumar 		if (ret & NOTIFY_STOP_MASK)
89fe9d4f57SAlexey Dobriyan 			break;
90fe9d4f57SAlexey Dobriyan 		nb = next_nb;
91fe9d4f57SAlexey Dobriyan 		nr_to_call--;
92fe9d4f57SAlexey Dobriyan 	}
93fe9d4f57SAlexey Dobriyan 	return ret;
94fe9d4f57SAlexey Dobriyan }
95b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notifier_call_chain);
96fe9d4f57SAlexey Dobriyan 
97*70d93298SPeter Zijlstra /**
98*70d93298SPeter Zijlstra  * notifier_call_chain_robust - Inform the registered notifiers about an event
99*70d93298SPeter Zijlstra  *                              and rollback on error.
100*70d93298SPeter Zijlstra  * @nl:		Pointer to head of the blocking notifier chain
101*70d93298SPeter Zijlstra  * @val_up:	Value passed unmodified to the notifier function
102*70d93298SPeter Zijlstra  * @val_down:	Value passed unmodified to the notifier function when recovering
103*70d93298SPeter Zijlstra  *              from an error on @val_up
104*70d93298SPeter Zijlstra  * @v		Pointer passed unmodified to the notifier function
105*70d93298SPeter Zijlstra  *
106*70d93298SPeter Zijlstra  * NOTE:	It is important the @nl chain doesn't change between the two
107*70d93298SPeter Zijlstra  *		invocations of notifier_call_chain() such that we visit the
108*70d93298SPeter Zijlstra  *		exact same notifier callbacks; this rules out any RCU usage.
109*70d93298SPeter Zijlstra  *
110*70d93298SPeter Zijlstra  * Returns:	the return value of the @val_up call.
111*70d93298SPeter Zijlstra  */
112*70d93298SPeter Zijlstra static int notifier_call_chain_robust(struct notifier_block **nl,
113*70d93298SPeter Zijlstra 				     unsigned long val_up, unsigned long val_down,
114*70d93298SPeter Zijlstra 				     void *v)
115*70d93298SPeter Zijlstra {
116*70d93298SPeter Zijlstra 	int ret, nr = 0;
117*70d93298SPeter Zijlstra 
118*70d93298SPeter Zijlstra 	ret = notifier_call_chain(nl, val_up, v, -1, &nr);
119*70d93298SPeter Zijlstra 	if (ret & NOTIFY_STOP_MASK)
120*70d93298SPeter Zijlstra 		notifier_call_chain(nl, val_down, v, nr-1, NULL);
121*70d93298SPeter Zijlstra 
122*70d93298SPeter Zijlstra 	return ret;
123*70d93298SPeter Zijlstra }
124*70d93298SPeter Zijlstra 
125fe9d4f57SAlexey Dobriyan /*
126fe9d4f57SAlexey Dobriyan  *	Atomic notifier chain routines.  Registration and unregistration
127fe9d4f57SAlexey Dobriyan  *	use a spinlock, and call_chain is synchronized by RCU (no locks).
128fe9d4f57SAlexey Dobriyan  */
129fe9d4f57SAlexey Dobriyan 
130fe9d4f57SAlexey Dobriyan /**
131fe9d4f57SAlexey Dobriyan  *	atomic_notifier_chain_register - Add notifier to an atomic notifier chain
132fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
133fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
134fe9d4f57SAlexey Dobriyan  *
135fe9d4f57SAlexey Dobriyan  *	Adds a notifier to an atomic notifier chain.
136fe9d4f57SAlexey Dobriyan  *
137fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
138fe9d4f57SAlexey Dobriyan  */
139fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
140fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
141fe9d4f57SAlexey Dobriyan {
142fe9d4f57SAlexey Dobriyan 	unsigned long flags;
143fe9d4f57SAlexey Dobriyan 	int ret;
144fe9d4f57SAlexey Dobriyan 
145fe9d4f57SAlexey Dobriyan 	spin_lock_irqsave(&nh->lock, flags);
146fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
147fe9d4f57SAlexey Dobriyan 	spin_unlock_irqrestore(&nh->lock, flags);
148fe9d4f57SAlexey Dobriyan 	return ret;
149fe9d4f57SAlexey Dobriyan }
150fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
151fe9d4f57SAlexey Dobriyan 
152fe9d4f57SAlexey Dobriyan /**
153fe9d4f57SAlexey Dobriyan  *	atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
154fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
155fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
156fe9d4f57SAlexey Dobriyan  *
157fe9d4f57SAlexey Dobriyan  *	Removes a notifier from an atomic notifier chain.
158fe9d4f57SAlexey Dobriyan  *
159fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
160fe9d4f57SAlexey Dobriyan  */
161fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
162fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
163fe9d4f57SAlexey Dobriyan {
164fe9d4f57SAlexey Dobriyan 	unsigned long flags;
165fe9d4f57SAlexey Dobriyan 	int ret;
166fe9d4f57SAlexey Dobriyan 
167fe9d4f57SAlexey Dobriyan 	spin_lock_irqsave(&nh->lock, flags);
168fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
169fe9d4f57SAlexey Dobriyan 	spin_unlock_irqrestore(&nh->lock, flags);
170fe9d4f57SAlexey Dobriyan 	synchronize_rcu();
171fe9d4f57SAlexey Dobriyan 	return ret;
172fe9d4f57SAlexey Dobriyan }
173fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
174fe9d4f57SAlexey Dobriyan 
175*70d93298SPeter Zijlstra int atomic_notifier_call_chain_robust(struct atomic_notifier_head *nh,
176*70d93298SPeter Zijlstra 		unsigned long val_up, unsigned long val_down, void *v)
177*70d93298SPeter Zijlstra {
178*70d93298SPeter Zijlstra 	unsigned long flags;
179*70d93298SPeter Zijlstra 	int ret;
180*70d93298SPeter Zijlstra 
181*70d93298SPeter Zijlstra 	/*
182*70d93298SPeter Zijlstra 	 * Musn't use RCU; because then the notifier list can
183*70d93298SPeter Zijlstra 	 * change between the up and down traversal.
184*70d93298SPeter Zijlstra 	 */
185*70d93298SPeter Zijlstra 	spin_lock_irqsave(&nh->lock, flags);
186*70d93298SPeter Zijlstra 	ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v);
187*70d93298SPeter Zijlstra 	spin_unlock_irqrestore(&nh->lock, flags);
188*70d93298SPeter Zijlstra 
189*70d93298SPeter Zijlstra 	return ret;
190*70d93298SPeter Zijlstra }
191*70d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(atomic_notifier_call_chain_robust);
192*70d93298SPeter Zijlstra NOKPROBE_SYMBOL(atomic_notifier_call_chain_robust);
193*70d93298SPeter Zijlstra 
194fe9d4f57SAlexey Dobriyan /**
195*70d93298SPeter Zijlstra  *	atomic_notifier_call_chain - Call functions in an atomic notifier chain
196fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
197fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
198fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
199fe9d4f57SAlexey Dobriyan  *
200fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
201fe9d4f57SAlexey Dobriyan  *	run in an atomic context, so they must not block.
202fe9d4f57SAlexey Dobriyan  *	This routine uses RCU to synchronize with changes to the chain.
203fe9d4f57SAlexey Dobriyan  *
204fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
205fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
206fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
207fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
208fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
209fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
210fe9d4f57SAlexey Dobriyan  */
211*70d93298SPeter Zijlstra int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
212*70d93298SPeter Zijlstra 			       unsigned long val, void *v)
213fe9d4f57SAlexey Dobriyan {
214fe9d4f57SAlexey Dobriyan 	int ret;
215fe9d4f57SAlexey Dobriyan 
216fe9d4f57SAlexey Dobriyan 	rcu_read_lock();
217*70d93298SPeter Zijlstra 	ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
218fe9d4f57SAlexey Dobriyan 	rcu_read_unlock();
219fe9d4f57SAlexey Dobriyan 
220*70d93298SPeter Zijlstra 	return ret;
221fe9d4f57SAlexey Dobriyan }
222fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
223b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(atomic_notifier_call_chain);
224fe9d4f57SAlexey Dobriyan 
225fe9d4f57SAlexey Dobriyan /*
226fe9d4f57SAlexey Dobriyan  *	Blocking notifier chain routines.  All access to the chain is
227fe9d4f57SAlexey Dobriyan  *	synchronized by an rwsem.
228fe9d4f57SAlexey Dobriyan  */
229fe9d4f57SAlexey Dobriyan 
230fe9d4f57SAlexey Dobriyan /**
231fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_register - Add notifier to a blocking notifier chain
232fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
233fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
234fe9d4f57SAlexey Dobriyan  *
235fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a blocking notifier chain.
236fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
237fe9d4f57SAlexey Dobriyan  *
238fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
239fe9d4f57SAlexey Dobriyan  */
240fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
241fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
242fe9d4f57SAlexey Dobriyan {
243fe9d4f57SAlexey Dobriyan 	int ret;
244fe9d4f57SAlexey Dobriyan 
245fe9d4f57SAlexey Dobriyan 	/*
246fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
247fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
248fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
249fe9d4f57SAlexey Dobriyan 	 */
250fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
251fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
252fe9d4f57SAlexey Dobriyan 
253fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
254fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
255fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
256fe9d4f57SAlexey Dobriyan 	return ret;
257fe9d4f57SAlexey Dobriyan }
258fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
259fe9d4f57SAlexey Dobriyan 
260fe9d4f57SAlexey Dobriyan /**
261fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
262fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
263fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
264fe9d4f57SAlexey Dobriyan  *
265fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a blocking notifier chain.
266fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
267fe9d4f57SAlexey Dobriyan  *
268fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
269fe9d4f57SAlexey Dobriyan  */
270fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
271fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
272fe9d4f57SAlexey Dobriyan {
273fe9d4f57SAlexey Dobriyan 	int ret;
274fe9d4f57SAlexey Dobriyan 
275fe9d4f57SAlexey Dobriyan 	/*
276fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
277fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
278fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
279fe9d4f57SAlexey Dobriyan 	 */
280fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
281fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
282fe9d4f57SAlexey Dobriyan 
283fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
284fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
285fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
286fe9d4f57SAlexey Dobriyan 	return ret;
287fe9d4f57SAlexey Dobriyan }
288fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
289fe9d4f57SAlexey Dobriyan 
290*70d93298SPeter Zijlstra int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh,
291*70d93298SPeter Zijlstra 		unsigned long val_up, unsigned long val_down, void *v)
292*70d93298SPeter Zijlstra {
293*70d93298SPeter Zijlstra 	int ret = NOTIFY_DONE;
294*70d93298SPeter Zijlstra 
295*70d93298SPeter Zijlstra 	/*
296*70d93298SPeter Zijlstra 	 * We check the head outside the lock, but if this access is
297*70d93298SPeter Zijlstra 	 * racy then it does not matter what the result of the test
298*70d93298SPeter Zijlstra 	 * is, we re-check the list after having taken the lock anyway:
299*70d93298SPeter Zijlstra 	 */
300*70d93298SPeter Zijlstra 	if (rcu_access_pointer(nh->head)) {
301*70d93298SPeter Zijlstra 		down_read(&nh->rwsem);
302*70d93298SPeter Zijlstra 		ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v);
303*70d93298SPeter Zijlstra 		up_read(&nh->rwsem);
304*70d93298SPeter Zijlstra 	}
305*70d93298SPeter Zijlstra 	return ret;
306*70d93298SPeter Zijlstra }
307*70d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust);
308*70d93298SPeter Zijlstra 
309fe9d4f57SAlexey Dobriyan /**
310*70d93298SPeter Zijlstra  *	blocking_notifier_call_chain - Call functions in a blocking notifier chain
311fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
312fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
313fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
314fe9d4f57SAlexey Dobriyan  *
315fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
316fe9d4f57SAlexey Dobriyan  *	run in a process context, so they are allowed to block.
317fe9d4f57SAlexey Dobriyan  *
318fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
319fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
320fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
321fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
322fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
323fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
324fe9d4f57SAlexey Dobriyan  */
325*70d93298SPeter Zijlstra int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
326*70d93298SPeter Zijlstra 		unsigned long val, void *v)
327fe9d4f57SAlexey Dobriyan {
328fe9d4f57SAlexey Dobriyan 	int ret = NOTIFY_DONE;
329fe9d4f57SAlexey Dobriyan 
330fe9d4f57SAlexey Dobriyan 	/*
331fe9d4f57SAlexey Dobriyan 	 * We check the head outside the lock, but if this access is
332fe9d4f57SAlexey Dobriyan 	 * racy then it does not matter what the result of the test
333fe9d4f57SAlexey Dobriyan 	 * is, we re-check the list after having taken the lock anyway:
334fe9d4f57SAlexey Dobriyan 	 */
3358857563bSPaul E. McKenney 	if (rcu_access_pointer(nh->head)) {
336fe9d4f57SAlexey Dobriyan 		down_read(&nh->rwsem);
337*70d93298SPeter Zijlstra 		ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
338fe9d4f57SAlexey Dobriyan 		up_read(&nh->rwsem);
339fe9d4f57SAlexey Dobriyan 	}
340fe9d4f57SAlexey Dobriyan 	return ret;
341fe9d4f57SAlexey Dobriyan }
342fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
343fe9d4f57SAlexey Dobriyan 
344fe9d4f57SAlexey Dobriyan /*
345fe9d4f57SAlexey Dobriyan  *	Raw notifier chain routines.  There is no protection;
346fe9d4f57SAlexey Dobriyan  *	the caller must provide it.  Use at your own risk!
347fe9d4f57SAlexey Dobriyan  */
348fe9d4f57SAlexey Dobriyan 
349fe9d4f57SAlexey Dobriyan /**
350fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_register - Add notifier to a raw notifier chain
351fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
352fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
353fe9d4f57SAlexey Dobriyan  *
354fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a raw notifier chain.
355fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
356fe9d4f57SAlexey Dobriyan  *
357fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
358fe9d4f57SAlexey Dobriyan  */
359fe9d4f57SAlexey Dobriyan int raw_notifier_chain_register(struct raw_notifier_head *nh,
360fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
361fe9d4f57SAlexey Dobriyan {
362fe9d4f57SAlexey Dobriyan 	return notifier_chain_register(&nh->head, n);
363fe9d4f57SAlexey Dobriyan }
364fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
365fe9d4f57SAlexey Dobriyan 
366fe9d4f57SAlexey Dobriyan /**
367fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
368fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
369fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
370fe9d4f57SAlexey Dobriyan  *
371fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a raw notifier chain.
372fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
373fe9d4f57SAlexey Dobriyan  *
374fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
375fe9d4f57SAlexey Dobriyan  */
376fe9d4f57SAlexey Dobriyan int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
377fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
378fe9d4f57SAlexey Dobriyan {
379fe9d4f57SAlexey Dobriyan 	return notifier_chain_unregister(&nh->head, n);
380fe9d4f57SAlexey Dobriyan }
381fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
382fe9d4f57SAlexey Dobriyan 
383*70d93298SPeter Zijlstra int raw_notifier_call_chain_robust(struct raw_notifier_head *nh,
384*70d93298SPeter Zijlstra 		unsigned long val_up, unsigned long val_down, void *v)
385*70d93298SPeter Zijlstra {
386*70d93298SPeter Zijlstra 	return notifier_call_chain_robust(&nh->head, val_up, val_down, v);
387*70d93298SPeter Zijlstra }
388*70d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust);
389*70d93298SPeter Zijlstra 
390fe9d4f57SAlexey Dobriyan /**
391*70d93298SPeter Zijlstra  *	raw_notifier_call_chain - Call functions in a raw notifier chain
392fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
393fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
394fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
395fe9d4f57SAlexey Dobriyan  *
396fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
397fe9d4f57SAlexey Dobriyan  *	run in an undefined context.
398fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
399fe9d4f57SAlexey Dobriyan  *
400fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
401fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
402fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
403fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
404fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
405fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
406fe9d4f57SAlexey Dobriyan  */
407fe9d4f57SAlexey Dobriyan int raw_notifier_call_chain(struct raw_notifier_head *nh,
408fe9d4f57SAlexey Dobriyan 		unsigned long val, void *v)
409fe9d4f57SAlexey Dobriyan {
410*70d93298SPeter Zijlstra 	return notifier_call_chain(&nh->head, val, v, -1, NULL);
411fe9d4f57SAlexey Dobriyan }
412fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
413fe9d4f57SAlexey Dobriyan 
41483fe27eaSPranith Kumar #ifdef CONFIG_SRCU
415fe9d4f57SAlexey Dobriyan /*
416fe9d4f57SAlexey Dobriyan  *	SRCU notifier chain routines.    Registration and unregistration
417fe9d4f57SAlexey Dobriyan  *	use a mutex, and call_chain is synchronized by SRCU (no locks).
418fe9d4f57SAlexey Dobriyan  */
419fe9d4f57SAlexey Dobriyan 
420fe9d4f57SAlexey Dobriyan /**
421fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
422fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
423fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
424fe9d4f57SAlexey Dobriyan  *
425fe9d4f57SAlexey Dobriyan  *	Adds a notifier to an SRCU notifier chain.
426fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
427fe9d4f57SAlexey Dobriyan  *
428fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
429fe9d4f57SAlexey Dobriyan  */
430fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
431fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
432fe9d4f57SAlexey Dobriyan {
433fe9d4f57SAlexey Dobriyan 	int ret;
434fe9d4f57SAlexey Dobriyan 
435fe9d4f57SAlexey Dobriyan 	/*
436fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
437fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
438fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
439fe9d4f57SAlexey Dobriyan 	 */
440fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
441fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
442fe9d4f57SAlexey Dobriyan 
443fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
444fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
445fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
446fe9d4f57SAlexey Dobriyan 	return ret;
447fe9d4f57SAlexey Dobriyan }
448fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
449fe9d4f57SAlexey Dobriyan 
450fe9d4f57SAlexey Dobriyan /**
451fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
452fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
453fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
454fe9d4f57SAlexey Dobriyan  *
455fe9d4f57SAlexey Dobriyan  *	Removes a notifier from an SRCU notifier chain.
456fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
457fe9d4f57SAlexey Dobriyan  *
458fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
459fe9d4f57SAlexey Dobriyan  */
460fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
461fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
462fe9d4f57SAlexey Dobriyan {
463fe9d4f57SAlexey Dobriyan 	int ret;
464fe9d4f57SAlexey Dobriyan 
465fe9d4f57SAlexey Dobriyan 	/*
466fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
467fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
468fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
469fe9d4f57SAlexey Dobriyan 	 */
470fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
471fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
472fe9d4f57SAlexey Dobriyan 
473fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
474fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
475fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
476fe9d4f57SAlexey Dobriyan 	synchronize_srcu(&nh->srcu);
477fe9d4f57SAlexey Dobriyan 	return ret;
478fe9d4f57SAlexey Dobriyan }
479fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
480fe9d4f57SAlexey Dobriyan 
481fe9d4f57SAlexey Dobriyan /**
482*70d93298SPeter Zijlstra  *	srcu_notifier_call_chain - Call functions in an SRCU notifier chain
483fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
484fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
485fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
486fe9d4f57SAlexey Dobriyan  *
487fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
488fe9d4f57SAlexey Dobriyan  *	run in a process context, so they are allowed to block.
489fe9d4f57SAlexey Dobriyan  *
490fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
491fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then srcu_notifier_call_chain()
492fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
493fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
494fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
495fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
496fe9d4f57SAlexey Dobriyan  */
497*70d93298SPeter Zijlstra int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
498*70d93298SPeter Zijlstra 		unsigned long val, void *v)
499fe9d4f57SAlexey Dobriyan {
500fe9d4f57SAlexey Dobriyan 	int ret;
501fe9d4f57SAlexey Dobriyan 	int idx;
502fe9d4f57SAlexey Dobriyan 
503fe9d4f57SAlexey Dobriyan 	idx = srcu_read_lock(&nh->srcu);
504*70d93298SPeter Zijlstra 	ret = notifier_call_chain(&nh->head, val, v, -1, NULL);
505fe9d4f57SAlexey Dobriyan 	srcu_read_unlock(&nh->srcu, idx);
506fe9d4f57SAlexey Dobriyan 	return ret;
507fe9d4f57SAlexey Dobriyan }
508fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
509fe9d4f57SAlexey Dobriyan 
510fe9d4f57SAlexey Dobriyan /**
511fe9d4f57SAlexey Dobriyan  *	srcu_init_notifier_head - Initialize an SRCU notifier head
512fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the srcu notifier chain
513fe9d4f57SAlexey Dobriyan  *
514fe9d4f57SAlexey Dobriyan  *	Unlike other sorts of notifier heads, SRCU notifier heads require
515fe9d4f57SAlexey Dobriyan  *	dynamic initialization.  Be sure to call this routine before
516fe9d4f57SAlexey Dobriyan  *	calling any of the other SRCU notifier routines for this head.
517fe9d4f57SAlexey Dobriyan  *
518fe9d4f57SAlexey Dobriyan  *	If an SRCU notifier head is deallocated, it must first be cleaned
519fe9d4f57SAlexey Dobriyan  *	up by calling srcu_cleanup_notifier_head().  Otherwise the head's
520fe9d4f57SAlexey Dobriyan  *	per-cpu data (used by the SRCU mechanism) will leak.
521fe9d4f57SAlexey Dobriyan  */
522fe9d4f57SAlexey Dobriyan void srcu_init_notifier_head(struct srcu_notifier_head *nh)
523fe9d4f57SAlexey Dobriyan {
524fe9d4f57SAlexey Dobriyan 	mutex_init(&nh->mutex);
525fe9d4f57SAlexey Dobriyan 	if (init_srcu_struct(&nh->srcu) < 0)
526fe9d4f57SAlexey Dobriyan 		BUG();
527fe9d4f57SAlexey Dobriyan 	nh->head = NULL;
528fe9d4f57SAlexey Dobriyan }
529fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
530fe9d4f57SAlexey Dobriyan 
53183fe27eaSPranith Kumar #endif /* CONFIG_SRCU */
53283fe27eaSPranith Kumar 
533fe9d4f57SAlexey Dobriyan static ATOMIC_NOTIFIER_HEAD(die_chain);
534fe9d4f57SAlexey Dobriyan 
535b40a2cb6SMasami Hiramatsu int notrace notify_die(enum die_val val, const char *str,
536fe9d4f57SAlexey Dobriyan 	       struct pt_regs *regs, long err, int trap, int sig)
537fe9d4f57SAlexey Dobriyan {
538fe9d4f57SAlexey Dobriyan 	struct die_args args = {
539fe9d4f57SAlexey Dobriyan 		.regs	= regs,
540fe9d4f57SAlexey Dobriyan 		.str	= str,
541fe9d4f57SAlexey Dobriyan 		.err	= err,
542fe9d4f57SAlexey Dobriyan 		.trapnr	= trap,
543fe9d4f57SAlexey Dobriyan 		.signr	= sig,
544fe9d4f57SAlexey Dobriyan 
545fe9d4f57SAlexey Dobriyan 	};
5465778077dSLinus Torvalds 	RCU_LOCKDEP_WARN(!rcu_is_watching(),
547e727c7d7SAndy Lutomirski 			   "notify_die called but RCU thinks we're quiescent");
548fe9d4f57SAlexey Dobriyan 	return atomic_notifier_call_chain(&die_chain, val, &args);
549fe9d4f57SAlexey Dobriyan }
550b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notify_die);
551fe9d4f57SAlexey Dobriyan 
552fe9d4f57SAlexey Dobriyan int register_die_notifier(struct notifier_block *nb)
553fe9d4f57SAlexey Dobriyan {
554fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_register(&die_chain, nb);
555fe9d4f57SAlexey Dobriyan }
556fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(register_die_notifier);
557fe9d4f57SAlexey Dobriyan 
558fe9d4f57SAlexey Dobriyan int unregister_die_notifier(struct notifier_block *nb)
559fe9d4f57SAlexey Dobriyan {
560fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_unregister(&die_chain, nb);
561fe9d4f57SAlexey Dobriyan }
562fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(unregister_die_notifier);
563