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