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