2 * Copyright (C) 2015-2016 Mentor Graphics
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
11 #include <linux/list.h>
12 #include <linux/slab.h>
13 #include <linux/spinlock.h>
14 #include <linux/string.h>
15 #include <linux/watchdog.h>
17 #include "watchdog_pretimeout.h"
19 /* Default watchdog pretimeout governor */
20 static struct watchdog_governor
*default_gov
;
22 /* The spinlock protects default_gov, wdd->gov and pretimeout_list */
23 static DEFINE_SPINLOCK(pretimeout_lock
);
25 /* List of watchdog devices, which can generate a pretimeout event */
26 static LIST_HEAD(pretimeout_list
);
28 struct watchdog_pretimeout
{
29 struct watchdog_device
*wdd
;
30 struct list_head entry
;
33 /* The mutex protects governor list and serializes external interfaces */
34 static DEFINE_MUTEX(governor_lock
);
36 /* List of the registered watchdog pretimeout governors */
37 static LIST_HEAD(governor_list
);
39 struct governor_priv
{
40 struct watchdog_governor
*gov
;
41 struct list_head entry
;
44 static struct governor_priv
*find_governor_by_name(const char *gov_name
)
46 struct governor_priv
*priv
;
48 list_for_each_entry(priv
, &governor_list
, entry
)
49 if (sysfs_streq(gov_name
, priv
->gov
->name
))
55 int watchdog_pretimeout_available_governors_get(char *buf
)
57 struct governor_priv
*priv
;
60 mutex_lock(&governor_lock
);
62 list_for_each_entry(priv
, &governor_list
, entry
)
63 count
+= sprintf(buf
+ count
, "%s\n", priv
->gov
->name
);
65 mutex_unlock(&governor_lock
);
70 int watchdog_pretimeout_governor_get(struct watchdog_device
*wdd
, char *buf
)
74 spin_lock_irq(&pretimeout_lock
);
76 count
= sprintf(buf
, "%s\n", wdd
->gov
->name
);
77 spin_unlock_irq(&pretimeout_lock
);
82 int watchdog_pretimeout_governor_set(struct watchdog_device
*wdd
,
85 struct governor_priv
*priv
;
87 mutex_lock(&governor_lock
);
89 priv
= find_governor_by_name(buf
);
91 mutex_unlock(&governor_lock
);
95 spin_lock_irq(&pretimeout_lock
);
97 spin_unlock_irq(&pretimeout_lock
);
99 mutex_unlock(&governor_lock
);
104 void watchdog_notify_pretimeout(struct watchdog_device
*wdd
)
108 spin_lock_irqsave(&pretimeout_lock
, flags
);
110 spin_unlock_irqrestore(&pretimeout_lock
, flags
);
114 wdd
->gov
->pretimeout(wdd
);
115 spin_unlock_irqrestore(&pretimeout_lock
, flags
);
117 EXPORT_SYMBOL_GPL(watchdog_notify_pretimeout
);
119 int watchdog_register_governor(struct watchdog_governor
*gov
)
121 struct watchdog_pretimeout
*p
;
122 struct governor_priv
*priv
;
124 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
128 mutex_lock(&governor_lock
);
130 if (find_governor_by_name(gov
->name
)) {
131 mutex_unlock(&governor_lock
);
137 list_add(&priv
->entry
, &governor_list
);
139 if (!strncmp(gov
->name
, WATCHDOG_PRETIMEOUT_DEFAULT_GOV
,
140 WATCHDOG_GOV_NAME_MAXLEN
)) {
141 spin_lock_irq(&pretimeout_lock
);
144 list_for_each_entry(p
, &pretimeout_list
, entry
)
146 p
->wdd
->gov
= default_gov
;
147 spin_unlock_irq(&pretimeout_lock
);
150 mutex_unlock(&governor_lock
);
154 EXPORT_SYMBOL(watchdog_register_governor
);
156 void watchdog_unregister_governor(struct watchdog_governor
*gov
)
158 struct watchdog_pretimeout
*p
;
159 struct governor_priv
*priv
, *t
;
161 mutex_lock(&governor_lock
);
163 list_for_each_entry_safe(priv
, t
, &governor_list
, entry
) {
164 if (priv
->gov
== gov
) {
165 list_del(&priv
->entry
);
171 spin_lock_irq(&pretimeout_lock
);
172 list_for_each_entry(p
, &pretimeout_list
, entry
)
173 if (p
->wdd
->gov
== gov
)
174 p
->wdd
->gov
= default_gov
;
175 spin_unlock_irq(&pretimeout_lock
);
177 mutex_unlock(&governor_lock
);
179 EXPORT_SYMBOL(watchdog_unregister_governor
);
181 int watchdog_register_pretimeout(struct watchdog_device
*wdd
)
183 struct watchdog_pretimeout
*p
;
185 if (!(wdd
->info
->options
& WDIOF_PRETIMEOUT
))
188 p
= kzalloc(sizeof(*p
), GFP_KERNEL
);
192 spin_lock_irq(&pretimeout_lock
);
193 list_add(&p
->entry
, &pretimeout_list
);
195 wdd
->gov
= default_gov
;
196 spin_unlock_irq(&pretimeout_lock
);
201 void watchdog_unregister_pretimeout(struct watchdog_device
*wdd
)
203 struct watchdog_pretimeout
*p
, *t
;
205 if (!(wdd
->info
->options
& WDIOF_PRETIMEOUT
))
208 spin_lock_irq(&pretimeout_lock
);
211 list_for_each_entry_safe(p
, t
, &pretimeout_list
, entry
) {
217 spin_unlock_irq(&pretimeout_lock
);