| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Watchdog driver for z/VM and LPAR using the diag 288 interface. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 25 | 26 | #include <linux/module.h> |
|---|
| 26 | 27 | #include <linux/moduleparam.h> |
|---|
| 27 | 28 | #include <linux/slab.h> |
|---|
| 28 | | -#include <linux/miscdevice.h> |
|---|
| 29 | 29 | #include <linux/watchdog.h> |
|---|
| 30 | 30 | #include <linux/suspend.h> |
|---|
| 31 | 31 | #include <asm/ebcdic.h> |
|---|
| 32 | 32 | #include <asm/diag.h> |
|---|
| 33 | 33 | #include <linux/io.h> |
|---|
| 34 | | -#include <linux/uaccess.h> |
|---|
| 35 | 34 | |
|---|
| 36 | 35 | #define MAX_CMDLEN 240 |
|---|
| 37 | 36 | #define DEFAULT_CMD "SYSTEM RESTART" |
|---|
| .. | .. |
|---|
| 69 | 68 | module_param_named(nowayout, nowayout_info, bool, 0444); |
|---|
| 70 | 69 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default = CONFIG_WATCHDOG_NOWAYOUT)"); |
|---|
| 71 | 70 | |
|---|
| 72 | | -MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
|---|
| 73 | 71 | MODULE_ALIAS("vmwatchdog"); |
|---|
| 74 | 72 | |
|---|
| 75 | 73 | static int __diag288(unsigned int func, unsigned int timeout, |
|---|
| .. | .. |
|---|
| 88 | 86 | "1:\n" |
|---|
| 89 | 87 | EX_TABLE(0b, 1b) |
|---|
| 90 | 88 | : "+d" (err) : "d"(__func), "d"(__timeout), |
|---|
| 91 | | - "d"(__action), "d"(__len) : "1", "cc"); |
|---|
| 89 | + "d"(__action), "d"(__len) : "1", "cc", "memory"); |
|---|
| 92 | 90 | return err; |
|---|
| 93 | 91 | } |
|---|
| 94 | 92 | |
|---|
| .. | .. |
|---|
| 274 | 272 | char ebc_begin[] = { |
|---|
| 275 | 273 | 194, 197, 199, 201, 213 |
|---|
| 276 | 274 | }; |
|---|
| 275 | + char *ebc_cmd; |
|---|
| 277 | 276 | |
|---|
| 278 | 277 | watchdog_set_nowayout(&wdt_dev, nowayout_info); |
|---|
| 279 | 278 | |
|---|
| 280 | 279 | if (MACHINE_IS_VM) { |
|---|
| 281 | | - if (__diag288_vm(WDT_FUNC_INIT, 15, |
|---|
| 282 | | - ebc_begin, sizeof(ebc_begin)) != 0) { |
|---|
| 280 | + ebc_cmd = kmalloc(sizeof(ebc_begin), GFP_KERNEL); |
|---|
| 281 | + if (!ebc_cmd) { |
|---|
| 282 | + pr_err("The watchdog cannot be initialized\n"); |
|---|
| 283 | + return -ENOMEM; |
|---|
| 284 | + } |
|---|
| 285 | + memcpy(ebc_cmd, ebc_begin, sizeof(ebc_begin)); |
|---|
| 286 | + ret = __diag288_vm(WDT_FUNC_INIT, 15, |
|---|
| 287 | + ebc_cmd, sizeof(ebc_begin)); |
|---|
| 288 | + kfree(ebc_cmd); |
|---|
| 289 | + if (ret != 0) { |
|---|
| 283 | 290 | pr_err("The watchdog cannot be initialized\n"); |
|---|
| 284 | 291 | return -EINVAL; |
|---|
| 285 | 292 | } |
|---|