Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
vmwatchdog.c
Go to the documentation of this file.
1 /*
2  * Watchdog implementation based on z/VM Watchdog Timer API
3  *
4  * Copyright IBM Corp. 2004, 2009
5  *
6  * The user space watchdog daemon can use this driver as
7  * /dev/vmwatchdog to have z/VM execute the specified CP
8  * command when the timeout expires. The default command is
9  * "IPL", which which cause an immediate reboot.
10  */
11 #define KMSG_COMPONENT "vmwatchdog"
12 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
13 
14 #include <linux/init.h>
15 #include <linux/fs.h>
16 #include <linux/kernel.h>
17 #include <linux/miscdevice.h>
18 #include <linux/module.h>
19 #include <linux/moduleparam.h>
20 #include <linux/slab.h>
21 #include <linux/suspend.h>
22 #include <linux/watchdog.h>
23 
24 #include <asm/ebcdic.h>
25 #include <asm/io.h>
26 #include <asm/uaccess.h>
27 
28 #define MAX_CMDLEN 240
29 #define MIN_INTERVAL 15
30 static char vmwdt_cmd[MAX_CMDLEN] = "IPL";
31 static bool vmwdt_conceal;
32 
33 static bool vmwdt_nowayout = WATCHDOG_NOWAYOUT;
34 
35 MODULE_LICENSE("GPL");
36 MODULE_AUTHOR("Arnd Bergmann <[email protected]>");
37 MODULE_DESCRIPTION("z/VM Watchdog Timer");
38 module_param_string(cmd, vmwdt_cmd, MAX_CMDLEN, 0644);
39 MODULE_PARM_DESC(cmd, "CP command that is run when the watchdog triggers");
40 module_param_named(conceal, vmwdt_conceal, bool, 0644);
41 MODULE_PARM_DESC(conceal, "Enable the CONCEAL CP option while the watchdog "
42  " is active");
43 module_param_named(nowayout, vmwdt_nowayout, bool, 0);
44 MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"
45  " (default=CONFIG_WATCHDOG_NOWAYOUT)");
47 
48 static unsigned int vmwdt_interval = 60;
49 static unsigned long vmwdt_is_open;
50 static int vmwdt_expect_close;
51 
52 static DEFINE_MUTEX(vmwdt_mutex);
53 
54 #define VMWDT_OPEN 0 /* devnode is open or suspend in progress */
55 #define VMWDT_RUNNING 1 /* The watchdog is armed */
56 
57 enum vmwdt_func {
58  /* function codes */
59  wdt_init = 0,
62  /* flags */
63  wdt_conceal = 0x80000000,
64 };
65 
66 static int __diag288(enum vmwdt_func func, unsigned int timeout,
67  char *cmd, size_t len)
68 {
69  register unsigned long __func asm("2") = func;
70  register unsigned long __timeout asm("3") = timeout;
71  register unsigned long __cmdp asm("4") = virt_to_phys(cmd);
72  register unsigned long __cmdl 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"(__cmdp), "d"(__cmdl) : "1", "cc");
83  return err;
84 }
85 
86 static int vmwdt_keepalive(void)
87 {
88  /* we allocate new memory every time to avoid having
89  * to track the state. static allocation is not an
90  * option since that might not be contiguous in real
91  * storage in case of a modular build */
92  static char *ebc_cmd;
93  size_t len;
94  int ret;
95  unsigned int func;
96 
97  ebc_cmd = kmalloc(MAX_CMDLEN, GFP_KERNEL);
98  if (!ebc_cmd)
99  return -ENOMEM;
100 
101  len = strlcpy(ebc_cmd, vmwdt_cmd, MAX_CMDLEN);
102  ASCEBC(ebc_cmd, MAX_CMDLEN);
103  EBC_TOUPPER(ebc_cmd, MAX_CMDLEN);
104 
105  func = vmwdt_conceal ? (wdt_init | wdt_conceal) : wdt_init;
106  set_bit(VMWDT_RUNNING, &vmwdt_is_open);
107  ret = __diag288(func, vmwdt_interval, ebc_cmd, len);
108  WARN_ON(ret != 0);
109  kfree(ebc_cmd);
110  return ret;
111 }
112 
113 static int vmwdt_disable(void)
114 {
115  int ret = __diag288(wdt_cancel, 0, "", 0);
116  WARN_ON(ret != 0);
117  clear_bit(VMWDT_RUNNING, &vmwdt_is_open);
118  return ret;
119 }
120 
121 static int __init vmwdt_probe(void)
122 {
123  /* there is no real way to see if the watchdog is supported,
124  * so we try initializing it with a NOP command ("BEGIN")
125  * that won't cause any harm even if the following disable
126  * fails for some reason */
127  static char __initdata ebc_begin[] = {
128  194, 197, 199, 201, 213
129  };
130  if (__diag288(wdt_init, 15, ebc_begin, sizeof(ebc_begin)) != 0)
131  return -EINVAL;
132  return vmwdt_disable();
133 }
134 
135 static int vmwdt_open(struct inode *i, struct file *f)
136 {
137  int ret;
138  if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open))
139  return -EBUSY;
140  ret = vmwdt_keepalive();
141  if (ret)
142  clear_bit(VMWDT_OPEN, &vmwdt_is_open);
143  return ret ? ret : nonseekable_open(i, f);
144 }
145 
146 static int vmwdt_close(struct inode *i, struct file *f)
147 {
148  if (vmwdt_expect_close == 42)
149  vmwdt_disable();
150  vmwdt_expect_close = 0;
151  clear_bit(VMWDT_OPEN, &vmwdt_is_open);
152  return 0;
153 }
154 
155 static struct watchdog_info vmwdt_info = {
157  .firmware_version = 0,
158  .identity = "z/VM Watchdog Timer",
159 };
160 
161 static int __vmwdt_ioctl(unsigned int cmd, unsigned long arg)
162 {
163  switch (cmd) {
164  case WDIOC_GETSUPPORT:
165  if (copy_to_user((void __user *)arg, &vmwdt_info,
166  sizeof(vmwdt_info)))
167  return -EFAULT;
168  return 0;
169  case WDIOC_GETSTATUS:
170  case WDIOC_GETBOOTSTATUS:
171  return put_user(0, (int __user *)arg);
172  case WDIOC_GETTEMP:
173  return -EINVAL;
174  case WDIOC_SETOPTIONS:
175  {
176  int options, ret;
177  if (get_user(options, (int __user *)arg))
178  return -EFAULT;
179  ret = -EINVAL;
180  if (options & WDIOS_DISABLECARD) {
181  ret = vmwdt_disable();
182  if (ret)
183  return ret;
184  }
185  if (options & WDIOS_ENABLECARD) {
186  ret = vmwdt_keepalive();
187  }
188  return ret;
189  }
190  case WDIOC_GETTIMEOUT:
191  return put_user(vmwdt_interval, (int __user *)arg);
192  case WDIOC_SETTIMEOUT:
193  {
194  int interval;
195  if (get_user(interval, (int __user *)arg))
196  return -EFAULT;
197  if (interval < MIN_INTERVAL)
198  return -EINVAL;
199  vmwdt_interval = interval;
200  }
201  return vmwdt_keepalive();
202  case WDIOC_KEEPALIVE:
203  return vmwdt_keepalive();
204  }
205  return -EINVAL;
206 }
207 
208 static long vmwdt_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
209 {
210  int rc;
211 
212  mutex_lock(&vmwdt_mutex);
213  rc = __vmwdt_ioctl(cmd, arg);
214  mutex_unlock(&vmwdt_mutex);
215  return (long) rc;
216 }
217 
218 static ssize_t vmwdt_write(struct file *f, const char __user *buf,
219  size_t count, loff_t *ppos)
220 {
221  if(count) {
222  if (!vmwdt_nowayout) {
223  size_t i;
224 
225  /* note: just in case someone wrote the magic character
226  * five months ago... */
227  vmwdt_expect_close = 0;
228 
229  for (i = 0; i != count; i++) {
230  char c;
231  if (get_user(c, buf+i))
232  return -EFAULT;
233  if (c == 'V')
234  vmwdt_expect_close = 42;
235  }
236  }
237  /* someone wrote to us, we should restart timer */
238  vmwdt_keepalive();
239  }
240  return count;
241 }
242 
243 static int vmwdt_resume(void)
244 {
245  clear_bit(VMWDT_OPEN, &vmwdt_is_open);
246  return NOTIFY_DONE;
247 }
248 
249 /*
250  * It makes no sense to go into suspend while the watchdog is running.
251  * Depending on the memory size, the watchdog might trigger, while we
252  * are still saving the memory.
253  * We reuse the open flag to ensure that suspend and watchdog open are
254  * exclusive operations
255  */
256 static int vmwdt_suspend(void)
257 {
258  if (test_and_set_bit(VMWDT_OPEN, &vmwdt_is_open)) {
259  pr_err("The system cannot be suspended while the watchdog"
260  " is in use\n");
261  return notifier_from_errno(-EBUSY);
262  }
263  if (test_bit(VMWDT_RUNNING, &vmwdt_is_open)) {
264  clear_bit(VMWDT_OPEN, &vmwdt_is_open);
265  pr_err("The system cannot be suspended while the watchdog"
266  " is running\n");
267  return notifier_from_errno(-EBUSY);
268  }
269  return NOTIFY_DONE;
270 }
271 
272 /*
273  * This function is called for suspend and resume.
274  */
275 static int vmwdt_power_event(struct notifier_block *this, unsigned long event,
276  void *ptr)
277 {
278  switch (event) {
279  case PM_POST_HIBERNATION:
280  case PM_POST_SUSPEND:
281  return vmwdt_resume();
283  case PM_SUSPEND_PREPARE:
284  return vmwdt_suspend();
285  default:
286  return NOTIFY_DONE;
287  }
288 }
289 
290 static struct notifier_block vmwdt_power_notifier = {
291  .notifier_call = vmwdt_power_event,
292 };
293 
294 static const struct file_operations vmwdt_fops = {
295  .open = &vmwdt_open,
296  .release = &vmwdt_close,
297  .unlocked_ioctl = &vmwdt_ioctl,
298  .write = &vmwdt_write,
299  .owner = THIS_MODULE,
300  .llseek = noop_llseek,
301 };
302 
303 static struct miscdevice vmwdt_dev = {
304  .minor = WATCHDOG_MINOR,
305  .name = "watchdog",
306  .fops = &vmwdt_fops,
307 };
308 
309 static int __init vmwdt_init(void)
310 {
311  int ret;
312 
313  ret = vmwdt_probe();
314  if (ret)
315  return ret;
316  ret = register_pm_notifier(&vmwdt_power_notifier);
317  if (ret)
318  return ret;
319  /*
320  * misc_register() has to be the last action in module_init(), because
321  * file operations will be available right after this.
322  */
323  ret = misc_register(&vmwdt_dev);
324  if (ret) {
325  unregister_pm_notifier(&vmwdt_power_notifier);
326  return ret;
327  }
328  return 0;
329 }
330 module_init(vmwdt_init);
331 
332 static void __exit vmwdt_exit(void)
333 {
334  unregister_pm_notifier(&vmwdt_power_notifier);
335  misc_deregister(&vmwdt_dev);
336 }
337 module_exit(vmwdt_exit);