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