On Wednesday, January 14, 2015 04:38:49 PM Muller, Francois-nicolas wrote: > From 54d2ff5e13c1b35d5019b82376dabb903ebe30d6 Mon Sep 17 00:00:00 2001 > From: Francois-Nicolas Muller <francois-nicolas.muller@xxxxxxxxx> > Date: Wed, 14 Jan 2015 14:27:43 +0100 > Subject: [PATCH] Adding TCO watchdog warning interrupt handling. > > This feature is useful to root cause watchdog expiration. > It is activated by boot parameter 'warn_irq' (disabled by default). > > Upon first expiration of the TCO watchdog, a warning interrupt is fired then the > interrupt handler dumps registers and call stack of all available cores. > > Finally panic() is called and notifies the panic handlers if any. At the same > time, the TCO watchdog reloads with 2.4 seconds timeout value. > > When warning interrupt is enabled, platform reboot depends on > CONFIG_PANIC_TIMEOUT value : > > - If CONFIG_PANIC_TIMEOUT is zero or greater than 3 seconds, TCO watchdog will > reset the platform if second expiration happens before TCO has been kicked > again. > > - If CONFIG_PANIC_TIMEOUT is < 0, platform will reboot immediately (emergency > restart procedure). > > - If CONFIG_PANIC_TIMEOUT is 1 or 2 seconds, platform will reboot after 1 or 2 > seconds delay (emergency restart procedure). > > Change-Id: I009c41f2f3dc3bd091b4d2a45b4ea0be85c8ce27 > Signed-off-by: Francois-Nicolas Muller <francois-nicolas.muller@xxxxxxxxx> > --- > drivers/watchdog/iTCO_wdt.c | 64 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 64 insertions(+) > > diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c > index e802a54..a8c16d2 100644 > --- a/drivers/watchdog/iTCO_wdt.c > +++ b/drivers/watchdog/iTCO_wdt.c > @@ -49,6 +49,8 @@ > /* Module and version information */ > #define DRV_NAME "iTCO_wdt" > #define DRV_VERSION "1.11" > +#define DRV_NAME_ACPI "iTCO_wdt_wirq" > +#define TCO_CLASS DRV_NAME > > /* Includes */ > #include <linux/module.h> /* For module specific items */ > @@ -68,6 +70,9 @@ > #include <linux/pm.h> /* For suspend/resume */ > #include <linux/mfd/core.h> > #include <linux/mfd/lpc_ich.h> > +#include <linux/nmi.h> > +#include <linux/acpi.h> > +#include <acpi/actypes.h> > > #include "iTCO_vendor.h" > > @@ -107,6 +112,12 @@ static struct { /* this is private data for the iTCO_wdt device */ > bool started; > } iTCO_wdt_private; > > +static const struct acpi_device_id iTCO_wdt_ids[] = { > + {"8086229C", 0}, This is not a proper ACPI or PNP device name as far as I can say. What is it? > + {"", 0}, > +}; > +MODULE_DEVICE_TABLE(acpi, iTCO_wdt_ids); > + > /* module parameters */ > #define WATCHDOG_TIMEOUT 30 /* 30 sec default heartbeat */ > static int heartbeat = WATCHDOG_TIMEOUT; /* in seconds */ > @@ -126,6 +137,11 @@ module_param(turn_SMI_watchdog_clear_off, int, 0); > MODULE_PARM_DESC(turn_SMI_watchdog_clear_off, > "Turn off SMI clearing watchdog (depends on TCO-version)(default=1)"); > > +static bool warn_irq; > +module_param(warn_irq, bool, 0); > +MODULE_PARM_DESC(warn_irq, > + "Watchdog trigs a panic at first expiration (default=0)"); > + > /* > * Some TCO specific functions > */ > @@ -200,6 +216,35 @@ static int iTCO_wdt_unset_NO_REBOOT_bit(void) > return ret; /* returns: 0 = OK, -EIO = Error */ > } > > +static u32 iTCO_wdt_wirq(acpi_handle gpe_device, u32 gpe, void *context) > +{ > + trigger_all_cpu_backtrace(); > + panic("Kernel Watchdog"); > + > + /* This code should not be reached */ > + return IRQ_HANDLED; > +} > + > +static int iTCO_wdt_acpi_add(struct acpi_device *device) > +{ > + unsigned long long gpe; > + acpi_status status; > + The code below seems to mean: "If the device _HID returns '8086229C', there should be a _GPE object under it which then returns the number of the GPE to bind to within the FADT GPE blocks." Where is this documented? > + status = acpi_evaluate_integer(device->handle, "_GPE", NULL, &gpe); > + if (ACPI_FAILURE(status)) > + return -EINVAL; > + > + status = acpi_install_gpe_handler(NULL, gpe, ACPI_GPE_EDGE_TRIGGERED, > + iTCO_wdt_wirq, NULL); > + if (ACPI_FAILURE(status)) > + return -ENODEV; > + > + acpi_enable_gpe(NULL, gpe); > + > + pr_debug("interrupt=SCI GPE=0x%02llx", gpe); > + return 0; > +} > + > static int iTCO_wdt_start(struct watchdog_device *wd_dev) > { > unsigned int val; > @@ -628,6 +673,15 @@ static struct platform_driver iTCO_wdt_driver = { > }, > }; > > +static struct acpi_driver iTCO_wdt_acpi_driver = { > + .name = DRV_NAME_ACPI, > + .class = TCO_CLASS, > + .ids = iTCO_wdt_ids, > + .ops = { > + .add = iTCO_wdt_acpi_add, > + }, > +}; > + > static int __init iTCO_wdt_init_module(void) > { > int err; > @@ -638,12 +692,22 @@ static int __init iTCO_wdt_init_module(void) > if (err) > return err; > > + if (warn_irq) { > + err = acpi_bus_register_driver(&iTCO_wdt_acpi_driver); > + if (err) { > + platform_driver_unregister(&iTCO_wdt_driver); > + return err; > + } > + } > + > return 0; > } > > static void __exit iTCO_wdt_cleanup_module(void) > { > platform_driver_unregister(&iTCO_wdt_driver); > + if (warn_irq) > + acpi_bus_unregister_driver(&iTCO_wdt_acpi_driver); > pr_info("Watchdog Module Unloaded\n"); > } > > -- > 1.9.1 And does it build for CONFIG_ACPI unset? -- To unsubscribe from this list: send the line "unsubscribe linux-acpi" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html