/*
- * Watchdog driver for z/VM using the diag 288 interface.
+ * Watchdog driver for z/VM and LPAR using the diag 288 interface.
*
* Under z/VM, expiration of the watchdog will send a "system restart" command
* to CP.
*
- * The command can be altered using the module parameter "cmd".
+ * The command can be altered using the module parameter "cmd". This is
+ * not recommended because it's only supported on z/VM but not whith LPAR.
+ *
+ * On LPAR, the watchdog will always trigger a system restart. the module
+ * paramter cmd is meaningless here.
+ *
*
* Copyright IBM Corp. 2004, 2013
* Author(s): Arnd Bergmann (arndb@de.ibm.com)
#define WDT_FUNC_CANCEL 2
#define WDT_FUNC_CONCEAL 0x80000000
+/* Action codes for LPAR watchdog */
+#define LPARWDT_RESTART 0
+
static char wdt_cmd[MAX_CMDLEN] = DEFAULT_CMD;
static bool conceal_on;
static bool nowayout_info = WATCHDOG_NOWAYOUT;
return __diag288(func, timeout, virt_to_phys(cmd), len);
}
+static int __diag288_lpar(unsigned int func, unsigned int timeout,
+ unsigned long action)
+{
+ return __diag288(func, timeout, action, 0);
+}
+
static int wdt_start(struct watchdog_device *dev)
{
char *ebc_cmd;
kfree(ebc_cmd);
}
+ if (MACHINE_IS_LPAR) {
+ ret = __diag288_lpar(WDT_FUNC_INIT,
+ dev->timeout, LPARWDT_RESTART);
+ }
+
if (ret) {
pr_err("The watchdog cannot be activated\n");
return ret;
/*
* It seems to be ok to z/VM to use the init function to
- * retrigger the watchdog.
+ * retrigger the watchdog. On LPAR WDT_FUNC_CHANGE must
+ * be used when the watchdog is running.
*/
func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
: WDT_FUNC_INIT;
kfree(ebc_cmd);
}
+ if (MACHINE_IS_LPAR)
+ ret = __diag288_lpar(WDT_FUNC_CHANGE, dev->timeout, 0);
+
if (ret)
pr_err("The watchdog timer cannot be started or reset\n");
return ret;
pr_err("The watchdog cannot be initialized\n");
return -EINVAL;
}
+ } else if (MACHINE_IS_LPAR) {
+ pr_info("The watchdog device driver detected an LPAR environment\n");
+ if (__diag288_lpar(WDT_FUNC_INIT, 30, LPARWDT_RESTART)) {
+ pr_err("The watchdog cannot be initialized\n");
+ return -EINVAL;
+ }
} else {
pr_err("Linux runs in an environment that does not support the diag288 watchdog\n");
return -ENODEV;
}
- if (__diag288_vm(WDT_FUNC_CANCEL, 0, NULL, 0)) {
+ if (__diag288_lpar(WDT_FUNC_CANCEL, 0, 0)) {
pr_err("The watchdog cannot be deactivated\n");
return -EINVAL;
}