aboutsummaryrefslogtreecommitdiff
path: root/arch/powerpc/kernel/watchdog.c
diff options
context:
space:
mode:
authorGravatar Nicholas Piggin <npiggin@gmail.com> 2017-08-09 22:41:26 +1000
committerGravatar Michael Ellerman <mpe@ellerman.id.au> 2017-08-09 23:45:33 +1000
commit96ea91e7b6ee2c406598d859e7348b4829404eea (patch)
tree571de7dd46c078978511f27a1db07fc3ec6c9f61 /arch/powerpc/kernel/watchdog.c
parentpowerpc/watchdog: Fix marking of stuck CPUs (diff)
downloadlinux-96ea91e7b6ee2c406598d859e7348b4829404eea.tar.gz
linux-96ea91e7b6ee2c406598d859e7348b4829404eea.tar.bz2
linux-96ea91e7b6ee2c406598d859e7348b4829404eea.zip
powerpc/watchdog: add locking around init/exit functions
When CPUs start and stop the watchdog, they manipulate shared data that is normally protected by the lock. Other CPUs can be running concurrently at this time, so it's a good idea to use locking here to be on the safe side. Remove the barrier which is undocumented and didn't do anything. Signed-off-by: Nicholas Piggin <npiggin@gmail.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/kernel/watchdog.c')
-rw-r--r--arch/powerpc/kernel/watchdog.c11
1 files changed, 10 insertions, 1 deletions
diff --git a/arch/powerpc/kernel/watchdog.c b/arch/powerpc/kernel/watchdog.c
index 12e90ae712fe..34721a257a77 100644
--- a/arch/powerpc/kernel/watchdog.c
+++ b/arch/powerpc/kernel/watchdog.c
@@ -297,6 +297,8 @@ static void stop_watchdog_timer_on(unsigned int cpu)
static int start_wd_on_cpu(unsigned int cpu)
{
+ unsigned long flags;
+
if (cpumask_test_cpu(cpu, &wd_cpus_enabled)) {
WARN_ON(1);
return 0;
@@ -311,12 +313,14 @@ static int start_wd_on_cpu(unsigned int cpu)
if (!cpumask_test_cpu(cpu, &watchdog_cpumask))
return 0;
+ wd_smp_lock(&flags);
cpumask_set_cpu(cpu, &wd_cpus_enabled);
if (cpumask_weight(&wd_cpus_enabled) == 1) {
cpumask_set_cpu(cpu, &wd_smp_cpus_pending);
wd_smp_last_reset_tb = get_tb();
}
- smp_wmb();
+ wd_smp_unlock(&flags);
+
start_watchdog_timer_on(cpu);
return 0;
@@ -324,12 +328,17 @@ static int start_wd_on_cpu(unsigned int cpu)
static int stop_wd_on_cpu(unsigned int cpu)
{
+ unsigned long flags;
+
if (!cpumask_test_cpu(cpu, &wd_cpus_enabled))
return 0; /* Can happen in CPU unplug case */
stop_watchdog_timer_on(cpu);
+ wd_smp_lock(&flags);
cpumask_clear_cpu(cpu, &wd_cpus_enabled);
+ wd_smp_unlock(&flags);
+
wd_smp_clear_cpu_pending(cpu, get_tb());
return 0;