d406711d770e5b0c6f598ad6daed50afd2574613
[deliverable/linux.git] / drivers / watchdog / diag288_wdt.c
1 /*
2 * Watchdog driver for z/VM using the diag 288 interface.
3 *
4 * Under z/VM, expiration of the watchdog will send a "system restart" command
5 * to CP.
6 *
7 * The command can be altered using the module parameter "cmd".
8 *
9 * Copyright IBM Corp. 2004, 2013
10 * Author(s): Arnd Bergmann (arndb@de.ibm.com)
11 * Philipp Hachtmann (phacht@de.ibm.com)
12 *
13 */
14
15 #define KMSG_COMPONENT "diag288_wdt"
16 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
17
18 #include <linux/init.h>
19 #include <linux/kernel.h>
20 #include <linux/module.h>
21 #include <linux/moduleparam.h>
22 #include <linux/slab.h>
23 #include <linux/miscdevice.h>
24 #include <linux/watchdog.h>
25 #include <linux/suspend.h>
26 #include <asm/ebcdic.h>
27 #include <linux/io.h>
28 #include <linux/uaccess.h>
29
30 #define MAX_CMDLEN 240
31 #define DEFAULT_CMD "SYSTEM RESTART"
32
33 #define MIN_INTERVAL 15 /* Minimal time supported by diag88 */
34 #define MAX_INTERVAL 3600 /* One hour should be enough - pure estimation */
35
36 #define WDT_DEFAULT_TIMEOUT 30
37
38 /* Function codes - init, change, cancel */
39 #define WDT_FUNC_INIT 0
40 #define WDT_FUNC_CHANGE 1
41 #define WDT_FUNC_CANCEL 2
42 #define WDT_FUNC_CONCEAL 0x80000000
43
44 static char wdt_cmd[MAX_CMDLEN] = DEFAULT_CMD;
45 static bool conceal_on;
46 static bool nowayout_info = WATCHDOG_NOWAYOUT;
47
48 MODULE_LICENSE("GPL");
49 MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
50 MODULE_AUTHOR("Philipp Hachtmann <phacht@de.ibm.com>");
51
52 MODULE_DESCRIPTION("System z diag288 Watchdog Timer");
53
54 module_param_string(cmd, wdt_cmd, MAX_CMDLEN, 0644);
55 MODULE_PARM_DESC(cmd, "CP command that is run when the watchdog triggers (z/VM only)");
56
57 module_param_named(conceal, conceal_on, bool, 0644);
58 MODULE_PARM_DESC(conceal, "Enable the CONCEAL CP option while the watchdog is active (z/VM only)");
59
60 module_param_named(nowayout, nowayout_info, bool, 0444);
61 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default = CONFIG_WATCHDOG_NOWAYOUT)");
62
63 MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR);
64 MODULE_ALIAS("vmwatchdog");
65
66 static int __diag288(unsigned int func, unsigned int timeout,
67 unsigned long action, unsigned int len)
68 {
69 register unsigned long __func asm("2") = func;
70 register unsigned long __timeout asm("3") = timeout;
71 register unsigned long __action asm("4") = action;
72 register unsigned long __len asm("5") = len;
73 int err;
74
75 err = -EINVAL;
76 asm volatile(
77 " diag %1, %3, 0x288\n"
78 "0: la %0, 0\n"
79 "1:\n"
80 EX_TABLE(0b, 1b)
81 : "+d" (err) : "d"(__func), "d"(__timeout),
82 "d"(__action), "d"(__len) : "1", "cc");
83 return err;
84 }
85
86 static int __diag288_vm(unsigned int func, unsigned int timeout,
87 char *cmd, size_t len)
88 {
89 return __diag288(func, timeout, virt_to_phys(cmd), len);
90 }
91
92 static int wdt_start(struct watchdog_device *dev)
93 {
94 char *ebc_cmd;
95 size_t len;
96 int ret;
97 unsigned int func;
98
99 ret = -ENODEV;
100
101 if (MACHINE_IS_VM) {
102 ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
103 if (!ebc_cmd)
104 return -ENOMEM;
105 len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
106 ASCEBC(ebc_cmd, MAX_CMDLEN);
107 EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
108
109 func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
110 : WDT_FUNC_INIT;
111 ret = __diag288_vm(func, dev->timeout, ebc_cmd, len);
112 WARN_ON(ret != 0);
113 kfree(ebc_cmd);
114 }
115
116 if (ret) {
117 pr_err("The watchdog cannot be activated\n");
118 return ret;
119 }
120 pr_info("The watchdog was activated\n");
121 return 0;
122 }
123
124 static int wdt_stop(struct watchdog_device *dev)
125 {
126 int ret;
127
128 ret = __diag288(WDT_FUNC_CANCEL, 0, 0, 0);
129 pr_info("The watchdog was deactivated\n");
130 return ret;
131 }
132
133 static int wdt_ping(struct watchdog_device *dev)
134 {
135 char *ebc_cmd;
136 size_t len;
137 int ret;
138 unsigned int func;
139
140 ret = -ENODEV;
141
142 if (MACHINE_IS_VM) {
143 ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
144 if (!ebc_cmd)
145 return -ENOMEM;
146 len = strlcpy(ebc_cmd, wdt_cmd, MAX_CMDLEN);
147 ASCEBC(ebc_cmd, MAX_CMDLEN);
148 EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
149
150 /*
151 * It seems to be ok to z/VM to use the init function to
152 * retrigger the watchdog.
153 */
154 func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
155 : WDT_FUNC_INIT;
156
157 ret = __diag288_vm(func, dev->timeout, ebc_cmd, len);
158 WARN_ON(ret != 0);
159 kfree(ebc_cmd);
160 }
161
162 if (ret)
163 pr_err("The watchdog timer cannot be started or reset\n");
164 return ret;
165 }
166
167 static int wdt_set_timeout(struct watchdog_device * dev, unsigned int new_to)
168 {
169 dev->timeout = new_to;
170 return wdt_ping(dev);
171 }
172
173 static struct watchdog_ops wdt_ops = {
174 .owner = THIS_MODULE,
175 .start = wdt_start,
176 .stop = wdt_stop,
177 .ping = wdt_ping,
178 .set_timeout = wdt_set_timeout,
179 };
180
181 static struct watchdog_info wdt_info = {
182 .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
183 .firmware_version = 0,
184 .identity = "z Watchdog",
185 };
186
187 static struct watchdog_device wdt_dev = {
188 .parent = NULL,
189 .info = &wdt_info,
190 .ops = &wdt_ops,
191 .bootstatus = 0,
192 .timeout = WDT_DEFAULT_TIMEOUT,
193 .min_timeout = MIN_INTERVAL,
194 .max_timeout = MAX_INTERVAL,
195 };
196
197 /*
198 * It makes no sense to go into suspend while the watchdog is running.
199 * Depending on the memory size, the watchdog might trigger, while we
200 * are still saving the memory.
201 * We reuse the open flag to ensure that suspend and watchdog open are
202 * exclusive operations
203 */
204 static int wdt_suspend(void)
205 {
206 if (test_and_set_bit(WDOG_DEV_OPEN, &wdt_dev.status)) {
207 pr_err("Linux cannot be suspended while the watchdog is in use\n");
208 return notifier_from_errno(-EBUSY);
209 }
210 if (test_bit(WDOG_ACTIVE, &wdt_dev.status)) {
211 clear_bit(WDOG_DEV_OPEN, &wdt_dev.status);
212 pr_err("Linux cannot be suspended while the watchdog is in use\n");
213 return notifier_from_errno(-EBUSY);
214 }
215 return NOTIFY_DONE;
216 }
217
218 static int wdt_resume(void)
219 {
220 clear_bit(WDOG_DEV_OPEN, &wdt_dev.status);
221 return NOTIFY_DONE;
222 }
223
224 static int wdt_power_event(struct notifier_block *this, unsigned long event,
225 void *ptr)
226 {
227 switch (event) {
228 case PM_POST_HIBERNATION:
229 case PM_POST_SUSPEND:
230 return wdt_resume();
231 case PM_HIBERNATION_PREPARE:
232 case PM_SUSPEND_PREPARE:
233 return wdt_suspend();
234 default:
235 return NOTIFY_DONE;
236 }
237 }
238
239 static struct notifier_block wdt_power_notifier = {
240 .notifier_call = wdt_power_event,
241 };
242
243 static int __init diag288_init(void)
244 {
245 int ret;
246 char ebc_begin[] = {
247 194, 197, 199, 201, 213
248 };
249
250 watchdog_set_nowayout(&wdt_dev, nowayout_info);
251
252 if (MACHINE_IS_VM) {
253 pr_info("The watchdog device driver detected a z/VM environment\n");
254 if (__diag288_vm(WDT_FUNC_INIT, 15,
255 ebc_begin, sizeof(ebc_begin)) != 0) {
256 pr_err("The watchdog cannot be initialized\n");
257 return -EINVAL;
258 }
259 } else {
260 pr_err("Linux runs in an environment that does not support the diag288 watchdog\n");
261 return -ENODEV;
262 }
263
264 if (__diag288_vm(WDT_FUNC_CANCEL, 0, NULL, 0)) {
265 pr_err("The watchdog cannot be deactivated\n");
266 return -EINVAL;
267 }
268
269 ret = register_pm_notifier(&wdt_power_notifier);
270 if (ret)
271 return ret;
272
273 ret = watchdog_register_device(&wdt_dev);
274 if (ret)
275 unregister_pm_notifier(&wdt_power_notifier);
276
277 return ret;
278 }
279
280 static void __exit diag288_exit(void)
281 {
282 watchdog_unregister_device(&wdt_dev);
283 unregister_pm_notifier(&wdt_power_notifier);
284 }
285
286 module_init(diag288_init);
287 module_exit(diag288_exit);
This page took 0.052422 seconds and 4 git commands to generate.