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