1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015-2016 Mentor Graphics
6 #include <linux/list.h>
7 #include <linux/slab.h>
8 #include <linux/spinlock.h>
9 #include <linux/string.h>
10 #include <linux/watchdog.h>
12 #include "watchdog_core.h"
13 #include "watchdog_pretimeout.h"
15 /* Default watchdog pretimeout governor */
16 static struct watchdog_governor
*default_gov
;
18 /* The spinlock protects default_gov, wdd->gov and pretimeout_list */
19 static DEFINE_SPINLOCK(pretimeout_lock
);
21 /* List of watchdog devices, which can generate a pretimeout event */
22 static LIST_HEAD(pretimeout_list
);
24 struct watchdog_pretimeout
{
25 struct watchdog_device
*wdd
;
26 struct list_head entry
;
29 /* The mutex protects governor list and serializes external interfaces */
30 static DEFINE_MUTEX(governor_lock
);
32 /* List of the registered watchdog pretimeout governors */
33 static LIST_HEAD(governor_list
);
35 struct governor_priv
{
36 struct watchdog_governor
*gov
;
37 struct list_head entry
;
40 static struct governor_priv
*find_governor_by_name(const char *gov_name
)
42 struct governor_priv
*priv
;
44 list_for_each_entry(priv
, &governor_list
, entry
)
45 if (sysfs_streq(gov_name
, priv
->gov
->name
))
51 int watchdog_pretimeout_available_governors_get(char *buf
)
53 struct governor_priv
*priv
;
56 mutex_lock(&governor_lock
);
58 list_for_each_entry(priv
, &governor_list
, entry
)
59 count
+= sysfs_emit_at(buf
, count
, "%s\n", priv
->gov
->name
);
61 mutex_unlock(&governor_lock
);
66 int watchdog_pretimeout_governor_get(struct watchdog_device
*wdd
, char *buf
)
70 spin_lock_irq(&pretimeout_lock
);
72 count
= sysfs_emit(buf
, "%s\n", wdd
->gov
->name
);
73 spin_unlock_irq(&pretimeout_lock
);
78 int watchdog_pretimeout_governor_set(struct watchdog_device
*wdd
,
81 struct governor_priv
*priv
;
83 mutex_lock(&governor_lock
);
85 priv
= find_governor_by_name(buf
);
87 mutex_unlock(&governor_lock
);
91 spin_lock_irq(&pretimeout_lock
);
93 spin_unlock_irq(&pretimeout_lock
);
95 mutex_unlock(&governor_lock
);
100 void watchdog_notify_pretimeout(struct watchdog_device
*wdd
)
104 spin_lock_irqsave(&pretimeout_lock
, flags
);
106 spin_unlock_irqrestore(&pretimeout_lock
, flags
);
110 wdd
->gov
->pretimeout(wdd
);
111 spin_unlock_irqrestore(&pretimeout_lock
, flags
);
113 EXPORT_SYMBOL_GPL(watchdog_notify_pretimeout
);
115 int watchdog_register_governor(struct watchdog_governor
*gov
)
117 struct watchdog_pretimeout
*p
;
118 struct governor_priv
*priv
;
120 priv
= kzalloc(sizeof(*priv
), GFP_KERNEL
);
124 mutex_lock(&governor_lock
);
126 if (find_governor_by_name(gov
->name
)) {
127 mutex_unlock(&governor_lock
);
133 list_add(&priv
->entry
, &governor_list
);
135 if (!strncmp(gov
->name
, WATCHDOG_PRETIMEOUT_DEFAULT_GOV
,
136 WATCHDOG_GOV_NAME_MAXLEN
)) {
137 spin_lock_irq(&pretimeout_lock
);
140 list_for_each_entry(p
, &pretimeout_list
, entry
)
142 p
->wdd
->gov
= default_gov
;
143 spin_unlock_irq(&pretimeout_lock
);
146 mutex_unlock(&governor_lock
);
150 EXPORT_SYMBOL(watchdog_register_governor
);
152 void watchdog_unregister_governor(struct watchdog_governor
*gov
)
154 struct watchdog_pretimeout
*p
;
155 struct governor_priv
*priv
, *t
;
157 mutex_lock(&governor_lock
);
159 list_for_each_entry_safe(priv
, t
, &governor_list
, entry
) {
160 if (priv
->gov
== gov
) {
161 list_del(&priv
->entry
);
167 spin_lock_irq(&pretimeout_lock
);
168 list_for_each_entry(p
, &pretimeout_list
, entry
)
169 if (p
->wdd
->gov
== gov
)
170 p
->wdd
->gov
= default_gov
;
171 spin_unlock_irq(&pretimeout_lock
);
173 mutex_unlock(&governor_lock
);
175 EXPORT_SYMBOL(watchdog_unregister_governor
);
177 int watchdog_register_pretimeout(struct watchdog_device
*wdd
)
179 struct watchdog_pretimeout
*p
;
181 if (!watchdog_have_pretimeout(wdd
))
184 p
= kzalloc(sizeof(*p
), GFP_KERNEL
);
188 spin_lock_irq(&pretimeout_lock
);
189 list_add(&p
->entry
, &pretimeout_list
);
191 wdd
->gov
= default_gov
;
192 spin_unlock_irq(&pretimeout_lock
);
197 void watchdog_unregister_pretimeout(struct watchdog_device
*wdd
)
199 struct watchdog_pretimeout
*p
, *t
;
201 if (!watchdog_have_pretimeout(wdd
))
204 spin_lock_irq(&pretimeout_lock
);
207 list_for_each_entry_safe(p
, t
, &pretimeout_list
, entry
) {
214 spin_unlock_irq(&pretimeout_lock
);