diag288_wdt.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Watchdog driver for z/VM and LPAR using the diag 288 interface.
  4. *
  5. * Under z/VM, expiration of the watchdog will send a "system restart" command
  6. * to CP.
  7. *
  8. * The command can be altered using the module parameter "cmd". This is
  9. * not recommended because it's only supported on z/VM but not with LPAR.
  10. *
  11. * On LPAR, the watchdog will always trigger a system restart. The module
  12. * parameter cmd is meaningless here.
  13. *
  14. *
  15. * Copyright IBM Corp. 2004, 2013
  16. * Author(s): Arnd Bergmann (arndb@de.ibm.com)
  17. * Philipp Hachtmann (phacht@de.ibm.com)
  18. *
  19. */
  20. #define pr_fmt(fmt) "diag288_wdt: " fmt
  21. #include <linux/init.h>
  22. #include <linux/kernel.h>
  23. #include <linux/module.h>
  24. #include <linux/moduleparam.h>
  25. #include <linux/slab.h>
  26. #include <linux/watchdog.h>
  27. #include <asm/machine.h>
  28. #include <asm/ebcdic.h>
  29. #include <asm/diag288.h>
  30. #include <asm/diag.h>
  31. #include <linux/io.h>
  32. #define MAX_CMDLEN 240
  33. #define DEFAULT_CMD "SYSTEM RESTART"
  34. static char wdt_cmd[MAX_CMDLEN] = DEFAULT_CMD;
  35. static bool conceal_on;
  36. static bool nowayout_info = WATCHDOG_NOWAYOUT;
  37. MODULE_LICENSE("GPL");
  38. MODULE_AUTHOR("Arnd Bergmann <arndb@de.ibm.com>");
  39. MODULE_AUTHOR("Philipp Hachtmann <phacht@de.ibm.com>");
  40. MODULE_DESCRIPTION("System z diag288 Watchdog Timer");
  41. module_param_string(cmd, wdt_cmd, MAX_CMDLEN, 0644);
  42. MODULE_PARM_DESC(cmd, "CP command that is run when the watchdog triggers (z/VM only)");
  43. module_param_named(conceal, conceal_on, bool, 0644);
  44. MODULE_PARM_DESC(conceal, "Enable the CONCEAL CP option while the watchdog is active (z/VM only)");
  45. module_param_named(nowayout, nowayout_info, bool, 0444);
  46. MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default = CONFIG_WATCHDOG_NOWAYOUT)");
  47. MODULE_ALIAS("vmwatchdog");
  48. static char *cmd_buf;
  49. static int diag288(unsigned int func, unsigned int timeout,
  50. unsigned long action, unsigned int len)
  51. {
  52. diag_stat_inc(DIAG_STAT_X288);
  53. return __diag288(func, timeout, action, len);
  54. }
  55. static int diag288_str(unsigned int func, unsigned int timeout, char *cmd)
  56. {
  57. ssize_t len;
  58. len = strscpy(cmd_buf, cmd, MAX_CMDLEN);
  59. if (len < 0)
  60. return len;
  61. ASCEBC(cmd_buf, MAX_CMDLEN);
  62. EBC_TOUPPER(cmd_buf, MAX_CMDLEN);
  63. return diag288(func, timeout, virt_to_phys(cmd_buf), len);
  64. }
  65. static int wdt_start(struct watchdog_device *dev)
  66. {
  67. int ret;
  68. unsigned int func;
  69. if (machine_is_vm()) {
  70. func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
  71. : WDT_FUNC_INIT;
  72. ret = diag288_str(func, dev->timeout, wdt_cmd);
  73. WARN_ON(ret != 0);
  74. } else {
  75. ret = diag288(WDT_FUNC_INIT, dev->timeout, LPARWDT_RESTART, 0);
  76. }
  77. if (ret) {
  78. pr_err("The watchdog cannot be activated\n");
  79. return ret;
  80. }
  81. return 0;
  82. }
  83. static int wdt_stop(struct watchdog_device *dev)
  84. {
  85. return diag288(WDT_FUNC_CANCEL, 0, 0, 0);
  86. }
  87. static int wdt_ping(struct watchdog_device *dev)
  88. {
  89. int ret;
  90. unsigned int func;
  91. if (machine_is_vm()) {
  92. /*
  93. * It seems to be ok to z/VM to use the init function to
  94. * retrigger the watchdog. On LPAR WDT_FUNC_CHANGE must
  95. * be used when the watchdog is running.
  96. */
  97. func = conceal_on ? (WDT_FUNC_INIT | WDT_FUNC_CONCEAL)
  98. : WDT_FUNC_INIT;
  99. ret = diag288_str(func, dev->timeout, wdt_cmd);
  100. WARN_ON(ret != 0);
  101. } else {
  102. ret = diag288(WDT_FUNC_CHANGE, dev->timeout, 0, 0);
  103. }
  104. if (ret)
  105. pr_err("The watchdog timer cannot be started or reset\n");
  106. return ret;
  107. }
  108. static int wdt_set_timeout(struct watchdog_device * dev, unsigned int new_to)
  109. {
  110. dev->timeout = new_to;
  111. return wdt_ping(dev);
  112. }
  113. static const struct watchdog_ops wdt_ops = {
  114. .owner = THIS_MODULE,
  115. .start = wdt_start,
  116. .stop = wdt_stop,
  117. .ping = wdt_ping,
  118. .set_timeout = wdt_set_timeout,
  119. };
  120. static const struct watchdog_info wdt_info = {
  121. .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE,
  122. .firmware_version = 0,
  123. .identity = "z Watchdog",
  124. };
  125. static struct watchdog_device wdt_dev = {
  126. .parent = NULL,
  127. .info = &wdt_info,
  128. .ops = &wdt_ops,
  129. .bootstatus = 0,
  130. .timeout = WDT_DEFAULT_TIMEOUT,
  131. .min_timeout = MIN_INTERVAL,
  132. .max_timeout = MAX_INTERVAL,
  133. };
  134. static int __init diag288_init(void)
  135. {
  136. watchdog_set_nowayout(&wdt_dev, nowayout_info);
  137. if (machine_is_vm()) {
  138. cmd_buf = kmalloc(MAX_CMDLEN, GFP_KERNEL);
  139. if (!cmd_buf) {
  140. pr_err("The watchdog cannot be initialized\n");
  141. return -ENOMEM;
  142. }
  143. }
  144. return watchdog_register_device(&wdt_dev);
  145. }
  146. static void __exit diag288_exit(void)
  147. {
  148. watchdog_unregister_device(&wdt_dev);
  149. kfree(cmd_buf);
  150. }
  151. module_cpu_feature_match(S390_CPU_FEATURE_D288, diag288_init);
  152. module_exit(diag288_exit);