aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 13:11:12 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 13:11:12 -0500
commit42d4ebb42a17754d2e8344dc1aa486119671d0eb (patch)
treeb5a9e0a4ecc5a9041912102790bb089601c7afa4
parent6aabef681df96b851b4a11459520d4a20ab1cae4 (diff)
parent760d280084f8805e5de73e3591912d5db9da9dbe (diff)
Merge git://www.linux-watchdog.org/linux-watchdog
Pull watchdog update from Wim Van Sebroeck: - New driver for Broadcom 7038 Set-Top Box - imx2_wdt: Use register definition in regmap_write() - intel-mid: add Magic Closure flag - watchdog framework improvements: - Use device tree alias for naming watchdogs - propagate ping error code to the user space - Always evaluate new timeout against min_timeout - Use single variable name for struct watchdog_device - include clean-ups * git://www.linux-watchdog.org/linux-watchdog: watchdog: include: add units for timeout values in kerneldoc watchdog: include: fix some typos watchdog: core: propagate ping error code to the user space watchdog: watchdog_dev: Use single variable name for struct watchdog_device watchdog: Always evaluate new timeout against min_timeout watchdog: intel-mid: add Magic Closure flag watchdog: imx2_wdt: Use register definition in regmap_write() watchdog: watchdog_dev: Use device tree alias for naming watchdogs watchdog: Watchdog driver for Broadcom Set-Top Box watchdog: bcm7038: add device tree binding documentation
-rw-r--r--Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt19
-rw-r--r--drivers/watchdog/Kconfig8
-rw-r--r--drivers/watchdog/Makefile1
-rw-r--r--drivers/watchdog/bcm7038_wdt.c237
-rw-r--r--drivers/watchdog/imx2_wdt.c6
-rw-r--r--drivers/watchdog/intel-mid_wdt.c2
-rw-r--r--drivers/watchdog/watchdog_core.c15
-rw-r--r--drivers/watchdog/watchdog_dev.c163
-rw-r--r--include/linux/watchdog.h23
9 files changed, 380 insertions, 94 deletions
diff --git a/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
new file mode 100644
index 000000000000..84122270be8f
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/brcm,bcm7038-wdt.txt
@@ -0,0 +1,19 @@
1BCM7038 Watchdog timer
2
3Required properties:
4
5- compatible : should be "brcm,bcm7038-wdt"
6- reg : Specifies base physical address and size of the registers.
7
8Optional properties:
9
10- clocks: The clock running the watchdog. If no clock is found the
11 driver will default to 27000000 Hz.
12
13Example:
14
15watchdog@f040a7e8 {
16 compatible = "brcm,bcm7038-wdt";
17 clocks = <&upg_fixed>;
18 reg = <0xf040a7e8 0x16>;
19};
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 79e1aa1b0959..7a8a6c6952e9 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -1313,6 +1313,14 @@ config BCM_KONA_WDT_DEBUG
1313 1313
1314 If in doubt, say 'N'. 1314 If in doubt, say 'N'.
1315 1315
1316config BCM7038_WDT
1317 tristate "BCM7038 Watchdog"
1318 select WATCHDOG_CORE
1319 help
1320 Watchdog driver for the built-in hardware in Broadcom 7038 SoCs.
1321
1322 Say 'Y or 'M' here to enable the driver.
1323
1316config IMGPDC_WDT 1324config IMGPDC_WDT
1317 tristate "Imagination Technologies PDC Watchdog Timer" 1325 tristate "Imagination Technologies PDC Watchdog Timer"
1318 depends on HAS_IOMEM 1326 depends on HAS_IOMEM
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 0c616e3f67bb..53d4827ddfe1 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -68,6 +68,7 @@ obj-$(CONFIG_MESON_WATCHDOG) += meson_wdt.o
68obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o 68obj-$(CONFIG_MEDIATEK_WATCHDOG) += mtk_wdt.o
69obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o 69obj-$(CONFIG_DIGICOLOR_WATCHDOG) += digicolor_wdt.o
70obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o 70obj-$(CONFIG_LPC18XX_WATCHDOG) += lpc18xx_wdt.o
71obj-$(CONFIG_BCM7038_WDT) += bcm7038_wdt.o
71 72
72# AVR32 Architecture 73# AVR32 Architecture
73obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o 74obj-$(CONFIG_AT32AP700X_WDT) += at32ap700x_wdt.o
diff --git a/drivers/watchdog/bcm7038_wdt.c b/drivers/watchdog/bcm7038_wdt.c
new file mode 100644
index 000000000000..4245b65d645c
--- /dev/null
+++ b/drivers/watchdog/bcm7038_wdt.c
@@ -0,0 +1,237 @@
1/*
2 * Copyright (C) 2015 Broadcom Corporation
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/clk.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/module.h>
19#include <linux/of.h>
20#include <linux/platform_device.h>
21#include <linux/pm.h>
22#include <linux/watchdog.h>
23
24#define WDT_START_1 0xff00
25#define WDT_START_2 0x00ff
26#define WDT_STOP_1 0xee00
27#define WDT_STOP_2 0x00ee
28
29#define WDT_TIMEOUT_REG 0x0
30#define WDT_CMD_REG 0x4
31
32#define WDT_MIN_TIMEOUT 1 /* seconds */
33#define WDT_DEFAULT_TIMEOUT 30 /* seconds */
34#define WDT_DEFAULT_RATE 27000000
35
36struct bcm7038_watchdog {
37 void __iomem *base;
38 struct watchdog_device wdd;
39 u32 rate;
40 struct clk *clk;
41};
42
43static bool nowayout = WATCHDOG_NOWAYOUT;
44
45static void bcm7038_wdt_set_timeout_reg(struct watchdog_device *wdog)
46{
47 struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
48 u32 timeout;
49
50 timeout = wdt->rate * wdog->timeout;
51
52 writel(timeout, wdt->base + WDT_TIMEOUT_REG);
53}
54
55static int bcm7038_wdt_ping(struct watchdog_device *wdog)
56{
57 struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
58
59 writel(WDT_START_1, wdt->base + WDT_CMD_REG);
60 writel(WDT_START_2, wdt->base + WDT_CMD_REG);
61
62 return 0;
63}
64
65static int bcm7038_wdt_start(struct watchdog_device *wdog)
66{
67 bcm7038_wdt_set_timeout_reg(wdog);
68 bcm7038_wdt_ping(wdog);
69
70 return 0;
71}
72
73static int bcm7038_wdt_stop(struct watchdog_device *wdog)
74{
75 struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
76
77 writel(WDT_STOP_1, wdt->base + WDT_CMD_REG);
78 writel(WDT_STOP_2, wdt->base + WDT_CMD_REG);
79
80 return 0;
81}
82
83static int bcm7038_wdt_set_timeout(struct watchdog_device *wdog,
84 unsigned int t)
85{
86 /* Can't modify timeout value if watchdog timer is running */
87 bcm7038_wdt_stop(wdog);
88 wdog->timeout = t;
89 bcm7038_wdt_start(wdog);
90
91 return 0;
92}
93
94static unsigned int bcm7038_wdt_get_timeleft(struct watchdog_device *wdog)
95{
96 struct bcm7038_watchdog *wdt = watchdog_get_drvdata(wdog);
97 u32 time_left;
98
99 time_left = readl(wdt->base + WDT_CMD_REG);
100
101 return time_left / wdt->rate;
102}
103
104static struct watchdog_info bcm7038_wdt_info = {
105 .identity = "Broadcom BCM7038 Watchdog Timer",
106 .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING |
107 WDIOF_MAGICCLOSE
108};
109
110static struct watchdog_ops bcm7038_wdt_ops = {
111 .owner = THIS_MODULE,
112 .start = bcm7038_wdt_start,
113 .stop = bcm7038_wdt_stop,
114 .set_timeout = bcm7038_wdt_set_timeout,
115 .get_timeleft = bcm7038_wdt_get_timeleft,
116};
117
118static int bcm7038_wdt_probe(struct platform_device *pdev)
119{
120 struct device *dev = &pdev->dev;
121 struct bcm7038_watchdog *wdt;
122 struct resource *res;
123 int err;
124
125 wdt = devm_kzalloc(dev, sizeof(*wdt), GFP_KERNEL);
126 if (!wdt)
127 return -ENOMEM;
128
129 platform_set_drvdata(pdev, wdt);
130
131 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
132 wdt->base = devm_ioremap_resource(dev, res);
133 if (IS_ERR(wdt->base))
134 return PTR_ERR(wdt->base);
135
136 wdt->clk = devm_clk_get(dev, NULL);
137 /* If unable to get clock, use default frequency */
138 if (!IS_ERR(wdt->clk)) {
139 clk_prepare_enable(wdt->clk);
140 wdt->rate = clk_get_rate(wdt->clk);
141 /* Prevent divide-by-zero exception */
142 if (!wdt->rate)
143 wdt->rate = WDT_DEFAULT_RATE;
144 } else {
145 wdt->rate = WDT_DEFAULT_RATE;
146 wdt->clk = NULL;
147 }
148
149 wdt->wdd.info = &bcm7038_wdt_info;
150 wdt->wdd.ops = &bcm7038_wdt_ops;
151 wdt->wdd.min_timeout = WDT_MIN_TIMEOUT;
152 wdt->wdd.timeout = WDT_DEFAULT_TIMEOUT;
153 wdt->wdd.max_timeout = 0xffffffff / wdt->rate;
154 wdt->wdd.parent = dev;
155 watchdog_set_drvdata(&wdt->wdd, wdt);
156
157 err = watchdog_register_device(&wdt->wdd);
158 if (err) {
159 dev_err(dev, "Failed to register watchdog device\n");
160 clk_disable_unprepare(wdt->clk);
161 return err;
162 }
163
164 dev_info(dev, "Registered BCM7038 Watchdog\n");
165
166 return 0;
167}
168
169static int bcm7038_wdt_remove(struct platform_device *pdev)
170{
171 struct bcm7038_watchdog *wdt = platform_get_drvdata(pdev);
172
173 if (!nowayout)
174 bcm7038_wdt_stop(&wdt->wdd);
175
176 watchdog_unregister_device(&wdt->wdd);
177 clk_disable_unprepare(wdt->clk);
178
179 return 0;
180}
181
182#ifdef CONFIG_PM_SLEEP
183static int bcm7038_wdt_suspend(struct device *dev)
184{
185 struct bcm7038_watchdog *wdt = dev_get_drvdata(dev);
186
187 if (watchdog_active(&wdt->wdd))
188 return bcm7038_wdt_stop(&wdt->wdd);
189
190 return 0;
191}
192
193static int bcm7038_wdt_resume(struct device *dev)
194{
195 struct bcm7038_watchdog *wdt = dev_get_drvdata(dev);
196
197 if (watchdog_active(&wdt->wdd))
198 return bcm7038_wdt_start(&wdt->wdd);
199
200 return 0;
201}
202#endif
203
204static SIMPLE_DEV_PM_OPS(bcm7038_wdt_pm_ops, bcm7038_wdt_suspend,
205 bcm7038_wdt_resume);
206
207static void bcm7038_wdt_shutdown(struct platform_device *pdev)
208{
209 struct bcm7038_watchdog *wdt = platform_get_drvdata(pdev);
210
211 if (watchdog_active(&wdt->wdd))
212 bcm7038_wdt_stop(&wdt->wdd);
213}
214
215static const struct of_device_id bcm7038_wdt_match[] = {
216 { .compatible = "brcm,bcm7038-wdt" },
217 {},
218};
219
220static struct platform_driver bcm7038_wdt_driver = {
221 .probe = bcm7038_wdt_probe,
222 .remove = bcm7038_wdt_remove,
223 .shutdown = bcm7038_wdt_shutdown,
224 .driver = {
225 .name = "bcm7038-wdt",
226 .of_match_table = bcm7038_wdt_match,
227 .pm = &bcm7038_wdt_pm_ops,
228 }
229};
230module_platform_driver(bcm7038_wdt_driver);
231
232module_param(nowayout, bool, 0);
233MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
234 __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
235MODULE_LICENSE("GPL v2");
236MODULE_DESCRIPTION("Driver for Broadcom 7038 SoCs Watchdog");
237MODULE_AUTHOR("Justin Chen");
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 0bb1a1d1b170..29ef719a6a3c 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -91,7 +91,7 @@ static int imx2_restart_handler(struct notifier_block *this, unsigned long mode,
91 struct imx2_wdt_device, 91 struct imx2_wdt_device,
92 restart_handler); 92 restart_handler);
93 /* Assert SRS signal */ 93 /* Assert SRS signal */
94 regmap_write(wdev->regmap, 0, wcr_enable); 94 regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
95 /* 95 /*
96 * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be 96 * Due to imx6q errata ERR004346 (WDOG: WDOG SRS bit requires to be
97 * written twice), we add another two writes to ensure there must be at 97 * written twice), we add another two writes to ensure there must be at
@@ -99,8 +99,8 @@ static int imx2_restart_handler(struct notifier_block *this, unsigned long mode,
99 * the target check here, since the writes shouldn't be a huge burden 99 * the target check here, since the writes shouldn't be a huge burden
100 * for other platforms. 100 * for other platforms.
101 */ 101 */
102 regmap_write(wdev->regmap, 0, wcr_enable); 102 regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
103 regmap_write(wdev->regmap, 0, wcr_enable); 103 regmap_write(wdev->regmap, IMX2_WDT_WCR, wcr_enable);
104 104
105 /* wait for reset to assert... */ 105 /* wait for reset to assert... */
106 mdelay(500); 106 mdelay(500);
diff --git a/drivers/watchdog/intel-mid_wdt.c b/drivers/watchdog/intel-mid_wdt.c
index 0a436b5d1e84..db36d12e2b52 100644
--- a/drivers/watchdog/intel-mid_wdt.c
+++ b/drivers/watchdog/intel-mid_wdt.c
@@ -101,7 +101,7 @@ static irqreturn_t mid_wdt_irq(int irq, void *dev_id)
101 101
102static const struct watchdog_info mid_wdt_info = { 102static const struct watchdog_info mid_wdt_info = {
103 .identity = "Intel MID SCU watchdog", 103 .identity = "Intel MID SCU watchdog",
104 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT, 104 .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE,
105}; 105};
106 106
107static const struct watchdog_ops mid_wdt_ops = { 107static const struct watchdog_ops mid_wdt_ops = {
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 1a8059455413..873f13972cf4 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -139,7 +139,7 @@ EXPORT_SYMBOL_GPL(watchdog_init_timeout);
139 139
140static int __watchdog_register_device(struct watchdog_device *wdd) 140static int __watchdog_register_device(struct watchdog_device *wdd)
141{ 141{
142 int ret, id, devno; 142 int ret, id = -1, devno;
143 143
144 if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL) 144 if (wdd == NULL || wdd->info == NULL || wdd->ops == NULL)
145 return -EINVAL; 145 return -EINVAL;
@@ -157,7 +157,18 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
157 */ 157 */
158 158
159 mutex_init(&wdd->lock); 159 mutex_init(&wdd->lock);
160 id = ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL); 160
161 /* Use alias for watchdog id if possible */
162 if (wdd->parent) {
163 ret = of_alias_get_id(wdd->parent->of_node, "watchdog");
164 if (ret >= 0)
165 id = ida_simple_get(&watchdog_ida, ret,
166 ret + 1, GFP_KERNEL);
167 }
168
169 if (id < 0)
170 id = ida_simple_get(&watchdog_ida, 0, MAX_DOGS, GFP_KERNEL);
171
161 if (id < 0) 172 if (id < 0)
162 return id; 173 return id;
163 wdd->id = id; 174 wdd->id = id;
diff --git a/drivers/watchdog/watchdog_dev.c b/drivers/watchdog/watchdog_dev.c
index 6aaefbad303e..56a649e66eb2 100644
--- a/drivers/watchdog/watchdog_dev.c
+++ b/drivers/watchdog/watchdog_dev.c
@@ -51,7 +51,7 @@ static struct watchdog_device *old_wdd;
51 51
52/* 52/*
53 * watchdog_ping: ping the watchdog. 53 * watchdog_ping: ping the watchdog.
54 * @wddev: the watchdog device to ping 54 * @wdd: the watchdog device to ping
55 * 55 *
56 * If the watchdog has no own ping operation then it needs to be 56 * If the watchdog has no own ping operation then it needs to be
57 * restarted via the start operation. This wrapper function does 57 * restarted via the start operation. This wrapper function does
@@ -59,65 +59,65 @@ static struct watchdog_device *old_wdd;
59 * We only ping when the watchdog device is running. 59 * We only ping when the watchdog device is running.
60 */ 60 */
61 61
62static int watchdog_ping(struct watchdog_device *wddev) 62static int watchdog_ping(struct watchdog_device *wdd)
63{ 63{
64 int err = 0; 64 int err = 0;
65 65
66 mutex_lock(&wddev->lock); 66 mutex_lock(&wdd->lock);
67 67
68 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) { 68 if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
69 err = -ENODEV; 69 err = -ENODEV;
70 goto out_ping; 70 goto out_ping;
71 } 71 }
72 72
73 if (!watchdog_active(wddev)) 73 if (!watchdog_active(wdd))
74 goto out_ping; 74 goto out_ping;
75 75
76 if (wddev->ops->ping) 76 if (wdd->ops->ping)
77 err = wddev->ops->ping(wddev); /* ping the watchdog */ 77 err = wdd->ops->ping(wdd); /* ping the watchdog */
78 else 78 else
79 err = wddev->ops->start(wddev); /* restart watchdog */ 79 err = wdd->ops->start(wdd); /* restart watchdog */
80 80
81out_ping: 81out_ping:
82 mutex_unlock(&wddev->lock); 82 mutex_unlock(&wdd->lock);
83 return err; 83 return err;
84} 84}
85 85
86/* 86/*
87 * watchdog_start: wrapper to start the watchdog. 87 * watchdog_start: wrapper to start the watchdog.
88 * @wddev: the watchdog device to start 88 * @wdd: the watchdog device to start
89 * 89 *
90 * Start the watchdog if it is not active and mark it active. 90 * Start the watchdog if it is not active and mark it active.
91 * This function returns zero on success or a negative errno code for 91 * This function returns zero on success or a negative errno code for
92 * failure. 92 * failure.
93 */ 93 */
94 94
95static int watchdog_start(struct watchdog_device *wddev) 95static int watchdog_start(struct watchdog_device *wdd)
96{ 96{
97 int err = 0; 97 int err = 0;
98 98
99 mutex_lock(&wddev->lock); 99 mutex_lock(&wdd->lock);
100 100
101 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) { 101 if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
102 err = -ENODEV; 102 err = -ENODEV;
103 goto out_start; 103 goto out_start;
104 } 104 }
105 105
106 if (watchdog_active(wddev)) 106 if (watchdog_active(wdd))
107 goto out_start; 107 goto out_start;
108 108
109 err = wddev->ops->start(wddev); 109 err = wdd->ops->start(wdd);
110 if (err == 0) 110 if (err == 0)
111 set_bit(WDOG_ACTIVE, &wddev->status); 111 set_bit(WDOG_ACTIVE, &wdd->status);
112 112
113out_start: 113out_start:
114 mutex_unlock(&wddev->lock); 114 mutex_unlock(&wdd->lock);
115 return err; 115 return err;
116} 116}
117 117
118/* 118/*
119 * watchdog_stop: wrapper to stop the watchdog. 119 * watchdog_stop: wrapper to stop the watchdog.
120 * @wddev: the watchdog device to stop 120 * @wdd: the watchdog device to stop
121 * 121 *
122 * Stop the watchdog if it is still active and unmark it active. 122 * Stop the watchdog if it is still active and unmark it active.
123 * This function returns zero on success or a negative errno code for 123 * This function returns zero on success or a negative errno code for
@@ -125,155 +125,154 @@ out_start:
125 * If the 'nowayout' feature was set, the watchdog cannot be stopped. 125 * If the 'nowayout' feature was set, the watchdog cannot be stopped.
126 */ 126 */
127 127
128static int watchdog_stop(struct watchdog_device *wddev) 128static int watchdog_stop(struct watchdog_device *wdd)
129{ 129{
130 int err = 0; 130 int err = 0;
131 131
132 mutex_lock(&wddev->lock); 132 mutex_lock(&wdd->lock);
133 133
134 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) { 134 if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
135 err = -ENODEV; 135 err = -ENODEV;
136 goto out_stop; 136 goto out_stop;
137 } 137 }
138 138
139 if (!watchdog_active(wddev)) 139 if (!watchdog_active(wdd))
140 goto out_stop; 140 goto out_stop;
141 141
142 if (test_bit(WDOG_NO_WAY_OUT, &wddev->status)) { 142 if (test_bit(WDOG_NO_WAY_OUT, &wdd->status)) {
143 dev_info(wddev->dev, "nowayout prevents watchdog being stopped!\n"); 143 dev_info(wdd->dev, "nowayout prevents watchdog being stopped!\n");
144 err = -EBUSY; 144 err = -EBUSY;
145 goto out_stop; 145 goto out_stop;
146 } 146 }
147 147
148 err = wddev->ops->stop(wddev); 148 err = wdd->ops->stop(wdd);
149 if (err == 0) 149 if (err == 0)
150 clear_bit(WDOG_ACTIVE, &wddev->status); 150 clear_bit(WDOG_ACTIVE, &wdd->status);
151 151
152out_stop: 152out_stop:
153 mutex_unlock(&wddev->lock); 153 mutex_unlock(&wdd->lock);
154 return err; 154 return err;
155} 155}
156 156
157/* 157/*
158 * watchdog_get_status: wrapper to get the watchdog status 158 * watchdog_get_status: wrapper to get the watchdog status
159 * @wddev: the watchdog device to get the status from 159 * @wdd: the watchdog device to get the status from
160 * @status: the status of the watchdog device 160 * @status: the status of the watchdog device
161 * 161 *
162 * Get the watchdog's status flags. 162 * Get the watchdog's status flags.
163 */ 163 */
164 164
165static int watchdog_get_status(struct watchdog_device *wddev, 165static int watchdog_get_status(struct watchdog_device *wdd,
166 unsigned int *status) 166 unsigned int *status)
167{ 167{
168 int err = 0; 168 int err = 0;
169 169
170 *status = 0; 170 *status = 0;
171 if (!wddev->ops->status) 171 if (!wdd->ops->status)
172 return -EOPNOTSUPP; 172 return -EOPNOTSUPP;
173 173
174 mutex_lock(&wddev->lock); 174 mutex_lock(&wdd->lock);
175 175
176 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) { 176 if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
177 err = -ENODEV; 177 err = -ENODEV;
178 goto out_status; 178 goto out_status;
179 } 179 }
180 180
181 *status = wddev->ops->status(wddev); 181 *status = wdd->ops->status(wdd);
182 182
183out_status: 183out_status:
184 mutex_unlock(&wddev->lock); 184 mutex_unlock(&wdd->lock);
185 return err; 185 return err;
186} 186}
187 187
188/* 188/*
189 * watchdog_set_timeout: set the watchdog timer timeout 189 * watchdog_set_timeout: set the watchdog timer timeout
190 * @wddev: the watchdog device to set the timeout for 190 * @wdd: the watchdog device to set the timeout for
191 * @timeout: timeout to set in seconds 191 * @timeout: timeout to set in seconds
192 */ 192 */
193 193
194static int watchdog_set_timeout(struct watchdog_device *wddev, 194static int watchdog_set_timeout(struct watchdog_device *wdd,
195 unsigned int timeout) 195 unsigned int timeout)
196{ 196{
197 int err; 197 int err;
198 198
199 if ((wddev->ops->set_timeout == NULL) || 199 if (!wdd->ops->set_timeout || !(wdd->info->options & WDIOF_SETTIMEOUT))
200 !(wddev->info->options & WDIOF_SETTIMEOUT))
201 return -EOPNOTSUPP; 200 return -EOPNOTSUPP;
202 201
203 if (watchdog_timeout_invalid(wddev, timeout)) 202 if (watchdog_timeout_invalid(wdd, timeout))
204 return -EINVAL; 203 return -EINVAL;
205 204
206 mutex_lock(&wddev->lock); 205 mutex_lock(&wdd->lock);
207 206
208 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) { 207 if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
209 err = -ENODEV; 208 err = -ENODEV;
210 goto out_timeout; 209 goto out_timeout;
211 } 210 }
212 211
213 err = wddev->ops->set_timeout(wddev, timeout); 212 err = wdd->ops->set_timeout(wdd, timeout);
214 213
215out_timeout: 214out_timeout:
216 mutex_unlock(&wddev->lock); 215 mutex_unlock(&wdd->lock);
217 return err; 216 return err;
218} 217}
219 218
220/* 219/*
221 * watchdog_get_timeleft: wrapper to get the time left before a reboot 220 * watchdog_get_timeleft: wrapper to get the time left before a reboot
222 * @wddev: the watchdog device to get the remaining time from 221 * @wdd: the watchdog device to get the remaining time from
223 * @timeleft: the time that's left 222 * @timeleft: the time that's left
224 * 223 *
225 * Get the time before a watchdog will reboot (if not pinged). 224 * Get the time before a watchdog will reboot (if not pinged).
226 */ 225 */
227 226
228static int watchdog_get_timeleft(struct watchdog_device *wddev, 227static int watchdog_get_timeleft(struct watchdog_device *wdd,
229 unsigned int *timeleft) 228 unsigned int *timeleft)
230{ 229{
231 int err = 0; 230 int err = 0;
232 231
233 *timeleft = 0; 232 *timeleft = 0;
234 if (!wddev->ops->get_timeleft) 233 if (!wdd->ops->get_timeleft)
235 return -EOPNOTSUPP; 234 return -EOPNOTSUPP;
236 235
237 mutex_lock(&wddev->lock); 236 mutex_lock(&wdd->lock);
238 237
239 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) { 238 if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
240 err = -ENODEV; 239 err = -ENODEV;
241 goto out_timeleft; 240 goto out_timeleft;
242 } 241 }
243 242
244 *timeleft = wddev->ops->get_timeleft(wddev); 243 *timeleft = wdd->ops->get_timeleft(wdd);
245 244
246out_timeleft: 245out_timeleft:
247 mutex_unlock(&wddev->lock); 246 mutex_unlock(&wdd->lock);
248 return err; 247 return err;
249} 248}
250 249
251/* 250/*
252 * watchdog_ioctl_op: call the watchdog drivers ioctl op if defined 251 * watchdog_ioctl_op: call the watchdog drivers ioctl op if defined
253 * @wddev: the watchdog device to do the ioctl on 252 * @wdd: the watchdog device to do the ioctl on
254 * @cmd: watchdog command 253 * @cmd: watchdog command
255 * @arg: argument pointer 254 * @arg: argument pointer
256 */ 255 */
257 256
258static int watchdog_ioctl_op(struct watchdog_device *wddev, unsigned int cmd, 257static int watchdog_ioctl_op(struct watchdog_device *wdd, unsigned int cmd,
259 unsigned long arg) 258 unsigned long arg)
260{ 259{
261 int err; 260 int err;
262 261
263 if (!wddev->ops->ioctl) 262 if (!wdd->ops->ioctl)
264 return -ENOIOCTLCMD; 263 return -ENOIOCTLCMD;
265 264
266 mutex_lock(&wddev->lock); 265 mutex_lock(&wdd->lock);
267 266
268 if (test_bit(WDOG_UNREGISTERED, &wddev->status)) { 267 if (test_bit(WDOG_UNREGISTERED, &wdd->status)) {
269 err = -ENODEV; 268 err = -ENODEV;
270 goto out_ioctl; 269 goto out_ioctl;
271 } 270 }
272 271
273 err = wddev->ops->ioctl(wddev, cmd, arg); 272 err = wdd->ops->ioctl(wdd, cmd, arg);
274 273
275out_ioctl: 274out_ioctl:
276 mutex_unlock(&wddev->lock); 275 mutex_unlock(&wdd->lock);
277 return err; 276 return err;
278} 277}
279 278
@@ -295,6 +294,7 @@ static ssize_t watchdog_write(struct file *file, const char __user *data,
295 struct watchdog_device *wdd = file->private_data; 294 struct watchdog_device *wdd = file->private_data;
296 size_t i; 295 size_t i;
297 char c; 296 char c;
297 int err;
298 298
299 if (len == 0) 299 if (len == 0)
300 return 0; 300 return 0;
@@ -314,7 +314,9 @@ static ssize_t watchdog_write(struct file *file, const char __user *data,
314 } 314 }
315 315
316 /* someone wrote to us, so we send the watchdog a keepalive ping */ 316 /* someone wrote to us, so we send the watchdog a keepalive ping */
317 watchdog_ping(wdd); 317 err = watchdog_ping(wdd);
318 if (err < 0)
319 return err;
318 320
319 return len; 321 return len;
320} 322}
@@ -370,8 +372,7 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
370 case WDIOC_KEEPALIVE: 372 case WDIOC_KEEPALIVE:
371 if (!(wdd->info->options & WDIOF_KEEPALIVEPING)) 373 if (!(wdd->info->options & WDIOF_KEEPALIVEPING))
372 return -EOPNOTSUPP; 374 return -EOPNOTSUPP;
373 watchdog_ping(wdd); 375 return watchdog_ping(wdd);
374 return 0;
375 case WDIOC_SETTIMEOUT: 376 case WDIOC_SETTIMEOUT:
376 if (get_user(val, p)) 377 if (get_user(val, p))
377 return -EFAULT; 378 return -EFAULT;
@@ -381,7 +382,9 @@ static long watchdog_ioctl(struct file *file, unsigned int cmd,
381 /* If the watchdog is active then we send a keepalive ping 382 /* If the watchdog is active then we send a keepalive ping
382 * to make sure that the watchdog keep's running (and if 383 * to make sure that the watchdog keep's running (and if
383 * possible that it takes the new timeout) */ 384 * possible that it takes the new timeout) */
384 watchdog_ping(wdd); 385 err = watchdog_ping(wdd);
386 if (err < 0)
387 return err;
385 /* Fall */ 388 /* Fall */
386 case WDIOC_GETTIMEOUT: 389 case WDIOC_GETTIMEOUT:
387 /* timeout == 0 means that we don't know the timeout */ 390 /* timeout == 0 means that we don't know the timeout */
@@ -513,43 +516,43 @@ static struct miscdevice watchdog_miscdev = {
513 516
514/* 517/*
515 * watchdog_dev_register: register a watchdog device 518 * watchdog_dev_register: register a watchdog device
516 * @watchdog: watchdog device 519 * @wdd: watchdog device
517 * 520 *
518 * Register a watchdog device including handling the legacy 521 * Register a watchdog device including handling the legacy
519 * /dev/watchdog node. /dev/watchdog is actually a miscdevice and 522 * /dev/watchdog node. /dev/watchdog is actually a miscdevice and
520 * thus we set it up like that. 523 * thus we set it up like that.
521 */ 524 */
522 525
523int watchdog_dev_register(struct watchdog_device *watchdog) 526int watchdog_dev_register(struct watchdog_device *wdd)
524{ 527{
525 int err, devno; 528 int err, devno;
526 529
527 if (watchdog->id == 0) { 530 if (wdd->id == 0) {
528 old_wdd = watchdog; 531 old_wdd = wdd;
529 watchdog_miscdev.parent = watchdog->parent; 532 watchdog_miscdev.parent = wdd->parent;
530 err = misc_register(&watchdog_miscdev); 533 err = misc_register(&watchdog_miscdev);
531 if (err != 0) { 534 if (err != 0) {
532 pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n", 535 pr_err("%s: cannot register miscdev on minor=%d (err=%d).\n",
533 watchdog->info->identity, WATCHDOG_MINOR, err); 536 wdd->info->identity, WATCHDOG_MINOR, err);
534 if (err == -EBUSY) 537 if (err == -EBUSY)
535 pr_err("%s: a legacy watchdog module is probably present.\n", 538 pr_err("%s: a legacy watchdog module is probably present.\n",
536 watchdog->info->identity); 539 wdd->info->identity);
537 old_wdd = NULL; 540 old_wdd = NULL;
538 return err; 541 return err;
539 } 542 }
540 } 543 }
541 544
542 /* Fill in the data structures */ 545 /* Fill in the data structures */
543 devno = MKDEV(MAJOR(watchdog_devt), watchdog->id); 546 devno = MKDEV(MAJOR(watchdog_devt), wdd->id);
544 cdev_init(&watchdog->cdev, &watchdog_fops); 547 cdev_init(&wdd->cdev, &watchdog_fops);
545 watchdog->cdev.owner = watchdog->ops->owner; 548 wdd->cdev.owner = wdd->ops->owner;
546 549
547 /* Add the device */ 550 /* Add the device */
548 err = cdev_add(&watchdog->cdev, devno, 1); 551 err = cdev_add(&wdd->cdev, devno, 1);
549 if (err) { 552 if (err) {
550 pr_err("watchdog%d unable to add device %d:%d\n", 553 pr_err("watchdog%d unable to add device %d:%d\n",
551 watchdog->id, MAJOR(watchdog_devt), watchdog->id); 554 wdd->id, MAJOR(watchdog_devt), wdd->id);
552 if (watchdog->id == 0) { 555 if (wdd->id == 0) {
553 misc_deregister(&watchdog_miscdev); 556 misc_deregister(&watchdog_miscdev);
554 old_wdd = NULL; 557 old_wdd = NULL;
555 } 558 }
@@ -564,14 +567,14 @@ int watchdog_dev_register(struct watchdog_device *watchdog)
564 * Unregister the watchdog and if needed the legacy /dev/watchdog device. 567 * Unregister the watchdog and if needed the legacy /dev/watchdog device.
565 */ 568 */
566 569
567int watchdog_dev_unregister(struct watchdog_device *watchdog) 570int watchdog_dev_unregister(struct watchdog_device *wdd)
568{ 571{
569 mutex_lock(&watchdog->lock); 572 mutex_lock(&wdd->lock);
570 set_bit(WDOG_UNREGISTERED, &watchdog->status); 573 set_bit(WDOG_UNREGISTERED, &wdd->status);
571 mutex_unlock(&watchdog->lock); 574 mutex_unlock(&wdd->lock);
572 575
573 cdev_del(&watchdog->cdev); 576 cdev_del(&wdd->cdev);
574 if (watchdog->id == 0) { 577 if (wdd->id == 0) {
575 misc_deregister(&watchdog_miscdev); 578 misc_deregister(&watchdog_miscdev);
576 old_wdd = NULL; 579 old_wdd = NULL;
577 } 580 }
diff --git a/include/linux/watchdog.h b/include/linux/watchdog.h
index d74a0e907b9e..027b1f43f12d 100644
--- a/include/linux/watchdog.h
+++ b/include/linux/watchdog.h
@@ -24,8 +24,8 @@ struct watchdog_device;
24 * @stop: The routine for stopping the watchdog device. 24 * @stop: The routine for stopping the watchdog device.
25 * @ping: The routine that sends a keepalive ping to the watchdog device. 25 * @ping: The routine that sends a keepalive ping to the watchdog device.
26 * @status: The routine that shows the status of the watchdog device. 26 * @status: The routine that shows the status of the watchdog device.
27 * @set_timeout:The routine for setting the watchdog devices timeout value. 27 * @set_timeout:The routine for setting the watchdog devices timeout value (in seconds).
28 * @get_timeleft:The routine that get's the time that's left before a reset. 28 * @get_timeleft:The routine that gets the time left before a reset (in seconds).
29 * @ref: The ref operation for dyn. allocated watchdog_device structs 29 * @ref: The ref operation for dyn. allocated watchdog_device structs
30 * @unref: The unref operation for dyn. allocated watchdog_device structs 30 * @unref: The unref operation for dyn. allocated watchdog_device structs
31 * @ioctl: The routines that handles extra ioctl calls. 31 * @ioctl: The routines that handles extra ioctl calls.
@@ -33,7 +33,7 @@ struct watchdog_device;
33 * The watchdog_ops structure contains a list of low-level operations 33 * The watchdog_ops structure contains a list of low-level operations
34 * that control a watchdog device. It also contains the module that owns 34 * that control a watchdog device. It also contains the module that owns
35 * these operations. The start and stop function are mandatory, all other 35 * these operations. The start and stop function are mandatory, all other
36 * functions are optonal. 36 * functions are optional.
37 */ 37 */
38struct watchdog_ops { 38struct watchdog_ops {
39 struct module *owner; 39 struct module *owner;
@@ -59,9 +59,9 @@ struct watchdog_ops {
59 * @info: Pointer to a watchdog_info structure. 59 * @info: Pointer to a watchdog_info structure.
60 * @ops: Pointer to the list of watchdog operations. 60 * @ops: Pointer to the list of watchdog operations.
61 * @bootstatus: Status of the watchdog device at boot. 61 * @bootstatus: Status of the watchdog device at boot.
62 * @timeout: The watchdog devices timeout value. 62 * @timeout: The watchdog devices timeout value (in seconds).
63 * @min_timeout:The watchdog devices minimum timeout value. 63 * @min_timeout:The watchdog devices minimum timeout value (in seconds).
64 * @max_timeout:The watchdog devices maximum timeout value. 64 * @max_timeout:The watchdog devices maximum timeout value (in seconds).
65 * @driver-data:Pointer to the drivers private data. 65 * @driver-data:Pointer to the drivers private data.
66 * @lock: Lock for watchdog core internal use only. 66 * @lock: Lock for watchdog core internal use only.
67 * @status: Field that contains the devices internal status bits. 67 * @status: Field that contains the devices internal status bits.
@@ -119,8 +119,15 @@ static inline void watchdog_set_nowayout(struct watchdog_device *wdd, bool noway
119/* Use the following function to check if a timeout value is invalid */ 119/* Use the following function to check if a timeout value is invalid */
120static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t) 120static inline bool watchdog_timeout_invalid(struct watchdog_device *wdd, unsigned int t)
121{ 121{
122 return ((wdd->max_timeout != 0) && 122 /*
123 (t < wdd->min_timeout || t > wdd->max_timeout)); 123 * The timeout is invalid if
124 * - the requested value is smaller than the configured minimum timeout,
125 * or
126 * - a maximum timeout is configured, and the requested value is larger
127 * than the maximum timeout.
128 */
129 return t < wdd->min_timeout ||
130 (wdd->max_timeout && t > wdd->max_timeout);
124} 131}
125 132
126/* Use the following functions to manipulate watchdog driver specific data */ 133/* Use the following functions to manipulate watchdog driver specific data */