Skip to content

Commit

Permalink
powerpc/watchdog: Make use of watchdog_nmi_probe()
Browse files Browse the repository at this point in the history
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: Michael Ellerman <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Acked-by: Michael Ellerman <[email protected]>
Cc: Benjamin Herrenschmidt <[email protected]>
Cc: Nicholas Piggin <[email protected]>
Cc: [email protected]
  • Loading branch information
KAGA-KOKO committed Oct 4, 2017
1 parent e31d688 commit 34ddaa3
Show file tree
Hide file tree
Showing 3 changed files with 13 additions and 10 deletions.
17 changes: 8 additions & 9 deletions arch/powerpc/kernel/watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -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",
start_wd_on_cpu, stop_wd_on_cpu);
if (err < 0)
err = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
"powerpc/watchdog:online",
start_wd_on_cpu, stop_wd_on_cpu);
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)
{
Expand Down
1 change: 1 addition & 0 deletions include/linux/nmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
5 changes: 4 additions & 1 deletion kernel/watchdog.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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)
Expand Down

0 comments on commit 34ddaa3

Please sign in to comment.