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