···114114 BUG();115115}116116117117-static void null_restart(enum reboot_mode reboot_mode, const char *cmd)118118-{119119-}120120-121117/*122118 * Function pointers to optional machine specific functions123119 */124120void (*pm_power_off)(void);125121EXPORT_SYMBOL(pm_power_off);126122127127-void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd) = null_restart;128128-EXPORT_SYMBOL_GPL(arm_pm_restart);123123+void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);129124130125/*131126 * This is our default idle handler.···225230 local_irq_disable();226231 smp_send_stop();227232228228- arm_pm_restart(reboot_mode, cmd);233233+ if (arm_pm_restart)234234+ arm_pm_restart(reboot_mode, cmd);235235+ else236236+ do_kernel_restart(cmd);229237230238 /* Give a grace period for failure to restart of 1s */231239 mdelay(1000);
+2-1
arch/arm64/kernel/process.c
···9898EXPORT_SYMBOL_GPL(pm_power_off);9999100100void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);101101-EXPORT_SYMBOL_GPL(arm_pm_restart);102101103102/*104103 * This is our default idle handler.···179180 /* Now call the architecture specific reboot code. */180181 if (arm_pm_restart)181182 arm_pm_restart(reboot_mode, cmd);183183+ else184184+ do_kernel_restart(cmd);182185183186 /*184187 * Whoops - the architecture was unable to reboot.
···301301 .fops = &wdt_fops,302302};303303304304+static int wdt_restart_handle(struct notifier_block *this, unsigned long mode,305305+ void *cmd)306306+{307307+ /*308308+ * Cobalt devices have no way of rebooting themselves other309309+ * than getting the watchdog to pull reset, so we restart the310310+ * watchdog on reboot with no heartbeat.311311+ */312312+ wdt_change(WDT_ENABLE);313313+314314+ /* loop until the watchdog fires */315315+ while (true)316316+ ;317317+318318+ return NOTIFY_DONE;319319+}320320+321321+static struct notifier_block wdt_restart_handler = {322322+ .notifier_call = wdt_restart_handle,323323+ .priority = 128,324324+};325325+304326/*305327 * Notifier for system down306328 */···333311 if (code == SYS_DOWN || code == SYS_HALT)334312 wdt_turnoff();335313336336- if (code == SYS_RESTART) {337337- /*338338- * Cobalt devices have no way of rebooting themselves other339339- * than getting the watchdog to pull reset, so we restart the340340- * watchdog on reboot with no heartbeat341341- */342342- wdt_change(WDT_ENABLE);343343- pr_info("Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second\n");344344- }345314 return NOTIFY_DONE;346315}347316···351338 /* Deregister */352339 misc_deregister(&wdt_miscdev);353340 unregister_reboot_notifier(&wdt_notifier);341341+ unregister_restart_handler(&wdt_restart_handler);354342 pci_dev_put(alim7101_pmu);355343}356344···404390 goto err_out;405391 }406392393393+ rc = register_restart_handler(&wdt_restart_handler);394394+ if (rc) {395395+ pr_err("cannot register restart handler (err=%d)\n", rc);396396+ goto err_out_reboot;397397+ }398398+407399 rc = misc_register(&wdt_miscdev);408400 if (rc) {409401 pr_err("cannot register miscdev on minor=%d (err=%d)\n",410402 wdt_miscdev.minor, rc);411411- goto err_out_reboot;403403+ goto err_out_restart;412404 }413405414406 if (nowayout)···424404 timeout, nowayout);425405 return 0;426406407407+err_out_restart:408408+ unregister_restart_handler(&wdt_restart_handler);427409err_out_reboot:428410 unregister_reboot_notifier(&wdt_notifier);429411err_out:
···3838extern int register_reboot_notifier(struct notifier_block *);3939extern int unregister_reboot_notifier(struct notifier_block *);40404141+extern int register_restart_handler(struct notifier_block *);4242+extern int unregister_restart_handler(struct notifier_block *);4343+extern void do_kernel_restart(char *cmd);41444245/*4346 * Architecture-specific implementations of sys_reboot commands.
+81
kernel/reboot.c
···104104}105105EXPORT_SYMBOL(unregister_reboot_notifier);106106107107+/*108108+ * Notifier list for kernel code which wants to be called109109+ * to restart the system.110110+ */111111+static ATOMIC_NOTIFIER_HEAD(restart_handler_list);112112+113113+/**114114+ * register_restart_handler - Register function to be called to reset115115+ * the system116116+ * @nb: Info about handler function to be called117117+ * @nb->priority: Handler priority. Handlers should follow the118118+ * following guidelines for setting priorities.119119+ * 0: Restart handler of last resort,120120+ * with limited restart capabilities121121+ * 128: Default restart handler; use if no other122122+ * restart handler is expected to be available,123123+ * and/or if restart functionality is124124+ * sufficient to restart the entire system125125+ * 255: Highest priority restart handler, will126126+ * preempt all other restart handlers127127+ *128128+ * Registers a function with code to be called to restart the129129+ * system.130130+ *131131+ * Registered functions will be called from machine_restart as last132132+ * step of the restart sequence (if the architecture specific133133+ * machine_restart function calls do_kernel_restart - see below134134+ * for details).135135+ * Registered functions are expected to restart the system immediately.136136+ * If more than one function is registered, the restart handler priority137137+ * selects which function will be called first.138138+ *139139+ * Restart handlers are expected to be registered from non-architecture140140+ * code, typically from drivers. A typical use case would be a system141141+ * where restart functionality is provided through a watchdog. Multiple142142+ * restart handlers may exist; for example, one restart handler might143143+ * restart the entire system, while another only restarts the CPU.144144+ * In such cases, the restart handler which only restarts part of the145145+ * hardware is expected to register with low priority to ensure that146146+ * it only runs if no other means to restart the system is available.147147+ *148148+ * Currently always returns zero, as atomic_notifier_chain_register()149149+ * always returns zero.150150+ */151151+int register_restart_handler(struct notifier_block *nb)152152+{153153+ return atomic_notifier_chain_register(&restart_handler_list, nb);154154+}155155+EXPORT_SYMBOL(register_restart_handler);156156+157157+/**158158+ * unregister_restart_handler - Unregister previously registered159159+ * restart handler160160+ * @nb: Hook to be unregistered161161+ *162162+ * Unregisters a previously registered restart handler function.163163+ *164164+ * Returns zero on success, or %-ENOENT on failure.165165+ */166166+int unregister_restart_handler(struct notifier_block *nb)167167+{168168+ return atomic_notifier_chain_unregister(&restart_handler_list, nb);169169+}170170+EXPORT_SYMBOL(unregister_restart_handler);171171+172172+/**173173+ * do_kernel_restart - Execute kernel restart handler call chain174174+ *175175+ * Calls functions registered with register_restart_handler.176176+ *177177+ * Expected to be called from machine_restart as last step of the restart178178+ * sequence.179179+ *180180+ * Restarts the system immediately if a restart handler function has been181181+ * registered. Otherwise does nothing.182182+ */183183+void do_kernel_restart(char *cmd)184184+{185185+ atomic_notifier_call_chain(&restart_handler_list, reboot_mode, cmd);186186+}187187+107188void migrate_to_reboot_cpu(void)108189{109190 /* The boot cpu is always logical cpu 0 */