009-4-watchdog-Read-device-status-through-sysfs-attributes.patch 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. From 33b711269ade3f6bc9d9d15e4343e6fa922d999b Mon Sep 17 00:00:00 2001
  2. From: Pratyush Anand <panand@redhat.com>
  3. Date: Thu, 17 Dec 2015 17:53:59 +0530
  4. Subject: watchdog: Read device status through sysfs attributes
  5. This patch adds following attributes to watchdog device's sysfs interface
  6. to read its different status.
  7. * state - reads whether device is active or not
  8. * identity - reads Watchdog device's identity string.
  9. * timeout - reads current timeout.
  10. * timeleft - reads timeleft before watchdog generates a reset
  11. * bootstatus - reads status of the watchdog device at boot
  12. * status - reads watchdog device's internal status bits
  13. * nowayout - reads whether nowayout feature was set or not
  14. Testing with iTCO_wdt:
  15. # cd /sys/class/watchdog/watchdog1/
  16. # ls
  17. bootstatus dev device identity nowayout power state
  18. subsystem timeleft timeout uevent
  19. # cat identity
  20. iTCO_wdt
  21. # cat timeout
  22. 30
  23. # cat state
  24. inactive
  25. # echo > /dev/watchdog1
  26. # cat timeleft
  27. 26
  28. # cat state
  29. active
  30. # cat bootstatus
  31. 0
  32. # cat nowayout
  33. 0
  34. Signed-off-by: Pratyush Anand <panand@redhat.com>
  35. Reviewed-by: Guenter Roeck <linux@roeck-us.net>
  36. Signed-off-by: Guenter Roeck <linux@roeck-us.net>
  37. Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
  38. ---
  39. Documentation/ABI/testing/sysfs-class-watchdog | 51 +++++++++++
  40. drivers/watchdog/Kconfig | 7 ++
  41. drivers/watchdog/watchdog_core.c | 2 +-
  42. drivers/watchdog/watchdog_dev.c | 114 +++++++++++++++++++++++++
  43. 4 files changed, 173 insertions(+), 1 deletion(-)
  44. create mode 100644 Documentation/ABI/testing/sysfs-class-watchdog
  45. --- /dev/null
  46. +++ b/Documentation/ABI/testing/sysfs-class-watchdog
  47. @@ -0,0 +1,51 @@
  48. +What: /sys/class/watchdog/watchdogn/bootstatus
  49. +Date: August 2015
  50. +Contact: Wim Van Sebroeck <wim@iguana.be>
  51. +Description:
  52. + It is a read only file. It contains status of the watchdog
  53. + device at boot. It is equivalent to WDIOC_GETBOOTSTATUS of
  54. + ioctl interface.
  55. +
  56. +What: /sys/class/watchdog/watchdogn/identity
  57. +Date: August 2015
  58. +Contact: Wim Van Sebroeck <wim@iguana.be>
  59. +Description:
  60. + It is a read only file. It contains identity string of
  61. + watchdog device.
  62. +
  63. +What: /sys/class/watchdog/watchdogn/nowayout
  64. +Date: August 2015
  65. +Contact: Wim Van Sebroeck <wim@iguana.be>
  66. +Description:
  67. + It is a read only file. While reading, it gives '1' if that
  68. + device supports nowayout feature else, it gives '0'.
  69. +
  70. +What: /sys/class/watchdog/watchdogn/state
  71. +Date: August 2015
  72. +Contact: Wim Van Sebroeck <wim@iguana.be>
  73. +Description:
  74. + It is a read only file. It gives active/inactive status of
  75. + watchdog device.
  76. +
  77. +What: /sys/class/watchdog/watchdogn/status
  78. +Date: August 2015
  79. +Contact: Wim Van Sebroeck <wim@iguana.be>
  80. +Description:
  81. + It is a read only file. It contains watchdog device's
  82. + internal status bits. It is equivalent to WDIOC_GETSTATUS
  83. + of ioctl interface.
  84. +
  85. +What: /sys/class/watchdog/watchdogn/timeleft
  86. +Date: August 2015
  87. +Contact: Wim Van Sebroeck <wim@iguana.be>
  88. +Description:
  89. + It is a read only file. It contains value of time left for
  90. + reset generation. It is equivalent to WDIOC_GETTIMELEFT of
  91. + ioctl interface.
  92. +
  93. +What: /sys/class/watchdog/watchdogn/timeout
  94. +Date: August 2015
  95. +Contact: Wim Van Sebroeck <wim@iguana.be>
  96. +Description:
  97. + It is a read only file. It is read to know about current
  98. + value of timeout programmed.
  99. --- a/drivers/watchdog/Kconfig
  100. +++ b/drivers/watchdog/Kconfig
  101. @@ -46,6 +46,13 @@ config WATCHDOG_NOWAYOUT
  102. get killed. If you say Y here, the watchdog cannot be stopped once
  103. it has been started.
  104. +config WATCHDOG_SYSFS
  105. + bool "Read different watchdog information through sysfs"
  106. + default n
  107. + help
  108. + Say Y here if you want to enable watchdog device status read through
  109. + sysfs attributes.
  110. +
  111. #
  112. # General Watchdog drivers
  113. #
  114. --- a/drivers/watchdog/watchdog_core.c
  115. +++ b/drivers/watchdog/watchdog_core.c
  116. @@ -249,7 +249,7 @@ static int __watchdog_register_device(st
  117. devno = wdd->cdev.dev;
  118. wdd->dev = device_create(watchdog_class, wdd->parent, devno,
  119. - NULL, "watchdog%d", wdd->id);
  120. + wdd, "watchdog%d", wdd->id);
  121. if (IS_ERR(wdd->dev)) {
  122. watchdog_dev_unregister(wdd);
  123. ida_simple_remove(&watchdog_ida, id);
  124. --- a/drivers/watchdog/watchdog_dev.c
  125. +++ b/drivers/watchdog/watchdog_dev.c
  126. @@ -247,6 +247,119 @@ out_timeleft:
  127. return err;
  128. }
  129. +#ifdef CONFIG_WATCHDOG_SYSFS
  130. +static ssize_t nowayout_show(struct device *dev, struct device_attribute *attr,
  131. + char *buf)
  132. +{
  133. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  134. +
  135. + return sprintf(buf, "%d\n", !!test_bit(WDOG_NO_WAY_OUT, &wdd->status));
  136. +}
  137. +static DEVICE_ATTR_RO(nowayout);
  138. +
  139. +static ssize_t status_show(struct device *dev, struct device_attribute *attr,
  140. + char *buf)
  141. +{
  142. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  143. + ssize_t status;
  144. + unsigned int val;
  145. +
  146. + status = watchdog_get_status(wdd, &val);
  147. + if (!status)
  148. + status = sprintf(buf, "%u\n", val);
  149. +
  150. + return status;
  151. +}
  152. +static DEVICE_ATTR_RO(status);
  153. +
  154. +static ssize_t bootstatus_show(struct device *dev,
  155. + struct device_attribute *attr, char *buf)
  156. +{
  157. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  158. +
  159. + return sprintf(buf, "%u\n", wdd->bootstatus);
  160. +}
  161. +static DEVICE_ATTR_RO(bootstatus);
  162. +
  163. +static ssize_t timeleft_show(struct device *dev, struct device_attribute *attr,
  164. + char *buf)
  165. +{
  166. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  167. + ssize_t status;
  168. + unsigned int val;
  169. +
  170. + status = watchdog_get_timeleft(wdd, &val);
  171. + if (!status)
  172. + status = sprintf(buf, "%u\n", val);
  173. +
  174. + return status;
  175. +}
  176. +static DEVICE_ATTR_RO(timeleft);
  177. +
  178. +static ssize_t timeout_show(struct device *dev, struct device_attribute *attr,
  179. + char *buf)
  180. +{
  181. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  182. +
  183. + return sprintf(buf, "%u\n", wdd->timeout);
  184. +}
  185. +static DEVICE_ATTR_RO(timeout);
  186. +
  187. +static ssize_t identity_show(struct device *dev, struct device_attribute *attr,
  188. + char *buf)
  189. +{
  190. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  191. +
  192. + return sprintf(buf, "%s\n", wdd->info->identity);
  193. +}
  194. +static DEVICE_ATTR_RO(identity);
  195. +
  196. +static ssize_t state_show(struct device *dev, struct device_attribute *attr,
  197. + char *buf)
  198. +{
  199. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  200. +
  201. + if (watchdog_active(wdd))
  202. + return sprintf(buf, "active\n");
  203. +
  204. + return sprintf(buf, "inactive\n");
  205. +}
  206. +static DEVICE_ATTR_RO(state);
  207. +
  208. +static umode_t wdt_is_visible(struct kobject *kobj, struct attribute *attr,
  209. + int n)
  210. +{
  211. + struct device *dev = container_of(kobj, struct device, kobj);
  212. + struct watchdog_device *wdd = dev_get_drvdata(dev);
  213. + umode_t mode = attr->mode;
  214. +
  215. + if (attr == &dev_attr_status.attr && !wdd->ops->status)
  216. + mode = 0;
  217. + else if (attr == &dev_attr_timeleft.attr && !wdd->ops->get_timeleft)
  218. + mode = 0;
  219. +
  220. + return mode;
  221. +}
  222. +static struct attribute *wdt_attrs[] = {
  223. + &dev_attr_state.attr,
  224. + &dev_attr_identity.attr,
  225. + &dev_attr_timeout.attr,
  226. + &dev_attr_timeleft.attr,
  227. + &dev_attr_bootstatus.attr,
  228. + &dev_attr_status.attr,
  229. + &dev_attr_nowayout.attr,
  230. + NULL,
  231. +};
  232. +
  233. +static const struct attribute_group wdt_group = {
  234. + .attrs = wdt_attrs,
  235. + .is_visible = wdt_is_visible,
  236. +};
  237. +__ATTRIBUTE_GROUPS(wdt);
  238. +#else
  239. +#define wdt_groups NULL
  240. +#endif
  241. +
  242. /*
  243. * watchdog_ioctl_op: call the watchdog drivers ioctl op if defined
  244. * @wdd: the watchdog device to do the ioctl on
  245. @@ -584,6 +697,7 @@ int watchdog_dev_unregister(struct watch
  246. static struct class watchdog_class = {
  247. .name = "watchdog",
  248. .owner = THIS_MODULE,
  249. + .dev_groups = wdt_groups,
  250. };
  251. /*