0001
0002
0003
0004
0005
0006 #include <linux/list.h>
0007 #include <linux/slab.h>
0008 #include <linux/spinlock.h>
0009 #include <linux/string.h>
0010 #include <linux/watchdog.h>
0011
0012 #include "watchdog_core.h"
0013 #include "watchdog_pretimeout.h"
0014
0015
0016 static struct watchdog_governor *default_gov;
0017
0018
0019 static DEFINE_SPINLOCK(pretimeout_lock);
0020
0021
0022 static LIST_HEAD(pretimeout_list);
0023
0024 struct watchdog_pretimeout {
0025 struct watchdog_device *wdd;
0026 struct list_head entry;
0027 };
0028
0029
0030 static DEFINE_MUTEX(governor_lock);
0031
0032
0033 static LIST_HEAD(governor_list);
0034
0035 struct governor_priv {
0036 struct watchdog_governor *gov;
0037 struct list_head entry;
0038 };
0039
0040 static struct governor_priv *find_governor_by_name(const char *gov_name)
0041 {
0042 struct governor_priv *priv;
0043
0044 list_for_each_entry(priv, &governor_list, entry)
0045 if (sysfs_streq(gov_name, priv->gov->name))
0046 return priv;
0047
0048 return NULL;
0049 }
0050
0051 int watchdog_pretimeout_available_governors_get(char *buf)
0052 {
0053 struct governor_priv *priv;
0054 int count = 0;
0055
0056 mutex_lock(&governor_lock);
0057
0058 list_for_each_entry(priv, &governor_list, entry)
0059 count += sysfs_emit_at(buf, count, "%s\n", priv->gov->name);
0060
0061 mutex_unlock(&governor_lock);
0062
0063 return count;
0064 }
0065
0066 int watchdog_pretimeout_governor_get(struct watchdog_device *wdd, char *buf)
0067 {
0068 int count = 0;
0069
0070 spin_lock_irq(&pretimeout_lock);
0071 if (wdd->gov)
0072 count = sysfs_emit(buf, "%s\n", wdd->gov->name);
0073 spin_unlock_irq(&pretimeout_lock);
0074
0075 return count;
0076 }
0077
0078 int watchdog_pretimeout_governor_set(struct watchdog_device *wdd,
0079 const char *buf)
0080 {
0081 struct governor_priv *priv;
0082
0083 mutex_lock(&governor_lock);
0084
0085 priv = find_governor_by_name(buf);
0086 if (!priv) {
0087 mutex_unlock(&governor_lock);
0088 return -EINVAL;
0089 }
0090
0091 spin_lock_irq(&pretimeout_lock);
0092 wdd->gov = priv->gov;
0093 spin_unlock_irq(&pretimeout_lock);
0094
0095 mutex_unlock(&governor_lock);
0096
0097 return 0;
0098 }
0099
0100 void watchdog_notify_pretimeout(struct watchdog_device *wdd)
0101 {
0102 unsigned long flags;
0103
0104 spin_lock_irqsave(&pretimeout_lock, flags);
0105 if (!wdd->gov) {
0106 spin_unlock_irqrestore(&pretimeout_lock, flags);
0107 return;
0108 }
0109
0110 wdd->gov->pretimeout(wdd);
0111 spin_unlock_irqrestore(&pretimeout_lock, flags);
0112 }
0113 EXPORT_SYMBOL_GPL(watchdog_notify_pretimeout);
0114
0115 int watchdog_register_governor(struct watchdog_governor *gov)
0116 {
0117 struct watchdog_pretimeout *p;
0118 struct governor_priv *priv;
0119
0120 priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0121 if (!priv)
0122 return -ENOMEM;
0123
0124 mutex_lock(&governor_lock);
0125
0126 if (find_governor_by_name(gov->name)) {
0127 mutex_unlock(&governor_lock);
0128 kfree(priv);
0129 return -EBUSY;
0130 }
0131
0132 priv->gov = gov;
0133 list_add(&priv->entry, &governor_list);
0134
0135 if (!strncmp(gov->name, WATCHDOG_PRETIMEOUT_DEFAULT_GOV,
0136 WATCHDOG_GOV_NAME_MAXLEN)) {
0137 spin_lock_irq(&pretimeout_lock);
0138 default_gov = gov;
0139
0140 list_for_each_entry(p, &pretimeout_list, entry)
0141 if (!p->wdd->gov)
0142 p->wdd->gov = default_gov;
0143 spin_unlock_irq(&pretimeout_lock);
0144 }
0145
0146 mutex_unlock(&governor_lock);
0147
0148 return 0;
0149 }
0150 EXPORT_SYMBOL(watchdog_register_governor);
0151
0152 void watchdog_unregister_governor(struct watchdog_governor *gov)
0153 {
0154 struct watchdog_pretimeout *p;
0155 struct governor_priv *priv, *t;
0156
0157 mutex_lock(&governor_lock);
0158
0159 list_for_each_entry_safe(priv, t, &governor_list, entry) {
0160 if (priv->gov == gov) {
0161 list_del(&priv->entry);
0162 kfree(priv);
0163 break;
0164 }
0165 }
0166
0167 spin_lock_irq(&pretimeout_lock);
0168 list_for_each_entry(p, &pretimeout_list, entry)
0169 if (p->wdd->gov == gov)
0170 p->wdd->gov = default_gov;
0171 spin_unlock_irq(&pretimeout_lock);
0172
0173 mutex_unlock(&governor_lock);
0174 }
0175 EXPORT_SYMBOL(watchdog_unregister_governor);
0176
0177 int watchdog_register_pretimeout(struct watchdog_device *wdd)
0178 {
0179 struct watchdog_pretimeout *p;
0180
0181 if (!watchdog_have_pretimeout(wdd))
0182 return 0;
0183
0184 p = kzalloc(sizeof(*p), GFP_KERNEL);
0185 if (!p)
0186 return -ENOMEM;
0187
0188 spin_lock_irq(&pretimeout_lock);
0189 list_add(&p->entry, &pretimeout_list);
0190 p->wdd = wdd;
0191 wdd->gov = default_gov;
0192 spin_unlock_irq(&pretimeout_lock);
0193
0194 return 0;
0195 }
0196
0197 void watchdog_unregister_pretimeout(struct watchdog_device *wdd)
0198 {
0199 struct watchdog_pretimeout *p, *t;
0200
0201 if (!watchdog_have_pretimeout(wdd))
0202 return;
0203
0204 spin_lock_irq(&pretimeout_lock);
0205 wdd->gov = NULL;
0206
0207 list_for_each_entry_safe(p, t, &pretimeout_list, entry) {
0208 if (p->wdd == wdd) {
0209 list_del(&p->entry);
0210 break;
0211 }
0212 }
0213 spin_unlock_irq(&pretimeout_lock);
0214
0215 kfree(p);
0216 }