Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 34ddaa3e authored by Thomas Gleixner's avatar Thomas Gleixner
Browse files

powerpc/watchdog: Make use of watchdog_nmi_probe()



The rework of the core hotplug code triggers the WARN_ON in start_wd_cpu()
on powerpc because it is called multiple times for the boot CPU.

The first call is via:

  start_wd_on_cpu+0x80/0x2f0
  watchdog_nmi_reconfigure+0x124/0x170
  softlockup_reconfigure_threads+0x110/0x130
  lockup_detector_init+0xbc/0xe0
  kernel_init_freeable+0x18c/0x37c
  kernel_init+0x2c/0x160
  ret_from_kernel_thread+0x5c/0xbc

And then again via the CPU hotplug registration:

  start_wd_on_cpu+0x80/0x2f0
  cpuhp_invoke_callback+0x194/0x620
  cpuhp_thread_fun+0x7c/0x1b0
  smpboot_thread_fn+0x290/0x2a0
  kthread+0x168/0x1b0
  ret_from_kernel_thread+0x5c/0xbc

This can be avoided by setting up the cpu hotplug state with nocalls and
move the initialization to the watchdog_nmi_probe() function. That
initializes the hotplug callbacks without invoking the callback and the
following core initialization function then configures the watchdog for the
online CPUs (in this case CPU0) via softlockup_reconfigure_threads().

Reported-and-tested-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Acked-by: default avatarMichael Ellerman <mpe@ellerman.id.au>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: linuxppc-dev@lists.ozlabs.org
parent e31d6883
Loading
Loading
Loading
Loading
+8 −9
Original line number Diff line number Diff line
@@ -373,22 +373,21 @@ void watchdog_nmi_start(void)
}

/*
 * This runs after lockup_detector_init() which sets up watchdog_cpumask.
 * Invoked from core watchdog init.
 */
static int __init powerpc_watchdog_init(void)
int __init watchdog_nmi_probe(void)
{
	int err;

	watchdog_calc_timeouts();

	err = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "powerpc/watchdog:online",
	err = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
					"powerpc/watchdog:online",
					start_wd_on_cpu, stop_wd_on_cpu);
	if (err < 0)
	if (err < 0) {
		pr_warn("Watchdog could not be initialized");

		return err;
	}
	return 0;
}
arch_initcall(powerpc_watchdog_init);

static void handle_backtrace_ipi(struct pt_regs *regs)
{
+1 −0
Original line number Diff line number Diff line
@@ -111,6 +111,7 @@ static inline int hardlockup_detector_perf_init(void) { return 0; }

void watchdog_nmi_stop(void);
void watchdog_nmi_start(void);
int watchdog_nmi_probe(void);

/**
 * touch_nmi_watchdog - restart NMI watchdog timeout.
+4 −1
Original line number Diff line number Diff line
@@ -608,7 +608,6 @@ static inline int watchdog_park_threads(void) { return 0; }
static inline void watchdog_unpark_threads(void) { }
static inline int watchdog_enable_all_cpus(void) { return 0; }
static inline void watchdog_disable_all_cpus(void) { }
static inline void softlockup_init_threads(void) { }
static void softlockup_reconfigure_threads(void)
{
	cpus_read_lock();
@@ -617,6 +616,10 @@ static void softlockup_reconfigure_threads(void)
	watchdog_nmi_start();
	cpus_read_unlock();
}
static inline void softlockup_init_threads(void)
{
	softlockup_reconfigure_threads();
}
#endif /* !CONFIG_SOFTLOCKUP_DETECTOR */

static void __lockup_detector_cleanup(void)