xref: /openbmc/linux/kernel/notifier.c (revision 457c89965399115e5cd8bf38f9c597293405703d)
1*457c8996SThomas 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) {
2683124657SVasily Averin 		WARN_ONCE(((*nl) == n), "double register detected");
27fe9d4f57SAlexey Dobriyan 		if (n->priority > (*nl)->priority)
28fe9d4f57SAlexey Dobriyan 			break;
29fe9d4f57SAlexey Dobriyan 		nl = &((*nl)->next);
30fe9d4f57SAlexey Dobriyan 	}
31fe9d4f57SAlexey Dobriyan 	n->next = *nl;
32fe9d4f57SAlexey Dobriyan 	rcu_assign_pointer(*nl, n);
33fe9d4f57SAlexey Dobriyan 	return 0;
34fe9d4f57SAlexey Dobriyan }
35fe9d4f57SAlexey Dobriyan 
366546bc42SNadia Derbey static int notifier_chain_cond_register(struct notifier_block **nl,
376546bc42SNadia Derbey 		struct notifier_block *n)
386546bc42SNadia Derbey {
396546bc42SNadia Derbey 	while ((*nl) != NULL) {
406546bc42SNadia Derbey 		if ((*nl) == n)
416546bc42SNadia Derbey 			return 0;
426546bc42SNadia Derbey 		if (n->priority > (*nl)->priority)
436546bc42SNadia Derbey 			break;
446546bc42SNadia Derbey 		nl = &((*nl)->next);
456546bc42SNadia Derbey 	}
466546bc42SNadia Derbey 	n->next = *nl;
476546bc42SNadia Derbey 	rcu_assign_pointer(*nl, n);
486546bc42SNadia Derbey 	return 0;
496546bc42SNadia Derbey }
506546bc42SNadia Derbey 
51fe9d4f57SAlexey Dobriyan static int notifier_chain_unregister(struct notifier_block **nl,
52fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
53fe9d4f57SAlexey Dobriyan {
54fe9d4f57SAlexey Dobriyan 	while ((*nl) != NULL) {
55fe9d4f57SAlexey Dobriyan 		if ((*nl) == n) {
56fe9d4f57SAlexey Dobriyan 			rcu_assign_pointer(*nl, n->next);
57fe9d4f57SAlexey Dobriyan 			return 0;
58fe9d4f57SAlexey Dobriyan 		}
59fe9d4f57SAlexey Dobriyan 		nl = &((*nl)->next);
60fe9d4f57SAlexey Dobriyan 	}
61fe9d4f57SAlexey Dobriyan 	return -ENOENT;
62fe9d4f57SAlexey Dobriyan }
63fe9d4f57SAlexey Dobriyan 
64fe9d4f57SAlexey Dobriyan /**
65fe9d4f57SAlexey Dobriyan  * notifier_call_chain - Informs the registered notifiers about an event.
66fe9d4f57SAlexey Dobriyan  *	@nl:		Pointer to head of the blocking notifier chain
67fe9d4f57SAlexey Dobriyan  *	@val:		Value passed unmodified to notifier function
68fe9d4f57SAlexey Dobriyan  *	@v:		Pointer passed unmodified to notifier function
69fe9d4f57SAlexey Dobriyan  *	@nr_to_call:	Number of notifier functions to be called. Don't care
70fe9d4f57SAlexey Dobriyan  *			value of this parameter is -1.
71fe9d4f57SAlexey Dobriyan  *	@nr_calls:	Records the number of notifications sent. Don't care
72fe9d4f57SAlexey Dobriyan  *			value of this field is NULL.
73fe9d4f57SAlexey Dobriyan  *	@returns:	notifier_call_chain returns the value returned by the
74fe9d4f57SAlexey Dobriyan  *			last notifier function called.
75fe9d4f57SAlexey Dobriyan  */
76b40a2cb6SMasami Hiramatsu static int notifier_call_chain(struct notifier_block **nl,
77fe9d4f57SAlexey Dobriyan 			       unsigned long val, void *v,
78fe9d4f57SAlexey Dobriyan 			       int nr_to_call, int *nr_calls)
79fe9d4f57SAlexey Dobriyan {
80fe9d4f57SAlexey Dobriyan 	int ret = NOTIFY_DONE;
81fe9d4f57SAlexey Dobriyan 	struct notifier_block *nb, *next_nb;
82fe9d4f57SAlexey Dobriyan 
83d11c563dSPaul E. McKenney 	nb = rcu_dereference_raw(*nl);
84fe9d4f57SAlexey Dobriyan 
85fe9d4f57SAlexey Dobriyan 	while (nb && nr_to_call) {
86d11c563dSPaul E. McKenney 		next_nb = rcu_dereference_raw(nb->next);
871b2439dbSArjan van de Ven 
881b2439dbSArjan van de Ven #ifdef CONFIG_DEBUG_NOTIFIERS
89ab7476cfSArjan van de Ven 		if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) {
901b2439dbSArjan van de Ven 			WARN(1, "Invalid notifier called!");
911b2439dbSArjan van de Ven 			nb = next_nb;
921b2439dbSArjan van de Ven 			continue;
931b2439dbSArjan van de Ven 		}
941b2439dbSArjan van de Ven #endif
95fe9d4f57SAlexey Dobriyan 		ret = nb->notifier_call(nb, val, v);
96fe9d4f57SAlexey Dobriyan 
97fe9d4f57SAlexey Dobriyan 		if (nr_calls)
98fe9d4f57SAlexey Dobriyan 			(*nr_calls)++;
99fe9d4f57SAlexey Dobriyan 
1003e6dadedSViresh Kumar 		if (ret & NOTIFY_STOP_MASK)
101fe9d4f57SAlexey Dobriyan 			break;
102fe9d4f57SAlexey Dobriyan 		nb = next_nb;
103fe9d4f57SAlexey Dobriyan 		nr_to_call--;
104fe9d4f57SAlexey Dobriyan 	}
105fe9d4f57SAlexey Dobriyan 	return ret;
106fe9d4f57SAlexey Dobriyan }
107b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notifier_call_chain);
108fe9d4f57SAlexey Dobriyan 
109fe9d4f57SAlexey Dobriyan /*
110fe9d4f57SAlexey Dobriyan  *	Atomic notifier chain routines.  Registration and unregistration
111fe9d4f57SAlexey Dobriyan  *	use a spinlock, and call_chain is synchronized by RCU (no locks).
112fe9d4f57SAlexey Dobriyan  */
113fe9d4f57SAlexey Dobriyan 
114fe9d4f57SAlexey Dobriyan /**
115fe9d4f57SAlexey Dobriyan  *	atomic_notifier_chain_register - Add notifier to an atomic notifier chain
116fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
117fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
118fe9d4f57SAlexey Dobriyan  *
119fe9d4f57SAlexey Dobriyan  *	Adds a notifier to an atomic notifier chain.
120fe9d4f57SAlexey Dobriyan  *
121fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
122fe9d4f57SAlexey Dobriyan  */
123fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_register(struct atomic_notifier_head *nh,
124fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
125fe9d4f57SAlexey Dobriyan {
126fe9d4f57SAlexey Dobriyan 	unsigned long flags;
127fe9d4f57SAlexey Dobriyan 	int ret;
128fe9d4f57SAlexey Dobriyan 
129fe9d4f57SAlexey Dobriyan 	spin_lock_irqsave(&nh->lock, flags);
130fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
131fe9d4f57SAlexey Dobriyan 	spin_unlock_irqrestore(&nh->lock, flags);
132fe9d4f57SAlexey Dobriyan 	return ret;
133fe9d4f57SAlexey Dobriyan }
134fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
135fe9d4f57SAlexey Dobriyan 
136fe9d4f57SAlexey Dobriyan /**
137fe9d4f57SAlexey Dobriyan  *	atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain
138fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
139fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
140fe9d4f57SAlexey Dobriyan  *
141fe9d4f57SAlexey Dobriyan  *	Removes a notifier from an atomic notifier chain.
142fe9d4f57SAlexey Dobriyan  *
143fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
144fe9d4f57SAlexey Dobriyan  */
145fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh,
146fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
147fe9d4f57SAlexey Dobriyan {
148fe9d4f57SAlexey Dobriyan 	unsigned long flags;
149fe9d4f57SAlexey Dobriyan 	int ret;
150fe9d4f57SAlexey Dobriyan 
151fe9d4f57SAlexey Dobriyan 	spin_lock_irqsave(&nh->lock, flags);
152fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
153fe9d4f57SAlexey Dobriyan 	spin_unlock_irqrestore(&nh->lock, flags);
154fe9d4f57SAlexey Dobriyan 	synchronize_rcu();
155fe9d4f57SAlexey Dobriyan 	return ret;
156fe9d4f57SAlexey Dobriyan }
157fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister);
158fe9d4f57SAlexey Dobriyan 
159fe9d4f57SAlexey Dobriyan /**
160fe9d4f57SAlexey Dobriyan  *	__atomic_notifier_call_chain - Call functions in an atomic notifier chain
161fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the atomic notifier chain
162fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
163fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
164fe9d4f57SAlexey Dobriyan  *	@nr_to_call: See the comment for notifier_call_chain.
165fe9d4f57SAlexey Dobriyan  *	@nr_calls: See the comment for notifier_call_chain.
166fe9d4f57SAlexey Dobriyan  *
167fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
168fe9d4f57SAlexey Dobriyan  *	run in an atomic context, so they must not block.
169fe9d4f57SAlexey Dobriyan  *	This routine uses RCU to synchronize with changes to the chain.
170fe9d4f57SAlexey Dobriyan  *
171fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
172fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then atomic_notifier_call_chain()
173fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
174fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
175fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
176fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
177fe9d4f57SAlexey Dobriyan  */
178b40a2cb6SMasami Hiramatsu int __atomic_notifier_call_chain(struct atomic_notifier_head *nh,
179fe9d4f57SAlexey Dobriyan 				 unsigned long val, void *v,
180fe9d4f57SAlexey Dobriyan 				 int nr_to_call, int *nr_calls)
181fe9d4f57SAlexey Dobriyan {
182fe9d4f57SAlexey Dobriyan 	int ret;
183fe9d4f57SAlexey Dobriyan 
184fe9d4f57SAlexey Dobriyan 	rcu_read_lock();
185fe9d4f57SAlexey Dobriyan 	ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
186fe9d4f57SAlexey Dobriyan 	rcu_read_unlock();
187fe9d4f57SAlexey Dobriyan 	return ret;
188fe9d4f57SAlexey Dobriyan }
189fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(__atomic_notifier_call_chain);
190b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(__atomic_notifier_call_chain);
191fe9d4f57SAlexey Dobriyan 
192b40a2cb6SMasami Hiramatsu int atomic_notifier_call_chain(struct atomic_notifier_head *nh,
193fe9d4f57SAlexey Dobriyan 			       unsigned long val, void *v)
194fe9d4f57SAlexey Dobriyan {
195fe9d4f57SAlexey Dobriyan 	return __atomic_notifier_call_chain(nh, val, v, -1, NULL);
196fe9d4f57SAlexey Dobriyan }
197fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_call_chain);
198b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(atomic_notifier_call_chain);
199fe9d4f57SAlexey Dobriyan 
200fe9d4f57SAlexey Dobriyan /*
201fe9d4f57SAlexey Dobriyan  *	Blocking notifier chain routines.  All access to the chain is
202fe9d4f57SAlexey Dobriyan  *	synchronized by an rwsem.
203fe9d4f57SAlexey Dobriyan  */
204fe9d4f57SAlexey Dobriyan 
205fe9d4f57SAlexey Dobriyan /**
206fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_register - Add notifier to a blocking notifier chain
207fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
208fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
209fe9d4f57SAlexey Dobriyan  *
210fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a blocking notifier chain.
211fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
212fe9d4f57SAlexey Dobriyan  *
213fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
214fe9d4f57SAlexey Dobriyan  */
215fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_register(struct blocking_notifier_head *nh,
216fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
217fe9d4f57SAlexey Dobriyan {
218fe9d4f57SAlexey Dobriyan 	int ret;
219fe9d4f57SAlexey Dobriyan 
220fe9d4f57SAlexey Dobriyan 	/*
221fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
222fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
223fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
224fe9d4f57SAlexey Dobriyan 	 */
225fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
226fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
227fe9d4f57SAlexey Dobriyan 
228fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
229fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
230fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
231fe9d4f57SAlexey Dobriyan 	return ret;
232fe9d4f57SAlexey Dobriyan }
233fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_register);
234fe9d4f57SAlexey Dobriyan 
235fe9d4f57SAlexey Dobriyan /**
2366546bc42SNadia Derbey  *	blocking_notifier_chain_cond_register - Cond add notifier to a blocking notifier chain
2376546bc42SNadia Derbey  *	@nh: Pointer to head of the blocking notifier chain
2386546bc42SNadia Derbey  *	@n: New entry in notifier chain
2396546bc42SNadia Derbey  *
2406546bc42SNadia Derbey  *	Adds a notifier to a blocking notifier chain, only if not already
2416546bc42SNadia Derbey  *	present in the chain.
2426546bc42SNadia Derbey  *	Must be called in process context.
2436546bc42SNadia Derbey  *
2446546bc42SNadia Derbey  *	Currently always returns zero.
2456546bc42SNadia Derbey  */
2466546bc42SNadia Derbey int blocking_notifier_chain_cond_register(struct blocking_notifier_head *nh,
2476546bc42SNadia Derbey 		struct notifier_block *n)
2486546bc42SNadia Derbey {
2496546bc42SNadia Derbey 	int ret;
2506546bc42SNadia Derbey 
2516546bc42SNadia Derbey 	down_write(&nh->rwsem);
2526546bc42SNadia Derbey 	ret = notifier_chain_cond_register(&nh->head, n);
2536546bc42SNadia Derbey 	up_write(&nh->rwsem);
2546546bc42SNadia Derbey 	return ret;
2556546bc42SNadia Derbey }
2566546bc42SNadia Derbey EXPORT_SYMBOL_GPL(blocking_notifier_chain_cond_register);
2576546bc42SNadia Derbey 
2586546bc42SNadia Derbey /**
259fe9d4f57SAlexey Dobriyan  *	blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain
260fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
261fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
262fe9d4f57SAlexey Dobriyan  *
263fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a blocking notifier chain.
264fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
265fe9d4f57SAlexey Dobriyan  *
266fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
267fe9d4f57SAlexey Dobriyan  */
268fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh,
269fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
270fe9d4f57SAlexey Dobriyan {
271fe9d4f57SAlexey Dobriyan 	int ret;
272fe9d4f57SAlexey Dobriyan 
273fe9d4f57SAlexey Dobriyan 	/*
274fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
275fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
276fe9d4f57SAlexey Dobriyan 	 * such times we must not call down_write().
277fe9d4f57SAlexey Dobriyan 	 */
278fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
279fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
280fe9d4f57SAlexey Dobriyan 
281fe9d4f57SAlexey Dobriyan 	down_write(&nh->rwsem);
282fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
283fe9d4f57SAlexey Dobriyan 	up_write(&nh->rwsem);
284fe9d4f57SAlexey Dobriyan 	return ret;
285fe9d4f57SAlexey Dobriyan }
286fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister);
287fe9d4f57SAlexey Dobriyan 
288fe9d4f57SAlexey Dobriyan /**
289fe9d4f57SAlexey Dobriyan  *	__blocking_notifier_call_chain - Call functions in a blocking notifier chain
290fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the blocking notifier chain
291fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
292fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
293fe9d4f57SAlexey Dobriyan  *	@nr_to_call: See comment for notifier_call_chain.
294fe9d4f57SAlexey Dobriyan  *	@nr_calls: See comment for notifier_call_chain.
295fe9d4f57SAlexey Dobriyan  *
296fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
297fe9d4f57SAlexey Dobriyan  *	run in a process context, so they are allowed to block.
298fe9d4f57SAlexey Dobriyan  *
299fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
300fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then blocking_notifier_call_chain()
301fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
302fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
303fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
304fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
305fe9d4f57SAlexey Dobriyan  */
306fe9d4f57SAlexey Dobriyan int __blocking_notifier_call_chain(struct blocking_notifier_head *nh,
307fe9d4f57SAlexey Dobriyan 				   unsigned long val, void *v,
308fe9d4f57SAlexey Dobriyan 				   int nr_to_call, int *nr_calls)
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);
319fe9d4f57SAlexey Dobriyan 		ret = notifier_call_chain(&nh->head, val, v, nr_to_call,
320fe9d4f57SAlexey Dobriyan 					nr_calls);
321fe9d4f57SAlexey Dobriyan 		up_read(&nh->rwsem);
322fe9d4f57SAlexey Dobriyan 	}
323fe9d4f57SAlexey Dobriyan 	return ret;
324fe9d4f57SAlexey Dobriyan }
325fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(__blocking_notifier_call_chain);
326fe9d4f57SAlexey Dobriyan 
327fe9d4f57SAlexey Dobriyan int blocking_notifier_call_chain(struct blocking_notifier_head *nh,
328fe9d4f57SAlexey Dobriyan 		unsigned long val, void *v)
329fe9d4f57SAlexey Dobriyan {
330fe9d4f57SAlexey Dobriyan 	return __blocking_notifier_call_chain(nh, val, v, -1, NULL);
331fe9d4f57SAlexey Dobriyan }
332fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_call_chain);
333fe9d4f57SAlexey Dobriyan 
334fe9d4f57SAlexey Dobriyan /*
335fe9d4f57SAlexey Dobriyan  *	Raw notifier chain routines.  There is no protection;
336fe9d4f57SAlexey Dobriyan  *	the caller must provide it.  Use at your own risk!
337fe9d4f57SAlexey Dobriyan  */
338fe9d4f57SAlexey Dobriyan 
339fe9d4f57SAlexey Dobriyan /**
340fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_register - Add notifier to a raw notifier chain
341fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
342fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
343fe9d4f57SAlexey Dobriyan  *
344fe9d4f57SAlexey Dobriyan  *	Adds a notifier to a raw notifier chain.
345fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
346fe9d4f57SAlexey Dobriyan  *
347fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
348fe9d4f57SAlexey Dobriyan  */
349fe9d4f57SAlexey Dobriyan int raw_notifier_chain_register(struct raw_notifier_head *nh,
350fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
351fe9d4f57SAlexey Dobriyan {
352fe9d4f57SAlexey Dobriyan 	return notifier_chain_register(&nh->head, n);
353fe9d4f57SAlexey Dobriyan }
354fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_register);
355fe9d4f57SAlexey Dobriyan 
356fe9d4f57SAlexey Dobriyan /**
357fe9d4f57SAlexey Dobriyan  *	raw_notifier_chain_unregister - Remove notifier from a raw notifier chain
358fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
359fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
360fe9d4f57SAlexey Dobriyan  *
361fe9d4f57SAlexey Dobriyan  *	Removes a notifier from a raw notifier chain.
362fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
363fe9d4f57SAlexey Dobriyan  *
364fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
365fe9d4f57SAlexey Dobriyan  */
366fe9d4f57SAlexey Dobriyan int raw_notifier_chain_unregister(struct raw_notifier_head *nh,
367fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
368fe9d4f57SAlexey Dobriyan {
369fe9d4f57SAlexey Dobriyan 	return notifier_chain_unregister(&nh->head, n);
370fe9d4f57SAlexey Dobriyan }
371fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister);
372fe9d4f57SAlexey Dobriyan 
373fe9d4f57SAlexey Dobriyan /**
374fe9d4f57SAlexey Dobriyan  *	__raw_notifier_call_chain - Call functions in a raw notifier chain
375fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the raw notifier chain
376fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
377fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
378fe9d4f57SAlexey Dobriyan  *	@nr_to_call: See comment for notifier_call_chain.
379fe9d4f57SAlexey Dobriyan  *	@nr_calls: See comment for notifier_call_chain
380fe9d4f57SAlexey Dobriyan  *
381fe9d4f57SAlexey Dobriyan  *	Calls each function in a notifier chain in turn.  The functions
382fe9d4f57SAlexey Dobriyan  *	run in an undefined context.
383fe9d4f57SAlexey Dobriyan  *	All locking must be provided by the caller.
384fe9d4f57SAlexey Dobriyan  *
385fe9d4f57SAlexey Dobriyan  *	If the return value of the notifier can be and'ed
386fe9d4f57SAlexey Dobriyan  *	with %NOTIFY_STOP_MASK then raw_notifier_call_chain()
387fe9d4f57SAlexey Dobriyan  *	will return immediately, with the return value of
388fe9d4f57SAlexey Dobriyan  *	the notifier function which halted execution.
389fe9d4f57SAlexey Dobriyan  *	Otherwise the return value is the return value
390fe9d4f57SAlexey Dobriyan  *	of the last notifier function called.
391fe9d4f57SAlexey Dobriyan  */
392fe9d4f57SAlexey Dobriyan int __raw_notifier_call_chain(struct raw_notifier_head *nh,
393fe9d4f57SAlexey Dobriyan 			      unsigned long val, void *v,
394fe9d4f57SAlexey Dobriyan 			      int nr_to_call, int *nr_calls)
395fe9d4f57SAlexey Dobriyan {
396fe9d4f57SAlexey Dobriyan 	return notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
397fe9d4f57SAlexey Dobriyan }
398fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(__raw_notifier_call_chain);
399fe9d4f57SAlexey Dobriyan 
400fe9d4f57SAlexey Dobriyan int raw_notifier_call_chain(struct raw_notifier_head *nh,
401fe9d4f57SAlexey Dobriyan 		unsigned long val, void *v)
402fe9d4f57SAlexey Dobriyan {
403fe9d4f57SAlexey Dobriyan 	return __raw_notifier_call_chain(nh, val, v, -1, NULL);
404fe9d4f57SAlexey Dobriyan }
405fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_call_chain);
406fe9d4f57SAlexey Dobriyan 
40783fe27eaSPranith Kumar #ifdef CONFIG_SRCU
408fe9d4f57SAlexey Dobriyan /*
409fe9d4f57SAlexey Dobriyan  *	SRCU notifier chain routines.    Registration and unregistration
410fe9d4f57SAlexey Dobriyan  *	use a mutex, and call_chain is synchronized by SRCU (no locks).
411fe9d4f57SAlexey Dobriyan  */
412fe9d4f57SAlexey Dobriyan 
413fe9d4f57SAlexey Dobriyan /**
414fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_register - Add notifier to an SRCU notifier chain
415fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
416fe9d4f57SAlexey Dobriyan  *	@n: New entry in notifier chain
417fe9d4f57SAlexey Dobriyan  *
418fe9d4f57SAlexey Dobriyan  *	Adds a notifier to an SRCU notifier chain.
419fe9d4f57SAlexey Dobriyan  *	Must be called in process context.
420fe9d4f57SAlexey Dobriyan  *
421fe9d4f57SAlexey Dobriyan  *	Currently always returns zero.
422fe9d4f57SAlexey Dobriyan  */
423fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_register(struct srcu_notifier_head *nh,
424fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
425fe9d4f57SAlexey Dobriyan {
426fe9d4f57SAlexey Dobriyan 	int ret;
427fe9d4f57SAlexey Dobriyan 
428fe9d4f57SAlexey Dobriyan 	/*
429fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
430fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
431fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
432fe9d4f57SAlexey Dobriyan 	 */
433fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
434fe9d4f57SAlexey Dobriyan 		return notifier_chain_register(&nh->head, n);
435fe9d4f57SAlexey Dobriyan 
436fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
437fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_register(&nh->head, n);
438fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
439fe9d4f57SAlexey Dobriyan 	return ret;
440fe9d4f57SAlexey Dobriyan }
441fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_register);
442fe9d4f57SAlexey Dobriyan 
443fe9d4f57SAlexey Dobriyan /**
444fe9d4f57SAlexey Dobriyan  *	srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain
445fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
446fe9d4f57SAlexey Dobriyan  *	@n: Entry to remove from notifier chain
447fe9d4f57SAlexey Dobriyan  *
448fe9d4f57SAlexey Dobriyan  *	Removes a notifier from an SRCU notifier chain.
449fe9d4f57SAlexey Dobriyan  *	Must be called from process context.
450fe9d4f57SAlexey Dobriyan  *
451fe9d4f57SAlexey Dobriyan  *	Returns zero on success or %-ENOENT on failure.
452fe9d4f57SAlexey Dobriyan  */
453fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh,
454fe9d4f57SAlexey Dobriyan 		struct notifier_block *n)
455fe9d4f57SAlexey Dobriyan {
456fe9d4f57SAlexey Dobriyan 	int ret;
457fe9d4f57SAlexey Dobriyan 
458fe9d4f57SAlexey Dobriyan 	/*
459fe9d4f57SAlexey Dobriyan 	 * This code gets used during boot-up, when task switching is
460fe9d4f57SAlexey Dobriyan 	 * not yet working and interrupts must remain disabled.  At
461fe9d4f57SAlexey Dobriyan 	 * such times we must not call mutex_lock().
462fe9d4f57SAlexey Dobriyan 	 */
463fe9d4f57SAlexey Dobriyan 	if (unlikely(system_state == SYSTEM_BOOTING))
464fe9d4f57SAlexey Dobriyan 		return notifier_chain_unregister(&nh->head, n);
465fe9d4f57SAlexey Dobriyan 
466fe9d4f57SAlexey Dobriyan 	mutex_lock(&nh->mutex);
467fe9d4f57SAlexey Dobriyan 	ret = notifier_chain_unregister(&nh->head, n);
468fe9d4f57SAlexey Dobriyan 	mutex_unlock(&nh->mutex);
469fe9d4f57SAlexey Dobriyan 	synchronize_srcu(&nh->srcu);
470fe9d4f57SAlexey Dobriyan 	return ret;
471fe9d4f57SAlexey Dobriyan }
472fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister);
473fe9d4f57SAlexey Dobriyan 
474fe9d4f57SAlexey Dobriyan /**
475fe9d4f57SAlexey Dobriyan  *	__srcu_notifier_call_chain - Call functions in an SRCU notifier chain
476fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the SRCU notifier chain
477fe9d4f57SAlexey Dobriyan  *	@val: Value passed unmodified to notifier function
478fe9d4f57SAlexey Dobriyan  *	@v: Pointer passed unmodified to notifier function
479fe9d4f57SAlexey Dobriyan  *	@nr_to_call: See comment for notifier_call_chain.
480fe9d4f57SAlexey Dobriyan  *	@nr_calls: See comment for notifier_call_chain
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  */
492fe9d4f57SAlexey Dobriyan int __srcu_notifier_call_chain(struct srcu_notifier_head *nh,
493fe9d4f57SAlexey Dobriyan 			       unsigned long val, void *v,
494fe9d4f57SAlexey Dobriyan 			       int nr_to_call, int *nr_calls)
495fe9d4f57SAlexey Dobriyan {
496fe9d4f57SAlexey Dobriyan 	int ret;
497fe9d4f57SAlexey Dobriyan 	int idx;
498fe9d4f57SAlexey Dobriyan 
499fe9d4f57SAlexey Dobriyan 	idx = srcu_read_lock(&nh->srcu);
500fe9d4f57SAlexey Dobriyan 	ret = notifier_call_chain(&nh->head, val, v, nr_to_call, nr_calls);
501fe9d4f57SAlexey Dobriyan 	srcu_read_unlock(&nh->srcu, idx);
502fe9d4f57SAlexey Dobriyan 	return ret;
503fe9d4f57SAlexey Dobriyan }
504fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(__srcu_notifier_call_chain);
505fe9d4f57SAlexey Dobriyan 
506fe9d4f57SAlexey Dobriyan int srcu_notifier_call_chain(struct srcu_notifier_head *nh,
507fe9d4f57SAlexey Dobriyan 		unsigned long val, void *v)
508fe9d4f57SAlexey Dobriyan {
509fe9d4f57SAlexey Dobriyan 	return __srcu_notifier_call_chain(nh, val, v, -1, NULL);
510fe9d4f57SAlexey Dobriyan }
511fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_call_chain);
512fe9d4f57SAlexey Dobriyan 
513fe9d4f57SAlexey Dobriyan /**
514fe9d4f57SAlexey Dobriyan  *	srcu_init_notifier_head - Initialize an SRCU notifier head
515fe9d4f57SAlexey Dobriyan  *	@nh: Pointer to head of the srcu notifier chain
516fe9d4f57SAlexey Dobriyan  *
517fe9d4f57SAlexey Dobriyan  *	Unlike other sorts of notifier heads, SRCU notifier heads require
518fe9d4f57SAlexey Dobriyan  *	dynamic initialization.  Be sure to call this routine before
519fe9d4f57SAlexey Dobriyan  *	calling any of the other SRCU notifier routines for this head.
520fe9d4f57SAlexey Dobriyan  *
521fe9d4f57SAlexey Dobriyan  *	If an SRCU notifier head is deallocated, it must first be cleaned
522fe9d4f57SAlexey Dobriyan  *	up by calling srcu_cleanup_notifier_head().  Otherwise the head's
523fe9d4f57SAlexey Dobriyan  *	per-cpu data (used by the SRCU mechanism) will leak.
524fe9d4f57SAlexey Dobriyan  */
525fe9d4f57SAlexey Dobriyan void srcu_init_notifier_head(struct srcu_notifier_head *nh)
526fe9d4f57SAlexey Dobriyan {
527fe9d4f57SAlexey Dobriyan 	mutex_init(&nh->mutex);
528fe9d4f57SAlexey Dobriyan 	if (init_srcu_struct(&nh->srcu) < 0)
529fe9d4f57SAlexey Dobriyan 		BUG();
530fe9d4f57SAlexey Dobriyan 	nh->head = NULL;
531fe9d4f57SAlexey Dobriyan }
532fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_init_notifier_head);
533fe9d4f57SAlexey Dobriyan 
53483fe27eaSPranith Kumar #endif /* CONFIG_SRCU */
53583fe27eaSPranith Kumar 
536fe9d4f57SAlexey Dobriyan static ATOMIC_NOTIFIER_HEAD(die_chain);
537fe9d4f57SAlexey Dobriyan 
538b40a2cb6SMasami Hiramatsu int notrace notify_die(enum die_val val, const char *str,
539fe9d4f57SAlexey Dobriyan 	       struct pt_regs *regs, long err, int trap, int sig)
540fe9d4f57SAlexey Dobriyan {
541fe9d4f57SAlexey Dobriyan 	struct die_args args = {
542fe9d4f57SAlexey Dobriyan 		.regs	= regs,
543fe9d4f57SAlexey Dobriyan 		.str	= str,
544fe9d4f57SAlexey Dobriyan 		.err	= err,
545fe9d4f57SAlexey Dobriyan 		.trapnr	= trap,
546fe9d4f57SAlexey Dobriyan 		.signr	= sig,
547fe9d4f57SAlexey Dobriyan 
548fe9d4f57SAlexey Dobriyan 	};
5495778077dSLinus Torvalds 	RCU_LOCKDEP_WARN(!rcu_is_watching(),
550e727c7d7SAndy Lutomirski 			   "notify_die called but RCU thinks we're quiescent");
551fe9d4f57SAlexey Dobriyan 	return atomic_notifier_call_chain(&die_chain, val, &args);
552fe9d4f57SAlexey Dobriyan }
553b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notify_die);
554fe9d4f57SAlexey Dobriyan 
555fe9d4f57SAlexey Dobriyan int register_die_notifier(struct notifier_block *nb)
556fe9d4f57SAlexey Dobriyan {
557fe9d4f57SAlexey Dobriyan 	vmalloc_sync_all();
558fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_register(&die_chain, nb);
559fe9d4f57SAlexey Dobriyan }
560fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(register_die_notifier);
561fe9d4f57SAlexey Dobriyan 
562fe9d4f57SAlexey Dobriyan int unregister_die_notifier(struct notifier_block *nb)
563fe9d4f57SAlexey Dobriyan {
564fe9d4f57SAlexey Dobriyan 	return atomic_notifier_chain_unregister(&die_chain, nb);
565fe9d4f57SAlexey Dobriyan }
566fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(unregister_die_notifier);
567