ipq806x: set v4.9 as default
[openwrt/openwrt.git] / target / linux / ipq806x / patches-4.4 / 009-1-watchdog-core-add-restart-handler-support.patch
1 From 2165bf524da5f5e496d1cdb8c5afae1345ecce1e Mon Sep 17 00:00:00 2001
2 From: Damien Riegel <damien.riegel@savoirfairelinux.com>
3 Date: Mon, 16 Nov 2015 12:27:59 -0500
4 Subject: watchdog: core: add restart handler support
5
6 Many watchdog drivers implement the same code to register a restart
7 handler. This patch provides a generic way to set such a function.
8
9 The patch adds a new restart watchdog operation. If a restart priority
10 greater than 0 is needed, the driver can call
11 watchdog_set_restart_priority to set it.
12
13 Suggested-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
14 Signed-off-by: Damien Riegel <damien.riegel@savoirfairelinux.com>
15 Reviewed-by: Guenter Roeck <linux@roeck-us.net>
16 Reviewed-by: Vivien Didelot <vivien.didelot@savoirfairelinux.com>
17 Signed-off-by: Guenter Roeck <linux@roeck-us.net>
18 Signed-off-by: Wim Van Sebroeck <wim@iguana.be>
19 ---
20 Documentation/watchdog/watchdog-kernel-api.txt | 19 ++++++++++
21 drivers/watchdog/watchdog_core.c | 48 ++++++++++++++++++++++++++
22 include/linux/watchdog.h | 6 ++++
23 3 files changed, 73 insertions(+)
24
25 --- a/Documentation/watchdog/watchdog-kernel-api.txt
26 +++ b/Documentation/watchdog/watchdog-kernel-api.txt
27 @@ -53,6 +53,7 @@ struct watchdog_device {
28 unsigned int timeout;
29 unsigned int min_timeout;
30 unsigned int max_timeout;
31 + struct notifier_block restart_nb;
32 void *driver_data;
33 struct mutex lock;
34 unsigned long status;
35 @@ -75,6 +76,10 @@ It contains following fields:
36 * timeout: the watchdog timer's timeout value (in seconds).
37 * min_timeout: the watchdog timer's minimum timeout value (in seconds).
38 * max_timeout: the watchdog timer's maximum timeout value (in seconds).
39 +* restart_nb: notifier block that is registered for machine restart, for
40 + internal use only. If a watchdog is capable of restarting the machine, it
41 + should define ops->restart. Priority can be changed through
42 + watchdog_set_restart_priority.
43 * bootstatus: status of the device after booting (reported with watchdog
44 WDIOF_* status bits).
45 * driver_data: a pointer to the drivers private data of a watchdog device.
46 @@ -100,6 +105,7 @@ struct watchdog_ops {
47 unsigned int (*status)(struct watchdog_device *);
48 int (*set_timeout)(struct watchdog_device *, unsigned int);
49 unsigned int (*get_timeleft)(struct watchdog_device *);
50 + int (*restart)(struct watchdog_device *);
51 void (*ref)(struct watchdog_device *);
52 void (*unref)(struct watchdog_device *);
53 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
54 @@ -164,6 +170,8 @@ they are supported. These optional routi
55 (Note: the WDIOF_SETTIMEOUT needs to be set in the options field of the
56 watchdog's info structure).
57 * get_timeleft: this routines returns the time that's left before a reset.
58 +* restart: this routine restarts the machine. It returns 0 on success or a
59 + negative errno code for failure.
60 * ref: the operation that calls kref_get on the kref of a dynamically
61 allocated watchdog_device struct.
62 * unref: the operation that calls kref_put on the kref of a dynamically
63 @@ -231,3 +239,14 @@ the device tree (if the module timeout p
64 to set the default timeout value as timeout value in the watchdog_device and
65 then use this function to set the user "preferred" timeout value.
66 This routine returns zero on success and a negative errno code for failure.
67 +
68 +To change the priority of the restart handler the following helper should be
69 +used:
70 +
71 +void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority);
72 +
73 +User should follow the following guidelines for setting the priority:
74 +* 0: should be called in last resort, has limited restart capabilities
75 +* 128: default restart handler, use if no other handler is expected to be
76 + available, and/or if restart is sufficient to restart the entire system
77 +* 255: highest priority, will preempt all other restart handlers
78 --- a/drivers/watchdog/watchdog_core.c
79 +++ b/drivers/watchdog/watchdog_core.c
80 @@ -32,6 +32,7 @@
81 #include <linux/types.h> /* For standard types */
82 #include <linux/errno.h> /* For the -ENODEV/... values */
83 #include <linux/kernel.h> /* For printk/panic/... */
84 +#include <linux/reboot.h> /* For restart handler */
85 #include <linux/watchdog.h> /* For watchdog specific items */
86 #include <linux/init.h> /* For __init/__exit/... */
87 #include <linux/idr.h> /* For ida_* macros */
88 @@ -137,6 +138,41 @@ int watchdog_init_timeout(struct watchdo
89 }
90 EXPORT_SYMBOL_GPL(watchdog_init_timeout);
91
92 +static int watchdog_restart_notifier(struct notifier_block *nb,
93 + unsigned long action, void *data)
94 +{
95 + struct watchdog_device *wdd = container_of(nb, struct watchdog_device,
96 + restart_nb);
97 +
98 + int ret;
99 +
100 + ret = wdd->ops->restart(wdd);
101 + if (ret)
102 + return NOTIFY_BAD;
103 +
104 + return NOTIFY_DONE;
105 +}
106 +
107 +/**
108 + * watchdog_set_restart_priority - Change priority of restart handler
109 + * @wdd: watchdog device
110 + * @priority: priority of the restart handler, should follow these guidelines:
111 + * 0: use watchdog's restart function as last resort, has limited restart
112 + * capabilies
113 + * 128: default restart handler, use if no other handler is expected to be
114 + * available and/or if restart is sufficient to restart the entire system
115 + * 255: preempt all other handlers
116 + *
117 + * If a wdd->ops->restart function is provided when watchdog_register_device is
118 + * called, it will be registered as a restart handler with the priority given
119 + * here.
120 + */
121 +void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority)
122 +{
123 + wdd->restart_nb.priority = priority;
124 +}
125 +EXPORT_SYMBOL_GPL(watchdog_set_restart_priority);
126 +
127 static int __watchdog_register_device(struct watchdog_device *wdd)
128 {
129 int ret, id = -1, devno;
130 @@ -202,6 +238,15 @@ static int __watchdog_register_device(st
131 return ret;
132 }
133
134 + if (wdd->ops->restart) {
135 + wdd->restart_nb.notifier_call = watchdog_restart_notifier;
136 +
137 + ret = register_restart_handler(&wdd->restart_nb);
138 + if (ret)
139 + dev_warn(wdd->dev, "Cannot register restart handler (%d)\n",
140 + ret);
141 + }
142 +
143 return 0;
144 }
145
146 @@ -238,6 +283,9 @@ static void __watchdog_unregister_device
147 if (wdd == NULL)
148 return;
149
150 + if (wdd->ops->restart)
151 + unregister_restart_handler(&wdd->restart_nb);
152 +
153 devno = wdd->cdev.dev;
154 ret = watchdog_dev_unregister(wdd);
155 if (ret)
156 --- a/include/linux/watchdog.h
157 +++ b/include/linux/watchdog.h
158 @@ -12,6 +12,7 @@
159 #include <linux/bitops.h>
160 #include <linux/device.h>
161 #include <linux/cdev.h>
162 +#include <linux/notifier.h>
163 #include <uapi/linux/watchdog.h>
164
165 struct watchdog_ops;
166 @@ -26,6 +27,7 @@ struct watchdog_device;
167 * @status: The routine that shows the status of the watchdog device.
168 * @set_timeout:The routine for setting the watchdog devices timeout value (in seconds).
169 * @get_timeleft:The routine that gets the time left before a reset (in seconds).
170 + * @restart: The routine for restarting the machine.
171 * @ref: The ref operation for dyn. allocated watchdog_device structs
172 * @unref: The unref operation for dyn. allocated watchdog_device structs
173 * @ioctl: The routines that handles extra ioctl calls.
174 @@ -45,6 +47,7 @@ struct watchdog_ops {
175 unsigned int (*status)(struct watchdog_device *);
176 int (*set_timeout)(struct watchdog_device *, unsigned int);
177 unsigned int (*get_timeleft)(struct watchdog_device *);
178 + int (*restart)(struct watchdog_device *);
179 void (*ref)(struct watchdog_device *);
180 void (*unref)(struct watchdog_device *);
181 long (*ioctl)(struct watchdog_device *, unsigned int, unsigned long);
182 @@ -62,6 +65,7 @@ struct watchdog_ops {
183 * @timeout: The watchdog devices timeout value (in seconds).
184 * @min_timeout:The watchdog devices minimum timeout value (in seconds).
185 * @max_timeout:The watchdog devices maximum timeout value (in seconds).
186 + * @restart_nb: The notifier block to register a restart function.
187 * @driver-data:Pointer to the drivers private data.
188 * @lock: Lock for watchdog core internal use only.
189 * @status: Field that contains the devices internal status bits.
190 @@ -88,6 +92,7 @@ struct watchdog_device {
191 unsigned int timeout;
192 unsigned int min_timeout;
193 unsigned int max_timeout;
194 + struct notifier_block restart_nb;
195 void *driver_data;
196 struct mutex lock;
197 unsigned long status;
198 @@ -142,6 +147,7 @@ static inline void *watchdog_get_drvdata
199 }
200
201 /* drivers/watchdog/watchdog_core.c */
202 +void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority);
203 extern int watchdog_init_timeout(struct watchdog_device *wdd,
204 unsigned int timeout_parm, struct device *dev);
205 extern int watchdog_register_device(struct watchdog_device *);