OpenCores
URL https://opencores.org/ocsvn/or1k_soc_on_altera_embedded_dev_kit/or1k_soc_on_altera_embedded_dev_kit/trunk

Subversion Repositories or1k_soc_on_altera_embedded_dev_kit

[/] [or1k_soc_on_altera_embedded_dev_kit/] [tags/] [linux-2.6/] [linux-2.6.24_orig/] [kernel/] [notifier.c] - Blame information for rev 8

Go to most recent revision | Details | Compare with Previous | View Log

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

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.