static u64 wd_timer_period_ms __read_mostly;  /* interval between heartbeat */
 
-static DEFINE_PER_CPU(struct timer_list, wd_timer);
+static DEFINE_PER_CPU(struct hrtimer, wd_hrtimer);
 static DEFINE_PER_CPU(u64, wd_timer_tb);
 
 /* SMP checker bits */
        nmi_exit();
 }
 
-static void wd_timer_reset(unsigned int cpu, struct timer_list *t)
-{
-       t->expires = jiffies + msecs_to_jiffies(wd_timer_period_ms);
-       if (wd_timer_period_ms > 1000)
-               t->expires = __round_jiffies_up(t->expires, cpu);
-       add_timer_on(t, cpu);
-}
-
-static void wd_timer_fn(struct timer_list *t)
+static enum hrtimer_restart watchdog_timer_fn(struct hrtimer *hrtimer)
 {
        int cpu = smp_processor_id();
 
+       if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
+               return HRTIMER_NORESTART;
+
+       if (!cpumask_test_cpu(cpu, &watchdog_cpumask))
+               return HRTIMER_NORESTART;
+
        watchdog_timer_interrupt(cpu);
 
-       wd_timer_reset(cpu, t);
+       hrtimer_forward_now(hrtimer, ms_to_ktime(wd_timer_period_ms));
+
+       return HRTIMER_RESTART;
 }
 
 void arch_touch_nmi_watchdog(void)
 }
 EXPORT_SYMBOL(arch_touch_nmi_watchdog);
 
-static void start_watchdog_timer_on(unsigned int cpu)
-{
-       struct timer_list *t = per_cpu_ptr(&wd_timer, cpu);
-
-       per_cpu(wd_timer_tb, cpu) = get_tb();
-
-       timer_setup(t, wd_timer_fn, TIMER_PINNED);
-       wd_timer_reset(cpu, t);
-}
-
-static void stop_watchdog_timer_on(unsigned int cpu)
-{
-       struct timer_list *t = per_cpu_ptr(&wd_timer, cpu);
-
-       del_timer_sync(t);
-}
-
-static int start_wd_on_cpu(unsigned int cpu)
+static void start_watchdog(void *arg)
 {
+       struct hrtimer *hrtimer = this_cpu_ptr(&wd_hrtimer);
+       int cpu = smp_processor_id();
        unsigned long flags;
 
        if (cpumask_test_cpu(cpu, &wd_cpus_enabled)) {
                WARN_ON(1);
-               return 0;
+               return;
        }
 
        if (!(watchdog_enabled & NMI_WATCHDOG_ENABLED))
-               return 0;
+               return;
 
        if (!cpumask_test_cpu(cpu, &watchdog_cpumask))
-               return 0;
+               return;
 
        wd_smp_lock(&flags);
        cpumask_set_cpu(cpu, &wd_cpus_enabled);
        }
        wd_smp_unlock(&flags);
 
-       start_watchdog_timer_on(cpu);
+       *this_cpu_ptr(&wd_timer_tb) = get_tb();
 
-       return 0;
+       hrtimer_init(hrtimer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+       hrtimer->function = watchdog_timer_fn;
+       hrtimer_start(hrtimer, ms_to_ktime(wd_timer_period_ms),
+                     HRTIMER_MODE_REL_PINNED);
 }
 
-static int stop_wd_on_cpu(unsigned int cpu)
+static int start_watchdog_on_cpu(unsigned int cpu)
 {
+       return smp_call_function_single(cpu, start_watchdog, NULL, true);
+}
+
+static void stop_watchdog(void *arg)
+{
+       struct hrtimer *hrtimer = this_cpu_ptr(&wd_hrtimer);
+       int cpu = smp_processor_id();
        unsigned long flags;
 
        if (!cpumask_test_cpu(cpu, &wd_cpus_enabled))
-               return 0; /* Can happen in CPU unplug case */
+               return; /* Can happen in CPU unplug case */
 
-       stop_watchdog_timer_on(cpu);
+       hrtimer_cancel(hrtimer);
 
        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;
+static int stop_watchdog_on_cpu(unsigned int cpu)
+{
+       return smp_call_function_single(cpu, stop_watchdog, NULL, true);
 }
 
 static void watchdog_calc_timeouts(void)
        int cpu;
 
        for_each_cpu(cpu, &wd_cpus_enabled)
-               stop_wd_on_cpu(cpu);
+               stop_watchdog_on_cpu(cpu);
 }
 
 void watchdog_nmi_start(void)
 
        watchdog_calc_timeouts();
        for_each_cpu_and(cpu, cpu_online_mask, &watchdog_cpumask)
-               start_wd_on_cpu(cpu);
+               start_watchdog_on_cpu(cpu);
 }
 
 /*
 
        err = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE_DYN,
                                        "powerpc/watchdog:online",
-                                       start_wd_on_cpu, stop_wd_on_cpu);
+                                       start_watchdog_on_cpu,
+                                       stop_watchdog_on_cpu);
        if (err < 0) {
                pr_warn("could not be initialized");
                return err;