diff options
author | Sebastian Andrzej Siewior <bigeasy@linutronix.de> | 2016-11-17 13:35:32 -0500 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-11-22 17:34:40 -0500 |
commit | 948b9c60cb3e044ed4a56fd170ef0d0617ab840f (patch) | |
tree | af96cace590fcaae8e47259d6f9b3f4616365811 | |
parent | 9c248f8896e6bf0c77abb98bfea8d69b5a7cd11d (diff) |
watchdog/octeon: Convert to hotplug state machine
Install the callbacks via the state machine and let the core invoke
the callbacks on the already online CPUs.
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Cc: Wim Van Sebroeck <wim@iguana.be>
Cc: rt@linuxtronix.de
Cc: Guenter Roeck <linux@roeck-us.net>
Cc: linux-watchdog@vger.kernel.org
Link: http://lkml.kernel.org/r/20161117183541.8588-12-bigeasy@linutronix.de
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
-rw-r--r-- | drivers/watchdog/octeon-wdt-main.c | 62 |
1 files changed, 15 insertions, 47 deletions
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c index b55981f88a08..529182d7d8a7 100644 --- a/drivers/watchdog/octeon-wdt-main.c +++ b/drivers/watchdog/octeon-wdt-main.c | |||
@@ -374,7 +374,7 @@ void octeon_wdt_nmi_stage3(u64 reg[32]) | |||
374 | octeon_wdt_write_string("*** Chip soft reset soon ***\r\n"); | 374 | octeon_wdt_write_string("*** Chip soft reset soon ***\r\n"); |
375 | } | 375 | } |
376 | 376 | ||
377 | static void octeon_wdt_disable_interrupt(int cpu) | 377 | static int octeon_wdt_cpu_pre_down(unsigned int cpu) |
378 | { | 378 | { |
379 | unsigned int core; | 379 | unsigned int core; |
380 | unsigned int irq; | 380 | unsigned int irq; |
@@ -392,9 +392,10 @@ static void octeon_wdt_disable_interrupt(int cpu) | |||
392 | cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); | 392 | cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); |
393 | 393 | ||
394 | free_irq(irq, octeon_wdt_poke_irq); | 394 | free_irq(irq, octeon_wdt_poke_irq); |
395 | return 0; | ||
395 | } | 396 | } |
396 | 397 | ||
397 | static void octeon_wdt_setup_interrupt(int cpu) | 398 | static int octeon_wdt_cpu_online(unsigned int cpu) |
398 | { | 399 | { |
399 | unsigned int core; | 400 | unsigned int core; |
400 | unsigned int irq; | 401 | unsigned int irq; |
@@ -424,25 +425,8 @@ static void octeon_wdt_setup_interrupt(int cpu) | |||
424 | ciu_wdog.s.len = timeout_cnt; | 425 | ciu_wdog.s.len = timeout_cnt; |
425 | ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */ | 426 | ciu_wdog.s.mode = 3; /* 3 = Interrupt + NMI + Soft-Reset */ |
426 | cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); | 427 | cvmx_write_csr(CVMX_CIU_WDOGX(core), ciu_wdog.u64); |
427 | } | ||
428 | 428 | ||
429 | static int octeon_wdt_cpu_callback(struct notifier_block *nfb, | 429 | return 0; |
430 | unsigned long action, void *hcpu) | ||
431 | { | ||
432 | unsigned int cpu = (unsigned long)hcpu; | ||
433 | |||
434 | switch (action & ~CPU_TASKS_FROZEN) { | ||
435 | case CPU_DOWN_PREPARE: | ||
436 | octeon_wdt_disable_interrupt(cpu); | ||
437 | break; | ||
438 | case CPU_ONLINE: | ||
439 | case CPU_DOWN_FAILED: | ||
440 | octeon_wdt_setup_interrupt(cpu); | ||
441 | break; | ||
442 | default: | ||
443 | break; | ||
444 | } | ||
445 | return NOTIFY_OK; | ||
446 | } | 430 | } |
447 | 431 | ||
448 | static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog) | 432 | static int octeon_wdt_ping(struct watchdog_device __always_unused *wdog) |
@@ -531,10 +515,6 @@ static int octeon_wdt_stop(struct watchdog_device *wdog) | |||
531 | return 0; | 515 | return 0; |
532 | } | 516 | } |
533 | 517 | ||
534 | static struct notifier_block octeon_wdt_cpu_notifier = { | ||
535 | .notifier_call = octeon_wdt_cpu_callback, | ||
536 | }; | ||
537 | |||
538 | static const struct watchdog_info octeon_wdt_info = { | 518 | static const struct watchdog_info octeon_wdt_info = { |
539 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | 519 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, |
540 | .identity = "OCTEON", | 520 | .identity = "OCTEON", |
@@ -553,6 +533,7 @@ static struct watchdog_device octeon_wdt = { | |||
553 | .ops = &octeon_wdt_ops, | 533 | .ops = &octeon_wdt_ops, |
554 | }; | 534 | }; |
555 | 535 | ||
536 | static enum cpuhp_state octeon_wdt_online; | ||
556 | /** | 537 | /** |
557 | * Module/ driver initialization. | 538 | * Module/ driver initialization. |
558 | * | 539 | * |
@@ -562,7 +543,6 @@ static int __init octeon_wdt_init(void) | |||
562 | { | 543 | { |
563 | int i; | 544 | int i; |
564 | int ret; | 545 | int ret; |
565 | int cpu; | ||
566 | u64 *ptr; | 546 | u64 *ptr; |
567 | 547 | ||
568 | /* | 548 | /* |
@@ -610,14 +590,16 @@ static int __init octeon_wdt_init(void) | |||
610 | 590 | ||
611 | cpumask_clear(&irq_enabled_cpus); | 591 | cpumask_clear(&irq_enabled_cpus); |
612 | 592 | ||
613 | cpu_notifier_register_begin(); | 593 | ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, "watchdog/octeon:online", |
614 | for_each_online_cpu(cpu) | 594 | octeon_wdt_cpu_online, octeon_wdt_cpu_pre_down); |
615 | octeon_wdt_setup_interrupt(cpu); | 595 | if (ret < 0) |
616 | 596 | goto err; | |
617 | __register_hotcpu_notifier(&octeon_wdt_cpu_notifier); | 597 | octeon_wdt_online = ret; |
618 | cpu_notifier_register_done(); | ||
619 | |||
620 | return 0; | 598 | return 0; |
599 | err: | ||
600 | cvmx_write_csr(CVMX_MIO_BOOT_LOC_CFGX(0), 0); | ||
601 | watchdog_unregister_device(&octeon_wdt); | ||
602 | return ret; | ||
621 | } | 603 | } |
622 | 604 | ||
623 | /** | 605 | /** |
@@ -625,22 +607,8 @@ static int __init octeon_wdt_init(void) | |||
625 | */ | 607 | */ |
626 | static void __exit octeon_wdt_cleanup(void) | 608 | static void __exit octeon_wdt_cleanup(void) |
627 | { | 609 | { |
628 | int cpu; | ||
629 | |||
630 | watchdog_unregister_device(&octeon_wdt); | 610 | watchdog_unregister_device(&octeon_wdt); |
631 | 611 | cpuhp_remove_state(octeon_wdt_online); | |
632 | cpu_notifier_register_begin(); | ||
633 | __unregister_hotcpu_notifier(&octeon_wdt_cpu_notifier); | ||
634 | |||
635 | for_each_online_cpu(cpu) { | ||
636 | int core = cpu2core(cpu); | ||
637 | /* Disable the watchdog */ | ||
638 | cvmx_write_csr(CVMX_CIU_WDOGX(core), 0); | ||
639 | /* Free the interrupt handler */ | ||
640 | free_irq(OCTEON_IRQ_WDOG0 + core, octeon_wdt_poke_irq); | ||
641 | } | ||
642 | |||
643 | cpu_notifier_register_done(); | ||
644 | 612 | ||
645 | /* | 613 | /* |
646 | * Disable the boot-bus memory, the code it points to is soon | 614 | * Disable the boot-bus memory, the code it points to is soon |