pseries-wdt.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (c) 2022 International Business Machines, Inc.
  4. */
  5. #include <linux/bitops.h>
  6. #include <linux/kernel.h>
  7. #include <linux/limits.h>
  8. #include <linux/math.h>
  9. #include <linux/mod_devicetable.h>
  10. #include <linux/module.h>
  11. #include <linux/moduleparam.h>
  12. #include <linux/platform_device.h>
  13. #include <linux/time64.h>
  14. #include <linux/watchdog.h>
  15. #define DRV_NAME "pseries-wdt"
  16. /*
  17. * H_WATCHDOG Input
  18. *
  19. * R4: "flags":
  20. *
  21. * Bits 48-55: "operation"
  22. */
  23. #define PSERIES_WDTF_OP_START 0x100UL /* start timer */
  24. #define PSERIES_WDTF_OP_STOP 0x200UL /* stop timer */
  25. #define PSERIES_WDTF_OP_QUERY 0x300UL /* query timer capabilities */
  26. /*
  27. * Bits 56-63: "timeoutAction" (for "Start Watchdog" only)
  28. */
  29. #define PSERIES_WDTF_ACTION_HARD_POWEROFF 0x1UL /* poweroff */
  30. #define PSERIES_WDTF_ACTION_HARD_RESTART 0x2UL /* restart */
  31. #define PSERIES_WDTF_ACTION_DUMP_RESTART 0x3UL /* dump + restart */
  32. /*
  33. * H_WATCHDOG Output
  34. *
  35. * R3: Return code
  36. *
  37. * H_SUCCESS The operation completed.
  38. *
  39. * H_BUSY The hypervisor is too busy; retry the operation.
  40. *
  41. * H_PARAMETER The given "flags" are somehow invalid. Either the
  42. * "operation" or "timeoutAction" is invalid, or a
  43. * reserved bit is set.
  44. *
  45. * H_P2 The given "watchdogNumber" is zero or exceeds the
  46. * supported maximum value.
  47. *
  48. * H_P3 The given "timeoutInMs" is below the supported
  49. * minimum value.
  50. *
  51. * H_NOOP The given "watchdogNumber" is already stopped.
  52. *
  53. * H_HARDWARE The operation failed for ineffable reasons.
  54. *
  55. * H_FUNCTION The H_WATCHDOG hypercall is not supported by this
  56. * hypervisor.
  57. *
  58. * R4:
  59. *
  60. * - For the "Query Watchdog Capabilities" operation, a 64-bit
  61. * structure:
  62. */
  63. #define PSERIES_WDTQ_MIN_TIMEOUT(cap) (((cap) >> 48) & 0xffff)
  64. #define PSERIES_WDTQ_MAX_NUMBER(cap) (((cap) >> 32) & 0xffff)
  65. static const unsigned long pseries_wdt_action[] = {
  66. [0] = PSERIES_WDTF_ACTION_HARD_POWEROFF,
  67. [1] = PSERIES_WDTF_ACTION_HARD_RESTART,
  68. [2] = PSERIES_WDTF_ACTION_DUMP_RESTART,
  69. };
  70. #define WATCHDOG_ACTION 1
  71. static unsigned int action = WATCHDOG_ACTION;
  72. module_param(action, uint, 0444);
  73. MODULE_PARM_DESC(action, "Action taken when watchdog expires (default="
  74. __MODULE_STRING(WATCHDOG_ACTION) ")");
  75. static bool nowayout = WATCHDOG_NOWAYOUT;
  76. module_param(nowayout, bool, 0444);
  77. MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
  78. __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
  79. #define WATCHDOG_TIMEOUT 60
  80. static unsigned int timeout = WATCHDOG_TIMEOUT;
  81. module_param(timeout, uint, 0444);
  82. MODULE_PARM_DESC(timeout, "Initial watchdog timeout in seconds (default="
  83. __MODULE_STRING(WATCHDOG_TIMEOUT) ")");
  84. struct pseries_wdt {
  85. struct watchdog_device wd;
  86. unsigned long action;
  87. unsigned long num; /* Watchdog numbers are 1-based */
  88. };
  89. static int pseries_wdt_start(struct watchdog_device *wdd)
  90. {
  91. struct pseries_wdt *pw = watchdog_get_drvdata(wdd);
  92. struct device *dev = wdd->parent;
  93. unsigned long flags, msecs;
  94. long rc;
  95. flags = pw->action | PSERIES_WDTF_OP_START;
  96. msecs = wdd->timeout * MSEC_PER_SEC;
  97. rc = plpar_hcall_norets(H_WATCHDOG, flags, pw->num, msecs);
  98. if (rc != H_SUCCESS) {
  99. dev_crit(dev, "H_WATCHDOG: %ld: failed to start timer %lu",
  100. rc, pw->num);
  101. return -EIO;
  102. }
  103. return 0;
  104. }
  105. static int pseries_wdt_stop(struct watchdog_device *wdd)
  106. {
  107. struct pseries_wdt *pw = watchdog_get_drvdata(wdd);
  108. struct device *dev = wdd->parent;
  109. long rc;
  110. rc = plpar_hcall_norets(H_WATCHDOG, PSERIES_WDTF_OP_STOP, pw->num);
  111. if (rc != H_SUCCESS && rc != H_NOOP) {
  112. dev_crit(dev, "H_WATCHDOG: %ld: failed to stop timer %lu",
  113. rc, pw->num);
  114. return -EIO;
  115. }
  116. return 0;
  117. }
  118. static struct watchdog_info pseries_wdt_info = {
  119. .identity = DRV_NAME,
  120. .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT
  121. | WDIOF_PRETIMEOUT,
  122. };
  123. static const struct watchdog_ops pseries_wdt_ops = {
  124. .owner = THIS_MODULE,
  125. .start = pseries_wdt_start,
  126. .stop = pseries_wdt_stop,
  127. };
  128. static int pseries_wdt_probe(struct platform_device *pdev)
  129. {
  130. unsigned long ret[PLPAR_HCALL_BUFSIZE] = { 0 };
  131. struct pseries_wdt *pw;
  132. unsigned long cap;
  133. long msecs, rc;
  134. int err;
  135. rc = plpar_hcall(H_WATCHDOG, ret, PSERIES_WDTF_OP_QUERY);
  136. if (rc == H_FUNCTION)
  137. return -ENODEV;
  138. if (rc != H_SUCCESS)
  139. return -EIO;
  140. cap = ret[0];
  141. pw = devm_kzalloc(&pdev->dev, sizeof(*pw), GFP_KERNEL);
  142. if (!pw)
  143. return -ENOMEM;
  144. /*
  145. * Assume watchdogNumber 1 for now. If we ever support
  146. * multiple timers we will need to devise a way to choose a
  147. * distinct watchdogNumber for each platform device at device
  148. * registration time.
  149. */
  150. pw->num = 1;
  151. if (PSERIES_WDTQ_MAX_NUMBER(cap) < pw->num)
  152. return -ENODEV;
  153. if (action >= ARRAY_SIZE(pseries_wdt_action))
  154. return -EINVAL;
  155. pw->action = pseries_wdt_action[action];
  156. pw->wd.parent = &pdev->dev;
  157. pw->wd.info = &pseries_wdt_info;
  158. pw->wd.ops = &pseries_wdt_ops;
  159. msecs = PSERIES_WDTQ_MIN_TIMEOUT(cap);
  160. pw->wd.min_timeout = DIV_ROUND_UP(msecs, MSEC_PER_SEC);
  161. pw->wd.max_timeout = UINT_MAX / 1000; /* from linux/watchdog.h */
  162. pw->wd.timeout = timeout;
  163. if (watchdog_init_timeout(&pw->wd, 0, NULL))
  164. return -EINVAL;
  165. watchdog_set_nowayout(&pw->wd, nowayout);
  166. watchdog_stop_on_reboot(&pw->wd);
  167. watchdog_stop_on_unregister(&pw->wd);
  168. watchdog_set_drvdata(&pw->wd, pw);
  169. err = devm_watchdog_register_device(&pdev->dev, &pw->wd);
  170. if (err)
  171. return err;
  172. platform_set_drvdata(pdev, &pw->wd);
  173. return 0;
  174. }
  175. static int pseries_wdt_suspend(struct platform_device *pdev, pm_message_t state)
  176. {
  177. struct watchdog_device *wd = platform_get_drvdata(pdev);
  178. if (watchdog_active(wd))
  179. return pseries_wdt_stop(wd);
  180. return 0;
  181. }
  182. static int pseries_wdt_resume(struct platform_device *pdev)
  183. {
  184. struct watchdog_device *wd = platform_get_drvdata(pdev);
  185. if (watchdog_active(wd))
  186. return pseries_wdt_start(wd);
  187. return 0;
  188. }
  189. static const struct platform_device_id pseries_wdt_id[] = {
  190. { .name = "pseries-wdt" },
  191. {}
  192. };
  193. MODULE_DEVICE_TABLE(platform, pseries_wdt_id);
  194. static struct platform_driver pseries_wdt_driver = {
  195. .driver = {
  196. .name = DRV_NAME,
  197. },
  198. .id_table = pseries_wdt_id,
  199. .probe = pseries_wdt_probe,
  200. .resume = pseries_wdt_resume,
  201. .suspend = pseries_wdt_suspend,
  202. };
  203. module_platform_driver(pseries_wdt_driver);
  204. MODULE_AUTHOR("Alexey Kardashevskiy");
  205. MODULE_AUTHOR("Scott Cheloha");
  206. MODULE_DESCRIPTION("POWER Architecture Platform Watchdog Driver");
  207. MODULE_LICENSE("GPL");