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