Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 646f919e authored by Philipp Hachtmann's avatar Philipp Hachtmann Committed by Martin Schwidefsky
Browse files

s390/watchdog: add support for LPAR operation (diag288)



Add the LPAR variant of the diag 288 watchdog to the driver.
The only available action on timeout for LPAR is a PSW restart.

Signed-off-by: default avatarPhilipp Hachtmann <phacht@de.ibm.com>
Signed-off-by: default avatarMartin Schwidefsky <schwidefsky@de.ibm.com>
parent f7a94db4
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -1304,6 +1304,8 @@ config DIAG288_WATCHDOG
	  provide a virtual watchdog timer to their guest that cause a
	  user define Control Program command to be executed after a
	  timeout.
	  LPAR provides a very similar interface. This driver handles
	  both.

	  To compile this driver as a module, choose M here. The module
	  will be called vmwatchdog.
+33 −4
Original line number Diff line number Diff line
/*
 * 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)
@@ -41,6 +46,9 @@
#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;
@@ -89,6 +97,12 @@ static int __diag288_vm(unsigned int func, unsigned int timeout,
	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;
@@ -113,6 +127,11 @@ static int wdt_start(struct watchdog_device *dev)
		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;
@@ -149,7 +168,8 @@ static int wdt_ping(struct watchdog_device *dev)

		/*
		 * 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;
@@ -159,6 +179,9 @@ static int wdt_ping(struct watchdog_device *dev)
		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;
@@ -256,12 +279,18 @@ static int __init diag288_init(void)
			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;
	}