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