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