diff options
author | Alexander Egorenkov <egorenar@linux.ibm.com> | 2023-02-03 08:39:56 +0100 |
---|---|---|
committer | Heiko Carstens <hca@linux.ibm.com> | 2023-02-06 15:14:09 +0100 |
commit | 221f748ac8633083b7800d4e33a076fce22e341e (patch) | |
tree | f9bd88efed4bf7b59afee2ccb7c5782cdf8c5b2e /drivers/watchdog | |
parent | watchdog: diag288_wdt: remove power management (diff) | |
download | linux-221f748ac8633083b7800d4e33a076fce22e341e.tar.xz linux-221f748ac8633083b7800d4e33a076fce22e341e.zip |
watchdog: diag288_wdt: unify command buffer handling for diag288 zvm
Simplify and de-duplicate code by introducing a common single command
buffer allocated once at initialization. Moreover, simplify the interface
of __diag288_vm() by accepting ASCII strings as the command parameter
and converting it to the EBCDIC format within the function itself.
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Alexander Egorenkov <egorenar@linux.ibm.com>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Link: https://lore.kernel.org/r/20230203073958.1585738-4-egorenar@linux.ibm.com
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/diag288_wdt.c | 55 |
1 files changed, 20 insertions, 35 deletions
diff --git a/drivers/watchdog/diag288_wdt.c b/drivers/watchdog/diag288_wdt.c index c8d516ced6d2..c717f47dd4c3 100644 --- a/drivers/watchdog/diag288_wdt.c +++ b/drivers/watchdog/diag288_wdt.c @@ -69,6 +69,8 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default = C MODULE_ALIAS("vmwatchdog"); +static char *cmd_buf; + static int __diag288(unsigned int func, unsigned int timeout, unsigned long action, unsigned int len) { @@ -88,11 +90,18 @@ static int __diag288(unsigned int func, unsigned int timeout, return err; } -static int __diag288_vm(unsigned int func, unsigned int timeout, - char *cmd, size_t len) +static int __diag288_vm(unsigned int func, unsigned int timeout, char *cmd) { + ssize_t len; + + len = strscpy(cmd_buf, cmd, MAX_CMDLEN); + if (len < 0) + return len; + ASCEBC(cmd_buf, MAX_CMDLEN); + EBC_TOUPPER(cmd_buf, MAX_CMDLEN); + diag_stat_inc(DIAG_STAT_X288); - return __diag288(func, timeout, virt_to_phys(cmd), len); + return __diag288(func, timeout, virt_to_phys(cmd_buf), len); } static int __diag288_lpar(unsigned int func, unsigned int timeout, @@ -104,24 +113,14 @@ static int __diag288_lpar(unsigned int func, unsigned int timeout, static int wdt_start(struct watchdog_device *dev) { - char *ebc_cmd; - size_t len; int ret; unsigned int func; if (MACHINE_IS_VM) { - ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL); - if (!ebc_cmd) - return -ENOMEM; - len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN); - ASCEBC(ebc_cmd, MAX_CMDLEN); - EBC_TOUPPER(ebc_cmd, MAX_CMDLEN); - func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL) : WDT_FUNC_INIT; - ret = __diag288_vm(func, dev->timeout, ebc_cmd, len); + ret = __diag288_vm(func, dev->timeout, wdt_cmd); WARN_ON(ret != 0); - kfree(ebc_cmd); } else { ret = __diag288_lpar(WDT_FUNC_INIT, dev->timeout, LPARWDT_RESTART); @@ -146,19 +145,10 @@ static int wdt_stop(struct watchdog_device *dev) static int wdt_ping(struct watchdog_device *dev) { - char *ebc_cmd; - size_t len; int ret; unsigned int func; if (MACHINE_IS_VM) { - ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL); - if (!ebc_cmd) - return -ENOMEM; - len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN); - ASCEBC(ebc_cmd, MAX_CMDLEN); - EBC_TOUPPER(ebc_cmd, MAX_CMDLEN); - /* * It seems to be ok to z/VM to use the init function to * retrigger the watchdog. On LPAR WDT_FUNC_CHANGE must @@ -167,9 +157,8 @@ static int wdt_ping(struct watchdog_device *dev) func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL) : WDT_FUNC_INIT; - ret = __diag288_vm(func, dev->timeout, ebc_cmd, len); + ret = __diag288_vm(func, dev->timeout, wdt_cmd); WARN_ON(ret != 0); - kfree(ebc_cmd); } else { ret = __diag288_lpar(WDT_FUNC_CHANGE, dev->timeout, 0); } @@ -212,25 +201,20 @@ static struct watchdog_device wdt_dev = { static int __init diag288_init(void) { int ret; - char ebc_begin[] = { - 194, 197, 199, 201, 213 - }; - char *ebc_cmd; watchdog_set_nowayout(&wdt_dev, nowayout_info); if (MACHINE_IS_VM) { - ebc_cmd = kmalloc(sizeof(ebc_begin), GFP_KERNEL); - if (!ebc_cmd) { + cmd_buf = kmalloc(MAX_CMDLEN, GFP_KERNEL); + if (!cmd_buf) { pr_err("The watchdog cannot be initialized\n"); return -ENOMEM; } - memcpy(ebc_cmd, ebc_begin, sizeof(ebc_begin)); - ret = __diag288_vm(WDT_FUNC_INIT, 15, - ebc_cmd, sizeof(ebc_begin)); - kfree(ebc_cmd); + + ret = __diag288_vm(WDT_FUNC_INIT, MIN_INTERVAL, "BEGIN"); if (ret != 0) { pr_err("The watchdog cannot be initialized\n"); + kfree(cmd_buf); return -EINVAL; } } else { @@ -251,6 +235,7 @@ static int __init diag288_init(void) static void __exit diag288_exit(void) { watchdog_unregister_device(&wdt_dev); + kfree(cmd_buf); } module_init(diag288_init); |