watchdog_pretimeout.c 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright (C) 2015-2016 Mentor Graphics
  4. */
  5. #include <linux/list.h>
  6. #include <linux/slab.h>
  7. #include <linux/spinlock.h>
  8. #include <linux/string.h>
  9. #include <linux/watchdog.h>
  10. #include "watchdog_pretimeout.h"
  11. /* Default watchdog pretimeout governor */
  12. static struct watchdog_governor *default_gov;
  13. /* The spinlock protects default_gov, wdd->gov and pretimeout_list */
  14. static DEFINE_SPINLOCK(pretimeout_lock);
  15. /* List of watchdog devices, which can generate a pretimeout event */
  16. static LIST_HEAD(pretimeout_list);
  17. struct watchdog_pretimeout {
  18. struct watchdog_device *wdd;
  19. struct list_head entry;
  20. };
  21. /* The mutex protects governor list and serializes external interfaces */
  22. static DEFINE_MUTEX(governor_lock);
  23. /* List of the registered watchdog pretimeout governors */
  24. static LIST_HEAD(governor_list);
  25. struct governor_priv {
  26. struct watchdog_governor *gov;
  27. struct list_head entry;
  28. };
  29. static struct governor_priv *find_governor_by_name(const char *gov_name)
  30. {
  31. struct governor_priv *priv;
  32. list_for_each_entry(priv, &governor_list, entry)
  33. if (sysfs_streq(gov_name, priv->gov->name))
  34. return priv;
  35. return NULL;
  36. }
  37. int watchdog_pretimeout_available_governors_get(char *buf)
  38. {
  39. struct governor_priv *priv;
  40. int count = 0;
  41. mutex_lock(&governor_lock);
  42. list_for_each_entry(priv, &governor_list, entry)
  43. count += sprintf(buf + count, "%s\n", priv->gov->name);
  44. mutex_unlock(&governor_lock);
  45. return count;
  46. }
  47. int watchdog_pretimeout_governor_get(struct watchdog_device *wdd, char *buf)
  48. {
  49. int count = 0;
  50. spin_lock_irq(&pretimeout_lock);
  51. if (wdd->gov)
  52. count = sprintf(buf, "%s\n", wdd->gov->name);
  53. spin_unlock_irq(&pretimeout_lock);
  54. return count;
  55. }
  56. int watchdog_pretimeout_governor_set(struct watchdog_device *wdd,
  57. const char *buf)
  58. {
  59. struct governor_priv *priv;
  60. mutex_lock(&governor_lock);
  61. priv = find_governor_by_name(buf);
  62. if (!priv) {
  63. mutex_unlock(&governor_lock);
  64. return -EINVAL;
  65. }
  66. spin_lock_irq(&pretimeout_lock);
  67. wdd->gov = priv->gov;
  68. spin_unlock_irq(&pretimeout_lock);
  69. mutex_unlock(&governor_lock);
  70. return 0;
  71. }
  72. void watchdog_notify_pretimeout(struct watchdog_device *wdd)
  73. {
  74. unsigned long flags;
  75. spin_lock_irqsave(&pretimeout_lock, flags);
  76. if (!wdd->gov) {
  77. spin_unlock_irqrestore(&pretimeout_lock, flags);
  78. return;
  79. }
  80. wdd->gov->pretimeout(wdd);
  81. spin_unlock_irqrestore(&pretimeout_lock, flags);
  82. }
  83. EXPORT_SYMBOL_GPL(watchdog_notify_pretimeout);
  84. int watchdog_register_governor(struct watchdog_governor *gov)
  85. {
  86. struct watchdog_pretimeout *p;
  87. struct governor_priv *priv;
  88. priv = kzalloc(sizeof(*priv), GFP_KERNEL);
  89. if (!priv)
  90. return -ENOMEM;
  91. mutex_lock(&governor_lock);
  92. if (find_governor_by_name(gov->name)) {
  93. mutex_unlock(&governor_lock);
  94. kfree(priv);
  95. return -EBUSY;
  96. }
  97. priv->gov = gov;
  98. list_add(&priv->entry, &governor_list);
  99. if (!strncmp(gov->name, WATCHDOG_PRETIMEOUT_DEFAULT_GOV,
  100. WATCHDOG_GOV_NAME_MAXLEN)) {
  101. spin_lock_irq(&pretimeout_lock);
  102. default_gov = gov;
  103. list_for_each_entry(p, &pretimeout_list, entry)
  104. if (!p->wdd->gov)
  105. p->wdd->gov = default_gov;
  106. spin_unlock_irq(&pretimeout_lock);
  107. }
  108. mutex_unlock(&governor_lock);
  109. return 0;
  110. }
  111. EXPORT_SYMBOL(watchdog_register_governor);
  112. void watchdog_unregister_governor(struct watchdog_governor *gov)
  113. {
  114. struct watchdog_pretimeout *p;
  115. struct governor_priv *priv, *t;
  116. mutex_lock(&governor_lock);
  117. list_for_each_entry_safe(priv, t, &governor_list, entry) {
  118. if (priv->gov == gov) {
  119. list_del(&priv->entry);
  120. kfree(priv);
  121. break;
  122. }
  123. }
  124. spin_lock_irq(&pretimeout_lock);
  125. list_for_each_entry(p, &pretimeout_list, entry)
  126. if (p->wdd->gov == gov)
  127. p->wdd->gov = default_gov;
  128. spin_unlock_irq(&pretimeout_lock);
  129. mutex_unlock(&governor_lock);
  130. }
  131. EXPORT_SYMBOL(watchdog_unregister_governor);
  132. int watchdog_register_pretimeout(struct watchdog_device *wdd)
  133. {
  134. struct watchdog_pretimeout *p;
  135. if (!(wdd->info->options & WDIOF_PRETIMEOUT))
  136. return 0;
  137. p = kzalloc(sizeof(*p), GFP_KERNEL);
  138. if (!p)
  139. return -ENOMEM;
  140. spin_lock_irq(&pretimeout_lock);
  141. list_add(&p->entry, &pretimeout_list);
  142. p->wdd = wdd;
  143. wdd->gov = default_gov;
  144. spin_unlock_irq(&pretimeout_lock);
  145. return 0;
  146. }
  147. void watchdog_unregister_pretimeout(struct watchdog_device *wdd)
  148. {
  149. struct watchdog_pretimeout *p, *t;
  150. if (!(wdd->info->options & WDIOF_PRETIMEOUT))
  151. return;
  152. spin_lock_irq(&pretimeout_lock);
  153. wdd->gov = NULL;
  154. list_for_each_entry_safe(p, t, &pretimeout_list, entry) {
  155. if (p->wdd == wdd) {
  156. list_del(&p->entry);
  157. break;
  158. }
  159. }
  160. spin_unlock_irq(&pretimeout_lock);
  161. kfree(p);
  162. }