Implement the initial configuration of the timer to be used by the hardlockup detector. Return a data structure with a description of the timer; this information is subsequently used by the hardlockup detector.
Only provide the timer if it supports Front Side Bus interrupt delivery. This condition greatly simplifies the implementation of the detector. Cc: "H. Peter Anvin" <[email protected]> Cc: Ashok Raj <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Tony Luck <[email protected]> Cc: Clemens Ladisch <[email protected]> Cc: Arnd Bergmann <[email protected]> Cc: Philippe Ombredanne <[email protected]> Cc: Kate Stewart <[email protected]> Cc: "Rafael J. Wysocki" <[email protected]> Cc: "Ravi V. Shankar" <[email protected]> Cc: [email protected] Signed-off-by: Ricardo Neri <[email protected]> --- arch/x86/include/asm/hpet.h | 13 +++++++++++++ arch/x86/kernel/hpet.c | 27 +++++++++++++++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/arch/x86/include/asm/hpet.h b/arch/x86/include/asm/hpet.h index 9fd112a0ffdd..4d559e0c746f 100644 --- a/arch/x86/include/asm/hpet.h +++ b/arch/x86/include/asm/hpet.h @@ -118,6 +118,19 @@ extern void hpet_unregister_irq_handler(rtc_irq_handler handler); #endif /* CONFIG_HPET_EMULATE_RTC */ +#ifdef CONFIG_X86_HARDLOCKUP_DETECTOR_HPET +struct hpet_hld_data { + u32 num; + u32 flags; + u64 ticks_per_second; +}; + +extern struct hpet_hld_data *hpet_hardlockup_detector_assign_timer(void); +#else +static inline struct hpet_hld_data *hpet_hardlockup_detector_assign_timer(void) +{ return NULL; } +#endif /* CONFIG_X86_HARDLOCKUP_DETECTOR_HPET */ + #else /* CONFIG_HPET_TIMER */ static inline int hpet_enable(void) { return 0; } diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c index 1c5c63366109..923b8061e815 100644 --- a/arch/x86/kernel/hpet.c +++ b/arch/x86/kernel/hpet.c @@ -174,6 +174,33 @@ do { \ _hpet_print_config(__func__, __LINE__); \ } while (0) +#ifdef CONFIG_X86_HARDLOCKUP_DETECTOR_HPET +struct hpet_hld_data *hpet_hardlockup_detector_assign_timer(void) +{ + struct hpet_hld_data *hdata; + unsigned int cfg; + + cfg = hpet_readl(HPET_Tn_CFG(HPET_WD_TIMER_NR)); + + if (!(cfg & HPET_TN_FSB_CAP)) + return NULL; + + hdata = kzalloc(sizeof(*hdata), GFP_KERNEL); + if (!hdata) + return NULL; + + hdata->flags = HPET_DEV_FSB_CAP; + + if (cfg & HPET_TN_PERIODIC_CAP) + hdata->flags |= HPET_DEV_PERI_CAP; + + hdata->num = HPET_WD_TIMER_NR; + hdata->ticks_per_second = hpet_get_ticks_per_sec(hpet_readq(HPET_ID)); + + return hdata; +} +#endif /* CONFIG_X86_HARDLOCKUP_DETECTOR_HPET */ + /* * When the hpet driver (/dev/hpet) is enabled, we need to reserve * timer 0 and timer 1 in case of RTC emulation. Timer 2 is reserved in case -- 2.17.1

