diff options
Diffstat (limited to 'drivers/watchdog')
70 files changed, 3837 insertions, 3765 deletions
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index 48399e134c0d..32b9fe153641 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -463,7 +463,7 @@ config PC87413_WDT | |||
463 | module will be called pc87413_wdt. | 463 | module will be called pc87413_wdt. |
464 | 464 | ||
465 | Most people will say N. | 465 | Most people will say N. |
466 | 466 | ||
467 | config 60XX_WDT | 467 | config 60XX_WDT |
468 | tristate "SBC-60XX Watchdog Timer" | 468 | tristate "SBC-60XX Watchdog Timer" |
469 | depends on X86 | 469 | depends on X86 |
@@ -695,9 +695,17 @@ config 8xx_WDT | |||
695 | tristate "MPC8xx Watchdog Timer" | 695 | tristate "MPC8xx Watchdog Timer" |
696 | depends on 8xx | 696 | depends on 8xx |
697 | 697 | ||
698 | config 83xx_WDT | 698 | config 8xxx_WDT |
699 | tristate "MPC83xx Watchdog Timer" | 699 | tristate "MPC8xxx Platform Watchdog Timer" |
700 | depends on PPC_83xx | 700 | depends on PPC_8xx || PPC_83xx || PPC_86xx |
701 | help | ||
702 | This driver is for a SoC level watchdog that exists on some | ||
703 | Freescale PowerPC processors. So far this driver supports: | ||
704 | - MPC8xx watchdogs | ||
705 | - MPC83xx watchdogs | ||
706 | - MPC86xx watchdogs | ||
707 | |||
708 | For BookE processors (MPC85xx) use the BOOKE_WDT driver instead. | ||
701 | 709 | ||
702 | config MV64X60_WDT | 710 | config MV64X60_WDT |
703 | tristate "MV64X60 (Marvell Discovery) Watchdog Timer" | 711 | tristate "MV64X60 (Marvell Discovery) Watchdog Timer" |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index edd305a64e63..049c91895699 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -92,7 +92,7 @@ obj-$(CONFIG_SBC_EPX_C3_WATCHDOG) += sbc_epx_c3.o | |||
92 | 92 | ||
93 | # MIPS Architecture | 93 | # MIPS Architecture |
94 | obj-$(CONFIG_INDYDOG) += indydog.o | 94 | obj-$(CONFIG_INDYDOG) += indydog.o |
95 | obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o | 95 | obj-$(CONFIG_WDT_MTX1) += mtx-1_wdt.o |
96 | obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o | 96 | obj-$(CONFIG_WDT_RM9K_GPI) += rm9k_wdt.o |
97 | obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o | 97 | obj-$(CONFIG_SIBYTE_WDOG) += sb_wdog.o |
98 | obj-$(CONFIG_AR7_WDT) += ar7_wdt.o | 98 | obj-$(CONFIG_AR7_WDT) += ar7_wdt.o |
@@ -103,7 +103,7 @@ obj-$(CONFIG_TXX9_WDT) += txx9wdt.o | |||
103 | # POWERPC Architecture | 103 | # POWERPC Architecture |
104 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o | 104 | obj-$(CONFIG_8xx_WDT) += mpc8xx_wdt.o |
105 | obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o | 105 | obj-$(CONFIG_MPC5200_WDT) += mpc5200_wdt.o |
106 | obj-$(CONFIG_83xx_WDT) += mpc83xx_wdt.o | 106 | obj-$(CONFIG_8xxx_WDT) += mpc8xxx_wdt.o |
107 | obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o | 107 | obj-$(CONFIG_MV64X60_WDT) += mv64x60_wdt.o |
108 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o | 108 | obj-$(CONFIG_BOOKE_WDT) += booke_wdt.o |
109 | 109 | ||
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c index 85269c365a10..6e46a551395c 100644 --- a/drivers/watchdog/acquirewdt.c +++ b/drivers/watchdog/acquirewdt.c | |||
@@ -58,39 +58,45 @@ | |||
58 | #include <linux/types.h> /* For standard types (like size_t) */ | 58 | #include <linux/types.h> /* For standard types (like size_t) */ |
59 | #include <linux/errno.h> /* For the -ENODEV/... values */ | 59 | #include <linux/errno.h> /* For the -ENODEV/... values */ |
60 | #include <linux/kernel.h> /* For printk/panic/... */ | 60 | #include <linux/kernel.h> /* For printk/panic/... */ |
61 | #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ | 61 | #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV |
62 | (WATCHDOG_MINOR) */ | ||
62 | #include <linux/watchdog.h> /* For the watchdog specific items */ | 63 | #include <linux/watchdog.h> /* For the watchdog specific items */ |
63 | #include <linux/fs.h> /* For file operations */ | 64 | #include <linux/fs.h> /* For file operations */ |
64 | #include <linux/ioport.h> /* For io-port access */ | 65 | #include <linux/ioport.h> /* For io-port access */ |
65 | #include <linux/platform_device.h> /* For platform_driver framework */ | 66 | #include <linux/platform_device.h> /* For platform_driver framework */ |
66 | #include <linux/init.h> /* For __init/__exit/... */ | 67 | #include <linux/init.h> /* For __init/__exit/... */ |
67 | 68 | #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ | |
68 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | 69 | #include <linux/io.h> /* For inb/outb/... */ |
69 | #include <asm/io.h> /* For inb/outb/... */ | ||
70 | 70 | ||
71 | /* Module information */ | 71 | /* Module information */ |
72 | #define DRV_NAME "acquirewdt" | 72 | #define DRV_NAME "acquirewdt" |
73 | #define PFX DRV_NAME ": " | 73 | #define PFX DRV_NAME ": " |
74 | #define WATCHDOG_NAME "Acquire WDT" | 74 | #define WATCHDOG_NAME "Acquire WDT" |
75 | #define WATCHDOG_HEARTBEAT 0 /* There is no way to see what the correct time-out period is */ | 75 | /* There is no way to see what the correct time-out period is */ |
76 | #define WATCHDOG_HEARTBEAT 0 | ||
76 | 77 | ||
77 | /* internal variables */ | 78 | /* internal variables */ |
78 | static struct platform_device *acq_platform_device; /* the watchdog platform device */ | 79 | /* the watchdog platform device */ |
80 | static struct platform_device *acq_platform_device; | ||
79 | static unsigned long acq_is_open; | 81 | static unsigned long acq_is_open; |
80 | static char expect_close; | 82 | static char expect_close; |
81 | 83 | ||
82 | /* module parameters */ | 84 | /* module parameters */ |
83 | static int wdt_stop = 0x43; /* You must set this - there is no sane way to probe for this board. */ | 85 | /* You must set this - there is no sane way to probe for this board. */ |
86 | static int wdt_stop = 0x43; | ||
84 | module_param(wdt_stop, int, 0); | 87 | module_param(wdt_stop, int, 0); |
85 | MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)"); | 88 | MODULE_PARM_DESC(wdt_stop, "Acquire WDT 'stop' io port (default 0x43)"); |
86 | 89 | ||
87 | static int wdt_start = 0x443; /* You must set this - there is no sane way to probe for this board. */ | 90 | /* You must set this - there is no sane way to probe for this board. */ |
91 | static int wdt_start = 0x443; | ||
88 | module_param(wdt_start, int, 0); | 92 | module_param(wdt_start, int, 0); |
89 | MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)"); | 93 | MODULE_PARM_DESC(wdt_start, "Acquire WDT 'start' io port (default 0x443)"); |
90 | 94 | ||
91 | static int nowayout = WATCHDOG_NOWAYOUT; | 95 | static int nowayout = WATCHDOG_NOWAYOUT; |
92 | module_param(nowayout, int, 0); | 96 | module_param(nowayout, int, 0); |
93 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 97 | MODULE_PARM_DESC(nowayout, |
98 | "Watchdog cannot be stopped once started (default=" | ||
99 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
94 | 100 | ||
95 | /* | 101 | /* |
96 | * Watchdog Operations | 102 | * Watchdog Operations |
@@ -112,18 +118,18 @@ static void acq_stop(void) | |||
112 | * /dev/watchdog handling | 118 | * /dev/watchdog handling |
113 | */ | 119 | */ |
114 | 120 | ||
115 | static ssize_t acq_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 121 | static ssize_t acq_write(struct file *file, const char __user *buf, |
122 | size_t count, loff_t *ppos) | ||
116 | { | 123 | { |
117 | /* See if we got the magic character 'V' and reload the timer */ | 124 | /* See if we got the magic character 'V' and reload the timer */ |
118 | if(count) { | 125 | if (count) { |
119 | if (!nowayout) { | 126 | if (!nowayout) { |
120 | size_t i; | 127 | size_t i; |
121 | |||
122 | /* note: just in case someone wrote the magic character | 128 | /* note: just in case someone wrote the magic character |
123 | * five months ago... */ | 129 | five months ago... */ |
124 | expect_close = 0; | 130 | expect_close = 0; |
125 | 131 | /* scan to see whether or not we got the | |
126 | /* scan to see whether or not we got the magic character */ | 132 | magic character */ |
127 | for (i = 0; i != count; i++) { | 133 | for (i = 0; i != count; i++) { |
128 | char c; | 134 | char c; |
129 | if (get_user(c, buf + i)) | 135 | if (get_user(c, buf + i)) |
@@ -132,64 +138,55 @@ static ssize_t acq_write(struct file *file, const char __user *buf, size_t count | |||
132 | expect_close = 42; | 138 | expect_close = 42; |
133 | } | 139 | } |
134 | } | 140 | } |
135 | 141 | /* Well, anyhow someone wrote to us, we should | |
136 | /* Well, anyhow someone wrote to us, we should return that favour */ | 142 | return that favour */ |
137 | acq_keepalive(); | 143 | acq_keepalive(); |
138 | } | 144 | } |
139 | return count; | 145 | return count; |
140 | } | 146 | } |
141 | 147 | ||
142 | static int acq_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 148 | static long acq_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
143 | unsigned long arg) | ||
144 | { | 149 | { |
145 | int options, retval = -EINVAL; | 150 | int options, retval = -EINVAL; |
146 | void __user *argp = (void __user *)arg; | 151 | void __user *argp = (void __user *)arg; |
147 | int __user *p = argp; | 152 | int __user *p = argp; |
148 | static struct watchdog_info ident = | 153 | static struct watchdog_info ident = { |
149 | { | ||
150 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, | 154 | .options = WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE, |
151 | .firmware_version = 1, | 155 | .firmware_version = 1, |
152 | .identity = WATCHDOG_NAME, | 156 | .identity = WATCHDOG_NAME, |
153 | }; | 157 | }; |
154 | 158 | ||
155 | switch(cmd) | 159 | switch (cmd) { |
156 | { | ||
157 | case WDIOC_GETSUPPORT: | 160 | case WDIOC_GETSUPPORT: |
158 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | 161 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
159 | 162 | ||
160 | case WDIOC_GETSTATUS: | 163 | case WDIOC_GETSTATUS: |
161 | case WDIOC_GETBOOTSTATUS: | 164 | case WDIOC_GETBOOTSTATUS: |
162 | return put_user(0, p); | 165 | return put_user(0, p); |
163 | |||
164 | case WDIOC_KEEPALIVE: | ||
165 | acq_keepalive(); | ||
166 | return 0; | ||
167 | |||
168 | case WDIOC_GETTIMEOUT: | ||
169 | return put_user(WATCHDOG_HEARTBEAT, p); | ||
170 | 166 | ||
171 | case WDIOC_SETOPTIONS: | 167 | case WDIOC_SETOPTIONS: |
172 | { | 168 | { |
173 | if (get_user(options, p)) | 169 | if (get_user(options, p)) |
174 | return -EFAULT; | 170 | return -EFAULT; |
175 | 171 | if (options & WDIOS_DISABLECARD) { | |
176 | if (options & WDIOS_DISABLECARD) | 172 | acq_stop(); |
177 | { | 173 | retval = 0; |
178 | acq_stop(); | 174 | } |
179 | retval = 0; | 175 | if (options & WDIOS_ENABLECARD) { |
180 | } | 176 | acq_keepalive(); |
181 | 177 | retval = 0; | |
182 | if (options & WDIOS_ENABLECARD) | 178 | } |
183 | { | 179 | return retval; |
184 | acq_keepalive(); | ||
185 | retval = 0; | ||
186 | } | ||
187 | |||
188 | return retval; | ||
189 | } | 180 | } |
181 | case WDIOC_KEEPALIVE: | ||
182 | acq_keepalive(); | ||
183 | return 0; | ||
184 | |||
185 | case WDIOC_GETTIMEOUT: | ||
186 | return put_user(WATCHDOG_HEARTBEAT, p); | ||
190 | 187 | ||
191 | default: | 188 | default: |
192 | return -ENOTTY; | 189 | return -ENOTTY; |
193 | } | 190 | } |
194 | } | 191 | } |
195 | 192 | ||
@@ -211,7 +208,8 @@ static int acq_close(struct inode *inode, struct file *file) | |||
211 | if (expect_close == 42) { | 208 | if (expect_close == 42) { |
212 | acq_stop(); | 209 | acq_stop(); |
213 | } else { | 210 | } else { |
214 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 211 | printk(KERN_CRIT PFX |
212 | "Unexpected close, not stopping watchdog!\n"); | ||
215 | acq_keepalive(); | 213 | acq_keepalive(); |
216 | } | 214 | } |
217 | clear_bit(0, &acq_is_open); | 215 | clear_bit(0, &acq_is_open); |
@@ -227,7 +225,7 @@ static const struct file_operations acq_fops = { | |||
227 | .owner = THIS_MODULE, | 225 | .owner = THIS_MODULE, |
228 | .llseek = no_llseek, | 226 | .llseek = no_llseek, |
229 | .write = acq_write, | 227 | .write = acq_write, |
230 | .ioctl = acq_ioctl, | 228 | .unlocked_ioctl = acq_ioctl, |
231 | .open = acq_open, | 229 | .open = acq_open, |
232 | .release = acq_close, | 230 | .release = acq_close, |
233 | }; | 231 | }; |
@@ -248,32 +246,29 @@ static int __devinit acq_probe(struct platform_device *dev) | |||
248 | 246 | ||
249 | if (wdt_stop != wdt_start) { | 247 | if (wdt_stop != wdt_start) { |
250 | if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { | 248 | if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { |
251 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 249 | printk(KERN_ERR PFX |
252 | wdt_stop); | 250 | "I/O address 0x%04x already in use\n", wdt_stop); |
253 | ret = -EIO; | 251 | ret = -EIO; |
254 | goto out; | 252 | goto out; |
255 | } | 253 | } |
256 | } | 254 | } |
257 | 255 | ||
258 | if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { | 256 | if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { |
259 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 257 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
260 | wdt_start); | 258 | wdt_start); |
261 | ret = -EIO; | 259 | ret = -EIO; |
262 | goto unreg_stop; | 260 | goto unreg_stop; |
263 | } | 261 | } |
264 | |||
265 | ret = misc_register(&acq_miscdev); | 262 | ret = misc_register(&acq_miscdev); |
266 | if (ret != 0) { | 263 | if (ret != 0) { |
267 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 264 | printk(KERN_ERR PFX |
268 | WATCHDOG_MINOR, ret); | 265 | "cannot register miscdev on minor=%d (err=%d)\n", |
266 | WATCHDOG_MINOR, ret); | ||
269 | goto unreg_regions; | 267 | goto unreg_regions; |
270 | } | 268 | } |
271 | 269 | printk(KERN_INFO PFX "initialized. (nowayout=%d)\n", nowayout); | |
272 | printk (KERN_INFO PFX "initialized. (nowayout=%d)\n", | ||
273 | nowayout); | ||
274 | 270 | ||
275 | return 0; | 271 | return 0; |
276 | |||
277 | unreg_regions: | 272 | unreg_regions: |
278 | release_region(wdt_start, 1); | 273 | release_region(wdt_start, 1); |
279 | unreg_stop: | 274 | unreg_stop: |
@@ -286,9 +281,9 @@ out: | |||
286 | static int __devexit acq_remove(struct platform_device *dev) | 281 | static int __devexit acq_remove(struct platform_device *dev) |
287 | { | 282 | { |
288 | misc_deregister(&acq_miscdev); | 283 | misc_deregister(&acq_miscdev); |
289 | release_region(wdt_start,1); | 284 | release_region(wdt_start, 1); |
290 | if(wdt_stop != wdt_start) | 285 | if (wdt_stop != wdt_start) |
291 | release_region(wdt_stop,1); | 286 | release_region(wdt_stop, 1); |
292 | 287 | ||
293 | return 0; | 288 | return 0; |
294 | } | 289 | } |
@@ -313,18 +308,19 @@ static int __init acq_init(void) | |||
313 | { | 308 | { |
314 | int err; | 309 | int err; |
315 | 310 | ||
316 | printk(KERN_INFO "WDT driver for Acquire single board computer initialising.\n"); | 311 | printk(KERN_INFO |
312 | "WDT driver for Acquire single board computer initialising.\n"); | ||
317 | 313 | ||
318 | err = platform_driver_register(&acquirewdt_driver); | 314 | err = platform_driver_register(&acquirewdt_driver); |
319 | if (err) | 315 | if (err) |
320 | return err; | 316 | return err; |
321 | 317 | ||
322 | acq_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); | 318 | acq_platform_device = platform_device_register_simple(DRV_NAME, |
319 | -1, NULL, 0); | ||
323 | if (IS_ERR(acq_platform_device)) { | 320 | if (IS_ERR(acq_platform_device)) { |
324 | err = PTR_ERR(acq_platform_device); | 321 | err = PTR_ERR(acq_platform_device); |
325 | goto unreg_platform_driver; | 322 | goto unreg_platform_driver; |
326 | } | 323 | } |
327 | |||
328 | return 0; | 324 | return 0; |
329 | 325 | ||
330 | unreg_platform_driver: | 326 | unreg_platform_driver: |
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index 8121cc247343..a5110f93a755 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c | |||
@@ -37,9 +37,9 @@ | |||
37 | #include <linux/ioport.h> | 37 | #include <linux/ioport.h> |
38 | #include <linux/platform_device.h> | 38 | #include <linux/platform_device.h> |
39 | #include <linux/init.h> | 39 | #include <linux/init.h> |
40 | #include <linux/io.h> | ||
41 | #include <linux/uaccess.h> | ||
40 | 42 | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/uaccess.h> | ||
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | 44 | ||
45 | #define DRV_NAME "advantechwdt" | 45 | #define DRV_NAME "advantechwdt" |
@@ -47,7 +47,8 @@ | |||
47 | #define WATCHDOG_NAME "Advantech WDT" | 47 | #define WATCHDOG_NAME "Advantech WDT" |
48 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ | 48 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ |
49 | 49 | ||
50 | static struct platform_device *advwdt_platform_device; /* the watchdog platform device */ | 50 | /* the watchdog platform device */ |
51 | static struct platform_device *advwdt_platform_device; | ||
51 | static unsigned long advwdt_is_open; | 52 | static unsigned long advwdt_is_open; |
52 | static char adv_expect_close; | 53 | static char adv_expect_close; |
53 | 54 | ||
@@ -72,35 +73,35 @@ MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)"); | |||
72 | 73 | ||
73 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | 74 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ |
74 | module_param(timeout, int, 0); | 75 | module_param(timeout, int, 0); |
75 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | 76 | MODULE_PARM_DESC(timeout, |
77 | "Watchdog timeout in seconds. 1<= timeout <=63, default=" | ||
78 | __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | ||
76 | 79 | ||
77 | static int nowayout = WATCHDOG_NOWAYOUT; | 80 | static int nowayout = WATCHDOG_NOWAYOUT; |
78 | module_param(nowayout, int, 0); | 81 | module_param(nowayout, int, 0); |
79 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 82 | MODULE_PARM_DESC(nowayout, |
83 | "Watchdog cannot be stopped once started (default=" | ||
84 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
80 | 85 | ||
81 | /* | 86 | /* |
82 | * Watchdog Operations | 87 | * Watchdog Operations |
83 | */ | 88 | */ |
84 | 89 | ||
85 | static void | 90 | static void advwdt_ping(void) |
86 | advwdt_ping(void) | ||
87 | { | 91 | { |
88 | /* Write a watchdog value */ | 92 | /* Write a watchdog value */ |
89 | outb_p(timeout, wdt_start); | 93 | outb_p(timeout, wdt_start); |
90 | } | 94 | } |
91 | 95 | ||
92 | static void | 96 | static void advwdt_disable(void) |
93 | advwdt_disable(void) | ||
94 | { | 97 | { |
95 | inb_p(wdt_stop); | 98 | inb_p(wdt_stop); |
96 | } | 99 | } |
97 | 100 | ||
98 | static int | 101 | static int advwdt_set_heartbeat(int t) |
99 | advwdt_set_heartbeat(int t) | ||
100 | { | 102 | { |
101 | if ((t < 1) || (t > 63)) | 103 | if (t < 1 || t > 63) |
102 | return -EINVAL; | 104 | return -EINVAL; |
103 | |||
104 | timeout = t; | 105 | timeout = t; |
105 | return 0; | 106 | return 0; |
106 | } | 107 | } |
@@ -109,8 +110,8 @@ advwdt_set_heartbeat(int t) | |||
109 | * /dev/watchdog handling | 110 | * /dev/watchdog handling |
110 | */ | 111 | */ |
111 | 112 | ||
112 | static ssize_t | 113 | static ssize_t advwdt_write(struct file *file, const char __user *buf, |
113 | advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 114 | size_t count, loff_t *ppos) |
114 | { | 115 | { |
115 | if (count) { | 116 | if (count) { |
116 | if (!nowayout) { | 117 | if (!nowayout) { |
@@ -120,7 +121,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp | |||
120 | 121 | ||
121 | for (i = 0; i != count; i++) { | 122 | for (i = 0; i != count; i++) { |
122 | char c; | 123 | char c; |
123 | if (get_user(c, buf+i)) | 124 | if (get_user(c, buf + i)) |
124 | return -EFAULT; | 125 | return -EFAULT; |
125 | if (c == 'V') | 126 | if (c == 'V') |
126 | adv_expect_close = 42; | 127 | adv_expect_close = 42; |
@@ -131,9 +132,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp | |||
131 | return count; | 132 | return count; |
132 | } | 133 | } |
133 | 134 | ||
134 | static int | 135 | static long advwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
135 | advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
136 | unsigned long arg) | ||
137 | { | 136 | { |
138 | int new_timeout; | 137 | int new_timeout; |
139 | void __user *argp = (void __user *)arg; | 138 | void __user *argp = (void __user *)arg; |
@@ -146,57 +145,50 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
146 | 145 | ||
147 | switch (cmd) { | 146 | switch (cmd) { |
148 | case WDIOC_GETSUPPORT: | 147 | case WDIOC_GETSUPPORT: |
149 | if (copy_to_user(argp, &ident, sizeof(ident))) | 148 | if (copy_to_user(argp, &ident, sizeof(ident))) |
150 | return -EFAULT; | 149 | return -EFAULT; |
151 | break; | 150 | break; |
152 | 151 | ||
153 | case WDIOC_GETSTATUS: | 152 | case WDIOC_GETSTATUS: |
154 | case WDIOC_GETBOOTSTATUS: | 153 | case WDIOC_GETBOOTSTATUS: |
155 | return put_user(0, p); | 154 | return put_user(0, p); |
156 | |||
157 | case WDIOC_KEEPALIVE: | ||
158 | advwdt_ping(); | ||
159 | break; | ||
160 | |||
161 | case WDIOC_SETTIMEOUT: | ||
162 | if (get_user(new_timeout, p)) | ||
163 | return -EFAULT; | ||
164 | if (advwdt_set_heartbeat(new_timeout)) | ||
165 | return -EINVAL; | ||
166 | advwdt_ping(); | ||
167 | /* Fall */ | ||
168 | |||
169 | case WDIOC_GETTIMEOUT: | ||
170 | return put_user(timeout, p); | ||
171 | 155 | ||
172 | case WDIOC_SETOPTIONS: | 156 | case WDIOC_SETOPTIONS: |
173 | { | 157 | { |
174 | int options, retval = -EINVAL; | 158 | int options, retval = -EINVAL; |
175 | |||
176 | if (get_user(options, p)) | ||
177 | return -EFAULT; | ||
178 | |||
179 | if (options & WDIOS_DISABLECARD) { | ||
180 | advwdt_disable(); | ||
181 | retval = 0; | ||
182 | } | ||
183 | 159 | ||
184 | if (options & WDIOS_ENABLECARD) { | 160 | if (get_user(options, p)) |
185 | advwdt_ping(); | 161 | return -EFAULT; |
186 | retval = 0; | 162 | if (options & WDIOS_DISABLECARD) { |
187 | } | 163 | advwdt_disable(); |
188 | 164 | retval = 0; | |
189 | return retval; | 165 | } |
166 | if (options & WDIOS_ENABLECARD) { | ||
167 | advwdt_ping(); | ||
168 | retval = 0; | ||
169 | } | ||
170 | return retval; | ||
190 | } | 171 | } |
172 | case WDIOC_KEEPALIVE: | ||
173 | advwdt_ping(); | ||
174 | break; | ||
191 | 175 | ||
176 | case WDIOC_SETTIMEOUT: | ||
177 | if (get_user(new_timeout, p)) | ||
178 | return -EFAULT; | ||
179 | if (advwdt_set_heartbeat(new_timeout)) | ||
180 | return -EINVAL; | ||
181 | advwdt_ping(); | ||
182 | /* Fall */ | ||
183 | case WDIOC_GETTIMEOUT: | ||
184 | return put_user(timeout, p); | ||
192 | default: | 185 | default: |
193 | return -ENOTTY; | 186 | return -ENOTTY; |
194 | } | 187 | } |
195 | return 0; | 188 | return 0; |
196 | } | 189 | } |
197 | 190 | ||
198 | static int | 191 | static int advwdt_open(struct inode *inode, struct file *file) |
199 | advwdt_open(struct inode *inode, struct file *file) | ||
200 | { | 192 | { |
201 | if (test_and_set_bit(0, &advwdt_is_open)) | 193 | if (test_and_set_bit(0, &advwdt_is_open)) |
202 | return -EBUSY; | 194 | return -EBUSY; |
@@ -208,13 +200,13 @@ advwdt_open(struct inode *inode, struct file *file) | |||
208 | return nonseekable_open(inode, file); | 200 | return nonseekable_open(inode, file); |
209 | } | 201 | } |
210 | 202 | ||
211 | static int | 203 | static int advwdt_close(struct inode *inode, struct file *file) |
212 | advwdt_close(struct inode *inode, struct file *file) | ||
213 | { | 204 | { |
214 | if (adv_expect_close == 42) { | 205 | if (adv_expect_close == 42) { |
215 | advwdt_disable(); | 206 | advwdt_disable(); |
216 | } else { | 207 | } else { |
217 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 208 | printk(KERN_CRIT PFX |
209 | "Unexpected close, not stopping watchdog!\n"); | ||
218 | advwdt_ping(); | 210 | advwdt_ping(); |
219 | } | 211 | } |
220 | clear_bit(0, &advwdt_is_open); | 212 | clear_bit(0, &advwdt_is_open); |
@@ -230,7 +222,7 @@ static const struct file_operations advwdt_fops = { | |||
230 | .owner = THIS_MODULE, | 222 | .owner = THIS_MODULE, |
231 | .llseek = no_llseek, | 223 | .llseek = no_llseek, |
232 | .write = advwdt_write, | 224 | .write = advwdt_write, |
233 | .ioctl = advwdt_ioctl, | 225 | .unlocked_ioctl = advwdt_ioctl, |
234 | .open = advwdt_open, | 226 | .open = advwdt_open, |
235 | .release = advwdt_close, | 227 | .release = advwdt_close, |
236 | }; | 228 | }; |
@@ -245,23 +237,24 @@ static struct miscdevice advwdt_miscdev = { | |||
245 | * Init & exit routines | 237 | * Init & exit routines |
246 | */ | 238 | */ |
247 | 239 | ||
248 | static int __devinit | 240 | static int __devinit advwdt_probe(struct platform_device *dev) |
249 | advwdt_probe(struct platform_device *dev) | ||
250 | { | 241 | { |
251 | int ret; | 242 | int ret; |
252 | 243 | ||
253 | if (wdt_stop != wdt_start) { | 244 | if (wdt_stop != wdt_start) { |
254 | if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { | 245 | if (!request_region(wdt_stop, 1, WATCHDOG_NAME)) { |
255 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 246 | printk(KERN_ERR PFX |
256 | wdt_stop); | 247 | "I/O address 0x%04x already in use\n", |
248 | wdt_stop); | ||
257 | ret = -EIO; | 249 | ret = -EIO; |
258 | goto out; | 250 | goto out; |
259 | } | 251 | } |
260 | } | 252 | } |
261 | 253 | ||
262 | if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { | 254 | if (!request_region(wdt_start, 1, WATCHDOG_NAME)) { |
263 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 255 | printk(KERN_ERR PFX |
264 | wdt_start); | 256 | "I/O address 0x%04x already in use\n", |
257 | wdt_start); | ||
265 | ret = -EIO; | 258 | ret = -EIO; |
266 | goto unreg_stop; | 259 | goto unreg_stop; |
267 | } | 260 | } |
@@ -269,20 +262,19 @@ advwdt_probe(struct platform_device *dev) | |||
269 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 262 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ |
270 | if (advwdt_set_heartbeat(timeout)) { | 263 | if (advwdt_set_heartbeat(timeout)) { |
271 | advwdt_set_heartbeat(WATCHDOG_TIMEOUT); | 264 | advwdt_set_heartbeat(WATCHDOG_TIMEOUT); |
272 | printk (KERN_INFO PFX "timeout value must be 1<=x<=63, using %d\n", | 265 | printk(KERN_INFO PFX |
273 | timeout); | 266 | "timeout value must be 1<=x<=63, using %d\n", timeout); |
274 | } | 267 | } |
275 | 268 | ||
276 | ret = misc_register(&advwdt_miscdev); | 269 | ret = misc_register(&advwdt_miscdev); |
277 | if (ret != 0) { | 270 | if (ret != 0) { |
278 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 271 | printk(KERN_ERR PFX |
279 | WATCHDOG_MINOR, ret); | 272 | "cannot register miscdev on minor=%d (err=%d)\n", |
273 | WATCHDOG_MINOR, ret); | ||
280 | goto unreg_regions; | 274 | goto unreg_regions; |
281 | } | 275 | } |
282 | 276 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", | |
283 | printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", | ||
284 | timeout, nowayout); | 277 | timeout, nowayout); |
285 | |||
286 | out: | 278 | out: |
287 | return ret; | 279 | return ret; |
288 | unreg_regions: | 280 | unreg_regions: |
@@ -293,19 +285,17 @@ unreg_stop: | |||
293 | goto out; | 285 | goto out; |
294 | } | 286 | } |
295 | 287 | ||
296 | static int __devexit | 288 | static int __devexit advwdt_remove(struct platform_device *dev) |
297 | advwdt_remove(struct platform_device *dev) | ||
298 | { | 289 | { |
299 | misc_deregister(&advwdt_miscdev); | 290 | misc_deregister(&advwdt_miscdev); |
300 | release_region(wdt_start,1); | 291 | release_region(wdt_start, 1); |
301 | if(wdt_stop != wdt_start) | 292 | if (wdt_stop != wdt_start) |
302 | release_region(wdt_stop,1); | 293 | release_region(wdt_stop, 1); |
303 | 294 | ||
304 | return 0; | 295 | return 0; |
305 | } | 296 | } |
306 | 297 | ||
307 | static void | 298 | static void advwdt_shutdown(struct platform_device *dev) |
308 | advwdt_shutdown(struct platform_device *dev) | ||
309 | { | 299 | { |
310 | /* Turn the WDT off if we have a soft shutdown */ | 300 | /* Turn the WDT off if we have a soft shutdown */ |
311 | advwdt_disable(); | 301 | advwdt_disable(); |
@@ -321,18 +311,19 @@ static struct platform_driver advwdt_driver = { | |||
321 | }, | 311 | }, |
322 | }; | 312 | }; |
323 | 313 | ||
324 | static int __init | 314 | static int __init advwdt_init(void) |
325 | advwdt_init(void) | ||
326 | { | 315 | { |
327 | int err; | 316 | int err; |
328 | 317 | ||
329 | printk(KERN_INFO "WDT driver for Advantech single board computer initialising.\n"); | 318 | printk(KERN_INFO |
319 | "WDT driver for Advantech single board computer initialising.\n"); | ||
330 | 320 | ||
331 | err = platform_driver_register(&advwdt_driver); | 321 | err = platform_driver_register(&advwdt_driver); |
332 | if (err) | 322 | if (err) |
333 | return err; | 323 | return err; |
334 | 324 | ||
335 | advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); | 325 | advwdt_platform_device = platform_device_register_simple(DRV_NAME, |
326 | -1, NULL, 0); | ||
336 | if (IS_ERR(advwdt_platform_device)) { | 327 | if (IS_ERR(advwdt_platform_device)) { |
337 | err = PTR_ERR(advwdt_platform_device); | 328 | err = PTR_ERR(advwdt_platform_device); |
338 | goto unreg_platform_driver; | 329 | goto unreg_platform_driver; |
@@ -345,8 +336,7 @@ unreg_platform_driver: | |||
345 | return err; | 336 | return err; |
346 | } | 337 | } |
347 | 338 | ||
348 | static void __exit | 339 | static void __exit advwdt_exit(void) |
349 | advwdt_exit(void) | ||
350 | { | 340 | { |
351 | platform_device_unregister(advwdt_platform_device); | 341 | platform_device_unregister(advwdt_platform_device); |
352 | platform_driver_unregister(&advwdt_driver); | 342 | platform_driver_unregister(&advwdt_driver); |
diff --git a/drivers/watchdog/alim1535_wdt.c b/drivers/watchdog/alim1535_wdt.c index 2b1fbdb2fcf7..2a7690ecf97d 100644 --- a/drivers/watchdog/alim1535_wdt.c +++ b/drivers/watchdog/alim1535_wdt.c | |||
@@ -18,9 +18,8 @@ | |||
18 | #include <linux/init.h> | 18 | #include <linux/init.h> |
19 | #include <linux/fs.h> | 19 | #include <linux/fs.h> |
20 | #include <linux/pci.h> | 20 | #include <linux/pci.h> |
21 | 21 | #include <linux/uaccess.h> | |
22 | #include <asm/uaccess.h> | 22 | #include <linux/io.h> |
23 | #include <asm/io.h> | ||
24 | 23 | ||
25 | #define WATCHDOG_NAME "ALi_M1535" | 24 | #define WATCHDOG_NAME "ALi_M1535" |
26 | #define PFX WATCHDOG_NAME ": " | 25 | #define PFX WATCHDOG_NAME ": " |
@@ -30,17 +29,21 @@ | |||
30 | static unsigned long ali_is_open; | 29 | static unsigned long ali_is_open; |
31 | static char ali_expect_release; | 30 | static char ali_expect_release; |
32 | static struct pci_dev *ali_pci; | 31 | static struct pci_dev *ali_pci; |
33 | static u32 ali_timeout_bits; /* stores the computed timeout */ | 32 | static u32 ali_timeout_bits; /* stores the computed timeout */ |
34 | static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */ | 33 | static DEFINE_SPINLOCK(ali_lock); /* Guards the hardware */ |
35 | 34 | ||
36 | /* module parameters */ | 35 | /* module parameters */ |
37 | static int timeout = WATCHDOG_TIMEOUT; | 36 | static int timeout = WATCHDOG_TIMEOUT; |
38 | module_param(timeout, int, 0); | 37 | module_param(timeout, int, 0); |
39 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (0<timeout<18000, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 38 | MODULE_PARM_DESC(timeout, |
39 | "Watchdog timeout in seconds. (0 < timeout < 18000, default=" | ||
40 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
40 | 41 | ||
41 | static int nowayout = WATCHDOG_NOWAYOUT; | 42 | static int nowayout = WATCHDOG_NOWAYOUT; |
42 | module_param(nowayout, int, 0); | 43 | module_param(nowayout, int, 0); |
43 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 44 | MODULE_PARM_DESC(nowayout, |
45 | "Watchdog cannot be stopped once started (default=" | ||
46 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
44 | 47 | ||
45 | /* | 48 | /* |
46 | * ali_start - start watchdog countdown | 49 | * ali_start - start watchdog countdown |
@@ -103,15 +106,16 @@ static void ali_keepalive(void) | |||
103 | 106 | ||
104 | static int ali_settimer(int t) | 107 | static int ali_settimer(int t) |
105 | { | 108 | { |
106 | if(t < 0) | 109 | if (t < 0) |
107 | return -EINVAL; | 110 | return -EINVAL; |
108 | else if(t < 60) | 111 | else if (t < 60) |
109 | ali_timeout_bits = t|(1<<6); | 112 | ali_timeout_bits = t|(1<<6); |
110 | else if(t < 3600) | 113 | else if (t < 3600) |
111 | ali_timeout_bits = (t/60)|(1<<7); | 114 | ali_timeout_bits = (t/60)|(1<<7); |
112 | else if(t < 18000) | 115 | else if (t < 18000) |
113 | ali_timeout_bits = (t/300)|(1<<6)|(1<<7); | 116 | ali_timeout_bits = (t/300)|(1<<6)|(1<<7); |
114 | else return -EINVAL; | 117 | else |
118 | return -EINVAL; | ||
115 | 119 | ||
116 | timeout = t; | 120 | timeout = t; |
117 | return 0; | 121 | return 0; |
@@ -134,21 +138,22 @@ static int ali_settimer(int t) | |||
134 | */ | 138 | */ |
135 | 139 | ||
136 | static ssize_t ali_write(struct file *file, const char __user *data, | 140 | static ssize_t ali_write(struct file *file, const char __user *data, |
137 | size_t len, loff_t * ppos) | 141 | size_t len, loff_t *ppos) |
138 | { | 142 | { |
139 | /* See if we got the magic character 'V' and reload the timer */ | 143 | /* See if we got the magic character 'V' and reload the timer */ |
140 | if (len) { | 144 | if (len) { |
141 | if (!nowayout) { | 145 | if (!nowayout) { |
142 | size_t i; | 146 | size_t i; |
143 | 147 | ||
144 | /* note: just in case someone wrote the magic character | 148 | /* note: just in case someone wrote the |
145 | * five months ago... */ | 149 | magic character five months ago... */ |
146 | ali_expect_release = 0; | 150 | ali_expect_release = 0; |
147 | 151 | ||
148 | /* scan to see whether or not we got the magic character */ | 152 | /* scan to see whether or not we got |
153 | the magic character */ | ||
149 | for (i = 0; i != len; i++) { | 154 | for (i = 0; i != len; i++) { |
150 | char c; | 155 | char c; |
151 | if(get_user(c, data+i)) | 156 | if (get_user(c, data + i)) |
152 | return -EFAULT; | 157 | return -EFAULT; |
153 | if (c == 'V') | 158 | if (c == 'V') |
154 | ali_expect_release = 42; | 159 | ali_expect_release = 42; |
@@ -163,7 +168,6 @@ static ssize_t ali_write(struct file *file, const char __user *data, | |||
163 | 168 | ||
164 | /* | 169 | /* |
165 | * ali_ioctl - handle watchdog ioctls | 170 | * ali_ioctl - handle watchdog ioctls |
166 | * @inode: VFS inode | ||
167 | * @file: VFS file pointer | 171 | * @file: VFS file pointer |
168 | * @cmd: ioctl number | 172 | * @cmd: ioctl number |
169 | * @arg: arguments to the ioctl | 173 | * @arg: arguments to the ioctl |
@@ -172,8 +176,7 @@ static ssize_t ali_write(struct file *file, const char __user *data, | |||
172 | * we want an extension to enable irq ack monitoring and the like | 176 | * we want an extension to enable irq ack monitoring and the like |
173 | */ | 177 | */ |
174 | 178 | ||
175 | static int ali_ioctl(struct inode *inode, struct file *file, | 179 | static long ali_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
176 | unsigned int cmd, unsigned long arg) | ||
177 | { | 180 | { |
178 | void __user *argp = (void __user *)arg; | 181 | void __user *argp = (void __user *)arg; |
179 | int __user *p = argp; | 182 | int __user *p = argp; |
@@ -186,57 +189,45 @@ static int ali_ioctl(struct inode *inode, struct file *file, | |||
186 | }; | 189 | }; |
187 | 190 | ||
188 | switch (cmd) { | 191 | switch (cmd) { |
189 | case WDIOC_GETSUPPORT: | 192 | case WDIOC_GETSUPPORT: |
190 | return copy_to_user(argp, &ident, | 193 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
191 | sizeof (ident)) ? -EFAULT : 0; | 194 | |
192 | 195 | case WDIOC_GETSTATUS: | |
193 | case WDIOC_GETSTATUS: | 196 | case WDIOC_GETBOOTSTATUS: |
194 | case WDIOC_GETBOOTSTATUS: | 197 | return put_user(0, p); |
195 | return put_user(0, p); | 198 | case WDIOC_SETOPTIONS: |
196 | 199 | { | |
197 | case WDIOC_KEEPALIVE: | 200 | int new_options, retval = -EINVAL; |
198 | ali_keepalive(); | 201 | |
199 | return 0; | 202 | if (get_user(new_options, p)) |
200 | 203 | return -EFAULT; | |
201 | case WDIOC_SETOPTIONS: | 204 | if (new_options & WDIOS_DISABLECARD) { |
202 | { | 205 | ali_stop(); |
203 | int new_options, retval = -EINVAL; | 206 | retval = 0; |
204 | |||
205 | if (get_user (new_options, p)) | ||
206 | return -EFAULT; | ||
207 | |||
208 | if (new_options & WDIOS_DISABLECARD) { | ||
209 | ali_stop(); | ||
210 | retval = 0; | ||
211 | } | ||
212 | |||
213 | if (new_options & WDIOS_ENABLECARD) { | ||
214 | ali_start(); | ||
215 | retval = 0; | ||
216 | } | ||
217 | |||
218 | return retval; | ||
219 | } | 207 | } |
220 | 208 | if (new_options & WDIOS_ENABLECARD) { | |
221 | case WDIOC_SETTIMEOUT: | 209 | ali_start(); |
222 | { | 210 | retval = 0; |
223 | int new_timeout; | ||
224 | |||
225 | if (get_user(new_timeout, p)) | ||
226 | return -EFAULT; | ||
227 | |||
228 | if (ali_settimer(new_timeout)) | ||
229 | return -EINVAL; | ||
230 | |||
231 | ali_keepalive(); | ||
232 | /* Fall */ | ||
233 | } | 211 | } |
234 | 212 | return retval; | |
235 | case WDIOC_GETTIMEOUT: | 213 | } |
236 | return put_user(timeout, p); | 214 | case WDIOC_KEEPALIVE: |
237 | 215 | ali_keepalive(); | |
238 | default: | 216 | return 0; |
239 | return -ENOTTY; | 217 | case WDIOC_SETTIMEOUT: |
218 | { | ||
219 | int new_timeout; | ||
220 | if (get_user(new_timeout, p)) | ||
221 | return -EFAULT; | ||
222 | if (ali_settimer(new_timeout)) | ||
223 | return -EINVAL; | ||
224 | ali_keepalive(); | ||
225 | /* Fall */ | ||
226 | } | ||
227 | case WDIOC_GETTIMEOUT: | ||
228 | return put_user(timeout, p); | ||
229 | default: | ||
230 | return -ENOTTY; | ||
240 | } | 231 | } |
241 | } | 232 | } |
242 | 233 | ||
@@ -274,10 +265,11 @@ static int ali_release(struct inode *inode, struct file *file) | |||
274 | /* | 265 | /* |
275 | * Shut off the timer. | 266 | * Shut off the timer. |
276 | */ | 267 | */ |
277 | if (ali_expect_release == 42) { | 268 | if (ali_expect_release == 42) |
278 | ali_stop(); | 269 | ali_stop(); |
279 | } else { | 270 | else { |
280 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 271 | printk(KERN_CRIT PFX |
272 | "Unexpected close, not stopping watchdog!\n"); | ||
281 | ali_keepalive(); | 273 | ali_keepalive(); |
282 | } | 274 | } |
283 | clear_bit(0, &ali_is_open); | 275 | clear_bit(0, &ali_is_open); |
@@ -292,13 +284,11 @@ static int ali_release(struct inode *inode, struct file *file) | |||
292 | */ | 284 | */ |
293 | 285 | ||
294 | 286 | ||
295 | static int ali_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 287 | static int ali_notify_sys(struct notifier_block *this, |
288 | unsigned long code, void *unused) | ||
296 | { | 289 | { |
297 | if (code==SYS_DOWN || code==SYS_HALT) { | 290 | if (code == SYS_DOWN || code == SYS_HALT) |
298 | /* Turn the WDT off */ | 291 | ali_stop(); /* Turn the WDT off */ |
299 | ali_stop(); | ||
300 | } | ||
301 | |||
302 | return NOTIFY_DONE; | 292 | return NOTIFY_DONE; |
303 | } | 293 | } |
304 | 294 | ||
@@ -340,10 +330,10 @@ static int __init ali_find_watchdog(void) | |||
340 | 330 | ||
341 | /* Check for the a 7101 PMU */ | 331 | /* Check for the a 7101 PMU */ |
342 | pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL); | 332 | pdev = pci_get_device(PCI_VENDOR_ID_AL, 0x7101, NULL); |
343 | if(pdev == NULL) | 333 | if (pdev == NULL) |
344 | return -ENODEV; | 334 | return -ENODEV; |
345 | 335 | ||
346 | if(pci_enable_device(pdev)) { | 336 | if (pci_enable_device(pdev)) { |
347 | pci_dev_put(pdev); | 337 | pci_dev_put(pdev); |
348 | return -EIO; | 338 | return -EIO; |
349 | } | 339 | } |
@@ -355,9 +345,12 @@ static int __init ali_find_watchdog(void) | |||
355 | */ | 345 | */ |
356 | pci_read_config_dword(pdev, 0xCC, &wdog); | 346 | pci_read_config_dword(pdev, 0xCC, &wdog); |
357 | 347 | ||
358 | wdog &= ~0x3F; /* Timer bits */ | 348 | /* Timer bits */ |
359 | wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24)); /* Issued events */ | 349 | wdog &= ~0x3F; |
360 | wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)); /* No monitor bits */ | 350 | /* Issued events */ |
351 | wdog &= ~((1<<27)|(1<<26)|(1<<25)|(1<<24)); | ||
352 | /* No monitor bits */ | ||
353 | wdog &= ~((1<<16)|(1<<13)|(1<<12)|(1<<11)|(1<<10)|(1<<9)); | ||
361 | 354 | ||
362 | pci_write_config_dword(pdev, 0xCC, wdog); | 355 | pci_write_config_dword(pdev, 0xCC, wdog); |
363 | 356 | ||
@@ -369,12 +362,12 @@ static int __init ali_find_watchdog(void) | |||
369 | */ | 362 | */ |
370 | 363 | ||
371 | static const struct file_operations ali_fops = { | 364 | static const struct file_operations ali_fops = { |
372 | .owner = THIS_MODULE, | 365 | .owner = THIS_MODULE, |
373 | .llseek = no_llseek, | 366 | .llseek = no_llseek, |
374 | .write = ali_write, | 367 | .write = ali_write, |
375 | .ioctl = ali_ioctl, | 368 | .unlocked_ioctl = ali_ioctl, |
376 | .open = ali_open, | 369 | .open = ali_open, |
377 | .release = ali_release, | 370 | .release = ali_release, |
378 | }; | 371 | }; |
379 | 372 | ||
380 | static struct miscdevice ali_miscdev = { | 373 | static struct miscdevice ali_miscdev = { |
@@ -399,15 +392,16 @@ static int __init watchdog_init(void) | |||
399 | int ret; | 392 | int ret; |
400 | 393 | ||
401 | /* Check whether or not the hardware watchdog is there */ | 394 | /* Check whether or not the hardware watchdog is there */ |
402 | if (ali_find_watchdog() != 0) { | 395 | if (ali_find_watchdog() != 0) |
403 | return -ENODEV; | 396 | return -ENODEV; |
404 | } | ||
405 | 397 | ||
406 | /* Check that the timeout value is within it's range ; if not reset to the default */ | 398 | /* Check that the timeout value is within it's range; |
399 | if not reset to the default */ | ||
407 | if (timeout < 1 || timeout >= 18000) { | 400 | if (timeout < 1 || timeout >= 18000) { |
408 | timeout = WATCHDOG_TIMEOUT; | 401 | timeout = WATCHDOG_TIMEOUT; |
409 | printk(KERN_INFO PFX "timeout value must be 0<timeout<18000, using %d\n", | 402 | printk(KERN_INFO PFX |
410 | timeout); | 403 | "timeout value must be 0 < timeout < 18000, using %d\n", |
404 | timeout); | ||
411 | } | 405 | } |
412 | 406 | ||
413 | /* Calculate the watchdog's timeout */ | 407 | /* Calculate the watchdog's timeout */ |
@@ -415,15 +409,16 @@ static int __init watchdog_init(void) | |||
415 | 409 | ||
416 | ret = register_reboot_notifier(&ali_notifier); | 410 | ret = register_reboot_notifier(&ali_notifier); |
417 | if (ret != 0) { | 411 | if (ret != 0) { |
418 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 412 | printk(KERN_ERR PFX |
419 | ret); | 413 | "cannot register reboot notifier (err=%d)\n", ret); |
420 | goto out; | 414 | goto out; |
421 | } | 415 | } |
422 | 416 | ||
423 | ret = misc_register(&ali_miscdev); | 417 | ret = misc_register(&ali_miscdev); |
424 | if (ret != 0) { | 418 | if (ret != 0) { |
425 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 419 | printk(KERN_ERR PFX |
426 | WATCHDOG_MINOR, ret); | 420 | "cannot register miscdev on minor=%d (err=%d)\n", |
421 | WATCHDOG_MINOR, ret); | ||
427 | goto unreg_reboot; | 422 | goto unreg_reboot; |
428 | } | 423 | } |
429 | 424 | ||
diff --git a/drivers/watchdog/alim7101_wdt.c b/drivers/watchdog/alim7101_wdt.c index 238273c98656..a045ef869439 100644 --- a/drivers/watchdog/alim7101_wdt.c +++ b/drivers/watchdog/alim7101_wdt.c | |||
@@ -31,9 +31,9 @@ | |||
31 | #include <linux/init.h> | 31 | #include <linux/init.h> |
32 | #include <linux/fs.h> | 32 | #include <linux/fs.h> |
33 | #include <linux/pci.h> | 33 | #include <linux/pci.h> |
34 | #include <linux/io.h> | ||
35 | #include <linux/uaccess.h> | ||
34 | 36 | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | #include <asm/system.h> | 37 | #include <asm/system.h> |
38 | 38 | ||
39 | #define OUR_NAME "alim7101_wdt" | 39 | #define OUR_NAME "alim7101_wdt" |
@@ -60,13 +60,17 @@ | |||
60 | */ | 60 | */ |
61 | 61 | ||
62 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ | 62 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ |
63 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ | 63 | /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ |
64 | static int timeout = WATCHDOG_TIMEOUT; | ||
64 | module_param(timeout, int, 0); | 65 | module_param(timeout, int, 0); |
65 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 66 | MODULE_PARM_DESC(timeout, |
67 | "Watchdog timeout in seconds. (1<=timeout<=3600, default=" | ||
68 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
66 | 69 | ||
67 | static int use_gpio = 0; /* Use the pic (for a1d revision alim7101) */ | 70 | static int use_gpio; /* Use the pic (for a1d revision alim7101) */ |
68 | module_param(use_gpio, int, 0); | 71 | module_param(use_gpio, int, 0); |
69 | MODULE_PARM_DESC(use_gpio, "Use the gpio watchdog. (required by old cobalt boards)"); | 72 | MODULE_PARM_DESC(use_gpio, |
73 | "Use the gpio watchdog (required by old cobalt boards)."); | ||
70 | 74 | ||
71 | static void wdt_timer_ping(unsigned long); | 75 | static void wdt_timer_ping(unsigned long); |
72 | static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1); | 76 | static DEFINE_TIMER(timer, wdt_timer_ping, 0, 1); |
@@ -77,8 +81,9 @@ static struct pci_dev *alim7101_pmu; | |||
77 | 81 | ||
78 | static int nowayout = WATCHDOG_NOWAYOUT; | 82 | static int nowayout = WATCHDOG_NOWAYOUT; |
79 | module_param(nowayout, int, 0); | 83 | module_param(nowayout, int, 0); |
80 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" | 84 | MODULE_PARM_DESC(nowayout, |
81 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 85 | "Watchdog cannot be stopped once started (default=" |
86 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
82 | 87 | ||
83 | /* | 88 | /* |
84 | * Whack the dog | 89 | * Whack the dog |
@@ -89,23 +94,26 @@ static void wdt_timer_ping(unsigned long data) | |||
89 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL | 94 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL |
90 | * we agree to ping the WDT | 95 | * we agree to ping the WDT |
91 | */ | 96 | */ |
92 | char tmp; | 97 | char tmp; |
93 | 98 | ||
94 | if(time_before(jiffies, next_heartbeat)) | 99 | if (time_before(jiffies, next_heartbeat)) { |
95 | { | ||
96 | /* Ping the WDT (this is actually a disarm/arm sequence) */ | 100 | /* Ping the WDT (this is actually a disarm/arm sequence) */ |
97 | pci_read_config_byte(alim7101_pmu, 0x92, &tmp); | 101 | pci_read_config_byte(alim7101_pmu, 0x92, &tmp); |
98 | pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM)); | 102 | pci_write_config_byte(alim7101_pmu, |
99 | pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM)); | 103 | ALI_7101_WDT, (tmp & ~ALI_WDT_ARM)); |
104 | pci_write_config_byte(alim7101_pmu, | ||
105 | ALI_7101_WDT, (tmp | ALI_WDT_ARM)); | ||
100 | if (use_gpio) { | 106 | if (use_gpio) { |
101 | pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp); | 107 | pci_read_config_byte(alim7101_pmu, |
102 | pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp | 108 | ALI_7101_GPIO_O, &tmp); |
103 | | 0x20); | 109 | pci_write_config_byte(alim7101_pmu, |
104 | pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp | 110 | ALI_7101_GPIO_O, tmp | 0x20); |
105 | & ~0x20); | 111 | pci_write_config_byte(alim7101_pmu, |
112 | ALI_7101_GPIO_O, tmp & ~0x20); | ||
106 | } | 113 | } |
107 | } else { | 114 | } else { |
108 | printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); | 115 | printk(KERN_WARNING PFX |
116 | "Heartbeat lost! Will not ping the watchdog\n"); | ||
109 | } | 117 | } |
110 | /* Re-set the timer interval */ | 118 | /* Re-set the timer interval */ |
111 | mod_timer(&timer, jiffies + WDT_INTERVAL); | 119 | mod_timer(&timer, jiffies + WDT_INTERVAL); |
@@ -117,21 +125,27 @@ static void wdt_timer_ping(unsigned long data) | |||
117 | 125 | ||
118 | static void wdt_change(int writeval) | 126 | static void wdt_change(int writeval) |
119 | { | 127 | { |
120 | char tmp; | 128 | char tmp; |
121 | 129 | ||
122 | pci_read_config_byte(alim7101_pmu, ALI_7101_WDT, &tmp); | 130 | pci_read_config_byte(alim7101_pmu, ALI_7101_WDT, &tmp); |
123 | if (writeval == WDT_ENABLE) { | 131 | if (writeval == WDT_ENABLE) { |
124 | pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp | ALI_WDT_ARM)); | 132 | pci_write_config_byte(alim7101_pmu, |
133 | ALI_7101_WDT, (tmp | ALI_WDT_ARM)); | ||
125 | if (use_gpio) { | 134 | if (use_gpio) { |
126 | pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp); | 135 | pci_read_config_byte(alim7101_pmu, |
127 | pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp & ~0x20); | 136 | ALI_7101_GPIO_O, &tmp); |
137 | pci_write_config_byte(alim7101_pmu, | ||
138 | ALI_7101_GPIO_O, tmp & ~0x20); | ||
128 | } | 139 | } |
129 | 140 | ||
130 | } else { | 141 | } else { |
131 | pci_write_config_byte(alim7101_pmu, ALI_7101_WDT, (tmp & ~ALI_WDT_ARM)); | 142 | pci_write_config_byte(alim7101_pmu, |
143 | ALI_7101_WDT, (tmp & ~ALI_WDT_ARM)); | ||
132 | if (use_gpio) { | 144 | if (use_gpio) { |
133 | pci_read_config_byte(alim7101_pmu, ALI_7101_GPIO_O, &tmp); | 145 | pci_read_config_byte(alim7101_pmu, |
134 | pci_write_config_byte(alim7101_pmu, ALI_7101_GPIO_O, tmp | 0x20); | 146 | ALI_7101_GPIO_O, &tmp); |
147 | pci_write_config_byte(alim7101_pmu, | ||
148 | ALI_7101_GPIO_O, tmp | 0x20); | ||
135 | } | 149 | } |
136 | } | 150 | } |
137 | } | 151 | } |
@@ -169,10 +183,11 @@ static void wdt_keepalive(void) | |||
169 | * /dev/watchdog handling | 183 | * /dev/watchdog handling |
170 | */ | 184 | */ |
171 | 185 | ||
172 | static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) | 186 | static ssize_t fop_write(struct file *file, const char __user *buf, |
187 | size_t count, loff_t *ppos) | ||
173 | { | 188 | { |
174 | /* See if we got the magic character 'V' and reload the timer */ | 189 | /* See if we got the magic character 'V' and reload the timer */ |
175 | if(count) { | 190 | if (count) { |
176 | if (!nowayout) { | 191 | if (!nowayout) { |
177 | size_t ofs; | 192 | size_t ofs; |
178 | 193 | ||
@@ -183,7 +198,7 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou | |||
183 | /* now scan */ | 198 | /* now scan */ |
184 | for (ofs = 0; ofs != count; ofs++) { | 199 | for (ofs = 0; ofs != count; ofs++) { |
185 | char c; | 200 | char c; |
186 | if (get_user(c, buf+ofs)) | 201 | if (get_user(c, buf + ofs)) |
187 | return -EFAULT; | 202 | return -EFAULT; |
188 | if (c == 'V') | 203 | if (c == 'V') |
189 | wdt_expect_close = 42; | 204 | wdt_expect_close = 42; |
@@ -195,119 +210,116 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou | |||
195 | return count; | 210 | return count; |
196 | } | 211 | } |
197 | 212 | ||
198 | static int fop_open(struct inode * inode, struct file * file) | 213 | static int fop_open(struct inode *inode, struct file *file) |
199 | { | 214 | { |
200 | /* Just in case we're already talking to someone... */ | 215 | /* Just in case we're already talking to someone... */ |
201 | if(test_and_set_bit(0, &wdt_is_open)) | 216 | if (test_and_set_bit(0, &wdt_is_open)) |
202 | return -EBUSY; | 217 | return -EBUSY; |
203 | /* Good, fire up the show */ | 218 | /* Good, fire up the show */ |
204 | wdt_startup(); | 219 | wdt_startup(); |
205 | return nonseekable_open(inode, file); | 220 | return nonseekable_open(inode, file); |
206 | } | 221 | } |
207 | 222 | ||
208 | static int fop_close(struct inode * inode, struct file * file) | 223 | static int fop_close(struct inode *inode, struct file *file) |
209 | { | 224 | { |
210 | if(wdt_expect_close == 42) | 225 | if (wdt_expect_close == 42) |
211 | wdt_turnoff(); | 226 | wdt_turnoff(); |
212 | else { | 227 | else { |
213 | /* wim: shouldn't there be a: del_timer(&timer); */ | 228 | /* wim: shouldn't there be a: del_timer(&timer); */ |
214 | printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); | 229 | printk(KERN_CRIT PFX |
230 | "device file closed unexpectedly. Will not stop the WDT!\n"); | ||
215 | } | 231 | } |
216 | clear_bit(0, &wdt_is_open); | 232 | clear_bit(0, &wdt_is_open); |
217 | wdt_expect_close = 0; | 233 | wdt_expect_close = 0; |
218 | return 0; | 234 | return 0; |
219 | } | 235 | } |
220 | 236 | ||
221 | static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 237 | static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
222 | { | 238 | { |
223 | void __user *argp = (void __user *)arg; | 239 | void __user *argp = (void __user *)arg; |
224 | int __user *p = argp; | 240 | int __user *p = argp; |
225 | static struct watchdog_info ident = | 241 | static struct watchdog_info ident = { |
226 | { | 242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
227 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 243 | | WDIOF_MAGICCLOSE, |
228 | .firmware_version = 1, | 244 | .firmware_version = 1, |
229 | .identity = "ALiM7101", | 245 | .identity = "ALiM7101", |
230 | }; | 246 | }; |
231 | 247 | ||
232 | switch(cmd) | 248 | switch (cmd) { |
249 | case WDIOC_GETSUPPORT: | ||
250 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
251 | case WDIOC_GETSTATUS: | ||
252 | case WDIOC_GETBOOTSTATUS: | ||
253 | return put_user(0, p); | ||
254 | case WDIOC_SETOPTIONS: | ||
233 | { | 255 | { |
234 | case WDIOC_GETSUPPORT: | 256 | int new_options, retval = -EINVAL; |
235 | return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; | ||
236 | case WDIOC_GETSTATUS: | ||
237 | case WDIOC_GETBOOTSTATUS: | ||
238 | return put_user(0, p); | ||
239 | case WDIOC_KEEPALIVE: | ||
240 | wdt_keepalive(); | ||
241 | return 0; | ||
242 | case WDIOC_SETOPTIONS: | ||
243 | { | ||
244 | int new_options, retval = -EINVAL; | ||
245 | |||
246 | if(get_user(new_options, p)) | ||
247 | return -EFAULT; | ||
248 | |||
249 | if(new_options & WDIOS_DISABLECARD) { | ||
250 | wdt_turnoff(); | ||
251 | retval = 0; | ||
252 | } | ||
253 | 257 | ||
254 | if(new_options & WDIOS_ENABLECARD) { | 258 | if (get_user(new_options, p)) |
255 | wdt_startup(); | 259 | return -EFAULT; |
256 | retval = 0; | 260 | if (new_options & WDIOS_DISABLECARD) { |
257 | } | 261 | wdt_turnoff(); |
258 | 262 | retval = 0; | |
259 | return retval; | ||
260 | } | 263 | } |
261 | case WDIOC_SETTIMEOUT: | 264 | if (new_options & WDIOS_ENABLECARD) { |
262 | { | 265 | wdt_startup(); |
263 | int new_timeout; | 266 | retval = 0; |
264 | |||
265 | if(get_user(new_timeout, p)) | ||
266 | return -EFAULT; | ||
267 | |||
268 | if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ | ||
269 | return -EINVAL; | ||
270 | |||
271 | timeout = new_timeout; | ||
272 | wdt_keepalive(); | ||
273 | /* Fall through */ | ||
274 | } | 267 | } |
275 | case WDIOC_GETTIMEOUT: | 268 | return retval; |
276 | return put_user(timeout, p); | 269 | } |
277 | default: | 270 | case WDIOC_KEEPALIVE: |
278 | return -ENOTTY; | 271 | wdt_keepalive(); |
272 | return 0; | ||
273 | case WDIOC_SETTIMEOUT: | ||
274 | { | ||
275 | int new_timeout; | ||
276 | |||
277 | if (get_user(new_timeout, p)) | ||
278 | return -EFAULT; | ||
279 | /* arbitrary upper limit */ | ||
280 | if (new_timeout < 1 || new_timeout > 3600) | ||
281 | return -EINVAL; | ||
282 | timeout = new_timeout; | ||
283 | wdt_keepalive(); | ||
284 | /* Fall through */ | ||
285 | } | ||
286 | case WDIOC_GETTIMEOUT: | ||
287 | return put_user(timeout, p); | ||
288 | default: | ||
289 | return -ENOTTY; | ||
279 | } | 290 | } |
280 | } | 291 | } |
281 | 292 | ||
282 | static const struct file_operations wdt_fops = { | 293 | static const struct file_operations wdt_fops = { |
283 | .owner= THIS_MODULE, | 294 | .owner = THIS_MODULE, |
284 | .llseek= no_llseek, | 295 | .llseek = no_llseek, |
285 | .write= fop_write, | 296 | .write = fop_write, |
286 | .open= fop_open, | 297 | .open = fop_open, |
287 | .release= fop_close, | 298 | .release = fop_close, |
288 | .ioctl= fop_ioctl, | 299 | .unlocked_ioctl = fop_ioctl, |
289 | }; | 300 | }; |
290 | 301 | ||
291 | static struct miscdevice wdt_miscdev = { | 302 | static struct miscdevice wdt_miscdev = { |
292 | .minor=WATCHDOG_MINOR, | 303 | .minor = WATCHDOG_MINOR, |
293 | .name="watchdog", | 304 | .name = "watchdog", |
294 | .fops=&wdt_fops, | 305 | .fops = &wdt_fops, |
295 | }; | 306 | }; |
296 | 307 | ||
297 | /* | 308 | /* |
298 | * Notifier for system down | 309 | * Notifier for system down |
299 | */ | 310 | */ |
300 | 311 | ||
301 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 312 | static int wdt_notify_sys(struct notifier_block *this, |
313 | unsigned long code, void *unused) | ||
302 | { | 314 | { |
303 | if (code==SYS_DOWN || code==SYS_HALT) | 315 | if (code == SYS_DOWN || code == SYS_HALT) |
304 | wdt_turnoff(); | 316 | wdt_turnoff(); |
305 | 317 | ||
306 | if (code==SYS_RESTART) { | 318 | if (code == SYS_RESTART) { |
307 | /* | 319 | /* |
308 | * Cobalt devices have no way of rebooting themselves other than | 320 | * Cobalt devices have no way of rebooting themselves other |
309 | * getting the watchdog to pull reset, so we restart the watchdog on | 321 | * than getting the watchdog to pull reset, so we restart the |
310 | * reboot with no heartbeat | 322 | * watchdog on reboot with no heartbeat |
311 | */ | 323 | */ |
312 | wdt_change(WDT_ENABLE); | 324 | wdt_change(WDT_ENABLE); |
313 | printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n"); | 325 | printk(KERN_INFO PFX "Watchdog timer is now enabled with no heartbeat - should reboot in ~1 second.\n"); |
@@ -320,8 +332,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, void | |||
320 | * turn the timebomb registers off. | 332 | * turn the timebomb registers off. |
321 | */ | 333 | */ |
322 | 334 | ||
323 | static struct notifier_block wdt_notifier= | 335 | static struct notifier_block wdt_notifier = { |
324 | { | ||
325 | .notifier_call = wdt_notify_sys, | 336 | .notifier_call = wdt_notify_sys, |
326 | }; | 337 | }; |
327 | 338 | ||
@@ -354,7 +365,8 @@ static int __init alim7101_wdt_init(void) | |||
354 | ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, | 365 | ali1543_south = pci_get_device(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M1533, |
355 | NULL); | 366 | NULL); |
356 | if (!ali1543_south) { | 367 | if (!ali1543_south) { |
357 | printk(KERN_INFO PFX "ALi 1543 South-Bridge not present - WDT not set\n"); | 368 | printk(KERN_INFO PFX |
369 | "ALi 1543 South-Bridge not present - WDT not set\n"); | ||
358 | goto err_out; | 370 | goto err_out; |
359 | } | 371 | } |
360 | pci_read_config_byte(ali1543_south, 0x5e, &tmp); | 372 | pci_read_config_byte(ali1543_south, 0x5e, &tmp); |
@@ -363,24 +375,25 @@ static int __init alim7101_wdt_init(void) | |||
363 | if (!use_gpio) { | 375 | if (!use_gpio) { |
364 | printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n"); | 376 | printk(KERN_INFO PFX "Detected old alim7101 revision 'a1d'. If this is a cobalt board, set the 'use_gpio' module parameter.\n"); |
365 | goto err_out; | 377 | goto err_out; |
366 | } | 378 | } |
367 | nowayout = 1; | 379 | nowayout = 1; |
368 | } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) { | 380 | } else if ((tmp & 0x1e) != 0x12 && (tmp & 0x1e) != 0x00) { |
369 | printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); | 381 | printk(KERN_INFO PFX "ALi 1543 South-Bridge does not have the correct revision number (???1001?) - WDT not set\n"); |
370 | goto err_out; | 382 | goto err_out; |
371 | } | 383 | } |
372 | 384 | ||
373 | if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ | 385 | if (timeout < 1 || timeout > 3600) { |
374 | { | 386 | /* arbitrary upper limit */ |
375 | timeout = WATCHDOG_TIMEOUT; | 387 | timeout = WATCHDOG_TIMEOUT; |
376 | printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", | 388 | printk(KERN_INFO PFX |
377 | timeout); | 389 | "timeout value must be 1 <= x <= 3600, using %d\n", |
390 | timeout); | ||
378 | } | 391 | } |
379 | 392 | ||
380 | rc = register_reboot_notifier(&wdt_notifier); | 393 | rc = register_reboot_notifier(&wdt_notifier); |
381 | if (rc) { | 394 | if (rc) { |
382 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 395 | printk(KERN_ERR PFX |
383 | rc); | 396 | "cannot register reboot notifier (err=%d)\n", rc); |
384 | goto err_out; | 397 | goto err_out; |
385 | } | 398 | } |
386 | 399 | ||
@@ -391,9 +404,8 @@ static int __init alim7101_wdt_init(void) | |||
391 | goto err_out_reboot; | 404 | goto err_out_reboot; |
392 | } | 405 | } |
393 | 406 | ||
394 | if (nowayout) { | 407 | if (nowayout) |
395 | __module_get(THIS_MODULE); | 408 | __module_get(THIS_MODULE); |
396 | } | ||
397 | 409 | ||
398 | printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n", | 410 | printk(KERN_INFO PFX "WDT driver for ALi M7101 initialised. timeout=%d sec (nowayout=%d)\n", |
399 | timeout, nowayout); | 411 | timeout, nowayout); |
diff --git a/drivers/watchdog/ar7_wdt.c b/drivers/watchdog/ar7_wdt.c index ef7b0d67095e..55dcbfe2bb72 100644 --- a/drivers/watchdog/ar7_wdt.c +++ b/drivers/watchdog/ar7_wdt.c | |||
@@ -213,7 +213,7 @@ static int ar7_wdt_notify_sys(struct notifier_block *this, | |||
213 | } | 213 | } |
214 | 214 | ||
215 | static struct notifier_block ar7_wdt_notifier = { | 215 | static struct notifier_block ar7_wdt_notifier = { |
216 | .notifier_call = ar7_wdt_notify_sys | 216 | .notifier_call = ar7_wdt_notify_sys, |
217 | }; | 217 | }; |
218 | 218 | ||
219 | static ssize_t ar7_wdt_write(struct file *file, const char *data, | 219 | static ssize_t ar7_wdt_write(struct file *file, const char *data, |
@@ -230,7 +230,7 @@ static ssize_t ar7_wdt_write(struct file *file, const char *data, | |||
230 | expect_close = 0; | 230 | expect_close = 0; |
231 | for (i = 0; i < len; ++i) { | 231 | for (i = 0; i < len; ++i) { |
232 | char c; | 232 | char c; |
233 | if (get_user(c, data+i)) | 233 | if (get_user(c, data + i)) |
234 | return -EFAULT; | 234 | return -EFAULT; |
235 | if (c == 'V') | 235 | if (c == 'V') |
236 | expect_close = 1; | 236 | expect_close = 1; |
@@ -251,8 +251,6 @@ static long ar7_wdt_ioctl(struct file *file, | |||
251 | int new_margin; | 251 | int new_margin; |
252 | 252 | ||
253 | switch (cmd) { | 253 | switch (cmd) { |
254 | default: | ||
255 | return -ENOTTY; | ||
256 | case WDIOC_GETSUPPORT: | 254 | case WDIOC_GETSUPPORT: |
257 | if (copy_to_user((struct watchdog_info *)arg, &ident, | 255 | if (copy_to_user((struct watchdog_info *)arg, &ident, |
258 | sizeof(ident))) | 256 | sizeof(ident))) |
@@ -281,6 +279,8 @@ static long ar7_wdt_ioctl(struct file *file, | |||
281 | if (put_user(margin, (int *)arg)) | 279 | if (put_user(margin, (int *)arg)) |
282 | return -EFAULT; | 280 | return -EFAULT; |
283 | return 0; | 281 | return 0; |
282 | default: | ||
283 | return -ENOTTY; | ||
284 | } | 284 | } |
285 | } | 285 | } |
286 | 286 | ||
diff --git a/drivers/watchdog/at32ap700x_wdt.c b/drivers/watchdog/at32ap700x_wdt.c index ae0fca5e8749..e8ae638e5804 100644 --- a/drivers/watchdog/at32ap700x_wdt.c +++ b/drivers/watchdog/at32ap700x_wdt.c | |||
@@ -212,8 +212,8 @@ static struct watchdog_info at32_wdt_info = { | |||
212 | /* | 212 | /* |
213 | * Handle commands from user-space. | 213 | * Handle commands from user-space. |
214 | */ | 214 | */ |
215 | static int at32_wdt_ioctl(struct inode *inode, struct file *file, | 215 | static long at32_wdt_ioctl(struct file *file, |
216 | unsigned int cmd, unsigned long arg) | 216 | unsigned int cmd, unsigned long arg) |
217 | { | 217 | { |
218 | int ret = -ENOTTY; | 218 | int ret = -ENOTTY; |
219 | int time; | 219 | int time; |
@@ -221,27 +221,10 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file, | |||
221 | int __user *p = argp; | 221 | int __user *p = argp; |
222 | 222 | ||
223 | switch (cmd) { | 223 | switch (cmd) { |
224 | case WDIOC_KEEPALIVE: | ||
225 | at32_wdt_pat(); | ||
226 | ret = 0; | ||
227 | break; | ||
228 | case WDIOC_GETSUPPORT: | 224 | case WDIOC_GETSUPPORT: |
229 | ret = copy_to_user(argp, &at32_wdt_info, | 225 | ret = copy_to_user(argp, &at32_wdt_info, |
230 | sizeof(at32_wdt_info)) ? -EFAULT : 0; | 226 | sizeof(at32_wdt_info)) ? -EFAULT : 0; |
231 | break; | 227 | break; |
232 | case WDIOC_SETTIMEOUT: | ||
233 | ret = get_user(time, p); | ||
234 | if (ret) | ||
235 | break; | ||
236 | ret = at32_wdt_settimeout(time); | ||
237 | if (ret) | ||
238 | break; | ||
239 | /* Enable new time value */ | ||
240 | at32_wdt_start(); | ||
241 | /* fall through */ | ||
242 | case WDIOC_GETTIMEOUT: | ||
243 | ret = put_user(wdt->timeout, p); | ||
244 | break; | ||
245 | case WDIOC_GETSTATUS: | 228 | case WDIOC_GETSTATUS: |
246 | ret = put_user(0, p); | 229 | ret = put_user(0, p); |
247 | break; | 230 | break; |
@@ -258,6 +241,23 @@ static int at32_wdt_ioctl(struct inode *inode, struct file *file, | |||
258 | at32_wdt_start(); | 241 | at32_wdt_start(); |
259 | ret = 0; | 242 | ret = 0; |
260 | break; | 243 | break; |
244 | case WDIOC_KEEPALIVE: | ||
245 | at32_wdt_pat(); | ||
246 | ret = 0; | ||
247 | break; | ||
248 | case WDIOC_SETTIMEOUT: | ||
249 | ret = get_user(time, p); | ||
250 | if (ret) | ||
251 | break; | ||
252 | ret = at32_wdt_settimeout(time); | ||
253 | if (ret) | ||
254 | break; | ||
255 | /* Enable new time value */ | ||
256 | at32_wdt_start(); | ||
257 | /* fall through */ | ||
258 | case WDIOC_GETTIMEOUT: | ||
259 | ret = put_user(wdt->timeout, p); | ||
260 | break; | ||
261 | } | 261 | } |
262 | 262 | ||
263 | return ret; | 263 | return ret; |
@@ -283,7 +283,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data, | |||
283 | */ | 283 | */ |
284 | for (i = 0; i != len; i++) { | 284 | for (i = 0; i != len; i++) { |
285 | char c; | 285 | char c; |
286 | if (get_user(c, data+i)) | 286 | if (get_user(c, data + i)) |
287 | return -EFAULT; | 287 | return -EFAULT; |
288 | if (c == 'V') | 288 | if (c == 'V') |
289 | expect_release = 42; | 289 | expect_release = 42; |
@@ -298,7 +298,7 @@ static ssize_t at32_wdt_write(struct file *file, const char __user *data, | |||
298 | static const struct file_operations at32_wdt_fops = { | 298 | static const struct file_operations at32_wdt_fops = { |
299 | .owner = THIS_MODULE, | 299 | .owner = THIS_MODULE, |
300 | .llseek = no_llseek, | 300 | .llseek = no_llseek, |
301 | .ioctl = at32_wdt_ioctl, | 301 | .unlocked_ioctl = at32_wdt_ioctl, |
302 | .open = at32_wdt_open, | 302 | .open = at32_wdt_open, |
303 | .release = at32_wdt_close, | 303 | .release = at32_wdt_close, |
304 | .write = at32_wdt_write, | 304 | .write = at32_wdt_write, |
@@ -391,7 +391,6 @@ static int __exit at32_wdt_remove(struct platform_device *pdev) | |||
391 | wdt = NULL; | 391 | wdt = NULL; |
392 | platform_set_drvdata(pdev, NULL); | 392 | platform_set_drvdata(pdev, NULL); |
393 | } | 393 | } |
394 | |||
395 | return 0; | 394 | return 0; |
396 | } | 395 | } |
397 | 396 | ||
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c index bf872aa2b9f3..bacd867dd22e 100644 --- a/drivers/watchdog/at91rm9200_wdt.c +++ b/drivers/watchdog/at91rm9200_wdt.c | |||
@@ -20,10 +20,9 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/types.h> | 21 | #include <linux/types.h> |
22 | #include <linux/watchdog.h> | 22 | #include <linux/watchdog.h> |
23 | #include <asm/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <mach/at91_st.h> | 24 | #include <mach/at91_st.h> |
25 | 25 | ||
26 | |||
27 | #define WDT_DEFAULT_TIME 5 /* seconds */ | 26 | #define WDT_DEFAULT_TIME 5 /* seconds */ |
28 | #define WDT_MAX_TIME 256 /* seconds */ | 27 | #define WDT_MAX_TIME 256 /* seconds */ |
29 | 28 | ||
@@ -31,11 +30,14 @@ static int wdt_time = WDT_DEFAULT_TIME; | |||
31 | static int nowayout = WATCHDOG_NOWAYOUT; | 30 | static int nowayout = WATCHDOG_NOWAYOUT; |
32 | 31 | ||
33 | module_param(wdt_time, int, 0); | 32 | module_param(wdt_time, int, 0); |
34 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); | 33 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default=" |
34 | __MODULE_STRING(WDT_DEFAULT_TIME) ")"); | ||
35 | 35 | ||
36 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 36 | #ifdef CONFIG_WATCHDOG_NOWAYOUT |
37 | module_param(nowayout, int, 0); | 37 | module_param(nowayout, int, 0); |
38 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 38 | MODULE_PARM_DESC(nowayout, |
39 | "Watchdog cannot be stopped once started (default=" | ||
40 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
39 | #endif | 41 | #endif |
40 | 42 | ||
41 | 43 | ||
@@ -46,7 +48,7 @@ static unsigned long at91wdt_busy; | |||
46 | /* | 48 | /* |
47 | * Disable the watchdog. | 49 | * Disable the watchdog. |
48 | */ | 50 | */ |
49 | static void inline at91_wdt_stop(void) | 51 | static inline void at91_wdt_stop(void) |
50 | { | 52 | { |
51 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); | 53 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN); |
52 | } | 54 | } |
@@ -54,16 +56,17 @@ static void inline at91_wdt_stop(void) | |||
54 | /* | 56 | /* |
55 | * Enable and reset the watchdog. | 57 | * Enable and reset the watchdog. |
56 | */ | 58 | */ |
57 | static void inline at91_wdt_start(void) | 59 | static inline void at91_wdt_start(void) |
58 | { | 60 | { |
59 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); | 61 | at91_sys_write(AT91_ST_WDMR, AT91_ST_EXTEN | AT91_ST_RSTEN | |
62 | (((65536 * wdt_time) >> 8) & AT91_ST_WDV)); | ||
60 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); | 63 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); |
61 | } | 64 | } |
62 | 65 | ||
63 | /* | 66 | /* |
64 | * Reload the watchdog timer. (ie, pat the watchdog) | 67 | * Reload the watchdog timer. (ie, pat the watchdog) |
65 | */ | 68 | */ |
66 | static void inline at91_wdt_reload(void) | 69 | static inline void at91_wdt_reload(void) |
67 | { | 70 | { |
68 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); | 71 | at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); |
69 | } | 72 | } |
@@ -89,8 +92,9 @@ static int at91_wdt_open(struct inode *inode, struct file *file) | |||
89 | */ | 92 | */ |
90 | static int at91_wdt_close(struct inode *inode, struct file *file) | 93 | static int at91_wdt_close(struct inode *inode, struct file *file) |
91 | { | 94 | { |
95 | /* Disable the watchdog when file is closed */ | ||
92 | if (!nowayout) | 96 | if (!nowayout) |
93 | at91_wdt_stop(); /* Disable the watchdog when file is closed */ | 97 | at91_wdt_stop(); |
94 | 98 | ||
95 | clear_bit(0, &at91wdt_busy); | 99 | clear_bit(0, &at91wdt_busy); |
96 | return 0; | 100 | return 0; |
@@ -110,7 +114,8 @@ static int at91_wdt_settimeout(int new_time) | |||
110 | if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) | 114 | if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) |
111 | return -EINVAL; | 115 | return -EINVAL; |
112 | 116 | ||
113 | /* Set new watchdog time. It will be used when at91_wdt_start() is called. */ | 117 | /* Set new watchdog time. It will be used when |
118 | at91_wdt_start() is called. */ | ||
114 | wdt_time = new_time; | 119 | wdt_time = new_time; |
115 | return 0; | 120 | return 0; |
116 | } | 121 | } |
@@ -123,60 +128,52 @@ static struct watchdog_info at91_wdt_info = { | |||
123 | /* | 128 | /* |
124 | * Handle commands from user-space. | 129 | * Handle commands from user-space. |
125 | */ | 130 | */ |
126 | static int at91_wdt_ioctl(struct inode *inode, struct file *file, | 131 | static long at91_wdt_ioct(struct file *file, |
127 | unsigned int cmd, unsigned long arg) | 132 | unsigned int cmd, unsigned long arg) |
128 | { | 133 | { |
129 | void __user *argp = (void __user *)arg; | 134 | void __user *argp = (void __user *)arg; |
130 | int __user *p = argp; | 135 | int __user *p = argp; |
131 | int new_value; | 136 | int new_value; |
132 | 137 | ||
133 | switch(cmd) { | 138 | switch (cmd) { |
134 | case WDIOC_KEEPALIVE: | 139 | case WDIOC_GETSUPPORT: |
135 | at91_wdt_reload(); /* pat the watchdog */ | 140 | return copy_to_user(argp, &at91_wdt_info, |
136 | return 0; | 141 | sizeof(at91_wdt_info)) ? -EFAULT : 0; |
137 | 142 | case WDIOC_GETSTATUS: | |
138 | case WDIOC_GETSUPPORT: | 143 | case WDIOC_GETBOOTSTATUS: |
139 | return copy_to_user(argp, &at91_wdt_info, sizeof(at91_wdt_info)) ? -EFAULT : 0; | 144 | return put_user(0, p); |
140 | 145 | case WDIOC_SETOPTIONS: | |
141 | case WDIOC_SETTIMEOUT: | 146 | if (get_user(new_value, p)) |
142 | if (get_user(new_value, p)) | 147 | return -EFAULT; |
143 | return -EFAULT; | 148 | if (new_value & WDIOS_DISABLECARD) |
144 | 149 | at91_wdt_stop(); | |
145 | if (at91_wdt_settimeout(new_value)) | 150 | if (new_value & WDIOS_ENABLECARD) |
146 | return -EINVAL; | ||
147 | |||
148 | /* Enable new time value */ | ||
149 | at91_wdt_start(); | 151 | at91_wdt_start(); |
150 | 152 | return 0; | |
151 | /* Return current value */ | 153 | case WDIOC_KEEPALIVE: |
152 | return put_user(wdt_time, p); | 154 | at91_wdt_reload(); /* pat the watchdog */ |
153 | 155 | return 0; | |
154 | case WDIOC_GETTIMEOUT: | 156 | case WDIOC_SETTIMEOUT: |
155 | return put_user(wdt_time, p); | 157 | if (get_user(new_value, p)) |
156 | 158 | return -EFAULT; | |
157 | case WDIOC_GETSTATUS: | 159 | if (at91_wdt_settimeout(new_value)) |
158 | case WDIOC_GETBOOTSTATUS: | 160 | return -EINVAL; |
159 | return put_user(0, p); | 161 | /* Enable new time value */ |
160 | 162 | at91_wdt_start(); | |
161 | case WDIOC_SETOPTIONS: | 163 | /* Return current value */ |
162 | if (get_user(new_value, p)) | 164 | return put_user(wdt_time, p); |
163 | return -EFAULT; | 165 | case WDIOC_GETTIMEOUT: |
164 | 166 | return put_user(wdt_time, p); | |
165 | if (new_value & WDIOS_DISABLECARD) | 167 | default: |
166 | at91_wdt_stop(); | 168 | return -ENOTTY; |
167 | if (new_value & WDIOS_ENABLECARD) | ||
168 | at91_wdt_start(); | ||
169 | return 0; | ||
170 | |||
171 | default: | ||
172 | return -ENOTTY; | ||
173 | } | 169 | } |
174 | } | 170 | } |
175 | 171 | ||
176 | /* | 172 | /* |
177 | * Pat the watchdog whenever device is written to. | 173 | * Pat the watchdog whenever device is written to. |
178 | */ | 174 | */ |
179 | static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 175 | static ssize_t at91_wdt_write(struct file *file, const char *data, |
176 | size_t len, loff_t *ppos) | ||
180 | { | 177 | { |
181 | at91_wdt_reload(); /* pat the watchdog */ | 178 | at91_wdt_reload(); /* pat the watchdog */ |
182 | return len; | 179 | return len; |
@@ -187,7 +184,7 @@ static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, l | |||
187 | static const struct file_operations at91wdt_fops = { | 184 | static const struct file_operations at91wdt_fops = { |
188 | .owner = THIS_MODULE, | 185 | .owner = THIS_MODULE, |
189 | .llseek = no_llseek, | 186 | .llseek = no_llseek, |
190 | .ioctl = at91_wdt_ioctl, | 187 | .unlocked_ioctl = at91_wdt_ioctl, |
191 | .open = at91_wdt_open, | 188 | .open = at91_wdt_open, |
192 | .release = at91_wdt_close, | 189 | .release = at91_wdt_close, |
193 | .write = at91_wdt_write, | 190 | .write = at91_wdt_write, |
@@ -211,7 +208,8 @@ static int __init at91wdt_probe(struct platform_device *pdev) | |||
211 | if (res) | 208 | if (res) |
212 | return res; | 209 | return res; |
213 | 210 | ||
214 | printk("AT91 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); | 211 | printk(KERN_INFO "AT91 Watchdog Timer enabled (%d seconds%s)\n", |
212 | wdt_time, nowayout ? ", nowayout" : ""); | ||
215 | return 0; | 213 | return 0; |
216 | } | 214 | } |
217 | 215 | ||
@@ -265,7 +263,8 @@ static struct platform_driver at91wdt_driver = { | |||
265 | 263 | ||
266 | static int __init at91_wdt_init(void) | 264 | static int __init at91_wdt_init(void) |
267 | { | 265 | { |
268 | /* Check that the heartbeat value is within range; if not reset to the default */ | 266 | /* Check that the heartbeat value is within range; |
267 | if not reset to the default */ | ||
269 | if (at91_wdt_settimeout(wdt_time)) { | 268 | if (at91_wdt_settimeout(wdt_time)) { |
270 | at91_wdt_settimeout(WDT_DEFAULT_TIME); | 269 | at91_wdt_settimeout(WDT_DEFAULT_TIME); |
271 | pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); | 270 | pr_info("at91_wdt: wdt_time value must be 1 <= wdt_time <= 256, using %d\n", wdt_time); |
diff --git a/drivers/watchdog/bfin_wdt.c b/drivers/watchdog/bfin_wdt.c index 03b3e3d91e7c..31b42253054e 100644 --- a/drivers/watchdog/bfin_wdt.c +++ b/drivers/watchdog/bfin_wdt.c | |||
@@ -24,8 +24,8 @@ | |||
24 | #include <linux/reboot.h> | 24 | #include <linux/reboot.h> |
25 | #include <linux/init.h> | 25 | #include <linux/init.h> |
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/uaccess.h> | ||
27 | #include <asm/blackfin.h> | 28 | #include <asm/blackfin.h> |
28 | #include <asm/uaccess.h> | ||
29 | 29 | ||
30 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) | 30 | #define stamp(fmt, args...) pr_debug("%s:%i: " fmt "\n", __func__, __LINE__, ## args) |
31 | #define stampit() stamp("here i am") | 31 | #define stampit() stamp("here i am") |
@@ -148,7 +148,8 @@ static int bfin_wdt_set_timeout(unsigned long t) | |||
148 | int run = bfin_wdt_running(); | 148 | int run = bfin_wdt_running(); |
149 | bfin_wdt_stop(); | 149 | bfin_wdt_stop(); |
150 | bfin_write_WDOG_CNT(cnt); | 150 | bfin_write_WDOG_CNT(cnt); |
151 | if (run) bfin_wdt_start(); | 151 | if (run) |
152 | bfin_wdt_start(); | ||
152 | } | 153 | } |
153 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | 154 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); |
154 | 155 | ||
@@ -191,16 +192,15 @@ static int bfin_wdt_release(struct inode *inode, struct file *file) | |||
191 | { | 192 | { |
192 | stampit(); | 193 | stampit(); |
193 | 194 | ||
194 | if (expect_close == 42) { | 195 | if (expect_close == 42) |
195 | bfin_wdt_stop(); | 196 | bfin_wdt_stop(); |
196 | } else { | 197 | else { |
197 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 198 | printk(KERN_CRIT PFX |
199 | "Unexpected close, not stopping watchdog!\n"); | ||
198 | bfin_wdt_keepalive(); | 200 | bfin_wdt_keepalive(); |
199 | } | 201 | } |
200 | |||
201 | expect_close = 0; | 202 | expect_close = 0; |
202 | clear_bit(0, &open_check); | 203 | clear_bit(0, &open_check); |
203 | |||
204 | return 0; | 204 | return 0; |
205 | } | 205 | } |
206 | 206 | ||
@@ -214,7 +214,7 @@ static int bfin_wdt_release(struct inode *inode, struct file *file) | |||
214 | * Pings the watchdog on write. | 214 | * Pings the watchdog on write. |
215 | */ | 215 | */ |
216 | static ssize_t bfin_wdt_write(struct file *file, const char __user *data, | 216 | static ssize_t bfin_wdt_write(struct file *file, const char __user *data, |
217 | size_t len, loff_t *ppos) | 217 | size_t len, loff_t *ppos) |
218 | { | 218 | { |
219 | stampit(); | 219 | stampit(); |
220 | 220 | ||
@@ -241,7 +241,6 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data, | |||
241 | 241 | ||
242 | /** | 242 | /** |
243 | * bfin_wdt_ioctl - Query Device | 243 | * bfin_wdt_ioctl - Query Device |
244 | * @inode: inode of device | ||
245 | * @file: file handle of device | 244 | * @file: file handle of device |
246 | * @cmd: watchdog command | 245 | * @cmd: watchdog command |
247 | * @arg: argument | 246 | * @arg: argument |
@@ -249,8 +248,8 @@ static ssize_t bfin_wdt_write(struct file *file, const char __user *data, | |||
249 | * Query basic information from the device or ping it, as outlined by the | 248 | * Query basic information from the device or ping it, as outlined by the |
250 | * watchdog API. | 249 | * watchdog API. |
251 | */ | 250 | */ |
252 | static int bfin_wdt_ioctl(struct inode *inode, struct file *file, | 251 | static long bfin_wdt_ioctl(struct file *file, |
253 | unsigned int cmd, unsigned long arg) | 252 | unsigned int cmd, unsigned long arg) |
254 | { | 253 | { |
255 | void __user *argp = (void __user *)arg; | 254 | void __user *argp = (void __user *)arg; |
256 | int __user *p = argp; | 255 | int __user *p = argp; |
@@ -258,59 +257,49 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file, | |||
258 | stampit(); | 257 | stampit(); |
259 | 258 | ||
260 | switch (cmd) { | 259 | switch (cmd) { |
261 | default: | 260 | case WDIOC_GETSUPPORT: |
262 | return -ENOTTY; | 261 | if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) |
263 | 262 | return -EFAULT; | |
264 | case WDIOC_GETSUPPORT: | 263 | else |
265 | if (copy_to_user(argp, &bfin_wdt_info, sizeof(bfin_wdt_info))) | ||
266 | return -EFAULT; | ||
267 | else | ||
268 | return 0; | ||
269 | |||
270 | case WDIOC_GETSTATUS: | ||
271 | case WDIOC_GETBOOTSTATUS: | ||
272 | return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); | ||
273 | |||
274 | case WDIOC_KEEPALIVE: | ||
275 | bfin_wdt_keepalive(); | ||
276 | return 0; | 264 | return 0; |
277 | 265 | case WDIOC_GETSTATUS: | |
278 | case WDIOC_SETTIMEOUT: { | 266 | case WDIOC_GETBOOTSTATUS: |
279 | int new_timeout; | 267 | return put_user(!!(_bfin_swrst & SWRST_RESET_WDOG), p); |
280 | 268 | case WDIOC_SETOPTIONS: { | |
281 | if (get_user(new_timeout, p)) | 269 | unsigned long flags; |
282 | return -EFAULT; | 270 | int options, ret = -EINVAL; |
283 | 271 | ||
284 | if (bfin_wdt_set_timeout(new_timeout)) | 272 | if (get_user(options, p)) |
285 | return -EINVAL; | 273 | return -EFAULT; |
274 | |||
275 | spin_lock_irqsave(&bfin_wdt_spinlock, flags); | ||
276 | if (options & WDIOS_DISABLECARD) { | ||
277 | bfin_wdt_stop(); | ||
278 | ret = 0; | ||
286 | } | 279 | } |
287 | /* Fall */ | 280 | if (options & WDIOS_ENABLECARD) { |
288 | case WDIOC_GETTIMEOUT: | 281 | bfin_wdt_start(); |
289 | return put_user(timeout, p); | 282 | ret = 0; |
290 | |||
291 | case WDIOC_SETOPTIONS: { | ||
292 | unsigned long flags; | ||
293 | int options, ret = -EINVAL; | ||
294 | |||
295 | if (get_user(options, p)) | ||
296 | return -EFAULT; | ||
297 | |||
298 | spin_lock_irqsave(&bfin_wdt_spinlock, flags); | ||
299 | |||
300 | if (options & WDIOS_DISABLECARD) { | ||
301 | bfin_wdt_stop(); | ||
302 | ret = 0; | ||
303 | } | ||
304 | |||
305 | if (options & WDIOS_ENABLECARD) { | ||
306 | bfin_wdt_start(); | ||
307 | ret = 0; | ||
308 | } | ||
309 | |||
310 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | ||
311 | |||
312 | return ret; | ||
313 | } | 283 | } |
284 | spin_unlock_irqrestore(&bfin_wdt_spinlock, flags); | ||
285 | return ret; | ||
286 | } | ||
287 | case WDIOC_KEEPALIVE: | ||
288 | bfin_wdt_keepalive(); | ||
289 | return 0; | ||
290 | case WDIOC_SETTIMEOUT: { | ||
291 | int new_timeout; | ||
292 | |||
293 | if (get_user(new_timeout, p)) | ||
294 | return -EFAULT; | ||
295 | if (bfin_wdt_set_timeout(new_timeout)) | ||
296 | return -EINVAL; | ||
297 | } | ||
298 | /* Fall */ | ||
299 | case WDIOC_GETTIMEOUT: | ||
300 | return put_user(timeout, p); | ||
301 | default: | ||
302 | return -ENOTTY; | ||
314 | } | 303 | } |
315 | } | 304 | } |
316 | 305 | ||
@@ -323,8 +312,8 @@ static int bfin_wdt_ioctl(struct inode *inode, struct file *file, | |||
323 | * Handles specific events, such as turning off the watchdog during a | 312 | * Handles specific events, such as turning off the watchdog during a |
324 | * shutdown event. | 313 | * shutdown event. |
325 | */ | 314 | */ |
326 | static int bfin_wdt_notify_sys(struct notifier_block *this, unsigned long code, | 315 | static int bfin_wdt_notify_sys(struct notifier_block *this, |
327 | void *unused) | 316 | unsigned long code, void *unused) |
328 | { | 317 | { |
329 | stampit(); | 318 | stampit(); |
330 | 319 | ||
@@ -379,12 +368,12 @@ static int bfin_wdt_resume(struct platform_device *pdev) | |||
379 | #endif | 368 | #endif |
380 | 369 | ||
381 | static const struct file_operations bfin_wdt_fops = { | 370 | static const struct file_operations bfin_wdt_fops = { |
382 | .owner = THIS_MODULE, | 371 | .owner = THIS_MODULE, |
383 | .llseek = no_llseek, | 372 | .llseek = no_llseek, |
384 | .write = bfin_wdt_write, | 373 | .write = bfin_wdt_write, |
385 | .ioctl = bfin_wdt_ioctl, | 374 | .unlocked_ioctl = bfin_wdt_ioctl, |
386 | .open = bfin_wdt_open, | 375 | .open = bfin_wdt_open, |
387 | .release = bfin_wdt_release, | 376 | .release = bfin_wdt_release, |
388 | }; | 377 | }; |
389 | 378 | ||
390 | static struct miscdevice bfin_wdt_miscdev = { | 379 | static struct miscdevice bfin_wdt_miscdev = { |
@@ -396,8 +385,8 @@ static struct miscdevice bfin_wdt_miscdev = { | |||
396 | static struct watchdog_info bfin_wdt_info = { | 385 | static struct watchdog_info bfin_wdt_info = { |
397 | .identity = "Blackfin Watchdog", | 386 | .identity = "Blackfin Watchdog", |
398 | .options = WDIOF_SETTIMEOUT | | 387 | .options = WDIOF_SETTIMEOUT | |
399 | WDIOF_KEEPALIVEPING | | 388 | WDIOF_KEEPALIVEPING | |
400 | WDIOF_MAGICCLOSE, | 389 | WDIOF_MAGICCLOSE, |
401 | }; | 390 | }; |
402 | 391 | ||
403 | static struct notifier_block bfin_wdt_notifier = { | 392 | static struct notifier_block bfin_wdt_notifier = { |
@@ -416,14 +405,16 @@ static int __devinit bfin_wdt_probe(struct platform_device *pdev) | |||
416 | 405 | ||
417 | ret = register_reboot_notifier(&bfin_wdt_notifier); | 406 | ret = register_reboot_notifier(&bfin_wdt_notifier); |
418 | if (ret) { | 407 | if (ret) { |
419 | pr_devinit(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", ret); | 408 | pr_devinit(KERN_ERR PFX |
409 | "cannot register reboot notifier (err=%d)\n", ret); | ||
420 | return ret; | 410 | return ret; |
421 | } | 411 | } |
422 | 412 | ||
423 | ret = misc_register(&bfin_wdt_miscdev); | 413 | ret = misc_register(&bfin_wdt_miscdev); |
424 | if (ret) { | 414 | if (ret) { |
425 | pr_devinit(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 415 | pr_devinit(KERN_ERR PFX |
426 | WATCHDOG_MINOR, ret); | 416 | "cannot register miscdev on minor=%d (err=%d)\n", |
417 | WATCHDOG_MINOR, ret); | ||
427 | unregister_reboot_notifier(&bfin_wdt_notifier); | 418 | unregister_reboot_notifier(&bfin_wdt_notifier); |
428 | return ret; | 419 | return ret; |
429 | } | 420 | } |
@@ -516,7 +507,11 @@ MODULE_LICENSE("GPL"); | |||
516 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 507 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
517 | 508 | ||
518 | module_param(timeout, uint, 0); | 509 | module_param(timeout, uint, 0); |
519 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 510 | MODULE_PARM_DESC(timeout, |
511 | "Watchdog timeout in seconds. (1<=timeout<=((2^32)/SCLK), default=" | ||
512 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
520 | 513 | ||
521 | module_param(nowayout, int, 0); | 514 | module_param(nowayout, int, 0); |
522 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 515 | MODULE_PARM_DESC(nowayout, |
516 | "Watchdog cannot be stopped once started (default=" | ||
517 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
diff --git a/drivers/watchdog/booke_wdt.c b/drivers/watchdog/booke_wdt.c index 770824458d45..c3b78a76f173 100644 --- a/drivers/watchdog/booke_wdt.c +++ b/drivers/watchdog/booke_wdt.c | |||
@@ -18,9 +18,9 @@ | |||
18 | #include <linux/miscdevice.h> | 18 | #include <linux/miscdevice.h> |
19 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
20 | #include <linux/watchdog.h> | 20 | #include <linux/watchdog.h> |
21 | #include <linux/uaccess.h> | ||
21 | 22 | ||
22 | #include <asm/reg_booke.h> | 23 | #include <asm/reg_booke.h> |
23 | #include <asm/uaccess.h> | ||
24 | #include <asm/system.h> | 24 | #include <asm/system.h> |
25 | 25 | ||
26 | /* If the kernel parameter wdt=1, the watchdog will be enabled at boot. | 26 | /* If the kernel parameter wdt=1, the watchdog will be enabled at boot. |
@@ -32,7 +32,7 @@ | |||
32 | */ | 32 | */ |
33 | 33 | ||
34 | #ifdef CONFIG_FSL_BOOKE | 34 | #ifdef CONFIG_FSL_BOOKE |
35 | #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz , reset=~40sec */ | 35 | #define WDT_PERIOD_DEFAULT 63 /* Ex. wdt_period=28 bus=333Mhz,reset=~40sec */ |
36 | #else | 36 | #else |
37 | #define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ | 37 | #define WDT_PERIOD_DEFAULT 3 /* Refer to the PPC40x and PPC4xx manuals */ |
38 | #endif /* for timing information */ | 38 | #endif /* for timing information */ |
@@ -82,16 +82,15 @@ static struct watchdog_info ident = { | |||
82 | .identity = "PowerPC Book-E Watchdog", | 82 | .identity = "PowerPC Book-E Watchdog", |
83 | }; | 83 | }; |
84 | 84 | ||
85 | static int booke_wdt_ioctl(struct inode *inode, struct file *file, | 85 | static long booke_wdt_ioctl(struct file *file, |
86 | unsigned int cmd, unsigned long arg) | 86 | unsigned int cmd, unsigned long arg) |
87 | { | 87 | { |
88 | u32 tmp = 0; | 88 | u32 tmp = 0; |
89 | u32 __user *p = (u32 __user *)arg; | 89 | u32 __user *p = (u32 __user *)arg; |
90 | 90 | ||
91 | switch (cmd) { | 91 | switch (cmd) { |
92 | case WDIOC_GETSUPPORT: | 92 | case WDIOC_GETSUPPORT: |
93 | if (copy_to_user((struct watchdog_info __user *)arg, &ident, | 93 | if (copy_to_user(arg, &ident, sizeof(struct watchdog_info))) |
94 | sizeof(struct watchdog_info))) | ||
95 | return -EFAULT; | 94 | return -EFAULT; |
96 | case WDIOC_GETSTATUS: | 95 | case WDIOC_GETSTATUS: |
97 | return put_user(ident.options, p); | 96 | return put_user(ident.options, p); |
@@ -100,16 +99,6 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file, | |||
100 | tmp = mfspr(SPRN_TSR) & TSR_WRS(3); | 99 | tmp = mfspr(SPRN_TSR) & TSR_WRS(3); |
101 | /* returns 1 if last reset was caused by the WDT */ | 100 | /* returns 1 if last reset was caused by the WDT */ |
102 | return (tmp ? 1 : 0); | 101 | return (tmp ? 1 : 0); |
103 | case WDIOC_KEEPALIVE: | ||
104 | booke_wdt_ping(); | ||
105 | return 0; | ||
106 | case WDIOC_SETTIMEOUT: | ||
107 | if (get_user(booke_wdt_period, p)) | ||
108 | return -EFAULT; | ||
109 | mtspr(SPRN_TCR, (mfspr(SPRN_TCR)&~WDTP(0))|WDTP(booke_wdt_period)); | ||
110 | return 0; | ||
111 | case WDIOC_GETTIMEOUT: | ||
112 | return put_user(booke_wdt_period, p); | ||
113 | case WDIOC_SETOPTIONS: | 102 | case WDIOC_SETOPTIONS: |
114 | if (get_user(tmp, p)) | 103 | if (get_user(tmp, p)) |
115 | return -EINVAL; | 104 | return -EINVAL; |
@@ -119,6 +108,17 @@ static int booke_wdt_ioctl(struct inode *inode, struct file *file, | |||
119 | } else | 108 | } else |
120 | return -EINVAL; | 109 | return -EINVAL; |
121 | return 0; | 110 | return 0; |
111 | case WDIOC_KEEPALIVE: | ||
112 | booke_wdt_ping(); | ||
113 | return 0; | ||
114 | case WDIOC_SETTIMEOUT: | ||
115 | if (get_user(booke_wdt_period, p)) | ||
116 | return -EFAULT; | ||
117 | mtspr(SPRN_TCR, (mfspr(SPRN_TCR) & ~WDTP(0)) | | ||
118 | WDTP(booke_wdt_period)); | ||
119 | return 0; | ||
120 | case WDIOC_GETTIMEOUT: | ||
121 | return put_user(booke_wdt_period, p); | ||
122 | default: | 122 | default: |
123 | return -ENOTTY; | 123 | return -ENOTTY; |
124 | } | 124 | } |
@@ -132,8 +132,9 @@ static int booke_wdt_open(struct inode *inode, struct file *file) | |||
132 | if (booke_wdt_enabled == 0) { | 132 | if (booke_wdt_enabled == 0) { |
133 | booke_wdt_enabled = 1; | 133 | booke_wdt_enabled = 1; |
134 | on_each_cpu(__booke_wdt_enable, NULL, 0); | 134 | on_each_cpu(__booke_wdt_enable, NULL, 0); |
135 | printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " | 135 | printk(KERN_INFO |
136 | "(wdt_period=%d)\n", booke_wdt_period); | 136 | "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", |
137 | booke_wdt_period); | ||
137 | } | 138 | } |
138 | spin_unlock(&booke_wdt_lock); | 139 | spin_unlock(&booke_wdt_lock); |
139 | 140 | ||
@@ -144,7 +145,7 @@ static const struct file_operations booke_wdt_fops = { | |||
144 | .owner = THIS_MODULE, | 145 | .owner = THIS_MODULE, |
145 | .llseek = no_llseek, | 146 | .llseek = no_llseek, |
146 | .write = booke_wdt_write, | 147 | .write = booke_wdt_write, |
147 | .ioctl = booke_wdt_ioctl, | 148 | .unlocked_ioctl = booke_wdt_ioctl, |
148 | .open = booke_wdt_open, | 149 | .open = booke_wdt_open, |
149 | }; | 150 | }; |
150 | 151 | ||
@@ -175,8 +176,9 @@ static int __init booke_wdt_init(void) | |||
175 | 176 | ||
176 | spin_lock(&booke_wdt_lock); | 177 | spin_lock(&booke_wdt_lock); |
177 | if (booke_wdt_enabled == 1) { | 178 | if (booke_wdt_enabled == 1) { |
178 | printk(KERN_INFO "PowerPC Book-E Watchdog Timer Enabled " | 179 | printk(KERN_INFO |
179 | "(wdt_period=%d)\n", booke_wdt_period); | 180 | "PowerPC Book-E Watchdog Timer Enabled (wdt_period=%d)\n", |
181 | booke_wdt_period); | ||
180 | on_each_cpu(__booke_wdt_enable, NULL, 0); | 182 | on_each_cpu(__booke_wdt_enable, NULL, 0); |
181 | } | 183 | } |
182 | spin_unlock(&booke_wdt_lock); | 184 | spin_unlock(&booke_wdt_lock); |
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c index df72f90123df..71f6d7eec9a8 100644 --- a/drivers/watchdog/cpu5wdt.c +++ b/drivers/watchdog/cpu5wdt.c | |||
@@ -30,16 +30,16 @@ | |||
30 | #include <linux/timer.h> | 30 | #include <linux/timer.h> |
31 | #include <linux/completion.h> | 31 | #include <linux/completion.h> |
32 | #include <linux/jiffies.h> | 32 | #include <linux/jiffies.h> |
33 | #include <asm/io.h> | 33 | #include <linux/io.h> |
34 | #include <asm/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | |||
36 | #include <linux/watchdog.h> | 35 | #include <linux/watchdog.h> |
37 | 36 | ||
38 | /* adjustable parameters */ | 37 | /* adjustable parameters */ |
39 | 38 | ||
40 | static int verbose = 0; | 39 | static int verbose; |
41 | static int port = 0x91; | 40 | static int port = 0x91; |
42 | static int ticks = 10000; | 41 | static int ticks = 10000; |
42 | static spinlock_t cpu5wdt_lock; | ||
43 | 43 | ||
44 | #define PFX "cpu5wdt: " | 44 | #define PFX "cpu5wdt: " |
45 | 45 | ||
@@ -70,12 +70,13 @@ static struct { | |||
70 | 70 | ||
71 | static void cpu5wdt_trigger(unsigned long unused) | 71 | static void cpu5wdt_trigger(unsigned long unused) |
72 | { | 72 | { |
73 | if ( verbose > 2 ) | 73 | if (verbose > 2) |
74 | printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks); | 74 | printk(KERN_DEBUG PFX "trigger at %i ticks\n", ticks); |
75 | 75 | ||
76 | if( cpu5wdt_device.running ) | 76 | if (cpu5wdt_device.running) |
77 | ticks--; | 77 | ticks--; |
78 | 78 | ||
79 | spin_lock(&cpu5wdt_lock); | ||
79 | /* keep watchdog alive */ | 80 | /* keep watchdog alive */ |
80 | outb(1, port + CPU5WDT_TRIGGER_REG); | 81 | outb(1, port + CPU5WDT_TRIGGER_REG); |
81 | 82 | ||
@@ -86,6 +87,7 @@ static void cpu5wdt_trigger(unsigned long unused) | |||
86 | /* ticks doesn't matter anyway */ | 87 | /* ticks doesn't matter anyway */ |
87 | complete(&cpu5wdt_device.stop); | 88 | complete(&cpu5wdt_device.stop); |
88 | } | 89 | } |
90 | spin_unlock(&cpu5wdt_lock); | ||
89 | 91 | ||
90 | } | 92 | } |
91 | 93 | ||
@@ -93,14 +95,17 @@ static void cpu5wdt_reset(void) | |||
93 | { | 95 | { |
94 | ticks = cpu5wdt_device.default_ticks; | 96 | ticks = cpu5wdt_device.default_ticks; |
95 | 97 | ||
96 | if ( verbose ) | 98 | if (verbose) |
97 | printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks); | 99 | printk(KERN_DEBUG PFX "reset (%i ticks)\n", (int) ticks); |
98 | 100 | ||
99 | } | 101 | } |
100 | 102 | ||
101 | static void cpu5wdt_start(void) | 103 | static void cpu5wdt_start(void) |
102 | { | 104 | { |
103 | if ( !cpu5wdt_device.queue ) { | 105 | unsigned long flags; |
106 | |||
107 | spin_lock_irqsave(&cpu5wdt_lock, flags); | ||
108 | if (!cpu5wdt_device.queue) { | ||
104 | cpu5wdt_device.queue = 1; | 109 | cpu5wdt_device.queue = 1; |
105 | outb(0, port + CPU5WDT_TIME_A_REG); | 110 | outb(0, port + CPU5WDT_TIME_A_REG); |
106 | outb(0, port + CPU5WDT_TIME_B_REG); | 111 | outb(0, port + CPU5WDT_TIME_B_REG); |
@@ -111,18 +116,20 @@ static void cpu5wdt_start(void) | |||
111 | } | 116 | } |
112 | /* if process dies, counter is not decremented */ | 117 | /* if process dies, counter is not decremented */ |
113 | cpu5wdt_device.running++; | 118 | cpu5wdt_device.running++; |
119 | spin_unlock_irqrestore(&cpu5wdt_lock, flags); | ||
114 | } | 120 | } |
115 | 121 | ||
116 | static int cpu5wdt_stop(void) | 122 | static int cpu5wdt_stop(void) |
117 | { | 123 | { |
118 | if ( cpu5wdt_device.running ) | 124 | unsigned long flags; |
119 | cpu5wdt_device.running = 0; | ||
120 | 125 | ||
126 | spin_lock_irqsave(&cpu5wdt_lock, flags); | ||
127 | if (cpu5wdt_device.running) | ||
128 | cpu5wdt_device.running = 0; | ||
121 | ticks = cpu5wdt_device.default_ticks; | 129 | ticks = cpu5wdt_device.default_ticks; |
122 | 130 | spin_unlock_irqrestore(&cpu5wdt_lock, flags); | |
123 | if ( verbose ) | 131 | if (verbose) |
124 | printk(KERN_CRIT PFX "stop not possible\n"); | 132 | printk(KERN_CRIT PFX "stop not possible\n"); |
125 | |||
126 | return -EIO; | 133 | return -EIO; |
127 | } | 134 | } |
128 | 135 | ||
@@ -130,9 +137,8 @@ static int cpu5wdt_stop(void) | |||
130 | 137 | ||
131 | static int cpu5wdt_open(struct inode *inode, struct file *file) | 138 | static int cpu5wdt_open(struct inode *inode, struct file *file) |
132 | { | 139 | { |
133 | if ( test_and_set_bit(0, &cpu5wdt_device.inuse) ) | 140 | if (test_and_set_bit(0, &cpu5wdt_device.inuse)) |
134 | return -EBUSY; | 141 | return -EBUSY; |
135 | |||
136 | return nonseekable_open(inode, file); | 142 | return nonseekable_open(inode, file); |
137 | } | 143 | } |
138 | 144 | ||
@@ -142,67 +148,58 @@ static int cpu5wdt_release(struct inode *inode, struct file *file) | |||
142 | return 0; | 148 | return 0; |
143 | } | 149 | } |
144 | 150 | ||
145 | static int cpu5wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 151 | static long cpu5wdt_ioctl(struct file *file, unsigned int cmd, |
152 | unsigned long arg) | ||
146 | { | 153 | { |
147 | void __user *argp = (void __user *)arg; | 154 | void __user *argp = (void __user *)arg; |
155 | int __user *p = argp; | ||
148 | unsigned int value; | 156 | unsigned int value; |
149 | static struct watchdog_info ident = | 157 | static struct watchdog_info ident = { |
150 | { | ||
151 | .options = WDIOF_CARDRESET, | 158 | .options = WDIOF_CARDRESET, |
152 | .identity = "CPU5 WDT", | 159 | .identity = "CPU5 WDT", |
153 | }; | 160 | }; |
154 | 161 | ||
155 | switch(cmd) { | 162 | switch (cmd) { |
156 | case WDIOC_KEEPALIVE: | 163 | case WDIOC_GETSUPPORT: |
157 | cpu5wdt_reset(); | 164 | if (copy_to_user(argp, &ident, sizeof(ident))) |
158 | break; | 165 | return -EFAULT; |
159 | case WDIOC_GETSTATUS: | 166 | break; |
160 | value = inb(port + CPU5WDT_STATUS_REG); | 167 | case WDIOC_GETSTATUS: |
161 | value = (value >> 2) & 1; | 168 | value = inb(port + CPU5WDT_STATUS_REG); |
162 | if ( copy_to_user(argp, &value, sizeof(int)) ) | 169 | value = (value >> 2) & 1; |
163 | return -EFAULT; | 170 | return put_user(value, p); |
164 | break; | 171 | case WDIOC_GETBOOTSTATUS: |
165 | case WDIOC_GETBOOTSTATUS: | 172 | return put_user(0, p); |
166 | if ( copy_to_user(argp, &value, sizeof(int)) ) | 173 | case WDIOC_SETOPTIONS: |
167 | return -EFAULT; | 174 | if (get_user(value, p)) |
168 | break; | 175 | return -EFAULT; |
169 | case WDIOC_GETSUPPORT: | 176 | if (value & WDIOS_ENABLECARD) |
170 | if ( copy_to_user(argp, &ident, sizeof(ident)) ) | 177 | cpu5wdt_start(); |
171 | return -EFAULT; | 178 | if (value & WDIOS_DISABLECARD) |
172 | break; | 179 | cpu5wdt_stop(); |
173 | case WDIOC_SETOPTIONS: | 180 | break; |
174 | if ( copy_from_user(&value, argp, sizeof(int)) ) | 181 | case WDIOC_KEEPALIVE: |
175 | return -EFAULT; | 182 | cpu5wdt_reset(); |
176 | switch(value) { | 183 | break; |
177 | case WDIOS_ENABLECARD: | 184 | default: |
178 | cpu5wdt_start(); | 185 | return -ENOTTY; |
179 | break; | ||
180 | case WDIOS_DISABLECARD: | ||
181 | return cpu5wdt_stop(); | ||
182 | default: | ||
183 | return -EINVAL; | ||
184 | } | ||
185 | break; | ||
186 | default: | ||
187 | return -ENOTTY; | ||
188 | } | 186 | } |
189 | return 0; | 187 | return 0; |
190 | } | 188 | } |
191 | 189 | ||
192 | static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 190 | static ssize_t cpu5wdt_write(struct file *file, const char __user *buf, |
191 | size_t count, loff_t *ppos) | ||
193 | { | 192 | { |
194 | if ( !count ) | 193 | if (!count) |
195 | return -EIO; | 194 | return -EIO; |
196 | |||
197 | cpu5wdt_reset(); | 195 | cpu5wdt_reset(); |
198 | |||
199 | return count; | 196 | return count; |
200 | } | 197 | } |
201 | 198 | ||
202 | static const struct file_operations cpu5wdt_fops = { | 199 | static const struct file_operations cpu5wdt_fops = { |
203 | .owner = THIS_MODULE, | 200 | .owner = THIS_MODULE, |
204 | .llseek = no_llseek, | 201 | .llseek = no_llseek, |
205 | .ioctl = cpu5wdt_ioctl, | 202 | .unlocked_ioctl = cpu5wdt_ioctl, |
206 | .open = cpu5wdt_open, | 203 | .open = cpu5wdt_open, |
207 | .write = cpu5wdt_write, | 204 | .write = cpu5wdt_write, |
208 | .release = cpu5wdt_release, | 205 | .release = cpu5wdt_release, |
@@ -221,37 +218,36 @@ static int __devinit cpu5wdt_init(void) | |||
221 | unsigned int val; | 218 | unsigned int val; |
222 | int err; | 219 | int err; |
223 | 220 | ||
224 | if ( verbose ) | 221 | if (verbose) |
225 | printk(KERN_DEBUG PFX "port=0x%x, verbose=%i\n", port, verbose); | 222 | printk(KERN_DEBUG PFX |
223 | "port=0x%x, verbose=%i\n", port, verbose); | ||
226 | 224 | ||
227 | if ( !request_region(port, CPU5WDT_EXTENT, PFX) ) { | 225 | init_completion(&cpu5wdt_device.stop); |
226 | spin_lock_init(&cpu5wdt_lock); | ||
227 | cpu5wdt_device.queue = 0; | ||
228 | setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0); | ||
229 | cpu5wdt_device.default_ticks = ticks; | ||
230 | |||
231 | if (!request_region(port, CPU5WDT_EXTENT, PFX)) { | ||
228 | printk(KERN_ERR PFX "request_region failed\n"); | 232 | printk(KERN_ERR PFX "request_region failed\n"); |
229 | err = -EBUSY; | 233 | err = -EBUSY; |
230 | goto no_port; | 234 | goto no_port; |
231 | } | 235 | } |
232 | 236 | ||
233 | if ( (err = misc_register(&cpu5wdt_misc)) < 0 ) { | ||
234 | printk(KERN_ERR PFX "misc_register failed\n"); | ||
235 | goto no_misc; | ||
236 | } | ||
237 | |||
238 | /* watchdog reboot? */ | 237 | /* watchdog reboot? */ |
239 | val = inb(port + CPU5WDT_STATUS_REG); | 238 | val = inb(port + CPU5WDT_STATUS_REG); |
240 | val = (val >> 2) & 1; | 239 | val = (val >> 2) & 1; |
241 | if ( !val ) | 240 | if (!val) |
242 | printk(KERN_INFO PFX "sorry, was my fault\n"); | 241 | printk(KERN_INFO PFX "sorry, was my fault\n"); |
243 | 242 | ||
244 | init_completion(&cpu5wdt_device.stop); | 243 | err = misc_register(&cpu5wdt_misc); |
245 | cpu5wdt_device.queue = 0; | 244 | if (err < 0) { |
246 | 245 | printk(KERN_ERR PFX "misc_register failed\n"); | |
247 | clear_bit(0, &cpu5wdt_device.inuse); | 246 | goto no_misc; |
248 | 247 | } | |
249 | setup_timer(&cpu5wdt_device.timer, cpu5wdt_trigger, 0); | ||
250 | 248 | ||
251 | cpu5wdt_device.default_ticks = ticks; | ||
252 | 249 | ||
253 | printk(KERN_INFO PFX "init success\n"); | 250 | printk(KERN_INFO PFX "init success\n"); |
254 | |||
255 | return 0; | 251 | return 0; |
256 | 252 | ||
257 | no_misc: | 253 | no_misc: |
@@ -267,7 +263,7 @@ static int __devinit cpu5wdt_init_module(void) | |||
267 | 263 | ||
268 | static void __devexit cpu5wdt_exit(void) | 264 | static void __devexit cpu5wdt_exit(void) |
269 | { | 265 | { |
270 | if ( cpu5wdt_device.queue ) { | 266 | if (cpu5wdt_device.queue) { |
271 | cpu5wdt_device.queue = 0; | 267 | cpu5wdt_device.queue = 0; |
272 | wait_for_completion(&cpu5wdt_device.stop); | 268 | wait_for_completion(&cpu5wdt_device.stop); |
273 | } | 269 | } |
diff --git a/drivers/watchdog/davinci_wdt.c b/drivers/watchdog/davinci_wdt.c index 003dffe5cb19..2e1360286732 100644 --- a/drivers/watchdog/davinci_wdt.c +++ b/drivers/watchdog/davinci_wdt.c | |||
@@ -22,10 +22,9 @@ | |||
22 | #include <linux/bitops.h> | 22 | #include <linux/bitops.h> |
23 | #include <linux/platform_device.h> | 23 | #include <linux/platform_device.h> |
24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
25 | 25 | #include <linux/uaccess.h> | |
26 | #include <linux/io.h> | ||
26 | #include <mach/hardware.h> | 27 | #include <mach/hardware.h> |
27 | #include <asm/uaccess.h> | ||
28 | #include <asm/io.h> | ||
29 | 28 | ||
30 | #define MODULE_NAME "DAVINCI-WDT: " | 29 | #define MODULE_NAME "DAVINCI-WDT: " |
31 | 30 | ||
@@ -143,9 +142,8 @@ static struct watchdog_info ident = { | |||
143 | .identity = "DaVinci Watchdog", | 142 | .identity = "DaVinci Watchdog", |
144 | }; | 143 | }; |
145 | 144 | ||
146 | static int | 145 | static long davinci_wdt_ioctl(struct file *file, |
147 | davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 146 | unsigned int cmd, unsigned long arg) |
148 | unsigned long arg) | ||
149 | { | 147 | { |
150 | int ret = -ENOTTY; | 148 | int ret = -ENOTTY; |
151 | 149 | ||
@@ -160,14 +158,14 @@ davinci_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
160 | ret = put_user(0, (int *)arg); | 158 | ret = put_user(0, (int *)arg); |
161 | break; | 159 | break; |
162 | 160 | ||
163 | case WDIOC_GETTIMEOUT: | ||
164 | ret = put_user(heartbeat, (int *)arg); | ||
165 | break; | ||
166 | |||
167 | case WDIOC_KEEPALIVE: | 161 | case WDIOC_KEEPALIVE: |
168 | wdt_service(); | 162 | wdt_service(); |
169 | ret = 0; | 163 | ret = 0; |
170 | break; | 164 | break; |
165 | |||
166 | case WDIOC_GETTIMEOUT: | ||
167 | ret = put_user(heartbeat, (int *)arg); | ||
168 | break; | ||
171 | } | 169 | } |
172 | return ret; | 170 | return ret; |
173 | } | 171 | } |
@@ -184,7 +182,7 @@ static const struct file_operations davinci_wdt_fops = { | |||
184 | .owner = THIS_MODULE, | 182 | .owner = THIS_MODULE, |
185 | .llseek = no_llseek, | 183 | .llseek = no_llseek, |
186 | .write = davinci_wdt_write, | 184 | .write = davinci_wdt_write, |
187 | .ioctl = davinci_wdt_ioctl, | 185 | .unlocked_ioctl = davinci_wdt_ioctl, |
188 | .open = davinci_wdt_open, | 186 | .open = davinci_wdt_open, |
189 | .release = davinci_wdt_release, | 187 | .release = davinci_wdt_release, |
190 | }; | 188 | }; |
diff --git a/drivers/watchdog/ep93xx_wdt.c b/drivers/watchdog/ep93xx_wdt.c index af8ef14c0e4c..e9f950ff86ea 100644 --- a/drivers/watchdog/ep93xx_wdt.c +++ b/drivers/watchdog/ep93xx_wdt.c | |||
@@ -28,9 +28,8 @@ | |||
28 | #include <linux/miscdevice.h> | 28 | #include <linux/miscdevice.h> |
29 | #include <linux/watchdog.h> | 29 | #include <linux/watchdog.h> |
30 | #include <linux/timer.h> | 30 | #include <linux/timer.h> |
31 | 31 | #include <linux/uaccess.h> | |
32 | #include <mach/hardware.h> | 32 | #include <mach/hardware.h> |
33 | #include <asm/uaccess.h> | ||
34 | 33 | ||
35 | #define WDT_VERSION "0.3" | 34 | #define WDT_VERSION "0.3" |
36 | #define PFX "ep93xx_wdt: " | 35 | #define PFX "ep93xx_wdt: " |
@@ -136,9 +135,8 @@ static struct watchdog_info ident = { | |||
136 | .identity = "EP93xx Watchdog", | 135 | .identity = "EP93xx Watchdog", |
137 | }; | 136 | }; |
138 | 137 | ||
139 | static int | 138 | static long ep93xx_wdt_ioctl(struct file *file, |
140 | ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 139 | unsigned int cmd, unsigned long arg) |
141 | unsigned long arg) | ||
142 | { | 140 | { |
143 | int ret = -ENOTTY; | 141 | int ret = -ENOTTY; |
144 | 142 | ||
@@ -156,15 +154,15 @@ ep93xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
156 | ret = put_user(boot_status, (int __user *)arg); | 154 | ret = put_user(boot_status, (int __user *)arg); |
157 | break; | 155 | break; |
158 | 156 | ||
159 | case WDIOC_GETTIMEOUT: | ||
160 | /* actually, it is 0.250 seconds.... */ | ||
161 | ret = put_user(1, (int __user *)arg); | ||
162 | break; | ||
163 | |||
164 | case WDIOC_KEEPALIVE: | 157 | case WDIOC_KEEPALIVE: |
165 | wdt_keepalive(); | 158 | wdt_keepalive(); |
166 | ret = 0; | 159 | ret = 0; |
167 | break; | 160 | break; |
161 | |||
162 | case WDIOC_GETTIMEOUT: | ||
163 | /* actually, it is 0.250 seconds.... */ | ||
164 | ret = put_user(1, (int __user *)arg); | ||
165 | break; | ||
168 | } | 166 | } |
169 | return ret; | 167 | return ret; |
170 | } | 168 | } |
@@ -174,8 +172,8 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file) | |||
174 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | 172 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) |
175 | wdt_shutdown(); | 173 | wdt_shutdown(); |
176 | else | 174 | else |
177 | printk(KERN_CRIT PFX "Device closed unexpectedly - " | 175 | printk(KERN_CRIT PFX |
178 | "timer will not stop\n"); | 176 | "Device closed unexpectedly - timer will not stop\n"); |
179 | 177 | ||
180 | clear_bit(WDT_IN_USE, &wdt_status); | 178 | clear_bit(WDT_IN_USE, &wdt_status); |
181 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 179 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
@@ -186,7 +184,7 @@ static int ep93xx_wdt_release(struct inode *inode, struct file *file) | |||
186 | static const struct file_operations ep93xx_wdt_fops = { | 184 | static const struct file_operations ep93xx_wdt_fops = { |
187 | .owner = THIS_MODULE, | 185 | .owner = THIS_MODULE, |
188 | .write = ep93xx_wdt_write, | 186 | .write = ep93xx_wdt_write, |
189 | .ioctl = ep93xx_wdt_ioctl, | 187 | .unlocked_ioctl = ep93xx_wdt_ioctl, |
190 | .open = ep93xx_wdt_open, | 188 | .open = ep93xx_wdt_open, |
191 | .release = ep93xx_wdt_release, | 189 | .release = ep93xx_wdt_release, |
192 | }; | 190 | }; |
@@ -243,7 +241,9 @@ module_param(nowayout, int, 0); | |||
243 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | 241 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); |
244 | 242 | ||
245 | module_param(timeout, int, 0); | 243 | module_param(timeout, int, 0); |
246 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 244 | MODULE_PARM_DESC(timeout, |
245 | "Watchdog timeout in seconds. (1<=timeout<=3600, default=" | ||
246 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
247 | 247 | ||
248 | MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>," | 248 | MODULE_AUTHOR("Ray Lehtiniemi <rayl@mail.com>," |
249 | "Alessandro Zummo <a.zummo@towertech.it>"); | 249 | "Alessandro Zummo <a.zummo@towertech.it>"); |
diff --git a/drivers/watchdog/eurotechwdt.c b/drivers/watchdog/eurotechwdt.c index b14e9d1f164d..bbd14e34319f 100644 --- a/drivers/watchdog/eurotechwdt.c +++ b/drivers/watchdog/eurotechwdt.c | |||
@@ -56,14 +56,15 @@ | |||
56 | #include <linux/notifier.h> | 56 | #include <linux/notifier.h> |
57 | #include <linux/reboot.h> | 57 | #include <linux/reboot.h> |
58 | #include <linux/init.h> | 58 | #include <linux/init.h> |
59 | #include <linux/io.h> | ||
60 | #include <linux/uaccess.h> | ||
59 | 61 | ||
60 | #include <asm/io.h> | ||
61 | #include <asm/uaccess.h> | ||
62 | #include <asm/system.h> | 62 | #include <asm/system.h> |
63 | 63 | ||
64 | static unsigned long eurwdt_is_open; | 64 | static unsigned long eurwdt_is_open; |
65 | static int eurwdt_timeout; | 65 | static int eurwdt_timeout; |
66 | static char eur_expect_close; | 66 | static char eur_expect_close; |
67 | static spinlock_t eurwdt_lock; | ||
67 | 68 | ||
68 | /* | 69 | /* |
69 | * You must set these - there is no sane way to probe for this board. | 70 | * You must set these - there is no sane way to probe for this board. |
@@ -78,7 +79,9 @@ static char *ev = "int"; | |||
78 | 79 | ||
79 | static int nowayout = WATCHDOG_NOWAYOUT; | 80 | static int nowayout = WATCHDOG_NOWAYOUT; |
80 | module_param(nowayout, int, 0); | 81 | module_param(nowayout, int, 0); |
81 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 82 | MODULE_PARM_DESC(nowayout, |
83 | "Watchdog cannot be stopped once started (default=" | ||
84 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
82 | 85 | ||
83 | /* | 86 | /* |
84 | * Some symbolic names | 87 | * Some symbolic names |
@@ -137,7 +140,8 @@ static void eurwdt_activate_timer(void) | |||
137 | { | 140 | { |
138 | eurwdt_disable_timer(); | 141 | eurwdt_disable_timer(); |
139 | eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ | 142 | eurwdt_write_reg(WDT_CTRL_REG, 0x01); /* activate the WDT */ |
140 | eurwdt_write_reg(WDT_OUTPIN_CFG, !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT); | 143 | eurwdt_write_reg(WDT_OUTPIN_CFG, |
144 | !strcmp("int", ev) ? WDT_EVENT_INT : WDT_EVENT_REBOOT); | ||
141 | 145 | ||
142 | /* Setting interrupt line */ | 146 | /* Setting interrupt line */ |
143 | if (irq == 2 || irq > 15 || irq < 0) { | 147 | if (irq == 2 || irq > 15 || irq < 0) { |
@@ -206,21 +210,21 @@ size_t count, loff_t *ppos) | |||
206 | 210 | ||
207 | for (i = 0; i != count; i++) { | 211 | for (i = 0; i != count; i++) { |
208 | char c; | 212 | char c; |
209 | if(get_user(c, buf+i)) | 213 | if (get_user(c, buf + i)) |
210 | return -EFAULT; | 214 | return -EFAULT; |
211 | if (c == 'V') | 215 | if (c == 'V') |
212 | eur_expect_close = 42; | 216 | eur_expect_close = 42; |
213 | } | 217 | } |
214 | } | 218 | } |
219 | spin_lock(&eurwdt_lock); | ||
215 | eurwdt_ping(); /* the default timeout */ | 220 | eurwdt_ping(); /* the default timeout */ |
221 | spin_unlock(&eurwdt_lock); | ||
216 | } | 222 | } |
217 | |||
218 | return count; | 223 | return count; |
219 | } | 224 | } |
220 | 225 | ||
221 | /** | 226 | /** |
222 | * eurwdt_ioctl: | 227 | * eurwdt_ioctl: |
223 | * @inode: inode of the device | ||
224 | * @file: file handle to the device | 228 | * @file: file handle to the device |
225 | * @cmd: watchdog command | 229 | * @cmd: watchdog command |
226 | * @arg: argument pointer | 230 | * @arg: argument pointer |
@@ -229,13 +233,14 @@ size_t count, loff_t *ppos) | |||
229 | * according to their available features. | 233 | * according to their available features. |
230 | */ | 234 | */ |
231 | 235 | ||
232 | static int eurwdt_ioctl(struct inode *inode, struct file *file, | 236 | static long eurwdt_ioctl(struct file *file, |
233 | unsigned int cmd, unsigned long arg) | 237 | unsigned int cmd, unsigned long arg) |
234 | { | 238 | { |
235 | void __user *argp = (void __user *)arg; | 239 | void __user *argp = (void __user *)arg; |
236 | int __user *p = argp; | 240 | int __user *p = argp; |
237 | static struct watchdog_info ident = { | 241 | static struct watchdog_info ident = { |
238 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
243 | | WDIOF_MAGICCLOSE, | ||
239 | .firmware_version = 1, | 244 | .firmware_version = 1, |
240 | .identity = "WDT Eurotech CPU-1220/1410", | 245 | .identity = "WDT Eurotech CPU-1220/1410", |
241 | }; | 246 | }; |
@@ -243,10 +248,7 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
243 | int time; | 248 | int time; |
244 | int options, retval = -EINVAL; | 249 | int options, retval = -EINVAL; |
245 | 250 | ||
246 | switch(cmd) { | 251 | switch (cmd) { |
247 | default: | ||
248 | return -ENOTTY; | ||
249 | |||
250 | case WDIOC_GETSUPPORT: | 252 | case WDIOC_GETSUPPORT: |
251 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | 253 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
252 | 254 | ||
@@ -254,8 +256,26 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
254 | case WDIOC_GETBOOTSTATUS: | 256 | case WDIOC_GETBOOTSTATUS: |
255 | return put_user(0, p); | 257 | return put_user(0, p); |
256 | 258 | ||
259 | case WDIOC_SETOPTIONS: | ||
260 | if (get_user(options, p)) | ||
261 | return -EFAULT; | ||
262 | spin_lock(&eurwdt_lock); | ||
263 | if (options & WDIOS_DISABLECARD) { | ||
264 | eurwdt_disable_timer(); | ||
265 | retval = 0; | ||
266 | } | ||
267 | if (options & WDIOS_ENABLECARD) { | ||
268 | eurwdt_activate_timer(); | ||
269 | eurwdt_ping(); | ||
270 | retval = 0; | ||
271 | } | ||
272 | spin_unlock(&eurwdt_lock); | ||
273 | return retval; | ||
274 | |||
257 | case WDIOC_KEEPALIVE: | 275 | case WDIOC_KEEPALIVE: |
276 | spin_lock(&eurwdt_lock); | ||
258 | eurwdt_ping(); | 277 | eurwdt_ping(); |
278 | spin_unlock(&eurwdt_lock); | ||
259 | return 0; | 279 | return 0; |
260 | 280 | ||
261 | case WDIOC_SETTIMEOUT: | 281 | case WDIOC_SETTIMEOUT: |
@@ -266,26 +286,17 @@ static int eurwdt_ioctl(struct inode *inode, struct file *file, | |||
266 | if (time < 0 || time > 255) | 286 | if (time < 0 || time > 255) |
267 | return -EINVAL; | 287 | return -EINVAL; |
268 | 288 | ||
289 | spin_lock(&eurwdt_lock); | ||
269 | eurwdt_timeout = time; | 290 | eurwdt_timeout = time; |
270 | eurwdt_set_timeout(time); | 291 | eurwdt_set_timeout(time); |
292 | spin_unlock(&eurwdt_lock); | ||
271 | /* Fall */ | 293 | /* Fall */ |
272 | 294 | ||
273 | case WDIOC_GETTIMEOUT: | 295 | case WDIOC_GETTIMEOUT: |
274 | return put_user(eurwdt_timeout, p); | 296 | return put_user(eurwdt_timeout, p); |
275 | 297 | ||
276 | case WDIOC_SETOPTIONS: | 298 | default: |
277 | if (get_user(options, p)) | 299 | return -ENOTTY; |
278 | return -EFAULT; | ||
279 | if (options & WDIOS_DISABLECARD) { | ||
280 | eurwdt_disable_timer(); | ||
281 | retval = 0; | ||
282 | } | ||
283 | if (options & WDIOS_ENABLECARD) { | ||
284 | eurwdt_activate_timer(); | ||
285 | eurwdt_ping(); | ||
286 | retval = 0; | ||
287 | } | ||
288 | return retval; | ||
289 | } | 300 | } |
290 | } | 301 | } |
291 | 302 | ||
@@ -322,10 +333,11 @@ static int eurwdt_open(struct inode *inode, struct file *file) | |||
322 | 333 | ||
323 | static int eurwdt_release(struct inode *inode, struct file *file) | 334 | static int eurwdt_release(struct inode *inode, struct file *file) |
324 | { | 335 | { |
325 | if (eur_expect_close == 42) { | 336 | if (eur_expect_close == 42) |
326 | eurwdt_disable_timer(); | 337 | eurwdt_disable_timer(); |
327 | } else { | 338 | else { |
328 | printk(KERN_CRIT "eurwdt: Unexpected close, not stopping watchdog!\n"); | 339 | printk(KERN_CRIT |
340 | "eurwdt: Unexpected close, not stopping watchdog!\n"); | ||
329 | eurwdt_ping(); | 341 | eurwdt_ping(); |
330 | } | 342 | } |
331 | clear_bit(0, &eurwdt_is_open); | 343 | clear_bit(0, &eurwdt_is_open); |
@@ -348,10 +360,8 @@ static int eurwdt_release(struct inode *inode, struct file *file) | |||
348 | static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, | 360 | static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, |
349 | void *unused) | 361 | void *unused) |
350 | { | 362 | { |
351 | if (code == SYS_DOWN || code == SYS_HALT) { | 363 | if (code == SYS_DOWN || code == SYS_HALT) |
352 | /* Turn the card off */ | 364 | eurwdt_disable_timer(); /* Turn the card off */ |
353 | eurwdt_disable_timer(); | ||
354 | } | ||
355 | 365 | ||
356 | return NOTIFY_DONE; | 366 | return NOTIFY_DONE; |
357 | } | 367 | } |
@@ -362,11 +372,11 @@ static int eurwdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
362 | 372 | ||
363 | 373 | ||
364 | static const struct file_operations eurwdt_fops = { | 374 | static const struct file_operations eurwdt_fops = { |
365 | .owner = THIS_MODULE, | 375 | .owner = THIS_MODULE, |
366 | .llseek = no_llseek, | 376 | .llseek = no_llseek, |
367 | .write = eurwdt_write, | 377 | .write = eurwdt_write, |
368 | .ioctl = eurwdt_ioctl, | 378 | .unlocked_ioctl = eurwdt_ioctl, |
369 | .open = eurwdt_open, | 379 | .open = eurwdt_open, |
370 | .release = eurwdt_release, | 380 | .release = eurwdt_release, |
371 | }; | 381 | }; |
372 | 382 | ||
@@ -419,7 +429,7 @@ static int __init eurwdt_init(void) | |||
419 | int ret; | 429 | int ret; |
420 | 430 | ||
421 | ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); | 431 | ret = request_irq(irq, eurwdt_interrupt, IRQF_DISABLED, "eurwdt", NULL); |
422 | if(ret) { | 432 | if (ret) { |
423 | printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); | 433 | printk(KERN_ERR "eurwdt: IRQ %d is not free.\n", irq); |
424 | goto out; | 434 | goto out; |
425 | } | 435 | } |
@@ -432,10 +442,13 @@ static int __init eurwdt_init(void) | |||
432 | 442 | ||
433 | ret = register_reboot_notifier(&eurwdt_notifier); | 443 | ret = register_reboot_notifier(&eurwdt_notifier); |
434 | if (ret) { | 444 | if (ret) { |
435 | printk(KERN_ERR "eurwdt: can't register reboot notifier (err=%d)\n", ret); | 445 | printk(KERN_ERR |
446 | "eurwdt: can't register reboot notifier (err=%d)\n", ret); | ||
436 | goto outreg; | 447 | goto outreg; |
437 | } | 448 | } |
438 | 449 | ||
450 | spin_lock_init(&eurwdt_lock); | ||
451 | |||
439 | ret = misc_register(&eurwdt_miscdev); | 452 | ret = misc_register(&eurwdt_miscdev); |
440 | if (ret) { | 453 | if (ret) { |
441 | printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", | 454 | printk(KERN_ERR "eurwdt: can't misc_register on minor=%d\n", |
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c index 30d09cbbad94..614a5c7017b6 100644 --- a/drivers/watchdog/geodewdt.c +++ b/drivers/watchdog/geodewdt.c | |||
@@ -17,8 +17,8 @@ | |||
17 | #include <linux/fs.h> | 17 | #include <linux/fs.h> |
18 | #include <linux/platform_device.h> | 18 | #include <linux/platform_device.h> |
19 | #include <linux/reboot.h> | 19 | #include <linux/reboot.h> |
20 | #include <linux/uaccess.h> | ||
20 | 21 | ||
21 | #include <asm/uaccess.h> | ||
22 | #include <asm/geode.h> | 22 | #include <asm/geode.h> |
23 | 23 | ||
24 | #define GEODEWDT_HZ 500 | 24 | #define GEODEWDT_HZ 500 |
@@ -77,27 +77,24 @@ static int geodewdt_set_heartbeat(int val) | |||
77 | return 0; | 77 | return 0; |
78 | } | 78 | } |
79 | 79 | ||
80 | static int | 80 | static int geodewdt_open(struct inode *inode, struct file *file) |
81 | geodewdt_open(struct inode *inode, struct file *file) | ||
82 | { | 81 | { |
83 | if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) | 82 | if (test_and_set_bit(WDT_FLAGS_OPEN, &wdt_flags)) |
84 | return -EBUSY; | 83 | return -EBUSY; |
85 | 84 | ||
86 | if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) | 85 | if (!test_and_clear_bit(WDT_FLAGS_ORPHAN, &wdt_flags)) |
87 | __module_get(THIS_MODULE); | 86 | __module_get(THIS_MODULE); |
88 | 87 | ||
89 | geodewdt_ping(); | 88 | geodewdt_ping(); |
90 | return nonseekable_open(inode, file); | 89 | return nonseekable_open(inode, file); |
91 | } | 90 | } |
92 | 91 | ||
93 | static int | 92 | static int geodewdt_release(struct inode *inode, struct file *file) |
94 | geodewdt_release(struct inode *inode, struct file *file) | ||
95 | { | 93 | { |
96 | if (safe_close) { | 94 | if (safe_close) { |
97 | geodewdt_disable(); | 95 | geodewdt_disable(); |
98 | module_put(THIS_MODULE); | 96 | module_put(THIS_MODULE); |
99 | } | 97 | } else { |
100 | else { | ||
101 | printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n"); | 98 | printk(KERN_CRIT "Unexpected close - watchdog is not stopping.\n"); |
102 | geodewdt_ping(); | 99 | geodewdt_ping(); |
103 | 100 | ||
@@ -109,11 +106,10 @@ geodewdt_release(struct inode *inode, struct file *file) | |||
109 | return 0; | 106 | return 0; |
110 | } | 107 | } |
111 | 108 | ||
112 | static ssize_t | 109 | static ssize_t geodewdt_write(struct file *file, const char __user *data, |
113 | geodewdt_write(struct file *file, const char __user *data, size_t len, | 110 | size_t len, loff_t *ppos) |
114 | loff_t *ppos) | ||
115 | { | 111 | { |
116 | if(len) { | 112 | if (len) { |
117 | if (!nowayout) { | 113 | if (!nowayout) { |
118 | size_t i; | 114 | size_t i; |
119 | safe_close = 0; | 115 | safe_close = 0; |
@@ -134,9 +130,8 @@ geodewdt_write(struct file *file, const char __user *data, size_t len, | |||
134 | return len; | 130 | return len; |
135 | } | 131 | } |
136 | 132 | ||
137 | static int | 133 | static int geodewdt_ioctl(struct inode *inode, struct file *file, |
138 | geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 134 | unsigned int cmd, unsigned long arg) |
139 | unsigned long arg) | ||
140 | { | 135 | { |
141 | void __user *argp = (void __user *)arg; | 136 | void __user *argp = (void __user *)arg; |
142 | int __user *p = argp; | 137 | int __user *p = argp; |
@@ -147,9 +142,9 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
147 | | WDIOF_MAGICCLOSE, | 142 | | WDIOF_MAGICCLOSE, |
148 | .firmware_version = 1, | 143 | .firmware_version = 1, |
149 | .identity = WATCHDOG_NAME, | 144 | .identity = WATCHDOG_NAME, |
150 | }; | 145 | }; |
151 | 146 | ||
152 | switch(cmd) { | 147 | switch (cmd) { |
153 | case WDIOC_GETSUPPORT: | 148 | case WDIOC_GETSUPPORT: |
154 | return copy_to_user(argp, &ident, | 149 | return copy_to_user(argp, &ident, |
155 | sizeof(ident)) ? -EFAULT : 0; | 150 | sizeof(ident)) ? -EFAULT : 0; |
@@ -159,22 +154,6 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
159 | case WDIOC_GETBOOTSTATUS: | 154 | case WDIOC_GETBOOTSTATUS: |
160 | return put_user(0, p); | 155 | return put_user(0, p); |
161 | 156 | ||
162 | case WDIOC_KEEPALIVE: | ||
163 | geodewdt_ping(); | ||
164 | return 0; | ||
165 | |||
166 | case WDIOC_SETTIMEOUT: | ||
167 | if (get_user(interval, p)) | ||
168 | return -EFAULT; | ||
169 | |||
170 | if (geodewdt_set_heartbeat(interval)) | ||
171 | return -EINVAL; | ||
172 | |||
173 | /* Fall through */ | ||
174 | |||
175 | case WDIOC_GETTIMEOUT: | ||
176 | return put_user(timeout, p); | ||
177 | |||
178 | case WDIOC_SETOPTIONS: | 157 | case WDIOC_SETOPTIONS: |
179 | { | 158 | { |
180 | int options, ret = -EINVAL; | 159 | int options, ret = -EINVAL; |
@@ -194,6 +173,20 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
194 | 173 | ||
195 | return ret; | 174 | return ret; |
196 | } | 175 | } |
176 | case WDIOC_KEEPALIVE: | ||
177 | geodewdt_ping(); | ||
178 | return 0; | ||
179 | |||
180 | case WDIOC_SETTIMEOUT: | ||
181 | if (get_user(interval, p)) | ||
182 | return -EFAULT; | ||
183 | |||
184 | if (geodewdt_set_heartbeat(interval)) | ||
185 | return -EINVAL; | ||
186 | /* Fall through */ | ||
187 | case WDIOC_GETTIMEOUT: | ||
188 | return put_user(timeout, p); | ||
189 | |||
197 | default: | 190 | default: |
198 | return -ENOTTY; | 191 | return -ENOTTY; |
199 | } | 192 | } |
@@ -202,22 +195,21 @@ geodewdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
202 | } | 195 | } |
203 | 196 | ||
204 | static const struct file_operations geodewdt_fops = { | 197 | static const struct file_operations geodewdt_fops = { |
205 | .owner = THIS_MODULE, | 198 | .owner = THIS_MODULE, |
206 | .llseek = no_llseek, | 199 | .llseek = no_llseek, |
207 | .write = geodewdt_write, | 200 | .write = geodewdt_write, |
208 | .ioctl = geodewdt_ioctl, | 201 | .ioctl = geodewdt_ioctl, |
209 | .open = geodewdt_open, | 202 | .open = geodewdt_open, |
210 | .release = geodewdt_release, | 203 | .release = geodewdt_release, |
211 | }; | 204 | }; |
212 | 205 | ||
213 | static struct miscdevice geodewdt_miscdev = { | 206 | static struct miscdevice geodewdt_miscdev = { |
214 | .minor = WATCHDOG_MINOR, | 207 | .minor = WATCHDOG_MINOR, |
215 | .name = "watchdog", | 208 | .name = "watchdog", |
216 | .fops = &geodewdt_fops | 209 | .fops = &geodewdt_fops, |
217 | }; | 210 | }; |
218 | 211 | ||
219 | static int __devinit | 212 | static int __devinit geodewdt_probe(struct platform_device *dev) |
220 | geodewdt_probe(struct platform_device *dev) | ||
221 | { | 213 | { |
222 | int ret, timer; | 214 | int ret, timer; |
223 | 215 | ||
@@ -248,15 +240,13 @@ geodewdt_probe(struct platform_device *dev) | |||
248 | return ret; | 240 | return ret; |
249 | } | 241 | } |
250 | 242 | ||
251 | static int __devexit | 243 | static int __devexit geodewdt_remove(struct platform_device *dev) |
252 | geodewdt_remove(struct platform_device *dev) | ||
253 | { | 244 | { |
254 | misc_deregister(&geodewdt_miscdev); | 245 | misc_deregister(&geodewdt_miscdev); |
255 | return 0; | 246 | return 0; |
256 | } | 247 | } |
257 | 248 | ||
258 | static void | 249 | static void geodewdt_shutdown(struct platform_device *dev) |
259 | geodewdt_shutdown(struct platform_device *dev) | ||
260 | { | 250 | { |
261 | geodewdt_disable(); | 251 | geodewdt_disable(); |
262 | } | 252 | } |
@@ -271,8 +261,7 @@ static struct platform_driver geodewdt_driver = { | |||
271 | }, | 261 | }, |
272 | }; | 262 | }; |
273 | 263 | ||
274 | static int __init | 264 | static int __init geodewdt_init(void) |
275 | geodewdt_init(void) | ||
276 | { | 265 | { |
277 | int ret; | 266 | int ret; |
278 | 267 | ||
@@ -292,8 +281,7 @@ err: | |||
292 | return ret; | 281 | return ret; |
293 | } | 282 | } |
294 | 283 | ||
295 | static void __exit | 284 | static void __exit geodewdt_exit(void) |
296 | geodewdt_exit(void) | ||
297 | { | 285 | { |
298 | platform_device_unregister(geodewdt_platform_device); | 286 | platform_device_unregister(geodewdt_platform_device); |
299 | platform_driver_unregister(&geodewdt_driver); | 287 | platform_driver_unregister(&geodewdt_driver); |
diff --git a/drivers/watchdog/hpwdt.c b/drivers/watchdog/hpwdt.c index ccd6c530782d..d039d5f2fd1c 100644 --- a/drivers/watchdog/hpwdt.c +++ b/drivers/watchdog/hpwdt.c | |||
@@ -39,9 +39,7 @@ | |||
39 | #include <linux/string.h> | 39 | #include <linux/string.h> |
40 | #include <linux/bootmem.h> | 40 | #include <linux/bootmem.h> |
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | #include <asm/dmi.h> | ||
43 | #include <asm/desc.h> | 42 | #include <asm/desc.h> |
44 | #include <asm/kdebug.h> | ||
45 | 43 | ||
46 | #define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ | 44 | #define PCI_BIOS32_SD_VALUE 0x5F32335F /* "_32_" */ |
47 | #define CRU_BIOS_SIGNATURE_VALUE 0x55524324 | 45 | #define CRU_BIOS_SIGNATURE_VALUE 0x55524324 |
@@ -407,7 +405,7 @@ static int __devinit detect_cru_service(void) | |||
407 | dmi_walk(dmi_find_cru); | 405 | dmi_walk(dmi_find_cru); |
408 | 406 | ||
409 | /* if cru_rom_addr has been set then we found a CRU service */ | 407 | /* if cru_rom_addr has been set then we found a CRU service */ |
410 | return ((cru_rom_addr != NULL)? 0: -ENODEV); | 408 | return ((cru_rom_addr != NULL) ? 0: -ENODEV); |
411 | } | 409 | } |
412 | 410 | ||
413 | /* ------------------------------------------------------------------------- */ | 411 | /* ------------------------------------------------------------------------- */ |
@@ -535,7 +533,7 @@ static ssize_t hpwdt_write(struct file *file, const char __user *data, | |||
535 | /* scan to see whether or not we got the magic char. */ | 533 | /* scan to see whether or not we got the magic char. */ |
536 | for (i = 0; i != len; i++) { | 534 | for (i = 0; i != len; i++) { |
537 | char c; | 535 | char c; |
538 | if (get_user(c, data+i)) | 536 | if (get_user(c, data + i)) |
539 | return -EFAULT; | 537 | return -EFAULT; |
540 | if (c == 'V') | 538 | if (c == 'V') |
541 | expect_release = 42; | 539 | expect_release = 42; |
diff --git a/drivers/watchdog/i6300esb.c b/drivers/watchdog/i6300esb.c index ca44fd9b19bb..c13383f7fcb9 100644 --- a/drivers/watchdog/i6300esb.c +++ b/drivers/watchdog/i6300esb.c | |||
@@ -9,18 +9,18 @@ | |||
9 | * as published by the Free Software Foundation; either version | 9 | * as published by the Free Software Foundation; either version |
10 | * 2 of the License, or (at your option) any later version. | 10 | * 2 of the License, or (at your option) any later version. |
11 | * | 11 | * |
12 | * based on i810-tco.c which is in turn based on softdog.c | 12 | * based on i810-tco.c which is in turn based on softdog.c |
13 | * | 13 | * |
14 | * The timer is implemented in the following I/O controller hubs: | 14 | * The timer is implemented in the following I/O controller hubs: |
15 | * (See the intel documentation on http://developer.intel.com.) | 15 | * (See the intel documentation on http://developer.intel.com.) |
16 | * 6300ESB chip : document number 300641-003 | 16 | * 6300ESB chip : document number 300641-003 |
17 | * | 17 | * |
18 | * 2004YYZZ Ross Biro | 18 | * 2004YYZZ Ross Biro |
19 | * Initial version 0.01 | 19 | * Initial version 0.01 |
20 | * 2004YYZZ Ross Biro | 20 | * 2004YYZZ Ross Biro |
21 | * Version 0.02 | 21 | * Version 0.02 |
22 | * 20050210 David Härdeman <david@2gen.com> | 22 | * 20050210 David Härdeman <david@2gen.com> |
23 | * Ported driver to kernel 2.6 | 23 | * Ported driver to kernel 2.6 |
24 | */ | 24 | */ |
25 | 25 | ||
26 | /* | 26 | /* |
@@ -38,9 +38,8 @@ | |||
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/pci.h> | 39 | #include <linux/pci.h> |
40 | #include <linux/ioport.h> | 40 | #include <linux/ioport.h> |
41 | 41 | #include <linux/uaccess.h> | |
42 | #include <asm/uaccess.h> | 42 | #include <linux/io.h> |
43 | #include <asm/io.h> | ||
44 | 43 | ||
45 | /* Module and version information */ | 44 | /* Module and version information */ |
46 | #define ESB_VERSION "0.03" | 45 | #define ESB_VERSION "0.03" |
@@ -59,17 +58,17 @@ | |||
59 | #define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ | 58 | #define ESB_RELOAD_REG BASEADDR + 0x0c /* Reload register */ |
60 | 59 | ||
61 | /* Lock register bits */ | 60 | /* Lock register bits */ |
62 | #define ESB_WDT_FUNC ( 0x01 << 2 ) /* Watchdog functionality */ | 61 | #define ESB_WDT_FUNC (0x01 << 2) /* Watchdog functionality */ |
63 | #define ESB_WDT_ENABLE ( 0x01 << 1 ) /* Enable WDT */ | 62 | #define ESB_WDT_ENABLE (0x01 << 1) /* Enable WDT */ |
64 | #define ESB_WDT_LOCK ( 0x01 << 0 ) /* Lock (nowayout) */ | 63 | #define ESB_WDT_LOCK (0x01 << 0) /* Lock (nowayout) */ |
65 | 64 | ||
66 | /* Config register bits */ | 65 | /* Config register bits */ |
67 | #define ESB_WDT_REBOOT ( 0x01 << 5 ) /* Enable reboot on timeout */ | 66 | #define ESB_WDT_REBOOT (0x01 << 5) /* Enable reboot on timeout */ |
68 | #define ESB_WDT_FREQ ( 0x01 << 2 ) /* Decrement frequency */ | 67 | #define ESB_WDT_FREQ (0x01 << 2) /* Decrement frequency */ |
69 | #define ESB_WDT_INTTYPE ( 0x11 << 0 ) /* Interrupt type on timer1 timeout */ | 68 | #define ESB_WDT_INTTYPE (0x11 << 0) /* Interrupt type on timer1 timeout */ |
70 | 69 | ||
71 | /* Reload register bits */ | 70 | /* Reload register bits */ |
72 | #define ESB_WDT_RELOAD ( 0x01 << 8 ) /* prevent timeout */ | 71 | #define ESB_WDT_RELOAD (0x01 << 8) /* prevent timeout */ |
73 | 72 | ||
74 | /* Magic constants */ | 73 | /* Magic constants */ |
75 | #define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */ | 74 | #define ESB_UNLOCK1 0x80 /* Step 1 to unlock reset registers */ |
@@ -84,14 +83,20 @@ static unsigned short triggered; /* The status of the watchdog upon boot */ | |||
84 | static char esb_expect_close; | 83 | static char esb_expect_close; |
85 | 84 | ||
86 | /* module parameters */ | 85 | /* module parameters */ |
87 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat (1<heartbeat<2*1023) */ | 86 | /* 30 sec default heartbeat (1 < heartbeat < 2*1023) */ |
87 | #define WATCHDOG_HEARTBEAT 30 | ||
88 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 88 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
89 | |||
89 | module_param(heartbeat, int, 0); | 90 | module_param(heartbeat, int, 0); |
90 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 91 | MODULE_PARM_DESC(heartbeat, |
92 | "Watchdog heartbeat in seconds. (1<heartbeat<2046, default=" | ||
93 | __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | ||
91 | 94 | ||
92 | static int nowayout = WATCHDOG_NOWAYOUT; | 95 | static int nowayout = WATCHDOG_NOWAYOUT; |
93 | module_param(nowayout, int, 0); | 96 | module_param(nowayout, int, 0); |
94 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 97 | MODULE_PARM_DESC(nowayout, |
98 | "Watchdog cannot be stopped once started (default=" | ||
99 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
95 | 100 | ||
96 | /* | 101 | /* |
97 | * Some i6300ESB specific functions | 102 | * Some i6300ESB specific functions |
@@ -103,9 +108,10 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _ | |||
103 | * reload register. After this the appropriate registers can be written | 108 | * reload register. After this the appropriate registers can be written |
104 | * to once before they need to be unlocked again. | 109 | * to once before they need to be unlocked again. |
105 | */ | 110 | */ |
106 | static inline void esb_unlock_registers(void) { | 111 | static inline void esb_unlock_registers(void) |
107 | writeb(ESB_UNLOCK1, ESB_RELOAD_REG); | 112 | { |
108 | writeb(ESB_UNLOCK2, ESB_RELOAD_REG); | 113 | writeb(ESB_UNLOCK1, ESB_RELOAD_REG); |
114 | writeb(ESB_UNLOCK2, ESB_RELOAD_REG); | ||
109 | } | 115 | } |
110 | 116 | ||
111 | static void esb_timer_start(void) | 117 | static void esb_timer_start(void) |
@@ -114,8 +120,7 @@ static void esb_timer_start(void) | |||
114 | 120 | ||
115 | /* Enable or Enable + Lock? */ | 121 | /* Enable or Enable + Lock? */ |
116 | val = 0x02 | (nowayout ? 0x01 : 0x00); | 122 | val = 0x02 | (nowayout ? 0x01 : 0x00); |
117 | 123 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); | |
118 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, val); | ||
119 | } | 124 | } |
120 | 125 | ||
121 | static int esb_timer_stop(void) | 126 | static int esb_timer_stop(void) |
@@ -140,7 +145,7 @@ static void esb_timer_keepalive(void) | |||
140 | spin_lock(&esb_lock); | 145 | spin_lock(&esb_lock); |
141 | esb_unlock_registers(); | 146 | esb_unlock_registers(); |
142 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); | 147 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); |
143 | /* FIXME: Do we need to flush anything here? */ | 148 | /* FIXME: Do we need to flush anything here? */ |
144 | spin_unlock(&esb_lock); | 149 | spin_unlock(&esb_lock); |
145 | } | 150 | } |
146 | 151 | ||
@@ -165,9 +170,9 @@ static int esb_timer_set_heartbeat(int time) | |||
165 | 170 | ||
166 | /* Write timer 2 */ | 171 | /* Write timer 2 */ |
167 | esb_unlock_registers(); | 172 | esb_unlock_registers(); |
168 | writel(val, ESB_TIMER2_REG); | 173 | writel(val, ESB_TIMER2_REG); |
169 | 174 | ||
170 | /* Reload */ | 175 | /* Reload */ |
171 | esb_unlock_registers(); | 176 | esb_unlock_registers(); |
172 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); | 177 | writew(ESB_WDT_RELOAD, ESB_RELOAD_REG); |
173 | 178 | ||
@@ -179,54 +184,55 @@ static int esb_timer_set_heartbeat(int time) | |||
179 | return 0; | 184 | return 0; |
180 | } | 185 | } |
181 | 186 | ||
182 | static int esb_timer_read (void) | 187 | static int esb_timer_read(void) |
183 | { | 188 | { |
184 | u32 count; | 189 | u32 count; |
185 | 190 | ||
186 | /* This isn't documented, and doesn't take into | 191 | /* This isn't documented, and doesn't take into |
187 | * acount which stage is running, but it looks | 192 | * acount which stage is running, but it looks |
188 | * like a 20 bit count down, so we might as well report it. | 193 | * like a 20 bit count down, so we might as well report it. |
189 | */ | 194 | */ |
190 | pci_read_config_dword(esb_pci, 0x64, &count); | 195 | pci_read_config_dword(esb_pci, 0x64, &count); |
191 | return (int)count; | 196 | return (int)count; |
192 | } | 197 | } |
193 | 198 | ||
194 | /* | 199 | /* |
195 | * /dev/watchdog handling | 200 | * /dev/watchdog handling |
196 | */ | 201 | */ |
197 | 202 | ||
198 | static int esb_open (struct inode *inode, struct file *file) | 203 | static int esb_open(struct inode *inode, struct file *file) |
199 | { | 204 | { |
200 | /* /dev/watchdog can only be opened once */ | 205 | /* /dev/watchdog can only be opened once */ |
201 | if (test_and_set_bit(0, &timer_alive)) | 206 | if (test_and_set_bit(0, &timer_alive)) |
202 | return -EBUSY; | 207 | return -EBUSY; |
203 | 208 | ||
204 | /* Reload and activate timer */ | 209 | /* Reload and activate timer */ |
205 | esb_timer_keepalive (); | 210 | esb_timer_keepalive(); |
206 | esb_timer_start (); | 211 | esb_timer_start(); |
207 | 212 | ||
208 | return nonseekable_open(inode, file); | 213 | return nonseekable_open(inode, file); |
209 | } | 214 | } |
210 | 215 | ||
211 | static int esb_release (struct inode *inode, struct file *file) | 216 | static int esb_release(struct inode *inode, struct file *file) |
212 | { | 217 | { |
213 | /* Shut off the timer. */ | 218 | /* Shut off the timer. */ |
214 | if (esb_expect_close == 42) { | 219 | if (esb_expect_close == 42) |
215 | esb_timer_stop (); | 220 | esb_timer_stop(); |
216 | } else { | 221 | else { |
217 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 222 | printk(KERN_CRIT PFX |
218 | esb_timer_keepalive (); | 223 | "Unexpected close, not stopping watchdog!\n"); |
219 | } | 224 | esb_timer_keepalive(); |
220 | clear_bit(0, &timer_alive); | 225 | } |
221 | esb_expect_close = 0; | 226 | clear_bit(0, &timer_alive); |
222 | return 0; | 227 | esb_expect_close = 0; |
228 | return 0; | ||
223 | } | 229 | } |
224 | 230 | ||
225 | static ssize_t esb_write (struct file *file, const char __user *data, | 231 | static ssize_t esb_write(struct file *file, const char __user *data, |
226 | size_t len, loff_t * ppos) | 232 | size_t len, loff_t *ppos) |
227 | { | 233 | { |
228 | /* See if we got the magic character 'V' and reload the timer */ | 234 | /* See if we got the magic character 'V' and reload the timer */ |
229 | if (len) { | 235 | if (len) { |
230 | if (!nowayout) { | 236 | if (!nowayout) { |
231 | size_t i; | 237 | size_t i; |
232 | 238 | ||
@@ -237,7 +243,7 @@ static ssize_t esb_write (struct file *file, const char __user *data, | |||
237 | /* scan to see whether or not we got the magic character */ | 243 | /* scan to see whether or not we got the magic character */ |
238 | for (i = 0; i != len; i++) { | 244 | for (i = 0; i != len; i++) { |
239 | char c; | 245 | char c; |
240 | if(get_user(c, data+i)) | 246 | if (get_user(c, data + i)) |
241 | return -EFAULT; | 247 | return -EFAULT; |
242 | if (c == 'V') | 248 | if (c == 'V') |
243 | esb_expect_close = 42; | 249 | esb_expect_close = 42; |
@@ -245,92 +251,84 @@ static ssize_t esb_write (struct file *file, const char __user *data, | |||
245 | } | 251 | } |
246 | 252 | ||
247 | /* someone wrote to us, we should reload the timer */ | 253 | /* someone wrote to us, we should reload the timer */ |
248 | esb_timer_keepalive (); | 254 | esb_timer_keepalive(); |
249 | } | 255 | } |
250 | return len; | 256 | return len; |
251 | } | 257 | } |
252 | 258 | ||
253 | static int esb_ioctl (struct inode *inode, struct file *file, | 259 | static long esb_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
254 | unsigned int cmd, unsigned long arg) | ||
255 | { | 260 | { |
256 | int new_options, retval = -EINVAL; | 261 | int new_options, retval = -EINVAL; |
257 | int new_heartbeat; | 262 | int new_heartbeat; |
258 | void __user *argp = (void __user *)arg; | 263 | void __user *argp = (void __user *)arg; |
259 | int __user *p = argp; | 264 | int __user *p = argp; |
260 | static struct watchdog_info ident = { | 265 | static struct watchdog_info ident = { |
261 | .options = WDIOF_SETTIMEOUT | | 266 | .options = WDIOF_SETTIMEOUT | |
262 | WDIOF_KEEPALIVEPING | | 267 | WDIOF_KEEPALIVEPING | |
263 | WDIOF_MAGICCLOSE, | 268 | WDIOF_MAGICCLOSE, |
264 | .firmware_version = 0, | 269 | .firmware_version = 0, |
265 | .identity = ESB_MODULE_NAME, | 270 | .identity = ESB_MODULE_NAME, |
266 | }; | 271 | }; |
267 | 272 | ||
268 | switch (cmd) { | 273 | switch (cmd) { |
269 | case WDIOC_GETSUPPORT: | 274 | case WDIOC_GETSUPPORT: |
270 | return copy_to_user(argp, &ident, | 275 | return copy_to_user(argp, &ident, |
271 | sizeof (ident)) ? -EFAULT : 0; | 276 | sizeof(ident)) ? -EFAULT : 0; |
272 | |||
273 | case WDIOC_GETSTATUS: | ||
274 | return put_user (esb_timer_read(), p); | ||
275 | |||
276 | case WDIOC_GETBOOTSTATUS: | ||
277 | return put_user (triggered, p); | ||
278 | 277 | ||
279 | case WDIOC_KEEPALIVE: | 278 | case WDIOC_GETSTATUS: |
280 | esb_timer_keepalive (); | 279 | return put_user(esb_timer_read(), p); |
281 | return 0; | ||
282 | 280 | ||
283 | case WDIOC_SETOPTIONS: | 281 | case WDIOC_GETBOOTSTATUS: |
284 | { | 282 | return put_user(triggered, p); |
285 | if (get_user (new_options, p)) | ||
286 | return -EFAULT; | ||
287 | 283 | ||
288 | if (new_options & WDIOS_DISABLECARD) { | 284 | case WDIOC_SETOPTIONS: |
289 | esb_timer_stop (); | 285 | { |
290 | retval = 0; | 286 | if (get_user(new_options, p)) |
291 | } | 287 | return -EFAULT; |
292 | 288 | ||
293 | if (new_options & WDIOS_ENABLECARD) { | 289 | if (new_options & WDIOS_DISABLECARD) { |
294 | esb_timer_keepalive (); | 290 | esb_timer_stop(); |
295 | esb_timer_start (); | 291 | retval = 0; |
296 | retval = 0; | 292 | } |
297 | } | ||
298 | |||
299 | return retval; | ||
300 | } | ||
301 | |||
302 | case WDIOC_SETTIMEOUT: | ||
303 | { | ||
304 | if (get_user(new_heartbeat, p)) | ||
305 | return -EFAULT; | ||
306 | |||
307 | if (esb_timer_set_heartbeat(new_heartbeat)) | ||
308 | return -EINVAL; | ||
309 | |||
310 | esb_timer_keepalive (); | ||
311 | /* Fall */ | ||
312 | } | ||
313 | |||
314 | case WDIOC_GETTIMEOUT: | ||
315 | return put_user(heartbeat, p); | ||
316 | 293 | ||
317 | default: | 294 | if (new_options & WDIOS_ENABLECARD) { |
318 | return -ENOTTY; | 295 | esb_timer_keepalive(); |
319 | } | 296 | esb_timer_start(); |
297 | retval = 0; | ||
298 | } | ||
299 | return retval; | ||
300 | } | ||
301 | case WDIOC_KEEPALIVE: | ||
302 | esb_timer_keepalive(); | ||
303 | return 0; | ||
304 | |||
305 | case WDIOC_SETTIMEOUT: | ||
306 | { | ||
307 | if (get_user(new_heartbeat, p)) | ||
308 | return -EFAULT; | ||
309 | if (esb_timer_set_heartbeat(new_heartbeat)) | ||
310 | return -EINVAL; | ||
311 | esb_timer_keepalive(); | ||
312 | /* Fall */ | ||
313 | } | ||
314 | case WDIOC_GETTIMEOUT: | ||
315 | return put_user(heartbeat, p); | ||
316 | default: | ||
317 | return -ENOTTY; | ||
318 | } | ||
320 | } | 319 | } |
321 | 320 | ||
322 | /* | 321 | /* |
323 | * Notify system | 322 | * Notify system |
324 | */ | 323 | */ |
325 | 324 | ||
326 | static int esb_notify_sys (struct notifier_block *this, unsigned long code, void *unused) | 325 | static int esb_notify_sys(struct notifier_block *this, |
326 | unsigned long code, void *unused) | ||
327 | { | 327 | { |
328 | if (code==SYS_DOWN || code==SYS_HALT) { | 328 | if (code == SYS_DOWN || code == SYS_HALT) |
329 | /* Turn the WDT off */ | 329 | esb_timer_stop(); /* Turn the WDT off */ |
330 | esb_timer_stop (); | ||
331 | } | ||
332 | 330 | ||
333 | return NOTIFY_DONE; | 331 | return NOTIFY_DONE; |
334 | } | 332 | } |
335 | 333 | ||
336 | /* | 334 | /* |
@@ -338,22 +336,22 @@ static int esb_notify_sys (struct notifier_block *this, unsigned long code, void | |||
338 | */ | 336 | */ |
339 | 337 | ||
340 | static const struct file_operations esb_fops = { | 338 | static const struct file_operations esb_fops = { |
341 | .owner = THIS_MODULE, | 339 | .owner = THIS_MODULE, |
342 | .llseek = no_llseek, | 340 | .llseek = no_llseek, |
343 | .write = esb_write, | 341 | .write = esb_write, |
344 | .ioctl = esb_ioctl, | 342 | .unlocked_ioctl = esb_ioctl, |
345 | .open = esb_open, | 343 | .open = esb_open, |
346 | .release = esb_release, | 344 | .release = esb_release, |
347 | }; | 345 | }; |
348 | 346 | ||
349 | static struct miscdevice esb_miscdev = { | 347 | static struct miscdevice esb_miscdev = { |
350 | .minor = WATCHDOG_MINOR, | 348 | .minor = WATCHDOG_MINOR, |
351 | .name = "watchdog", | 349 | .name = "watchdog", |
352 | .fops = &esb_fops, | 350 | .fops = &esb_fops, |
353 | }; | 351 | }; |
354 | 352 | ||
355 | static struct notifier_block esb_notifier = { | 353 | static struct notifier_block esb_notifier = { |
356 | .notifier_call = esb_notify_sys, | 354 | .notifier_call = esb_notify_sys, |
357 | }; | 355 | }; |
358 | 356 | ||
359 | /* | 357 | /* |
@@ -365,50 +363,44 @@ static struct notifier_block esb_notifier = { | |||
365 | * want to register another driver on the same PCI id. | 363 | * want to register another driver on the same PCI id. |
366 | */ | 364 | */ |
367 | static struct pci_device_id esb_pci_tbl[] = { | 365 | static struct pci_device_id esb_pci_tbl[] = { |
368 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, | 366 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ESB_9), }, |
369 | { 0, }, /* End of list */ | 367 | { 0, }, /* End of list */ |
370 | }; | 368 | }; |
371 | MODULE_DEVICE_TABLE (pci, esb_pci_tbl); | 369 | MODULE_DEVICE_TABLE(pci, esb_pci_tbl); |
372 | 370 | ||
373 | /* | 371 | /* |
374 | * Init & exit routines | 372 | * Init & exit routines |
375 | */ | 373 | */ |
376 | 374 | ||
377 | static unsigned char __init esb_getdevice (void) | 375 | static unsigned char __init esb_getdevice(void) |
378 | { | 376 | { |
379 | u8 val1; | 377 | u8 val1; |
380 | unsigned short val2; | 378 | unsigned short val2; |
379 | /* | ||
380 | * Find the PCI device | ||
381 | */ | ||
381 | 382 | ||
382 | struct pci_dev *dev = NULL; | 383 | esb_pci = pci_get_device(PCI_VENDOR_ID_INTEL, |
383 | /* | 384 | PCI_DEVICE_ID_INTEL_ESB_9, NULL); |
384 | * Find the PCI device | ||
385 | */ | ||
386 | |||
387 | for_each_pci_dev(dev) { | ||
388 | if (pci_match_id(esb_pci_tbl, dev)) { | ||
389 | esb_pci = dev; | ||
390 | break; | ||
391 | } | ||
392 | } | ||
393 | 385 | ||
394 | if (esb_pci) { | 386 | if (esb_pci) { |
395 | if (pci_enable_device(esb_pci)) { | 387 | if (pci_enable_device(esb_pci)) { |
396 | printk (KERN_ERR PFX "failed to enable device\n"); | 388 | printk(KERN_ERR PFX "failed to enable device\n"); |
397 | goto err_devput; | 389 | goto err_devput; |
398 | } | 390 | } |
399 | 391 | ||
400 | if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { | 392 | if (pci_request_region(esb_pci, 0, ESB_MODULE_NAME)) { |
401 | printk (KERN_ERR PFX "failed to request region\n"); | 393 | printk(KERN_ERR PFX "failed to request region\n"); |
402 | goto err_disable; | 394 | goto err_disable; |
403 | } | 395 | } |
404 | 396 | ||
405 | BASEADDR = ioremap(pci_resource_start(esb_pci, 0), | 397 | BASEADDR = ioremap(pci_resource_start(esb_pci, 0), |
406 | pci_resource_len(esb_pci, 0)); | 398 | pci_resource_len(esb_pci, 0)); |
407 | if (BASEADDR == NULL) { | 399 | if (BASEADDR == NULL) { |
408 | /* Something's wrong here, BASEADDR has to be set */ | 400 | /* Something's wrong here, BASEADDR has to be set */ |
409 | printk (KERN_ERR PFX "failed to get BASEADDR\n"); | 401 | printk(KERN_ERR PFX "failed to get BASEADDR\n"); |
410 | goto err_release; | 402 | goto err_release; |
411 | } | 403 | } |
412 | 404 | ||
413 | /* | 405 | /* |
414 | * The watchdog has two timers, it can be setup so that the | 406 | * The watchdog has two timers, it can be setup so that the |
@@ -425,7 +417,7 @@ static unsigned char __init esb_getdevice (void) | |||
425 | /* Check that the WDT isn't already locked */ | 417 | /* Check that the WDT isn't already locked */ |
426 | pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); | 418 | pci_read_config_byte(esb_pci, ESB_LOCK_REG, &val1); |
427 | if (val1 & ESB_WDT_LOCK) | 419 | if (val1 & ESB_WDT_LOCK) |
428 | printk (KERN_WARNING PFX "nowayout already set\n"); | 420 | printk(KERN_WARNING PFX "nowayout already set\n"); |
429 | 421 | ||
430 | /* Set the timer to watchdog mode and disable it for now */ | 422 | /* Set the timer to watchdog mode and disable it for now */ |
431 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); | 423 | pci_write_config_byte(esb_pci, ESB_LOCK_REG, 0x00); |
@@ -452,44 +444,44 @@ err_devput: | |||
452 | return 0; | 444 | return 0; |
453 | } | 445 | } |
454 | 446 | ||
455 | static int __init watchdog_init (void) | 447 | static int __init watchdog_init(void) |
456 | { | 448 | { |
457 | int ret; | 449 | int ret; |
458 | 450 | ||
459 | /* Check whether or not the hardware watchdog is there */ | 451 | /* Check whether or not the hardware watchdog is there */ |
460 | if (!esb_getdevice () || esb_pci == NULL) | 452 | if (!esb_getdevice() || esb_pci == NULL) |
461 | return -ENODEV; | 453 | return -ENODEV; |
462 | 454 | ||
463 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 455 | /* Check that the heartbeat value is within it's range; |
464 | if (esb_timer_set_heartbeat (heartbeat)) { | 456 | if not reset to the default */ |
465 | esb_timer_set_heartbeat (WATCHDOG_HEARTBEAT); | 457 | if (esb_timer_set_heartbeat(heartbeat)) { |
466 | printk(KERN_INFO PFX "heartbeat value must be 1<heartbeat<2046, using %d\n", | 458 | esb_timer_set_heartbeat(WATCHDOG_HEARTBEAT); |
467 | heartbeat); | 459 | printk(KERN_INFO PFX |
468 | } | 460 | "heartbeat value must be 1<heartbeat<2046, using %d\n", |
469 | 461 | heartbeat); | |
470 | ret = register_reboot_notifier(&esb_notifier); | 462 | } |
471 | if (ret != 0) { | 463 | ret = register_reboot_notifier(&esb_notifier); |
472 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 464 | if (ret != 0) { |
473 | ret); | 465 | printk(KERN_ERR PFX |
474 | goto err_unmap; | 466 | "cannot register reboot notifier (err=%d)\n", ret); |
475 | } | 467 | goto err_unmap; |
476 | 468 | } | |
477 | ret = misc_register(&esb_miscdev); | ||
478 | if (ret != 0) { | ||
479 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | ||
480 | WATCHDOG_MINOR, ret); | ||
481 | goto err_notifier; | ||
482 | } | ||
483 | |||
484 | esb_timer_stop (); | ||
485 | |||
486 | printk (KERN_INFO PFX "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", | ||
487 | BASEADDR, heartbeat, nowayout); | ||
488 | 469 | ||
489 | return 0; | 470 | ret = misc_register(&esb_miscdev); |
471 | if (ret != 0) { | ||
472 | printk(KERN_ERR PFX | ||
473 | "cannot register miscdev on minor=%d (err=%d)\n", | ||
474 | WATCHDOG_MINOR, ret); | ||
475 | goto err_notifier; | ||
476 | } | ||
477 | esb_timer_stop(); | ||
478 | printk(KERN_INFO PFX | ||
479 | "initialized (0x%p). heartbeat=%d sec (nowayout=%d)\n", | ||
480 | BASEADDR, heartbeat, nowayout); | ||
481 | return 0; | ||
490 | 482 | ||
491 | err_notifier: | 483 | err_notifier: |
492 | unregister_reboot_notifier(&esb_notifier); | 484 | unregister_reboot_notifier(&esb_notifier); |
493 | err_unmap: | 485 | err_unmap: |
494 | iounmap(BASEADDR); | 486 | iounmap(BASEADDR); |
495 | /* err_release: */ | 487 | /* err_release: */ |
@@ -498,18 +490,18 @@ err_unmap: | |||
498 | pci_disable_device(esb_pci); | 490 | pci_disable_device(esb_pci); |
499 | /* err_devput: */ | 491 | /* err_devput: */ |
500 | pci_dev_put(esb_pci); | 492 | pci_dev_put(esb_pci); |
501 | return ret; | 493 | return ret; |
502 | } | 494 | } |
503 | 495 | ||
504 | static void __exit watchdog_cleanup (void) | 496 | static void __exit watchdog_cleanup(void) |
505 | { | 497 | { |
506 | /* Stop the timer before we leave */ | 498 | /* Stop the timer before we leave */ |
507 | if (!nowayout) | 499 | if (!nowayout) |
508 | esb_timer_stop (); | 500 | esb_timer_stop(); |
509 | 501 | ||
510 | /* Deregister */ | 502 | /* Deregister */ |
511 | misc_deregister(&esb_miscdev); | 503 | misc_deregister(&esb_miscdev); |
512 | unregister_reboot_notifier(&esb_notifier); | 504 | unregister_reboot_notifier(&esb_notifier); |
513 | iounmap(BASEADDR); | 505 | iounmap(BASEADDR); |
514 | pci_release_region(esb_pci, 0); | 506 | pci_release_region(esb_pci, 0); |
515 | pci_disable_device(esb_pci); | 507 | pci_disable_device(esb_pci); |
diff --git a/drivers/watchdog/iTCO_vendor.h b/drivers/watchdog/iTCO_vendor.h new file mode 100644 index 000000000000..9e27e6422f66 --- /dev/null +++ b/drivers/watchdog/iTCO_vendor.h | |||
@@ -0,0 +1,15 @@ | |||
1 | /* iTCO Vendor Specific Support hooks */ | ||
2 | #ifdef CONFIG_ITCO_VENDOR_SUPPORT | ||
3 | extern void iTCO_vendor_pre_start(unsigned long, unsigned int); | ||
4 | extern void iTCO_vendor_pre_stop(unsigned long); | ||
5 | extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int); | ||
6 | extern void iTCO_vendor_pre_set_heartbeat(unsigned int); | ||
7 | extern int iTCO_vendor_check_noreboot_on(void); | ||
8 | #else | ||
9 | #define iTCO_vendor_pre_start(acpibase, heartbeat) {} | ||
10 | #define iTCO_vendor_pre_stop(acpibase) {} | ||
11 | #define iTCO_vendor_pre_keepalive(acpibase, heartbeat) {} | ||
12 | #define iTCO_vendor_pre_set_heartbeat(heartbeat) {} | ||
13 | #define iTCO_vendor_check_noreboot_on() 1 | ||
14 | /* 1=check noreboot; 0=don't check */ | ||
15 | #endif | ||
diff --git a/drivers/watchdog/iTCO_vendor_support.c b/drivers/watchdog/iTCO_vendor_support.c index cafc465f2ae3..ca344a85eb95 100644 --- a/drivers/watchdog/iTCO_vendor_support.c +++ b/drivers/watchdog/iTCO_vendor_support.c | |||
@@ -18,9 +18,9 @@ | |||
18 | */ | 18 | */ |
19 | 19 | ||
20 | /* Module and version information */ | 20 | /* Module and version information */ |
21 | #define DRV_NAME "iTCO_vendor_support" | 21 | #define DRV_NAME "iTCO_vendor_support" |
22 | #define DRV_VERSION "1.01" | 22 | #define DRV_VERSION "1.01" |
23 | #define DRV_RELDATE "11-Nov-2006" | 23 | #define DRV_RELDATE "11-Nov-2006" |
24 | #define PFX DRV_NAME ": " | 24 | #define PFX DRV_NAME ": " |
25 | 25 | ||
26 | /* Includes */ | 26 | /* Includes */ |
@@ -31,19 +31,22 @@ | |||
31 | #include <linux/kernel.h> /* For printk/panic/... */ | 31 | #include <linux/kernel.h> /* For printk/panic/... */ |
32 | #include <linux/init.h> /* For __init/__exit/... */ | 32 | #include <linux/init.h> /* For __init/__exit/... */ |
33 | #include <linux/ioport.h> /* For io-port access */ | 33 | #include <linux/ioport.h> /* For io-port access */ |
34 | #include <linux/io.h> /* For inb/outb/... */ | ||
34 | 35 | ||
35 | #include <asm/io.h> /* For inb/outb/... */ | 36 | #include "iTCO_vendor.h" |
36 | 37 | ||
37 | /* iTCO defines */ | 38 | /* iTCO defines */ |
38 | #define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */ | 39 | #define SMI_EN acpibase + 0x30 /* SMI Control and Enable Register */ |
39 | #define TCOBASE acpibase + 0x60 /* TCO base address */ | 40 | #define TCOBASE acpibase + 0x60 /* TCO base address */ |
40 | #define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ | 41 | #define TCO1_STS TCOBASE + 0x04 /* TCO1 Status Register */ |
41 | 42 | ||
42 | /* List of vendor support modes */ | 43 | /* List of vendor support modes */ |
43 | #define SUPERMICRO_OLD_BOARD 1 /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ | 44 | /* SuperMicro Pentium 3 Era 370SSE+-OEM1/P3TSSE */ |
44 | #define SUPERMICRO_NEW_BOARD 2 /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */ | 45 | #define SUPERMICRO_OLD_BOARD 1 |
46 | /* SuperMicro Pentium 4 / Xeon 4 / EMT64T Era Systems */ | ||
47 | #define SUPERMICRO_NEW_BOARD 2 | ||
45 | 48 | ||
46 | static int vendorsupport = 0; | 49 | static int vendorsupport; |
47 | module_param(vendorsupport, int, 0); | 50 | module_param(vendorsupport, int, 0); |
48 | MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+"); | 51 | MODULE_PARM_DESC(vendorsupport, "iTCO vendor specific support mode, default=0 (none), 1=SuperMicro Pent3, 2=SuperMicro Pent4+"); |
49 | 52 | ||
@@ -143,34 +146,35 @@ static void supermicro_old_pre_keepalive(unsigned long acpibase) | |||
143 | */ | 146 | */ |
144 | 147 | ||
145 | /* I/O Port's */ | 148 | /* I/O Port's */ |
146 | #define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */ | 149 | #define SM_REGINDEX 0x2e /* SuperMicro ICH4+ Register Index */ |
147 | #define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */ | 150 | #define SM_DATAIO 0x2f /* SuperMicro ICH4+ Register Data I/O */ |
148 | 151 | ||
149 | /* Control Register's */ | 152 | /* Control Register's */ |
150 | #define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */ | 153 | #define SM_CTLPAGESW 0x07 /* SuperMicro ICH4+ Control Page Switch */ |
151 | #define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */ | 154 | #define SM_CTLPAGE 0x08 /* SuperMicro ICH4+ Control Page Num */ |
152 | 155 | ||
153 | #define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */ | 156 | #define SM_WATCHENABLE 0x30 /* Watchdog enable: Bit 0: 0=off, 1=on */ |
154 | 157 | ||
155 | #define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */ | 158 | #define SM_WATCHPAGE 0x87 /* Watchdog unlock control page */ |
156 | 159 | ||
157 | #define SM_ENDWATCH 0xAA /* Watchdog lock control page */ | 160 | #define SM_ENDWATCH 0xAA /* Watchdog lock control page */ |
158 | 161 | ||
159 | #define SM_COUNTMODE 0xf5 /* Watchdog count mode select */ | 162 | #define SM_COUNTMODE 0xf5 /* Watchdog count mode select */ |
160 | /* (Bit 3: 0 = seconds, 1 = minutes */ | 163 | /* (Bit 3: 0 = seconds, 1 = minutes */ |
161 | 164 | ||
162 | #define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */ | 165 | #define SM_WATCHTIMER 0xf6 /* 8-bits, Watchdog timer counter (RW) */ |
163 | 166 | ||
164 | #define SM_RESETCONTROL 0xf7 /* Watchdog reset control */ | 167 | #define SM_RESETCONTROL 0xf7 /* Watchdog reset control */ |
165 | /* Bit 6: timer is reset by kbd interrupt */ | 168 | /* Bit 6: timer is reset by kbd interrupt */ |
166 | /* Bit 7: timer is reset by mouse interrupt */ | 169 | /* Bit 7: timer is reset by mouse interrupt */ |
167 | 170 | ||
168 | static void supermicro_new_unlock_watchdog(void) | 171 | static void supermicro_new_unlock_watchdog(void) |
169 | { | 172 | { |
170 | outb(SM_WATCHPAGE, SM_REGINDEX); /* Write 0x87 to port 0x2e twice */ | 173 | /* Write 0x87 to port 0x2e twice */ |
171 | outb(SM_WATCHPAGE, SM_REGINDEX); | 174 | outb(SM_WATCHPAGE, SM_REGINDEX); |
172 | 175 | outb(SM_WATCHPAGE, SM_REGINDEX); | |
173 | outb(SM_CTLPAGESW, SM_REGINDEX); /* Switch to watchdog control page */ | 176 | /* Switch to watchdog control page */ |
177 | outb(SM_CTLPAGESW, SM_REGINDEX); | ||
174 | outb(SM_CTLPAGE, SM_DATAIO); | 178 | outb(SM_CTLPAGE, SM_DATAIO); |
175 | } | 179 | } |
176 | 180 | ||
@@ -192,7 +196,7 @@ static void supermicro_new_pre_start(unsigned int heartbeat) | |||
192 | outb(val, SM_DATAIO); | 196 | outb(val, SM_DATAIO); |
193 | 197 | ||
194 | /* Write heartbeat interval to WDOG */ | 198 | /* Write heartbeat interval to WDOG */ |
195 | outb (SM_WATCHTIMER, SM_REGINDEX); | 199 | outb(SM_WATCHTIMER, SM_REGINDEX); |
196 | outb((heartbeat & 255), SM_DATAIO); | 200 | outb((heartbeat & 255), SM_DATAIO); |
197 | 201 | ||
198 | /* Make sure keyboard/mouse interrupts don't interfere */ | 202 | /* Make sure keyboard/mouse interrupts don't interfere */ |
@@ -277,7 +281,7 @@ EXPORT_SYMBOL(iTCO_vendor_pre_set_heartbeat); | |||
277 | 281 | ||
278 | int iTCO_vendor_check_noreboot_on(void) | 282 | int iTCO_vendor_check_noreboot_on(void) |
279 | { | 283 | { |
280 | switch(vendorsupport) { | 284 | switch (vendorsupport) { |
281 | case SUPERMICRO_OLD_BOARD: | 285 | case SUPERMICRO_OLD_BOARD: |
282 | return 0; | 286 | return 0; |
283 | default: | 287 | default: |
@@ -288,13 +292,13 @@ EXPORT_SYMBOL(iTCO_vendor_check_noreboot_on); | |||
288 | 292 | ||
289 | static int __init iTCO_vendor_init_module(void) | 293 | static int __init iTCO_vendor_init_module(void) |
290 | { | 294 | { |
291 | printk (KERN_INFO PFX "vendor-support=%d\n", vendorsupport); | 295 | printk(KERN_INFO PFX "vendor-support=%d\n", vendorsupport); |
292 | return 0; | 296 | return 0; |
293 | } | 297 | } |
294 | 298 | ||
295 | static void __exit iTCO_vendor_exit_module(void) | 299 | static void __exit iTCO_vendor_exit_module(void) |
296 | { | 300 | { |
297 | printk (KERN_INFO PFX "Module Unloaded\n"); | 301 | printk(KERN_INFO PFX "Module Unloaded\n"); |
298 | } | 302 | } |
299 | 303 | ||
300 | module_init(iTCO_vendor_init_module); | 304 | module_init(iTCO_vendor_init_module); |
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c index 95ba985bd341..bfb93bc2ca9f 100644 --- a/drivers/watchdog/iTCO_wdt.c +++ b/drivers/watchdog/iTCO_wdt.c | |||
@@ -55,9 +55,9 @@ | |||
55 | */ | 55 | */ |
56 | 56 | ||
57 | /* Module and version information */ | 57 | /* Module and version information */ |
58 | #define DRV_NAME "iTCO_wdt" | 58 | #define DRV_NAME "iTCO_wdt" |
59 | #define DRV_VERSION "1.03" | 59 | #define DRV_VERSION "1.03" |
60 | #define DRV_RELDATE "30-Apr-2008" | 60 | #define DRV_RELDATE "30-Apr-2008" |
61 | #define PFX DRV_NAME ": " | 61 | #define PFX DRV_NAME ": " |
62 | 62 | ||
63 | /* Includes */ | 63 | /* Includes */ |
@@ -66,7 +66,8 @@ | |||
66 | #include <linux/types.h> /* For standard types (like size_t) */ | 66 | #include <linux/types.h> /* For standard types (like size_t) */ |
67 | #include <linux/errno.h> /* For the -ENODEV/... values */ | 67 | #include <linux/errno.h> /* For the -ENODEV/... values */ |
68 | #include <linux/kernel.h> /* For printk/panic/... */ | 68 | #include <linux/kernel.h> /* For printk/panic/... */ |
69 | #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR) */ | 69 | #include <linux/miscdevice.h> /* For MODULE_ALIAS_MISCDEV |
70 | (WATCHDOG_MINOR) */ | ||
70 | #include <linux/watchdog.h> /* For the watchdog specific items */ | 71 | #include <linux/watchdog.h> /* For the watchdog specific items */ |
71 | #include <linux/init.h> /* For __init/__exit/... */ | 72 | #include <linux/init.h> /* For __init/__exit/... */ |
72 | #include <linux/fs.h> /* For file operations */ | 73 | #include <linux/fs.h> /* For file operations */ |
@@ -74,9 +75,10 @@ | |||
74 | #include <linux/pci.h> /* For pci functions */ | 75 | #include <linux/pci.h> /* For pci functions */ |
75 | #include <linux/ioport.h> /* For io-port access */ | 76 | #include <linux/ioport.h> /* For io-port access */ |
76 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ | 77 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ |
78 | #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ | ||
79 | #include <linux/io.h> /* For inb/outb/... */ | ||
77 | 80 | ||
78 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | 81 | #include "iTCO_vendor.h" |
79 | #include <asm/io.h> /* For inb/outb/... */ | ||
80 | 82 | ||
81 | /* TCO related info */ | 83 | /* TCO related info */ |
82 | enum iTCO_chipsets { | 84 | enum iTCO_chipsets { |
@@ -105,7 +107,7 @@ enum iTCO_chipsets { | |||
105 | TCO_ICH9, /* ICH9 */ | 107 | TCO_ICH9, /* ICH9 */ |
106 | TCO_ICH9R, /* ICH9R */ | 108 | TCO_ICH9R, /* ICH9R */ |
107 | TCO_ICH9DH, /* ICH9DH */ | 109 | TCO_ICH9DH, /* ICH9DH */ |
108 | TCO_ICH9DO, /* ICH9DO */ | 110 | TCO_ICH9DO, /* ICH9DO */ |
109 | TCO_631XESB, /* 631xESB/632xESB */ | 111 | TCO_631XESB, /* 631xESB/632xESB */ |
110 | }; | 112 | }; |
111 | 113 | ||
@@ -140,7 +142,7 @@ static struct { | |||
140 | {"ICH9DH", 2}, | 142 | {"ICH9DH", 2}, |
141 | {"ICH9DO", 2}, | 143 | {"ICH9DO", 2}, |
142 | {"631xESB/632xESB", 2}, | 144 | {"631xESB/632xESB", 2}, |
143 | {NULL,0} | 145 | {NULL, 0} |
144 | }; | 146 | }; |
145 | 147 | ||
146 | #define ITCO_PCI_DEVICE(dev, data) \ | 148 | #define ITCO_PCI_DEVICE(dev, data) \ |
@@ -159,32 +161,32 @@ static struct { | |||
159 | * functions that probably will be registered by other drivers. | 161 | * functions that probably will be registered by other drivers. |
160 | */ | 162 | */ |
161 | static struct pci_device_id iTCO_wdt_pci_tbl[] = { | 163 | static struct pci_device_id iTCO_wdt_pci_tbl[] = { |
162 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH )}, | 164 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AA_0, TCO_ICH)}, |
163 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0 )}, | 165 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801AB_0, TCO_ICH0)}, |
164 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2 )}, | 166 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_0, TCO_ICH2)}, |
165 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10, TCO_ICH2M )}, | 167 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801BA_10, TCO_ICH2M)}, |
166 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0, TCO_ICH3 )}, | 168 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_0, TCO_ICH3)}, |
167 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12, TCO_ICH3M )}, | 169 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801CA_12, TCO_ICH3M)}, |
168 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0, TCO_ICH4 )}, | 170 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_0, TCO_ICH4)}, |
169 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12, TCO_ICH4M )}, | 171 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801DB_12, TCO_ICH4M)}, |
170 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0, TCO_CICH )}, | 172 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801E_0, TCO_CICH)}, |
171 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0, TCO_ICH5 )}, | 173 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_82801EB_0, TCO_ICH5)}, |
172 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1, TCO_6300ESB)}, | 174 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB_1, TCO_6300ESB)}, |
173 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6 )}, | 175 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_0, TCO_ICH6)}, |
174 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M )}, | 176 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_1, TCO_ICH6M)}, |
175 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W )}, | 177 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH6_2, TCO_ICH6W)}, |
176 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7 )}, | 178 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_0, TCO_ICH7)}, |
177 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M )}, | 179 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_1, TCO_ICH7M)}, |
178 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, | 180 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH7_31, TCO_ICH7MDH)}, |
179 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8 )}, | 181 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_0, TCO_ICH8)}, |
180 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME )}, | 182 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_1, TCO_ICH8ME)}, |
181 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH )}, | 183 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_2, TCO_ICH8DH)}, |
182 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO )}, | 184 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_3, TCO_ICH8DO)}, |
183 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M )}, | 185 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH8_4, TCO_ICH8M)}, |
184 | { ITCO_PCI_DEVICE(0x2918, TCO_ICH9 )}, | 186 | { ITCO_PCI_DEVICE(0x2918, TCO_ICH9)}, |
185 | { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R )}, | 187 | { ITCO_PCI_DEVICE(0x2916, TCO_ICH9R)}, |
186 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH )}, | 188 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_2, TCO_ICH9DH)}, |
187 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO )}, | 189 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ICH9_4, TCO_ICH9DO)}, |
188 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)}, | 190 | { ITCO_PCI_DEVICE(PCI_DEVICE_ID_INTEL_ESB2_0, TCO_631XESB)}, |
189 | { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)}, | 191 | { ITCO_PCI_DEVICE(0x2671, TCO_631XESB)}, |
190 | { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)}, | 192 | { ITCO_PCI_DEVICE(0x2672, TCO_631XESB)}, |
@@ -203,13 +205,15 @@ static struct pci_device_id iTCO_wdt_pci_tbl[] = { | |||
203 | { ITCO_PCI_DEVICE(0x267f, TCO_631XESB)}, | 205 | { ITCO_PCI_DEVICE(0x267f, TCO_631XESB)}, |
204 | { 0, }, /* End of list */ | 206 | { 0, }, /* End of list */ |
205 | }; | 207 | }; |
206 | MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); | 208 | MODULE_DEVICE_TABLE(pci, iTCO_wdt_pci_tbl); |
207 | 209 | ||
208 | /* Address definitions for the TCO */ | 210 | /* Address definitions for the TCO */ |
209 | #define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60 /* TCO base address */ | 211 | /* TCO base address */ |
210 | #define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30 /* SMI Control and Enable Register */ | 212 | #define TCOBASE iTCO_wdt_private.ACPIBASE + 0x60 |
213 | /* SMI Control and Enable Register */ | ||
214 | #define SMI_EN iTCO_wdt_private.ACPIBASE + 0x30 | ||
211 | 215 | ||
212 | #define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Current Value */ | 216 | #define TCO_RLD TCOBASE + 0x00 /* TCO Timer Reload and Curr. Value */ |
213 | #define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */ | 217 | #define TCOv1_TMR TCOBASE + 0x01 /* TCOv1 Timer Initial Value */ |
214 | #define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ | 218 | #define TCO_DAT_IN TCOBASE + 0x02 /* TCO Data In Register */ |
215 | #define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ | 219 | #define TCO_DAT_OUT TCOBASE + 0x03 /* TCO Data Out Register */ |
@@ -222,15 +226,21 @@ MODULE_DEVICE_TABLE (pci, iTCO_wdt_pci_tbl); | |||
222 | /* internal variables */ | 226 | /* internal variables */ |
223 | static unsigned long is_active; | 227 | static unsigned long is_active; |
224 | static char expect_release; | 228 | static char expect_release; |
225 | static struct { /* this is private data for the iTCO_wdt device */ | 229 | static struct { /* this is private data for the iTCO_wdt device */ |
226 | unsigned int iTCO_version; /* TCO version/generation */ | 230 | /* TCO version/generation */ |
227 | unsigned long ACPIBASE; /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ | 231 | unsigned int iTCO_version; |
228 | unsigned long __iomem *gcs; /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2) */ | 232 | /* The cards ACPIBASE address (TCOBASE = ACPIBASE+0x60) */ |
229 | spinlock_t io_lock; /* the lock for io operations */ | 233 | unsigned long ACPIBASE; |
230 | struct pci_dev *pdev; /* the PCI-device */ | 234 | /* NO_REBOOT flag is Memory-Mapped GCS register bit 5 (TCO version 2)*/ |
235 | unsigned long __iomem *gcs; | ||
236 | /* the lock for io operations */ | ||
237 | spinlock_t io_lock; | ||
238 | /* the PCI-device */ | ||
239 | struct pci_dev *pdev; | ||
231 | } iTCO_wdt_private; | 240 | } iTCO_wdt_private; |
232 | 241 | ||
233 | static struct platform_device *iTCO_wdt_platform_device; /* the watchdog platform device */ | 242 | /* the watchdog platform device */ |
243 | static struct platform_device *iTCO_wdt_platform_device; | ||
234 | 244 | ||
235 | /* module parameters */ | 245 | /* module parameters */ |
236 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ | 246 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ |
@@ -240,22 +250,9 @@ MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<heartbeat<39 (TCO | |||
240 | 250 | ||
241 | static int nowayout = WATCHDOG_NOWAYOUT; | 251 | static int nowayout = WATCHDOG_NOWAYOUT; |
242 | module_param(nowayout, int, 0); | 252 | module_param(nowayout, int, 0); |
243 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 253 | MODULE_PARM_DESC(nowayout, |
244 | 254 | "Watchdog cannot be stopped once started (default=" | |
245 | /* iTCO Vendor Specific Support hooks */ | 255 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); |
246 | #ifdef CONFIG_ITCO_VENDOR_SUPPORT | ||
247 | extern void iTCO_vendor_pre_start(unsigned long, unsigned int); | ||
248 | extern void iTCO_vendor_pre_stop(unsigned long); | ||
249 | extern void iTCO_vendor_pre_keepalive(unsigned long, unsigned int); | ||
250 | extern void iTCO_vendor_pre_set_heartbeat(unsigned int); | ||
251 | extern int iTCO_vendor_check_noreboot_on(void); | ||
252 | #else | ||
253 | #define iTCO_vendor_pre_start(acpibase, heartbeat) {} | ||
254 | #define iTCO_vendor_pre_stop(acpibase) {} | ||
255 | #define iTCO_vendor_pre_keepalive(acpibase,heartbeat) {} | ||
256 | #define iTCO_vendor_pre_set_heartbeat(heartbeat) {} | ||
257 | #define iTCO_vendor_check_noreboot_on() 1 /* 1=check noreboot; 0=don't check */ | ||
258 | #endif | ||
259 | 256 | ||
260 | /* | 257 | /* |
261 | * Some TCO specific functions | 258 | * Some TCO specific functions |
@@ -369,11 +366,10 @@ static int iTCO_wdt_keepalive(void) | |||
369 | iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); | 366 | iTCO_vendor_pre_keepalive(iTCO_wdt_private.ACPIBASE, heartbeat); |
370 | 367 | ||
371 | /* Reload the timer by writing to the TCO Timer Counter register */ | 368 | /* Reload the timer by writing to the TCO Timer Counter register */ |
372 | if (iTCO_wdt_private.iTCO_version == 2) { | 369 | if (iTCO_wdt_private.iTCO_version == 2) |
373 | outw(0x01, TCO_RLD); | 370 | outw(0x01, TCO_RLD); |
374 | } else if (iTCO_wdt_private.iTCO_version == 1) { | 371 | else if (iTCO_wdt_private.iTCO_version == 1) |
375 | outb(0x01, TCO_RLD); | 372 | outb(0x01, TCO_RLD); |
376 | } | ||
377 | 373 | ||
378 | spin_unlock(&iTCO_wdt_private.io_lock); | 374 | spin_unlock(&iTCO_wdt_private.io_lock); |
379 | return 0; | 375 | return 0; |
@@ -425,7 +421,7 @@ static int iTCO_wdt_set_heartbeat(int t) | |||
425 | return 0; | 421 | return 0; |
426 | } | 422 | } |
427 | 423 | ||
428 | static int iTCO_wdt_get_timeleft (int *time_left) | 424 | static int iTCO_wdt_get_timeleft(int *time_left) |
429 | { | 425 | { |
430 | unsigned int val16; | 426 | unsigned int val16; |
431 | unsigned char val8; | 427 | unsigned char val8; |
@@ -454,7 +450,7 @@ static int iTCO_wdt_get_timeleft (int *time_left) | |||
454 | * /dev/watchdog handling | 450 | * /dev/watchdog handling |
455 | */ | 451 | */ |
456 | 452 | ||
457 | static int iTCO_wdt_open (struct inode *inode, struct file *file) | 453 | static int iTCO_wdt_open(struct inode *inode, struct file *file) |
458 | { | 454 | { |
459 | /* /dev/watchdog can only be opened once */ | 455 | /* /dev/watchdog can only be opened once */ |
460 | if (test_and_set_bit(0, &is_active)) | 456 | if (test_and_set_bit(0, &is_active)) |
@@ -468,7 +464,7 @@ static int iTCO_wdt_open (struct inode *inode, struct file *file) | |||
468 | return nonseekable_open(inode, file); | 464 | return nonseekable_open(inode, file); |
469 | } | 465 | } |
470 | 466 | ||
471 | static int iTCO_wdt_release (struct inode *inode, struct file *file) | 467 | static int iTCO_wdt_release(struct inode *inode, struct file *file) |
472 | { | 468 | { |
473 | /* | 469 | /* |
474 | * Shut off the timer. | 470 | * Shut off the timer. |
@@ -476,7 +472,8 @@ static int iTCO_wdt_release (struct inode *inode, struct file *file) | |||
476 | if (expect_release == 42) { | 472 | if (expect_release == 42) { |
477 | iTCO_wdt_stop(); | 473 | iTCO_wdt_stop(); |
478 | } else { | 474 | } else { |
479 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 475 | printk(KERN_CRIT PFX |
476 | "Unexpected close, not stopping watchdog!\n"); | ||
480 | iTCO_wdt_keepalive(); | 477 | iTCO_wdt_keepalive(); |
481 | } | 478 | } |
482 | clear_bit(0, &is_active); | 479 | clear_bit(0, &is_active); |
@@ -484,22 +481,23 @@ static int iTCO_wdt_release (struct inode *inode, struct file *file) | |||
484 | return 0; | 481 | return 0; |
485 | } | 482 | } |
486 | 483 | ||
487 | static ssize_t iTCO_wdt_write (struct file *file, const char __user *data, | 484 | static ssize_t iTCO_wdt_write(struct file *file, const char __user *data, |
488 | size_t len, loff_t * ppos) | 485 | size_t len, loff_t *ppos) |
489 | { | 486 | { |
490 | /* See if we got the magic character 'V' and reload the timer */ | 487 | /* See if we got the magic character 'V' and reload the timer */ |
491 | if (len) { | 488 | if (len) { |
492 | if (!nowayout) { | 489 | if (!nowayout) { |
493 | size_t i; | 490 | size_t i; |
494 | 491 | ||
495 | /* note: just in case someone wrote the magic character | 492 | /* note: just in case someone wrote the magic |
496 | * five months ago... */ | 493 | character five months ago... */ |
497 | expect_release = 0; | 494 | expect_release = 0; |
498 | 495 | ||
499 | /* scan to see whether or not we got the magic character */ | 496 | /* scan to see whether or not we got the |
497 | magic character */ | ||
500 | for (i = 0; i != len; i++) { | 498 | for (i = 0; i != len; i++) { |
501 | char c; | 499 | char c; |
502 | if (get_user(c, data+i)) | 500 | if (get_user(c, data + i)) |
503 | return -EFAULT; | 501 | return -EFAULT; |
504 | if (c == 'V') | 502 | if (c == 'V') |
505 | expect_release = 42; | 503 | expect_release = 42; |
@@ -512,8 +510,8 @@ static ssize_t iTCO_wdt_write (struct file *file, const char __user *data, | |||
512 | return len; | 510 | return len; |
513 | } | 511 | } |
514 | 512 | ||
515 | static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, | 513 | static long iTCO_wdt_ioctl(struct file *file, unsigned int cmd, |
516 | unsigned int cmd, unsigned long arg) | 514 | unsigned long arg) |
517 | { | 515 | { |
518 | int new_options, retval = -EINVAL; | 516 | int new_options, retval = -EINVAL; |
519 | int new_heartbeat; | 517 | int new_heartbeat; |
@@ -528,64 +526,52 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, | |||
528 | }; | 526 | }; |
529 | 527 | ||
530 | switch (cmd) { | 528 | switch (cmd) { |
531 | case WDIOC_GETSUPPORT: | 529 | case WDIOC_GETSUPPORT: |
532 | return copy_to_user(argp, &ident, | 530 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
533 | sizeof (ident)) ? -EFAULT : 0; | 531 | case WDIOC_GETSTATUS: |
534 | 532 | case WDIOC_GETBOOTSTATUS: | |
535 | case WDIOC_GETSTATUS: | 533 | return put_user(0, p); |
536 | case WDIOC_GETBOOTSTATUS: | 534 | |
537 | return put_user(0, p); | 535 | case WDIOC_SETOPTIONS: |
538 | 536 | { | |
539 | case WDIOC_KEEPALIVE: | 537 | if (get_user(new_options, p)) |
540 | iTCO_wdt_keepalive(); | 538 | return -EFAULT; |
541 | return 0; | 539 | |
542 | 540 | if (new_options & WDIOS_DISABLECARD) { | |
543 | case WDIOC_SETOPTIONS: | 541 | iTCO_wdt_stop(); |
544 | { | 542 | retval = 0; |
545 | if (get_user(new_options, p)) | ||
546 | return -EFAULT; | ||
547 | |||
548 | if (new_options & WDIOS_DISABLECARD) { | ||
549 | iTCO_wdt_stop(); | ||
550 | retval = 0; | ||
551 | } | ||
552 | |||
553 | if (new_options & WDIOS_ENABLECARD) { | ||
554 | iTCO_wdt_keepalive(); | ||
555 | iTCO_wdt_start(); | ||
556 | retval = 0; | ||
557 | } | ||
558 | |||
559 | return retval; | ||
560 | } | 543 | } |
561 | 544 | if (new_options & WDIOS_ENABLECARD) { | |
562 | case WDIOC_SETTIMEOUT: | ||
563 | { | ||
564 | if (get_user(new_heartbeat, p)) | ||
565 | return -EFAULT; | ||
566 | |||
567 | if (iTCO_wdt_set_heartbeat(new_heartbeat)) | ||
568 | return -EINVAL; | ||
569 | |||
570 | iTCO_wdt_keepalive(); | 545 | iTCO_wdt_keepalive(); |
571 | /* Fall */ | 546 | iTCO_wdt_start(); |
572 | } | 547 | retval = 0; |
573 | |||
574 | case WDIOC_GETTIMEOUT: | ||
575 | return put_user(heartbeat, p); | ||
576 | |||
577 | case WDIOC_GETTIMELEFT: | ||
578 | { | ||
579 | int time_left; | ||
580 | |||
581 | if (iTCO_wdt_get_timeleft(&time_left)) | ||
582 | return -EINVAL; | ||
583 | |||
584 | return put_user(time_left, p); | ||
585 | } | 548 | } |
549 | return retval; | ||
550 | } | ||
551 | case WDIOC_KEEPALIVE: | ||
552 | iTCO_wdt_keepalive(); | ||
553 | return 0; | ||
586 | 554 | ||
587 | default: | 555 | case WDIOC_SETTIMEOUT: |
588 | return -ENOTTY; | 556 | { |
557 | if (get_user(new_heartbeat, p)) | ||
558 | return -EFAULT; | ||
559 | if (iTCO_wdt_set_heartbeat(new_heartbeat)) | ||
560 | return -EINVAL; | ||
561 | iTCO_wdt_keepalive(); | ||
562 | /* Fall */ | ||
563 | } | ||
564 | case WDIOC_GETTIMEOUT: | ||
565 | return put_user(heartbeat, p); | ||
566 | case WDIOC_GETTIMELEFT: | ||
567 | { | ||
568 | int time_left; | ||
569 | if (iTCO_wdt_get_timeleft(&time_left)) | ||
570 | return -EINVAL; | ||
571 | return put_user(time_left, p); | ||
572 | } | ||
573 | default: | ||
574 | return -ENOTTY; | ||
589 | } | 575 | } |
590 | } | 576 | } |
591 | 577 | ||
@@ -594,12 +580,12 @@ static int iTCO_wdt_ioctl (struct inode *inode, struct file *file, | |||
594 | */ | 580 | */ |
595 | 581 | ||
596 | static const struct file_operations iTCO_wdt_fops = { | 582 | static const struct file_operations iTCO_wdt_fops = { |
597 | .owner = THIS_MODULE, | 583 | .owner = THIS_MODULE, |
598 | .llseek = no_llseek, | 584 | .llseek = no_llseek, |
599 | .write = iTCO_wdt_write, | 585 | .write = iTCO_wdt_write, |
600 | .ioctl = iTCO_wdt_ioctl, | 586 | .unlocked_ioctl = iTCO_wdt_ioctl, |
601 | .open = iTCO_wdt_open, | 587 | .open = iTCO_wdt_open, |
602 | .release = iTCO_wdt_release, | 588 | .release = iTCO_wdt_release, |
603 | }; | 589 | }; |
604 | 590 | ||
605 | static struct miscdevice iTCO_wdt_miscdev = { | 591 | static struct miscdevice iTCO_wdt_miscdev = { |
@@ -612,7 +598,8 @@ static struct miscdevice iTCO_wdt_miscdev = { | |||
612 | * Init & exit routines | 598 | * Init & exit routines |
613 | */ | 599 | */ |
614 | 600 | ||
615 | static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device_id *ent, struct platform_device *dev) | 601 | static int __devinit iTCO_wdt_init(struct pci_dev *pdev, |
602 | const struct pci_device_id *ent, struct platform_device *dev) | ||
616 | { | 603 | { |
617 | int ret; | 604 | int ret; |
618 | u32 base_address; | 605 | u32 base_address; |
@@ -632,17 +619,19 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device | |||
632 | pci_dev_put(pdev); | 619 | pci_dev_put(pdev); |
633 | return -ENODEV; | 620 | return -ENODEV; |
634 | } | 621 | } |
635 | iTCO_wdt_private.iTCO_version = iTCO_chipset_info[ent->driver_data].iTCO_version; | 622 | iTCO_wdt_private.iTCO_version = |
623 | iTCO_chipset_info[ent->driver_data].iTCO_version; | ||
636 | iTCO_wdt_private.ACPIBASE = base_address; | 624 | iTCO_wdt_private.ACPIBASE = base_address; |
637 | iTCO_wdt_private.pdev = pdev; | 625 | iTCO_wdt_private.pdev = pdev; |
638 | 626 | ||
639 | /* Get the Memory-Mapped GCS register, we need it for the NO_REBOOT flag (TCO v2) */ | 627 | /* Get the Memory-Mapped GCS register, we need it for the |
640 | /* To get access to it you have to read RCBA from PCI Config space 0xf0 | 628 | NO_REBOOT flag (TCO v2). To get access to it you have to |
641 | and use it as base. GCS = RCBA + ICH6_GCS(0x3410). */ | 629 | read RCBA from PCI Config space 0xf0 and use it as base. |
630 | GCS = RCBA + ICH6_GCS(0x3410). */ | ||
642 | if (iTCO_wdt_private.iTCO_version == 2) { | 631 | if (iTCO_wdt_private.iTCO_version == 2) { |
643 | pci_read_config_dword(pdev, 0xf0, &base_address); | 632 | pci_read_config_dword(pdev, 0xf0, &base_address); |
644 | RCBA = base_address & 0xffffc000; | 633 | RCBA = base_address & 0xffffc000; |
645 | iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410),4); | 634 | iTCO_wdt_private.gcs = ioremap((RCBA + 0x3410), 4); |
646 | } | 635 | } |
647 | 636 | ||
648 | /* Check chipset's NO_REBOOT bit */ | 637 | /* Check chipset's NO_REBOOT bit */ |
@@ -657,8 +646,8 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device | |||
657 | 646 | ||
658 | /* Set the TCO_EN bit in SMI_EN register */ | 647 | /* Set the TCO_EN bit in SMI_EN register */ |
659 | if (!request_region(SMI_EN, 4, "iTCO_wdt")) { | 648 | if (!request_region(SMI_EN, 4, "iTCO_wdt")) { |
660 | printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", | 649 | printk(KERN_ERR PFX |
661 | SMI_EN ); | 650 | "I/O address 0x%04lx already in use\n", SMI_EN); |
662 | ret = -EIO; | 651 | ret = -EIO; |
663 | goto out; | 652 | goto out; |
664 | } | 653 | } |
@@ -667,18 +656,20 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device | |||
667 | outl(val32, SMI_EN); | 656 | outl(val32, SMI_EN); |
668 | release_region(SMI_EN, 4); | 657 | release_region(SMI_EN, 4); |
669 | 658 | ||
670 | /* The TCO I/O registers reside in a 32-byte range pointed to by the TCOBASE value */ | 659 | /* The TCO I/O registers reside in a 32-byte range pointed to |
671 | if (!request_region (TCOBASE, 0x20, "iTCO_wdt")) { | 660 | by the TCOBASE value */ |
672 | printk (KERN_ERR PFX "I/O address 0x%04lx already in use\n", | 661 | if (!request_region(TCOBASE, 0x20, "iTCO_wdt")) { |
662 | printk(KERN_ERR PFX "I/O address 0x%04lx already in use\n", | ||
673 | TCOBASE); | 663 | TCOBASE); |
674 | ret = -EIO; | 664 | ret = -EIO; |
675 | goto out; | 665 | goto out; |
676 | } | 666 | } |
677 | 667 | ||
678 | printk(KERN_INFO PFX "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n", | 668 | printk(KERN_INFO PFX |
679 | iTCO_chipset_info[ent->driver_data].name, | 669 | "Found a %s TCO device (Version=%d, TCOBASE=0x%04lx)\n", |
680 | iTCO_chipset_info[ent->driver_data].iTCO_version, | 670 | iTCO_chipset_info[ent->driver_data].name, |
681 | TCOBASE); | 671 | iTCO_chipset_info[ent->driver_data].iTCO_version, |
672 | TCOBASE); | ||
682 | 673 | ||
683 | /* Clear out the (probably old) status */ | 674 | /* Clear out the (probably old) status */ |
684 | outb(0, TCO1_STS); | 675 | outb(0, TCO1_STS); |
@@ -687,27 +678,29 @@ static int __devinit iTCO_wdt_init(struct pci_dev *pdev, const struct pci_device | |||
687 | /* Make sure the watchdog is not running */ | 678 | /* Make sure the watchdog is not running */ |
688 | iTCO_wdt_stop(); | 679 | iTCO_wdt_stop(); |
689 | 680 | ||
690 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 681 | /* Check that the heartbeat value is within it's range; |
682 | if not reset to the default */ | ||
691 | if (iTCO_wdt_set_heartbeat(heartbeat)) { | 683 | if (iTCO_wdt_set_heartbeat(heartbeat)) { |
692 | iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); | 684 | iTCO_wdt_set_heartbeat(WATCHDOG_HEARTBEAT); |
693 | printk(KERN_INFO PFX "heartbeat value must be 2<heartbeat<39 (TCO v1) or 613 (TCO v2), using %d\n", | 685 | printk(KERN_INFO PFX "heartbeat value must be 2 < heartbeat < 39 (TCO v1) or 613 (TCO v2), using %d\n", |
694 | heartbeat); | 686 | heartbeat); |
695 | } | 687 | } |
696 | 688 | ||
697 | ret = misc_register(&iTCO_wdt_miscdev); | 689 | ret = misc_register(&iTCO_wdt_miscdev); |
698 | if (ret != 0) { | 690 | if (ret != 0) { |
699 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 691 | printk(KERN_ERR PFX |
700 | WATCHDOG_MINOR, ret); | 692 | "cannot register miscdev on minor=%d (err=%d)\n", |
693 | WATCHDOG_MINOR, ret); | ||
701 | goto unreg_region; | 694 | goto unreg_region; |
702 | } | 695 | } |
703 | 696 | ||
704 | printk (KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", | 697 | printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", |
705 | heartbeat, nowayout); | 698 | heartbeat, nowayout); |
706 | 699 | ||
707 | return 0; | 700 | return 0; |
708 | 701 | ||
709 | unreg_region: | 702 | unreg_region: |
710 | release_region (TCOBASE, 0x20); | 703 | release_region(TCOBASE, 0x20); |
711 | out: | 704 | out: |
712 | if (iTCO_wdt_private.iTCO_version == 2) | 705 | if (iTCO_wdt_private.iTCO_version == 2) |
713 | iounmap(iTCO_wdt_private.gcs); | 706 | iounmap(iTCO_wdt_private.gcs); |
@@ -796,7 +789,8 @@ static int __init iTCO_wdt_init_module(void) | |||
796 | if (err) | 789 | if (err) |
797 | return err; | 790 | return err; |
798 | 791 | ||
799 | iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); | 792 | iTCO_wdt_platform_device = platform_device_register_simple(DRV_NAME, |
793 | -1, NULL, 0); | ||
800 | if (IS_ERR(iTCO_wdt_platform_device)) { | 794 | if (IS_ERR(iTCO_wdt_platform_device)) { |
801 | err = PTR_ERR(iTCO_wdt_platform_device); | 795 | err = PTR_ERR(iTCO_wdt_platform_device); |
802 | goto unreg_platform_driver; | 796 | goto unreg_platform_driver; |
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c index 4b89f401691a..05a28106e8eb 100644 --- a/drivers/watchdog/ib700wdt.c +++ b/drivers/watchdog/ib700wdt.c | |||
@@ -41,9 +41,9 @@ | |||
41 | #include <linux/spinlock.h> | 41 | #include <linux/spinlock.h> |
42 | #include <linux/moduleparam.h> | 42 | #include <linux/moduleparam.h> |
43 | #include <linux/platform_device.h> | 43 | #include <linux/platform_device.h> |
44 | #include <linux/io.h> | ||
45 | #include <linux/uaccess.h> | ||
44 | 46 | ||
45 | #include <asm/io.h> | ||
46 | #include <asm/uaccess.h> | ||
47 | #include <asm/system.h> | 47 | #include <asm/system.h> |
48 | 48 | ||
49 | static struct platform_device *ibwdt_platform_device; | 49 | static struct platform_device *ibwdt_platform_device; |
@@ -120,15 +120,16 @@ static int wd_margin = WD_TIMO; | |||
120 | 120 | ||
121 | static int nowayout = WATCHDOG_NOWAYOUT; | 121 | static int nowayout = WATCHDOG_NOWAYOUT; |
122 | module_param(nowayout, int, 0); | 122 | module_param(nowayout, int, 0); |
123 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 123 | MODULE_PARM_DESC(nowayout, |
124 | "Watchdog cannot be stopped once started (default=" | ||
125 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
124 | 126 | ||
125 | 127 | ||
126 | /* | 128 | /* |
127 | * Watchdog Operations | 129 | * Watchdog Operations |
128 | */ | 130 | */ |
129 | 131 | ||
130 | static void | 132 | static void ibwdt_ping(void) |
131 | ibwdt_ping(void) | ||
132 | { | 133 | { |
133 | spin_lock(&ibwdt_lock); | 134 | spin_lock(&ibwdt_lock); |
134 | 135 | ||
@@ -138,16 +139,14 @@ ibwdt_ping(void) | |||
138 | spin_unlock(&ibwdt_lock); | 139 | spin_unlock(&ibwdt_lock); |
139 | } | 140 | } |
140 | 141 | ||
141 | static void | 142 | static void ibwdt_disable(void) |
142 | ibwdt_disable(void) | ||
143 | { | 143 | { |
144 | spin_lock(&ibwdt_lock); | 144 | spin_lock(&ibwdt_lock); |
145 | outb_p(0, WDT_STOP); | 145 | outb_p(0, WDT_STOP); |
146 | spin_unlock(&ibwdt_lock); | 146 | spin_unlock(&ibwdt_lock); |
147 | } | 147 | } |
148 | 148 | ||
149 | static int | 149 | static int ibwdt_set_heartbeat(int t) |
150 | ibwdt_set_heartbeat(int t) | ||
151 | { | 150 | { |
152 | int i; | 151 | int i; |
153 | 152 | ||
@@ -165,8 +164,8 @@ ibwdt_set_heartbeat(int t) | |||
165 | * /dev/watchdog handling | 164 | * /dev/watchdog handling |
166 | */ | 165 | */ |
167 | 166 | ||
168 | static ssize_t | 167 | static ssize_t ibwdt_write(struct file *file, const char __user *buf, |
169 | ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 168 | size_t count, loff_t *ppos) |
170 | { | 169 | { |
171 | if (count) { | 170 | if (count) { |
172 | if (!nowayout) { | 171 | if (!nowayout) { |
@@ -188,77 +187,71 @@ ibwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppo | |||
188 | return count; | 187 | return count; |
189 | } | 188 | } |
190 | 189 | ||
191 | static int | 190 | static long ibwdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
192 | ibwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
193 | unsigned long arg) | ||
194 | { | 191 | { |
195 | int new_margin; | 192 | int new_margin; |
196 | void __user *argp = (void __user *)arg; | 193 | void __user *argp = (void __user *)arg; |
197 | int __user *p = argp; | 194 | int __user *p = argp; |
198 | 195 | ||
199 | static struct watchdog_info ident = { | 196 | static struct watchdog_info ident = { |
200 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 197 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
198 | | WDIOF_MAGICCLOSE, | ||
201 | .firmware_version = 1, | 199 | .firmware_version = 1, |
202 | .identity = "IB700 WDT", | 200 | .identity = "IB700 WDT", |
203 | }; | 201 | }; |
204 | 202 | ||
205 | switch (cmd) { | 203 | switch (cmd) { |
206 | case WDIOC_GETSUPPORT: | 204 | case WDIOC_GETSUPPORT: |
207 | if (copy_to_user(argp, &ident, sizeof(ident))) | 205 | if (copy_to_user(argp, &ident, sizeof(ident))) |
208 | return -EFAULT; | 206 | return -EFAULT; |
209 | break; | 207 | break; |
210 | 208 | ||
211 | case WDIOC_GETSTATUS: | 209 | case WDIOC_GETSTATUS: |
212 | case WDIOC_GETBOOTSTATUS: | 210 | case WDIOC_GETBOOTSTATUS: |
213 | return put_user(0, p); | 211 | return put_user(0, p); |
214 | |||
215 | case WDIOC_KEEPALIVE: | ||
216 | ibwdt_ping(); | ||
217 | break; | ||
218 | |||
219 | case WDIOC_SETTIMEOUT: | ||
220 | if (get_user(new_margin, p)) | ||
221 | return -EFAULT; | ||
222 | if (ibwdt_set_heartbeat(new_margin)) | ||
223 | return -EINVAL; | ||
224 | ibwdt_ping(); | ||
225 | /* Fall */ | ||
226 | |||
227 | case WDIOC_GETTIMEOUT: | ||
228 | return put_user(wd_times[wd_margin], p); | ||
229 | 212 | ||
230 | case WDIOC_SETOPTIONS: | 213 | case WDIOC_SETOPTIONS: |
231 | { | 214 | { |
232 | int options, retval = -EINVAL; | 215 | int options, retval = -EINVAL; |
233 | 216 | ||
234 | if (get_user(options, p)) | 217 | if (get_user(options, p)) |
235 | return -EFAULT; | 218 | return -EFAULT; |
236 | 219 | ||
237 | if (options & WDIOS_DISABLECARD) { | 220 | if (options & WDIOS_DISABLECARD) { |
238 | ibwdt_disable(); | 221 | ibwdt_disable(); |
239 | retval = 0; | 222 | retval = 0; |
240 | } | 223 | } |
224 | if (options & WDIOS_ENABLECARD) { | ||
225 | ibwdt_ping(); | ||
226 | retval = 0; | ||
227 | } | ||
228 | return retval; | ||
229 | } | ||
230 | case WDIOC_KEEPALIVE: | ||
231 | ibwdt_ping(); | ||
232 | break; | ||
241 | 233 | ||
242 | if (options & WDIOS_ENABLECARD) { | 234 | case WDIOC_SETTIMEOUT: |
243 | ibwdt_ping(); | 235 | if (get_user(new_margin, p)) |
244 | retval = 0; | 236 | return -EFAULT; |
245 | } | 237 | if (ibwdt_set_heartbeat(new_margin)) |
238 | return -EINVAL; | ||
239 | ibwdt_ping(); | ||
240 | /* Fall */ | ||
246 | 241 | ||
247 | return retval; | 242 | case WDIOC_GETTIMEOUT: |
248 | } | 243 | return put_user(wd_times[wd_margin], p); |
249 | 244 | ||
250 | default: | 245 | default: |
251 | return -ENOTTY; | 246 | return -ENOTTY; |
252 | } | 247 | } |
253 | return 0; | 248 | return 0; |
254 | } | 249 | } |
255 | 250 | ||
256 | static int | 251 | static int ibwdt_open(struct inode *inode, struct file *file) |
257 | ibwdt_open(struct inode *inode, struct file *file) | ||
258 | { | 252 | { |
259 | if (test_and_set_bit(0, &ibwdt_is_open)) { | 253 | if (test_and_set_bit(0, &ibwdt_is_open)) |
260 | return -EBUSY; | 254 | return -EBUSY; |
261 | } | ||
262 | if (nowayout) | 255 | if (nowayout) |
263 | __module_get(THIS_MODULE); | 256 | __module_get(THIS_MODULE); |
264 | 257 | ||
@@ -267,13 +260,13 @@ ibwdt_open(struct inode *inode, struct file *file) | |||
267 | return nonseekable_open(inode, file); | 260 | return nonseekable_open(inode, file); |
268 | } | 261 | } |
269 | 262 | ||
270 | static int | 263 | static int ibwdt_close(struct inode *inode, struct file *file) |
271 | ibwdt_close(struct inode *inode, struct file *file) | ||
272 | { | 264 | { |
273 | if (expect_close == 42) { | 265 | if (expect_close == 42) { |
274 | ibwdt_disable(); | 266 | ibwdt_disable(); |
275 | } else { | 267 | } else { |
276 | printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); | 268 | printk(KERN_CRIT PFX |
269 | "WDT device closed unexpectedly. WDT will not stop!\n"); | ||
277 | ibwdt_ping(); | 270 | ibwdt_ping(); |
278 | } | 271 | } |
279 | clear_bit(0, &ibwdt_is_open); | 272 | clear_bit(0, &ibwdt_is_open); |
@@ -289,7 +282,7 @@ static const struct file_operations ibwdt_fops = { | |||
289 | .owner = THIS_MODULE, | 282 | .owner = THIS_MODULE, |
290 | .llseek = no_llseek, | 283 | .llseek = no_llseek, |
291 | .write = ibwdt_write, | 284 | .write = ibwdt_write, |
292 | .ioctl = ibwdt_ioctl, | 285 | .unlocked_ioctl = ibwdt_ioctl, |
293 | .open = ibwdt_open, | 286 | .open = ibwdt_open, |
294 | .release = ibwdt_close, | 287 | .release = ibwdt_close, |
295 | }; | 288 | }; |
@@ -310,21 +303,23 @@ static int __devinit ibwdt_probe(struct platform_device *dev) | |||
310 | 303 | ||
311 | #if WDT_START != WDT_STOP | 304 | #if WDT_START != WDT_STOP |
312 | if (!request_region(WDT_STOP, 1, "IB700 WDT")) { | 305 | if (!request_region(WDT_STOP, 1, "IB700 WDT")) { |
313 | printk (KERN_ERR PFX "STOP method I/O %X is not available.\n", WDT_STOP); | 306 | printk(KERN_ERR PFX "STOP method I/O %X is not available.\n", |
307 | WDT_STOP); | ||
314 | res = -EIO; | 308 | res = -EIO; |
315 | goto out_nostopreg; | 309 | goto out_nostopreg; |
316 | } | 310 | } |
317 | #endif | 311 | #endif |
318 | 312 | ||
319 | if (!request_region(WDT_START, 1, "IB700 WDT")) { | 313 | if (!request_region(WDT_START, 1, "IB700 WDT")) { |
320 | printk (KERN_ERR PFX "START method I/O %X is not available.\n", WDT_START); | 314 | printk(KERN_ERR PFX "START method I/O %X is not available.\n", |
315 | WDT_START); | ||
321 | res = -EIO; | 316 | res = -EIO; |
322 | goto out_nostartreg; | 317 | goto out_nostartreg; |
323 | } | 318 | } |
324 | 319 | ||
325 | res = misc_register(&ibwdt_miscdev); | 320 | res = misc_register(&ibwdt_miscdev); |
326 | if (res) { | 321 | if (res) { |
327 | printk (KERN_ERR PFX "failed to register misc device\n"); | 322 | printk(KERN_ERR PFX "failed to register misc device\n"); |
328 | goto out_nomisc; | 323 | goto out_nomisc; |
329 | } | 324 | } |
330 | return 0; | 325 | return 0; |
@@ -342,9 +337,9 @@ out_nostopreg: | |||
342 | static int __devexit ibwdt_remove(struct platform_device *dev) | 337 | static int __devexit ibwdt_remove(struct platform_device *dev) |
343 | { | 338 | { |
344 | misc_deregister(&ibwdt_miscdev); | 339 | misc_deregister(&ibwdt_miscdev); |
345 | release_region(WDT_START,1); | 340 | release_region(WDT_START, 1); |
346 | #if WDT_START != WDT_STOP | 341 | #if WDT_START != WDT_STOP |
347 | release_region(WDT_STOP,1); | 342 | release_region(WDT_STOP, 1); |
348 | #endif | 343 | #endif |
349 | return 0; | 344 | return 0; |
350 | } | 345 | } |
@@ -369,13 +364,15 @@ static int __init ibwdt_init(void) | |||
369 | { | 364 | { |
370 | int err; | 365 | int err; |
371 | 366 | ||
372 | printk(KERN_INFO PFX "WDT driver for IB700 single board computer initialising.\n"); | 367 | printk(KERN_INFO PFX |
368 | "WDT driver for IB700 single board computer initialising.\n"); | ||
373 | 369 | ||
374 | err = platform_driver_register(&ibwdt_driver); | 370 | err = platform_driver_register(&ibwdt_driver); |
375 | if (err) | 371 | if (err) |
376 | return err; | 372 | return err; |
377 | 373 | ||
378 | ibwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); | 374 | ibwdt_platform_device = platform_device_register_simple(DRV_NAME, |
375 | -1, NULL, 0); | ||
379 | if (IS_ERR(ibwdt_platform_device)) { | 376 | if (IS_ERR(ibwdt_platform_device)) { |
380 | err = PTR_ERR(ibwdt_platform_device); | 377 | err = PTR_ERR(ibwdt_platform_device); |
381 | goto unreg_platform_driver; | 378 | goto unreg_platform_driver; |
diff --git a/drivers/watchdog/ibmasr.c b/drivers/watchdog/ibmasr.c index 94155f6136c2..b82405cfb4cd 100644 --- a/drivers/watchdog/ibmasr.c +++ b/drivers/watchdog/ibmasr.c | |||
@@ -19,9 +19,8 @@ | |||
19 | #include <linux/miscdevice.h> | 19 | #include <linux/miscdevice.h> |
20 | #include <linux/watchdog.h> | 20 | #include <linux/watchdog.h> |
21 | #include <linux/dmi.h> | 21 | #include <linux/dmi.h> |
22 | 22 | #include <linux/io.h> | |
23 | #include <asm/io.h> | 23 | #include <linux/uaccess.h> |
24 | #include <asm/uaccess.h> | ||
25 | 24 | ||
26 | 25 | ||
27 | enum { | 26 | enum { |
@@ -70,10 +69,13 @@ static char asr_expect_close; | |||
70 | static unsigned int asr_type, asr_base, asr_length; | 69 | static unsigned int asr_type, asr_base, asr_length; |
71 | static unsigned int asr_read_addr, asr_write_addr; | 70 | static unsigned int asr_read_addr, asr_write_addr; |
72 | static unsigned char asr_toggle_mask, asr_disable_mask; | 71 | static unsigned char asr_toggle_mask, asr_disable_mask; |
72 | static spinlock_t asr_lock; | ||
73 | 73 | ||
74 | static void asr_toggle(void) | 74 | static void __asr_toggle(void) |
75 | { | 75 | { |
76 | unsigned char reg = inb(asr_read_addr); | 76 | unsigned char reg; |
77 | |||
78 | reg = inb(asr_read_addr); | ||
77 | 79 | ||
78 | outb(reg & ~asr_toggle_mask, asr_write_addr); | 80 | outb(reg & ~asr_toggle_mask, asr_write_addr); |
79 | reg = inb(asr_read_addr); | 81 | reg = inb(asr_read_addr); |
@@ -83,12 +85,21 @@ static void asr_toggle(void) | |||
83 | 85 | ||
84 | outb(reg & ~asr_toggle_mask, asr_write_addr); | 86 | outb(reg & ~asr_toggle_mask, asr_write_addr); |
85 | reg = inb(asr_read_addr); | 87 | reg = inb(asr_read_addr); |
88 | spin_unlock(&asr_lock); | ||
89 | } | ||
90 | |||
91 | static void asr_toggle(void) | ||
92 | { | ||
93 | spin_lock(&asr_lock); | ||
94 | __asr_toggle(); | ||
95 | spin_unlock(&asr_lock); | ||
86 | } | 96 | } |
87 | 97 | ||
88 | static void asr_enable(void) | 98 | static void asr_enable(void) |
89 | { | 99 | { |
90 | unsigned char reg; | 100 | unsigned char reg; |
91 | 101 | ||
102 | spin_lock(&asr_lock); | ||
92 | if (asr_type == ASMTYPE_TOPAZ) { | 103 | if (asr_type == ASMTYPE_TOPAZ) { |
93 | /* asr_write_addr == asr_read_addr */ | 104 | /* asr_write_addr == asr_read_addr */ |
94 | reg = inb(asr_read_addr); | 105 | reg = inb(asr_read_addr); |
@@ -99,17 +110,21 @@ static void asr_enable(void) | |||
99 | * First make sure the hardware timer is reset by toggling | 110 | * First make sure the hardware timer is reset by toggling |
100 | * ASR hardware timer line. | 111 | * ASR hardware timer line. |
101 | */ | 112 | */ |
102 | asr_toggle(); | 113 | __asr_toggle(); |
103 | 114 | ||
104 | reg = inb(asr_read_addr); | 115 | reg = inb(asr_read_addr); |
105 | outb(reg & ~asr_disable_mask, asr_write_addr); | 116 | outb(reg & ~asr_disable_mask, asr_write_addr); |
106 | } | 117 | } |
107 | reg = inb(asr_read_addr); | 118 | reg = inb(asr_read_addr); |
119 | spin_unlock(&asr_lock); | ||
108 | } | 120 | } |
109 | 121 | ||
110 | static void asr_disable(void) | 122 | static void asr_disable(void) |
111 | { | 123 | { |
112 | unsigned char reg = inb(asr_read_addr); | 124 | unsigned char reg; |
125 | |||
126 | spin_lock(&asr_lock); | ||
127 | reg = inb(asr_read_addr); | ||
113 | 128 | ||
114 | if (asr_type == ASMTYPE_TOPAZ) | 129 | if (asr_type == ASMTYPE_TOPAZ) |
115 | /* asr_write_addr == asr_read_addr */ | 130 | /* asr_write_addr == asr_read_addr */ |
@@ -122,6 +137,7 @@ static void asr_disable(void) | |||
122 | outb(reg | asr_disable_mask, asr_write_addr); | 137 | outb(reg | asr_disable_mask, asr_write_addr); |
123 | } | 138 | } |
124 | reg = inb(asr_read_addr); | 139 | reg = inb(asr_read_addr); |
140 | spin_unlock(&asr_lock); | ||
125 | } | 141 | } |
126 | 142 | ||
127 | static int __init asr_get_base_address(void) | 143 | static int __init asr_get_base_address(void) |
@@ -133,7 +149,8 @@ static int __init asr_get_base_address(void) | |||
133 | 149 | ||
134 | switch (asr_type) { | 150 | switch (asr_type) { |
135 | case ASMTYPE_TOPAZ: | 151 | case ASMTYPE_TOPAZ: |
136 | /* SELECT SuperIO CHIP FOR QUERYING (WRITE 0x07 TO BOTH 0x2E and 0x2F) */ | 152 | /* SELECT SuperIO CHIP FOR QUERYING |
153 | (WRITE 0x07 TO BOTH 0x2E and 0x2F) */ | ||
137 | outb(0x07, 0x2e); | 154 | outb(0x07, 0x2e); |
138 | outb(0x07, 0x2f); | 155 | outb(0x07, 0x2f); |
139 | 156 | ||
@@ -154,14 +171,26 @@ static int __init asr_get_base_address(void) | |||
154 | 171 | ||
155 | case ASMTYPE_JASPER: | 172 | case ASMTYPE_JASPER: |
156 | type = "Jaspers "; | 173 | type = "Jaspers "; |
157 | 174 | #if 0 | |
158 | /* FIXME: need to use pci_config_lock here, but it's not exported */ | 175 | u32 r; |
176 | /* Suggested fix */ | ||
177 | pdev = pci_get_bus_and_slot(0, DEVFN(0x1f, 0)); | ||
178 | if (pdev == NULL) | ||
179 | return -ENODEV; | ||
180 | pci_read_config_dword(pdev, 0x58, &r); | ||
181 | asr_base = r & 0xFFFE; | ||
182 | pci_dev_put(pdev); | ||
183 | #else | ||
184 | /* FIXME: need to use pci_config_lock here, | ||
185 | but it's not exported */ | ||
159 | 186 | ||
160 | /* spin_lock_irqsave(&pci_config_lock, flags);*/ | 187 | /* spin_lock_irqsave(&pci_config_lock, flags);*/ |
161 | 188 | ||
162 | /* Select the SuperIO chip in the PCI I/O port register */ | 189 | /* Select the SuperIO chip in the PCI I/O port register */ |
163 | outl(0x8000f858, 0xcf8); | 190 | outl(0x8000f858, 0xcf8); |
164 | 191 | ||
192 | /* BUS 0, Slot 1F, fnc 0, offset 58 */ | ||
193 | |||
165 | /* | 194 | /* |
166 | * Read the base address for the SuperIO chip. | 195 | * Read the base address for the SuperIO chip. |
167 | * Only the lower 16 bits are valid, but the address is word | 196 | * Only the lower 16 bits are valid, but the address is word |
@@ -170,7 +199,7 @@ static int __init asr_get_base_address(void) | |||
170 | asr_base = inl(0xcfc) & 0xfffe; | 199 | asr_base = inl(0xcfc) & 0xfffe; |
171 | 200 | ||
172 | /* spin_unlock_irqrestore(&pci_config_lock, flags);*/ | 201 | /* spin_unlock_irqrestore(&pci_config_lock, flags);*/ |
173 | 202 | #endif | |
174 | asr_read_addr = asr_write_addr = | 203 | asr_read_addr = asr_write_addr = |
175 | asr_base + JASPER_ASR_REG_OFFSET; | 204 | asr_base + JASPER_ASR_REG_OFFSET; |
176 | asr_toggle_mask = JASPER_ASR_TOGGLE_MASK; | 205 | asr_toggle_mask = JASPER_ASR_TOGGLE_MASK; |
@@ -241,66 +270,57 @@ static ssize_t asr_write(struct file *file, const char __user *buf, | |||
241 | return count; | 270 | return count; |
242 | } | 271 | } |
243 | 272 | ||
244 | static int asr_ioctl(struct inode *inode, struct file *file, | 273 | static long asr_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
245 | unsigned int cmd, unsigned long arg) | ||
246 | { | 274 | { |
247 | static const struct watchdog_info ident = { | 275 | static const struct watchdog_info ident = { |
248 | .options = WDIOF_KEEPALIVEPING | | 276 | .options = WDIOF_KEEPALIVEPING | |
249 | WDIOF_MAGICCLOSE, | 277 | WDIOF_MAGICCLOSE, |
250 | .identity = "IBM ASR" | 278 | .identity = "IBM ASR", |
251 | }; | 279 | }; |
252 | void __user *argp = (void __user *)arg; | 280 | void __user *argp = (void __user *)arg; |
253 | int __user *p = argp; | 281 | int __user *p = argp; |
254 | int heartbeat; | 282 | int heartbeat; |
255 | 283 | ||
256 | switch (cmd) { | 284 | switch (cmd) { |
257 | case WDIOC_GETSUPPORT: | 285 | case WDIOC_GETSUPPORT: |
258 | return copy_to_user(argp, &ident, sizeof(ident)) ? | 286 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
259 | -EFAULT : 0; | 287 | case WDIOC_GETSTATUS: |
260 | 288 | case WDIOC_GETBOOTSTATUS: | |
261 | case WDIOC_GETSTATUS: | 289 | return put_user(0, p); |
262 | case WDIOC_GETBOOTSTATUS: | 290 | case WDIOC_SETOPTIONS: |
263 | return put_user(0, p); | 291 | { |
264 | 292 | int new_options, retval = -EINVAL; | |
265 | case WDIOC_KEEPALIVE: | 293 | if (get_user(new_options, p)) |
294 | return -EFAULT; | ||
295 | if (new_options & WDIOS_DISABLECARD) { | ||
296 | asr_disable(); | ||
297 | retval = 0; | ||
298 | } | ||
299 | if (new_options & WDIOS_ENABLECARD) { | ||
300 | asr_enable(); | ||
266 | asr_toggle(); | 301 | asr_toggle(); |
267 | return 0; | 302 | retval = 0; |
268 | |||
269 | /* | ||
270 | * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT | ||
271 | * and WDIOC_GETTIMEOUT always returns 256. | ||
272 | */ | ||
273 | case WDIOC_GETTIMEOUT: | ||
274 | heartbeat = 256; | ||
275 | return put_user(heartbeat, p); | ||
276 | |||
277 | case WDIOC_SETOPTIONS: { | ||
278 | int new_options, retval = -EINVAL; | ||
279 | |||
280 | if (get_user(new_options, p)) | ||
281 | return -EFAULT; | ||
282 | |||
283 | if (new_options & WDIOS_DISABLECARD) { | ||
284 | asr_disable(); | ||
285 | retval = 0; | ||
286 | } | ||
287 | |||
288 | if (new_options & WDIOS_ENABLECARD) { | ||
289 | asr_enable(); | ||
290 | asr_toggle(); | ||
291 | retval = 0; | ||
292 | } | ||
293 | |||
294 | return retval; | ||
295 | } | 303 | } |
304 | return retval; | ||
305 | } | ||
306 | case WDIOC_KEEPALIVE: | ||
307 | asr_toggle(); | ||
308 | return 0; | ||
309 | /* | ||
310 | * The hardware has a fixed timeout value, so no WDIOC_SETTIMEOUT | ||
311 | * and WDIOC_GETTIMEOUT always returns 256. | ||
312 | */ | ||
313 | case WDIOC_GETTIMEOUT: | ||
314 | heartbeat = 256; | ||
315 | return put_user(heartbeat, p); | ||
316 | default: | ||
317 | return -ENOTTY; | ||
296 | } | 318 | } |
297 | |||
298 | return -ENOTTY; | ||
299 | } | 319 | } |
300 | 320 | ||
301 | static int asr_open(struct inode *inode, struct file *file) | 321 | static int asr_open(struct inode *inode, struct file *file) |
302 | { | 322 | { |
303 | if(test_and_set_bit(0, &asr_is_open)) | 323 | if (test_and_set_bit(0, &asr_is_open)) |
304 | return -EBUSY; | 324 | return -EBUSY; |
305 | 325 | ||
306 | asr_toggle(); | 326 | asr_toggle(); |
@@ -314,7 +334,8 @@ static int asr_release(struct inode *inode, struct file *file) | |||
314 | if (asr_expect_close == 42) | 334 | if (asr_expect_close == 42) |
315 | asr_disable(); | 335 | asr_disable(); |
316 | else { | 336 | else { |
317 | printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); | 337 | printk(KERN_CRIT PFX |
338 | "unexpected close, not stopping watchdog!\n"); | ||
318 | asr_toggle(); | 339 | asr_toggle(); |
319 | } | 340 | } |
320 | clear_bit(0, &asr_is_open); | 341 | clear_bit(0, &asr_is_open); |
@@ -323,12 +344,12 @@ static int asr_release(struct inode *inode, struct file *file) | |||
323 | } | 344 | } |
324 | 345 | ||
325 | static const struct file_operations asr_fops = { | 346 | static const struct file_operations asr_fops = { |
326 | .owner = THIS_MODULE, | 347 | .owner = THIS_MODULE, |
327 | .llseek = no_llseek, | 348 | .llseek = no_llseek, |
328 | .write = asr_write, | 349 | .write = asr_write, |
329 | .ioctl = asr_ioctl, | 350 | .unlocked_ioctl = asr_ioctl, |
330 | .open = asr_open, | 351 | .open = asr_open, |
331 | .release = asr_release, | 352 | .release = asr_release, |
332 | }; | 353 | }; |
333 | 354 | ||
334 | static struct miscdevice asr_miscdev = { | 355 | static struct miscdevice asr_miscdev = { |
@@ -367,6 +388,8 @@ static int __init ibmasr_init(void) | |||
367 | if (!asr_type) | 388 | if (!asr_type) |
368 | return -ENODEV; | 389 | return -ENODEV; |
369 | 390 | ||
391 | spin_lock_init(&asr_lock); | ||
392 | |||
370 | rc = asr_get_base_address(); | 393 | rc = asr_get_base_address(); |
371 | if (rc) | 394 | if (rc) |
372 | return rc; | 395 | return rc; |
@@ -395,7 +418,9 @@ module_init(ibmasr_init); | |||
395 | module_exit(ibmasr_exit); | 418 | module_exit(ibmasr_exit); |
396 | 419 | ||
397 | module_param(nowayout, int, 0); | 420 | module_param(nowayout, int, 0); |
398 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 421 | MODULE_PARM_DESC(nowayout, |
422 | "Watchdog cannot be stopped once started (default=" | ||
423 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
399 | 424 | ||
400 | MODULE_DESCRIPTION("IBM Automatic Server Restart driver"); | 425 | MODULE_DESCRIPTION("IBM Automatic Server Restart driver"); |
401 | MODULE_AUTHOR("Andrey Panin"); | 426 | MODULE_AUTHOR("Andrey Panin"); |
diff --git a/drivers/watchdog/indydog.c b/drivers/watchdog/indydog.c index 788245bdaa7f..73c9e7992feb 100644 --- a/drivers/watchdog/indydog.c +++ b/drivers/watchdog/indydog.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22 | 2 | * IndyDog 0.3 A Hardware Watchdog Device for SGI IP22 |
3 | * | 3 | * |
4 | * (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, All Rights Reserved. | 4 | * (c) Copyright 2002 Guido Guenther <agx@sigxcpu.org>, |
5 | * All Rights Reserved. | ||
5 | * | 6 | * |
6 | * This program is free software; you can redistribute it and/or | 7 | * This program is free software; you can redistribute it and/or |
7 | * modify it under the terms of the GNU General Public License | 8 | * modify it under the terms of the GNU General Public License |
@@ -22,32 +23,42 @@ | |||
22 | #include <linux/notifier.h> | 23 | #include <linux/notifier.h> |
23 | #include <linux/reboot.h> | 24 | #include <linux/reboot.h> |
24 | #include <linux/init.h> | 25 | #include <linux/init.h> |
25 | #include <asm/uaccess.h> | 26 | #include <linux/uaccess.h> |
26 | #include <asm/sgi/mc.h> | 27 | #include <asm/sgi/mc.h> |
27 | 28 | ||
28 | #define PFX "indydog: " | 29 | #define PFX "indydog: " |
29 | static int indydog_alive; | 30 | static unsigned long indydog_alive; |
31 | static spinlock_t indydog_lock; | ||
30 | 32 | ||
31 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ | 33 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ |
32 | 34 | ||
33 | static int nowayout = WATCHDOG_NOWAYOUT; | 35 | static int nowayout = WATCHDOG_NOWAYOUT; |
34 | module_param(nowayout, int, 0); | 36 | module_param(nowayout, int, 0); |
35 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 37 | MODULE_PARM_DESC(nowayout, |
38 | "Watchdog cannot be stopped once started (default=" | ||
39 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
36 | 40 | ||
37 | static void indydog_start(void) | 41 | static void indydog_start(void) |
38 | { | 42 | { |
39 | u32 mc_ctrl0 = sgimc->cpuctrl0; | 43 | u32 mc_ctrl0; |
40 | 44 | ||
45 | spin_lock(&indydog_lock); | ||
46 | mc_ctrl0 = sgimc->cpuctrl0; | ||
41 | mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG; | 47 | mc_ctrl0 = sgimc->cpuctrl0 | SGIMC_CCTRL0_WDOG; |
42 | sgimc->cpuctrl0 = mc_ctrl0; | 48 | sgimc->cpuctrl0 = mc_ctrl0; |
49 | spin_unlock(&indydog_lock); | ||
43 | } | 50 | } |
44 | 51 | ||
45 | static void indydog_stop(void) | 52 | static void indydog_stop(void) |
46 | { | 53 | { |
47 | u32 mc_ctrl0 = sgimc->cpuctrl0; | 54 | u32 mc_ctrl0; |
48 | 55 | ||
56 | spin_lock(&indydog_lock); | ||
57 | |||
58 | mc_ctrl0 = sgimc->cpuctrl0; | ||
49 | mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; | 59 | mc_ctrl0 &= ~SGIMC_CCTRL0_WDOG; |
50 | sgimc->cpuctrl0 = mc_ctrl0; | 60 | sgimc->cpuctrl0 = mc_ctrl0; |
61 | spin_unlock(&indydog_lock); | ||
51 | 62 | ||
52 | printk(KERN_INFO PFX "Stopped watchdog timer.\n"); | 63 | printk(KERN_INFO PFX "Stopped watchdog timer.\n"); |
53 | } | 64 | } |
@@ -62,7 +73,7 @@ static void indydog_ping(void) | |||
62 | */ | 73 | */ |
63 | static int indydog_open(struct inode *inode, struct file *file) | 74 | static int indydog_open(struct inode *inode, struct file *file) |
64 | { | 75 | { |
65 | if (indydog_alive) | 76 | if (test_and_set_bit(0, &indydog_alive)) |
66 | return -EBUSY; | 77 | return -EBUSY; |
67 | 78 | ||
68 | if (nowayout) | 79 | if (nowayout) |
@@ -84,23 +95,21 @@ static int indydog_release(struct inode *inode, struct file *file) | |||
84 | * Lock it in if it's a module and we defined ...NOWAYOUT */ | 95 | * Lock it in if it's a module and we defined ...NOWAYOUT */ |
85 | if (!nowayout) | 96 | if (!nowayout) |
86 | indydog_stop(); /* Turn the WDT off */ | 97 | indydog_stop(); /* Turn the WDT off */ |
87 | 98 | clear_bit(0, &indydog_alive); | |
88 | indydog_alive = 0; | ||
89 | |||
90 | return 0; | 99 | return 0; |
91 | } | 100 | } |
92 | 101 | ||
93 | static ssize_t indydog_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 102 | static ssize_t indydog_write(struct file *file, const char *data, |
103 | size_t len, loff_t *ppos) | ||
94 | { | 104 | { |
95 | /* Refresh the timer. */ | 105 | /* Refresh the timer. */ |
96 | if (len) { | 106 | if (len) |
97 | indydog_ping(); | 107 | indydog_ping(); |
98 | } | ||
99 | return len; | 108 | return len; |
100 | } | 109 | } |
101 | 110 | ||
102 | static int indydog_ioctl(struct inode *inode, struct file *file, | 111 | static long indydog_ioctl(struct file *file, unsigned int cmd, |
103 | unsigned int cmd, unsigned long arg) | 112 | unsigned long arg) |
104 | { | 113 | { |
105 | int options, retval = -EINVAL; | 114 | int options, retval = -EINVAL; |
106 | static struct watchdog_info ident = { | 115 | static struct watchdog_info ident = { |
@@ -111,42 +120,40 @@ static int indydog_ioctl(struct inode *inode, struct file *file, | |||
111 | }; | 120 | }; |
112 | 121 | ||
113 | switch (cmd) { | 122 | switch (cmd) { |
114 | default: | 123 | case WDIOC_GETSUPPORT: |
115 | return -ENOTTY; | 124 | if (copy_to_user((struct watchdog_info *)arg, |
116 | case WDIOC_GETSUPPORT: | 125 | &ident, sizeof(ident))) |
117 | if (copy_to_user((struct watchdog_info *)arg, | 126 | return -EFAULT; |
118 | &ident, sizeof(ident))) | 127 | return 0; |
119 | return -EFAULT; | 128 | case WDIOC_GETSTATUS: |
120 | return 0; | 129 | case WDIOC_GETBOOTSTATUS: |
121 | case WDIOC_GETSTATUS: | 130 | return put_user(0, (int *)arg); |
122 | case WDIOC_GETBOOTSTATUS: | 131 | case WDIOC_SETOPTIONS: |
123 | return put_user(0,(int *)arg); | 132 | { |
124 | case WDIOC_KEEPALIVE: | 133 | if (get_user(options, (int *)arg)) |
125 | indydog_ping(); | 134 | return -EFAULT; |
126 | return 0; | 135 | if (options & WDIOS_DISABLECARD) { |
127 | case WDIOC_GETTIMEOUT: | 136 | indydog_stop(); |
128 | return put_user(WATCHDOG_TIMEOUT,(int *)arg); | 137 | retval = 0; |
129 | case WDIOC_SETOPTIONS: | ||
130 | { | ||
131 | if (get_user(options, (int *)arg)) | ||
132 | return -EFAULT; | ||
133 | |||
134 | if (options & WDIOS_DISABLECARD) { | ||
135 | indydog_stop(); | ||
136 | retval = 0; | ||
137 | } | ||
138 | |||
139 | if (options & WDIOS_ENABLECARD) { | ||
140 | indydog_start(); | ||
141 | retval = 0; | ||
142 | } | ||
143 | |||
144 | return retval; | ||
145 | } | 138 | } |
139 | if (options & WDIOS_ENABLECARD) { | ||
140 | indydog_start(); | ||
141 | retval = 0; | ||
142 | } | ||
143 | return retval; | ||
144 | } | ||
145 | case WDIOC_KEEPALIVE: | ||
146 | indydog_ping(); | ||
147 | return 0; | ||
148 | case WDIOC_GETTIMEOUT: | ||
149 | return put_user(WATCHDOG_TIMEOUT, (int *)arg); | ||
150 | default: | ||
151 | return -ENOTTY; | ||
146 | } | 152 | } |
147 | } | 153 | } |
148 | 154 | ||
149 | static int indydog_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 155 | static int indydog_notify_sys(struct notifier_block *this, |
156 | unsigned long code, void *unused) | ||
150 | { | 157 | { |
151 | if (code == SYS_DOWN || code == SYS_HALT) | 158 | if (code == SYS_DOWN || code == SYS_HALT) |
152 | indydog_stop(); /* Turn the WDT off */ | 159 | indydog_stop(); /* Turn the WDT off */ |
@@ -158,7 +165,7 @@ static const struct file_operations indydog_fops = { | |||
158 | .owner = THIS_MODULE, | 165 | .owner = THIS_MODULE, |
159 | .llseek = no_llseek, | 166 | .llseek = no_llseek, |
160 | .write = indydog_write, | 167 | .write = indydog_write, |
161 | .ioctl = indydog_ioctl, | 168 | .unlocked_ioctl = indydog_ioctl, |
162 | .open = indydog_open, | 169 | .open = indydog_open, |
163 | .release = indydog_release, | 170 | .release = indydog_release, |
164 | }; | 171 | }; |
@@ -180,17 +187,20 @@ static int __init watchdog_init(void) | |||
180 | { | 187 | { |
181 | int ret; | 188 | int ret; |
182 | 189 | ||
190 | spin_lock_init(&indydog_lock); | ||
191 | |||
183 | ret = register_reboot_notifier(&indydog_notifier); | 192 | ret = register_reboot_notifier(&indydog_notifier); |
184 | if (ret) { | 193 | if (ret) { |
185 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 194 | printk(KERN_ERR PFX |
186 | ret); | 195 | "cannot register reboot notifier (err=%d)\n", ret); |
187 | return ret; | 196 | return ret; |
188 | } | 197 | } |
189 | 198 | ||
190 | ret = misc_register(&indydog_miscdev); | 199 | ret = misc_register(&indydog_miscdev); |
191 | if (ret) { | 200 | if (ret) { |
192 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 201 | printk(KERN_ERR PFX |
193 | WATCHDOG_MINOR, ret); | 202 | "cannot register miscdev on minor=%d (err=%d)\n", |
203 | WATCHDOG_MINOR, ret); | ||
194 | unregister_reboot_notifier(&indydog_notifier); | 204 | unregister_reboot_notifier(&indydog_notifier); |
195 | return ret; | 205 | return ret; |
196 | } | 206 | } |
diff --git a/drivers/watchdog/iop_wdt.c b/drivers/watchdog/iop_wdt.c index 1946dd06d815..96eb2cbe5874 100644 --- a/drivers/watchdog/iop_wdt.c +++ b/drivers/watchdog/iop_wdt.c | |||
@@ -37,6 +37,7 @@ | |||
37 | static int nowayout = WATCHDOG_NOWAYOUT; | 37 | static int nowayout = WATCHDOG_NOWAYOUT; |
38 | static unsigned long wdt_status; | 38 | static unsigned long wdt_status; |
39 | static unsigned long boot_status; | 39 | static unsigned long boot_status; |
40 | static spinlock_t wdt_lock; | ||
40 | 41 | ||
41 | #define WDT_IN_USE 0 | 42 | #define WDT_IN_USE 0 |
42 | #define WDT_OK_TO_CLOSE 1 | 43 | #define WDT_OK_TO_CLOSE 1 |
@@ -68,8 +69,10 @@ static void wdt_enable(void) | |||
68 | /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF | 69 | /* Arm and enable the Timer to starting counting down from 0xFFFF.FFFF |
69 | * Takes approx. 10.7s to timeout | 70 | * Takes approx. 10.7s to timeout |
70 | */ | 71 | */ |
72 | spin_lock(&wdt_lock); | ||
71 | write_wdtcr(IOP_WDTCR_EN_ARM); | 73 | write_wdtcr(IOP_WDTCR_EN_ARM); |
72 | write_wdtcr(IOP_WDTCR_EN); | 74 | write_wdtcr(IOP_WDTCR_EN); |
75 | spin_unlock(&wdt_lock); | ||
73 | } | 76 | } |
74 | 77 | ||
75 | /* returns 0 if the timer was successfully disabled */ | 78 | /* returns 0 if the timer was successfully disabled */ |
@@ -77,9 +80,11 @@ static int wdt_disable(void) | |||
77 | { | 80 | { |
78 | /* Stop Counting */ | 81 | /* Stop Counting */ |
79 | if (wdt_supports_disable()) { | 82 | if (wdt_supports_disable()) { |
83 | spin_lock(&wdt_lock); | ||
80 | write_wdtcr(IOP_WDTCR_DIS_ARM); | 84 | write_wdtcr(IOP_WDTCR_DIS_ARM); |
81 | write_wdtcr(IOP_WDTCR_DIS); | 85 | write_wdtcr(IOP_WDTCR_DIS); |
82 | clear_bit(WDT_ENABLED, &wdt_status); | 86 | clear_bit(WDT_ENABLED, &wdt_status); |
87 | spin_unlock(&wdt_lock); | ||
83 | printk(KERN_INFO "WATCHDOG: Disabled\n"); | 88 | printk(KERN_INFO "WATCHDOG: Disabled\n"); |
84 | return 0; | 89 | return 0; |
85 | } else | 90 | } else |
@@ -92,16 +97,12 @@ static int iop_wdt_open(struct inode *inode, struct file *file) | |||
92 | return -EBUSY; | 97 | return -EBUSY; |
93 | 98 | ||
94 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 99 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
95 | |||
96 | wdt_enable(); | 100 | wdt_enable(); |
97 | |||
98 | set_bit(WDT_ENABLED, &wdt_status); | 101 | set_bit(WDT_ENABLED, &wdt_status); |
99 | |||
100 | return nonseekable_open(inode, file); | 102 | return nonseekable_open(inode, file); |
101 | } | 103 | } |
102 | 104 | ||
103 | static ssize_t | 105 | static ssize_t iop_wdt_write(struct file *file, const char *data, size_t len, |
104 | iop_wdt_write(struct file *file, const char *data, size_t len, | ||
105 | loff_t *ppos) | 106 | loff_t *ppos) |
106 | { | 107 | { |
107 | if (len) { | 108 | if (len) { |
@@ -121,46 +122,35 @@ iop_wdt_write(struct file *file, const char *data, size_t len, | |||
121 | } | 122 | } |
122 | wdt_enable(); | 123 | wdt_enable(); |
123 | } | 124 | } |
124 | |||
125 | return len; | 125 | return len; |
126 | } | 126 | } |
127 | 127 | ||
128 | static struct watchdog_info ident = { | 128 | static const struct watchdog_info ident = { |
129 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | 129 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, |
130 | .identity = "iop watchdog", | 130 | .identity = "iop watchdog", |
131 | }; | 131 | }; |
132 | 132 | ||
133 | static int | 133 | static long iop_wdt_ioctl(struct file *file, |
134 | iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 134 | unsigned int cmd, unsigned long arg) |
135 | unsigned long arg) | ||
136 | { | 135 | { |
137 | int options; | 136 | int options; |
138 | int ret = -ENOTTY; | 137 | int ret = -ENOTTY; |
138 | int __user *argp = (int __user *)arg; | ||
139 | 139 | ||
140 | switch (cmd) { | 140 | switch (cmd) { |
141 | case WDIOC_GETSUPPORT: | 141 | case WDIOC_GETSUPPORT: |
142 | if (copy_to_user | 142 | if (copy_to_user(argp, &ident, sizeof ident)) |
143 | ((struct watchdog_info *)arg, &ident, sizeof ident)) | ||
144 | ret = -EFAULT; | 143 | ret = -EFAULT; |
145 | else | 144 | else |
146 | ret = 0; | 145 | ret = 0; |
147 | break; | 146 | break; |
148 | 147 | ||
149 | case WDIOC_GETSTATUS: | 148 | case WDIOC_GETSTATUS: |
150 | ret = put_user(0, (int *)arg); | 149 | ret = put_user(0, argp); |
151 | break; | 150 | break; |
152 | 151 | ||
153 | case WDIOC_GETBOOTSTATUS: | 152 | case WDIOC_GETBOOTSTATUS: |
154 | ret = put_user(boot_status, (int *)arg); | 153 | ret = put_user(boot_status, argp); |
155 | break; | ||
156 | |||
157 | case WDIOC_GETTIMEOUT: | ||
158 | ret = put_user(iop_watchdog_timeout(), (int *)arg); | ||
159 | break; | ||
160 | |||
161 | case WDIOC_KEEPALIVE: | ||
162 | wdt_enable(); | ||
163 | ret = 0; | ||
164 | break; | 154 | break; |
165 | 155 | ||
166 | case WDIOC_SETOPTIONS: | 156 | case WDIOC_SETOPTIONS: |
@@ -177,14 +167,21 @@ iop_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
177 | } else | 167 | } else |
178 | ret = 0; | 168 | ret = 0; |
179 | } | 169 | } |
180 | |||
181 | if (options & WDIOS_ENABLECARD) { | 170 | if (options & WDIOS_ENABLECARD) { |
182 | wdt_enable(); | 171 | wdt_enable(); |
183 | ret = 0; | 172 | ret = 0; |
184 | } | 173 | } |
185 | break; | 174 | break; |
186 | } | ||
187 | 175 | ||
176 | case WDIOC_KEEPALIVE: | ||
177 | wdt_enable(); | ||
178 | ret = 0; | ||
179 | break; | ||
180 | |||
181 | case WDIOC_GETTIMEOUT: | ||
182 | ret = put_user(iop_watchdog_timeout(), argp); | ||
183 | break; | ||
184 | } | ||
188 | return ret; | 185 | return ret; |
189 | } | 186 | } |
190 | 187 | ||
@@ -214,7 +211,7 @@ static const struct file_operations iop_wdt_fops = { | |||
214 | .owner = THIS_MODULE, | 211 | .owner = THIS_MODULE, |
215 | .llseek = no_llseek, | 212 | .llseek = no_llseek, |
216 | .write = iop_wdt_write, | 213 | .write = iop_wdt_write, |
217 | .ioctl = iop_wdt_ioctl, | 214 | .unlocked_ioctl = iop_wdt_ioctl, |
218 | .open = iop_wdt_open, | 215 | .open = iop_wdt_open, |
219 | .release = iop_wdt_release, | 216 | .release = iop_wdt_release, |
220 | }; | 217 | }; |
@@ -229,10 +226,8 @@ static int __init iop_wdt_init(void) | |||
229 | { | 226 | { |
230 | int ret; | 227 | int ret; |
231 | 228 | ||
232 | ret = misc_register(&iop_wdt_miscdev); | 229 | spin_lock_init(&wdt_lock); |
233 | if (ret == 0) | 230 | |
234 | printk("iop watchdog timer: timeout %lu sec\n", | ||
235 | iop_watchdog_timeout()); | ||
236 | 231 | ||
237 | /* check if the reset was caused by the watchdog timer */ | 232 | /* check if the reset was caused by the watchdog timer */ |
238 | boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0; | 233 | boot_status = (read_rcsr() & IOP_RCSR_WDT) ? WDIOF_CARDRESET : 0; |
@@ -242,6 +237,13 @@ static int __init iop_wdt_init(void) | |||
242 | */ | 237 | */ |
243 | write_wdtsr(IOP13XX_WDTCR_IB_RESET); | 238 | write_wdtsr(IOP13XX_WDTCR_IB_RESET); |
244 | 239 | ||
240 | /* Register after we have the device set up so we cannot race | ||
241 | with an open */ | ||
242 | ret = misc_register(&iop_wdt_miscdev); | ||
243 | if (ret == 0) | ||
244 | printk(KERN_INFO "iop watchdog timer: timeout %lu sec\n", | ||
245 | iop_watchdog_timeout()); | ||
246 | |||
245 | return ret; | 247 | return ret; |
246 | } | 248 | } |
247 | 249 | ||
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index 51bfd5721833..2270ee07c01b 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c | |||
@@ -221,7 +221,7 @@ static ssize_t it8712f_wdt_write(struct file *file, const char __user *data, | |||
221 | expect_close = 0; | 221 | expect_close = 0; |
222 | for (i = 0; i < len; ++i) { | 222 | for (i = 0; i < len; ++i) { |
223 | char c; | 223 | char c; |
224 | if (get_user(c, data+i)) | 224 | if (get_user(c, data + i)) |
225 | return -EFAULT; | 225 | return -EFAULT; |
226 | if (c == 'V') | 226 | if (c == 'V') |
227 | expect_close = 42; | 227 | expect_close = 42; |
@@ -244,8 +244,6 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, | |||
244 | int value; | 244 | int value; |
245 | 245 | ||
246 | switch (cmd) { | 246 | switch (cmd) { |
247 | default: | ||
248 | return -ENOTTY; | ||
249 | case WDIOC_GETSUPPORT: | 247 | case WDIOC_GETSUPPORT: |
250 | if (copy_to_user(argp, &ident, sizeof(ident))) | 248 | if (copy_to_user(argp, &ident, sizeof(ident))) |
251 | return -EFAULT; | 249 | return -EFAULT; |
@@ -284,6 +282,8 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, | |||
284 | if (put_user(margin, p)) | 282 | if (put_user(margin, p)) |
285 | return -EFAULT; | 283 | return -EFAULT; |
286 | return 0; | 284 | return 0; |
285 | default: | ||
286 | return -ENOTTY; | ||
287 | } | 287 | } |
288 | } | 288 | } |
289 | 289 | ||
diff --git a/drivers/watchdog/ixp2000_wdt.c b/drivers/watchdog/ixp2000_wdt.c index 4226dae7d260..4f4b35a20d84 100644 --- a/drivers/watchdog/ixp2000_wdt.c +++ b/drivers/watchdog/ixp2000_wdt.c | |||
@@ -25,42 +25,44 @@ | |||
25 | #include <linux/watchdog.h> | 25 | #include <linux/watchdog.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/bitops.h> | 27 | #include <linux/bitops.h> |
28 | 28 | #include <linux/uaccess.h> | |
29 | #include <mach/hardware.h> | 29 | #include <mach/hardware.h> |
30 | #include <asm/uaccess.h> | ||
31 | 30 | ||
32 | static int nowayout = WATCHDOG_NOWAYOUT; | 31 | static int nowayout = WATCHDOG_NOWAYOUT; |
33 | static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ | 32 | static unsigned int heartbeat = 60; /* (secs) Default is 1 minute */ |
34 | static unsigned long wdt_status; | 33 | static unsigned long wdt_status; |
34 | static spinlock_t wdt_lock; | ||
35 | 35 | ||
36 | #define WDT_IN_USE 0 | 36 | #define WDT_IN_USE 0 |
37 | #define WDT_OK_TO_CLOSE 1 | 37 | #define WDT_OK_TO_CLOSE 1 |
38 | 38 | ||
39 | static unsigned long wdt_tick_rate; | 39 | static unsigned long wdt_tick_rate; |
40 | 40 | ||
41 | static void | 41 | static void wdt_enable(void) |
42 | wdt_enable(void) | ||
43 | { | 42 | { |
43 | spin_lock(&wdt_lock); | ||
44 | ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE); | 44 | ixp2000_reg_write(IXP2000_RESET0, *(IXP2000_RESET0) | WDT_RESET_ENABLE); |
45 | ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE); | 45 | ixp2000_reg_write(IXP2000_TWDE, WDT_ENABLE); |
46 | ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); | 46 | ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); |
47 | ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE); | 47 | ixp2000_reg_write(IXP2000_T4_CTL, TIMER_DIVIDER_256 | TIMER_ENABLE); |
48 | spin_unlock(&wdt_lock); | ||
48 | } | 49 | } |
49 | 50 | ||
50 | static void | 51 | static void wdt_disable(void) |
51 | wdt_disable(void) | ||
52 | { | 52 | { |
53 | spin_lock(&wdt_lock); | ||
53 | ixp2000_reg_write(IXP2000_T4_CTL, 0); | 54 | ixp2000_reg_write(IXP2000_T4_CTL, 0); |
55 | spin_unlock(&wdt_lock); | ||
54 | } | 56 | } |
55 | 57 | ||
56 | static void | 58 | static void wdt_keepalive(void) |
57 | wdt_keepalive(void) | ||
58 | { | 59 | { |
60 | spin_lock(&wdt_lock); | ||
59 | ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); | 61 | ixp2000_reg_write(IXP2000_T4_CLD, heartbeat * wdt_tick_rate); |
62 | spin_unlock(&wdt_lock); | ||
60 | } | 63 | } |
61 | 64 | ||
62 | static int | 65 | static int ixp2000_wdt_open(struct inode *inode, struct file *file) |
63 | ixp2000_wdt_open(struct inode *inode, struct file *file) | ||
64 | { | 66 | { |
65 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | 67 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) |
66 | return -EBUSY; | 68 | return -EBUSY; |
@@ -72,8 +74,8 @@ ixp2000_wdt_open(struct inode *inode, struct file *file) | |||
72 | return nonseekable_open(inode, file); | 74 | return nonseekable_open(inode, file); |
73 | } | 75 | } |
74 | 76 | ||
75 | static ssize_t | 77 | static ssize_t ixp2000_wdt_write(struct file *file, const char *data, |
76 | ixp2000_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 78 | size_t len, loff_t *ppos) |
77 | { | 79 | { |
78 | if (len) { | 80 | if (len) { |
79 | if (!nowayout) { | 81 | if (!nowayout) { |
@@ -103,9 +105,8 @@ static struct watchdog_info ident = { | |||
103 | .identity = "IXP2000 Watchdog", | 105 | .identity = "IXP2000 Watchdog", |
104 | }; | 106 | }; |
105 | 107 | ||
106 | static int | 108 | static long ixp2000_wdt_ioctl(struct file *file, unsigned int cmd, |
107 | ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 109 | unsigned long arg) |
108 | unsigned long arg) | ||
109 | { | 110 | { |
110 | int ret = -ENOTTY; | 111 | int ret = -ENOTTY; |
111 | int time; | 112 | int time; |
@@ -124,6 +125,11 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
124 | ret = put_user(0, (int *)arg); | 125 | ret = put_user(0, (int *)arg); |
125 | break; | 126 | break; |
126 | 127 | ||
128 | case WDIOC_KEEPALIVE: | ||
129 | wdt_enable(); | ||
130 | ret = 0; | ||
131 | break; | ||
132 | |||
127 | case WDIOC_SETTIMEOUT: | 133 | case WDIOC_SETTIMEOUT: |
128 | ret = get_user(time, (int *)arg); | 134 | ret = get_user(time, (int *)arg); |
129 | if (ret) | 135 | if (ret) |
@@ -141,26 +147,18 @@ ixp2000_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
141 | case WDIOC_GETTIMEOUT: | 147 | case WDIOC_GETTIMEOUT: |
142 | ret = put_user(heartbeat, (int *)arg); | 148 | ret = put_user(heartbeat, (int *)arg); |
143 | break; | 149 | break; |
144 | |||
145 | case WDIOC_KEEPALIVE: | ||
146 | wdt_enable(); | ||
147 | ret = 0; | ||
148 | break; | ||
149 | } | 150 | } |
150 | 151 | ||
151 | return ret; | 152 | return ret; |
152 | } | 153 | } |
153 | 154 | ||
154 | static int | 155 | static int ixp2000_wdt_release(struct inode *inode, struct file *file) |
155 | ixp2000_wdt_release(struct inode *inode, struct file *file) | ||
156 | { | 156 | { |
157 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { | 157 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) |
158 | wdt_disable(); | 158 | wdt_disable(); |
159 | } else { | 159 | else |
160 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | 160 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " |
161 | "timer will not stop\n"); | 161 | "timer will not stop\n"); |
162 | } | ||
163 | |||
164 | clear_bit(WDT_IN_USE, &wdt_status); | 162 | clear_bit(WDT_IN_USE, &wdt_status); |
165 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 163 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
166 | 164 | ||
@@ -168,18 +166,16 @@ ixp2000_wdt_release(struct inode *inode, struct file *file) | |||
168 | } | 166 | } |
169 | 167 | ||
170 | 168 | ||
171 | static const struct file_operations ixp2000_wdt_fops = | 169 | static const struct file_operations ixp2000_wdt_fops = { |
172 | { | ||
173 | .owner = THIS_MODULE, | 170 | .owner = THIS_MODULE, |
174 | .llseek = no_llseek, | 171 | .llseek = no_llseek, |
175 | .write = ixp2000_wdt_write, | 172 | .write = ixp2000_wdt_write, |
176 | .ioctl = ixp2000_wdt_ioctl, | 173 | .unlocked_ioctl = ixp2000_wdt_ioctl, |
177 | .open = ixp2000_wdt_open, | 174 | .open = ixp2000_wdt_open, |
178 | .release = ixp2000_wdt_release, | 175 | .release = ixp2000_wdt_release, |
179 | }; | 176 | }; |
180 | 177 | ||
181 | static struct miscdevice ixp2000_wdt_miscdev = | 178 | static struct miscdevice ixp2000_wdt_miscdev = { |
182 | { | ||
183 | .minor = WATCHDOG_MINOR, | 179 | .minor = WATCHDOG_MINOR, |
184 | .name = "watchdog", | 180 | .name = "watchdog", |
185 | .fops = &ixp2000_wdt_fops, | 181 | .fops = &ixp2000_wdt_fops, |
@@ -191,9 +187,8 @@ static int __init ixp2000_wdt_init(void) | |||
191 | printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n"); | 187 | printk(KERN_INFO "Unable to use IXP2000 watchdog due to IXP2800 erratum #25.\n"); |
192 | return -EIO; | 188 | return -EIO; |
193 | } | 189 | } |
194 | |||
195 | wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; | 190 | wdt_tick_rate = (*IXP2000_T1_CLD * HZ) / 256; |
196 | 191 | spin_lock_init(&wdt_lock); | |
197 | return misc_register(&ixp2000_wdt_miscdev); | 192 | return misc_register(&ixp2000_wdt_miscdev); |
198 | } | 193 | } |
199 | 194 | ||
diff --git a/drivers/watchdog/ixp4xx_wdt.c b/drivers/watchdog/ixp4xx_wdt.c index 2313fad0dbb1..41264a5f1731 100644 --- a/drivers/watchdog/ixp4xx_wdt.c +++ b/drivers/watchdog/ixp4xx_wdt.c | |||
@@ -22,48 +22,47 @@ | |||
22 | #include <linux/watchdog.h> | 22 | #include <linux/watchdog.h> |
23 | #include <linux/init.h> | 23 | #include <linux/init.h> |
24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
25 | 25 | #include <linux/uaccess.h> | |
26 | #include <mach/hardware.h> | 26 | #include <mach/hardware.h> |
27 | #include <asm/uaccess.h> | ||
28 | 27 | ||
29 | static int nowayout = WATCHDOG_NOWAYOUT; | 28 | static int nowayout = WATCHDOG_NOWAYOUT; |
30 | static int heartbeat = 60; /* (secs) Default is 1 minute */ | 29 | static int heartbeat = 60; /* (secs) Default is 1 minute */ |
31 | static unsigned long wdt_status; | 30 | static unsigned long wdt_status; |
32 | static unsigned long boot_status; | 31 | static unsigned long boot_status; |
32 | static spin_lock_t wdt_lock; | ||
33 | 33 | ||
34 | #define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL) | 34 | #define WDT_TICK_RATE (IXP4XX_PERIPHERAL_BUS_CLOCK * 1000000UL) |
35 | 35 | ||
36 | #define WDT_IN_USE 0 | 36 | #define WDT_IN_USE 0 |
37 | #define WDT_OK_TO_CLOSE 1 | 37 | #define WDT_OK_TO_CLOSE 1 |
38 | 38 | ||
39 | static void | 39 | static void wdt_enable(void) |
40 | wdt_enable(void) | ||
41 | { | 40 | { |
41 | spin_lock(&wdt_lock); | ||
42 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; | 42 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; |
43 | *IXP4XX_OSWE = 0; | 43 | *IXP4XX_OSWE = 0; |
44 | *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat; | 44 | *IXP4XX_OSWT = WDT_TICK_RATE * heartbeat; |
45 | *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE; | 45 | *IXP4XX_OSWE = IXP4XX_WDT_COUNT_ENABLE | IXP4XX_WDT_RESET_ENABLE; |
46 | *IXP4XX_OSWK = 0; | 46 | *IXP4XX_OSWK = 0; |
47 | spin_unlock(&wdt_lock); | ||
47 | } | 48 | } |
48 | 49 | ||
49 | static void | 50 | static void wdt_disable(void) |
50 | wdt_disable(void) | ||
51 | { | 51 | { |
52 | spin_lock(&wdt_lock); | ||
52 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; | 53 | *IXP4XX_OSWK = IXP4XX_WDT_KEY; |
53 | *IXP4XX_OSWE = 0; | 54 | *IXP4XX_OSWE = 0; |
54 | *IXP4XX_OSWK = 0; | 55 | *IXP4XX_OSWK = 0; |
56 | spin_unlock(&wdt_lock); | ||
55 | } | 57 | } |
56 | 58 | ||
57 | static int | 59 | static int ixp4xx_wdt_open(struct inode *inode, struct file *file) |
58 | ixp4xx_wdt_open(struct inode *inode, struct file *file) | ||
59 | { | 60 | { |
60 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | 61 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) |
61 | return -EBUSY; | 62 | return -EBUSY; |
62 | 63 | ||
63 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 64 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
64 | |||
65 | wdt_enable(); | 65 | wdt_enable(); |
66 | |||
67 | return nonseekable_open(inode, file); | 66 | return nonseekable_open(inode, file); |
68 | } | 67 | } |
69 | 68 | ||
@@ -87,7 +86,6 @@ ixp4xx_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | |||
87 | } | 86 | } |
88 | wdt_enable(); | 87 | wdt_enable(); |
89 | } | 88 | } |
90 | |||
91 | return len; | 89 | return len; |
92 | } | 90 | } |
93 | 91 | ||
@@ -98,9 +96,8 @@ static struct watchdog_info ident = { | |||
98 | }; | 96 | }; |
99 | 97 | ||
100 | 98 | ||
101 | static int | 99 | static long ixp4xx_wdt_ioctl(struct file *file, unsigned int cmd, |
102 | ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 100 | unsigned long arg) |
103 | unsigned long arg) | ||
104 | { | 101 | { |
105 | int ret = -ENOTTY; | 102 | int ret = -ENOTTY; |
106 | int time; | 103 | int time; |
@@ -119,6 +116,11 @@ ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
119 | ret = put_user(boot_status, (int *)arg); | 116 | ret = put_user(boot_status, (int *)arg); |
120 | break; | 117 | break; |
121 | 118 | ||
119 | case WDIOC_KEEPALIVE: | ||
120 | wdt_enable(); | ||
121 | ret = 0; | ||
122 | break; | ||
123 | |||
122 | case WDIOC_SETTIMEOUT: | 124 | case WDIOC_SETTIMEOUT: |
123 | ret = get_user(time, (int *)arg); | 125 | ret = get_user(time, (int *)arg); |
124 | if (ret) | 126 | if (ret) |
@@ -136,25 +138,17 @@ ixp4xx_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
136 | case WDIOC_GETTIMEOUT: | 138 | case WDIOC_GETTIMEOUT: |
137 | ret = put_user(heartbeat, (int *)arg); | 139 | ret = put_user(heartbeat, (int *)arg); |
138 | break; | 140 | break; |
139 | |||
140 | case WDIOC_KEEPALIVE: | ||
141 | wdt_enable(); | ||
142 | ret = 0; | ||
143 | break; | ||
144 | } | 141 | } |
145 | return ret; | 142 | return ret; |
146 | } | 143 | } |
147 | 144 | ||
148 | static int | 145 | static int ixp4xx_wdt_release(struct inode *inode, struct file *file) |
149 | ixp4xx_wdt_release(struct inode *inode, struct file *file) | ||
150 | { | 146 | { |
151 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) { | 147 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) |
152 | wdt_disable(); | 148 | wdt_disable(); |
153 | } else { | 149 | else |
154 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | 150 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " |
155 | "timer will not stop\n"); | 151 | "timer will not stop\n"); |
156 | } | ||
157 | |||
158 | clear_bit(WDT_IN_USE, &wdt_status); | 152 | clear_bit(WDT_IN_USE, &wdt_status); |
159 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | 153 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); |
160 | 154 | ||
@@ -162,18 +156,16 @@ ixp4xx_wdt_release(struct inode *inode, struct file *file) | |||
162 | } | 156 | } |
163 | 157 | ||
164 | 158 | ||
165 | static const struct file_operations ixp4xx_wdt_fops = | 159 | static const struct file_operations ixp4xx_wdt_fops = { |
166 | { | ||
167 | .owner = THIS_MODULE, | 160 | .owner = THIS_MODULE, |
168 | .llseek = no_llseek, | 161 | .llseek = no_llseek, |
169 | .write = ixp4xx_wdt_write, | 162 | .write = ixp4xx_wdt_write, |
170 | .ioctl = ixp4xx_wdt_ioctl, | 163 | .unlocked_ioctl = ixp4xx_wdt_ioctl, |
171 | .open = ixp4xx_wdt_open, | 164 | .open = ixp4xx_wdt_open, |
172 | .release = ixp4xx_wdt_release, | 165 | .release = ixp4xx_wdt_release, |
173 | }; | 166 | }; |
174 | 167 | ||
175 | static struct miscdevice ixp4xx_wdt_miscdev = | 168 | static struct miscdevice ixp4xx_wdt_miscdev = { |
176 | { | ||
177 | .minor = WATCHDOG_MINOR, | 169 | .minor = WATCHDOG_MINOR, |
178 | .name = "watchdog", | 170 | .name = "watchdog", |
179 | .fops = &ixp4xx_wdt_fops, | 171 | .fops = &ixp4xx_wdt_fops, |
@@ -186,19 +178,18 @@ static int __init ixp4xx_wdt_init(void) | |||
186 | 178 | ||
187 | asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :); | 179 | asm("mrc p15, 0, %0, cr0, cr0, 0;" : "=r"(processor_id) :); |
188 | if (!(processor_id & 0xf) && !cpu_is_ixp46x()) { | 180 | if (!(processor_id & 0xf) && !cpu_is_ixp46x()) { |
189 | printk("IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected - " | 181 | printk(KERN_ERR "IXP4XXX Watchdog: Rev. A0 IXP42x CPU detected" |
190 | "watchdog disabled\n"); | 182 | " - watchdog disabled\n"); |
191 | 183 | ||
192 | return -ENODEV; | 184 | return -ENODEV; |
193 | } | 185 | } |
194 | 186 | spin_lock_init(&wdt_lock); | |
195 | ret = misc_register(&ixp4xx_wdt_miscdev); | ||
196 | if (ret == 0) | ||
197 | printk("IXP4xx Watchdog Timer: heartbeat %d sec\n", heartbeat); | ||
198 | |||
199 | boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ? | 187 | boot_status = (*IXP4XX_OSST & IXP4XX_OSST_TIMER_WARM_RESET) ? |
200 | WDIOF_CARDRESET : 0; | 188 | WDIOF_CARDRESET : 0; |
201 | 189 | ret = misc_register(&ixp4xx_wdt_miscdev); | |
190 | if (ret == 0) | ||
191 | printk(KERN_INFO "IXP4xx Watchdog Timer: heartbeat %d sec\n", | ||
192 | heartbeat); | ||
202 | return ret; | 193 | return ret; |
203 | } | 194 | } |
204 | 195 | ||
diff --git a/drivers/watchdog/ks8695_wdt.c b/drivers/watchdog/ks8695_wdt.c index d21a6407fe21..0b798fdaa378 100644 --- a/drivers/watchdog/ks8695_wdt.c +++ b/drivers/watchdog/ks8695_wdt.c | |||
@@ -19,11 +19,10 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/types.h> | 20 | #include <linux/types.h> |
21 | #include <linux/watchdog.h> | 21 | #include <linux/watchdog.h> |
22 | #include <asm/io.h> | 22 | #include <linux/io.h> |
23 | #include <asm/uaccess.h> | 23 | #include <linux/uaccess.h> |
24 | #include <mach/regs-timer.h> | 24 | #include <mach/regs-timer.h> |
25 | 25 | ||
26 | |||
27 | #define WDT_DEFAULT_TIME 5 /* seconds */ | 26 | #define WDT_DEFAULT_TIME 5 /* seconds */ |
28 | #define WDT_MAX_TIME 171 /* seconds */ | 27 | #define WDT_MAX_TIME 171 /* seconds */ |
29 | 28 | ||
@@ -31,38 +30,44 @@ static int wdt_time = WDT_DEFAULT_TIME; | |||
31 | static int nowayout = WATCHDOG_NOWAYOUT; | 30 | static int nowayout = WATCHDOG_NOWAYOUT; |
32 | 31 | ||
33 | module_param(wdt_time, int, 0); | 32 | module_param(wdt_time, int, 0); |
34 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default="__MODULE_STRING(WDT_DEFAULT_TIME) ")"); | 33 | MODULE_PARM_DESC(wdt_time, "Watchdog time in seconds. (default=" |
34 | __MODULE_STRING(WDT_DEFAULT_TIME) ")"); | ||
35 | 35 | ||
36 | #ifdef CONFIG_WATCHDOG_NOWAYOUT | 36 | #ifdef CONFIG_WATCHDOG_NOWAYOUT |
37 | module_param(nowayout, int, 0); | 37 | module_param(nowayout, int, 0); |
38 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 38 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" |
39 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
39 | #endif | 40 | #endif |
40 | 41 | ||
41 | 42 | ||
42 | static unsigned long ks8695wdt_busy; | 43 | static unsigned long ks8695wdt_busy; |
44 | static spinlock_t ks8695_lock; | ||
43 | 45 | ||
44 | /* ......................................................................... */ | 46 | /* ......................................................................... */ |
45 | 47 | ||
46 | /* | 48 | /* |
47 | * Disable the watchdog. | 49 | * Disable the watchdog. |
48 | */ | 50 | */ |
49 | static void inline ks8695_wdt_stop(void) | 51 | static inline void ks8695_wdt_stop(void) |
50 | { | 52 | { |
51 | unsigned long tmcon; | 53 | unsigned long tmcon; |
52 | 54 | ||
55 | spin_lock(&ks8695_lock); | ||
53 | /* disable timer0 */ | 56 | /* disable timer0 */ |
54 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | 57 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); |
55 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | 58 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); |
59 | spin_unlock(&ks8695_lock); | ||
56 | } | 60 | } |
57 | 61 | ||
58 | /* | 62 | /* |
59 | * Enable and reset the watchdog. | 63 | * Enable and reset the watchdog. |
60 | */ | 64 | */ |
61 | static void inline ks8695_wdt_start(void) | 65 | static inline void ks8695_wdt_start(void) |
62 | { | 66 | { |
63 | unsigned long tmcon; | 67 | unsigned long tmcon; |
64 | unsigned long tval = wdt_time * CLOCK_TICK_RATE; | 68 | unsigned long tval = wdt_time * CLOCK_TICK_RATE; |
65 | 69 | ||
70 | spin_lock(&ks8695_lock); | ||
66 | /* disable timer0 */ | 71 | /* disable timer0 */ |
67 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | 72 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); |
68 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | 73 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); |
@@ -73,19 +78,22 @@ static void inline ks8695_wdt_start(void) | |||
73 | /* re-enable timer0 */ | 78 | /* re-enable timer0 */ |
74 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | 79 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); |
75 | __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | 80 | __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); |
81 | spin_unlock(&ks8695_lock); | ||
76 | } | 82 | } |
77 | 83 | ||
78 | /* | 84 | /* |
79 | * Reload the watchdog timer. (ie, pat the watchdog) | 85 | * Reload the watchdog timer. (ie, pat the watchdog) |
80 | */ | 86 | */ |
81 | static void inline ks8695_wdt_reload(void) | 87 | static inline void ks8695_wdt_reload(void) |
82 | { | 88 | { |
83 | unsigned long tmcon; | 89 | unsigned long tmcon; |
84 | 90 | ||
91 | spin_lock(&ks8695_lock); | ||
85 | /* disable, then re-enable timer0 */ | 92 | /* disable, then re-enable timer0 */ |
86 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); | 93 | tmcon = __raw_readl(KS8695_TMR_VA + KS8695_TMCON); |
87 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | 94 | __raw_writel(tmcon & ~TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); |
88 | __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); | 95 | __raw_writel(tmcon | TMCON_T0EN, KS8695_TMR_VA + KS8695_TMCON); |
96 | spin_unlock(&ks8695_lock); | ||
89 | } | 97 | } |
90 | 98 | ||
91 | /* | 99 | /* |
@@ -102,7 +110,8 @@ static int ks8695_wdt_settimeout(int new_time) | |||
102 | if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) | 110 | if ((new_time <= 0) || (new_time > WDT_MAX_TIME)) |
103 | return -EINVAL; | 111 | return -EINVAL; |
104 | 112 | ||
105 | /* Set new watchdog time. It will be used when ks8695_wdt_start() is called. */ | 113 | /* Set new watchdog time. It will be used when |
114 | ks8695_wdt_start() is called. */ | ||
106 | wdt_time = new_time; | 115 | wdt_time = new_time; |
107 | return 0; | 116 | return 0; |
108 | } | 117 | } |
@@ -128,9 +137,9 @@ static int ks8695_wdt_open(struct inode *inode, struct file *file) | |||
128 | */ | 137 | */ |
129 | static int ks8695_wdt_close(struct inode *inode, struct file *file) | 138 | static int ks8695_wdt_close(struct inode *inode, struct file *file) |
130 | { | 139 | { |
140 | /* Disable the watchdog when file is closed */ | ||
131 | if (!nowayout) | 141 | if (!nowayout) |
132 | ks8695_wdt_stop(); /* Disable the watchdog when file is closed */ | 142 | ks8695_wdt_stop(); |
133 | |||
134 | clear_bit(0, &ks8695wdt_busy); | 143 | clear_bit(0, &ks8695wdt_busy); |
135 | return 0; | 144 | return 0; |
136 | } | 145 | } |
@@ -143,60 +152,52 @@ static struct watchdog_info ks8695_wdt_info = { | |||
143 | /* | 152 | /* |
144 | * Handle commands from user-space. | 153 | * Handle commands from user-space. |
145 | */ | 154 | */ |
146 | static int ks8695_wdt_ioctl(struct inode *inode, struct file *file, | 155 | static long ks8695_wdt_ioctl(struct file *file, unsigned int cmd, |
147 | unsigned int cmd, unsigned long arg) | 156 | unsigned long arg) |
148 | { | 157 | { |
149 | void __user *argp = (void __user *)arg; | 158 | void __user *argp = (void __user *)arg; |
150 | int __user *p = argp; | 159 | int __user *p = argp; |
151 | int new_value; | 160 | int new_value; |
152 | 161 | ||
153 | switch(cmd) { | 162 | switch (cmd) { |
154 | case WDIOC_KEEPALIVE: | 163 | case WDIOC_GETSUPPORT: |
155 | ks8695_wdt_reload(); /* pat the watchdog */ | 164 | return copy_to_user(argp, &ks8695_wdt_info, |
156 | return 0; | 165 | sizeof(ks8695_wdt_info)) ? -EFAULT : 0; |
157 | 166 | case WDIOC_GETSTATUS: | |
158 | case WDIOC_GETSUPPORT: | 167 | case WDIOC_GETBOOTSTATUS: |
159 | return copy_to_user(argp, &ks8695_wdt_info, sizeof(ks8695_wdt_info)) ? -EFAULT : 0; | 168 | return put_user(0, p); |
160 | 169 | case WDIOC_SETOPTIONS: | |
161 | case WDIOC_SETTIMEOUT: | 170 | if (get_user(new_value, p)) |
162 | if (get_user(new_value, p)) | 171 | return -EFAULT; |
163 | return -EFAULT; | 172 | if (new_value & WDIOS_DISABLECARD) |
164 | 173 | ks8695_wdt_stop(); | |
165 | if (ks8695_wdt_settimeout(new_value)) | 174 | if (new_value & WDIOS_ENABLECARD) |
166 | return -EINVAL; | ||
167 | |||
168 | /* Enable new time value */ | ||
169 | ks8695_wdt_start(); | 175 | ks8695_wdt_start(); |
170 | 176 | return 0; | |
171 | /* Return current value */ | 177 | case WDIOC_KEEPALIVE: |
172 | return put_user(wdt_time, p); | 178 | ks8695_wdt_reload(); /* pat the watchdog */ |
173 | 179 | return 0; | |
174 | case WDIOC_GETTIMEOUT: | 180 | case WDIOC_SETTIMEOUT: |
175 | return put_user(wdt_time, p); | 181 | if (get_user(new_value, p)) |
176 | 182 | return -EFAULT; | |
177 | case WDIOC_GETSTATUS: | 183 | if (ks8695_wdt_settimeout(new_value)) |
178 | case WDIOC_GETBOOTSTATUS: | 184 | return -EINVAL; |
179 | return put_user(0, p); | 185 | /* Enable new time value */ |
180 | 186 | ks8695_wdt_start(); | |
181 | case WDIOC_SETOPTIONS: | 187 | /* Return current value */ |
182 | if (get_user(new_value, p)) | 188 | return put_user(wdt_time, p); |
183 | return -EFAULT; | 189 | case WDIOC_GETTIMEOUT: |
184 | 190 | return put_user(wdt_time, p); | |
185 | if (new_value & WDIOS_DISABLECARD) | 191 | default: |
186 | ks8695_wdt_stop(); | 192 | return -ENOTTY; |
187 | if (new_value & WDIOS_ENABLECARD) | ||
188 | ks8695_wdt_start(); | ||
189 | return 0; | ||
190 | |||
191 | default: | ||
192 | return -ENOTTY; | ||
193 | } | 193 | } |
194 | } | 194 | } |
195 | 195 | ||
196 | /* | 196 | /* |
197 | * Pat the watchdog whenever device is written to. | 197 | * Pat the watchdog whenever device is written to. |
198 | */ | 198 | */ |
199 | static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 199 | static ssize_t ks8695_wdt_write(struct file *file, const char *data, |
200 | size_t len, loff_t *ppos) | ||
200 | { | 201 | { |
201 | ks8695_wdt_reload(); /* pat the watchdog */ | 202 | ks8695_wdt_reload(); /* pat the watchdog */ |
202 | return len; | 203 | return len; |
@@ -207,7 +208,7 @@ static ssize_t ks8695_wdt_write(struct file *file, const char *data, size_t len, | |||
207 | static const struct file_operations ks8695wdt_fops = { | 208 | static const struct file_operations ks8695wdt_fops = { |
208 | .owner = THIS_MODULE, | 209 | .owner = THIS_MODULE, |
209 | .llseek = no_llseek, | 210 | .llseek = no_llseek, |
210 | .ioctl = ks8695_wdt_ioctl, | 211 | .unlocked_ioctl = ks8695_wdt_ioctl, |
211 | .open = ks8695_wdt_open, | 212 | .open = ks8695_wdt_open, |
212 | .release = ks8695_wdt_close, | 213 | .release = ks8695_wdt_close, |
213 | .write = ks8695_wdt_write, | 214 | .write = ks8695_wdt_write, |
@@ -231,7 +232,8 @@ static int __init ks8695wdt_probe(struct platform_device *pdev) | |||
231 | if (res) | 232 | if (res) |
232 | return res; | 233 | return res; |
233 | 234 | ||
234 | printk("KS8695 Watchdog Timer enabled (%d seconds%s)\n", wdt_time, nowayout ? ", nowayout" : ""); | 235 | printk(KERN_INFO "KS8695 Watchdog Timer enabled (%d seconds%s)\n", |
236 | wdt_time, nowayout ? ", nowayout" : ""); | ||
235 | return 0; | 237 | return 0; |
236 | } | 238 | } |
237 | 239 | ||
@@ -285,12 +287,14 @@ static struct platform_driver ks8695wdt_driver = { | |||
285 | 287 | ||
286 | static int __init ks8695_wdt_init(void) | 288 | static int __init ks8695_wdt_init(void) |
287 | { | 289 | { |
288 | /* Check that the heartbeat value is within range; if not reset to the default */ | 290 | spin_lock_init(&ks8695_lock); |
291 | /* Check that the heartbeat value is within range; | ||
292 | if not reset to the default */ | ||
289 | if (ks8695_wdt_settimeout(wdt_time)) { | 293 | if (ks8695_wdt_settimeout(wdt_time)) { |
290 | ks8695_wdt_settimeout(WDT_DEFAULT_TIME); | 294 | ks8695_wdt_settimeout(WDT_DEFAULT_TIME); |
291 | pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n", wdt_time, WDT_MAX_TIME); | 295 | pr_info("ks8695_wdt: wdt_time value must be 1 <= wdt_time <= %i, using %d\n", |
296 | wdt_time, WDT_MAX_TIME); | ||
292 | } | 297 | } |
293 | |||
294 | return platform_driver_register(&ks8695wdt_driver); | 298 | return platform_driver_register(&ks8695wdt_driver); |
295 | } | 299 | } |
296 | 300 | ||
diff --git a/drivers/watchdog/machzwd.c b/drivers/watchdog/machzwd.c index 6905135a776c..2dfc27559bf7 100644 --- a/drivers/watchdog/machzwd.c +++ b/drivers/watchdog/machzwd.c | |||
@@ -40,9 +40,9 @@ | |||
40 | #include <linux/notifier.h> | 40 | #include <linux/notifier.h> |
41 | #include <linux/reboot.h> | 41 | #include <linux/reboot.h> |
42 | #include <linux/init.h> | 42 | #include <linux/init.h> |
43 | #include <linux/io.h> | ||
44 | #include <linux/uaccess.h> | ||
43 | 45 | ||
44 | #include <asm/io.h> | ||
45 | #include <asm/uaccess.h> | ||
46 | #include <asm/system.h> | 46 | #include <asm/system.h> |
47 | 47 | ||
48 | /* ports */ | 48 | /* ports */ |
@@ -95,7 +95,9 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | |||
95 | 95 | ||
96 | static int nowayout = WATCHDOG_NOWAYOUT; | 96 | static int nowayout = WATCHDOG_NOWAYOUT; |
97 | module_param(nowayout, int, 0); | 97 | module_param(nowayout, int, 0); |
98 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 98 | MODULE_PARM_DESC(nowayout, |
99 | "Watchdog cannot be stopped once started (default=" | ||
100 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
99 | 101 | ||
100 | #define PFX "machzwd" | 102 | #define PFX "machzwd" |
101 | 103 | ||
@@ -114,7 +116,7 @@ static struct watchdog_info zf_info = { | |||
114 | * 3 = GEN_SCI | 116 | * 3 = GEN_SCI |
115 | * defaults to GEN_RESET (0) | 117 | * defaults to GEN_RESET (0) |
116 | */ | 118 | */ |
117 | static int action = 0; | 119 | static int action; |
118 | module_param(action, int, 0); | 120 | module_param(action, int, 0); |
119 | MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); | 121 | MODULE_PARM_DESC(action, "after watchdog resets, generate: 0 = RESET(*) 1 = SMI 2 = NMI 3 = SCI"); |
120 | 122 | ||
@@ -123,10 +125,9 @@ static void zf_ping(unsigned long data); | |||
123 | static int zf_action = GEN_RESET; | 125 | static int zf_action = GEN_RESET; |
124 | static unsigned long zf_is_open; | 126 | static unsigned long zf_is_open; |
125 | static char zf_expect_close; | 127 | static char zf_expect_close; |
126 | static DEFINE_SPINLOCK(zf_lock); | ||
127 | static DEFINE_SPINLOCK(zf_port_lock); | 128 | static DEFINE_SPINLOCK(zf_port_lock); |
128 | static DEFINE_TIMER(zf_timer, zf_ping, 0, 0); | 129 | static DEFINE_TIMER(zf_timer, zf_ping, 0, 0); |
129 | static unsigned long next_heartbeat = 0; | 130 | static unsigned long next_heartbeat; |
130 | 131 | ||
131 | 132 | ||
132 | /* timeout for user land heart beat (10 seconds) */ | 133 | /* timeout for user land heart beat (10 seconds) */ |
@@ -171,13 +172,13 @@ static inline void zf_set_control(unsigned short new) | |||
171 | 172 | ||
172 | static inline void zf_set_timer(unsigned short new, unsigned char n) | 173 | static inline void zf_set_timer(unsigned short new, unsigned char n) |
173 | { | 174 | { |
174 | switch(n){ | 175 | switch (n) { |
175 | case WD1: | 176 | case WD1: |
176 | zf_writew(COUNTER_1, new); | 177 | zf_writew(COUNTER_1, new); |
177 | case WD2: | 178 | case WD2: |
178 | zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); | 179 | zf_writeb(COUNTER_2, new > 0xff ? 0xff : new); |
179 | default: | 180 | default: |
180 | return; | 181 | return; |
181 | } | 182 | } |
182 | } | 183 | } |
183 | 184 | ||
@@ -241,10 +242,8 @@ static void zf_ping(unsigned long data) | |||
241 | 242 | ||
242 | zf_writeb(COUNTER_2, 0xff); | 243 | zf_writeb(COUNTER_2, 0xff); |
243 | 244 | ||
244 | if(time_before(jiffies, next_heartbeat)){ | 245 | if (time_before(jiffies, next_heartbeat)) { |
245 | |||
246 | dprintk("time_before: %ld\n", next_heartbeat - jiffies); | 246 | dprintk("time_before: %ld\n", next_heartbeat - jiffies); |
247 | |||
248 | /* | 247 | /* |
249 | * reset event is activated by transition from 0 to 1 on | 248 | * reset event is activated by transition from 0 to 1 on |
250 | * RESET_WD1 bit and we assume that it is already zero... | 249 | * RESET_WD1 bit and we assume that it is already zero... |
@@ -261,24 +260,21 @@ static void zf_ping(unsigned long data) | |||
261 | spin_unlock_irqrestore(&zf_port_lock, flags); | 260 | spin_unlock_irqrestore(&zf_port_lock, flags); |
262 | 261 | ||
263 | mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO); | 262 | mod_timer(&zf_timer, jiffies + ZF_HW_TIMEO); |
264 | }else{ | 263 | } else |
265 | printk(KERN_CRIT PFX ": I will reset your machine\n"); | 264 | printk(KERN_CRIT PFX ": I will reset your machine\n"); |
266 | } | ||
267 | } | 265 | } |
268 | 266 | ||
269 | static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, | 267 | static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, |
270 | loff_t *ppos) | 268 | loff_t *ppos) |
271 | { | 269 | { |
272 | /* See if we got the magic character */ | 270 | /* See if we got the magic character */ |
273 | if(count){ | 271 | if (count) { |
274 | |||
275 | /* | 272 | /* |
276 | * no need to check for close confirmation | 273 | * no need to check for close confirmation |
277 | * no way to disable watchdog ;) | 274 | * no way to disable watchdog ;) |
278 | */ | 275 | */ |
279 | if (!nowayout) { | 276 | if (!nowayout) { |
280 | size_t ofs; | 277 | size_t ofs; |
281 | |||
282 | /* | 278 | /* |
283 | * note: just in case someone wrote the magic character | 279 | * note: just in case someone wrote the magic character |
284 | * five months ago... | 280 | * five months ago... |
@@ -286,11 +282,11 @@ static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, | |||
286 | zf_expect_close = 0; | 282 | zf_expect_close = 0; |
287 | 283 | ||
288 | /* now scan */ | 284 | /* now scan */ |
289 | for (ofs = 0; ofs != count; ofs++){ | 285 | for (ofs = 0; ofs != count; ofs++) { |
290 | char c; | 286 | char c; |
291 | if (get_user(c, buf + ofs)) | 287 | if (get_user(c, buf + ofs)) |
292 | return -EFAULT; | 288 | return -EFAULT; |
293 | if (c == 'V'){ | 289 | if (c == 'V') { |
294 | zf_expect_close = 42; | 290 | zf_expect_close = 42; |
295 | dprintk("zf_expect_close = 42\n"); | 291 | dprintk("zf_expect_close = 42\n"); |
296 | } | 292 | } |
@@ -303,14 +299,11 @@ static ssize_t zf_write(struct file *file, const char __user *buf, size_t count, | |||
303 | */ | 299 | */ |
304 | next_heartbeat = jiffies + ZF_USER_TIMEO; | 300 | next_heartbeat = jiffies + ZF_USER_TIMEO; |
305 | dprintk("user ping at %ld\n", jiffies); | 301 | dprintk("user ping at %ld\n", jiffies); |
306 | |||
307 | } | 302 | } |
308 | |||
309 | return count; | 303 | return count; |
310 | } | 304 | } |
311 | 305 | ||
312 | static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 306 | static long zf_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
313 | unsigned long arg) | ||
314 | { | 307 | { |
315 | void __user *argp = (void __user *)arg; | 308 | void __user *argp = (void __user *)arg; |
316 | int __user *p = argp; | 309 | int __user *p = argp; |
@@ -319,55 +312,38 @@ static int zf_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
319 | if (copy_to_user(argp, &zf_info, sizeof(zf_info))) | 312 | if (copy_to_user(argp, &zf_info, sizeof(zf_info))) |
320 | return -EFAULT; | 313 | return -EFAULT; |
321 | break; | 314 | break; |
322 | |||
323 | case WDIOC_GETSTATUS: | 315 | case WDIOC_GETSTATUS: |
324 | case WDIOC_GETBOOTSTATUS: | 316 | case WDIOC_GETBOOTSTATUS: |
325 | return put_user(0, p); | 317 | return put_user(0, p); |
326 | |||
327 | case WDIOC_KEEPALIVE: | 318 | case WDIOC_KEEPALIVE: |
328 | zf_ping(0); | 319 | zf_ping(0); |
329 | break; | 320 | break; |
330 | |||
331 | default: | 321 | default: |
332 | return -ENOTTY; | 322 | return -ENOTTY; |
333 | } | 323 | } |
334 | |||
335 | return 0; | 324 | return 0; |
336 | } | 325 | } |
337 | 326 | ||
338 | static int zf_open(struct inode *inode, struct file *file) | 327 | static int zf_open(struct inode *inode, struct file *file) |
339 | { | 328 | { |
340 | spin_lock(&zf_lock); | 329 | if (test_and_set_bit(0, &zf_is_open)) |
341 | if(test_and_set_bit(0, &zf_is_open)) { | ||
342 | spin_unlock(&zf_lock); | ||
343 | return -EBUSY; | 330 | return -EBUSY; |
344 | } | ||
345 | |||
346 | if (nowayout) | 331 | if (nowayout) |
347 | __module_get(THIS_MODULE); | 332 | __module_get(THIS_MODULE); |
348 | |||
349 | spin_unlock(&zf_lock); | ||
350 | |||
351 | zf_timer_on(); | 333 | zf_timer_on(); |
352 | |||
353 | return nonseekable_open(inode, file); | 334 | return nonseekable_open(inode, file); |
354 | } | 335 | } |
355 | 336 | ||
356 | static int zf_close(struct inode *inode, struct file *file) | 337 | static int zf_close(struct inode *inode, struct file *file) |
357 | { | 338 | { |
358 | if(zf_expect_close == 42){ | 339 | if (zf_expect_close == 42) |
359 | zf_timer_off(); | 340 | zf_timer_off(); |
360 | } else { | 341 | else { |
361 | del_timer(&zf_timer); | 342 | del_timer(&zf_timer); |
362 | printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n"); | 343 | printk(KERN_ERR PFX ": device file closed unexpectedly. Will not stop the WDT!\n"); |
363 | } | 344 | } |
364 | |||
365 | spin_lock(&zf_lock); | ||
366 | clear_bit(0, &zf_is_open); | 345 | clear_bit(0, &zf_is_open); |
367 | spin_unlock(&zf_lock); | ||
368 | |||
369 | zf_expect_close = 0; | 346 | zf_expect_close = 0; |
370 | |||
371 | return 0; | 347 | return 0; |
372 | } | 348 | } |
373 | 349 | ||
@@ -378,23 +354,18 @@ static int zf_close(struct inode *inode, struct file *file) | |||
378 | static int zf_notify_sys(struct notifier_block *this, unsigned long code, | 354 | static int zf_notify_sys(struct notifier_block *this, unsigned long code, |
379 | void *unused) | 355 | void *unused) |
380 | { | 356 | { |
381 | if(code == SYS_DOWN || code == SYS_HALT){ | 357 | if (code == SYS_DOWN || code == SYS_HALT) |
382 | zf_timer_off(); | 358 | zf_timer_off(); |
383 | } | ||
384 | |||
385 | return NOTIFY_DONE; | 359 | return NOTIFY_DONE; |
386 | } | 360 | } |
387 | 361 | ||
388 | |||
389 | |||
390 | |||
391 | static const struct file_operations zf_fops = { | 362 | static const struct file_operations zf_fops = { |
392 | .owner = THIS_MODULE, | 363 | .owner = THIS_MODULE, |
393 | .llseek = no_llseek, | 364 | .llseek = no_llseek, |
394 | .write = zf_write, | 365 | .write = zf_write, |
395 | .ioctl = zf_ioctl, | 366 | .unlocked_ioctl = zf_ioctl, |
396 | .open = zf_open, | 367 | .open = zf_open, |
397 | .release = zf_close, | 368 | .release = zf_close, |
398 | }; | 369 | }; |
399 | 370 | ||
400 | static struct miscdevice zf_miscdev = { | 371 | static struct miscdevice zf_miscdev = { |
@@ -402,7 +373,7 @@ static struct miscdevice zf_miscdev = { | |||
402 | .name = "watchdog", | 373 | .name = "watchdog", |
403 | .fops = &zf_fops, | 374 | .fops = &zf_fops, |
404 | }; | 375 | }; |
405 | 376 | ||
406 | 377 | ||
407 | /* | 378 | /* |
408 | * The device needs to learn about soft shutdowns in order to | 379 | * The device needs to learn about soft shutdowns in order to |
@@ -423,22 +394,23 @@ static int __init zf_init(void) | |||
423 | { | 394 | { |
424 | int ret; | 395 | int ret; |
425 | 396 | ||
426 | printk(KERN_INFO PFX ": MachZ ZF-Logic Watchdog driver initializing.\n"); | 397 | printk(KERN_INFO PFX |
398 | ": MachZ ZF-Logic Watchdog driver initializing.\n"); | ||
427 | 399 | ||
428 | ret = zf_get_ZFL_version(); | 400 | ret = zf_get_ZFL_version(); |
429 | if ((!ret) || (ret == 0xffff)) { | 401 | if (!ret || ret == 0xffff) { |
430 | printk(KERN_WARNING PFX ": no ZF-Logic found\n"); | 402 | printk(KERN_WARNING PFX ": no ZF-Logic found\n"); |
431 | return -ENODEV; | 403 | return -ENODEV; |
432 | } | 404 | } |
433 | 405 | ||
434 | if((action <= 3) && (action >= 0)){ | 406 | if (action <= 3 && action >= 0) |
435 | zf_action = zf_action>>action; | 407 | zf_action = zf_action >> action; |
436 | } else | 408 | else |
437 | action = 0; | 409 | action = 0; |
438 | 410 | ||
439 | zf_show_action(action); | 411 | zf_show_action(action); |
440 | 412 | ||
441 | if(!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")){ | 413 | if (!request_region(ZF_IOBASE, 3, "MachZ ZFL WDT")) { |
442 | printk(KERN_ERR "cannot reserve I/O ports at %d\n", | 414 | printk(KERN_ERR "cannot reserve I/O ports at %d\n", |
443 | ZF_IOBASE); | 415 | ZF_IOBASE); |
444 | ret = -EBUSY; | 416 | ret = -EBUSY; |
@@ -446,14 +418,14 @@ static int __init zf_init(void) | |||
446 | } | 418 | } |
447 | 419 | ||
448 | ret = register_reboot_notifier(&zf_notifier); | 420 | ret = register_reboot_notifier(&zf_notifier); |
449 | if(ret){ | 421 | if (ret) { |
450 | printk(KERN_ERR "can't register reboot notifier (err=%d)\n", | 422 | printk(KERN_ERR "can't register reboot notifier (err=%d)\n", |
451 | ret); | 423 | ret); |
452 | goto no_reboot; | 424 | goto no_reboot; |
453 | } | 425 | } |
454 | 426 | ||
455 | ret = misc_register(&zf_miscdev); | 427 | ret = misc_register(&zf_miscdev); |
456 | if (ret){ | 428 | if (ret) { |
457 | printk(KERN_ERR "can't misc_register on minor=%d\n", | 429 | printk(KERN_ERR "can't misc_register on minor=%d\n", |
458 | WATCHDOG_MINOR); | 430 | WATCHDOG_MINOR); |
459 | goto no_misc; | 431 | goto no_misc; |
diff --git a/drivers/watchdog/mixcomwd.c b/drivers/watchdog/mixcomwd.c index 1adf1d56027d..407b025cb104 100644 --- a/drivers/watchdog/mixcomwd.c +++ b/drivers/watchdog/mixcomwd.c | |||
@@ -29,7 +29,8 @@ | |||
29 | * - support for one more type board | 29 | * - support for one more type board |
30 | * | 30 | * |
31 | * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com> | 31 | * Version 0.5 (2001/12/14) Matt Domsch <Matt_Domsch@dell.com> |
32 | * - added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT | 32 | * - added nowayout module option to override |
33 | * CONFIG_WATCHDOG_NOWAYOUT | ||
33 | * | 34 | * |
34 | * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com> | 35 | * Version 0.6 (2002/04/12): Rob Radez <rob@osinvestor.com> |
35 | * - make mixcomwd_opened unsigned, | 36 | * - make mixcomwd_opened unsigned, |
@@ -53,8 +54,8 @@ | |||
53 | #include <linux/init.h> | 54 | #include <linux/init.h> |
54 | #include <linux/jiffies.h> | 55 | #include <linux/jiffies.h> |
55 | #include <linux/timer.h> | 56 | #include <linux/timer.h> |
56 | #include <asm/uaccess.h> | 57 | #include <linux/uaccess.h> |
57 | #include <asm/io.h> | 58 | #include <linux/io.h> |
58 | 59 | ||
59 | /* | 60 | /* |
60 | * We have two types of cards that can be probed: | 61 | * We have two types of cards that can be probed: |
@@ -108,18 +109,19 @@ static char expect_close; | |||
108 | 109 | ||
109 | static int nowayout = WATCHDOG_NOWAYOUT; | 110 | static int nowayout = WATCHDOG_NOWAYOUT; |
110 | module_param(nowayout, int, 0); | 111 | module_param(nowayout, int, 0); |
111 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 112 | MODULE_PARM_DESC(nowayout, |
113 | "Watchdog cannot be stopped once started (default=" | ||
114 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
112 | 115 | ||
113 | static void mixcomwd_ping(void) | 116 | static void mixcomwd_ping(void) |
114 | { | 117 | { |
115 | outb_p(55,watchdog_port); | 118 | outb_p(55, watchdog_port); |
116 | return; | 119 | return; |
117 | } | 120 | } |
118 | 121 | ||
119 | static void mixcomwd_timerfun(unsigned long d) | 122 | static void mixcomwd_timerfun(unsigned long d) |
120 | { | 123 | { |
121 | mixcomwd_ping(); | 124 | mixcomwd_ping(); |
122 | |||
123 | mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); | 125 | mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); |
124 | } | 126 | } |
125 | 127 | ||
@@ -129,22 +131,22 @@ static void mixcomwd_timerfun(unsigned long d) | |||
129 | 131 | ||
130 | static int mixcomwd_open(struct inode *inode, struct file *file) | 132 | static int mixcomwd_open(struct inode *inode, struct file *file) |
131 | { | 133 | { |
132 | if(test_and_set_bit(0,&mixcomwd_opened)) { | 134 | if (test_and_set_bit(0, &mixcomwd_opened)) |
133 | return -EBUSY; | 135 | return -EBUSY; |
134 | } | 136 | |
135 | mixcomwd_ping(); | 137 | mixcomwd_ping(); |
136 | 138 | ||
137 | if (nowayout) { | 139 | if (nowayout) |
138 | /* | 140 | /* |
139 | * fops_get() code via open() has already done | 141 | * fops_get() code via open() has already done |
140 | * a try_module_get() so it is safe to do the | 142 | * a try_module_get() so it is safe to do the |
141 | * __module_get(). | 143 | * __module_get(). |
142 | */ | 144 | */ |
143 | __module_get(THIS_MODULE); | 145 | __module_get(THIS_MODULE); |
144 | } else { | 146 | else { |
145 | if(mixcomwd_timer_alive) { | 147 | if (mixcomwd_timer_alive) { |
146 | del_timer(&mixcomwd_timer); | 148 | del_timer(&mixcomwd_timer); |
147 | mixcomwd_timer_alive=0; | 149 | mixcomwd_timer_alive = 0; |
148 | } | 150 | } |
149 | } | 151 | } |
150 | return nonseekable_open(inode, file); | 152 | return nonseekable_open(inode, file); |
@@ -153,26 +155,27 @@ static int mixcomwd_open(struct inode *inode, struct file *file) | |||
153 | static int mixcomwd_release(struct inode *inode, struct file *file) | 155 | static int mixcomwd_release(struct inode *inode, struct file *file) |
154 | { | 156 | { |
155 | if (expect_close == 42) { | 157 | if (expect_close == 42) { |
156 | if(mixcomwd_timer_alive) { | 158 | if (mixcomwd_timer_alive) { |
157 | printk(KERN_ERR PFX "release called while internal timer alive"); | 159 | printk(KERN_ERR PFX |
160 | "release called while internal timer alive"); | ||
158 | return -EBUSY; | 161 | return -EBUSY; |
159 | } | 162 | } |
160 | mixcomwd_timer_alive=1; | 163 | mixcomwd_timer_alive = 1; |
161 | mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); | 164 | mod_timer(&mixcomwd_timer, jiffies + 5 * HZ); |
162 | } else { | 165 | } else |
163 | printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); | 166 | printk(KERN_CRIT PFX |
164 | } | 167 | "WDT device closed unexpectedly. WDT will not stop!\n"); |
165 | 168 | ||
166 | clear_bit(0,&mixcomwd_opened); | 169 | clear_bit(0, &mixcomwd_opened); |
167 | expect_close=0; | 170 | expect_close = 0; |
168 | return 0; | 171 | return 0; |
169 | } | 172 | } |
170 | 173 | ||
171 | 174 | ||
172 | static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) | 175 | static ssize_t mixcomwd_write(struct file *file, const char __user *data, |
176 | size_t len, loff_t *ppos) | ||
173 | { | 177 | { |
174 | if(len) | 178 | if (len) { |
175 | { | ||
176 | if (!nowayout) { | 179 | if (!nowayout) { |
177 | size_t i; | 180 | size_t i; |
178 | 181 | ||
@@ -192,8 +195,8 @@ static ssize_t mixcomwd_write(struct file *file, const char __user *data, size_t | |||
192 | return len; | 195 | return len; |
193 | } | 196 | } |
194 | 197 | ||
195 | static int mixcomwd_ioctl(struct inode *inode, struct file *file, | 198 | static long mixcomwd_ioctl(struct file *file, |
196 | unsigned int cmd, unsigned long arg) | 199 | unsigned int cmd, unsigned long arg) |
197 | { | 200 | { |
198 | void __user *argp = (void __user *)arg; | 201 | void __user *argp = (void __user *)arg; |
199 | int __user *p = argp; | 202 | int __user *p = argp; |
@@ -204,32 +207,23 @@ static int mixcomwd_ioctl(struct inode *inode, struct file *file, | |||
204 | .identity = "MixCOM watchdog", | 207 | .identity = "MixCOM watchdog", |
205 | }; | 208 | }; |
206 | 209 | ||
207 | switch(cmd) | 210 | switch (cmd) { |
208 | { | 211 | case WDIOC_GETSUPPORT: |
209 | case WDIOC_GETSTATUS: | 212 | if (copy_to_user(argp, &ident, sizeof(ident))) |
210 | status=mixcomwd_opened; | 213 | return -EFAULT; |
211 | if (!nowayout) { | 214 | break; |
212 | status|=mixcomwd_timer_alive; | 215 | case WDIOC_GETSTATUS: |
213 | } | 216 | status = mixcomwd_opened; |
214 | if (copy_to_user(p, &status, sizeof(int))) { | 217 | if (!nowayout) |
215 | return -EFAULT; | 218 | status |= mixcomwd_timer_alive; |
216 | } | 219 | return put_user(status, p); |
217 | break; | 220 | case WDIOC_GETBOOTSTATUS: |
218 | case WDIOC_GETBOOTSTATUS: | 221 | return put_user(0, p); |
219 | if (copy_to_user(p, &status, sizeof(int))) { | 222 | case WDIOC_KEEPALIVE: |
220 | return -EFAULT; | 223 | mixcomwd_ping(); |
221 | } | 224 | break; |
222 | break; | 225 | default: |
223 | case WDIOC_GETSUPPORT: | 226 | return -ENOTTY; |
224 | if (copy_to_user(argp, &ident, sizeof(ident))) { | ||
225 | return -EFAULT; | ||
226 | } | ||
227 | break; | ||
228 | case WDIOC_KEEPALIVE: | ||
229 | mixcomwd_ping(); | ||
230 | break; | ||
231 | default: | ||
232 | return -ENOTTY; | ||
233 | } | 227 | } |
234 | return 0; | 228 | return 0; |
235 | } | 229 | } |
@@ -238,7 +232,7 @@ static const struct file_operations mixcomwd_fops = { | |||
238 | .owner = THIS_MODULE, | 232 | .owner = THIS_MODULE, |
239 | .llseek = no_llseek, | 233 | .llseek = no_llseek, |
240 | .write = mixcomwd_write, | 234 | .write = mixcomwd_write, |
241 | .ioctl = mixcomwd_ioctl, | 235 | .unlocked_ioctl = mixcomwd_ioctl, |
242 | .open = mixcomwd_open, | 236 | .open = mixcomwd_open, |
243 | .release = mixcomwd_release, | 237 | .release = mixcomwd_release, |
244 | }; | 238 | }; |
@@ -253,15 +247,14 @@ static int __init checkcard(int port, int card_id) | |||
253 | { | 247 | { |
254 | int id; | 248 | int id; |
255 | 249 | ||
256 | if (!request_region(port, 1, "MixCOM watchdog")) { | 250 | if (!request_region(port, 1, "MixCOM watchdog")) |
257 | return 0; | 251 | return 0; |
258 | } | ||
259 | 252 | ||
260 | id=inb_p(port); | 253 | id = inb_p(port); |
261 | if (card_id==MIXCOM_ID) | 254 | if (card_id == MIXCOM_ID) |
262 | id &= 0x3f; | 255 | id &= 0x3f; |
263 | 256 | ||
264 | if (id!=card_id) { | 257 | if (id != card_id) { |
265 | release_region(port, 1); | 258 | release_region(port, 1); |
266 | return 0; | 259 | return 0; |
267 | } | 260 | } |
@@ -270,9 +263,7 @@ static int __init checkcard(int port, int card_id) | |||
270 | 263 | ||
271 | static int __init mixcomwd_init(void) | 264 | static int __init mixcomwd_init(void) |
272 | { | 265 | { |
273 | int i; | 266 | int i, ret, found = 0; |
274 | int ret; | ||
275 | int found=0; | ||
276 | 267 | ||
277 | for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) { | 268 | for (i = 0; !found && mixcomwd_io_info[i].ioport != 0; i++) { |
278 | if (checkcard(mixcomwd_io_info[i].ioport, | 269 | if (checkcard(mixcomwd_io_info[i].ioport, |
@@ -283,20 +274,22 @@ static int __init mixcomwd_init(void) | |||
283 | } | 274 | } |
284 | 275 | ||
285 | if (!found) { | 276 | if (!found) { |
286 | printk(KERN_ERR PFX "No card detected, or port not available.\n"); | 277 | printk(KERN_ERR PFX |
278 | "No card detected, or port not available.\n"); | ||
287 | return -ENODEV; | 279 | return -ENODEV; |
288 | } | 280 | } |
289 | 281 | ||
290 | ret = misc_register(&mixcomwd_miscdev); | 282 | ret = misc_register(&mixcomwd_miscdev); |
291 | if (ret) | 283 | if (ret) { |
292 | { | 284 | printk(KERN_ERR PFX |
293 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 285 | "cannot register miscdev on minor=%d (err=%d)\n", |
294 | WATCHDOG_MINOR, ret); | 286 | WATCHDOG_MINOR, ret); |
295 | goto error_misc_register_watchdog; | 287 | goto error_misc_register_watchdog; |
296 | } | 288 | } |
297 | 289 | ||
298 | printk(KERN_INFO "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n", | 290 | printk(KERN_INFO |
299 | VERSION, watchdog_port); | 291 | "MixCOM watchdog driver v%s, watchdog port at 0x%3x\n", |
292 | VERSION, watchdog_port); | ||
300 | 293 | ||
301 | return 0; | 294 | return 0; |
302 | 295 | ||
@@ -309,15 +302,15 @@ error_misc_register_watchdog: | |||
309 | static void __exit mixcomwd_exit(void) | 302 | static void __exit mixcomwd_exit(void) |
310 | { | 303 | { |
311 | if (!nowayout) { | 304 | if (!nowayout) { |
312 | if(mixcomwd_timer_alive) { | 305 | if (mixcomwd_timer_alive) { |
313 | printk(KERN_WARNING PFX "I quit now, hardware will" | 306 | printk(KERN_WARNING PFX "I quit now, hardware will" |
314 | " probably reboot!\n"); | 307 | " probably reboot!\n"); |
315 | del_timer_sync(&mixcomwd_timer); | 308 | del_timer_sync(&mixcomwd_timer); |
316 | mixcomwd_timer_alive=0; | 309 | mixcomwd_timer_alive = 0; |
317 | } | 310 | } |
318 | } | 311 | } |
319 | misc_deregister(&mixcomwd_miscdev); | 312 | misc_deregister(&mixcomwd_miscdev); |
320 | release_region(watchdog_port,1); | 313 | release_region(watchdog_port, 1); |
321 | } | 314 | } |
322 | 315 | ||
323 | module_init(mixcomwd_init); | 316 | module_init(mixcomwd_init); |
diff --git a/drivers/watchdog/mpc5200_wdt.c b/drivers/watchdog/mpc5200_wdt.c index 77c1c2ae2cc2..db91892558f2 100644 --- a/drivers/watchdog/mpc5200_wdt.c +++ b/drivers/watchdog/mpc5200_wdt.c | |||
@@ -5,7 +5,7 @@ | |||
5 | #include <linux/io.h> | 5 | #include <linux/io.h> |
6 | #include <linux/spinlock.h> | 6 | #include <linux/spinlock.h> |
7 | #include <linux/of_platform.h> | 7 | #include <linux/of_platform.h> |
8 | #include <asm/uaccess.h> | 8 | #include <linux/uaccess.h> |
9 | #include <asm/mpc52xx.h> | 9 | #include <asm/mpc52xx.h> |
10 | 10 | ||
11 | 11 | ||
@@ -57,7 +57,8 @@ static int mpc5200_wdt_start(struct mpc5200_wdt *wdt) | |||
57 | /* set timeout, with maximum prescaler */ | 57 | /* set timeout, with maximum prescaler */ |
58 | out_be32(&wdt->regs->count, 0x0 | wdt->count); | 58 | out_be32(&wdt->regs->count, 0x0 | wdt->count); |
59 | /* enable watchdog */ | 59 | /* enable watchdog */ |
60 | out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | GPT_MODE_MS_TIMER); | 60 | out_be32(&wdt->regs->mode, GPT_MODE_CE | GPT_MODE_WDT | |
61 | GPT_MODE_MS_TIMER); | ||
61 | spin_unlock(&wdt->io_lock); | 62 | spin_unlock(&wdt->io_lock); |
62 | 63 | ||
63 | return 0; | 64 | return 0; |
@@ -66,7 +67,8 @@ static int mpc5200_wdt_ping(struct mpc5200_wdt *wdt) | |||
66 | { | 67 | { |
67 | spin_lock(&wdt->io_lock); | 68 | spin_lock(&wdt->io_lock); |
68 | /* writing A5 to OCPW resets the watchdog */ | 69 | /* writing A5 to OCPW resets the watchdog */ |
69 | out_be32(&wdt->regs->mode, 0xA5000000 | (0xffffff & in_be32(&wdt->regs->mode))); | 70 | out_be32(&wdt->regs->mode, 0xA5000000 | |
71 | (0xffffff & in_be32(&wdt->regs->mode))); | ||
70 | spin_unlock(&wdt->io_lock); | 72 | spin_unlock(&wdt->io_lock); |
71 | return 0; | 73 | return 0; |
72 | } | 74 | } |
@@ -92,8 +94,8 @@ static struct watchdog_info mpc5200_wdt_info = { | |||
92 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 94 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
93 | .identity = "mpc5200 watchdog on GPT0", | 95 | .identity = "mpc5200 watchdog on GPT0", |
94 | }; | 96 | }; |
95 | static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file, | 97 | static long mpc5200_wdt_ioctl(struct file *file, unsigned int cmd, |
96 | unsigned int cmd, unsigned long arg) | 98 | unsigned long arg) |
97 | { | 99 | { |
98 | struct mpc5200_wdt *wdt = file->private_data; | 100 | struct mpc5200_wdt *wdt = file->private_data; |
99 | int __user *data = (int __user *)arg; | 101 | int __user *data = (int __user *)arg; |
@@ -103,7 +105,7 @@ static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file, | |||
103 | switch (cmd) { | 105 | switch (cmd) { |
104 | case WDIOC_GETSUPPORT: | 106 | case WDIOC_GETSUPPORT: |
105 | ret = copy_to_user(data, &mpc5200_wdt_info, | 107 | ret = copy_to_user(data, &mpc5200_wdt_info, |
106 | sizeof(mpc5200_wdt_info)); | 108 | sizeof(mpc5200_wdt_info)); |
107 | if (ret) | 109 | if (ret) |
108 | ret = -EFAULT; | 110 | ret = -EFAULT; |
109 | break; | 111 | break; |
@@ -135,6 +137,7 @@ static int mpc5200_wdt_ioctl(struct inode *inode, struct file *file, | |||
135 | } | 137 | } |
136 | return ret; | 138 | return ret; |
137 | } | 139 | } |
140 | |||
138 | static int mpc5200_wdt_open(struct inode *inode, struct file *file) | 141 | static int mpc5200_wdt_open(struct inode *inode, struct file *file) |
139 | { | 142 | { |
140 | /* /dev/watchdog can only be opened once */ | 143 | /* /dev/watchdog can only be opened once */ |
@@ -161,13 +164,14 @@ static int mpc5200_wdt_release(struct inode *inode, struct file *file) | |||
161 | static const struct file_operations mpc5200_wdt_fops = { | 164 | static const struct file_operations mpc5200_wdt_fops = { |
162 | .owner = THIS_MODULE, | 165 | .owner = THIS_MODULE, |
163 | .write = mpc5200_wdt_write, | 166 | .write = mpc5200_wdt_write, |
164 | .ioctl = mpc5200_wdt_ioctl, | 167 | .unlocked_ioctl = mpc5200_wdt_ioctl, |
165 | .open = mpc5200_wdt_open, | 168 | .open = mpc5200_wdt_open, |
166 | .release = mpc5200_wdt_release, | 169 | .release = mpc5200_wdt_release, |
167 | }; | 170 | }; |
168 | 171 | ||
169 | /* module operations */ | 172 | /* module operations */ |
170 | static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *match) | 173 | static int mpc5200_wdt_probe(struct of_device *op, |
174 | const struct of_device_id *match) | ||
171 | { | 175 | { |
172 | struct mpc5200_wdt *wdt; | 176 | struct mpc5200_wdt *wdt; |
173 | int err; | 177 | int err; |
@@ -215,9 +219,9 @@ static int mpc5200_wdt_probe(struct of_device *op, const struct of_device_id *ma | |||
215 | return 0; | 219 | return 0; |
216 | 220 | ||
217 | iounmap(wdt->regs); | 221 | iounmap(wdt->regs); |
218 | out_release: | 222 | out_release: |
219 | release_mem_region(wdt->mem.start, size); | 223 | release_mem_region(wdt->mem.start, size); |
220 | out_free: | 224 | out_free: |
221 | kfree(wdt); | 225 | kfree(wdt); |
222 | return err; | 226 | return err; |
223 | } | 227 | } |
diff --git a/drivers/watchdog/mpc83xx_wdt.c b/drivers/watchdog/mpc83xx_wdt.c deleted file mode 100644 index b16c5cd972eb..000000000000 --- a/drivers/watchdog/mpc83xx_wdt.c +++ /dev/null | |||
@@ -1,230 +0,0 @@ | |||
1 | /* | ||
2 | * mpc83xx_wdt.c - MPC83xx watchdog userspace interface | ||
3 | * | ||
4 | * Authors: Dave Updegraff <dave@cray.org> | ||
5 | * Kumar Gala <galak@kernel.crashing.org> | ||
6 | * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> | ||
7 | * ..and from sc520_wdt | ||
8 | * | ||
9 | * Note: it appears that you can only actually ENABLE or DISABLE the thing | ||
10 | * once after POR. Once enabled, you cannot disable, and vice versa. | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or modify it | ||
13 | * under the terms of the GNU General Public License as published by the | ||
14 | * Free Software Foundation; either version 2 of the License, or (at your | ||
15 | * option) any later version. | ||
16 | */ | ||
17 | |||
18 | #include <linux/fs.h> | ||
19 | #include <linux/init.h> | ||
20 | #include <linux/kernel.h> | ||
21 | #include <linux/miscdevice.h> | ||
22 | #include <linux/platform_device.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/watchdog.h> | ||
25 | #include <asm/io.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | |||
28 | struct mpc83xx_wdt { | ||
29 | __be32 res0; | ||
30 | __be32 swcrr; /* System watchdog control register */ | ||
31 | #define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */ | ||
32 | #define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */ | ||
33 | #define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/ | ||
34 | #define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */ | ||
35 | __be32 swcnr; /* System watchdog count register */ | ||
36 | u8 res1[2]; | ||
37 | __be16 swsrr; /* System watchdog service register */ | ||
38 | u8 res2[0xF0]; | ||
39 | }; | ||
40 | |||
41 | static struct mpc83xx_wdt __iomem *wd_base; | ||
42 | |||
43 | static u16 timeout = 0xffff; | ||
44 | module_param(timeout, ushort, 0); | ||
45 | MODULE_PARM_DESC(timeout, "Watchdog timeout in ticks. (0<timeout<65536, default=65535"); | ||
46 | |||
47 | static int reset = 1; | ||
48 | module_param(reset, bool, 0); | ||
49 | MODULE_PARM_DESC(reset, "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset"); | ||
50 | |||
51 | /* | ||
52 | * We always prescale, but if someone really doesn't want to they can set this | ||
53 | * to 0 | ||
54 | */ | ||
55 | static int prescale = 1; | ||
56 | static unsigned int timeout_sec; | ||
57 | |||
58 | static unsigned long wdt_is_open; | ||
59 | static DEFINE_SPINLOCK(wdt_spinlock); | ||
60 | |||
61 | static void mpc83xx_wdt_keepalive(void) | ||
62 | { | ||
63 | /* Ping the WDT */ | ||
64 | spin_lock(&wdt_spinlock); | ||
65 | out_be16(&wd_base->swsrr, 0x556c); | ||
66 | out_be16(&wd_base->swsrr, 0xaa39); | ||
67 | spin_unlock(&wdt_spinlock); | ||
68 | } | ||
69 | |||
70 | static ssize_t mpc83xx_wdt_write(struct file *file, const char __user *buf, | ||
71 | size_t count, loff_t *ppos) | ||
72 | { | ||
73 | if (count) | ||
74 | mpc83xx_wdt_keepalive(); | ||
75 | return count; | ||
76 | } | ||
77 | |||
78 | static int mpc83xx_wdt_open(struct inode *inode, struct file *file) | ||
79 | { | ||
80 | u32 tmp = SWCRR_SWEN; | ||
81 | if (test_and_set_bit(0, &wdt_is_open)) | ||
82 | return -EBUSY; | ||
83 | |||
84 | /* Once we start the watchdog we can't stop it */ | ||
85 | __module_get(THIS_MODULE); | ||
86 | |||
87 | /* Good, fire up the show */ | ||
88 | if (prescale) | ||
89 | tmp |= SWCRR_SWPR; | ||
90 | if (reset) | ||
91 | tmp |= SWCRR_SWRI; | ||
92 | |||
93 | tmp |= timeout << 16; | ||
94 | |||
95 | out_be32(&wd_base->swcrr, tmp); | ||
96 | |||
97 | return nonseekable_open(inode, file); | ||
98 | } | ||
99 | |||
100 | static int mpc83xx_wdt_release(struct inode *inode, struct file *file) | ||
101 | { | ||
102 | printk(KERN_CRIT "Unexpected close, not stopping watchdog!\n"); | ||
103 | mpc83xx_wdt_keepalive(); | ||
104 | clear_bit(0, &wdt_is_open); | ||
105 | return 0; | ||
106 | } | ||
107 | |||
108 | static int mpc83xx_wdt_ioctl(struct inode *inode, struct file *file, | ||
109 | unsigned int cmd, unsigned long arg) | ||
110 | { | ||
111 | void __user *argp = (void __user *)arg; | ||
112 | int __user *p = argp; | ||
113 | static struct watchdog_info ident = { | ||
114 | .options = WDIOF_KEEPALIVEPING, | ||
115 | .firmware_version = 1, | ||
116 | .identity = "MPC83xx", | ||
117 | }; | ||
118 | |||
119 | switch (cmd) { | ||
120 | case WDIOC_GETSUPPORT: | ||
121 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
122 | case WDIOC_GETSTATUS: | ||
123 | case WDIOC_GETBOOTSTATUS: | ||
124 | return put_user(0, p); | ||
125 | case WDIOC_KEEPALIVE: | ||
126 | mpc83xx_wdt_keepalive(); | ||
127 | return 0; | ||
128 | case WDIOC_GETTIMEOUT: | ||
129 | return put_user(timeout_sec, p); | ||
130 | default: | ||
131 | return -ENOTTY; | ||
132 | } | ||
133 | } | ||
134 | |||
135 | static const struct file_operations mpc83xx_wdt_fops = { | ||
136 | .owner = THIS_MODULE, | ||
137 | .llseek = no_llseek, | ||
138 | .write = mpc83xx_wdt_write, | ||
139 | .ioctl = mpc83xx_wdt_ioctl, | ||
140 | .open = mpc83xx_wdt_open, | ||
141 | .release = mpc83xx_wdt_release, | ||
142 | }; | ||
143 | |||
144 | static struct miscdevice mpc83xx_wdt_miscdev = { | ||
145 | .minor = WATCHDOG_MINOR, | ||
146 | .name = "watchdog", | ||
147 | .fops = &mpc83xx_wdt_fops, | ||
148 | }; | ||
149 | |||
150 | static int __devinit mpc83xx_wdt_probe(struct platform_device *dev) | ||
151 | { | ||
152 | struct resource *r; | ||
153 | int ret; | ||
154 | unsigned int *freq = dev->dev.platform_data; | ||
155 | |||
156 | /* get a pointer to the register memory */ | ||
157 | r = platform_get_resource(dev, IORESOURCE_MEM, 0); | ||
158 | |||
159 | if (!r) { | ||
160 | ret = -ENODEV; | ||
161 | goto err_out; | ||
162 | } | ||
163 | |||
164 | wd_base = ioremap(r->start, sizeof (struct mpc83xx_wdt)); | ||
165 | |||
166 | if (wd_base == NULL) { | ||
167 | ret = -ENOMEM; | ||
168 | goto err_out; | ||
169 | } | ||
170 | |||
171 | ret = misc_register(&mpc83xx_wdt_miscdev); | ||
172 | if (ret) { | ||
173 | printk(KERN_ERR "cannot register miscdev on minor=%d " | ||
174 | "(err=%d)\n", | ||
175 | WATCHDOG_MINOR, ret); | ||
176 | goto err_unmap; | ||
177 | } | ||
178 | |||
179 | /* Calculate the timeout in seconds */ | ||
180 | if (prescale) | ||
181 | timeout_sec = (timeout * 0x10000) / (*freq); | ||
182 | else | ||
183 | timeout_sec = timeout / (*freq); | ||
184 | |||
185 | printk(KERN_INFO "WDT driver for MPC83xx initialized. " | ||
186 | "mode:%s timeout=%d (%d seconds)\n", | ||
187 | reset ? "reset":"interrupt", timeout, timeout_sec); | ||
188 | return 0; | ||
189 | |||
190 | err_unmap: | ||
191 | iounmap(wd_base); | ||
192 | err_out: | ||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | static int __devexit mpc83xx_wdt_remove(struct platform_device *dev) | ||
197 | { | ||
198 | misc_deregister(&mpc83xx_wdt_miscdev); | ||
199 | iounmap(wd_base); | ||
200 | |||
201 | return 0; | ||
202 | } | ||
203 | |||
204 | static struct platform_driver mpc83xx_wdt_driver = { | ||
205 | .probe = mpc83xx_wdt_probe, | ||
206 | .remove = __devexit_p(mpc83xx_wdt_remove), | ||
207 | .driver = { | ||
208 | .name = "mpc83xx_wdt", | ||
209 | .owner = THIS_MODULE, | ||
210 | }, | ||
211 | }; | ||
212 | |||
213 | static int __init mpc83xx_wdt_init(void) | ||
214 | { | ||
215 | return platform_driver_register(&mpc83xx_wdt_driver); | ||
216 | } | ||
217 | |||
218 | static void __exit mpc83xx_wdt_exit(void) | ||
219 | { | ||
220 | platform_driver_unregister(&mpc83xx_wdt_driver); | ||
221 | } | ||
222 | |||
223 | module_init(mpc83xx_wdt_init); | ||
224 | module_exit(mpc83xx_wdt_exit); | ||
225 | |||
226 | MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); | ||
227 | MODULE_DESCRIPTION("Driver for watchdog timer in MPC83xx uProcessor"); | ||
228 | MODULE_LICENSE("GPL"); | ||
229 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
230 | MODULE_ALIAS("platform:mpc83xx_wdt"); | ||
diff --git a/drivers/watchdog/mpc8xx_wdt.c b/drivers/watchdog/mpc8xx_wdt.c index 85b5734403a5..1336425acf20 100644 --- a/drivers/watchdog/mpc8xx_wdt.c +++ b/drivers/watchdog/mpc8xx_wdt.c | |||
@@ -16,36 +16,35 @@ | |||
16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
17 | #include <linux/watchdog.h> | 17 | #include <linux/watchdog.h> |
18 | #include <asm/8xx_immap.h> | 18 | #include <asm/8xx_immap.h> |
19 | #include <asm/uaccess.h> | 19 | #include <linux/uaccess.h> |
20 | #include <asm/io.h> | 20 | #include <linux/io.h> |
21 | #include <syslib/m8xx_wdt.h> | 21 | #include <syslib/m8xx_wdt.h> |
22 | 22 | ||
23 | static unsigned long wdt_opened; | 23 | static unsigned long wdt_opened; |
24 | static int wdt_status; | 24 | static int wdt_status; |
25 | static spinlock_t wdt_lock; | ||
25 | 26 | ||
26 | static void mpc8xx_wdt_handler_disable(void) | 27 | static void mpc8xx_wdt_handler_disable(void) |
27 | { | 28 | { |
28 | volatile uint __iomem *piscr; | 29 | volatile uint __iomem *piscr; |
29 | piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr; | 30 | piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr; |
30 | 31 | ||
31 | if (!m8xx_has_internal_rtc) | 32 | if (!m8xx_has_internal_rtc) |
32 | m8xx_wdt_stop_timer(); | 33 | m8xx_wdt_stop_timer(); |
33 | else | 34 | else |
34 | out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE)); | 35 | out_be32(piscr, in_be32(piscr) & ~(PISCR_PIE | PISCR_PTE)); |
35 | |||
36 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); | 36 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler deactivated\n"); |
37 | } | 37 | } |
38 | 38 | ||
39 | static void mpc8xx_wdt_handler_enable(void) | 39 | static void mpc8xx_wdt_handler_enable(void) |
40 | { | 40 | { |
41 | volatile uint __iomem *piscr; | 41 | volatile uint __iomem *piscr; |
42 | piscr = (uint *)&((immap_t*)IMAP_ADDR)->im_sit.sit_piscr; | 42 | piscr = (uint *)&((immap_t *)IMAP_ADDR)->im_sit.sit_piscr; |
43 | 43 | ||
44 | if (!m8xx_has_internal_rtc) | 44 | if (!m8xx_has_internal_rtc) |
45 | m8xx_wdt_install_timer(); | 45 | m8xx_wdt_install_timer(); |
46 | else | 46 | else |
47 | out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE); | 47 | out_be32(piscr, in_be32(piscr) | PISCR_PIE | PISCR_PTE); |
48 | |||
49 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); | 48 | printk(KERN_NOTICE "mpc8xx_wdt: keep-alive handler activated\n"); |
50 | } | 49 | } |
51 | 50 | ||
@@ -53,37 +52,34 @@ static int mpc8xx_wdt_open(struct inode *inode, struct file *file) | |||
53 | { | 52 | { |
54 | if (test_and_set_bit(0, &wdt_opened)) | 53 | if (test_and_set_bit(0, &wdt_opened)) |
55 | return -EBUSY; | 54 | return -EBUSY; |
56 | |||
57 | m8xx_wdt_reset(); | 55 | m8xx_wdt_reset(); |
58 | mpc8xx_wdt_handler_disable(); | 56 | mpc8xx_wdt_handler_disable(); |
59 | |||
60 | return nonseekable_open(inode, file); | 57 | return nonseekable_open(inode, file); |
61 | } | 58 | } |
62 | 59 | ||
63 | static int mpc8xx_wdt_release(struct inode *inode, struct file *file) | 60 | static int mpc8xx_wdt_release(struct inode *inode, struct file *file) |
64 | { | 61 | { |
65 | m8xx_wdt_reset(); | 62 | m8xx_wdt_reset(); |
66 | |||
67 | #if !defined(CONFIG_WATCHDOG_NOWAYOUT) | 63 | #if !defined(CONFIG_WATCHDOG_NOWAYOUT) |
68 | mpc8xx_wdt_handler_enable(); | 64 | mpc8xx_wdt_handler_enable(); |
69 | #endif | 65 | #endif |
70 | |||
71 | clear_bit(0, &wdt_opened); | 66 | clear_bit(0, &wdt_opened); |
72 | |||
73 | return 0; | 67 | return 0; |
74 | } | 68 | } |
75 | 69 | ||
76 | static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, size_t len, | 70 | static ssize_t mpc8xx_wdt_write(struct file *file, const char *data, |
77 | loff_t * ppos) | 71 | size_t len, loff_t *ppos) |
78 | { | 72 | { |
79 | if (len) | 73 | if (len) { |
74 | spin_lock(&wdt_lock); | ||
80 | m8xx_wdt_reset(); | 75 | m8xx_wdt_reset(); |
81 | 76 | spin_unlock(&wdt_lock); | |
77 | } | ||
82 | return len; | 78 | return len; |
83 | } | 79 | } |
84 | 80 | ||
85 | static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file, | 81 | static long mpc8xx_wdt_ioctl(struct file *file, |
86 | unsigned int cmd, unsigned long arg) | 82 | unsigned int cmd, unsigned long arg) |
87 | { | 83 | { |
88 | int timeout; | 84 | int timeout; |
89 | static struct watchdog_info info = { | 85 | static struct watchdog_info info = { |
@@ -112,15 +108,19 @@ static int mpc8xx_wdt_ioctl(struct inode *inode, struct file *file, | |||
112 | return -EOPNOTSUPP; | 108 | return -EOPNOTSUPP; |
113 | 109 | ||
114 | case WDIOC_KEEPALIVE: | 110 | case WDIOC_KEEPALIVE: |
111 | spin_lock(&wdt_lock); | ||
115 | m8xx_wdt_reset(); | 112 | m8xx_wdt_reset(); |
116 | wdt_status |= WDIOF_KEEPALIVEPING; | 113 | wdt_status |= WDIOF_KEEPALIVEPING; |
114 | spin_unlock(&wdt_lock); | ||
117 | break; | 115 | break; |
118 | 116 | ||
119 | case WDIOC_SETTIMEOUT: | 117 | case WDIOC_SETTIMEOUT: |
120 | return -EOPNOTSUPP; | 118 | return -EOPNOTSUPP; |
121 | 119 | ||
122 | case WDIOC_GETTIMEOUT: | 120 | case WDIOC_GETTIMEOUT: |
121 | spin_lock(&wdt_lock); | ||
123 | timeout = m8xx_wdt_get_timeout(); | 122 | timeout = m8xx_wdt_get_timeout(); |
123 | spin_unlock(&wdt_lock); | ||
124 | if (put_user(timeout, (int *)arg)) | 124 | if (put_user(timeout, (int *)arg)) |
125 | return -EFAULT; | 125 | return -EFAULT; |
126 | break; | 126 | break; |
@@ -136,7 +136,7 @@ static const struct file_operations mpc8xx_wdt_fops = { | |||
136 | .owner = THIS_MODULE, | 136 | .owner = THIS_MODULE, |
137 | .llseek = no_llseek, | 137 | .llseek = no_llseek, |
138 | .write = mpc8xx_wdt_write, | 138 | .write = mpc8xx_wdt_write, |
139 | .ioctl = mpc8xx_wdt_ioctl, | 139 | .unlocked_ioctl = mpc8xx_wdt_ioctl, |
140 | .open = mpc8xx_wdt_open, | 140 | .open = mpc8xx_wdt_open, |
141 | .release = mpc8xx_wdt_release, | 141 | .release = mpc8xx_wdt_release, |
142 | }; | 142 | }; |
@@ -149,6 +149,7 @@ static struct miscdevice mpc8xx_wdt_miscdev = { | |||
149 | 149 | ||
150 | static int __init mpc8xx_wdt_init(void) | 150 | static int __init mpc8xx_wdt_init(void) |
151 | { | 151 | { |
152 | spin_lock_init(&wdt_lock); | ||
152 | return misc_register(&mpc8xx_wdt_miscdev); | 153 | return misc_register(&mpc8xx_wdt_miscdev); |
153 | } | 154 | } |
154 | 155 | ||
diff --git a/drivers/watchdog/mpc8xxx_wdt.c b/drivers/watchdog/mpc8xxx_wdt.c new file mode 100644 index 000000000000..f2094960e662 --- /dev/null +++ b/drivers/watchdog/mpc8xxx_wdt.c | |||
@@ -0,0 +1,316 @@ | |||
1 | /* | ||
2 | * mpc8xxx_wdt.c - MPC8xx/MPC83xx/MPC86xx watchdog userspace interface | ||
3 | * | ||
4 | * Authors: Dave Updegraff <dave@cray.org> | ||
5 | * Kumar Gala <galak@kernel.crashing.org> | ||
6 | * Attribution: from 83xx_wst: Florian Schirmer <jolt@tuxbox.org> | ||
7 | * ..and from sc520_wdt | ||
8 | * Copyright (c) 2008 MontaVista Software, Inc. | ||
9 | * Anton Vorontsov <avorontsov@ru.mvista.com> | ||
10 | * | ||
11 | * Note: it appears that you can only actually ENABLE or DISABLE the thing | ||
12 | * once after POR. Once enabled, you cannot disable, and vice versa. | ||
13 | * | ||
14 | * This program is free software; you can redistribute it and/or modify it | ||
15 | * under the terms of the GNU General Public License as published by the | ||
16 | * Free Software Foundation; either version 2 of the License, or (at your | ||
17 | * option) any later version. | ||
18 | */ | ||
19 | |||
20 | #include <linux/fs.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/timer.h> | ||
24 | #include <linux/miscdevice.h> | ||
25 | #include <linux/of_platform.h> | ||
26 | #include <linux/module.h> | ||
27 | #include <linux/watchdog.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/uaccess.h> | ||
30 | #include <sysdev/fsl_soc.h> | ||
31 | |||
32 | struct mpc8xxx_wdt { | ||
33 | __be32 res0; | ||
34 | __be32 swcrr; /* System watchdog control register */ | ||
35 | #define SWCRR_SWTC 0xFFFF0000 /* Software Watchdog Time Count. */ | ||
36 | #define SWCRR_SWEN 0x00000004 /* Watchdog Enable bit. */ | ||
37 | #define SWCRR_SWRI 0x00000002 /* Software Watchdog Reset/Interrupt Select bit.*/ | ||
38 | #define SWCRR_SWPR 0x00000001 /* Software Watchdog Counter Prescale bit. */ | ||
39 | __be32 swcnr; /* System watchdog count register */ | ||
40 | u8 res1[2]; | ||
41 | __be16 swsrr; /* System watchdog service register */ | ||
42 | u8 res2[0xF0]; | ||
43 | }; | ||
44 | |||
45 | struct mpc8xxx_wdt_type { | ||
46 | int prescaler; | ||
47 | bool hw_enabled; | ||
48 | }; | ||
49 | |||
50 | static struct mpc8xxx_wdt __iomem *wd_base; | ||
51 | |||
52 | static u16 timeout = 0xffff; | ||
53 | module_param(timeout, ushort, 0); | ||
54 | MODULE_PARM_DESC(timeout, | ||
55 | "Watchdog timeout in ticks. (0<timeout<65536, default=65535"); | ||
56 | |||
57 | static int reset = 1; | ||
58 | module_param(reset, bool, 0); | ||
59 | MODULE_PARM_DESC(reset, | ||
60 | "Watchdog Interrupt/Reset Mode. 0 = interrupt, 1 = reset"); | ||
61 | |||
62 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
63 | module_param(nowayout, int, 0); | ||
64 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | ||
65 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
66 | |||
67 | /* | ||
68 | * We always prescale, but if someone really doesn't want to they can set this | ||
69 | * to 0 | ||
70 | */ | ||
71 | static int prescale = 1; | ||
72 | static unsigned int timeout_sec; | ||
73 | |||
74 | static unsigned long wdt_is_open; | ||
75 | static DEFINE_SPINLOCK(wdt_spinlock); | ||
76 | |||
77 | static void mpc8xxx_wdt_keepalive(void) | ||
78 | { | ||
79 | /* Ping the WDT */ | ||
80 | spin_lock(&wdt_spinlock); | ||
81 | out_be16(&wd_base->swsrr, 0x556c); | ||
82 | out_be16(&wd_base->swsrr, 0xaa39); | ||
83 | spin_unlock(&wdt_spinlock); | ||
84 | } | ||
85 | |||
86 | static void mpc8xxx_wdt_timer_ping(unsigned long arg); | ||
87 | static DEFINE_TIMER(wdt_timer, mpc8xxx_wdt_timer_ping, 0, 0); | ||
88 | |||
89 | static void mpc8xxx_wdt_timer_ping(unsigned long arg) | ||
90 | { | ||
91 | mpc8xxx_wdt_keepalive(); | ||
92 | /* We're pinging it twice faster than needed, just to be sure. */ | ||
93 | mod_timer(&wdt_timer, jiffies + HZ * timeout_sec / 2); | ||
94 | } | ||
95 | |||
96 | static void mpc8xxx_wdt_pr_warn(const char *msg) | ||
97 | { | ||
98 | pr_crit("mpc8xxx_wdt: %s, expect the %s soon!\n", msg, | ||
99 | reset ? "reset" : "machine check exception"); | ||
100 | } | ||
101 | |||
102 | static ssize_t mpc8xxx_wdt_write(struct file *file, const char __user *buf, | ||
103 | size_t count, loff_t *ppos) | ||
104 | { | ||
105 | if (count) | ||
106 | mpc8xxx_wdt_keepalive(); | ||
107 | return count; | ||
108 | } | ||
109 | |||
110 | static int mpc8xxx_wdt_open(struct inode *inode, struct file *file) | ||
111 | { | ||
112 | u32 tmp = SWCRR_SWEN; | ||
113 | if (test_and_set_bit(0, &wdt_is_open)) | ||
114 | return -EBUSY; | ||
115 | |||
116 | /* Once we start the watchdog we can't stop it */ | ||
117 | if (nowayout) | ||
118 | __module_get(THIS_MODULE); | ||
119 | |||
120 | /* Good, fire up the show */ | ||
121 | if (prescale) | ||
122 | tmp |= SWCRR_SWPR; | ||
123 | if (reset) | ||
124 | tmp |= SWCRR_SWRI; | ||
125 | |||
126 | tmp |= timeout << 16; | ||
127 | |||
128 | out_be32(&wd_base->swcrr, tmp); | ||
129 | |||
130 | del_timer_sync(&wdt_timer); | ||
131 | |||
132 | return nonseekable_open(inode, file); | ||
133 | } | ||
134 | |||
135 | static int mpc8xxx_wdt_release(struct inode *inode, struct file *file) | ||
136 | { | ||
137 | if (!nowayout) | ||
138 | mpc8xxx_wdt_timer_ping(0); | ||
139 | else | ||
140 | mpc8xxx_wdt_pr_warn("watchdog closed"); | ||
141 | clear_bit(0, &wdt_is_open); | ||
142 | return 0; | ||
143 | } | ||
144 | |||
145 | static long mpc8xxx_wdt_ioctl(struct file *file, unsigned int cmd, | ||
146 | unsigned long arg) | ||
147 | { | ||
148 | void __user *argp = (void __user *)arg; | ||
149 | int __user *p = argp; | ||
150 | static struct watchdog_info ident = { | ||
151 | .options = WDIOF_KEEPALIVEPING, | ||
152 | .firmware_version = 1, | ||
153 | .identity = "MPC8xxx", | ||
154 | }; | ||
155 | |||
156 | switch (cmd) { | ||
157 | case WDIOC_GETSUPPORT: | ||
158 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
159 | case WDIOC_GETSTATUS: | ||
160 | case WDIOC_GETBOOTSTATUS: | ||
161 | return put_user(0, p); | ||
162 | case WDIOC_KEEPALIVE: | ||
163 | mpc8xxx_wdt_keepalive(); | ||
164 | return 0; | ||
165 | case WDIOC_GETTIMEOUT: | ||
166 | return put_user(timeout_sec, p); | ||
167 | default: | ||
168 | return -ENOTTY; | ||
169 | } | ||
170 | } | ||
171 | |||
172 | static const struct file_operations mpc8xxx_wdt_fops = { | ||
173 | .owner = THIS_MODULE, | ||
174 | .llseek = no_llseek, | ||
175 | .write = mpc8xxx_wdt_write, | ||
176 | .unlocked_ioctl = mpc8xxx_wdt_ioctl, | ||
177 | .open = mpc8xxx_wdt_open, | ||
178 | .release = mpc8xxx_wdt_release, | ||
179 | }; | ||
180 | |||
181 | static struct miscdevice mpc8xxx_wdt_miscdev = { | ||
182 | .minor = WATCHDOG_MINOR, | ||
183 | .name = "watchdog", | ||
184 | .fops = &mpc8xxx_wdt_fops, | ||
185 | }; | ||
186 | |||
187 | static int __devinit mpc8xxx_wdt_probe(struct of_device *ofdev, | ||
188 | const struct of_device_id *match) | ||
189 | { | ||
190 | int ret; | ||
191 | struct device_node *np = ofdev->node; | ||
192 | struct mpc8xxx_wdt_type *wdt_type = match->data; | ||
193 | u32 freq = fsl_get_sys_freq(); | ||
194 | bool enabled; | ||
195 | |||
196 | if (!freq || freq == -1) | ||
197 | return -EINVAL; | ||
198 | |||
199 | wd_base = of_iomap(np, 0); | ||
200 | if (!wd_base) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | enabled = in_be32(&wd_base->swcrr) & SWCRR_SWEN; | ||
204 | if (!enabled && wdt_type->hw_enabled) { | ||
205 | pr_info("mpc8xxx_wdt: could not be enabled in software\n"); | ||
206 | ret = -ENOSYS; | ||
207 | goto err_unmap; | ||
208 | } | ||
209 | |||
210 | /* Calculate the timeout in seconds */ | ||
211 | if (prescale) | ||
212 | timeout_sec = (timeout * wdt_type->prescaler) / freq; | ||
213 | else | ||
214 | timeout_sec = timeout / freq; | ||
215 | |||
216 | pr_info("WDT driver for MPC8xxx initialized. mode:%s timeout=%d " | ||
217 | "(%d seconds)\n", reset ? "reset" : "interrupt", timeout, | ||
218 | timeout_sec); | ||
219 | |||
220 | /* | ||
221 | * If the watchdog was previously enabled or we're running on | ||
222 | * MPC8xxx, we should ping the wdt from the kernel until the | ||
223 | * userspace handles it. | ||
224 | */ | ||
225 | if (enabled) | ||
226 | mpc8xxx_wdt_timer_ping(0); | ||
227 | return 0; | ||
228 | err_unmap: | ||
229 | iounmap(wd_base); | ||
230 | wd_base = NULL; | ||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | static int __devexit mpc8xxx_wdt_remove(struct of_device *ofdev) | ||
235 | { | ||
236 | mpc8xxx_wdt_pr_warn("watchdog removed"); | ||
237 | del_timer_sync(&wdt_timer); | ||
238 | misc_deregister(&mpc8xxx_wdt_miscdev); | ||
239 | iounmap(wd_base); | ||
240 | |||
241 | return 0; | ||
242 | } | ||
243 | |||
244 | static const struct of_device_id mpc8xxx_wdt_match[] = { | ||
245 | { | ||
246 | .compatible = "mpc83xx_wdt", | ||
247 | .data = &(struct mpc8xxx_wdt_type) { | ||
248 | .prescaler = 0x10000, | ||
249 | }, | ||
250 | }, | ||
251 | { | ||
252 | .compatible = "fsl,mpc8610-wdt", | ||
253 | .data = &(struct mpc8xxx_wdt_type) { | ||
254 | .prescaler = 0x10000, | ||
255 | .hw_enabled = true, | ||
256 | }, | ||
257 | }, | ||
258 | { | ||
259 | .compatible = "fsl,mpc823-wdt", | ||
260 | .data = &(struct mpc8xxx_wdt_type) { | ||
261 | .prescaler = 0x800, | ||
262 | }, | ||
263 | }, | ||
264 | {}, | ||
265 | }; | ||
266 | MODULE_DEVICE_TABLE(of, mpc8xxx_wdt_match); | ||
267 | |||
268 | static struct of_platform_driver mpc8xxx_wdt_driver = { | ||
269 | .match_table = mpc8xxx_wdt_match, | ||
270 | .probe = mpc8xxx_wdt_probe, | ||
271 | .remove = __devexit_p(mpc8xxx_wdt_remove), | ||
272 | .driver = { | ||
273 | .name = "mpc8xxx_wdt", | ||
274 | .owner = THIS_MODULE, | ||
275 | }, | ||
276 | }; | ||
277 | |||
278 | /* | ||
279 | * We do wdt initialization in two steps: arch_initcall probes the wdt | ||
280 | * very early to start pinging the watchdog (misc devices are not yet | ||
281 | * available), and later module_init() just registers the misc device. | ||
282 | */ | ||
283 | static int __init mpc8xxx_wdt_init_late(void) | ||
284 | { | ||
285 | int ret; | ||
286 | |||
287 | if (!wd_base) | ||
288 | return -ENODEV; | ||
289 | |||
290 | ret = misc_register(&mpc8xxx_wdt_miscdev); | ||
291 | if (ret) { | ||
292 | pr_err("cannot register miscdev on minor=%d (err=%d)\n", | ||
293 | WATCHDOG_MINOR, ret); | ||
294 | return ret; | ||
295 | } | ||
296 | return 0; | ||
297 | } | ||
298 | module_init(mpc8xxx_wdt_init_late); | ||
299 | |||
300 | static int __init mpc8xxx_wdt_init(void) | ||
301 | { | ||
302 | return of_register_platform_driver(&mpc8xxx_wdt_driver); | ||
303 | } | ||
304 | arch_initcall(mpc8xxx_wdt_init); | ||
305 | |||
306 | static void __exit mpc8xxx_wdt_exit(void) | ||
307 | { | ||
308 | of_unregister_platform_driver(&mpc8xxx_wdt_driver); | ||
309 | } | ||
310 | module_exit(mpc8xxx_wdt_exit); | ||
311 | |||
312 | MODULE_AUTHOR("Dave Updegraff, Kumar Gala"); | ||
313 | MODULE_DESCRIPTION("Driver for watchdog timer in MPC8xx/MPC83xx/MPC86xx " | ||
314 | "uProcessors"); | ||
315 | MODULE_LICENSE("GPL"); | ||
316 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/mpcore_wdt.c b/drivers/watchdog/mpcore_wdt.c index 009573b81496..2a9bfa81f9d6 100644 --- a/drivers/watchdog/mpcore_wdt.c +++ b/drivers/watchdog/mpcore_wdt.c | |||
@@ -29,9 +29,9 @@ | |||
29 | #include <linux/init.h> | 29 | #include <linux/init.h> |
30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
31 | #include <linux/platform_device.h> | 31 | #include <linux/platform_device.h> |
32 | #include <linux/uaccess.h> | ||
32 | 33 | ||
33 | #include <asm/hardware/arm_twd.h> | 34 | #include <asm/hardware/arm_twd.h> |
34 | #include <asm/uaccess.h> | ||
35 | 35 | ||
36 | struct mpcore_wdt { | 36 | struct mpcore_wdt { |
37 | unsigned long timer_alive; | 37 | unsigned long timer_alive; |
@@ -43,17 +43,20 @@ struct mpcore_wdt { | |||
43 | }; | 43 | }; |
44 | 44 | ||
45 | static struct platform_device *mpcore_wdt_dev; | 45 | static struct platform_device *mpcore_wdt_dev; |
46 | |||
47 | extern unsigned int mpcore_timer_rate; | 46 | extern unsigned int mpcore_timer_rate; |
48 | 47 | ||
49 | #define TIMER_MARGIN 60 | 48 | #define TIMER_MARGIN 60 |
50 | static int mpcore_margin = TIMER_MARGIN; | 49 | static int mpcore_margin = TIMER_MARGIN; |
51 | module_param(mpcore_margin, int, 0); | 50 | module_param(mpcore_margin, int, 0); |
52 | MODULE_PARM_DESC(mpcore_margin, "MPcore timer margin in seconds. (0<mpcore_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); | 51 | MODULE_PARM_DESC(mpcore_margin, |
52 | "MPcore timer margin in seconds. (0 < mpcore_margin < 65536, default=" | ||
53 | __MODULE_STRING(TIMER_MARGIN) ")"); | ||
53 | 54 | ||
54 | static int nowayout = WATCHDOG_NOWAYOUT; | 55 | static int nowayout = WATCHDOG_NOWAYOUT; |
55 | module_param(nowayout, int, 0); | 56 | module_param(nowayout, int, 0); |
56 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 57 | MODULE_PARM_DESC(nowayout, |
58 | "Watchdog cannot be stopped once started (default=" | ||
59 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
57 | 60 | ||
58 | #define ONLY_TESTING 0 | 61 | #define ONLY_TESTING 0 |
59 | static int mpcore_noboot = ONLY_TESTING; | 62 | static int mpcore_noboot = ONLY_TESTING; |
@@ -70,14 +73,12 @@ static irqreturn_t mpcore_wdt_fire(int irq, void *arg) | |||
70 | 73 | ||
71 | /* Check it really was our interrupt */ | 74 | /* Check it really was our interrupt */ |
72 | if (readl(wdt->base + TWD_WDOG_INTSTAT)) { | 75 | if (readl(wdt->base + TWD_WDOG_INTSTAT)) { |
73 | dev_printk(KERN_CRIT, wdt->dev, "Triggered - Reboot ignored.\n"); | 76 | dev_printk(KERN_CRIT, wdt->dev, |
74 | 77 | "Triggered - Reboot ignored.\n"); | |
75 | /* Clear the interrupt on the watchdog */ | 78 | /* Clear the interrupt on the watchdog */ |
76 | writel(1, wdt->base + TWD_WDOG_INTSTAT); | 79 | writel(1, wdt->base + TWD_WDOG_INTSTAT); |
77 | |||
78 | return IRQ_HANDLED; | 80 | return IRQ_HANDLED; |
79 | } | 81 | } |
80 | |||
81 | return IRQ_NONE; | 82 | return IRQ_NONE; |
82 | } | 83 | } |
83 | 84 | ||
@@ -96,22 +97,26 @@ static void mpcore_wdt_keepalive(struct mpcore_wdt *wdt) | |||
96 | count = (mpcore_timer_rate / 256) * mpcore_margin; | 97 | count = (mpcore_timer_rate / 256) * mpcore_margin; |
97 | 98 | ||
98 | /* Reload the counter */ | 99 | /* Reload the counter */ |
100 | spin_lock(&wdt_lock); | ||
99 | writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); | 101 | writel(count + wdt->perturb, wdt->base + TWD_WDOG_LOAD); |
100 | |||
101 | wdt->perturb = wdt->perturb ? 0 : 1; | 102 | wdt->perturb = wdt->perturb ? 0 : 1; |
103 | spin_unlock(&wdt_lock); | ||
102 | } | 104 | } |
103 | 105 | ||
104 | static void mpcore_wdt_stop(struct mpcore_wdt *wdt) | 106 | static void mpcore_wdt_stop(struct mpcore_wdt *wdt) |
105 | { | 107 | { |
108 | spin_lock(&wdt_lock); | ||
106 | writel(0x12345678, wdt->base + TWD_WDOG_DISABLE); | 109 | writel(0x12345678, wdt->base + TWD_WDOG_DISABLE); |
107 | writel(0x87654321, wdt->base + TWD_WDOG_DISABLE); | 110 | writel(0x87654321, wdt->base + TWD_WDOG_DISABLE); |
108 | writel(0x0, wdt->base + TWD_WDOG_CONTROL); | 111 | writel(0x0, wdt->base + TWD_WDOG_CONTROL); |
112 | spin_unlock(&wdt_lock); | ||
109 | } | 113 | } |
110 | 114 | ||
111 | static void mpcore_wdt_start(struct mpcore_wdt *wdt) | 115 | static void mpcore_wdt_start(struct mpcore_wdt *wdt) |
112 | { | 116 | { |
113 | dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); | 117 | dev_printk(KERN_INFO, wdt->dev, "enabling watchdog.\n"); |
114 | 118 | ||
119 | spin_lock(&wdt_lock); | ||
115 | /* This loads the count register but does NOT start the count yet */ | 120 | /* This loads the count register but does NOT start the count yet */ |
116 | mpcore_wdt_keepalive(wdt); | 121 | mpcore_wdt_keepalive(wdt); |
117 | 122 | ||
@@ -122,6 +127,7 @@ static void mpcore_wdt_start(struct mpcore_wdt *wdt) | |||
122 | /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ | 127 | /* Enable watchdog - prescale=256, watchdog mode=1, enable=1 */ |
123 | writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); | 128 | writel(0x0000FF09, wdt->base + TWD_WDOG_CONTROL); |
124 | } | 129 | } |
130 | spin_unlock(&wdt_lock); | ||
125 | } | 131 | } |
126 | 132 | ||
127 | static int mpcore_wdt_set_heartbeat(int t) | 133 | static int mpcore_wdt_set_heartbeat(int t) |
@@ -164,10 +170,11 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file) | |||
164 | * Shut off the timer. | 170 | * Shut off the timer. |
165 | * Lock it in if it's a module and we set nowayout | 171 | * Lock it in if it's a module and we set nowayout |
166 | */ | 172 | */ |
167 | if (wdt->expect_close == 42) { | 173 | if (wdt->expect_close == 42) |
168 | mpcore_wdt_stop(wdt); | 174 | mpcore_wdt_stop(wdt); |
169 | } else { | 175 | else { |
170 | dev_printk(KERN_CRIT, wdt->dev, "unexpected close, not stopping watchdog!\n"); | 176 | dev_printk(KERN_CRIT, wdt->dev, |
177 | "unexpected close, not stopping watchdog!\n"); | ||
171 | mpcore_wdt_keepalive(wdt); | 178 | mpcore_wdt_keepalive(wdt); |
172 | } | 179 | } |
173 | clear_bit(0, &wdt->timer_alive); | 180 | clear_bit(0, &wdt->timer_alive); |
@@ -175,7 +182,8 @@ static int mpcore_wdt_release(struct inode *inode, struct file *file) | |||
175 | return 0; | 182 | return 0; |
176 | } | 183 | } |
177 | 184 | ||
178 | static ssize_t mpcore_wdt_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 185 | static ssize_t mpcore_wdt_write(struct file *file, const char *data, |
186 | size_t len, loff_t *ppos) | ||
179 | { | 187 | { |
180 | struct mpcore_wdt *wdt = file->private_data; | 188 | struct mpcore_wdt *wdt = file->private_data; |
181 | 189 | ||
@@ -210,8 +218,8 @@ static struct watchdog_info ident = { | |||
210 | .identity = "MPcore Watchdog", | 218 | .identity = "MPcore Watchdog", |
211 | }; | 219 | }; |
212 | 220 | ||
213 | static int mpcore_wdt_ioctl(struct inode *inode, struct file *file, | 221 | static long mpcore_wdt_ioctl(struct file *file, unsigned int cmd, |
214 | unsigned int cmd, unsigned long arg) | 222 | unsigned long arg) |
215 | { | 223 | { |
216 | struct mpcore_wdt *wdt = file->private_data; | 224 | struct mpcore_wdt *wdt = file->private_data; |
217 | int ret; | 225 | int ret; |
@@ -235,6 +243,12 @@ static int mpcore_wdt_ioctl(struct inode *inode, struct file *file, | |||
235 | ret = 0; | 243 | ret = 0; |
236 | break; | 244 | break; |
237 | 245 | ||
246 | case WDIOC_GETSTATUS: | ||
247 | case WDIOC_GETBOOTSTATUS: | ||
248 | uarg.i = 0; | ||
249 | ret = 0; | ||
250 | break; | ||
251 | |||
238 | case WDIOC_SETOPTIONS: | 252 | case WDIOC_SETOPTIONS: |
239 | ret = -EINVAL; | 253 | ret = -EINVAL; |
240 | if (uarg.i & WDIOS_DISABLECARD) { | 254 | if (uarg.i & WDIOS_DISABLECARD) { |
@@ -247,12 +261,6 @@ static int mpcore_wdt_ioctl(struct inode *inode, struct file *file, | |||
247 | } | 261 | } |
248 | break; | 262 | break; |
249 | 263 | ||
250 | case WDIOC_GETSTATUS: | ||
251 | case WDIOC_GETBOOTSTATUS: | ||
252 | uarg.i = 0; | ||
253 | ret = 0; | ||
254 | break; | ||
255 | |||
256 | case WDIOC_KEEPALIVE: | 264 | case WDIOC_KEEPALIVE: |
257 | mpcore_wdt_keepalive(wdt); | 265 | mpcore_wdt_keepalive(wdt); |
258 | ret = 0; | 266 | ret = 0; |
@@ -301,7 +309,7 @@ static const struct file_operations mpcore_wdt_fops = { | |||
301 | .owner = THIS_MODULE, | 309 | .owner = THIS_MODULE, |
302 | .llseek = no_llseek, | 310 | .llseek = no_llseek, |
303 | .write = mpcore_wdt_write, | 311 | .write = mpcore_wdt_write, |
304 | .ioctl = mpcore_wdt_ioctl, | 312 | .unlocked_ioctl = mpcore_wdt_ioctl, |
305 | .open = mpcore_wdt_open, | 313 | .open = mpcore_wdt_open, |
306 | .release = mpcore_wdt_release, | 314 | .release = mpcore_wdt_release, |
307 | }; | 315 | }; |
@@ -349,14 +357,17 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) | |||
349 | mpcore_wdt_miscdev.parent = &dev->dev; | 357 | mpcore_wdt_miscdev.parent = &dev->dev; |
350 | ret = misc_register(&mpcore_wdt_miscdev); | 358 | ret = misc_register(&mpcore_wdt_miscdev); |
351 | if (ret) { | 359 | if (ret) { |
352 | dev_printk(KERN_ERR, _dev, "cannot register miscdev on minor=%d (err=%d)\n", | 360 | dev_printk(KERN_ERR, _dev, |
353 | WATCHDOG_MINOR, ret); | 361 | "cannot register miscdev on minor=%d (err=%d)\n", |
362 | WATCHDOG_MINOR, ret); | ||
354 | goto err_misc; | 363 | goto err_misc; |
355 | } | 364 | } |
356 | 365 | ||
357 | ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, "mpcore_wdt", wdt); | 366 | ret = request_irq(wdt->irq, mpcore_wdt_fire, IRQF_DISABLED, |
367 | "mpcore_wdt", wdt); | ||
358 | if (ret) { | 368 | if (ret) { |
359 | dev_printk(KERN_ERR, _dev, "cannot register IRQ%d for watchdog\n", wdt->irq); | 369 | dev_printk(KERN_ERR, _dev, |
370 | "cannot register IRQ%d for watchdog\n", wdt->irq); | ||
360 | goto err_irq; | 371 | goto err_irq; |
361 | } | 372 | } |
362 | 373 | ||
@@ -366,13 +377,13 @@ static int __devinit mpcore_wdt_probe(struct platform_device *dev) | |||
366 | 377 | ||
367 | return 0; | 378 | return 0; |
368 | 379 | ||
369 | err_irq: | 380 | err_irq: |
370 | misc_deregister(&mpcore_wdt_miscdev); | 381 | misc_deregister(&mpcore_wdt_miscdev); |
371 | err_misc: | 382 | err_misc: |
372 | iounmap(wdt->base); | 383 | iounmap(wdt->base); |
373 | err_free: | 384 | err_free: |
374 | kfree(wdt); | 385 | kfree(wdt); |
375 | err_out: | 386 | err_out: |
376 | return ret; | 387 | return ret; |
377 | } | 388 | } |
378 | 389 | ||
@@ -415,7 +426,7 @@ static int __init mpcore_wdt_init(void) | |||
415 | */ | 426 | */ |
416 | if (mpcore_wdt_set_heartbeat(mpcore_margin)) { | 427 | if (mpcore_wdt_set_heartbeat(mpcore_margin)) { |
417 | mpcore_wdt_set_heartbeat(TIMER_MARGIN); | 428 | mpcore_wdt_set_heartbeat(TIMER_MARGIN); |
418 | printk(KERN_INFO "mpcore_margin value must be 0<mpcore_margin<65536, using %d\n", | 429 | printk(KERN_INFO "mpcore_margin value must be 0 < mpcore_margin < 65536, using %d\n", |
419 | TIMER_MARGIN); | 430 | TIMER_MARGIN); |
420 | } | 431 | } |
421 | 432 | ||
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c index a8e67383784e..b4b7b0a4c119 100644 --- a/drivers/watchdog/mtx-1_wdt.c +++ b/drivers/watchdog/mtx-1_wdt.c | |||
@@ -1,7 +1,8 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for the MTX-1 Watchdog. | 2 | * Driver for the MTX-1 Watchdog. |
3 | * | 3 | * |
4 | * (C) Copyright 2005 4G Systems <info@4g-systems.biz>, All Rights Reserved. | 4 | * (C) Copyright 2005 4G Systems <info@4g-systems.biz>, |
5 | * All Rights Reserved. | ||
5 | * http://www.4g-systems.biz | 6 | * http://www.4g-systems.biz |
6 | * | 7 | * |
7 | * (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org> | 8 | * (C) Copyright 2007 OpenWrt.org, Florian Fainelli <florian@openwrt.org> |
@@ -46,12 +47,11 @@ | |||
46 | #include <linux/jiffies.h> | 47 | #include <linux/jiffies.h> |
47 | #include <linux/watchdog.h> | 48 | #include <linux/watchdog.h> |
48 | #include <linux/platform_device.h> | 49 | #include <linux/platform_device.h> |
49 | 50 | #include <linux/io.h> | |
50 | #include <asm/io.h> | 51 | #include <linux/uaccess.h> |
51 | #include <asm/uaccess.h> | 52 | #include <linux/gpio.h> |
52 | 53 | ||
53 | #include <asm/mach-au1x00/au1000.h> | 54 | #include <asm/mach-au1x00/au1000.h> |
54 | #include <asm/gpio.h> | ||
55 | 55 | ||
56 | #define MTX1_WDT_INTERVAL (5 * HZ) | 56 | #define MTX1_WDT_INTERVAL (5 * HZ) |
57 | 57 | ||
@@ -59,6 +59,7 @@ static int ticks = 100 * HZ; | |||
59 | 59 | ||
60 | static struct { | 60 | static struct { |
61 | struct completion stop; | 61 | struct completion stop; |
62 | spinlock_t lock; | ||
62 | int running; | 63 | int running; |
63 | struct timer_list timer; | 64 | struct timer_list timer; |
64 | int queue; | 65 | int queue; |
@@ -71,6 +72,7 @@ static void mtx1_wdt_trigger(unsigned long unused) | |||
71 | { | 72 | { |
72 | u32 tmp; | 73 | u32 tmp; |
73 | 74 | ||
75 | spin_lock(&mtx1_wdt_device.lock); | ||
74 | if (mtx1_wdt_device.running) | 76 | if (mtx1_wdt_device.running) |
75 | ticks--; | 77 | ticks--; |
76 | /* | 78 | /* |
@@ -79,13 +81,13 @@ static void mtx1_wdt_trigger(unsigned long unused) | |||
79 | tmp = au_readl(GPIO2_DIR); | 81 | tmp = au_readl(GPIO2_DIR); |
80 | tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) | | 82 | tmp = (tmp & ~(1 << mtx1_wdt_device.gpio)) | |
81 | ((~tmp) & (1 << mtx1_wdt_device.gpio)); | 83 | ((~tmp) & (1 << mtx1_wdt_device.gpio)); |
82 | au_writel (tmp, GPIO2_DIR); | 84 | au_writel(tmp, GPIO2_DIR); |
83 | 85 | ||
84 | if (mtx1_wdt_device.queue && ticks) | 86 | if (mtx1_wdt_device.queue && ticks) |
85 | mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); | 87 | mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); |
86 | else { | 88 | else |
87 | complete(&mtx1_wdt_device.stop); | 89 | complete(&mtx1_wdt_device.stop); |
88 | } | 90 | spin_unlock(&mtx1_wdt_device.lock); |
89 | } | 91 | } |
90 | 92 | ||
91 | static void mtx1_wdt_reset(void) | 93 | static void mtx1_wdt_reset(void) |
@@ -96,23 +98,25 @@ static void mtx1_wdt_reset(void) | |||
96 | 98 | ||
97 | static void mtx1_wdt_start(void) | 99 | static void mtx1_wdt_start(void) |
98 | { | 100 | { |
101 | spin_lock_irqsave(&mtx1_wdt_device.lock, flags); | ||
99 | if (!mtx1_wdt_device.queue) { | 102 | if (!mtx1_wdt_device.queue) { |
100 | mtx1_wdt_device.queue = 1; | 103 | mtx1_wdt_device.queue = 1; |
101 | gpio_set_value(mtx1_wdt_device.gpio, 1); | 104 | gpio_set_value(mtx1_wdt_device.gpio, 1); |
102 | mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); | 105 | mod_timer(&mtx1_wdt_device.timer, jiffies + MTX1_WDT_INTERVAL); |
103 | } | 106 | } |
104 | mtx1_wdt_device.running++; | 107 | mtx1_wdt_device.running++; |
108 | spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags); | ||
105 | } | 109 | } |
106 | 110 | ||
107 | static int mtx1_wdt_stop(void) | 111 | static int mtx1_wdt_stop(void) |
108 | { | 112 | { |
113 | spin_lock_irqsave(&mtx1_wdt_device.lock, flags); | ||
109 | if (mtx1_wdt_device.queue) { | 114 | if (mtx1_wdt_device.queue) { |
110 | mtx1_wdt_device.queue = 0; | 115 | mtx1_wdt_device.queue = 0; |
111 | gpio_set_value(mtx1_wdt_device.gpio, 0); | 116 | gpio_set_value(mtx1_wdt_device.gpio, 0); |
112 | } | 117 | } |
113 | |||
114 | ticks = mtx1_wdt_device.default_ticks; | 118 | ticks = mtx1_wdt_device.default_ticks; |
115 | 119 | spin_unlock_irqrestore(&mtx1_wdt_device.lock, flags); | |
116 | return 0; | 120 | return 0; |
117 | } | 121 | } |
118 | 122 | ||
@@ -122,7 +126,6 @@ static int mtx1_wdt_open(struct inode *inode, struct file *file) | |||
122 | { | 126 | { |
123 | if (test_and_set_bit(0, &mtx1_wdt_device.inuse)) | 127 | if (test_and_set_bit(0, &mtx1_wdt_device.inuse)) |
124 | return -EBUSY; | 128 | return -EBUSY; |
125 | |||
126 | return nonseekable_open(inode, file); | 129 | return nonseekable_open(inode, file); |
127 | } | 130 | } |
128 | 131 | ||
@@ -133,54 +136,51 @@ static int mtx1_wdt_release(struct inode *inode, struct file *file) | |||
133 | return 0; | 136 | return 0; |
134 | } | 137 | } |
135 | 138 | ||
136 | static int mtx1_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 139 | static long mtx1_wdt_ioctl(struct file *file, unsigned int cmd, |
140 | unsigned long arg) | ||
137 | { | 141 | { |
138 | void __user *argp = (void __user *)arg; | 142 | void __user *argp = (void __user *)arg; |
143 | int __user *p = (int __user *)argp; | ||
139 | unsigned int value; | 144 | unsigned int value; |
140 | static struct watchdog_info ident = | 145 | static const struct watchdog_info ident = { |
141 | { | ||
142 | .options = WDIOF_CARDRESET, | 146 | .options = WDIOF_CARDRESET, |
143 | .identity = "MTX-1 WDT", | 147 | .identity = "MTX-1 WDT", |
144 | }; | 148 | }; |
145 | 149 | ||
146 | switch(cmd) { | 150 | switch (cmd) { |
147 | case WDIOC_KEEPALIVE: | 151 | case WDIOC_GETSUPPORT: |
148 | mtx1_wdt_reset(); | 152 | if (copy_to_user(argp, &ident, sizeof(ident))) |
149 | break; | 153 | return -EFAULT; |
150 | case WDIOC_GETSTATUS: | 154 | break; |
151 | case WDIOC_GETBOOTSTATUS: | 155 | case WDIOC_GETSTATUS: |
152 | if ( copy_to_user(argp, &value, sizeof(int)) ) | 156 | case WDIOC_GETBOOTSTATUS: |
153 | return -EFAULT; | 157 | put_user(0, p); |
154 | break; | 158 | break; |
155 | case WDIOC_GETSUPPORT: | 159 | case WDIOC_SETOPTIONS: |
156 | if ( copy_to_user(argp, &ident, sizeof(ident)) ) | 160 | if (get_user(value, p)) |
157 | return -EFAULT; | 161 | return -EFAULT; |
158 | break; | 162 | if (value & WDIOS_ENABLECARD) |
159 | case WDIOC_SETOPTIONS: | 163 | mtx1_wdt_start(); |
160 | if ( copy_from_user(&value, argp, sizeof(int)) ) | 164 | else if (value & WDIOS_DISABLECARD) |
161 | return -EFAULT; | 165 | mtx1_wdt_stop(); |
162 | switch(value) { | 166 | else |
163 | case WDIOS_ENABLECARD: | 167 | return -EINVAL; |
164 | mtx1_wdt_start(); | 168 | return 0; |
165 | break; | 169 | case WDIOC_KEEPALIVE: |
166 | case WDIOS_DISABLECARD: | 170 | mtx1_wdt_reset(); |
167 | return mtx1_wdt_stop(); | 171 | break; |
168 | default: | 172 | default: |
169 | return -EINVAL; | 173 | return -ENOTTY; |
170 | } | ||
171 | break; | ||
172 | default: | ||
173 | return -ENOTTY; | ||
174 | } | 174 | } |
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | 178 | ||
179 | static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, loff_t *ppos) | 179 | static ssize_t mtx1_wdt_write(struct file *file, const char *buf, |
180 | size_t count, loff_t *ppos) | ||
180 | { | 181 | { |
181 | if (!count) | 182 | if (!count) |
182 | return -EIO; | 183 | return -EIO; |
183 | |||
184 | mtx1_wdt_reset(); | 184 | mtx1_wdt_reset(); |
185 | return count; | 185 | return count; |
186 | } | 186 | } |
@@ -188,17 +188,17 @@ static ssize_t mtx1_wdt_write(struct file *file, const char *buf, size_t count, | |||
188 | static const struct file_operations mtx1_wdt_fops = { | 188 | static const struct file_operations mtx1_wdt_fops = { |
189 | .owner = THIS_MODULE, | 189 | .owner = THIS_MODULE, |
190 | .llseek = no_llseek, | 190 | .llseek = no_llseek, |
191 | .ioctl = mtx1_wdt_ioctl, | 191 | .unlocked_ioctl = mtx1_wdt_ioctl, |
192 | .open = mtx1_wdt_open, | 192 | .open = mtx1_wdt_open, |
193 | .write = mtx1_wdt_write, | 193 | .write = mtx1_wdt_write, |
194 | .release = mtx1_wdt_release | 194 | .release = mtx1_wdt_release, |
195 | }; | 195 | }; |
196 | 196 | ||
197 | 197 | ||
198 | static struct miscdevice mtx1_wdt_misc = { | 198 | static struct miscdevice mtx1_wdt_misc = { |
199 | .minor = WATCHDOG_MINOR, | 199 | .minor = WATCHDOG_MINOR, |
200 | .name = "watchdog", | 200 | .name = "watchdog", |
201 | .fops = &mtx1_wdt_fops | 201 | .fops = &mtx1_wdt_fops, |
202 | }; | 202 | }; |
203 | 203 | ||
204 | 204 | ||
@@ -208,29 +208,26 @@ static int mtx1_wdt_probe(struct platform_device *pdev) | |||
208 | 208 | ||
209 | mtx1_wdt_device.gpio = pdev->resource[0].start; | 209 | mtx1_wdt_device.gpio = pdev->resource[0].start; |
210 | 210 | ||
211 | if ((ret = misc_register(&mtx1_wdt_misc)) < 0) { | 211 | spin_lock_init(&mtx1_wdt_device.lock); |
212 | printk(KERN_ERR " mtx-1_wdt : failed to register\n"); | ||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | init_completion(&mtx1_wdt_device.stop); | 212 | init_completion(&mtx1_wdt_device.stop); |
217 | mtx1_wdt_device.queue = 0; | 213 | mtx1_wdt_device.queue = 0; |
218 | |||
219 | clear_bit(0, &mtx1_wdt_device.inuse); | 214 | clear_bit(0, &mtx1_wdt_device.inuse); |
220 | |||
221 | setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L); | 215 | setup_timer(&mtx1_wdt_device.timer, mtx1_wdt_trigger, 0L); |
222 | |||
223 | mtx1_wdt_device.default_ticks = ticks; | 216 | mtx1_wdt_device.default_ticks = ticks; |
224 | 217 | ||
218 | ret = misc_register(&mtx1_wdt_misc); | ||
219 | if (ret < 0) { | ||
220 | printk(KERN_ERR " mtx-1_wdt : failed to register\n"); | ||
221 | return ret; | ||
222 | } | ||
225 | mtx1_wdt_start(); | 223 | mtx1_wdt_start(); |
226 | |||
227 | printk(KERN_INFO "MTX-1 Watchdog driver\n"); | 224 | printk(KERN_INFO "MTX-1 Watchdog driver\n"); |
228 | |||
229 | return 0; | 225 | return 0; |
230 | } | 226 | } |
231 | 227 | ||
232 | static int mtx1_wdt_remove(struct platform_device *pdev) | 228 | static int mtx1_wdt_remove(struct platform_device *pdev) |
233 | { | 229 | { |
230 | /* FIXME: do we need to lock this test ? */ | ||
234 | if (mtx1_wdt_device.queue) { | 231 | if (mtx1_wdt_device.queue) { |
235 | mtx1_wdt_device.queue = 0; | 232 | mtx1_wdt_device.queue = 0; |
236 | wait_for_completion(&mtx1_wdt_device.stop); | 233 | wait_for_completion(&mtx1_wdt_device.stop); |
diff --git a/drivers/watchdog/mv64x60_wdt.c b/drivers/watchdog/mv64x60_wdt.c index b59ca3273967..acf589dc057c 100644 --- a/drivers/watchdog/mv64x60_wdt.c +++ b/drivers/watchdog/mv64x60_wdt.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * and services the watchdog. | 8 | * and services the watchdog. |
9 | * | 9 | * |
10 | * Derived from mpc8xx_wdt.c, with the following copyright. | 10 | * Derived from mpc8xx_wdt.c, with the following copyright. |
11 | * | 11 | * |
12 | * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under | 12 | * 2002 (c) Florian Schirmer <jolt@tuxbox.org> This file is licensed under |
13 | * the terms of the GNU General Public License version 2. This program | 13 | * the terms of the GNU General Public License version 2. This program |
14 | * is licensed "as is" without any warranty of any kind, whether express | 14 | * is licensed "as is" without any warranty of any kind, whether express |
@@ -22,10 +22,9 @@ | |||
22 | #include <linux/module.h> | 22 | #include <linux/module.h> |
23 | #include <linux/watchdog.h> | 23 | #include <linux/watchdog.h> |
24 | #include <linux/platform_device.h> | 24 | #include <linux/platform_device.h> |
25 | |||
26 | #include <linux/mv643xx.h> | 25 | #include <linux/mv643xx.h> |
27 | #include <asm/uaccess.h> | 26 | #include <linux/uaccess.h> |
28 | #include <asm/io.h> | 27 | #include <linux/io.h> |
29 | 28 | ||
30 | #define MV64x60_WDT_WDC_OFFSET 0 | 29 | #define MV64x60_WDT_WDC_OFFSET 0 |
31 | 30 | ||
@@ -61,7 +60,9 @@ static DEFINE_SPINLOCK(mv64x60_wdt_spinlock); | |||
61 | 60 | ||
62 | static int nowayout = WATCHDOG_NOWAYOUT; | 61 | static int nowayout = WATCHDOG_NOWAYOUT; |
63 | module_param(nowayout, int, 0); | 62 | module_param(nowayout, int, 0); |
64 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 63 | MODULE_PARM_DESC(nowayout, |
64 | "Watchdog cannot be stopped once started (default=" | ||
65 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
65 | 66 | ||
66 | static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) | 67 | static int mv64x60_wdt_toggle_wdc(int enabled_predicate, int field_shift) |
67 | { | 68 | { |
@@ -150,7 +151,7 @@ static int mv64x60_wdt_release(struct inode *inode, struct file *file) | |||
150 | } | 151 | } |
151 | 152 | ||
152 | static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, | 153 | static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, |
153 | size_t len, loff_t * ppos) | 154 | size_t len, loff_t *ppos) |
154 | { | 155 | { |
155 | if (len) { | 156 | if (len) { |
156 | if (!nowayout) { | 157 | if (!nowayout) { |
@@ -160,7 +161,7 @@ static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, | |||
160 | 161 | ||
161 | for (i = 0; i != len; i++) { | 162 | for (i = 0; i != len; i++) { |
162 | char c; | 163 | char c; |
163 | if(get_user(c, data + i)) | 164 | if (get_user(c, data + i)) |
164 | return -EFAULT; | 165 | return -EFAULT; |
165 | if (c == 'V') | 166 | if (c == 'V') |
166 | expect_close = 42; | 167 | expect_close = 42; |
@@ -172,8 +173,8 @@ static ssize_t mv64x60_wdt_write(struct file *file, const char __user *data, | |||
172 | return len; | 173 | return len; |
173 | } | 174 | } |
174 | 175 | ||
175 | static int mv64x60_wdt_ioctl(struct inode *inode, struct file *file, | 176 | static long mv64x60_wdt_ioctl(struct file *file, |
176 | unsigned int cmd, unsigned long arg) | 177 | unsigned int cmd, unsigned long arg) |
177 | { | 178 | { |
178 | int timeout; | 179 | int timeout; |
179 | int options; | 180 | int options; |
@@ -240,7 +241,7 @@ static const struct file_operations mv64x60_wdt_fops = { | |||
240 | .owner = THIS_MODULE, | 241 | .owner = THIS_MODULE, |
241 | .llseek = no_llseek, | 242 | .llseek = no_llseek, |
242 | .write = mv64x60_wdt_write, | 243 | .write = mv64x60_wdt_write, |
243 | .ioctl = mv64x60_wdt_ioctl, | 244 | .unlocked_ioctl = mv64x60_wdt_ioctl, |
244 | .open = mv64x60_wdt_open, | 245 | .open = mv64x60_wdt_open, |
245 | .release = mv64x60_wdt_release, | 246 | .release = mv64x60_wdt_release, |
246 | }; | 247 | }; |
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 74a10d50607b..3a11dadfd8e7 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -40,11 +40,9 @@ | |||
40 | #include <linux/moduleparam.h> | 40 | #include <linux/moduleparam.h> |
41 | #include <linux/clk.h> | 41 | #include <linux/clk.h> |
42 | #include <linux/bitops.h> | 42 | #include <linux/bitops.h> |
43 | 43 | #include <linux/io.h> | |
44 | #include <asm/io.h> | 44 | #include <linux/uaccess.h> |
45 | #include <asm/uaccess.h> | ||
46 | #include <mach/hardware.h> | 45 | #include <mach/hardware.h> |
47 | |||
48 | #include <mach/prcm.h> | 46 | #include <mach/prcm.h> |
49 | 47 | ||
50 | #include "omap_wdt.h" | 48 | #include "omap_wdt.h" |
@@ -54,11 +52,12 @@ module_param(timer_margin, uint, 0); | |||
54 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); | 52 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); |
55 | 53 | ||
56 | static int omap_wdt_users; | 54 | static int omap_wdt_users; |
57 | static struct clk *armwdt_ck = NULL; | 55 | static struct clk *armwdt_ck; |
58 | static struct clk *mpu_wdt_ick = NULL; | 56 | static struct clk *mpu_wdt_ick; |
59 | static struct clk *mpu_wdt_fck = NULL; | 57 | static struct clk *mpu_wdt_fck; |
60 | 58 | ||
61 | static unsigned int wdt_trgr_pattern = 0x1234; | 59 | static unsigned int wdt_trgr_pattern = 0x1234; |
60 | static spinlock_t wdt_lock; | ||
62 | 61 | ||
63 | static void omap_wdt_ping(void) | 62 | static void omap_wdt_ping(void) |
64 | { | 63 | { |
@@ -174,30 +173,29 @@ static int omap_wdt_release(struct inode *inode, struct file *file) | |||
174 | return 0; | 173 | return 0; |
175 | } | 174 | } |
176 | 175 | ||
177 | static ssize_t | 176 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, |
178 | omap_wdt_write(struct file *file, const char __user *data, | ||
179 | size_t len, loff_t *ppos) | 177 | size_t len, loff_t *ppos) |
180 | { | 178 | { |
181 | /* Refresh LOAD_TIME. */ | 179 | /* Refresh LOAD_TIME. */ |
182 | if (len) | 180 | if (len) { |
181 | spin_lock(&wdt_lock); | ||
183 | omap_wdt_ping(); | 182 | omap_wdt_ping(); |
183 | spin_unlock(&wdt_lock); | ||
184 | } | ||
184 | return len; | 185 | return len; |
185 | } | 186 | } |
186 | 187 | ||
187 | static int | 188 | static long omap_wdt_ioctl(struct file *file, unsigned int cmd, |
188 | omap_wdt_ioctl(struct inode *inode, struct file *file, | 189 | unsigned long arg) |
189 | unsigned int cmd, unsigned long arg) | ||
190 | { | 190 | { |
191 | int new_margin; | 191 | int new_margin; |
192 | static struct watchdog_info ident = { | 192 | static const struct watchdog_info ident = { |
193 | .identity = "OMAP Watchdog", | 193 | .identity = "OMAP Watchdog", |
194 | .options = WDIOF_SETTIMEOUT, | 194 | .options = WDIOF_SETTIMEOUT, |
195 | .firmware_version = 0, | 195 | .firmware_version = 0, |
196 | }; | 196 | }; |
197 | 197 | ||
198 | switch (cmd) { | 198 | switch (cmd) { |
199 | default: | ||
200 | return -ENOTTY; | ||
201 | case WDIOC_GETSUPPORT: | 199 | case WDIOC_GETSUPPORT: |
202 | return copy_to_user((struct watchdog_info __user *)arg, &ident, | 200 | return copy_to_user((struct watchdog_info __user *)arg, &ident, |
203 | sizeof(ident)); | 201 | sizeof(ident)); |
@@ -211,28 +209,34 @@ omap_wdt_ioctl(struct inode *inode, struct file *file, | |||
211 | return put_user(omap_prcm_get_reset_sources(), | 209 | return put_user(omap_prcm_get_reset_sources(), |
212 | (int __user *)arg); | 210 | (int __user *)arg); |
213 | case WDIOC_KEEPALIVE: | 211 | case WDIOC_KEEPALIVE: |
212 | spin_lock(&wdt_lock); | ||
214 | omap_wdt_ping(); | 213 | omap_wdt_ping(); |
214 | spin_unlock(&wdt_lock); | ||
215 | return 0; | 215 | return 0; |
216 | case WDIOC_SETTIMEOUT: | 216 | case WDIOC_SETTIMEOUT: |
217 | if (get_user(new_margin, (int __user *)arg)) | 217 | if (get_user(new_margin, (int __user *)arg)) |
218 | return -EFAULT; | 218 | return -EFAULT; |
219 | omap_wdt_adjust_timeout(new_margin); | 219 | omap_wdt_adjust_timeout(new_margin); |
220 | 220 | ||
221 | spin_lock(&wdt_lock); | ||
221 | omap_wdt_disable(); | 222 | omap_wdt_disable(); |
222 | omap_wdt_set_timeout(); | 223 | omap_wdt_set_timeout(); |
223 | omap_wdt_enable(); | 224 | omap_wdt_enable(); |
224 | 225 | ||
225 | omap_wdt_ping(); | 226 | omap_wdt_ping(); |
227 | spin_unlock(&wdt_lock); | ||
226 | /* Fall */ | 228 | /* Fall */ |
227 | case WDIOC_GETTIMEOUT: | 229 | case WDIOC_GETTIMEOUT: |
228 | return put_user(timer_margin, (int __user *)arg); | 230 | return put_user(timer_margin, (int __user *)arg); |
231 | default: | ||
232 | return -ENOTTY; | ||
229 | } | 233 | } |
230 | } | 234 | } |
231 | 235 | ||
232 | static const struct file_operations omap_wdt_fops = { | 236 | static const struct file_operations omap_wdt_fops = { |
233 | .owner = THIS_MODULE, | 237 | .owner = THIS_MODULE, |
234 | .write = omap_wdt_write, | 238 | .write = omap_wdt_write, |
235 | .ioctl = omap_wdt_ioctl, | 239 | .unlocked_ioctl = omap_wdt_ioctl, |
236 | .open = omap_wdt_open, | 240 | .open = omap_wdt_open, |
237 | .release = omap_wdt_release, | 241 | .release = omap_wdt_release, |
238 | }; | 242 | }; |
@@ -240,7 +244,7 @@ static const struct file_operations omap_wdt_fops = { | |||
240 | static struct miscdevice omap_wdt_miscdev = { | 244 | static struct miscdevice omap_wdt_miscdev = { |
241 | .minor = WATCHDOG_MINOR, | 245 | .minor = WATCHDOG_MINOR, |
242 | .name = "watchdog", | 246 | .name = "watchdog", |
243 | .fops = &omap_wdt_fops | 247 | .fops = &omap_wdt_fops, |
244 | }; | 248 | }; |
245 | 249 | ||
246 | static int __init omap_wdt_probe(struct platform_device *pdev) | 250 | static int __init omap_wdt_probe(struct platform_device *pdev) |
@@ -373,6 +377,7 @@ static struct platform_driver omap_wdt_driver = { | |||
373 | 377 | ||
374 | static int __init omap_wdt_init(void) | 378 | static int __init omap_wdt_init(void) |
375 | { | 379 | { |
380 | spin_lock_init(&wdt_lock); | ||
376 | return platform_driver_register(&omap_wdt_driver); | 381 | return platform_driver_register(&omap_wdt_driver); |
377 | } | 382 | } |
378 | 383 | ||
diff --git a/drivers/watchdog/pc87413_wdt.c b/drivers/watchdog/pc87413_wdt.c index 15e4f8887a9e..e91ada72da1d 100644 --- a/drivers/watchdog/pc87413_wdt.c +++ b/drivers/watchdog/pc87413_wdt.c | |||
@@ -31,14 +31,14 @@ | |||
31 | #include <linux/spinlock.h> | 31 | #include <linux/spinlock.h> |
32 | #include <linux/moduleparam.h> | 32 | #include <linux/moduleparam.h> |
33 | #include <linux/version.h> | 33 | #include <linux/version.h> |
34 | #include <linux/io.h> | ||
35 | #include <linux/uaccess.h> | ||
34 | 36 | ||
35 | #include <asm/io.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | #include <asm/system.h> | 37 | #include <asm/system.h> |
38 | 38 | ||
39 | /* #define DEBUG 1 */ | 39 | /* #define DEBUG 1 */ |
40 | 40 | ||
41 | #define DEFAULT_TIMEOUT 1 /* 1 minute */ | 41 | #define DEFAULT_TIMEOUT 1 /* 1 minute */ |
42 | #define MAX_TIMEOUT 255 | 42 | #define MAX_TIMEOUT 255 |
43 | 43 | ||
44 | #define VERSION "1.1" | 44 | #define VERSION "1.1" |
@@ -46,22 +46,22 @@ | |||
46 | #define PFX MODNAME ": " | 46 | #define PFX MODNAME ": " |
47 | #define DPFX MODNAME " - DEBUG: " | 47 | #define DPFX MODNAME " - DEBUG: " |
48 | 48 | ||
49 | #define WDT_INDEX_IO_PORT (io+0) /* I/O port base (index register) */ | 49 | #define WDT_INDEX_IO_PORT (io+0) /* I/O port base (index register) */ |
50 | #define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) | 50 | #define WDT_DATA_IO_PORT (WDT_INDEX_IO_PORT+1) |
51 | #define SWC_LDN 0x04 | 51 | #define SWC_LDN 0x04 |
52 | #define SIOCFG2 0x22 /* Serial IO register */ | 52 | #define SIOCFG2 0x22 /* Serial IO register */ |
53 | #define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ | 53 | #define WDCTL 0x10 /* Watchdog-Timer-Controll-Register */ |
54 | #define WDTO 0x11 /* Watchdog timeout register */ | 54 | #define WDTO 0x11 /* Watchdog timeout register */ |
55 | #define WDCFG 0x12 /* Watchdog config register */ | 55 | #define WDCFG 0x12 /* Watchdog config register */ |
56 | 56 | ||
57 | static int io = 0x2E; /* Address used on Portwell Boards */ | 57 | static int io = 0x2E; /* Address used on Portwell Boards */ |
58 | 58 | ||
59 | static int timeout = DEFAULT_TIMEOUT; /* timeout value */ | 59 | static int timeout = DEFAULT_TIMEOUT; /* timeout value */ |
60 | static unsigned long timer_enabled = 0; /* is the timer enabled? */ | 60 | static unsigned long timer_enabled; /* is the timer enabled? */ |
61 | 61 | ||
62 | static char expect_close; /* is the close expected? */ | 62 | static char expect_close; /* is the close expected? */ |
63 | 63 | ||
64 | static DEFINE_SPINLOCK(io_lock);/* to guard the watchdog from io races */ | 64 | static DEFINE_SPINLOCK(io_lock); /* to guard us from io races */ |
65 | 65 | ||
66 | static int nowayout = WATCHDOG_NOWAYOUT; | 66 | static int nowayout = WATCHDOG_NOWAYOUT; |
67 | 67 | ||
@@ -69,7 +69,7 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
69 | 69 | ||
70 | /* Select pins for Watchdog output */ | 70 | /* Select pins for Watchdog output */ |
71 | 71 | ||
72 | static inline void pc87413_select_wdt_out (void) | 72 | static inline void pc87413_select_wdt_out(void) |
73 | { | 73 | { |
74 | unsigned int cr_data = 0; | 74 | unsigned int cr_data = 0; |
75 | 75 | ||
@@ -77,7 +77,7 @@ static inline void pc87413_select_wdt_out (void) | |||
77 | 77 | ||
78 | outb_p(SIOCFG2, WDT_INDEX_IO_PORT); | 78 | outb_p(SIOCFG2, WDT_INDEX_IO_PORT); |
79 | 79 | ||
80 | cr_data = inb (WDT_DATA_IO_PORT); | 80 | cr_data = inb(WDT_DATA_IO_PORT); |
81 | 81 | ||
82 | cr_data |= 0x80; /* Set Bit7 to 1*/ | 82 | cr_data |= 0x80; /* Set Bit7 to 1*/ |
83 | outb_p(SIOCFG2, WDT_INDEX_IO_PORT); | 83 | outb_p(SIOCFG2, WDT_INDEX_IO_PORT); |
@@ -85,8 +85,9 @@ static inline void pc87413_select_wdt_out (void) | |||
85 | outb_p(cr_data, WDT_DATA_IO_PORT); | 85 | outb_p(cr_data, WDT_DATA_IO_PORT); |
86 | 86 | ||
87 | #ifdef DEBUG | 87 | #ifdef DEBUG |
88 | printk(KERN_INFO DPFX "Select multiple pin,pin55,as WDT output:" | 88 | printk(KERN_INFO DPFX |
89 | " Bit7 to 1: %d\n", cr_data); | 89 | "Select multiple pin,pin55,as WDT output: Bit7 to 1: %d\n", |
90 | cr_data); | ||
90 | #endif | 91 | #endif |
91 | } | 92 | } |
92 | 93 | ||
@@ -94,18 +95,18 @@ static inline void pc87413_select_wdt_out (void) | |||
94 | 95 | ||
95 | static inline void pc87413_enable_swc(void) | 96 | static inline void pc87413_enable_swc(void) |
96 | { | 97 | { |
97 | unsigned int cr_data=0; | 98 | unsigned int cr_data = 0; |
98 | 99 | ||
99 | /* Step 2: Enable SWC functions */ | 100 | /* Step 2: Enable SWC functions */ |
100 | 101 | ||
101 | outb_p(0x07, WDT_INDEX_IO_PORT); /* Point SWC_LDN (LDN=4) */ | 102 | outb_p(0x07, WDT_INDEX_IO_PORT); /* Point SWC_LDN (LDN=4) */ |
102 | outb_p(SWC_LDN, WDT_DATA_IO_PORT); | 103 | outb_p(SWC_LDN, WDT_DATA_IO_PORT); |
103 | 104 | ||
104 | outb_p(0x30, WDT_INDEX_IO_PORT); /* Read Index 0x30 First */ | 105 | outb_p(0x30, WDT_INDEX_IO_PORT); /* Read Index 0x30 First */ |
105 | cr_data = inb(WDT_DATA_IO_PORT); | 106 | cr_data = inb(WDT_DATA_IO_PORT); |
106 | cr_data |= 0x01; /* Set Bit0 to 1 */ | 107 | cr_data |= 0x01; /* Set Bit0 to 1 */ |
107 | outb_p(0x30, WDT_INDEX_IO_PORT); | 108 | outb_p(0x30, WDT_INDEX_IO_PORT); |
108 | outb_p(cr_data, WDT_DATA_IO_PORT); /* Index0x30_bit0P1 */ | 109 | outb_p(cr_data, WDT_DATA_IO_PORT); /* Index0x30_bit0P1 */ |
109 | 110 | ||
110 | #ifdef DEBUG | 111 | #ifdef DEBUG |
111 | printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n"); | 112 | printk(KERN_INFO DPFX "pc87413 - Enable SWC functions\n"); |
@@ -121,20 +122,19 @@ static inline unsigned int pc87413_get_swc_base(void) | |||
121 | 122 | ||
122 | /* Step 3: Read SWC I/O Base Address */ | 123 | /* Step 3: Read SWC I/O Base Address */ |
123 | 124 | ||
124 | outb_p(0x60, WDT_INDEX_IO_PORT); /* Read Index 0x60 */ | 125 | outb_p(0x60, WDT_INDEX_IO_PORT); /* Read Index 0x60 */ |
125 | addr_h = inb(WDT_DATA_IO_PORT); | 126 | addr_h = inb(WDT_DATA_IO_PORT); |
126 | 127 | ||
127 | outb_p(0x61, WDT_INDEX_IO_PORT); /* Read Index 0x61 */ | 128 | outb_p(0x61, WDT_INDEX_IO_PORT); /* Read Index 0x61 */ |
128 | 129 | ||
129 | addr_l = inb(WDT_DATA_IO_PORT); | 130 | addr_l = inb(WDT_DATA_IO_PORT); |
130 | 131 | ||
131 | swc_base_addr = (addr_h << 8) + addr_l; | 132 | swc_base_addr = (addr_h << 8) + addr_l; |
132 | |||
133 | #ifdef DEBUG | 133 | #ifdef DEBUG |
134 | printk(KERN_INFO DPFX "Read SWC I/O Base Address: low %d, high %d," | 134 | printk(KERN_INFO DPFX |
135 | " res %d\n", addr_l, addr_h, swc_base_addr); | 135 | "Read SWC I/O Base Address: low %d, high %d, res %d\n", |
136 | addr_l, addr_h, swc_base_addr); | ||
136 | #endif | 137 | #endif |
137 | |||
138 | return swc_base_addr; | 138 | return swc_base_addr; |
139 | } | 139 | } |
140 | 140 | ||
@@ -143,9 +143,7 @@ static inline unsigned int pc87413_get_swc_base(void) | |||
143 | static inline void pc87413_swc_bank3(unsigned int swc_base_addr) | 143 | static inline void pc87413_swc_bank3(unsigned int swc_base_addr) |
144 | { | 144 | { |
145 | /* Step 4: Select Bank3 of SWC */ | 145 | /* Step 4: Select Bank3 of SWC */ |
146 | |||
147 | outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f); | 146 | outb_p(inb(swc_base_addr + 0x0f) | 0x03, swc_base_addr + 0x0f); |
148 | |||
149 | #ifdef DEBUG | 147 | #ifdef DEBUG |
150 | printk(KERN_INFO DPFX "Select Bank3 of SWC\n"); | 148 | printk(KERN_INFO DPFX "Select Bank3 of SWC\n"); |
151 | #endif | 149 | #endif |
@@ -157,9 +155,7 @@ static inline void pc87413_programm_wdto(unsigned int swc_base_addr, | |||
157 | char pc87413_time) | 155 | char pc87413_time) |
158 | { | 156 | { |
159 | /* Step 5: Programm WDTO, Twd. */ | 157 | /* Step 5: Programm WDTO, Twd. */ |
160 | |||
161 | outb_p(pc87413_time, swc_base_addr + WDTO); | 158 | outb_p(pc87413_time, swc_base_addr + WDTO); |
162 | |||
163 | #ifdef DEBUG | 159 | #ifdef DEBUG |
164 | printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time); | 160 | printk(KERN_INFO DPFX "Set WDTO to %d minutes\n", pc87413_time); |
165 | #endif | 161 | #endif |
@@ -170,9 +166,7 @@ static inline void pc87413_programm_wdto(unsigned int swc_base_addr, | |||
170 | static inline void pc87413_enable_wden(unsigned int swc_base_addr) | 166 | static inline void pc87413_enable_wden(unsigned int swc_base_addr) |
171 | { | 167 | { |
172 | /* Step 6: Enable WDEN */ | 168 | /* Step 6: Enable WDEN */ |
173 | 169 | outb_p(inb(swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL); | |
174 | outb_p(inb (swc_base_addr + WDCTL) | 0x01, swc_base_addr + WDCTL); | ||
175 | |||
176 | #ifdef DEBUG | 170 | #ifdef DEBUG |
177 | printk(KERN_INFO DPFX "Enable WDEN\n"); | 171 | printk(KERN_INFO DPFX "Enable WDEN\n"); |
178 | #endif | 172 | #endif |
@@ -182,9 +176,7 @@ static inline void pc87413_enable_wden(unsigned int swc_base_addr) | |||
182 | static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr) | 176 | static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr) |
183 | { | 177 | { |
184 | /* Enable SW_WD_TREN */ | 178 | /* Enable SW_WD_TREN */ |
185 | 179 | outb_p(inb(swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG); | |
186 | outb_p(inb (swc_base_addr + WDCFG) | 0x80, swc_base_addr + WDCFG); | ||
187 | |||
188 | #ifdef DEBUG | 180 | #ifdef DEBUG |
189 | printk(KERN_INFO DPFX "Enable SW_WD_TREN\n"); | 181 | printk(KERN_INFO DPFX "Enable SW_WD_TREN\n"); |
190 | #endif | 182 | #endif |
@@ -195,9 +187,7 @@ static inline void pc87413_enable_sw_wd_tren(unsigned int swc_base_addr) | |||
195 | static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr) | 187 | static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr) |
196 | { | 188 | { |
197 | /* Disable SW_WD_TREN */ | 189 | /* Disable SW_WD_TREN */ |
198 | 190 | outb_p(inb(swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG); | |
199 | outb_p(inb (swc_base_addr + WDCFG) & 0x7f, swc_base_addr + WDCFG); | ||
200 | |||
201 | #ifdef DEBUG | 191 | #ifdef DEBUG |
202 | printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n"); | 192 | printk(KERN_INFO DPFX "pc87413 - Disable SW_WD_TREN\n"); |
203 | #endif | 193 | #endif |
@@ -208,9 +198,7 @@ static inline void pc87413_disable_sw_wd_tren(unsigned int swc_base_addr) | |||
208 | static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr) | 198 | static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr) |
209 | { | 199 | { |
210 | /* Enable SW_WD_TRG */ | 200 | /* Enable SW_WD_TRG */ |
211 | 201 | outb_p(inb(swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL); | |
212 | outb_p(inb (swc_base_addr + WDCTL) | 0x80, swc_base_addr + WDCTL); | ||
213 | |||
214 | #ifdef DEBUG | 202 | #ifdef DEBUG |
215 | printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n"); | 203 | printk(KERN_INFO DPFX "pc87413 - Enable SW_WD_TRG\n"); |
216 | #endif | 204 | #endif |
@@ -221,9 +209,7 @@ static inline void pc87413_enable_sw_wd_trg(unsigned int swc_base_addr) | |||
221 | static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr) | 209 | static inline void pc87413_disable_sw_wd_trg(unsigned int swc_base_addr) |
222 | { | 210 | { |
223 | /* Disable SW_WD_TRG */ | 211 | /* Disable SW_WD_TRG */ |
224 | 212 | outb_p(inb(swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL); | |
225 | outb_p(inb (swc_base_addr + WDCTL) & 0x7f, swc_base_addr + WDCTL); | ||
226 | |||
227 | #ifdef DEBUG | 213 | #ifdef DEBUG |
228 | printk(KERN_INFO DPFX "Disable SW_WD_TRG\n"); | 214 | printk(KERN_INFO DPFX "Disable SW_WD_TRG\n"); |
229 | #endif | 215 | #endif |
@@ -314,8 +300,8 @@ static int pc87413_open(struct inode *inode, struct file *file) | |||
314 | /* Reload and activate timer */ | 300 | /* Reload and activate timer */ |
315 | pc87413_refresh(); | 301 | pc87413_refresh(); |
316 | 302 | ||
317 | printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to" | 303 | printk(KERN_INFO MODNAME |
318 | " %d minute(s).\n", timeout); | 304 | "Watchdog enabled. Timeout set to %d minute(s).\n", timeout); |
319 | 305 | ||
320 | return nonseekable_open(inode, file); | 306 | return nonseekable_open(inode, file); |
321 | } | 307 | } |
@@ -338,17 +324,15 @@ static int pc87413_release(struct inode *inode, struct file *file) | |||
338 | 324 | ||
339 | if (expect_close == 42) { | 325 | if (expect_close == 42) { |
340 | pc87413_disable(); | 326 | pc87413_disable(); |
341 | printk(KERN_INFO MODNAME "Watchdog disabled," | 327 | printk(KERN_INFO MODNAME |
342 | " sleeping again...\n"); | 328 | "Watchdog disabled, sleeping again...\n"); |
343 | } else { | 329 | } else { |
344 | printk(KERN_CRIT MODNAME "Unexpected close, not stopping" | 330 | printk(KERN_CRIT MODNAME |
345 | " watchdog!\n"); | 331 | "Unexpected close, not stopping watchdog!\n"); |
346 | pc87413_refresh(); | 332 | pc87413_refresh(); |
347 | } | 333 | } |
348 | |||
349 | clear_bit(0, &timer_enabled); | 334 | clear_bit(0, &timer_enabled); |
350 | expect_close = 0; | 335 | expect_close = 0; |
351 | |||
352 | return 0; | 336 | return 0; |
353 | } | 337 | } |
354 | 338 | ||
@@ -386,10 +370,11 @@ static ssize_t pc87413_write(struct file *file, const char __user *data, | |||
386 | /* reset expect flag */ | 370 | /* reset expect flag */ |
387 | expect_close = 0; | 371 | expect_close = 0; |
388 | 372 | ||
389 | /* scan to see whether or not we got the magic character */ | 373 | /* scan to see whether or not we got the |
374 | magic character */ | ||
390 | for (i = 0; i != len; i++) { | 375 | for (i = 0; i != len; i++) { |
391 | char c; | 376 | char c; |
392 | if (get_user(c, data+i)) | 377 | if (get_user(c, data + i)) |
393 | return -EFAULT; | 378 | return -EFAULT; |
394 | if (c == 'V') | 379 | if (c == 'V') |
395 | expect_close = 42; | 380 | expect_close = 42; |
@@ -404,7 +389,6 @@ static ssize_t pc87413_write(struct file *file, const char __user *data, | |||
404 | 389 | ||
405 | /** | 390 | /** |
406 | * pc87413_ioctl: | 391 | * pc87413_ioctl: |
407 | * @inode: inode of the device | ||
408 | * @file: file handle to the device | 392 | * @file: file handle to the device |
409 | * @cmd: watchdog command | 393 | * @cmd: watchdog command |
410 | * @arg: argument pointer | 394 | * @arg: argument pointer |
@@ -414,8 +398,8 @@ static ssize_t pc87413_write(struct file *file, const char __user *data, | |||
414 | * querying capabilities and current status. | 398 | * querying capabilities and current status. |
415 | */ | 399 | */ |
416 | 400 | ||
417 | static int pc87413_ioctl(struct inode *inode, struct file *file, | 401 | static long pc87413_ioctl(struct file *file, unsigned int cmd, |
418 | unsigned int cmd, unsigned long arg) | 402 | unsigned long arg) |
419 | { | 403 | { |
420 | int new_timeout; | 404 | int new_timeout; |
421 | 405 | ||
@@ -426,75 +410,58 @@ static int pc87413_ioctl(struct inode *inode, struct file *file, | |||
426 | 410 | ||
427 | static struct watchdog_info ident = { | 411 | static struct watchdog_info ident = { |
428 | .options = WDIOF_KEEPALIVEPING | | 412 | .options = WDIOF_KEEPALIVEPING | |
429 | WDIOF_SETTIMEOUT | | 413 | WDIOF_SETTIMEOUT | |
430 | WDIOF_MAGICCLOSE, | 414 | WDIOF_MAGICCLOSE, |
431 | .firmware_version = 1, | 415 | .firmware_version = 1, |
432 | .identity = "PC87413(HF/F) watchdog" | 416 | .identity = "PC87413(HF/F) watchdog", |
433 | }; | 417 | }; |
434 | 418 | ||
435 | uarg.i = (int __user *)arg; | 419 | uarg.i = (int __user *)arg; |
436 | 420 | ||
437 | switch(cmd) { | 421 | switch (cmd) { |
438 | default: | 422 | case WDIOC_GETSUPPORT: |
439 | return -ENOTTY; | 423 | return copy_to_user(uarg.ident, &ident, |
440 | 424 | sizeof(ident)) ? -EFAULT : 0; | |
441 | case WDIOC_GETSUPPORT: | 425 | case WDIOC_GETSTATUS: |
442 | return copy_to_user(uarg.ident, &ident, | 426 | return put_user(pc87413_status(), uarg.i); |
443 | sizeof(ident)) ? -EFAULT : 0; | 427 | case WDIOC_GETBOOTSTATUS: |
444 | 428 | return put_user(0, uarg.i); | |
445 | case WDIOC_GETSTATUS: | 429 | case WDIOC_SETOPTIONS: |
446 | return put_user(pc87413_status(), uarg.i); | 430 | { |
447 | 431 | int options, retval = -EINVAL; | |
448 | case WDIOC_GETBOOTSTATUS: | 432 | if (get_user(options, uarg.i)) |
449 | return put_user(0, uarg.i); | 433 | return -EFAULT; |
450 | 434 | if (options & WDIOS_DISABLECARD) { | |
451 | case WDIOC_KEEPALIVE: | 435 | pc87413_disable(); |
452 | pc87413_refresh(); | 436 | retval = 0; |
437 | } | ||
438 | if (options & WDIOS_ENABLECARD) { | ||
439 | pc87413_enable(); | ||
440 | retval = 0; | ||
441 | } | ||
442 | return retval; | ||
443 | } | ||
444 | case WDIOC_KEEPALIVE: | ||
445 | pc87413_refresh(); | ||
453 | #ifdef DEBUG | 446 | #ifdef DEBUG |
454 | printk(KERN_INFO DPFX "keepalive\n"); | 447 | printk(KERN_INFO DPFX "keepalive\n"); |
455 | #endif | 448 | #endif |
456 | return 0; | 449 | return 0; |
457 | 450 | case WDIOC_SETTIMEOUT: | |
458 | case WDIOC_SETTIMEOUT: | 451 | if (get_user(new_timeout, uarg.i)) |
459 | if (get_user(new_timeout, uarg.i)) | 452 | return -EFAULT; |
460 | return -EFAULT; | 453 | /* the API states this is given in secs */ |
461 | 454 | new_timeout /= 60; | |
462 | // the API states this is given in secs | 455 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) |
463 | new_timeout /= 60; | 456 | return -EINVAL; |
464 | 457 | timeout = new_timeout; | |
465 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | 458 | pc87413_refresh(); |
466 | return -EINVAL; | 459 | /* fall through and return the new timeout... */ |
467 | 460 | case WDIOC_GETTIMEOUT: | |
468 | timeout = new_timeout; | 461 | new_timeout = timeout * 60; |
469 | pc87413_refresh(); | 462 | return put_user(new_timeout, uarg.i); |
470 | 463 | default: | |
471 | // fall through and return the new timeout... | 464 | return -ENOTTY; |
472 | |||
473 | case WDIOC_GETTIMEOUT: | ||
474 | |||
475 | new_timeout = timeout * 60; | ||
476 | |||
477 | return put_user(new_timeout, uarg.i); | ||
478 | |||
479 | case WDIOC_SETOPTIONS: | ||
480 | { | ||
481 | int options, retval = -EINVAL; | ||
482 | |||
483 | if (get_user(options, uarg.i)) | ||
484 | return -EFAULT; | ||
485 | |||
486 | if (options & WDIOS_DISABLECARD) { | ||
487 | pc87413_disable(); | ||
488 | retval = 0; | ||
489 | } | ||
490 | |||
491 | if (options & WDIOS_ENABLECARD) { | ||
492 | pc87413_enable(); | ||
493 | retval = 0; | ||
494 | } | ||
495 | |||
496 | return retval; | ||
497 | } | ||
498 | } | 465 | } |
499 | } | 466 | } |
500 | 467 | ||
@@ -517,10 +484,8 @@ static int pc87413_notify_sys(struct notifier_block *this, | |||
517 | void *unused) | 484 | void *unused) |
518 | { | 485 | { |
519 | if (code == SYS_DOWN || code == SYS_HALT) | 486 | if (code == SYS_DOWN || code == SYS_HALT) |
520 | { | ||
521 | /* Turn the card off */ | 487 | /* Turn the card off */ |
522 | pc87413_disable(); | 488 | pc87413_disable(); |
523 | } | ||
524 | return NOTIFY_DONE; | 489 | return NOTIFY_DONE; |
525 | } | 490 | } |
526 | 491 | ||
@@ -530,21 +495,19 @@ static const struct file_operations pc87413_fops = { | |||
530 | .owner = THIS_MODULE, | 495 | .owner = THIS_MODULE, |
531 | .llseek = no_llseek, | 496 | .llseek = no_llseek, |
532 | .write = pc87413_write, | 497 | .write = pc87413_write, |
533 | .ioctl = pc87413_ioctl, | 498 | .unlocked_ioctl = pc87413_ioctl, |
534 | .open = pc87413_open, | 499 | .open = pc87413_open, |
535 | .release = pc87413_release, | 500 | .release = pc87413_release, |
536 | }; | 501 | }; |
537 | 502 | ||
538 | static struct notifier_block pc87413_notifier = | 503 | static struct notifier_block pc87413_notifier = { |
539 | { | ||
540 | .notifier_call = pc87413_notify_sys, | 504 | .notifier_call = pc87413_notify_sys, |
541 | }; | 505 | }; |
542 | 506 | ||
543 | static struct miscdevice pc87413_miscdev= | 507 | static struct miscdevice pc87413_miscdev = { |
544 | { | ||
545 | .minor = WATCHDOG_MINOR, | 508 | .minor = WATCHDOG_MINOR, |
546 | .name = "watchdog", | 509 | .name = "watchdog", |
547 | .fops = &pc87413_fops | 510 | .fops = &pc87413_fops, |
548 | }; | 511 | }; |
549 | 512 | ||
550 | /* -- Module init functions -------------------------------------*/ | 513 | /* -- Module init functions -------------------------------------*/ |
@@ -561,29 +524,26 @@ static int __init pc87413_init(void) | |||
561 | { | 524 | { |
562 | int ret; | 525 | int ret; |
563 | 526 | ||
564 | printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", WDT_INDEX_IO_PORT); | 527 | printk(KERN_INFO PFX "Version " VERSION " at io 0x%X\n", |
528 | WDT_INDEX_IO_PORT); | ||
565 | 529 | ||
566 | /* request_region(io, 2, "pc87413"); */ | 530 | /* request_region(io, 2, "pc87413"); */ |
567 | 531 | ||
568 | ret = register_reboot_notifier(&pc87413_notifier); | 532 | ret = register_reboot_notifier(&pc87413_notifier); |
569 | if (ret != 0) { | 533 | if (ret != 0) { |
570 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 534 | printk(KERN_ERR PFX |
571 | ret); | 535 | "cannot register reboot notifier (err=%d)\n", ret); |
572 | } | 536 | } |
573 | 537 | ||
574 | ret = misc_register(&pc87413_miscdev); | 538 | ret = misc_register(&pc87413_miscdev); |
575 | |||
576 | if (ret != 0) { | 539 | if (ret != 0) { |
577 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 540 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", |
578 | WATCHDOG_MINOR, ret); | 541 | WATCHDOG_MINOR, ret); |
579 | unregister_reboot_notifier(&pc87413_notifier); | 542 | unregister_reboot_notifier(&pc87413_notifier); |
580 | return ret; | 543 | return ret; |
581 | } | 544 | } |
582 | |||
583 | printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout); | 545 | printk(KERN_INFO PFX "initialized. timeout=%d min \n", timeout); |
584 | |||
585 | pc87413_enable(); | 546 | pc87413_enable(); |
586 | |||
587 | return 0; | 547 | return 0; |
588 | } | 548 | } |
589 | 549 | ||
@@ -600,17 +560,16 @@ static int __init pc87413_init(void) | |||
600 | static void __exit pc87413_exit(void) | 560 | static void __exit pc87413_exit(void) |
601 | { | 561 | { |
602 | /* Stop the timer before we leave */ | 562 | /* Stop the timer before we leave */ |
603 | if (!nowayout) | 563 | if (!nowayout) { |
604 | { | ||
605 | pc87413_disable(); | 564 | pc87413_disable(); |
606 | printk(KERN_INFO MODNAME "Watchdog disabled.\n"); | 565 | printk(KERN_INFO MODNAME "Watchdog disabled.\n"); |
607 | } | 566 | } |
608 | 567 | ||
609 | misc_deregister(&pc87413_miscdev); | 568 | misc_deregister(&pc87413_miscdev); |
610 | unregister_reboot_notifier(&pc87413_notifier); | 569 | unregister_reboot_notifier(&pc87413_notifier); |
611 | /* release_region(io,2); */ | 570 | /* release_region(io, 2); */ |
612 | 571 | ||
613 | printk(MODNAME " watchdog component driver removed.\n"); | 572 | printk(KERN_INFO MODNAME " watchdog component driver removed.\n"); |
614 | } | 573 | } |
615 | 574 | ||
616 | module_init(pc87413_init); | 575 | module_init(pc87413_init); |
@@ -626,8 +585,12 @@ module_param(io, int, 0); | |||
626 | MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ")."); | 585 | MODULE_PARM_DESC(io, MODNAME " I/O port (default: " __MODULE_STRING(io) ")."); |
627 | 586 | ||
628 | module_param(timeout, int, 0); | 587 | module_param(timeout, int, 0); |
629 | MODULE_PARM_DESC(timeout, "Watchdog timeout in minutes (default=" __MODULE_STRING(timeout) ")."); | 588 | MODULE_PARM_DESC(timeout, |
589 | "Watchdog timeout in minutes (default=" | ||
590 | __MODULE_STRING(timeout) ")."); | ||
630 | 591 | ||
631 | module_param(nowayout, int, 0); | 592 | module_param(nowayout, int, 0); |
632 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 593 | MODULE_PARM_DESC(nowayout, |
594 | "Watchdog cannot be stopped once started (default=" | ||
595 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
633 | 596 | ||
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c index 7b41434fac8c..3b0ddc7fcf3f 100644 --- a/drivers/watchdog/pcwd.c +++ b/drivers/watchdog/pcwd.c | |||
@@ -40,13 +40,15 @@ | |||
40 | * fairly useless proc entry. | 40 | * fairly useless proc entry. |
41 | * 990610 removed said useless proc code for the merge <alan> | 41 | * 990610 removed said useless proc code for the merge <alan> |
42 | * 000403 Removed last traces of proc code. <davej> | 42 | * 000403 Removed last traces of proc code. <davej> |
43 | * 011214 Added nowayout module option to override CONFIG_WATCHDOG_NOWAYOUT <Matt_Domsch@dell.com> | 43 | * 011214 Added nowayout module option to override |
44 | * CONFIG_WATCHDOG_NOWAYOUT <Matt_Domsch@dell.com> | ||
44 | * Added timeout module option to override default | 45 | * Added timeout module option to override default |
45 | */ | 46 | */ |
46 | 47 | ||
47 | /* | 48 | /* |
48 | * A bells and whistles driver is available from http://www.pcwd.de/ | 49 | * A bells and whistles driver is available from http://www.pcwd.de/ |
49 | * More info available at http://www.berkprod.com/ or http://www.pcwatchdog.com/ | 50 | * More info available at http://www.berkprod.com/ or |
51 | * http://www.pcwatchdog.com/ | ||
50 | */ | 52 | */ |
51 | 53 | ||
52 | #include <linux/module.h> /* For module specific items */ | 54 | #include <linux/module.h> /* For module specific items */ |
@@ -65,9 +67,8 @@ | |||
65 | #include <linux/isa.h> /* For isa devices */ | 67 | #include <linux/isa.h> /* For isa devices */ |
66 | #include <linux/ioport.h> /* For io-port access */ | 68 | #include <linux/ioport.h> /* For io-port access */ |
67 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ | 69 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ |
68 | 70 | #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ | |
69 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | 71 | #include <linux/io.h> /* For inb/outb/... */ |
70 | #include <asm/io.h> /* For inb/outb/... */ | ||
71 | 72 | ||
72 | /* Module and version information */ | 73 | /* Module and version information */ |
73 | #define WATCHDOG_VERSION "1.20" | 74 | #define WATCHDOG_VERSION "1.20" |
@@ -111,14 +112,16 @@ static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; | |||
111 | #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ | 112 | #define WD_REVC_WTRP 0x01 /* Watchdog Trip status */ |
112 | #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ | 113 | #define WD_REVC_HRBT 0x02 /* Watchdog Heartbeat */ |
113 | #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ | 114 | #define WD_REVC_TTRP 0x04 /* Temperature Trip status */ |
114 | #define WD_REVC_RL2A 0x08 /* Relay 2 activated by on-board processor */ | 115 | #define WD_REVC_RL2A 0x08 /* Relay 2 activated by |
116 | on-board processor */ | ||
115 | #define WD_REVC_RL1A 0x10 /* Relay 1 active */ | 117 | #define WD_REVC_RL1A 0x10 /* Relay 1 active */ |
116 | #define WD_REVC_R2DS 0x40 /* Relay 2 disable */ | 118 | #define WD_REVC_R2DS 0x40 /* Relay 2 disable */ |
117 | #define WD_REVC_RLY2 0x80 /* Relay 2 activated? */ | 119 | #define WD_REVC_RLY2 0x80 /* Relay 2 activated? */ |
118 | /* Port 2 : Control Status #2 */ | 120 | /* Port 2 : Control Status #2 */ |
119 | #define WD_WDIS 0x10 /* Watchdog Disabled */ | 121 | #define WD_WDIS 0x10 /* Watchdog Disabled */ |
120 | #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ | 122 | #define WD_ENTP 0x20 /* Watchdog Enable Temperature Trip */ |
121 | #define WD_SSEL 0x40 /* Watchdog Switch Select (1:SW1 <-> 0:SW2) */ | 123 | #define WD_SSEL 0x40 /* Watchdog Switch Select |
124 | (1:SW1 <-> 0:SW2) */ | ||
122 | #define WD_WCMD 0x80 /* Watchdog Command Mode */ | 125 | #define WD_WCMD 0x80 /* Watchdog Command Mode */ |
123 | 126 | ||
124 | /* max. time we give an ISA watchdog card to process a command */ | 127 | /* max. time we give an ISA watchdog card to process a command */ |
@@ -142,7 +145,7 @@ static int pcwd_ioports[] = { 0x270, 0x350, 0x370, 0x000 }; | |||
142 | #define CMD_ISA_RESET_RELAYS 0x0D | 145 | #define CMD_ISA_RESET_RELAYS 0x0D |
143 | 146 | ||
144 | /* Watchdog's Dip Switch heartbeat values */ | 147 | /* Watchdog's Dip Switch heartbeat values */ |
145 | static const int heartbeat_tbl [] = { | 148 | static const int heartbeat_tbl[] = { |
146 | 20, /* OFF-OFF-OFF = 20 Sec */ | 149 | 20, /* OFF-OFF-OFF = 20 Sec */ |
147 | 40, /* OFF-OFF-ON = 40 Sec */ | 150 | 40, /* OFF-OFF-ON = 40 Sec */ |
148 | 60, /* OFF-ON-OFF = 1 Min */ | 151 | 60, /* OFF-ON-OFF = 1 Min */ |
@@ -168,11 +171,15 @@ static int cards_found; | |||
168 | static atomic_t open_allowed = ATOMIC_INIT(1); | 171 | static atomic_t open_allowed = ATOMIC_INIT(1); |
169 | static char expect_close; | 172 | static char expect_close; |
170 | static int temp_panic; | 173 | static int temp_panic; |
171 | static struct { /* this is private data for each ISA-PC watchdog card */ | 174 | |
175 | /* this is private data for each ISA-PC watchdog card */ | ||
176 | static struct { | ||
172 | char fw_ver_str[6]; /* The cards firmware version */ | 177 | char fw_ver_str[6]; /* The cards firmware version */ |
173 | int revision; /* The card's revision */ | 178 | int revision; /* The card's revision */ |
174 | int supports_temp; /* Wether or not the card has a temperature device */ | 179 | int supports_temp; /* Whether or not the card has |
175 | int command_mode; /* Wether or not the card is in command mode */ | 180 | a temperature device */ |
181 | int command_mode; /* Whether or not the card is in | ||
182 | command mode */ | ||
176 | int boot_status; /* The card's boot status */ | 183 | int boot_status; /* The card's boot status */ |
177 | int io_addr; /* The cards I/O address */ | 184 | int io_addr; /* The cards I/O address */ |
178 | spinlock_t io_lock; /* the lock for io operations */ | 185 | spinlock_t io_lock; /* the lock for io operations */ |
@@ -186,16 +193,20 @@ static struct { /* this is private data for each ISA-PC watchdog card */ | |||
186 | #define DEBUG 2 /* print fancy stuff too */ | 193 | #define DEBUG 2 /* print fancy stuff too */ |
187 | static int debug = QUIET; | 194 | static int debug = QUIET; |
188 | module_param(debug, int, 0); | 195 | module_param(debug, int, 0); |
189 | MODULE_PARM_DESC(debug, "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); | 196 | MODULE_PARM_DESC(debug, |
197 | "Debug level: 0=Quiet, 1=Verbose, 2=Debug (default=0)"); | ||
190 | 198 | ||
191 | #define WATCHDOG_HEARTBEAT 0 /* default heartbeat = delay-time from dip-switches */ | 199 | /* default heartbeat = delay-time from dip-switches */ |
200 | #define WATCHDOG_HEARTBEAT 0 | ||
192 | static int heartbeat = WATCHDOG_HEARTBEAT; | 201 | static int heartbeat = WATCHDOG_HEARTBEAT; |
193 | module_param(heartbeat, int, 0); | 202 | module_param(heartbeat, int, 0); |
194 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2<=heartbeat<=7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 203 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (2 <= heartbeat <= 7200 or 0=delay-time from dip-switches, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); |
195 | 204 | ||
196 | static int nowayout = WATCHDOG_NOWAYOUT; | 205 | static int nowayout = WATCHDOG_NOWAYOUT; |
197 | module_param(nowayout, int, 0); | 206 | module_param(nowayout, int, 0); |
198 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 207 | MODULE_PARM_DESC(nowayout, |
208 | "Watchdog cannot be stopped once started (default=" | ||
209 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
199 | 210 | ||
200 | /* | 211 | /* |
201 | * Internal functions | 212 | * Internal functions |
@@ -224,7 +235,7 @@ static int send_isa_command(int cmd) | |||
224 | if (port0 == last_port0) | 235 | if (port0 == last_port0) |
225 | break; /* Data is stable */ | 236 | break; /* Data is stable */ |
226 | 237 | ||
227 | udelay (250); | 238 | udelay(250); |
228 | } | 239 | } |
229 | 240 | ||
230 | if (debug >= DEBUG) | 241 | if (debug >= DEBUG) |
@@ -236,7 +247,7 @@ static int send_isa_command(int cmd) | |||
236 | 247 | ||
237 | static int set_command_mode(void) | 248 | static int set_command_mode(void) |
238 | { | 249 | { |
239 | int i, found=0, count=0; | 250 | int i, found = 0, count = 0; |
240 | 251 | ||
241 | /* Set the card into command mode */ | 252 | /* Set the card into command mode */ |
242 | spin_lock(&pcwd_private.io_lock); | 253 | spin_lock(&pcwd_private.io_lock); |
@@ -261,7 +272,7 @@ static int set_command_mode(void) | |||
261 | printk(KERN_DEBUG PFX "command_mode=%d\n", | 272 | printk(KERN_DEBUG PFX "command_mode=%d\n", |
262 | pcwd_private.command_mode); | 273 | pcwd_private.command_mode); |
263 | 274 | ||
264 | return(found); | 275 | return found; |
265 | } | 276 | } |
266 | 277 | ||
267 | static void unset_command_mode(void) | 278 | static void unset_command_mode(void) |
@@ -296,7 +307,8 @@ static inline void pcwd_get_firmware(void) | |||
296 | ten = send_isa_command(CMD_ISA_VERSION_TENTH); | 307 | ten = send_isa_command(CMD_ISA_VERSION_TENTH); |
297 | hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); | 308 | hund = send_isa_command(CMD_ISA_VERSION_HUNDRETH); |
298 | minor = send_isa_command(CMD_ISA_VERSION_MINOR); | 309 | minor = send_isa_command(CMD_ISA_VERSION_MINOR); |
299 | sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", one, ten, hund, minor); | 310 | sprintf(pcwd_private.fw_ver_str, "%c.%c%c%c", |
311 | one, ten, hund, minor); | ||
300 | } | 312 | } |
301 | unset_command_mode(); | 313 | unset_command_mode(); |
302 | 314 | ||
@@ -305,7 +317,7 @@ static inline void pcwd_get_firmware(void) | |||
305 | 317 | ||
306 | static inline int pcwd_get_option_switches(void) | 318 | static inline int pcwd_get_option_switches(void) |
307 | { | 319 | { |
308 | int option_switches=0; | 320 | int option_switches = 0; |
309 | 321 | ||
310 | if (set_command_mode()) { | 322 | if (set_command_mode()) { |
311 | /* Get switch settings */ | 323 | /* Get switch settings */ |
@@ -313,7 +325,7 @@ static inline int pcwd_get_option_switches(void) | |||
313 | } | 325 | } |
314 | 326 | ||
315 | unset_command_mode(); | 327 | unset_command_mode(); |
316 | return(option_switches); | 328 | return option_switches; |
317 | } | 329 | } |
318 | 330 | ||
319 | static void pcwd_show_card_info(void) | 331 | static void pcwd_show_card_info(void) |
@@ -322,7 +334,9 @@ static void pcwd_show_card_info(void) | |||
322 | 334 | ||
323 | /* Get some extra info from the hardware (in command/debug/diag mode) */ | 335 | /* Get some extra info from the hardware (in command/debug/diag mode) */ |
324 | if (pcwd_private.revision == PCWD_REVISION_A) | 336 | if (pcwd_private.revision == PCWD_REVISION_A) |
325 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", pcwd_private.io_addr); | 337 | printk(KERN_INFO PFX |
338 | "ISA-PC Watchdog (REV.A) detected at port 0x%04x\n", | ||
339 | pcwd_private.io_addr); | ||
326 | else if (pcwd_private.revision == PCWD_REVISION_C) { | 340 | else if (pcwd_private.revision == PCWD_REVISION_C) { |
327 | pcwd_get_firmware(); | 341 | pcwd_get_firmware(); |
328 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", | 342 | printk(KERN_INFO PFX "ISA-PC Watchdog (REV.C) detected at port 0x%04x (Firmware version: %s)\n", |
@@ -347,12 +361,15 @@ static void pcwd_show_card_info(void) | |||
347 | printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); | 361 | printk(KERN_INFO PFX "Previous reboot was caused by the card\n"); |
348 | 362 | ||
349 | if (pcwd_private.boot_status & WDIOF_OVERHEAT) { | 363 | if (pcwd_private.boot_status & WDIOF_OVERHEAT) { |
350 | printk(KERN_EMERG PFX "Card senses a CPU Overheat. Panicking!\n"); | 364 | printk(KERN_EMERG PFX |
351 | printk(KERN_EMERG PFX "CPU Overheat\n"); | 365 | "Card senses a CPU Overheat. Panicking!\n"); |
366 | printk(KERN_EMERG PFX | ||
367 | "CPU Overheat\n"); | ||
352 | } | 368 | } |
353 | 369 | ||
354 | if (pcwd_private.boot_status == 0) | 370 | if (pcwd_private.boot_status == 0) |
355 | printk(KERN_INFO PFX "No previous trip detected - Cold boot or reset\n"); | 371 | printk(KERN_INFO PFX |
372 | "No previous trip detected - Cold boot or reset\n"); | ||
356 | } | 373 | } |
357 | 374 | ||
358 | static void pcwd_timer_ping(unsigned long data) | 375 | static void pcwd_timer_ping(unsigned long data) |
@@ -361,11 +378,12 @@ static void pcwd_timer_ping(unsigned long data) | |||
361 | 378 | ||
362 | /* If we got a heartbeat pulse within the WDT_INTERVAL | 379 | /* If we got a heartbeat pulse within the WDT_INTERVAL |
363 | * we agree to ping the WDT */ | 380 | * we agree to ping the WDT */ |
364 | if(time_before(jiffies, pcwd_private.next_heartbeat)) { | 381 | if (time_before(jiffies, pcwd_private.next_heartbeat)) { |
365 | /* Ping the watchdog */ | 382 | /* Ping the watchdog */ |
366 | spin_lock(&pcwd_private.io_lock); | 383 | spin_lock(&pcwd_private.io_lock); |
367 | if (pcwd_private.revision == PCWD_REVISION_A) { | 384 | if (pcwd_private.revision == PCWD_REVISION_A) { |
368 | /* Rev A cards are reset by setting the WD_WDRST bit in register 1 */ | 385 | /* Rev A cards are reset by setting the |
386 | WD_WDRST bit in register 1 */ | ||
369 | wdrst_stat = inb_p(pcwd_private.io_addr); | 387 | wdrst_stat = inb_p(pcwd_private.io_addr); |
370 | wdrst_stat &= 0x0F; | 388 | wdrst_stat &= 0x0F; |
371 | wdrst_stat |= WD_WDRST; | 389 | wdrst_stat |= WD_WDRST; |
@@ -381,7 +399,8 @@ static void pcwd_timer_ping(unsigned long data) | |||
381 | 399 | ||
382 | spin_unlock(&pcwd_private.io_lock); | 400 | spin_unlock(&pcwd_private.io_lock); |
383 | } else { | 401 | } else { |
384 | printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); | 402 | printk(KERN_WARNING PFX |
403 | "Heartbeat lost! Will not ping the watchdog\n"); | ||
385 | } | 404 | } |
386 | } | 405 | } |
387 | 406 | ||
@@ -454,7 +473,7 @@ static int pcwd_keepalive(void) | |||
454 | 473 | ||
455 | static int pcwd_set_heartbeat(int t) | 474 | static int pcwd_set_heartbeat(int t) |
456 | { | 475 | { |
457 | if ((t < 2) || (t > 7200)) /* arbitrary upper limit */ | 476 | if (t < 2 || t > 7200) /* arbitrary upper limit */ |
458 | return -EINVAL; | 477 | return -EINVAL; |
459 | 478 | ||
460 | heartbeat = t; | 479 | heartbeat = t; |
@@ -470,7 +489,7 @@ static int pcwd_get_status(int *status) | |||
470 | { | 489 | { |
471 | int control_status; | 490 | int control_status; |
472 | 491 | ||
473 | *status=0; | 492 | *status = 0; |
474 | spin_lock(&pcwd_private.io_lock); | 493 | spin_lock(&pcwd_private.io_lock); |
475 | if (pcwd_private.revision == PCWD_REVISION_A) | 494 | if (pcwd_private.revision == PCWD_REVISION_A) |
476 | /* Rev A cards return status information from | 495 | /* Rev A cards return status information from |
@@ -494,9 +513,9 @@ static int pcwd_get_status(int *status) | |||
494 | if (control_status & WD_T110) { | 513 | if (control_status & WD_T110) { |
495 | *status |= WDIOF_OVERHEAT; | 514 | *status |= WDIOF_OVERHEAT; |
496 | if (temp_panic) { | 515 | if (temp_panic) { |
497 | printk(KERN_INFO PFX "Temperature overheat trip!\n"); | 516 | printk(KERN_INFO PFX |
517 | "Temperature overheat trip!\n"); | ||
498 | kernel_power_off(); | 518 | kernel_power_off(); |
499 | /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ | ||
500 | } | 519 | } |
501 | } | 520 | } |
502 | } else { | 521 | } else { |
@@ -506,9 +525,9 @@ static int pcwd_get_status(int *status) | |||
506 | if (control_status & WD_REVC_TTRP) { | 525 | if (control_status & WD_REVC_TTRP) { |
507 | *status |= WDIOF_OVERHEAT; | 526 | *status |= WDIOF_OVERHEAT; |
508 | if (temp_panic) { | 527 | if (temp_panic) { |
509 | printk(KERN_INFO PFX "Temperature overheat trip!\n"); | 528 | printk(KERN_INFO PFX |
529 | "Temperature overheat trip!\n"); | ||
510 | kernel_power_off(); | 530 | kernel_power_off(); |
511 | /* or should we just do a: panic(PFX "Temperature overheat trip!\n"); */ | ||
512 | } | 531 | } |
513 | } | 532 | } |
514 | } | 533 | } |
@@ -524,18 +543,21 @@ static int pcwd_clear_status(void) | |||
524 | spin_lock(&pcwd_private.io_lock); | 543 | spin_lock(&pcwd_private.io_lock); |
525 | 544 | ||
526 | if (debug >= VERBOSE) | 545 | if (debug >= VERBOSE) |
527 | printk(KERN_INFO PFX "clearing watchdog trip status\n"); | 546 | printk(KERN_INFO PFX |
547 | "clearing watchdog trip status\n"); | ||
528 | 548 | ||
529 | control_status = inb_p(pcwd_private.io_addr + 1); | 549 | control_status = inb_p(pcwd_private.io_addr + 1); |
530 | 550 | ||
531 | if (debug >= DEBUG) { | 551 | if (debug >= DEBUG) { |
532 | printk(KERN_DEBUG PFX "status was: 0x%02x\n", control_status); | 552 | printk(KERN_DEBUG PFX "status was: 0x%02x\n", |
553 | control_status); | ||
533 | printk(KERN_DEBUG PFX "sending: 0x%02x\n", | 554 | printk(KERN_DEBUG PFX "sending: 0x%02x\n", |
534 | (control_status & WD_REVC_R2DS)); | 555 | (control_status & WD_REVC_R2DS)); |
535 | } | 556 | } |
536 | 557 | ||
537 | /* clear reset status & Keep Relay 2 disable state as it is */ | 558 | /* clear reset status & Keep Relay 2 disable state as it is */ |
538 | outb_p((control_status & WD_REVC_R2DS), pcwd_private.io_addr + 1); | 559 | outb_p((control_status & WD_REVC_R2DS), |
560 | pcwd_private.io_addr + 1); | ||
539 | 561 | ||
540 | spin_unlock(&pcwd_private.io_lock); | 562 | spin_unlock(&pcwd_private.io_lock); |
541 | } | 563 | } |
@@ -572,8 +594,7 @@ static int pcwd_get_temperature(int *temperature) | |||
572 | * /dev/watchdog handling | 594 | * /dev/watchdog handling |
573 | */ | 595 | */ |
574 | 596 | ||
575 | static int pcwd_ioctl(struct inode *inode, struct file *file, | 597 | static long pcwd_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
576 | unsigned int cmd, unsigned long arg) | ||
577 | { | 598 | { |
578 | int rv; | 599 | int rv; |
579 | int status; | 600 | int status; |
@@ -590,12 +611,9 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, | |||
590 | .identity = "PCWD", | 611 | .identity = "PCWD", |
591 | }; | 612 | }; |
592 | 613 | ||
593 | switch(cmd) { | 614 | switch (cmd) { |
594 | default: | ||
595 | return -ENOTTY; | ||
596 | |||
597 | case WDIOC_GETSUPPORT: | 615 | case WDIOC_GETSUPPORT: |
598 | if(copy_to_user(argp, &ident, sizeof(ident))) | 616 | if (copy_to_user(argp, &ident, sizeof(ident))) |
599 | return -EFAULT; | 617 | return -EFAULT; |
600 | return 0; | 618 | return 0; |
601 | 619 | ||
@@ -613,25 +631,22 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, | |||
613 | return put_user(temperature, argp); | 631 | return put_user(temperature, argp); |
614 | 632 | ||
615 | case WDIOC_SETOPTIONS: | 633 | case WDIOC_SETOPTIONS: |
616 | if (pcwd_private.revision == PCWD_REVISION_C) | 634 | if (pcwd_private.revision == PCWD_REVISION_C) { |
617 | { | 635 | if (get_user(rv, argp)) |
618 | if(copy_from_user(&rv, argp, sizeof(int))) | ||
619 | return -EFAULT; | 636 | return -EFAULT; |
620 | 637 | ||
621 | if (rv & WDIOS_DISABLECARD) | 638 | if (rv & WDIOS_DISABLECARD) { |
622 | { | 639 | status = pcwd_stop(); |
623 | return pcwd_stop(); | 640 | if (status < 0) |
641 | return status; | ||
624 | } | 642 | } |
625 | 643 | if (rv & WDIOS_ENABLECARD) { | |
626 | if (rv & WDIOS_ENABLECARD) | 644 | status = pcwd_start(); |
627 | { | 645 | if (status < 0) |
628 | return pcwd_start(); | 646 | return status; |
629 | } | 647 | } |
630 | |||
631 | if (rv & WDIOS_TEMPPANIC) | 648 | if (rv & WDIOS_TEMPPANIC) |
632 | { | ||
633 | temp_panic = 1; | 649 | temp_panic = 1; |
634 | } | ||
635 | } | 650 | } |
636 | return -EINVAL; | 651 | return -EINVAL; |
637 | 652 | ||
@@ -651,6 +666,9 @@ static int pcwd_ioctl(struct inode *inode, struct file *file, | |||
651 | 666 | ||
652 | case WDIOC_GETTIMEOUT: | 667 | case WDIOC_GETTIMEOUT: |
653 | return put_user(heartbeat, argp); | 668 | return put_user(heartbeat, argp); |
669 | |||
670 | default: | ||
671 | return -ENOTTY; | ||
654 | } | 672 | } |
655 | 673 | ||
656 | return 0; | 674 | return 0; |
@@ -682,16 +700,10 @@ static ssize_t pcwd_write(struct file *file, const char __user *buf, size_t len, | |||
682 | 700 | ||
683 | static int pcwd_open(struct inode *inode, struct file *file) | 701 | static int pcwd_open(struct inode *inode, struct file *file) |
684 | { | 702 | { |
685 | if (!atomic_dec_and_test(&open_allowed) ) { | 703 | if (test_and_set_bit(0, &open_allowed)) |
686 | if (debug >= VERBOSE) | ||
687 | printk(KERN_ERR PFX "Attempt to open already opened device.\n"); | ||
688 | atomic_inc( &open_allowed ); | ||
689 | return -EBUSY; | 704 | return -EBUSY; |
690 | } | ||
691 | |||
692 | if (nowayout) | 705 | if (nowayout) |
693 | __module_get(THIS_MODULE); | 706 | __module_get(THIS_MODULE); |
694 | |||
695 | /* Activate */ | 707 | /* Activate */ |
696 | pcwd_start(); | 708 | pcwd_start(); |
697 | pcwd_keepalive(); | 709 | pcwd_keepalive(); |
@@ -700,14 +712,15 @@ static int pcwd_open(struct inode *inode, struct file *file) | |||
700 | 712 | ||
701 | static int pcwd_close(struct inode *inode, struct file *file) | 713 | static int pcwd_close(struct inode *inode, struct file *file) |
702 | { | 714 | { |
703 | if (expect_close == 42) { | 715 | if (expect_close == 42) |
704 | pcwd_stop(); | 716 | pcwd_stop(); |
705 | } else { | 717 | else { |
706 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 718 | printk(KERN_CRIT PFX |
719 | "Unexpected close, not stopping watchdog!\n"); | ||
707 | pcwd_keepalive(); | 720 | pcwd_keepalive(); |
708 | } | 721 | } |
709 | expect_close = 0; | 722 | expect_close = 0; |
710 | atomic_inc( &open_allowed ); | 723 | clear_bit(0, &open_allowed); |
711 | return 0; | 724 | return 0; |
712 | } | 725 | } |
713 | 726 | ||
@@ -750,7 +763,7 @@ static const struct file_operations pcwd_fops = { | |||
750 | .owner = THIS_MODULE, | 763 | .owner = THIS_MODULE, |
751 | .llseek = no_llseek, | 764 | .llseek = no_llseek, |
752 | .write = pcwd_write, | 765 | .write = pcwd_write, |
753 | .ioctl = pcwd_ioctl, | 766 | .unlocked_ioctl = pcwd_ioctl, |
754 | .open = pcwd_open, | 767 | .open = pcwd_open, |
755 | .release = pcwd_close, | 768 | .release = pcwd_close, |
756 | }; | 769 | }; |
@@ -788,7 +801,7 @@ static inline int get_revision(void) | |||
788 | * presumes a floating bus reads as 0xff. */ | 801 | * presumes a floating bus reads as 0xff. */ |
789 | if ((inb(pcwd_private.io_addr + 2) == 0xFF) || | 802 | if ((inb(pcwd_private.io_addr + 2) == 0xFF) || |
790 | (inb(pcwd_private.io_addr + 3) == 0xFF)) | 803 | (inb(pcwd_private.io_addr + 3) == 0xFF)) |
791 | r=PCWD_REVISION_A; | 804 | r = PCWD_REVISION_A; |
792 | spin_unlock(&pcwd_private.io_lock); | 805 | spin_unlock(&pcwd_private.io_lock); |
793 | 806 | ||
794 | return r; | 807 | return r; |
@@ -803,7 +816,7 @@ static inline int get_revision(void) | |||
803 | */ | 816 | */ |
804 | static int __devinit pcwd_isa_match(struct device *dev, unsigned int id) | 817 | static int __devinit pcwd_isa_match(struct device *dev, unsigned int id) |
805 | { | 818 | { |
806 | int base_addr=pcwd_ioports[id]; | 819 | int base_addr = pcwd_ioports[id]; |
807 | int port0, last_port0; /* Reg 0, in case it's REV A */ | 820 | int port0, last_port0; /* Reg 0, in case it's REV A */ |
808 | int port1, last_port1; /* Register 1 for REV C cards */ | 821 | int port1, last_port1; /* Register 1 for REV C cards */ |
809 | int i; | 822 | int i; |
@@ -813,7 +826,7 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id) | |||
813 | printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n", | 826 | printk(KERN_DEBUG PFX "pcwd_isa_match id=%d\n", |
814 | id); | 827 | id); |
815 | 828 | ||
816 | if (!request_region (base_addr, 4, "PCWD")) { | 829 | if (!request_region(base_addr, 4, "PCWD")) { |
817 | printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr); | 830 | printk(KERN_INFO PFX "Port 0x%04x unavailable\n", base_addr); |
818 | return 0; | 831 | return 0; |
819 | } | 832 | } |
@@ -842,7 +855,7 @@ static int __devinit pcwd_isa_match(struct device *dev, unsigned int id) | |||
842 | } | 855 | } |
843 | } | 856 | } |
844 | } | 857 | } |
845 | release_region (base_addr, 4); | 858 | release_region(base_addr, 4); |
846 | 859 | ||
847 | return retval; | 860 | return retval; |
848 | } | 861 | } |
@@ -857,7 +870,8 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) | |||
857 | 870 | ||
858 | cards_found++; | 871 | cards_found++; |
859 | if (cards_found == 1) | 872 | if (cards_found == 1) |
860 | printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", WD_VER); | 873 | printk(KERN_INFO PFX "v%s Ken Hollis (kenji@bitgate.com)\n", |
874 | WD_VER); | ||
861 | 875 | ||
862 | if (cards_found > 1) { | 876 | if (cards_found > 1) { |
863 | printk(KERN_ERR PFX "This driver only supports 1 device\n"); | 877 | printk(KERN_ERR PFX "This driver only supports 1 device\n"); |
@@ -875,10 +889,11 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) | |||
875 | /* Check card's revision */ | 889 | /* Check card's revision */ |
876 | pcwd_private.revision = get_revision(); | 890 | pcwd_private.revision = get_revision(); |
877 | 891 | ||
878 | if (!request_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { | 892 | if (!request_region(pcwd_private.io_addr, |
893 | (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4, "PCWD")) { | ||
879 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | 894 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
880 | pcwd_private.io_addr); | 895 | pcwd_private.io_addr); |
881 | ret=-EIO; | 896 | ret = -EIO; |
882 | goto error_request_region; | 897 | goto error_request_region; |
883 | } | 898 | } |
884 | 899 | ||
@@ -908,26 +923,30 @@ static int __devinit pcwd_isa_probe(struct device *dev, unsigned int id) | |||
908 | if (heartbeat == 0) | 923 | if (heartbeat == 0) |
909 | heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)]; | 924 | heartbeat = heartbeat_tbl[(pcwd_get_option_switches() & 0x07)]; |
910 | 925 | ||
911 | /* Check that the heartbeat value is within it's range ; if not reset to the default */ | 926 | /* Check that the heartbeat value is within it's range; |
927 | if not reset to the default */ | ||
912 | if (pcwd_set_heartbeat(heartbeat)) { | 928 | if (pcwd_set_heartbeat(heartbeat)) { |
913 | pcwd_set_heartbeat(WATCHDOG_HEARTBEAT); | 929 | pcwd_set_heartbeat(WATCHDOG_HEARTBEAT); |
914 | printk(KERN_INFO PFX "heartbeat value must be 2<=heartbeat<=7200, using %d\n", | 930 | printk(KERN_INFO PFX |
915 | WATCHDOG_HEARTBEAT); | 931 | "heartbeat value must be 2 <= heartbeat <= 7200, using %d\n", |
932 | WATCHDOG_HEARTBEAT); | ||
916 | } | 933 | } |
917 | 934 | ||
918 | if (pcwd_private.supports_temp) { | 935 | if (pcwd_private.supports_temp) { |
919 | ret = misc_register(&temp_miscdev); | 936 | ret = misc_register(&temp_miscdev); |
920 | if (ret) { | 937 | if (ret) { |
921 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 938 | printk(KERN_ERR PFX |
922 | TEMP_MINOR, ret); | 939 | "cannot register miscdev on minor=%d (err=%d)\n", |
940 | TEMP_MINOR, ret); | ||
923 | goto error_misc_register_temp; | 941 | goto error_misc_register_temp; |
924 | } | 942 | } |
925 | } | 943 | } |
926 | 944 | ||
927 | ret = misc_register(&pcwd_miscdev); | 945 | ret = misc_register(&pcwd_miscdev); |
928 | if (ret) { | 946 | if (ret) { |
929 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 947 | printk(KERN_ERR PFX |
930 | WATCHDOG_MINOR, ret); | 948 | "cannot register miscdev on minor=%d (err=%d)\n", |
949 | WATCHDOG_MINOR, ret); | ||
931 | goto error_misc_register_watchdog; | 950 | goto error_misc_register_watchdog; |
932 | } | 951 | } |
933 | 952 | ||
@@ -940,7 +959,8 @@ error_misc_register_watchdog: | |||
940 | if (pcwd_private.supports_temp) | 959 | if (pcwd_private.supports_temp) |
941 | misc_deregister(&temp_miscdev); | 960 | misc_deregister(&temp_miscdev); |
942 | error_misc_register_temp: | 961 | error_misc_register_temp: |
943 | release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); | 962 | release_region(pcwd_private.io_addr, |
963 | (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); | ||
944 | error_request_region: | 964 | error_request_region: |
945 | pcwd_private.io_addr = 0x0000; | 965 | pcwd_private.io_addr = 0x0000; |
946 | cards_found--; | 966 | cards_found--; |
@@ -964,7 +984,8 @@ static int __devexit pcwd_isa_remove(struct device *dev, unsigned int id) | |||
964 | misc_deregister(&pcwd_miscdev); | 984 | misc_deregister(&pcwd_miscdev); |
965 | if (pcwd_private.supports_temp) | 985 | if (pcwd_private.supports_temp) |
966 | misc_deregister(&temp_miscdev); | 986 | misc_deregister(&temp_miscdev); |
967 | release_region(pcwd_private.io_addr, (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); | 987 | release_region(pcwd_private.io_addr, |
988 | (pcwd_private.revision == PCWD_REVISION_A) ? 2 : 4); | ||
968 | pcwd_private.io_addr = 0x0000; | 989 | pcwd_private.io_addr = 0x0000; |
969 | cards_found--; | 990 | cards_found--; |
970 | 991 | ||
diff --git a/drivers/watchdog/pcwd_pci.c b/drivers/watchdog/pcwd_pci.c index 61a89e959642..90eb1d4271d7 100644 --- a/drivers/watchdog/pcwd_pci.c +++ b/drivers/watchdog/pcwd_pci.c | |||
@@ -46,9 +46,8 @@ | |||
46 | #include <linux/pci.h> /* For pci functions */ | 46 | #include <linux/pci.h> /* For pci functions */ |
47 | #include <linux/ioport.h> /* For io-port access */ | 47 | #include <linux/ioport.h> /* For io-port access */ |
48 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ | 48 | #include <linux/spinlock.h> /* For spin_lock/spin_unlock/... */ |
49 | 49 | #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ | |
50 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | 50 | #include <linux/io.h> /* For inb/outb/... */ |
51 | #include <asm/io.h> /* For inb/outb/... */ | ||
52 | 51 | ||
53 | /* Module and version information */ | 52 | /* Module and version information */ |
54 | #define WATCHDOG_VERSION "1.03" | 53 | #define WATCHDOG_VERSION "1.03" |
@@ -97,7 +96,7 @@ | |||
97 | #define CMD_GET_CLEAR_RESET_COUNT 0x84 | 96 | #define CMD_GET_CLEAR_RESET_COUNT 0x84 |
98 | 97 | ||
99 | /* Watchdog's Dip Switch heartbeat values */ | 98 | /* Watchdog's Dip Switch heartbeat values */ |
100 | static const int heartbeat_tbl [] = { | 99 | static const int heartbeat_tbl[] = { |
101 | 5, /* OFF-OFF-OFF = 5 Sec */ | 100 | 5, /* OFF-OFF-OFF = 5 Sec */ |
102 | 10, /* OFF-OFF-ON = 10 Sec */ | 101 | 10, /* OFF-OFF-ON = 10 Sec */ |
103 | 30, /* OFF-ON-OFF = 30 Sec */ | 102 | 30, /* OFF-ON-OFF = 30 Sec */ |
@@ -220,11 +219,10 @@ static void pcipcwd_show_card_info(void) | |||
220 | int option_switches; | 219 | int option_switches; |
221 | 220 | ||
222 | got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); | 221 | got_fw_rev = send_command(CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); |
223 | if (got_fw_rev) { | 222 | if (got_fw_rev) |
224 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); | 223 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); |
225 | } else { | 224 | else |
226 | sprintf(fw_ver_str, "<card no answer>"); | 225 | sprintf(fw_ver_str, "<card no answer>"); |
227 | } | ||
228 | 226 | ||
229 | /* Get switch settings */ | 227 | /* Get switch settings */ |
230 | option_switches = pcipcwd_get_option_switches(); | 228 | option_switches = pcipcwd_get_option_switches(); |
@@ -331,7 +329,7 @@ static int pcipcwd_get_status(int *status) | |||
331 | { | 329 | { |
332 | int control_status; | 330 | int control_status; |
333 | 331 | ||
334 | *status=0; | 332 | *status = 0; |
335 | control_status = inb_p(pcipcwd_private.io_addr + 1); | 333 | control_status = inb_p(pcipcwd_private.io_addr + 1); |
336 | if (control_status & WD_PCI_WTRP) | 334 | if (control_status & WD_PCI_WTRP) |
337 | *status |= WDIOF_CARDRESET; | 335 | *status |= WDIOF_CARDRESET; |
@@ -369,8 +367,8 @@ static int pcipcwd_clear_status(void) | |||
369 | outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); | 367 | outb_p((control_status & WD_PCI_R2DS) | WD_PCI_WTRP, pcipcwd_private.io_addr + 1); |
370 | 368 | ||
371 | /* clear reset counter */ | 369 | /* clear reset counter */ |
372 | msb=0; | 370 | msb = 0; |
373 | reset_counter=0xff; | 371 | reset_counter = 0xff; |
374 | send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); | 372 | send_command(CMD_GET_CLEAR_RESET_COUNT, &msb, &reset_counter); |
375 | 373 | ||
376 | if (debug >= DEBUG) { | 374 | if (debug >= DEBUG) { |
@@ -442,7 +440,7 @@ static ssize_t pcipcwd_write(struct file *file, const char __user *data, | |||
442 | /* scan to see whether or not we got the magic character */ | 440 | /* scan to see whether or not we got the magic character */ |
443 | for (i = 0; i != len; i++) { | 441 | for (i = 0; i != len; i++) { |
444 | char c; | 442 | char c; |
445 | if(get_user(c, data+i)) | 443 | if (get_user(c, data + i)) |
446 | return -EFAULT; | 444 | return -EFAULT; |
447 | if (c == 'V') | 445 | if (c == 'V') |
448 | expect_release = 42; | 446 | expect_release = 42; |
@@ -455,8 +453,8 @@ static ssize_t pcipcwd_write(struct file *file, const char __user *data, | |||
455 | return len; | 453 | return len; |
456 | } | 454 | } |
457 | 455 | ||
458 | static int pcipcwd_ioctl(struct inode *inode, struct file *file, | 456 | static long pcipcwd_ioctl(struct file *file, unsigned int cmd, |
459 | unsigned int cmd, unsigned long arg) | 457 | unsigned long arg) |
460 | { | 458 | { |
461 | void __user *argp = (void __user *)arg; | 459 | void __user *argp = (void __user *)arg; |
462 | int __user *p = argp; | 460 | int __user *p = argp; |
@@ -471,92 +469,89 @@ static int pcipcwd_ioctl(struct inode *inode, struct file *file, | |||
471 | }; | 469 | }; |
472 | 470 | ||
473 | switch (cmd) { | 471 | switch (cmd) { |
474 | case WDIOC_GETSUPPORT: | 472 | case WDIOC_GETSUPPORT: |
475 | return copy_to_user(argp, &ident, | 473 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
476 | sizeof (ident)) ? -EFAULT : 0; | 474 | |
475 | case WDIOC_GETSTATUS: | ||
476 | { | ||
477 | int status; | ||
478 | pcipcwd_get_status(&status); | ||
479 | return put_user(status, p); | ||
480 | } | ||
477 | 481 | ||
478 | case WDIOC_GETSTATUS: | 482 | case WDIOC_GETBOOTSTATUS: |
479 | { | 483 | return put_user(pcipcwd_private.boot_status, p); |
480 | int status; | ||
481 | 484 | ||
482 | pcipcwd_get_status(&status); | 485 | case WDIOC_GETTEMP: |
486 | { | ||
487 | int temperature; | ||
483 | 488 | ||
484 | return put_user(status, p); | 489 | if (pcipcwd_get_temperature(&temperature)) |
485 | } | 490 | return -EFAULT; |
486 | 491 | ||
487 | case WDIOC_GETBOOTSTATUS: | 492 | return put_user(temperature, p); |
488 | return put_user(pcipcwd_private.boot_status, p); | 493 | } |
489 | 494 | ||
490 | case WDIOC_GETTEMP: | 495 | case WDIOC_SETOPTIONS: |
491 | { | 496 | { |
492 | int temperature; | 497 | int new_options, retval = -EINVAL; |
493 | 498 | ||
494 | if (pcipcwd_get_temperature(&temperature)) | 499 | if (get_user(new_options, p)) |
495 | return -EFAULT; | 500 | return -EFAULT; |
496 | 501 | ||
497 | return put_user(temperature, p); | 502 | if (new_options & WDIOS_DISABLECARD) { |
503 | if (pcipcwd_stop()) | ||
504 | return -EIO; | ||
505 | retval = 0; | ||
498 | } | 506 | } |
499 | 507 | ||
500 | case WDIOC_KEEPALIVE: | 508 | if (new_options & WDIOS_ENABLECARD) { |
501 | pcipcwd_keepalive(); | 509 | if (pcipcwd_start()) |
502 | return 0; | 510 | return -EIO; |
503 | 511 | retval = 0; | |
504 | case WDIOC_SETOPTIONS: | 512 | } |
505 | { | ||
506 | int new_options, retval = -EINVAL; | ||
507 | |||
508 | if (get_user (new_options, p)) | ||
509 | return -EFAULT; | ||
510 | |||
511 | if (new_options & WDIOS_DISABLECARD) { | ||
512 | if (pcipcwd_stop()) | ||
513 | return -EIO; | ||
514 | retval = 0; | ||
515 | } | ||
516 | 513 | ||
517 | if (new_options & WDIOS_ENABLECARD) { | 514 | if (new_options & WDIOS_TEMPPANIC) { |
518 | if (pcipcwd_start()) | 515 | temp_panic = 1; |
519 | return -EIO; | 516 | retval = 0; |
520 | retval = 0; | 517 | } |
521 | } | ||
522 | 518 | ||
523 | if (new_options & WDIOS_TEMPPANIC) { | 519 | return retval; |
524 | temp_panic = 1; | 520 | } |
525 | retval = 0; | ||
526 | } | ||
527 | 521 | ||
528 | return retval; | 522 | case WDIOC_KEEPALIVE: |
529 | } | 523 | pcipcwd_keepalive(); |
524 | return 0; | ||
530 | 525 | ||
531 | case WDIOC_SETTIMEOUT: | 526 | case WDIOC_SETTIMEOUT: |
532 | { | 527 | { |
533 | int new_heartbeat; | 528 | int new_heartbeat; |
534 | 529 | ||
535 | if (get_user(new_heartbeat, p)) | 530 | if (get_user(new_heartbeat, p)) |
536 | return -EFAULT; | 531 | return -EFAULT; |
537 | 532 | ||
538 | if (pcipcwd_set_heartbeat(new_heartbeat)) | 533 | if (pcipcwd_set_heartbeat(new_heartbeat)) |
539 | return -EINVAL; | 534 | return -EINVAL; |
540 | 535 | ||
541 | pcipcwd_keepalive(); | 536 | pcipcwd_keepalive(); |
542 | /* Fall */ | 537 | /* Fall */ |
543 | } | 538 | } |
544 | 539 | ||
545 | case WDIOC_GETTIMEOUT: | 540 | case WDIOC_GETTIMEOUT: |
546 | return put_user(heartbeat, p); | 541 | return put_user(heartbeat, p); |
547 | 542 | ||
548 | case WDIOC_GETTIMELEFT: | 543 | case WDIOC_GETTIMELEFT: |
549 | { | 544 | { |
550 | int time_left; | 545 | int time_left; |
551 | 546 | ||
552 | if (pcipcwd_get_timeleft(&time_left)) | 547 | if (pcipcwd_get_timeleft(&time_left)) |
553 | return -EFAULT; | 548 | return -EFAULT; |
554 | 549 | ||
555 | return put_user(time_left, p); | 550 | return put_user(time_left, p); |
556 | } | 551 | } |
557 | 552 | ||
558 | default: | 553 | default: |
559 | return -ENOTTY; | 554 | return -ENOTTY; |
560 | } | 555 | } |
561 | } | 556 | } |
562 | 557 | ||
@@ -603,7 +598,7 @@ static ssize_t pcipcwd_temp_read(struct file *file, char __user *data, | |||
603 | if (pcipcwd_get_temperature(&temperature)) | 598 | if (pcipcwd_get_temperature(&temperature)) |
604 | return -EFAULT; | 599 | return -EFAULT; |
605 | 600 | ||
606 | if (copy_to_user (data, &temperature, 1)) | 601 | if (copy_to_user(data, &temperature, 1)) |
607 | return -EFAULT; | 602 | return -EFAULT; |
608 | 603 | ||
609 | return 1; | 604 | return 1; |
@@ -628,10 +623,8 @@ static int pcipcwd_temp_release(struct inode *inode, struct file *file) | |||
628 | 623 | ||
629 | static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 624 | static int pcipcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) |
630 | { | 625 | { |
631 | if (code==SYS_DOWN || code==SYS_HALT) { | 626 | if (code == SYS_DOWN || code == SYS_HALT) |
632 | /* Turn the WDT off */ | 627 | pcipcwd_stop(); /* Turn the WDT off */ |
633 | pcipcwd_stop(); | ||
634 | } | ||
635 | 628 | ||
636 | return NOTIFY_DONE; | 629 | return NOTIFY_DONE; |
637 | } | 630 | } |
@@ -644,7 +637,7 @@ static const struct file_operations pcipcwd_fops = { | |||
644 | .owner = THIS_MODULE, | 637 | .owner = THIS_MODULE, |
645 | .llseek = no_llseek, | 638 | .llseek = no_llseek, |
646 | .write = pcipcwd_write, | 639 | .write = pcipcwd_write, |
647 | .ioctl = pcipcwd_ioctl, | 640 | .unlocked_ioctl = pcipcwd_ioctl, |
648 | .open = pcipcwd_open, | 641 | .open = pcipcwd_open, |
649 | .release = pcipcwd_release, | 642 | .release = pcipcwd_release, |
650 | }; | 643 | }; |
diff --git a/drivers/watchdog/pcwd_usb.c b/drivers/watchdog/pcwd_usb.c index bf443d077a1e..c1685c942de6 100644 --- a/drivers/watchdog/pcwd_usb.c +++ b/drivers/watchdog/pcwd_usb.c | |||
@@ -40,8 +40,7 @@ | |||
40 | #include <linux/slab.h> /* For kmalloc, ... */ | 40 | #include <linux/slab.h> /* For kmalloc, ... */ |
41 | #include <linux/mutex.h> /* For mutex locking */ | 41 | #include <linux/mutex.h> /* For mutex locking */ |
42 | #include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */ | 42 | #include <linux/hid.h> /* For HID_REQ_SET_REPORT & HID_DT_REPORT */ |
43 | 43 | #include <linux/uaccess.h> /* For copy_to_user/put_user/... */ | |
44 | #include <asm/uaccess.h> /* For copy_to_user/put_user/... */ | ||
45 | 44 | ||
46 | 45 | ||
47 | #ifdef CONFIG_USB_DEBUG | 46 | #ifdef CONFIG_USB_DEBUG |
@@ -88,7 +87,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" _ | |||
88 | #define USB_PCWD_PRODUCT_ID 0x1140 | 87 | #define USB_PCWD_PRODUCT_ID 0x1140 |
89 | 88 | ||
90 | /* table of devices that work with this driver */ | 89 | /* table of devices that work with this driver */ |
91 | static struct usb_device_id usb_pcwd_table [] = { | 90 | static struct usb_device_id usb_pcwd_table[] = { |
92 | { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) }, | 91 | { USB_DEVICE(USB_PCWD_VENDOR_ID, USB_PCWD_PRODUCT_ID) }, |
93 | { } /* Terminating entry */ | 92 | { } /* Terminating entry */ |
94 | }; | 93 | }; |
@@ -110,7 +109,7 @@ MODULE_DEVICE_TABLE (usb, usb_pcwd_table); | |||
110 | #define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG | 109 | #define CMD_DISABLE_WATCHDOG CMD_ENABLE_WATCHDOG |
111 | 110 | ||
112 | /* Watchdog's Dip Switch heartbeat values */ | 111 | /* Watchdog's Dip Switch heartbeat values */ |
113 | static const int heartbeat_tbl [] = { | 112 | static const int heartbeat_tbl[] = { |
114 | 5, /* OFF-OFF-OFF = 5 Sec */ | 113 | 5, /* OFF-OFF-OFF = 5 Sec */ |
115 | 10, /* OFF-OFF-ON = 10 Sec */ | 114 | 10, /* OFF-OFF-ON = 10 Sec */ |
116 | 30, /* OFF-ON-OFF = 30 Sec */ | 115 | 30, /* OFF-ON-OFF = 30 Sec */ |
@@ -130,15 +129,15 @@ static char expect_release; | |||
130 | 129 | ||
131 | /* Structure to hold all of our device specific stuff */ | 130 | /* Structure to hold all of our device specific stuff */ |
132 | struct usb_pcwd_private { | 131 | struct usb_pcwd_private { |
133 | struct usb_device * udev; /* save off the usb device pointer */ | 132 | struct usb_device *udev; /* save off the usb device pointer */ |
134 | struct usb_interface * interface; /* the interface for this device */ | 133 | struct usb_interface *interface; /* the interface for this device */ |
135 | 134 | ||
136 | unsigned int interface_number; /* the interface number used for cmd's */ | 135 | unsigned int interface_number; /* the interface number used for cmd's */ |
137 | 136 | ||
138 | unsigned char * intr_buffer; /* the buffer to intr data */ | 137 | unsigned char *intr_buffer; /* the buffer to intr data */ |
139 | dma_addr_t intr_dma; /* the dma address for the intr buffer */ | 138 | dma_addr_t intr_dma; /* the dma address for the intr buffer */ |
140 | size_t intr_size; /* the size of the intr buffer */ | 139 | size_t intr_size; /* the size of the intr buffer */ |
141 | struct urb * intr_urb; /* the urb used for the intr pipe */ | 140 | struct urb *intr_urb; /* the urb used for the intr pipe */ |
142 | 141 | ||
143 | unsigned char cmd_command; /* The command that is reported back */ | 142 | unsigned char cmd_command; /* The command that is reported back */ |
144 | unsigned char cmd_data_msb; /* The data MSB that is reported back */ | 143 | unsigned char cmd_data_msb; /* The data MSB that is reported back */ |
@@ -154,8 +153,8 @@ static struct usb_pcwd_private *usb_pcwd_device; | |||
154 | static DEFINE_MUTEX(disconnect_mutex); | 153 | static DEFINE_MUTEX(disconnect_mutex); |
155 | 154 | ||
156 | /* local function prototypes */ | 155 | /* local function prototypes */ |
157 | static int usb_pcwd_probe (struct usb_interface *interface, const struct usb_device_id *id); | 156 | static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_device_id *id); |
158 | static void usb_pcwd_disconnect (struct usb_interface *interface); | 157 | static void usb_pcwd_disconnect(struct usb_interface *interface); |
159 | 158 | ||
160 | /* usb specific object needed to register this driver with the usb subsystem */ | 159 | /* usb specific object needed to register this driver with the usb subsystem */ |
161 | static struct usb_driver usb_pcwd_driver = { | 160 | static struct usb_driver usb_pcwd_driver = { |
@@ -195,10 +194,10 @@ static void usb_pcwd_intr_done(struct urb *urb) | |||
195 | usb_pcwd->cmd_data_lsb = data[2]; | 194 | usb_pcwd->cmd_data_lsb = data[2]; |
196 | 195 | ||
197 | /* notify anyone waiting that the cmd has finished */ | 196 | /* notify anyone waiting that the cmd has finished */ |
198 | atomic_set (&usb_pcwd->cmd_received, 1); | 197 | atomic_set(&usb_pcwd->cmd_received, 1); |
199 | 198 | ||
200 | resubmit: | 199 | resubmit: |
201 | retval = usb_submit_urb (urb, GFP_ATOMIC); | 200 | retval = usb_submit_urb(urb, GFP_ATOMIC); |
202 | if (retval) | 201 | if (retval) |
203 | printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n", | 202 | printk(KERN_ERR PFX "can't resubmit intr, usb_submit_urb failed with result %d\n", |
204 | retval); | 203 | retval); |
@@ -224,7 +223,7 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha | |||
224 | dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x", | 223 | dbg("sending following data cmd=0x%02x msb=0x%02x lsb=0x%02x", |
225 | buf[0], buf[1], buf[2]); | 224 | buf[0], buf[1], buf[2]); |
226 | 225 | ||
227 | atomic_set (&usb_pcwd->cmd_received, 0); | 226 | atomic_set(&usb_pcwd->cmd_received, 0); |
228 | 227 | ||
229 | if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0), | 228 | if (usb_control_msg(usb_pcwd->udev, usb_sndctrlpipe(usb_pcwd->udev, 0), |
230 | HID_REQ_SET_REPORT, HID_DT_REPORT, | 229 | HID_REQ_SET_REPORT, HID_DT_REPORT, |
@@ -237,7 +236,7 @@ static int usb_pcwd_send_command(struct usb_pcwd_private *usb_pcwd, unsigned cha | |||
237 | got_response = 0; | 236 | got_response = 0; |
238 | for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) { | 237 | for (count = 0; (count < USB_COMMAND_TIMEOUT) && (!got_response); count++) { |
239 | mdelay(1); | 238 | mdelay(1); |
240 | if (atomic_read (&usb_pcwd->cmd_received)) | 239 | if (atomic_read(&usb_pcwd->cmd_received)) |
241 | got_response = 1; | 240 | got_response = 1; |
242 | } | 241 | } |
243 | 242 | ||
@@ -356,7 +355,7 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data, | |||
356 | /* scan to see whether or not we got the magic character */ | 355 | /* scan to see whether or not we got the magic character */ |
357 | for (i = 0; i != len; i++) { | 356 | for (i = 0; i != len; i++) { |
358 | char c; | 357 | char c; |
359 | if(get_user(c, data+i)) | 358 | if (get_user(c, data + i)) |
360 | return -EFAULT; | 359 | return -EFAULT; |
361 | if (c == 'V') | 360 | if (c == 'V') |
362 | expect_release = 42; | 361 | expect_release = 42; |
@@ -369,8 +368,8 @@ static ssize_t usb_pcwd_write(struct file *file, const char __user *data, | |||
369 | return len; | 368 | return len; |
370 | } | 369 | } |
371 | 370 | ||
372 | static int usb_pcwd_ioctl(struct inode *inode, struct file *file, | 371 | static long usb_pcwd_ioctl(struct file *file, unsigned int cmd, |
373 | unsigned int cmd, unsigned long arg) | 372 | unsigned long arg) |
374 | { | 373 | { |
375 | void __user *argp = (void __user *)arg; | 374 | void __user *argp = (void __user *)arg; |
376 | int __user *p = argp; | 375 | int __user *p = argp; |
@@ -383,77 +382,76 @@ static int usb_pcwd_ioctl(struct inode *inode, struct file *file, | |||
383 | }; | 382 | }; |
384 | 383 | ||
385 | switch (cmd) { | 384 | switch (cmd) { |
386 | case WDIOC_GETSUPPORT: | 385 | case WDIOC_GETSUPPORT: |
387 | return copy_to_user(argp, &ident, | 386 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
388 | sizeof (ident)) ? -EFAULT : 0; | ||
389 | 387 | ||
390 | case WDIOC_GETSTATUS: | 388 | case WDIOC_GETSTATUS: |
391 | case WDIOC_GETBOOTSTATUS: | 389 | case WDIOC_GETBOOTSTATUS: |
392 | return put_user(0, p); | 390 | return put_user(0, p); |
393 | 391 | ||
394 | case WDIOC_GETTEMP: | 392 | case WDIOC_GETTEMP: |
395 | { | 393 | { |
396 | int temperature; | 394 | int temperature; |
397 | 395 | ||
398 | if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) | 396 | if (usb_pcwd_get_temperature(usb_pcwd_device, &temperature)) |
399 | return -EFAULT; | 397 | return -EFAULT; |
400 | 398 | ||
401 | return put_user(temperature, p); | 399 | return put_user(temperature, p); |
402 | } | 400 | } |
403 | 401 | ||
404 | case WDIOC_KEEPALIVE: | 402 | case WDIOC_SETOPTIONS: |
405 | usb_pcwd_keepalive(usb_pcwd_device); | 403 | { |
406 | return 0; | 404 | int new_options, retval = -EINVAL; |
407 | 405 | ||
408 | case WDIOC_SETOPTIONS: | 406 | if (get_user(new_options, p)) |
409 | { | 407 | return -EFAULT; |
410 | int new_options, retval = -EINVAL; | ||
411 | 408 | ||
412 | if (get_user (new_options, p)) | 409 | if (new_options & WDIOS_DISABLECARD) { |
413 | return -EFAULT; | 410 | usb_pcwd_stop(usb_pcwd_device); |
411 | retval = 0; | ||
412 | } | ||
414 | 413 | ||
415 | if (new_options & WDIOS_DISABLECARD) { | 414 | if (new_options & WDIOS_ENABLECARD) { |
416 | usb_pcwd_stop(usb_pcwd_device); | 415 | usb_pcwd_start(usb_pcwd_device); |
417 | retval = 0; | 416 | retval = 0; |
418 | } | 417 | } |
419 | 418 | ||
420 | if (new_options & WDIOS_ENABLECARD) { | 419 | return retval; |
421 | usb_pcwd_start(usb_pcwd_device); | 420 | } |
422 | retval = 0; | ||
423 | } | ||
424 | 421 | ||
425 | return retval; | 422 | case WDIOC_KEEPALIVE: |
426 | } | 423 | usb_pcwd_keepalive(usb_pcwd_device); |
424 | return 0; | ||
427 | 425 | ||
428 | case WDIOC_SETTIMEOUT: | 426 | case WDIOC_SETTIMEOUT: |
429 | { | 427 | { |
430 | int new_heartbeat; | 428 | int new_heartbeat; |
431 | 429 | ||
432 | if (get_user(new_heartbeat, p)) | 430 | if (get_user(new_heartbeat, p)) |
433 | return -EFAULT; | 431 | return -EFAULT; |
434 | 432 | ||
435 | if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) | 433 | if (usb_pcwd_set_heartbeat(usb_pcwd_device, new_heartbeat)) |
436 | return -EINVAL; | 434 | return -EINVAL; |
437 | 435 | ||
438 | usb_pcwd_keepalive(usb_pcwd_device); | 436 | usb_pcwd_keepalive(usb_pcwd_device); |
439 | /* Fall */ | 437 | /* Fall */ |
440 | } | 438 | } |
441 | 439 | ||
442 | case WDIOC_GETTIMEOUT: | 440 | case WDIOC_GETTIMEOUT: |
443 | return put_user(heartbeat, p); | 441 | return put_user(heartbeat, p); |
444 | 442 | ||
445 | case WDIOC_GETTIMELEFT: | 443 | case WDIOC_GETTIMELEFT: |
446 | { | 444 | { |
447 | int time_left; | 445 | int time_left; |
448 | 446 | ||
449 | if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left)) | 447 | if (usb_pcwd_get_timeleft(usb_pcwd_device, &time_left)) |
450 | return -EFAULT; | 448 | return -EFAULT; |
451 | 449 | ||
452 | return put_user(time_left, p); | 450 | return put_user(time_left, p); |
453 | } | 451 | } |
454 | 452 | ||
455 | default: | 453 | default: |
456 | return -ENOTTY; | 454 | return -ENOTTY; |
457 | } | 455 | } |
458 | } | 456 | } |
459 | 457 | ||
@@ -519,10 +517,8 @@ static int usb_pcwd_temperature_release(struct inode *inode, struct file *file) | |||
519 | 517 | ||
520 | static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 518 | static int usb_pcwd_notify_sys(struct notifier_block *this, unsigned long code, void *unused) |
521 | { | 519 | { |
522 | if (code==SYS_DOWN || code==SYS_HALT) { | 520 | if (code == SYS_DOWN || code == SYS_HALT) |
523 | /* Turn the WDT off */ | 521 | usb_pcwd_stop(usb_pcwd_device); /* Turn the WDT off */ |
524 | usb_pcwd_stop(usb_pcwd_device); | ||
525 | } | ||
526 | 522 | ||
527 | return NOTIFY_DONE; | 523 | return NOTIFY_DONE; |
528 | } | 524 | } |
@@ -535,7 +531,7 @@ static const struct file_operations usb_pcwd_fops = { | |||
535 | .owner = THIS_MODULE, | 531 | .owner = THIS_MODULE, |
536 | .llseek = no_llseek, | 532 | .llseek = no_llseek, |
537 | .write = usb_pcwd_write, | 533 | .write = usb_pcwd_write, |
538 | .ioctl = usb_pcwd_ioctl, | 534 | .unlocked_ioctl = usb_pcwd_ioctl, |
539 | .open = usb_pcwd_open, | 535 | .open = usb_pcwd_open, |
540 | .release = usb_pcwd_release, | 536 | .release = usb_pcwd_release, |
541 | }; | 537 | }; |
@@ -567,13 +563,13 @@ static struct notifier_block usb_pcwd_notifier = { | |||
567 | /** | 563 | /** |
568 | * usb_pcwd_delete | 564 | * usb_pcwd_delete |
569 | */ | 565 | */ |
570 | static inline void usb_pcwd_delete (struct usb_pcwd_private *usb_pcwd) | 566 | static inline void usb_pcwd_delete(struct usb_pcwd_private *usb_pcwd) |
571 | { | 567 | { |
572 | usb_free_urb(usb_pcwd->intr_urb); | 568 | usb_free_urb(usb_pcwd->intr_urb); |
573 | if (usb_pcwd->intr_buffer != NULL) | 569 | if (usb_pcwd->intr_buffer != NULL) |
574 | usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, | 570 | usb_buffer_free(usb_pcwd->udev, usb_pcwd->intr_size, |
575 | usb_pcwd->intr_buffer, usb_pcwd->intr_dma); | 571 | usb_pcwd->intr_buffer, usb_pcwd->intr_dma); |
576 | kfree (usb_pcwd); | 572 | kfree(usb_pcwd); |
577 | } | 573 | } |
578 | 574 | ||
579 | /** | 575 | /** |
@@ -626,7 +622,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
626 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); | 622 | maxp = usb_maxpacket(udev, pipe, usb_pipeout(pipe)); |
627 | 623 | ||
628 | /* allocate memory for our device and initialize it */ | 624 | /* allocate memory for our device and initialize it */ |
629 | usb_pcwd = kzalloc (sizeof(struct usb_pcwd_private), GFP_KERNEL); | 625 | usb_pcwd = kzalloc(sizeof(struct usb_pcwd_private), GFP_KERNEL); |
630 | if (usb_pcwd == NULL) { | 626 | if (usb_pcwd == NULL) { |
631 | printk(KERN_ERR PFX "Out of memory\n"); | 627 | printk(KERN_ERR PFX "Out of memory\n"); |
632 | goto error; | 628 | goto error; |
@@ -641,7 +637,8 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
641 | usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8); | 637 | usb_pcwd->intr_size = (le16_to_cpu(endpoint->wMaxPacketSize) > 8 ? le16_to_cpu(endpoint->wMaxPacketSize) : 8); |
642 | 638 | ||
643 | /* set up the memory buffer's */ | 639 | /* set up the memory buffer's */ |
644 | if (!(usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma))) { | 640 | usb_pcwd->intr_buffer = usb_buffer_alloc(udev, usb_pcwd->intr_size, GFP_ATOMIC, &usb_pcwd->intr_dma); |
641 | if (!usb_pcwd->intr_buffer) { | ||
645 | printk(KERN_ERR PFX "Out of memory\n"); | 642 | printk(KERN_ERR PFX "Out of memory\n"); |
646 | goto error; | 643 | goto error; |
647 | } | 644 | } |
@@ -675,11 +672,10 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
675 | 672 | ||
676 | /* Get the Firmware Version */ | 673 | /* Get the Firmware Version */ |
677 | got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); | 674 | got_fw_rev = usb_pcwd_send_command(usb_pcwd, CMD_GET_FIRMWARE_VERSION, &fw_rev_major, &fw_rev_minor); |
678 | if (got_fw_rev) { | 675 | if (got_fw_rev) |
679 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); | 676 | sprintf(fw_ver_str, "%u.%02u", fw_rev_major, fw_rev_minor); |
680 | } else { | 677 | else |
681 | sprintf(fw_ver_str, "<card no answer>"); | 678 | sprintf(fw_ver_str, "<card no answer>"); |
682 | } | ||
683 | 679 | ||
684 | printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n", | 680 | printk(KERN_INFO PFX "Found card (Firmware: %s) with temp option\n", |
685 | fw_ver_str); | 681 | fw_ver_str); |
@@ -725,7 +721,7 @@ static int usb_pcwd_probe(struct usb_interface *interface, const struct usb_devi | |||
725 | } | 721 | } |
726 | 722 | ||
727 | /* we can register the device now, as it is ready */ | 723 | /* we can register the device now, as it is ready */ |
728 | usb_set_intfdata (interface, usb_pcwd); | 724 | usb_set_intfdata(interface, usb_pcwd); |
729 | 725 | ||
730 | printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", | 726 | printk(KERN_INFO PFX "initialized. heartbeat=%d sec (nowayout=%d)\n", |
731 | heartbeat, nowayout); | 727 | heartbeat, nowayout); |
@@ -759,8 +755,8 @@ static void usb_pcwd_disconnect(struct usb_interface *interface) | |||
759 | /* prevent races with open() */ | 755 | /* prevent races with open() */ |
760 | mutex_lock(&disconnect_mutex); | 756 | mutex_lock(&disconnect_mutex); |
761 | 757 | ||
762 | usb_pcwd = usb_get_intfdata (interface); | 758 | usb_pcwd = usb_get_intfdata(interface); |
763 | usb_set_intfdata (interface, NULL); | 759 | usb_set_intfdata(interface, NULL); |
764 | 760 | ||
765 | mutex_lock(&usb_pcwd->mtx); | 761 | mutex_lock(&usb_pcwd->mtx); |
766 | 762 | ||
@@ -820,5 +816,5 @@ static void __exit usb_pcwd_exit(void) | |||
820 | } | 816 | } |
821 | 817 | ||
822 | 818 | ||
823 | module_init (usb_pcwd_init); | 819 | module_init(usb_pcwd_init); |
824 | module_exit (usb_pcwd_exit); | 820 | module_exit(usb_pcwd_exit); |
diff --git a/drivers/watchdog/pnx4008_wdt.c b/drivers/watchdog/pnx4008_wdt.c index f431a0427eaa..0ed84162437b 100644 --- a/drivers/watchdog/pnx4008_wdt.c +++ b/drivers/watchdog/pnx4008_wdt.c | |||
@@ -28,10 +28,9 @@ | |||
28 | #include <linux/platform_device.h> | 28 | #include <linux/platform_device.h> |
29 | #include <linux/clk.h> | 29 | #include <linux/clk.h> |
30 | #include <linux/spinlock.h> | 30 | #include <linux/spinlock.h> |
31 | 31 | #include <linux/uaccess.h> | |
32 | #include <linux/io.h> | ||
32 | #include <mach/hardware.h> | 33 | #include <mach/hardware.h> |
33 | #include <asm/uaccess.h> | ||
34 | #include <asm/io.h> | ||
35 | 34 | ||
36 | #define MODULE_NAME "PNX4008-WDT: " | 35 | #define MODULE_NAME "PNX4008-WDT: " |
37 | 36 | ||
@@ -144,9 +143,8 @@ static int pnx4008_wdt_open(struct inode *inode, struct file *file) | |||
144 | return nonseekable_open(inode, file); | 143 | return nonseekable_open(inode, file); |
145 | } | 144 | } |
146 | 145 | ||
147 | static ssize_t | 146 | static ssize_t pnx4008_wdt_write(struct file *file, const char *data, |
148 | pnx4008_wdt_write(struct file *file, const char *data, size_t len, | 147 | size_t len, loff_t *ppos) |
149 | loff_t * ppos) | ||
150 | { | 148 | { |
151 | if (len) { | 149 | if (len) { |
152 | if (!nowayout) { | 150 | if (!nowayout) { |
@@ -169,15 +167,14 @@ pnx4008_wdt_write(struct file *file, const char *data, size_t len, | |||
169 | return len; | 167 | return len; |
170 | } | 168 | } |
171 | 169 | ||
172 | static struct watchdog_info ident = { | 170 | static const struct watchdog_info ident = { |
173 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | | 171 | .options = WDIOF_CARDRESET | WDIOF_MAGICCLOSE | |
174 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 172 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
175 | .identity = "PNX4008 Watchdog", | 173 | .identity = "PNX4008 Watchdog", |
176 | }; | 174 | }; |
177 | 175 | ||
178 | static int | 176 | static long pnx4008_wdt_ioctl(struct inode *inode, struct file *file, |
179 | pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 177 | unsigned int cmd, unsigned long arg) |
180 | unsigned long arg) | ||
181 | { | 178 | { |
182 | int ret = -ENOTTY; | 179 | int ret = -ENOTTY; |
183 | int time; | 180 | int time; |
@@ -196,6 +193,11 @@ pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
196 | ret = put_user(boot_status, (int *)arg); | 193 | ret = put_user(boot_status, (int *)arg); |
197 | break; | 194 | break; |
198 | 195 | ||
196 | case WDIOC_KEEPALIVE: | ||
197 | wdt_enable(); | ||
198 | ret = 0; | ||
199 | break; | ||
200 | |||
199 | case WDIOC_SETTIMEOUT: | 201 | case WDIOC_SETTIMEOUT: |
200 | ret = get_user(time, (int *)arg); | 202 | ret = get_user(time, (int *)arg); |
201 | if (ret) | 203 | if (ret) |
@@ -213,11 +215,6 @@ pnx4008_wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
213 | case WDIOC_GETTIMEOUT: | 215 | case WDIOC_GETTIMEOUT: |
214 | ret = put_user(heartbeat, (int *)arg); | 216 | ret = put_user(heartbeat, (int *)arg); |
215 | break; | 217 | break; |
216 | |||
217 | case WDIOC_KEEPALIVE: | ||
218 | wdt_enable(); | ||
219 | ret = 0; | ||
220 | break; | ||
221 | } | 218 | } |
222 | return ret; | 219 | return ret; |
223 | } | 220 | } |
@@ -238,7 +235,7 @@ static const struct file_operations pnx4008_wdt_fops = { | |||
238 | .owner = THIS_MODULE, | 235 | .owner = THIS_MODULE, |
239 | .llseek = no_llseek, | 236 | .llseek = no_llseek, |
240 | .write = pnx4008_wdt_write, | 237 | .write = pnx4008_wdt_write, |
241 | .ioctl = pnx4008_wdt_ioctl, | 238 | .unlocked_ioctl = pnx4008_wdt_ioctl, |
242 | .open = pnx4008_wdt_open, | 239 | .open = pnx4008_wdt_open, |
243 | .release = pnx4008_wdt_release, | 240 | .release = pnx4008_wdt_release, |
244 | }; | 241 | }; |
diff --git a/drivers/watchdog/rm9k_wdt.c b/drivers/watchdog/rm9k_wdt.c index 5c921e471564..f1ae3729a19e 100644 --- a/drivers/watchdog/rm9k_wdt.c +++ b/drivers/watchdog/rm9k_wdt.c | |||
@@ -29,10 +29,10 @@ | |||
29 | #include <linux/notifier.h> | 29 | #include <linux/notifier.h> |
30 | #include <linux/miscdevice.h> | 30 | #include <linux/miscdevice.h> |
31 | #include <linux/watchdog.h> | 31 | #include <linux/watchdog.h> |
32 | #include <asm/io.h> | 32 | #include <linux/io.h> |
33 | #include <linux/uaccess.h> | ||
33 | #include <asm/atomic.h> | 34 | #include <asm/atomic.h> |
34 | #include <asm/processor.h> | 35 | #include <asm/processor.h> |
35 | #include <asm/uaccess.h> | ||
36 | #include <asm/system.h> | 36 | #include <asm/system.h> |
37 | #include <asm/rm9k-ocd.h> | 37 | #include <asm/rm9k-ocd.h> |
38 | 38 | ||
@@ -53,10 +53,12 @@ static void wdt_gpi_stop(void); | |||
53 | static void wdt_gpi_set_timeout(unsigned int); | 53 | static void wdt_gpi_set_timeout(unsigned int); |
54 | static int wdt_gpi_open(struct inode *, struct file *); | 54 | static int wdt_gpi_open(struct inode *, struct file *); |
55 | static int wdt_gpi_release(struct inode *, struct file *); | 55 | static int wdt_gpi_release(struct inode *, struct file *); |
56 | static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, loff_t *); | 56 | static ssize_t wdt_gpi_write(struct file *, const char __user *, size_t, |
57 | loff_t *); | ||
57 | static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); | 58 | static long wdt_gpi_ioctl(struct file *, unsigned int, unsigned long); |
58 | static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); | 59 | static int wdt_gpi_notify(struct notifier_block *, unsigned long, void *); |
59 | static const struct resource *wdt_gpi_get_resource(struct platform_device *, const char *, unsigned int); | 60 | static const struct resource *wdt_gpi_get_resource(struct platform_device *, |
61 | const char *, unsigned int); | ||
60 | static int __init wdt_gpi_probe(struct device *); | 62 | static int __init wdt_gpi_probe(struct device *); |
61 | static int __exit wdt_gpi_remove(struct device *); | 63 | static int __exit wdt_gpi_remove(struct device *); |
62 | 64 | ||
@@ -68,7 +70,7 @@ static int locked; | |||
68 | 70 | ||
69 | 71 | ||
70 | /* These are set from device resources */ | 72 | /* These are set from device resources */ |
71 | static void __iomem * wd_regs; | 73 | static void __iomem *wd_regs; |
72 | static unsigned int wd_irq, wd_ctr; | 74 | static unsigned int wd_irq, wd_ctr; |
73 | 75 | ||
74 | 76 | ||
@@ -216,7 +218,8 @@ static int wdt_gpi_release(struct inode *inode, struct file *file) | |||
216 | if (expect_close) { | 218 | if (expect_close) { |
217 | wdt_gpi_stop(); | 219 | wdt_gpi_stop(); |
218 | free_irq(wd_irq, &miscdev); | 220 | free_irq(wd_irq, &miscdev); |
219 | printk(KERN_INFO "%s: watchdog stopped\n", wdt_gpi_name); | 221 | printk(KERN_INFO "%s: watchdog stopped\n", |
222 | wdt_gpi_name); | ||
220 | } else { | 223 | } else { |
221 | printk(KERN_CRIT "%s: unexpected close() -" | 224 | printk(KERN_CRIT "%s: unexpected close() -" |
222 | " watchdog left running\n", | 225 | " watchdog left running\n", |
@@ -231,8 +234,8 @@ static int wdt_gpi_release(struct inode *inode, struct file *file) | |||
231 | return 0; | 234 | return 0; |
232 | } | 235 | } |
233 | 236 | ||
234 | static ssize_t | 237 | static ssize_t wdt_gpi_write(struct file *f, const char __user *d, size_t s, |
235 | wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) | 238 | loff_t *o) |
236 | { | 239 | { |
237 | char val; | 240 | char val; |
238 | 241 | ||
@@ -241,8 +244,7 @@ wdt_gpi_write(struct file *f, const char __user *d, size_t s, loff_t *o) | |||
241 | return s ? 1 : 0; | 244 | return s ? 1 : 0; |
242 | } | 245 | } |
243 | 246 | ||
244 | static long | 247 | static long wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) |
245 | wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | ||
246 | { | 248 | { |
247 | long res = -ENOTTY; | 249 | long res = -ENOTTY; |
248 | const long size = _IOC_SIZE(cmd); | 250 | const long size = _IOC_SIZE(cmd); |
@@ -271,7 +273,8 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
271 | case WDIOC_GETSUPPORT: | 273 | case WDIOC_GETSUPPORT: |
272 | wdinfo.options = nowayout ? | 274 | wdinfo.options = nowayout ? |
273 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING : | 275 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING : |
274 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | WDIOF_MAGICCLOSE; | 276 | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING | |
277 | WDIOF_MAGICCLOSE; | ||
275 | res = __copy_to_user(argp, &wdinfo, size) ? -EFAULT : size; | 278 | res = __copy_to_user(argp, &wdinfo, size) ? -EFAULT : size; |
276 | break; | 279 | break; |
277 | 280 | ||
@@ -322,8 +325,8 @@ wdt_gpi_ioctl(struct file *f, unsigned int cmd, unsigned long arg) | |||
322 | 325 | ||
323 | 326 | ||
324 | /* Shutdown notifier */ | 327 | /* Shutdown notifier */ |
325 | static int | 328 | static int wdt_gpi_notify(struct notifier_block *this, unsigned long code, |
326 | wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) | 329 | void *unused) |
327 | { | 330 | { |
328 | if (code == SYS_DOWN || code == SYS_HALT) | 331 | if (code == SYS_DOWN || code == SYS_HALT) |
329 | wdt_gpi_stop(); | 332 | wdt_gpi_stop(); |
@@ -333,9 +336,8 @@ wdt_gpi_notify(struct notifier_block *this, unsigned long code, void *unused) | |||
333 | 336 | ||
334 | 337 | ||
335 | /* Init & exit procedures */ | 338 | /* Init & exit procedures */ |
336 | static const struct resource * | 339 | static const struct resource *wdt_gpi_get_resource(struct platform_device *pdv, |
337 | wdt_gpi_get_resource(struct platform_device *pdv, const char *name, | 340 | const char *name, unsigned int type) |
338 | unsigned int type) | ||
339 | { | 341 | { |
340 | char buf[80]; | 342 | char buf[80]; |
341 | if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) | 343 | if (snprintf(buf, sizeof buf, "%s_0", name) >= sizeof buf) |
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c index f1fe800658f4..3da2b90d2fe6 100644 --- a/drivers/watchdog/s3c2410_wdt.c +++ b/drivers/watchdog/s3c2410_wdt.c | |||
@@ -119,17 +119,6 @@ static void __s3c2410wdt_stop(void) | |||
119 | { | 119 | { |
120 | unsigned long wtcon; | 120 | unsigned long wtcon; |
121 | 121 | ||
122 | spin_lock(&wdt_lock); | ||
123 | wtcon = readl(wdt_base + S3C2410_WTCON); | ||
124 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); | ||
125 | writel(wtcon, wdt_base + S3C2410_WTCON); | ||
126 | spin_unlock(&wdt_lock); | ||
127 | } | ||
128 | |||
129 | static void __s3c2410wdt_stop(void) | ||
130 | { | ||
131 | unsigned long wtcon; | ||
132 | |||
133 | wtcon = readl(wdt_base + S3C2410_WTCON); | 122 | wtcon = readl(wdt_base + S3C2410_WTCON); |
134 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); | 123 | wtcon &= ~(S3C2410_WTCON_ENABLE | S3C2410_WTCON_RSTEN); |
135 | writel(wtcon, wdt_base + S3C2410_WTCON); | 124 | writel(wtcon, wdt_base + S3C2410_WTCON); |
@@ -305,8 +294,6 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd, | |||
305 | int new_margin; | 294 | int new_margin; |
306 | 295 | ||
307 | switch (cmd) { | 296 | switch (cmd) { |
308 | default: | ||
309 | return -ENOTTY; | ||
310 | case WDIOC_GETSUPPORT: | 297 | case WDIOC_GETSUPPORT: |
311 | return copy_to_user(argp, &s3c2410_wdt_ident, | 298 | return copy_to_user(argp, &s3c2410_wdt_ident, |
312 | sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0; | 299 | sizeof(s3c2410_wdt_ident)) ? -EFAULT : 0; |
@@ -325,6 +312,8 @@ static long s3c2410wdt_ioctl(struct file *file, unsigned int cmd, | |||
325 | return put_user(tmr_margin, p); | 312 | return put_user(tmr_margin, p); |
326 | case WDIOC_GETTIMEOUT: | 313 | case WDIOC_GETTIMEOUT: |
327 | return put_user(tmr_margin, p); | 314 | return put_user(tmr_margin, p); |
315 | default: | ||
316 | return -ENOTTY; | ||
328 | } | 317 | } |
329 | } | 318 | } |
330 | 319 | ||
diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c index 97d9da758dcc..31a48437dc3d 100644 --- a/drivers/watchdog/sa1100_wdt.c +++ b/drivers/watchdog/sa1100_wdt.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/watchdog.h> | 26 | #include <linux/watchdog.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/uaccess.h> | ||
29 | 30 | ||
30 | #ifdef CONFIG_ARCH_PXA | 31 | #ifdef CONFIG_ARCH_PXA |
31 | #include <mach/pxa-regs.h> | 32 | #include <mach/pxa-regs.h> |
@@ -33,7 +34,6 @@ | |||
33 | 34 | ||
34 | #include <mach/reset.h> | 35 | #include <mach/reset.h> |
35 | #include <mach/hardware.h> | 36 | #include <mach/hardware.h> |
36 | #include <asm/uaccess.h> | ||
37 | 37 | ||
38 | #define OSCR_FREQ CLOCK_TICK_RATE | 38 | #define OSCR_FREQ CLOCK_TICK_RATE |
39 | 39 | ||
@@ -46,7 +46,7 @@ static int boot_status; | |||
46 | */ | 46 | */ |
47 | static int sa1100dog_open(struct inode *inode, struct file *file) | 47 | static int sa1100dog_open(struct inode *inode, struct file *file) |
48 | { | 48 | { |
49 | if (test_and_set_bit(1,&sa1100wdt_users)) | 49 | if (test_and_set_bit(1, &sa1100wdt_users)) |
50 | return -EBUSY; | 50 | return -EBUSY; |
51 | 51 | ||
52 | /* Activate SA1100 Watchdog timer */ | 52 | /* Activate SA1100 Watchdog timer */ |
@@ -67,28 +67,27 @@ static int sa1100dog_open(struct inode *inode, struct file *file) | |||
67 | static int sa1100dog_release(struct inode *inode, struct file *file) | 67 | static int sa1100dog_release(struct inode *inode, struct file *file) |
68 | { | 68 | { |
69 | printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); | 69 | printk(KERN_CRIT "WATCHDOG: Device closed - timer will not stop\n"); |
70 | |||
71 | clear_bit(1, &sa1100wdt_users); | 70 | clear_bit(1, &sa1100wdt_users); |
72 | |||
73 | return 0; | 71 | return 0; |
74 | } | 72 | } |
75 | 73 | ||
76 | static ssize_t sa1100dog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) | 74 | static ssize_t sa1100dog_write(struct file *file, const char __user *data, |
75 | size_t len, loff_t *ppos) | ||
77 | { | 76 | { |
78 | if (len) | 77 | if (len) |
79 | /* Refresh OSMR3 timer. */ | 78 | /* Refresh OSMR3 timer. */ |
80 | OSMR3 = OSCR + pre_margin; | 79 | OSMR3 = OSCR + pre_margin; |
81 | |||
82 | return len; | 80 | return len; |
83 | } | 81 | } |
84 | 82 | ||
85 | static struct watchdog_info ident = { | 83 | static const struct watchdog_info ident = { |
86 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 84 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT |
85 | | WDIOF_KEEPALIVEPING, | ||
87 | .identity = "SA1100/PXA255 Watchdog", | 86 | .identity = "SA1100/PXA255 Watchdog", |
88 | }; | 87 | }; |
89 | 88 | ||
90 | static int sa1100dog_ioctl(struct inode *inode, struct file *file, | 89 | static long sa1100dog_ioctl(struct file *file, unsigned int cmd, |
91 | unsigned int cmd, unsigned long arg) | 90 | unsigned long arg) |
92 | { | 91 | { |
93 | int ret = -ENOTTY; | 92 | int ret = -ENOTTY; |
94 | int time; | 93 | int time; |
@@ -109,6 +108,11 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, | |||
109 | ret = put_user(boot_status, p); | 108 | ret = put_user(boot_status, p); |
110 | break; | 109 | break; |
111 | 110 | ||
111 | case WDIOC_KEEPALIVE: | ||
112 | OSMR3 = OSCR + pre_margin; | ||
113 | ret = 0; | ||
114 | break; | ||
115 | |||
112 | case WDIOC_SETTIMEOUT: | 116 | case WDIOC_SETTIMEOUT: |
113 | ret = get_user(time, p); | 117 | ret = get_user(time, p); |
114 | if (ret) | 118 | if (ret) |
@@ -126,27 +130,20 @@ static int sa1100dog_ioctl(struct inode *inode, struct file *file, | |||
126 | case WDIOC_GETTIMEOUT: | 130 | case WDIOC_GETTIMEOUT: |
127 | ret = put_user(pre_margin / OSCR_FREQ, p); | 131 | ret = put_user(pre_margin / OSCR_FREQ, p); |
128 | break; | 132 | break; |
129 | |||
130 | case WDIOC_KEEPALIVE: | ||
131 | OSMR3 = OSCR + pre_margin; | ||
132 | ret = 0; | ||
133 | break; | ||
134 | } | 133 | } |
135 | return ret; | 134 | return ret; |
136 | } | 135 | } |
137 | 136 | ||
138 | static const struct file_operations sa1100dog_fops = | 137 | static const struct file_operations sa1100dog_fops = { |
139 | { | ||
140 | .owner = THIS_MODULE, | 138 | .owner = THIS_MODULE, |
141 | .llseek = no_llseek, | 139 | .llseek = no_llseek, |
142 | .write = sa1100dog_write, | 140 | .write = sa1100dog_write, |
143 | .ioctl = sa1100dog_ioctl, | 141 | .unlocked_ioctl = sa1100dog_ioctl, |
144 | .open = sa1100dog_open, | 142 | .open = sa1100dog_open, |
145 | .release = sa1100dog_release, | 143 | .release = sa1100dog_release, |
146 | }; | 144 | }; |
147 | 145 | ||
148 | static struct miscdevice sa1100dog_miscdev = | 146 | static struct miscdevice sa1100dog_miscdev = { |
149 | { | ||
150 | .minor = WATCHDOG_MINOR, | 147 | .minor = WATCHDOG_MINOR, |
151 | .name = "watchdog", | 148 | .name = "watchdog", |
152 | .fops = &sa1100dog_fops, | 149 | .fops = &sa1100dog_fops, |
@@ -169,8 +166,9 @@ static int __init sa1100dog_init(void) | |||
169 | 166 | ||
170 | ret = misc_register(&sa1100dog_miscdev); | 167 | ret = misc_register(&sa1100dog_miscdev); |
171 | if (ret == 0) | 168 | if (ret == 0) |
172 | printk("SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", | 169 | printk(KERN_INFO |
173 | margin); | 170 | "SA1100/PXA2xx Watchdog Timer: timer margin %d sec\n", |
171 | margin); | ||
174 | return ret; | 172 | return ret; |
175 | } | 173 | } |
176 | 174 | ||
diff --git a/drivers/watchdog/sb_wdog.c b/drivers/watchdog/sb_wdog.c index b94431433695..27e526a07c9a 100644 --- a/drivers/watchdog/sb_wdog.c +++ b/drivers/watchdog/sb_wdog.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <asm/sibyte/sb1250_int.h> | 57 | #include <asm/sibyte/sb1250_int.h> |
58 | #include <asm/sibyte/sb1250_scd.h> | 58 | #include <asm/sibyte/sb1250_scd.h> |
59 | 59 | ||
60 | static DEFINE_SPINLOCK(sbwd_lock); | ||
60 | 61 | ||
61 | /* | 62 | /* |
62 | * set the initial count value of a timer | 63 | * set the initial count value of a timer |
@@ -65,8 +66,10 @@ | |||
65 | */ | 66 | */ |
66 | void sbwdog_set(char __iomem *wdog, unsigned long t) | 67 | void sbwdog_set(char __iomem *wdog, unsigned long t) |
67 | { | 68 | { |
69 | spin_lock(&sbwd_lock); | ||
68 | __raw_writeb(0, wdog - 0x10); | 70 | __raw_writeb(0, wdog - 0x10); |
69 | __raw_writeq(t & 0x7fffffUL, wdog); | 71 | __raw_writeq(t & 0x7fffffUL, wdog); |
72 | spin_unlock(&sbwd_lock); | ||
70 | } | 73 | } |
71 | 74 | ||
72 | /* | 75 | /* |
@@ -77,7 +80,9 @@ void sbwdog_set(char __iomem *wdog, unsigned long t) | |||
77 | */ | 80 | */ |
78 | void sbwdog_pet(char __iomem *wdog) | 81 | void sbwdog_pet(char __iomem *wdog) |
79 | { | 82 | { |
83 | spin_lock(&sbwd_lock); | ||
80 | __raw_writeb(__raw_readb(wdog) | 1, wdog); | 84 | __raw_writeb(__raw_readb(wdog) | 1, wdog); |
85 | spin_unlock(&sbwd_lock); | ||
81 | } | 86 | } |
82 | 87 | ||
83 | static unsigned long sbwdog_gate; /* keeps it to one thread only */ | 88 | static unsigned long sbwdog_gate; /* keeps it to one thread only */ |
@@ -86,8 +91,9 @@ static char __iomem *user_dog = (char __iomem *)(IO_BASE + (A_SCD_WDOG_CFG_1)); | |||
86 | static unsigned long timeout = 0x7fffffUL; /* useconds: 8.3ish secs. */ | 91 | static unsigned long timeout = 0x7fffffUL; /* useconds: 8.3ish secs. */ |
87 | static int expect_close; | 92 | static int expect_close; |
88 | 93 | ||
89 | static struct watchdog_info ident = { | 94 | static const struct watchdog_info ident = { |
90 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | 95 | .options = WDIOF_CARDRESET | WDIOF_SETTIMEOUT | |
96 | WDIOF_KEEPALIVEPING, | ||
91 | .identity = "SiByte Watchdog", | 97 | .identity = "SiByte Watchdog", |
92 | }; | 98 | }; |
93 | 99 | ||
@@ -97,9 +103,8 @@ static struct watchdog_info ident = { | |||
97 | static int sbwdog_open(struct inode *inode, struct file *file) | 103 | static int sbwdog_open(struct inode *inode, struct file *file) |
98 | { | 104 | { |
99 | nonseekable_open(inode, file); | 105 | nonseekable_open(inode, file); |
100 | if (test_and_set_bit(0, &sbwdog_gate)) { | 106 | if (test_and_set_bit(0, &sbwdog_gate)) |
101 | return -EBUSY; | 107 | return -EBUSY; |
102 | } | ||
103 | __module_get(THIS_MODULE); | 108 | __module_get(THIS_MODULE); |
104 | 109 | ||
105 | /* | 110 | /* |
@@ -120,8 +125,9 @@ static int sbwdog_release(struct inode *inode, struct file *file) | |||
120 | __raw_writeb(0, user_dog); | 125 | __raw_writeb(0, user_dog); |
121 | module_put(THIS_MODULE); | 126 | module_put(THIS_MODULE); |
122 | } else { | 127 | } else { |
123 | printk(KERN_CRIT "%s: Unexpected close, not stopping watchdog!\n", | 128 | printk(KERN_CRIT |
124 | ident.identity); | 129 | "%s: Unexpected close, not stopping watchdog!\n", |
130 | ident.identity); | ||
125 | sbwdog_pet(user_dog); | 131 | sbwdog_pet(user_dog); |
126 | } | 132 | } |
127 | clear_bit(0, &sbwdog_gate); | 133 | clear_bit(0, &sbwdog_gate); |
@@ -147,12 +153,10 @@ static ssize_t sbwdog_write(struct file *file, const char __user *data, | |||
147 | for (i = 0; i != len; i++) { | 153 | for (i = 0; i != len; i++) { |
148 | char c; | 154 | char c; |
149 | 155 | ||
150 | if (get_user(c, data + i)) { | 156 | if (get_user(c, data + i)) |
151 | return -EFAULT; | 157 | return -EFAULT; |
152 | } | 158 | if (c == 'V') |
153 | if (c == 'V') { | ||
154 | expect_close = 42; | 159 | expect_close = 42; |
155 | } | ||
156 | } | 160 | } |
157 | sbwdog_pet(user_dog); | 161 | sbwdog_pet(user_dog); |
158 | } | 162 | } |
@@ -160,8 +164,8 @@ static ssize_t sbwdog_write(struct file *file, const char __user *data, | |||
160 | return len; | 164 | return len; |
161 | } | 165 | } |
162 | 166 | ||
163 | static int sbwdog_ioctl(struct inode *inode, struct file *file, | 167 | static long sbwdog_ioctl(struct file *file, unsigned int cmd, |
164 | unsigned int cmd, unsigned long arg) | 168 | unsigned long arg) |
165 | { | 169 | { |
166 | int ret = -ENOTTY; | 170 | int ret = -ENOTTY; |
167 | unsigned long time; | 171 | unsigned long time; |
@@ -178,11 +182,15 @@ static int sbwdog_ioctl(struct inode *inode, struct file *file, | |||
178 | ret = put_user(0, p); | 182 | ret = put_user(0, p); |
179 | break; | 183 | break; |
180 | 184 | ||
185 | case WDIOC_KEEPALIVE: | ||
186 | sbwdog_pet(user_dog); | ||
187 | ret = 0; | ||
188 | break; | ||
189 | |||
181 | case WDIOC_SETTIMEOUT: | 190 | case WDIOC_SETTIMEOUT: |
182 | ret = get_user(time, p); | 191 | ret = get_user(time, p); |
183 | if (ret) { | 192 | if (ret) |
184 | break; | 193 | break; |
185 | } | ||
186 | 194 | ||
187 | time *= 1000000; | 195 | time *= 1000000; |
188 | if (time > 0x7fffffUL) { | 196 | if (time > 0x7fffffUL) { |
@@ -200,11 +208,6 @@ static int sbwdog_ioctl(struct inode *inode, struct file *file, | |||
200 | */ | 208 | */ |
201 | ret = put_user(__raw_readq(user_dog - 8) / 1000000, p); | 209 | ret = put_user(__raw_readq(user_dog - 8) / 1000000, p); |
202 | break; | 210 | break; |
203 | |||
204 | case WDIOC_KEEPALIVE: | ||
205 | sbwdog_pet(user_dog); | ||
206 | ret = 0; | ||
207 | break; | ||
208 | } | 211 | } |
209 | return ret; | 212 | return ret; |
210 | } | 213 | } |
@@ -212,8 +215,8 @@ static int sbwdog_ioctl(struct inode *inode, struct file *file, | |||
212 | /* | 215 | /* |
213 | * Notifier for system down | 216 | * Notifier for system down |
214 | */ | 217 | */ |
215 | static int | 218 | static int sbwdog_notify_sys(struct notifier_block *this, unsigned long code, |
216 | sbwdog_notify_sys(struct notifier_block *this, unsigned long code, void *erf) | 219 | void *erf) |
217 | { | 220 | { |
218 | if (code == SYS_DOWN || code == SYS_HALT) { | 221 | if (code == SYS_DOWN || code == SYS_HALT) { |
219 | /* | 222 | /* |
@@ -226,18 +229,16 @@ sbwdog_notify_sys(struct notifier_block *this, unsigned long code, void *erf) | |||
226 | return NOTIFY_DONE; | 229 | return NOTIFY_DONE; |
227 | } | 230 | } |
228 | 231 | ||
229 | static const struct file_operations sbwdog_fops = | 232 | static const struct file_operations sbwdog_fops = { |
230 | { | ||
231 | .owner = THIS_MODULE, | 233 | .owner = THIS_MODULE, |
232 | .llseek = no_llseek, | 234 | .llseek = no_llseek, |
233 | .write = sbwdog_write, | 235 | .write = sbwdog_write, |
234 | .ioctl = sbwdog_ioctl, | 236 | .unlocked_ioctl = sbwdog_ioctl, |
235 | .open = sbwdog_open, | 237 | .open = sbwdog_open, |
236 | .release = sbwdog_release, | 238 | .release = sbwdog_release, |
237 | }; | 239 | }; |
238 | 240 | ||
239 | static struct miscdevice sbwdog_miscdev = | 241 | static struct miscdevice sbwdog_miscdev = { |
240 | { | ||
241 | .minor = WATCHDOG_MINOR, | 242 | .minor = WATCHDOG_MINOR, |
242 | .name = "watchdog", | 243 | .name = "watchdog", |
243 | .fops = &sbwdog_fops, | 244 | .fops = &sbwdog_fops, |
@@ -267,13 +268,12 @@ irqreturn_t sbwdog_interrupt(int irq, void *addr) | |||
267 | /* | 268 | /* |
268 | * if it's the second watchdog timer, it's for those users | 269 | * if it's the second watchdog timer, it's for those users |
269 | */ | 270 | */ |
270 | if (wd_cfg_reg == user_dog) { | 271 | if (wd_cfg_reg == user_dog) |
271 | printk(KERN_CRIT | 272 | printk(KERN_CRIT |
272 | "%s in danger of initiating system reset in %ld.%01ld seconds\n", | 273 | "%s in danger of initiating system reset in %ld.%01ld seconds\n", |
273 | ident.identity, wd_init / 1000000, (wd_init / 100000) % 10); | 274 | ident.identity, wd_init / 1000000, (wd_init / 100000) % 10); |
274 | } else { | 275 | else |
275 | cfg |= 1; | 276 | cfg |= 1; |
276 | } | ||
277 | 277 | ||
278 | __raw_writeb(cfg, wd_cfg_reg); | 278 | __raw_writeb(cfg, wd_cfg_reg); |
279 | 279 | ||
@@ -289,28 +289,31 @@ static int __init sbwdog_init(void) | |||
289 | */ | 289 | */ |
290 | ret = register_reboot_notifier(&sbwdog_notifier); | 290 | ret = register_reboot_notifier(&sbwdog_notifier); |
291 | if (ret) { | 291 | if (ret) { |
292 | printk (KERN_ERR "%s: cannot register reboot notifier (err=%d)\n", | 292 | printk(KERN_ERR |
293 | ident.identity, ret); | 293 | "%s: cannot register reboot notifier (err=%d)\n", |
294 | ident.identity, ret); | ||
294 | return ret; | 295 | return ret; |
295 | } | 296 | } |
296 | 297 | ||
297 | /* | 298 | /* |
298 | * get the resources | 299 | * get the resources |
299 | */ | 300 | */ |
300 | ret = misc_register(&sbwdog_miscdev); | ||
301 | if (ret == 0) { | ||
302 | printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", ident.identity, | ||
303 | timeout / 1000000, (timeout / 100000) % 10); | ||
304 | } | ||
305 | 301 | ||
306 | ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, | 302 | ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, |
307 | ident.identity, (void *)user_dog); | 303 | ident.identity, (void *)user_dog); |
308 | if (ret) { | 304 | if (ret) { |
309 | printk(KERN_ERR "%s: failed to request irq 1 - %d\n", ident.identity, | 305 | printk(KERN_ERR "%s: failed to request irq 1 - %d\n", |
310 | ret); | 306 | ident.identity, ret); |
311 | misc_deregister(&sbwdog_miscdev); | 307 | return ret; |
312 | } | 308 | } |
313 | 309 | ||
310 | ret = misc_register(&sbwdog_miscdev); | ||
311 | if (ret == 0) { | ||
312 | printk(KERN_INFO "%s: timeout is %ld.%ld secs\n", | ||
313 | ident.identity, | ||
314 | timeout / 1000000, (timeout / 100000) % 10); | ||
315 | } else | ||
316 | free_irq(1, (void *)user_dog); | ||
314 | return ret; | 317 | return ret; |
315 | } | 318 | } |
316 | 319 | ||
@@ -327,7 +330,7 @@ MODULE_DESCRIPTION("SiByte Watchdog"); | |||
327 | 330 | ||
328 | module_param(timeout, ulong, 0); | 331 | module_param(timeout, ulong, 0); |
329 | MODULE_PARM_DESC(timeout, | 332 | MODULE_PARM_DESC(timeout, |
330 | "Watchdog timeout in microseconds (max/default 8388607 or 8.3ish secs)"); | 333 | "Watchdog timeout in microseconds (max/default 8388607 or 8.3ish secs)"); |
331 | 334 | ||
332 | MODULE_LICENSE("GPL"); | 335 | MODULE_LICENSE("GPL"); |
333 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 336 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
@@ -336,16 +339,15 @@ MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | |||
336 | * example code that can be put in a platform code area to utilize the | 339 | * example code that can be put in a platform code area to utilize the |
337 | * first watchdog timer for the kernels own purpose. | 340 | * first watchdog timer for the kernels own purpose. |
338 | 341 | ||
339 | void | 342 | void platform_wd_setup(void) |
340 | platform_wd_setup(void) | ||
341 | { | 343 | { |
342 | int ret; | 344 | int ret; |
343 | 345 | ||
344 | ret = request_irq(0, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, | 346 | ret = request_irq(1, sbwdog_interrupt, IRQF_DISABLED | IRQF_SHARED, |
345 | "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0)); | 347 | "Kernel Watchdog", IOADDR(A_SCD_WDOG_CFG_0)); |
346 | if (ret) { | 348 | if (ret) { |
347 | printk(KERN_CRIT "Watchdog IRQ zero(0) failed to be requested - %d\n", | 349 | printk(KERN_CRIT |
348 | ret); | 350 | "Watchdog IRQ zero(0) failed to be requested - %d\n", ret); |
349 | } | 351 | } |
350 | } | 352 | } |
351 | 353 | ||
diff --git a/drivers/watchdog/sbc60xxwdt.c b/drivers/watchdog/sbc60xxwdt.c index ef76f01625e7..3266daaaecf8 100644 --- a/drivers/watchdog/sbc60xxwdt.c +++ b/drivers/watchdog/sbc60xxwdt.c | |||
@@ -16,19 +16,23 @@ | |||
16 | * | 16 | * |
17 | * 12/4 - 2000 [Initial revision] | 17 | * 12/4 - 2000 [Initial revision] |
18 | * 25/4 - 2000 Added /dev/watchdog support | 18 | * 25/4 - 2000 Added /dev/watchdog support |
19 | * 09/5 - 2001 [smj@oro.net] fixed fop_write to "return 1" on success | 19 | * 09/5 - 2001 [smj@oro.net] fixed fop_write to "return 1" |
20 | * on success | ||
20 | * 12/4 - 2002 [rob@osinvestor.com] eliminate fop_read | 21 | * 12/4 - 2002 [rob@osinvestor.com] eliminate fop_read |
21 | * fix possible wdt_is_open race | 22 | * fix possible wdt_is_open race |
22 | * add CONFIG_WATCHDOG_NOWAYOUT support | 23 | * add CONFIG_WATCHDOG_NOWAYOUT support |
23 | * remove lock_kernel/unlock_kernel pairs | 24 | * remove lock_kernel/unlock_kernel pairs |
24 | * added KERN_* to printk's | 25 | * added KERN_* to printk's |
25 | * got rid of extraneous comments | 26 | * got rid of extraneous comments |
26 | * changed watchdog_info to correctly reflect what the driver offers | 27 | * changed watchdog_info to correctly reflect what |
27 | * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT, | 28 | * the driver offers |
28 | * WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls | 29 | * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, |
30 | * WDIOC_SETTIMEOUT, WDIOC_GETTIMEOUT, and | ||
31 | * WDIOC_SETOPTIONS ioctls | ||
29 | * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces | 32 | * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces |
30 | * use module_param | 33 | * use module_param |
31 | * made timeout (the emulated heartbeat) a module_param | 34 | * made timeout (the emulated heartbeat) a |
35 | * module_param | ||
32 | * made the keepalive ping an internal subroutine | 36 | * made the keepalive ping an internal subroutine |
33 | * made wdt_stop and wdt_start module params | 37 | * made wdt_stop and wdt_start module params |
34 | * added extra printk's for startup problems | 38 | * added extra printk's for startup problems |
@@ -56,9 +60,9 @@ | |||
56 | #include <linux/notifier.h> | 60 | #include <linux/notifier.h> |
57 | #include <linux/reboot.h> | 61 | #include <linux/reboot.h> |
58 | #include <linux/init.h> | 62 | #include <linux/init.h> |
63 | #include <linux/io.h> | ||
64 | #include <linux/uaccess.h> | ||
59 | 65 | ||
60 | #include <asm/io.h> | ||
61 | #include <asm/uaccess.h> | ||
62 | #include <asm/system.h> | 66 | #include <asm/system.h> |
63 | 67 | ||
64 | #define OUR_NAME "sbc60xxwdt" | 68 | #define OUR_NAME "sbc60xxwdt" |
@@ -94,13 +98,18 @@ MODULE_PARM_DESC(wdt_start, "SBC60xx WDT 'start' io port (default 0x443)"); | |||
94 | */ | 98 | */ |
95 | 99 | ||
96 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ | 100 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ |
97 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ | 101 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds, multiplied by HZ to |
102 | get seconds to wait for a ping */ | ||
98 | module_param(timeout, int, 0); | 103 | module_param(timeout, int, 0); |
99 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 104 | MODULE_PARM_DESC(timeout, |
105 | "Watchdog timeout in seconds. (1<=timeout<=3600, default=" | ||
106 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
100 | 107 | ||
101 | static int nowayout = WATCHDOG_NOWAYOUT; | 108 | static int nowayout = WATCHDOG_NOWAYOUT; |
102 | module_param(nowayout, int, 0); | 109 | module_param(nowayout, int, 0); |
103 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 110 | MODULE_PARM_DESC(nowayout, |
111 | "Watchdog cannot be stopped once started (default=" | ||
112 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
104 | 113 | ||
105 | static void wdt_timer_ping(unsigned long); | 114 | static void wdt_timer_ping(unsigned long); |
106 | static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); | 115 | static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); |
@@ -117,15 +126,14 @@ static void wdt_timer_ping(unsigned long data) | |||
117 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL | 126 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL |
118 | * we agree to ping the WDT | 127 | * we agree to ping the WDT |
119 | */ | 128 | */ |
120 | if(time_before(jiffies, next_heartbeat)) | 129 | if (time_before(jiffies, next_heartbeat)) { |
121 | { | ||
122 | /* Ping the WDT by reading from wdt_start */ | 130 | /* Ping the WDT by reading from wdt_start */ |
123 | inb_p(wdt_start); | 131 | inb_p(wdt_start); |
124 | /* Re-set the timer interval */ | 132 | /* Re-set the timer interval */ |
125 | mod_timer(&timer, jiffies + WDT_INTERVAL); | 133 | mod_timer(&timer, jiffies + WDT_INTERVAL); |
126 | } else { | 134 | } else |
127 | printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); | 135 | printk(KERN_WARNING PFX |
128 | } | 136 | "Heartbeat lost! Will not ping the watchdog\n"); |
129 | } | 137 | } |
130 | 138 | ||
131 | /* | 139 | /* |
@@ -159,40 +167,40 @@ static void wdt_keepalive(void) | |||
159 | * /dev/watchdog handling | 167 | * /dev/watchdog handling |
160 | */ | 168 | */ |
161 | 169 | ||
162 | static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) | 170 | static ssize_t fop_write(struct file *file, const char __user *buf, |
171 | size_t count, loff_t *ppos) | ||
163 | { | 172 | { |
164 | /* See if we got the magic character 'V' and reload the timer */ | 173 | /* See if we got the magic character 'V' and reload the timer */ |
165 | if(count) | 174 | if (count) { |
166 | { | 175 | if (!nowayout) { |
167 | if (!nowayout) | ||
168 | { | ||
169 | size_t ofs; | 176 | size_t ofs; |
170 | 177 | ||
171 | /* note: just in case someone wrote the magic character | 178 | /* note: just in case someone wrote the |
172 | * five months ago... */ | 179 | magic character five months ago... */ |
173 | wdt_expect_close = 0; | 180 | wdt_expect_close = 0; |
174 | 181 | ||
175 | /* scan to see whether or not we got the magic character */ | 182 | /* scan to see whether or not we got the |
176 | for(ofs = 0; ofs != count; ofs++) | 183 | magic character */ |
177 | { | 184 | for (ofs = 0; ofs != count; ofs++) { |
178 | char c; | 185 | char c; |
179 | if(get_user(c, buf+ofs)) | 186 | if (get_user(c, buf + ofs)) |
180 | return -EFAULT; | 187 | return -EFAULT; |
181 | if(c == 'V') | 188 | if (c == 'V') |
182 | wdt_expect_close = 42; | 189 | wdt_expect_close = 42; |
183 | } | 190 | } |
184 | } | 191 | } |
185 | 192 | ||
186 | /* Well, anyhow someone wrote to us, we should return that favour */ | 193 | /* Well, anyhow someone wrote to us, we should |
194 | return that favour */ | ||
187 | wdt_keepalive(); | 195 | wdt_keepalive(); |
188 | } | 196 | } |
189 | return count; | 197 | return count; |
190 | } | 198 | } |
191 | 199 | ||
192 | static int fop_open(struct inode * inode, struct file * file) | 200 | static int fop_open(struct inode *inode, struct file *file) |
193 | { | 201 | { |
194 | /* Just in case we're already talking to someone... */ | 202 | /* Just in case we're already talking to someone... */ |
195 | if(test_and_set_bit(0, &wdt_is_open)) | 203 | if (test_and_set_bit(0, &wdt_is_open)) |
196 | return -EBUSY; | 204 | return -EBUSY; |
197 | 205 | ||
198 | if (nowayout) | 206 | if (nowayout) |
@@ -203,78 +211,72 @@ static int fop_open(struct inode * inode, struct file * file) | |||
203 | return nonseekable_open(inode, file); | 211 | return nonseekable_open(inode, file); |
204 | } | 212 | } |
205 | 213 | ||
206 | static int fop_close(struct inode * inode, struct file * file) | 214 | static int fop_close(struct inode *inode, struct file *file) |
207 | { | 215 | { |
208 | if(wdt_expect_close == 42) | 216 | if (wdt_expect_close == 42) |
209 | wdt_turnoff(); | 217 | wdt_turnoff(); |
210 | else { | 218 | else { |
211 | del_timer(&timer); | 219 | del_timer(&timer); |
212 | printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); | 220 | printk(KERN_CRIT PFX |
221 | "device file closed unexpectedly. Will not stop the WDT!\n"); | ||
213 | } | 222 | } |
214 | clear_bit(0, &wdt_is_open); | 223 | clear_bit(0, &wdt_is_open); |
215 | wdt_expect_close = 0; | 224 | wdt_expect_close = 0; |
216 | return 0; | 225 | return 0; |
217 | } | 226 | } |
218 | 227 | ||
219 | static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 228 | static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
220 | unsigned long arg) | ||
221 | { | 229 | { |
222 | void __user *argp = (void __user *)arg; | 230 | void __user *argp = (void __user *)arg; |
223 | int __user *p = argp; | 231 | int __user *p = argp; |
224 | static struct watchdog_info ident= | 232 | static const struct watchdog_info ident = { |
225 | { | 233 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
226 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 234 | WDIOF_MAGICCLOSE, |
227 | .firmware_version = 1, | 235 | .firmware_version = 1, |
228 | .identity = "SBC60xx", | 236 | .identity = "SBC60xx", |
229 | }; | 237 | }; |
230 | 238 | ||
231 | switch(cmd) | 239 | switch (cmd) { |
240 | case WDIOC_GETSUPPORT: | ||
241 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
242 | case WDIOC_GETSTATUS: | ||
243 | case WDIOC_GETBOOTSTATUS: | ||
244 | return put_user(0, p); | ||
245 | case WDIOC_SETOPTIONS: | ||
232 | { | 246 | { |
233 | default: | 247 | int new_options, retval = -EINVAL; |
234 | return -ENOTTY; | 248 | if (get_user(new_options, p)) |
235 | case WDIOC_GETSUPPORT: | 249 | return -EFAULT; |
236 | return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; | 250 | if (new_options & WDIOS_DISABLECARD) { |
237 | case WDIOC_GETSTATUS: | 251 | wdt_turnoff(); |
238 | case WDIOC_GETBOOTSTATUS: | 252 | retval = 0; |
239 | return put_user(0, p); | ||
240 | case WDIOC_KEEPALIVE: | ||
241 | wdt_keepalive(); | ||
242 | return 0; | ||
243 | case WDIOC_SETOPTIONS: | ||
244 | { | ||
245 | int new_options, retval = -EINVAL; | ||
246 | |||
247 | if(get_user(new_options, p)) | ||
248 | return -EFAULT; | ||
249 | |||
250 | if(new_options & WDIOS_DISABLECARD) { | ||
251 | wdt_turnoff(); | ||
252 | retval = 0; | ||
253 | } | ||
254 | |||
255 | if(new_options & WDIOS_ENABLECARD) { | ||
256 | wdt_startup(); | ||
257 | retval = 0; | ||
258 | } | ||
259 | |||
260 | return retval; | ||
261 | } | 253 | } |
262 | case WDIOC_SETTIMEOUT: | 254 | if (new_options & WDIOS_ENABLECARD) { |
263 | { | 255 | wdt_startup(); |
264 | int new_timeout; | 256 | retval = 0; |
265 | |||
266 | if(get_user(new_timeout, p)) | ||
267 | return -EFAULT; | ||
268 | |||
269 | if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ | ||
270 | return -EINVAL; | ||
271 | |||
272 | timeout = new_timeout; | ||
273 | wdt_keepalive(); | ||
274 | /* Fall through */ | ||
275 | } | 257 | } |
276 | case WDIOC_GETTIMEOUT: | 258 | return retval; |
277 | return put_user(timeout, p); | 259 | } |
260 | case WDIOC_KEEPALIVE: | ||
261 | wdt_keepalive(); | ||
262 | return 0; | ||
263 | case WDIOC_SETTIMEOUT: | ||
264 | { | ||
265 | int new_timeout; | ||
266 | if (get_user(new_timeout, p)) | ||
267 | return -EFAULT; | ||
268 | /* arbitrary upper limit */ | ||
269 | if (new_timeout < 1 || new_timeout > 3600) | ||
270 | return -EINVAL; | ||
271 | |||
272 | timeout = new_timeout; | ||
273 | wdt_keepalive(); | ||
274 | /* Fall through */ | ||
275 | } | ||
276 | case WDIOC_GETTIMEOUT: | ||
277 | return put_user(timeout, p); | ||
278 | default: | ||
279 | return -ENOTTY; | ||
278 | } | 280 | } |
279 | } | 281 | } |
280 | 282 | ||
@@ -284,7 +286,7 @@ static const struct file_operations wdt_fops = { | |||
284 | .write = fop_write, | 286 | .write = fop_write, |
285 | .open = fop_open, | 287 | .open = fop_open, |
286 | .release = fop_close, | 288 | .release = fop_close, |
287 | .ioctl = fop_ioctl, | 289 | .unlocked_ioctl = fop_ioctl, |
288 | }; | 290 | }; |
289 | 291 | ||
290 | static struct miscdevice wdt_miscdev = { | 292 | static struct miscdevice wdt_miscdev = { |
@@ -300,7 +302,7 @@ static struct miscdevice wdt_miscdev = { | |||
300 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | 302 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, |
301 | void *unused) | 303 | void *unused) |
302 | { | 304 | { |
303 | if(code==SYS_DOWN || code==SYS_HALT) | 305 | if (code == SYS_DOWN || code == SYS_HALT) |
304 | wdt_turnoff(); | 306 | wdt_turnoff(); |
305 | return NOTIFY_DONE; | 307 | return NOTIFY_DONE; |
306 | } | 308 | } |
@@ -310,8 +312,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
310 | * turn the timebomb registers off. | 312 | * turn the timebomb registers off. |
311 | */ | 313 | */ |
312 | 314 | ||
313 | static struct notifier_block wdt_notifier= | 315 | static struct notifier_block wdt_notifier = { |
314 | { | ||
315 | .notifier_call = wdt_notify_sys, | 316 | .notifier_call = wdt_notify_sys, |
316 | }; | 317 | }; |
317 | 318 | ||
@@ -324,23 +325,22 @@ static void __exit sbc60xxwdt_unload(void) | |||
324 | 325 | ||
325 | unregister_reboot_notifier(&wdt_notifier); | 326 | unregister_reboot_notifier(&wdt_notifier); |
326 | if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) | 327 | if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) |
327 | release_region(wdt_stop,1); | 328 | release_region(wdt_stop, 1); |
328 | release_region(wdt_start,1); | 329 | release_region(wdt_start, 1); |
329 | } | 330 | } |
330 | 331 | ||
331 | static int __init sbc60xxwdt_init(void) | 332 | static int __init sbc60xxwdt_init(void) |
332 | { | 333 | { |
333 | int rc = -EBUSY; | 334 | int rc = -EBUSY; |
334 | 335 | ||
335 | if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ | 336 | if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */ |
336 | { | ||
337 | timeout = WATCHDOG_TIMEOUT; | 337 | timeout = WATCHDOG_TIMEOUT; |
338 | printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", | 338 | printk(KERN_INFO PFX |
339 | timeout); | 339 | "timeout value must be 1 <= x <= 3600, using %d\n", |
340 | } | 340 | timeout); |
341 | } | ||
341 | 342 | ||
342 | if (!request_region(wdt_start, 1, "SBC 60XX WDT")) | 343 | if (!request_region(wdt_start, 1, "SBC 60XX WDT")) { |
343 | { | ||
344 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | 344 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
345 | wdt_start); | 345 | wdt_start); |
346 | rc = -EIO; | 346 | rc = -EIO; |
@@ -348,33 +348,30 @@ static int __init sbc60xxwdt_init(void) | |||
348 | } | 348 | } |
349 | 349 | ||
350 | /* We cannot reserve 0x45 - the kernel already has! */ | 350 | /* We cannot reserve 0x45 - the kernel already has! */ |
351 | if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) | 351 | if (wdt_stop != 0x45 && wdt_stop != wdt_start) { |
352 | { | 352 | if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) { |
353 | if (!request_region(wdt_stop, 1, "SBC 60XX WDT")) | 353 | printk(KERN_ERR PFX |
354 | { | 354 | "I/O address 0x%04x already in use\n", |
355 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | 355 | wdt_stop); |
356 | wdt_stop); | ||
357 | rc = -EIO; | 356 | rc = -EIO; |
358 | goto err_out_region1; | 357 | goto err_out_region1; |
359 | } | 358 | } |
360 | } | 359 | } |
361 | 360 | ||
362 | rc = register_reboot_notifier(&wdt_notifier); | 361 | rc = register_reboot_notifier(&wdt_notifier); |
363 | if (rc) | 362 | if (rc) { |
364 | { | 363 | printk(KERN_ERR PFX |
365 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 364 | "cannot register reboot notifier (err=%d)\n", rc); |
366 | rc); | ||
367 | goto err_out_region2; | 365 | goto err_out_region2; |
368 | } | 366 | } |
369 | 367 | ||
370 | rc = misc_register(&wdt_miscdev); | 368 | rc = misc_register(&wdt_miscdev); |
371 | if (rc) | 369 | if (rc) { |
372 | { | 370 | printk(KERN_ERR PFX |
373 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 371 | "cannot register miscdev on minor=%d (err=%d)\n", |
374 | wdt_miscdev.minor, rc); | 372 | wdt_miscdev.minor, rc); |
375 | goto err_out_reboot; | 373 | goto err_out_reboot; |
376 | } | 374 | } |
377 | |||
378 | printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n", | 375 | printk(KERN_INFO PFX "WDT driver for 60XX single board computer initialised. timeout=%d sec (nowayout=%d)\n", |
379 | timeout, nowayout); | 376 | timeout, nowayout); |
380 | 377 | ||
@@ -383,10 +380,10 @@ static int __init sbc60xxwdt_init(void) | |||
383 | err_out_reboot: | 380 | err_out_reboot: |
384 | unregister_reboot_notifier(&wdt_notifier); | 381 | unregister_reboot_notifier(&wdt_notifier); |
385 | err_out_region2: | 382 | err_out_region2: |
386 | if ((wdt_stop != 0x45) && (wdt_stop != wdt_start)) | 383 | if (wdt_stop != 0x45 && wdt_stop != wdt_start) |
387 | release_region(wdt_stop,1); | 384 | release_region(wdt_stop, 1); |
388 | err_out_region1: | 385 | err_out_region1: |
389 | release_region(wdt_start,1); | 386 | release_region(wdt_start, 1); |
390 | err_out: | 387 | err_out: |
391 | return rc; | 388 | return rc; |
392 | } | 389 | } |
diff --git a/drivers/watchdog/sbc7240_wdt.c b/drivers/watchdog/sbc7240_wdt.c index 4c8cefbd8627..67ddeb1c830a 100644 --- a/drivers/watchdog/sbc7240_wdt.c +++ b/drivers/watchdog/sbc7240_wdt.c | |||
@@ -27,10 +27,10 @@ | |||
27 | #include <linux/reboot.h> | 27 | #include <linux/reboot.h> |
28 | #include <linux/types.h> | 28 | #include <linux/types.h> |
29 | #include <linux/watchdog.h> | 29 | #include <linux/watchdog.h> |
30 | #include <linux/io.h> | ||
31 | #include <linux/uaccess.h> | ||
30 | #include <asm/atomic.h> | 32 | #include <asm/atomic.h> |
31 | #include <asm/io.h> | ||
32 | #include <asm/system.h> | 33 | #include <asm/system.h> |
33 | #include <asm/uaccess.h> | ||
34 | 34 | ||
35 | #define SBC7240_PREFIX "sbc7240_wdt: " | 35 | #define SBC7240_PREFIX "sbc7240_wdt: " |
36 | 36 | ||
@@ -159,7 +159,7 @@ static int fop_close(struct inode *inode, struct file *file) | |||
159 | return 0; | 159 | return 0; |
160 | } | 160 | } |
161 | 161 | ||
162 | static struct watchdog_info ident = { | 162 | static const struct watchdog_info ident = { |
163 | .options = WDIOF_KEEPALIVEPING| | 163 | .options = WDIOF_KEEPALIVEPING| |
164 | WDIOF_SETTIMEOUT| | 164 | WDIOF_SETTIMEOUT| |
165 | WDIOF_MAGICCLOSE, | 165 | WDIOF_MAGICCLOSE, |
@@ -168,50 +168,50 @@ static struct watchdog_info ident = { | |||
168 | }; | 168 | }; |
169 | 169 | ||
170 | 170 | ||
171 | static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 171 | static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
172 | unsigned long arg) | ||
173 | { | 172 | { |
174 | switch (cmd) { | 173 | switch (cmd) { |
175 | case WDIOC_GETSUPPORT: | 174 | case WDIOC_GETSUPPORT: |
176 | return copy_to_user | 175 | return copy_to_user((void __user *)arg, &ident, sizeof(ident)) |
177 | ((void __user *)arg, &ident, sizeof(ident)) | 176 | ? -EFAULT : 0; |
178 | ? -EFAULT : 0; | ||
179 | case WDIOC_GETSTATUS: | 177 | case WDIOC_GETSTATUS: |
180 | case WDIOC_GETBOOTSTATUS: | 178 | case WDIOC_GETBOOTSTATUS: |
181 | return put_user(0, (int __user *)arg); | 179 | return put_user(0, (int __user *)arg); |
182 | case WDIOC_KEEPALIVE: | 180 | case WDIOC_SETOPTIONS: |
183 | wdt_keepalive(); | 181 | { |
184 | return 0; | 182 | int options; |
185 | case WDIOC_SETOPTIONS:{ | 183 | int retval = -EINVAL; |
186 | int options; | ||
187 | int retval = -EINVAL; | ||
188 | 184 | ||
189 | if (get_user(options, (int __user *)arg)) | 185 | if (get_user(options, (int __user *)arg)) |
190 | return -EFAULT; | 186 | return -EFAULT; |
191 | 187 | ||
192 | if (options & WDIOS_DISABLECARD) { | 188 | if (options & WDIOS_DISABLECARD) { |
193 | wdt_disable(); | 189 | wdt_disable(); |
194 | retval = 0; | 190 | retval = 0; |
195 | } | 191 | } |
196 | |||
197 | if (options & WDIOS_ENABLECARD) { | ||
198 | wdt_enable(); | ||
199 | retval = 0; | ||
200 | } | ||
201 | 192 | ||
202 | return retval; | 193 | if (options & WDIOS_ENABLECARD) { |
194 | wdt_enable(); | ||
195 | retval = 0; | ||
203 | } | 196 | } |
204 | case WDIOC_SETTIMEOUT:{ | ||
205 | int new_timeout; | ||
206 | 197 | ||
207 | if (get_user(new_timeout, (int __user *)arg)) | 198 | return retval; |
208 | return -EFAULT; | 199 | } |
200 | case WDIOC_KEEPALIVE: | ||
201 | wdt_keepalive(); | ||
202 | return 0; | ||
203 | case WDIOC_SETTIMEOUT: | ||
204 | { | ||
205 | int new_timeout; | ||
209 | 206 | ||
210 | if (wdt_set_timeout(new_timeout)) | 207 | if (get_user(new_timeout, (int __user *)arg)) |
211 | return -EINVAL; | 208 | return -EFAULT; |
212 | 209 | ||
213 | /* Fall through */ | 210 | if (wdt_set_timeout(new_timeout)) |
214 | } | 211 | return -EINVAL; |
212 | |||
213 | /* Fall through */ | ||
214 | } | ||
215 | case WDIOC_GETTIMEOUT: | 215 | case WDIOC_GETTIMEOUT: |
216 | return put_user(timeout, (int __user *)arg); | 216 | return put_user(timeout, (int __user *)arg); |
217 | default: | 217 | default: |
@@ -225,7 +225,7 @@ static const struct file_operations wdt_fops = { | |||
225 | .write = fop_write, | 225 | .write = fop_write, |
226 | .open = fop_open, | 226 | .open = fop_open, |
227 | .release = fop_close, | 227 | .release = fop_close, |
228 | .ioctl = fop_ioctl, | 228 | .unlocked_ioctl = fop_ioctl, |
229 | }; | 229 | }; |
230 | 230 | ||
231 | static struct miscdevice wdt_miscdev = { | 231 | static struct miscdevice wdt_miscdev = { |
diff --git a/drivers/watchdog/sbc8360.c b/drivers/watchdog/sbc8360.c index 2ee2677f3648..fd83dd052d8c 100644 --- a/drivers/watchdog/sbc8360.c +++ b/drivers/watchdog/sbc8360.c | |||
@@ -48,13 +48,12 @@ | |||
48 | #include <linux/init.h> | 48 | #include <linux/init.h> |
49 | #include <linux/spinlock.h> | 49 | #include <linux/spinlock.h> |
50 | #include <linux/moduleparam.h> | 50 | #include <linux/moduleparam.h> |
51 | #include <linux/io.h> | ||
52 | #include <linux/uaccess.h> | ||
51 | 53 | ||
52 | #include <asm/io.h> | ||
53 | #include <asm/uaccess.h> | ||
54 | #include <asm/system.h> | 54 | #include <asm/system.h> |
55 | 55 | ||
56 | static unsigned long sbc8360_is_open; | 56 | static unsigned long sbc8360_is_open; |
57 | static DEFINE_SPINLOCK(sbc8360_lock); | ||
58 | static char expect_close; | 57 | static char expect_close; |
59 | 58 | ||
60 | #define PFX "sbc8360: " | 59 | #define PFX "sbc8360: " |
@@ -204,7 +203,8 @@ module_param(timeout, int, 0); | |||
204 | MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))"); | 203 | MODULE_PARM_DESC(timeout, "Index into timeout table (0-63) (default=27 (60s))"); |
205 | module_param(nowayout, int, 0); | 204 | module_param(nowayout, int, 0); |
206 | MODULE_PARM_DESC(nowayout, | 205 | MODULE_PARM_DESC(nowayout, |
207 | "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 206 | "Watchdog cannot be stopped once started (default=" |
207 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
208 | 208 | ||
209 | /* | 209 | /* |
210 | * Kernel methods. | 210 | * Kernel methods. |
@@ -231,9 +231,16 @@ static void sbc8360_ping(void) | |||
231 | outb(wd_margin, SBC8360_BASETIME); | 231 | outb(wd_margin, SBC8360_BASETIME); |
232 | } | 232 | } |
233 | 233 | ||
234 | /* stop watchdog */ | ||
235 | static void sbc8360_stop(void) | ||
236 | { | ||
237 | /* De-activate the watchdog */ | ||
238 | outb(0, SBC8360_ENABLE); | ||
239 | } | ||
240 | |||
234 | /* Userspace pings kernel driver, or requests clean close */ | 241 | /* Userspace pings kernel driver, or requests clean close */ |
235 | static ssize_t sbc8360_write(struct file *file, const char __user * buf, | 242 | static ssize_t sbc8360_write(struct file *file, const char __user *buf, |
236 | size_t count, loff_t * ppos) | 243 | size_t count, loff_t *ppos) |
237 | { | 244 | { |
238 | if (count) { | 245 | if (count) { |
239 | if (!nowayout) { | 246 | if (!nowayout) { |
@@ -257,16 +264,12 @@ static ssize_t sbc8360_write(struct file *file, const char __user * buf, | |||
257 | 264 | ||
258 | static int sbc8360_open(struct inode *inode, struct file *file) | 265 | static int sbc8360_open(struct inode *inode, struct file *file) |
259 | { | 266 | { |
260 | spin_lock(&sbc8360_lock); | 267 | if (test_and_set_bit(0, &sbc8360_is_open)) |
261 | if (test_and_set_bit(0, &sbc8360_is_open)) { | ||
262 | spin_unlock(&sbc8360_lock); | ||
263 | return -EBUSY; | 268 | return -EBUSY; |
264 | } | ||
265 | if (nowayout) | 269 | if (nowayout) |
266 | __module_get(THIS_MODULE); | 270 | __module_get(THIS_MODULE); |
267 | 271 | ||
268 | /* Activate and ping once to start the countdown */ | 272 | /* Activate and ping once to start the countdown */ |
269 | spin_unlock(&sbc8360_lock); | ||
270 | sbc8360_activate(); | 273 | sbc8360_activate(); |
271 | sbc8360_ping(); | 274 | sbc8360_ping(); |
272 | return nonseekable_open(inode, file); | 275 | return nonseekable_open(inode, file); |
@@ -274,16 +277,14 @@ static int sbc8360_open(struct inode *inode, struct file *file) | |||
274 | 277 | ||
275 | static int sbc8360_close(struct inode *inode, struct file *file) | 278 | static int sbc8360_close(struct inode *inode, struct file *file) |
276 | { | 279 | { |
277 | spin_lock(&sbc8360_lock); | ||
278 | if (expect_close == 42) | 280 | if (expect_close == 42) |
279 | outb(0, SBC8360_ENABLE); | 281 | sbc8360_stop(); |
280 | else | 282 | else |
281 | printk(KERN_CRIT PFX | 283 | printk(KERN_CRIT PFX |
282 | "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n"); | 284 | "SBC8360 device closed unexpectedly. SBC8360 will not stop!\n"); |
283 | 285 | ||
284 | clear_bit(0, &sbc8360_is_open); | 286 | clear_bit(0, &sbc8360_is_open); |
285 | expect_close = 0; | 287 | expect_close = 0; |
286 | spin_unlock(&sbc8360_lock); | ||
287 | return 0; | 288 | return 0; |
288 | } | 289 | } |
289 | 290 | ||
@@ -294,10 +295,9 @@ static int sbc8360_close(struct inode *inode, struct file *file) | |||
294 | static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code, | 295 | static int sbc8360_notify_sys(struct notifier_block *this, unsigned long code, |
295 | void *unused) | 296 | void *unused) |
296 | { | 297 | { |
297 | if (code == SYS_DOWN || code == SYS_HALT) { | 298 | if (code == SYS_DOWN || code == SYS_HALT) |
298 | /* Disable the SBC8360 Watchdog */ | 299 | sbc8360_stop(); /* Disable the SBC8360 Watchdog */ |
299 | outb(0, SBC8360_ENABLE); | 300 | |
300 | } | ||
301 | return NOTIFY_DONE; | 301 | return NOTIFY_DONE; |
302 | } | 302 | } |
303 | 303 | ||
@@ -382,13 +382,13 @@ static int __init sbc8360_init(void) | |||
382 | 382 | ||
383 | return 0; | 383 | return 0; |
384 | 384 | ||
385 | out_nomisc: | 385 | out_nomisc: |
386 | unregister_reboot_notifier(&sbc8360_notifier); | 386 | unregister_reboot_notifier(&sbc8360_notifier); |
387 | out_noreboot: | 387 | out_noreboot: |
388 | release_region(SBC8360_BASETIME, 1); | 388 | release_region(SBC8360_BASETIME, 1); |
389 | out_nobasetimereg: | 389 | out_nobasetimereg: |
390 | release_region(SBC8360_ENABLE, 1); | 390 | release_region(SBC8360_ENABLE, 1); |
391 | out: | 391 | out: |
392 | return res; | 392 | return res; |
393 | } | 393 | } |
394 | 394 | ||
diff --git a/drivers/watchdog/sbc_epx_c3.c b/drivers/watchdog/sbc_epx_c3.c index 82cbd8809a69..e5e470ca7759 100644 --- a/drivers/watchdog/sbc_epx_c3.c +++ b/drivers/watchdog/sbc_epx_c3.c | |||
@@ -25,8 +25,8 @@ | |||
25 | #include <linux/reboot.h> | 25 | #include <linux/reboot.h> |
26 | #include <linux/init.h> | 26 | #include <linux/init.h> |
27 | #include <linux/ioport.h> | 27 | #include <linux/ioport.h> |
28 | #include <asm/uaccess.h> | 28 | #include <linux/uaccess.h> |
29 | #include <asm/io.h> | 29 | #include <linux/io.h> |
30 | 30 | ||
31 | #define PFX "epx_c3: " | 31 | #define PFX "epx_c3: " |
32 | static int epx_c3_alive; | 32 | static int epx_c3_alive; |
@@ -100,12 +100,12 @@ static ssize_t epx_c3_write(struct file *file, const char __user *data, | |||
100 | return len; | 100 | return len; |
101 | } | 101 | } |
102 | 102 | ||
103 | static int epx_c3_ioctl(struct inode *inode, struct file *file, | 103 | static long epx_c3_ioctl(struct file *file, unsigned int cmd, |
104 | unsigned int cmd, unsigned long arg) | 104 | unsigned long arg) |
105 | { | 105 | { |
106 | int options, retval = -EINVAL; | 106 | int options, retval = -EINVAL; |
107 | int __user *argp = (void __user *)arg; | 107 | int __user *argp = (void __user *)arg; |
108 | static struct watchdog_info ident = { | 108 | static const struct watchdog_info ident = { |
109 | .options = WDIOF_KEEPALIVEPING | | 109 | .options = WDIOF_KEEPALIVEPING | |
110 | WDIOF_MAGICCLOSE, | 110 | WDIOF_MAGICCLOSE, |
111 | .firmware_version = 0, | 111 | .firmware_version = 0, |
@@ -120,11 +120,6 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, | |||
120 | case WDIOC_GETSTATUS: | 120 | case WDIOC_GETSTATUS: |
121 | case WDIOC_GETBOOTSTATUS: | 121 | case WDIOC_GETBOOTSTATUS: |
122 | return put_user(0, argp); | 122 | return put_user(0, argp); |
123 | case WDIOC_KEEPALIVE: | ||
124 | epx_c3_pet(); | ||
125 | return 0; | ||
126 | case WDIOC_GETTIMEOUT: | ||
127 | return put_user(WATCHDOG_TIMEOUT, argp); | ||
128 | case WDIOC_SETOPTIONS: | 123 | case WDIOC_SETOPTIONS: |
129 | if (get_user(options, argp)) | 124 | if (get_user(options, argp)) |
130 | return -EFAULT; | 125 | return -EFAULT; |
@@ -140,6 +135,11 @@ static int epx_c3_ioctl(struct inode *inode, struct file *file, | |||
140 | } | 135 | } |
141 | 136 | ||
142 | return retval; | 137 | return retval; |
138 | case WDIOC_KEEPALIVE: | ||
139 | epx_c3_pet(); | ||
140 | return 0; | ||
141 | case WDIOC_GETTIMEOUT: | ||
142 | return put_user(WATCHDOG_TIMEOUT, argp); | ||
143 | default: | 143 | default: |
144 | return -ENOTTY; | 144 | return -ENOTTY; |
145 | } | 145 | } |
@@ -158,7 +158,7 @@ static const struct file_operations epx_c3_fops = { | |||
158 | .owner = THIS_MODULE, | 158 | .owner = THIS_MODULE, |
159 | .llseek = no_llseek, | 159 | .llseek = no_llseek, |
160 | .write = epx_c3_write, | 160 | .write = epx_c3_write, |
161 | .ioctl = epx_c3_ioctl, | 161 | .unlocked_ioctl = epx_c3_ioctl, |
162 | .open = epx_c3_open, | 162 | .open = epx_c3_open, |
163 | .release = epx_c3_release, | 163 | .release = epx_c3_release, |
164 | }; | 164 | }; |
diff --git a/drivers/watchdog/sc1200wdt.c b/drivers/watchdog/sc1200wdt.c index 621ebad56d86..23da3ccd832a 100644 --- a/drivers/watchdog/sc1200wdt.c +++ b/drivers/watchdog/sc1200wdt.c | |||
@@ -196,7 +196,6 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd, | |||
196 | }; | 196 | }; |
197 | 197 | ||
198 | switch (cmd) { | 198 | switch (cmd) { |
199 | |||
200 | case WDIOC_GETSUPPORT: | 199 | case WDIOC_GETSUPPORT: |
201 | if (copy_to_user(argp, &ident, sizeof ident)) | 200 | if (copy_to_user(argp, &ident, sizeof ident)) |
202 | return -EFAULT; | 201 | return -EFAULT; |
@@ -208,24 +207,6 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd, | |||
208 | case WDIOC_GETBOOTSTATUS: | 207 | case WDIOC_GETBOOTSTATUS: |
209 | return put_user(0, p); | 208 | return put_user(0, p); |
210 | 209 | ||
211 | case WDIOC_KEEPALIVE: | ||
212 | sc1200wdt_write_data(WDTO, timeout); | ||
213 | return 0; | ||
214 | |||
215 | case WDIOC_SETTIMEOUT: | ||
216 | if (get_user(new_timeout, p)) | ||
217 | return -EFAULT; | ||
218 | /* the API states this is given in secs */ | ||
219 | new_timeout /= 60; | ||
220 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | ||
221 | return -EINVAL; | ||
222 | timeout = new_timeout; | ||
223 | sc1200wdt_write_data(WDTO, timeout); | ||
224 | /* fall through and return the new timeout */ | ||
225 | |||
226 | case WDIOC_GETTIMEOUT: | ||
227 | return put_user(timeout * 60, p); | ||
228 | |||
229 | case WDIOC_SETOPTIONS: | 210 | case WDIOC_SETOPTIONS: |
230 | { | 211 | { |
231 | int options, retval = -EINVAL; | 212 | int options, retval = -EINVAL; |
@@ -245,6 +226,24 @@ static long sc1200wdt_ioctl(struct file *file, unsigned int cmd, | |||
245 | 226 | ||
246 | return retval; | 227 | return retval; |
247 | } | 228 | } |
229 | case WDIOC_KEEPALIVE: | ||
230 | sc1200wdt_write_data(WDTO, timeout); | ||
231 | return 0; | ||
232 | |||
233 | case WDIOC_SETTIMEOUT: | ||
234 | if (get_user(new_timeout, p)) | ||
235 | return -EFAULT; | ||
236 | /* the API states this is given in secs */ | ||
237 | new_timeout /= 60; | ||
238 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | ||
239 | return -EINVAL; | ||
240 | timeout = new_timeout; | ||
241 | sc1200wdt_write_data(WDTO, timeout); | ||
242 | /* fall through and return the new timeout */ | ||
243 | |||
244 | case WDIOC_GETTIMEOUT: | ||
245 | return put_user(timeout * 60, p); | ||
246 | |||
248 | default: | 247 | default: |
249 | return -ENOTTY; | 248 | return -ENOTTY; |
250 | } | 249 | } |
@@ -280,7 +279,7 @@ static ssize_t sc1200wdt_write(struct file *file, const char __user *data, | |||
280 | for (i = 0; i != len; i++) { | 279 | for (i = 0; i != len; i++) { |
281 | char c; | 280 | char c; |
282 | 281 | ||
283 | if (get_user(c, data+i)) | 282 | if (get_user(c, data + i)) |
284 | return -EFAULT; | 283 | return -EFAULT; |
285 | if (c == 'V') | 284 | if (c == 'V') |
286 | expect_close = 42; | 285 | expect_close = 42; |
diff --git a/drivers/watchdog/sc520_wdt.c b/drivers/watchdog/sc520_wdt.c index 2847324a2be2..a2b6c1067ec5 100644 --- a/drivers/watchdog/sc520_wdt.c +++ b/drivers/watchdog/sc520_wdt.c | |||
@@ -64,9 +64,9 @@ | |||
64 | #include <linux/reboot.h> | 64 | #include <linux/reboot.h> |
65 | #include <linux/init.h> | 65 | #include <linux/init.h> |
66 | #include <linux/jiffies.h> | 66 | #include <linux/jiffies.h> |
67 | #include <linux/io.h> | ||
68 | #include <linux/uaccess.h> | ||
67 | 69 | ||
68 | #include <asm/io.h> | ||
69 | #include <asm/uaccess.h> | ||
70 | #include <asm/system.h> | 70 | #include <asm/system.h> |
71 | 71 | ||
72 | #define OUR_NAME "sc520_wdt" | 72 | #define OUR_NAME "sc520_wdt" |
@@ -91,13 +91,18 @@ | |||
91 | */ | 91 | */ |
92 | 92 | ||
93 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ | 93 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ |
94 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ | 94 | /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ |
95 | static int timeout = WATCHDOG_TIMEOUT; | ||
95 | module_param(timeout, int, 0); | 96 | module_param(timeout, int, 0); |
96 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 97 | MODULE_PARM_DESC(timeout, |
98 | "Watchdog timeout in seconds. (1 <= timeout <= 3600, default=" | ||
99 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
97 | 100 | ||
98 | static int nowayout = WATCHDOG_NOWAYOUT; | 101 | static int nowayout = WATCHDOG_NOWAYOUT; |
99 | module_param(nowayout, int, 0); | 102 | module_param(nowayout, int, 0); |
100 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 103 | MODULE_PARM_DESC(nowayout, |
104 | "Watchdog cannot be stopped once started (default=" | ||
105 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
101 | 106 | ||
102 | /* | 107 | /* |
103 | * AMD Elan SC520 - Watchdog Timer Registers | 108 | * AMD Elan SC520 - Watchdog Timer Registers |
@@ -136,8 +141,7 @@ static void wdt_timer_ping(unsigned long data) | |||
136 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL | 141 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL |
137 | * we agree to ping the WDT | 142 | * we agree to ping the WDT |
138 | */ | 143 | */ |
139 | if(time_before(jiffies, next_heartbeat)) | 144 | if (time_before(jiffies, next_heartbeat)) { |
140 | { | ||
141 | /* Ping the WDT */ | 145 | /* Ping the WDT */ |
142 | spin_lock(&wdt_spinlock); | 146 | spin_lock(&wdt_spinlock); |
143 | writew(0xAAAA, wdtmrctl); | 147 | writew(0xAAAA, wdtmrctl); |
@@ -146,9 +150,9 @@ static void wdt_timer_ping(unsigned long data) | |||
146 | 150 | ||
147 | /* Re-set the timer interval */ | 151 | /* Re-set the timer interval */ |
148 | mod_timer(&timer, jiffies + WDT_INTERVAL); | 152 | mod_timer(&timer, jiffies + WDT_INTERVAL); |
149 | } else { | 153 | } else |
150 | printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); | 154 | printk(KERN_WARNING PFX |
151 | } | 155 | "Heartbeat lost! Will not ping the watchdog\n"); |
152 | } | 156 | } |
153 | 157 | ||
154 | /* | 158 | /* |
@@ -162,7 +166,7 @@ static void wdt_config(int writeval) | |||
162 | 166 | ||
163 | /* buy some time (ping) */ | 167 | /* buy some time (ping) */ |
164 | spin_lock_irqsave(&wdt_spinlock, flags); | 168 | spin_lock_irqsave(&wdt_spinlock, flags); |
165 | dummy=readw(wdtmrctl); /* ensure write synchronization */ | 169 | dummy = readw(wdtmrctl); /* ensure write synchronization */ |
166 | writew(0xAAAA, wdtmrctl); | 170 | writew(0xAAAA, wdtmrctl); |
167 | writew(0x5555, wdtmrctl); | 171 | writew(0x5555, wdtmrctl); |
168 | /* unlock WDT = make WDT configuration register writable one time */ | 172 | /* unlock WDT = make WDT configuration register writable one time */ |
@@ -219,10 +223,11 @@ static int wdt_set_heartbeat(int t) | |||
219 | * /dev/watchdog handling | 223 | * /dev/watchdog handling |
220 | */ | 224 | */ |
221 | 225 | ||
222 | static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) | 226 | static ssize_t fop_write(struct file *file, const char __user *buf, |
227 | size_t count, loff_t *ppos) | ||
223 | { | 228 | { |
224 | /* See if we got the magic character 'V' and reload the timer */ | 229 | /* See if we got the magic character 'V' and reload the timer */ |
225 | if(count) { | 230 | if (count) { |
226 | if (!nowayout) { | 231 | if (!nowayout) { |
227 | size_t ofs; | 232 | size_t ofs; |
228 | 233 | ||
@@ -231,25 +236,26 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou | |||
231 | wdt_expect_close = 0; | 236 | wdt_expect_close = 0; |
232 | 237 | ||
233 | /* now scan */ | 238 | /* now scan */ |
234 | for(ofs = 0; ofs != count; ofs++) { | 239 | for (ofs = 0; ofs != count; ofs++) { |
235 | char c; | 240 | char c; |
236 | if (get_user(c, buf + ofs)) | 241 | if (get_user(c, buf + ofs)) |
237 | return -EFAULT; | 242 | return -EFAULT; |
238 | if(c == 'V') | 243 | if (c == 'V') |
239 | wdt_expect_close = 42; | 244 | wdt_expect_close = 42; |
240 | } | 245 | } |
241 | } | 246 | } |
242 | 247 | ||
243 | /* Well, anyhow someone wrote to us, we should return that favour */ | 248 | /* Well, anyhow someone wrote to us, we should |
249 | return that favour */ | ||
244 | wdt_keepalive(); | 250 | wdt_keepalive(); |
245 | } | 251 | } |
246 | return count; | 252 | return count; |
247 | } | 253 | } |
248 | 254 | ||
249 | static int fop_open(struct inode * inode, struct file * file) | 255 | static int fop_open(struct inode *inode, struct file *file) |
250 | { | 256 | { |
251 | /* Just in case we're already talking to someone... */ | 257 | /* Just in case we're already talking to someone... */ |
252 | if(test_and_set_bit(0, &wdt_is_open)) | 258 | if (test_and_set_bit(0, &wdt_is_open)) |
253 | return -EBUSY; | 259 | return -EBUSY; |
254 | if (nowayout) | 260 | if (nowayout) |
255 | __module_get(THIS_MODULE); | 261 | __module_get(THIS_MODULE); |
@@ -259,12 +265,13 @@ static int fop_open(struct inode * inode, struct file * file) | |||
259 | return nonseekable_open(inode, file); | 265 | return nonseekable_open(inode, file); |
260 | } | 266 | } |
261 | 267 | ||
262 | static int fop_close(struct inode * inode, struct file * file) | 268 | static int fop_close(struct inode *inode, struct file *file) |
263 | { | 269 | { |
264 | if(wdt_expect_close == 42) { | 270 | if (wdt_expect_close == 42) |
265 | wdt_turnoff(); | 271 | wdt_turnoff(); |
266 | } else { | 272 | else { |
267 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 273 | printk(KERN_CRIT PFX |
274 | "Unexpected close, not stopping watchdog!\n"); | ||
268 | wdt_keepalive(); | 275 | wdt_keepalive(); |
269 | } | 276 | } |
270 | clear_bit(0, &wdt_is_open); | 277 | clear_bit(0, &wdt_is_open); |
@@ -272,63 +279,62 @@ static int fop_close(struct inode * inode, struct file * file) | |||
272 | return 0; | 279 | return 0; |
273 | } | 280 | } |
274 | 281 | ||
275 | static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 282 | static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
276 | unsigned long arg) | ||
277 | { | 283 | { |
278 | void __user *argp = (void __user *)arg; | 284 | void __user *argp = (void __user *)arg; |
279 | int __user *p = argp; | 285 | int __user *p = argp; |
280 | static struct watchdog_info ident = { | 286 | static const struct watchdog_info ident = { |
281 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 287 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
288 | | WDIOF_MAGICCLOSE, | ||
282 | .firmware_version = 1, | 289 | .firmware_version = 1, |
283 | .identity = "SC520", | 290 | .identity = "SC520", |
284 | }; | 291 | }; |
285 | 292 | ||
286 | switch(cmd) | 293 | switch (cmd) { |
294 | case WDIOC_GETSUPPORT: | ||
295 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
296 | case WDIOC_GETSTATUS: | ||
297 | case WDIOC_GETBOOTSTATUS: | ||
298 | return put_user(0, p); | ||
299 | case WDIOC_SETOPTIONS: | ||
287 | { | 300 | { |
288 | default: | 301 | int new_options, retval = -EINVAL; |
289 | return -ENOTTY; | ||
290 | case WDIOC_GETSUPPORT: | ||
291 | return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; | ||
292 | case WDIOC_GETSTATUS: | ||
293 | case WDIOC_GETBOOTSTATUS: | ||
294 | return put_user(0, p); | ||
295 | case WDIOC_KEEPALIVE: | ||
296 | wdt_keepalive(); | ||
297 | return 0; | ||
298 | case WDIOC_SETOPTIONS: | ||
299 | { | ||
300 | int new_options, retval = -EINVAL; | ||
301 | |||
302 | if(get_user(new_options, p)) | ||
303 | return -EFAULT; | ||
304 | |||
305 | if(new_options & WDIOS_DISABLECARD) { | ||
306 | wdt_turnoff(); | ||
307 | retval = 0; | ||
308 | } | ||
309 | 302 | ||
310 | if(new_options & WDIOS_ENABLECARD) { | 303 | if (get_user(new_options, p)) |
311 | wdt_startup(); | 304 | return -EFAULT; |
312 | retval = 0; | ||
313 | } | ||
314 | 305 | ||
315 | return retval; | 306 | if (new_options & WDIOS_DISABLECARD) { |
307 | wdt_turnoff(); | ||
308 | retval = 0; | ||
316 | } | 309 | } |
317 | case WDIOC_SETTIMEOUT: | ||
318 | { | ||
319 | int new_timeout; | ||
320 | 310 | ||
321 | if(get_user(new_timeout, p)) | 311 | if (new_options & WDIOS_ENABLECARD) { |
322 | return -EFAULT; | 312 | wdt_startup(); |
313 | retval = 0; | ||
314 | } | ||
323 | 315 | ||
324 | if(wdt_set_heartbeat(new_timeout)) | 316 | return retval; |
325 | return -EINVAL; | 317 | } |
318 | case WDIOC_KEEPALIVE: | ||
319 | wdt_keepalive(); | ||
320 | return 0; | ||
321 | case WDIOC_SETTIMEOUT: | ||
322 | { | ||
323 | int new_timeout; | ||
326 | 324 | ||
327 | wdt_keepalive(); | 325 | if (get_user(new_timeout, p)) |
328 | /* Fall through */ | 326 | return -EFAULT; |
329 | } | 327 | |
330 | case WDIOC_GETTIMEOUT: | 328 | if (wdt_set_heartbeat(new_timeout)) |
331 | return put_user(timeout, p); | 329 | return -EINVAL; |
330 | |||
331 | wdt_keepalive(); | ||
332 | /* Fall through */ | ||
333 | } | ||
334 | case WDIOC_GETTIMEOUT: | ||
335 | return put_user(timeout, p); | ||
336 | default: | ||
337 | return -ENOTTY; | ||
332 | } | 338 | } |
333 | } | 339 | } |
334 | 340 | ||
@@ -338,7 +344,7 @@ static const struct file_operations wdt_fops = { | |||
338 | .write = fop_write, | 344 | .write = fop_write, |
339 | .open = fop_open, | 345 | .open = fop_open, |
340 | .release = fop_close, | 346 | .release = fop_close, |
341 | .ioctl = fop_ioctl, | 347 | .unlocked_ioctl = fop_ioctl, |
342 | }; | 348 | }; |
343 | 349 | ||
344 | static struct miscdevice wdt_miscdev = { | 350 | static struct miscdevice wdt_miscdev = { |
@@ -354,7 +360,7 @@ static struct miscdevice wdt_miscdev = { | |||
354 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | 360 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, |
355 | void *unused) | 361 | void *unused) |
356 | { | 362 | { |
357 | if(code==SYS_DOWN || code==SYS_HALT) | 363 | if (code == SYS_DOWN || code == SYS_HALT) |
358 | wdt_turnoff(); | 364 | wdt_turnoff(); |
359 | return NOTIFY_DONE; | 365 | return NOTIFY_DONE; |
360 | } | 366 | } |
@@ -383,11 +389,13 @@ static int __init sc520_wdt_init(void) | |||
383 | { | 389 | { |
384 | int rc = -EBUSY; | 390 | int rc = -EBUSY; |
385 | 391 | ||
386 | /* Check that the timeout value is within it's range ; if not reset to the default */ | 392 | /* Check that the timeout value is within it's range ; |
393 | if not reset to the default */ | ||
387 | if (wdt_set_heartbeat(timeout)) { | 394 | if (wdt_set_heartbeat(timeout)) { |
388 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | 395 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); |
389 | printk(KERN_INFO PFX "timeout value must be 1<=timeout<=3600, using %d\n", | 396 | printk(KERN_INFO PFX |
390 | WATCHDOG_TIMEOUT); | 397 | "timeout value must be 1 <= timeout <= 3600, using %d\n", |
398 | WATCHDOG_TIMEOUT); | ||
391 | } | 399 | } |
392 | 400 | ||
393 | wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2); | 401 | wdtmrctl = ioremap((unsigned long)(MMCR_BASE + OFFS_WDTMRCTL), 2); |
@@ -399,20 +407,22 @@ static int __init sc520_wdt_init(void) | |||
399 | 407 | ||
400 | rc = register_reboot_notifier(&wdt_notifier); | 408 | rc = register_reboot_notifier(&wdt_notifier); |
401 | if (rc) { | 409 | if (rc) { |
402 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 410 | printk(KERN_ERR PFX |
403 | rc); | 411 | "cannot register reboot notifier (err=%d)\n", rc); |
404 | goto err_out_ioremap; | 412 | goto err_out_ioremap; |
405 | } | 413 | } |
406 | 414 | ||
407 | rc = misc_register(&wdt_miscdev); | 415 | rc = misc_register(&wdt_miscdev); |
408 | if (rc) { | 416 | if (rc) { |
409 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 417 | printk(KERN_ERR PFX |
410 | WATCHDOG_MINOR, rc); | 418 | "cannot register miscdev on minor=%d (err=%d)\n", |
419 | WATCHDOG_MINOR, rc); | ||
411 | goto err_out_notifier; | 420 | goto err_out_notifier; |
412 | } | 421 | } |
413 | 422 | ||
414 | printk(KERN_INFO PFX "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n", | 423 | printk(KERN_INFO PFX |
415 | timeout,nowayout); | 424 | "WDT driver for SC520 initialised. timeout=%d sec (nowayout=%d)\n", |
425 | timeout, nowayout); | ||
416 | 426 | ||
417 | return 0; | 427 | return 0; |
418 | 428 | ||
diff --git a/drivers/watchdog/scx200_wdt.c b/drivers/watchdog/scx200_wdt.c index d55882bca319..9e19a10a5bb9 100644 --- a/drivers/watchdog/scx200_wdt.c +++ b/drivers/watchdog/scx200_wdt.c | |||
@@ -27,9 +27,8 @@ | |||
27 | #include <linux/fs.h> | 27 | #include <linux/fs.h> |
28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/scx200.h> | 29 | #include <linux/scx200.h> |
30 | 30 | #include <linux/uaccess.h> | |
31 | #include <asm/uaccess.h> | 31 | #include <linux/io.h> |
32 | #include <asm/io.h> | ||
33 | 32 | ||
34 | #define NAME "scx200_wdt" | 33 | #define NAME "scx200_wdt" |
35 | 34 | ||
@@ -47,8 +46,9 @@ module_param(nowayout, int, 0); | |||
47 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | 46 | MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); |
48 | 47 | ||
49 | static u16 wdto_restart; | 48 | static u16 wdto_restart; |
50 | static struct semaphore open_semaphore; | ||
51 | static char expect_close; | 49 | static char expect_close; |
50 | static unsigned long open_lock; | ||
51 | static DEFINE_SPINLOCK(scx_lock); | ||
52 | 52 | ||
53 | /* Bits of the WDCNFG register */ | 53 | /* Bits of the WDCNFG register */ |
54 | #define W_ENABLE 0x00fa /* Enable watchdog */ | 54 | #define W_ENABLE 0x00fa /* Enable watchdog */ |
@@ -59,7 +59,9 @@ static char expect_close; | |||
59 | 59 | ||
60 | static void scx200_wdt_ping(void) | 60 | static void scx200_wdt_ping(void) |
61 | { | 61 | { |
62 | spin_lock(&scx_lock); | ||
62 | outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO); | 63 | outw(wdto_restart, scx200_cb_base + SCx200_WDT_WDTO); |
64 | spin_unlock(&scx_lock); | ||
63 | } | 65 | } |
64 | 66 | ||
65 | static void scx200_wdt_update_margin(void) | 67 | static void scx200_wdt_update_margin(void) |
@@ -73,9 +75,11 @@ static void scx200_wdt_enable(void) | |||
73 | printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", | 75 | printk(KERN_DEBUG NAME ": enabling watchdog timer, wdto_restart = %d\n", |
74 | wdto_restart); | 76 | wdto_restart); |
75 | 77 | ||
78 | spin_lock(&scx_lock); | ||
76 | outw(0, scx200_cb_base + SCx200_WDT_WDTO); | 79 | outw(0, scx200_cb_base + SCx200_WDT_WDTO); |
77 | outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); | 80 | outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); |
78 | outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG); | 81 | outw(W_ENABLE, scx200_cb_base + SCx200_WDT_WDCNFG); |
82 | spin_unlock(&scx_lock); | ||
79 | 83 | ||
80 | scx200_wdt_ping(); | 84 | scx200_wdt_ping(); |
81 | } | 85 | } |
@@ -84,15 +88,17 @@ static void scx200_wdt_disable(void) | |||
84 | { | 88 | { |
85 | printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); | 89 | printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); |
86 | 90 | ||
91 | spin_lock(&scx_lock); | ||
87 | outw(0, scx200_cb_base + SCx200_WDT_WDTO); | 92 | outw(0, scx200_cb_base + SCx200_WDT_WDTO); |
88 | outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); | 93 | outb(SCx200_WDT_WDSTS_WDOVF, scx200_cb_base + SCx200_WDT_WDSTS); |
89 | outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG); | 94 | outw(W_DISABLE, scx200_cb_base + SCx200_WDT_WDCNFG); |
95 | spin_unlock(&scx_lock); | ||
90 | } | 96 | } |
91 | 97 | ||
92 | static int scx200_wdt_open(struct inode *inode, struct file *file) | 98 | static int scx200_wdt_open(struct inode *inode, struct file *file) |
93 | { | 99 | { |
94 | /* only allow one at a time */ | 100 | /* only allow one at a time */ |
95 | if (down_trylock(&open_semaphore)) | 101 | if (test_and_set_bit(0, &open_lock)) |
96 | return -EBUSY; | 102 | return -EBUSY; |
97 | scx200_wdt_enable(); | 103 | scx200_wdt_enable(); |
98 | 104 | ||
@@ -101,13 +107,12 @@ static int scx200_wdt_open(struct inode *inode, struct file *file) | |||
101 | 107 | ||
102 | static int scx200_wdt_release(struct inode *inode, struct file *file) | 108 | static int scx200_wdt_release(struct inode *inode, struct file *file) |
103 | { | 109 | { |
104 | if (expect_close != 42) { | 110 | if (expect_close != 42) |
105 | printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n"); | 111 | printk(KERN_WARNING NAME ": watchdog device closed unexpectedly, will not disable the watchdog timer\n"); |
106 | } else if (!nowayout) { | 112 | else if (!nowayout) |
107 | scx200_wdt_disable(); | 113 | scx200_wdt_disable(); |
108 | } | ||
109 | expect_close = 0; | 114 | expect_close = 0; |
110 | up(&open_semaphore); | 115 | clear_bit(0, &open_lock); |
111 | 116 | ||
112 | return 0; | 117 | return 0; |
113 | } | 118 | } |
@@ -122,8 +127,7 @@ static int scx200_wdt_notify_sys(struct notifier_block *this, | |||
122 | return NOTIFY_DONE; | 127 | return NOTIFY_DONE; |
123 | } | 128 | } |
124 | 129 | ||
125 | static struct notifier_block scx200_wdt_notifier = | 130 | static struct notifier_block scx200_wdt_notifier = { |
126 | { | ||
127 | .notifier_call = scx200_wdt_notify_sys, | 131 | .notifier_call = scx200_wdt_notify_sys, |
128 | }; | 132 | }; |
129 | 133 | ||
@@ -131,8 +135,7 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data, | |||
131 | size_t len, loff_t *ppos) | 135 | size_t len, loff_t *ppos) |
132 | { | 136 | { |
133 | /* check for a magic close character */ | 137 | /* check for a magic close character */ |
134 | if (len) | 138 | if (len) { |
135 | { | ||
136 | size_t i; | 139 | size_t i; |
137 | 140 | ||
138 | scx200_wdt_ping(); | 141 | scx200_wdt_ping(); |
@@ -140,7 +143,7 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data, | |||
140 | expect_close = 0; | 143 | expect_close = 0; |
141 | for (i = 0; i < len; ++i) { | 144 | for (i = 0; i < len; ++i) { |
142 | char c; | 145 | char c; |
143 | if (get_user(c, data+i)) | 146 | if (get_user(c, data + i)) |
144 | return -EFAULT; | 147 | return -EFAULT; |
145 | if (c == 'V') | 148 | if (c == 'V') |
146 | expect_close = 42; | 149 | expect_close = 42; |
@@ -152,23 +155,21 @@ static ssize_t scx200_wdt_write(struct file *file, const char __user *data, | |||
152 | return 0; | 155 | return 0; |
153 | } | 156 | } |
154 | 157 | ||
155 | static int scx200_wdt_ioctl(struct inode *inode, struct file *file, | 158 | static long scx200_wdt_ioctl(struct file *file, unsigned int cmd, |
156 | unsigned int cmd, unsigned long arg) | 159 | unsigned long arg) |
157 | { | 160 | { |
158 | void __user *argp = (void __user *)arg; | 161 | void __user *argp = (void __user *)arg; |
159 | int __user *p = argp; | 162 | int __user *p = argp; |
160 | static struct watchdog_info ident = { | 163 | static const struct watchdog_info ident = { |
161 | .identity = "NatSemi SCx200 Watchdog", | 164 | .identity = "NatSemi SCx200 Watchdog", |
162 | .firmware_version = 1, | 165 | .firmware_version = 1, |
163 | .options = (WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING), | 166 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, |
164 | }; | 167 | }; |
165 | int new_margin; | 168 | int new_margin; |
166 | 169 | ||
167 | switch (cmd) { | 170 | switch (cmd) { |
168 | default: | ||
169 | return -ENOTTY; | ||
170 | case WDIOC_GETSUPPORT: | 171 | case WDIOC_GETSUPPORT: |
171 | if(copy_to_user(argp, &ident, sizeof(ident))) | 172 | if (copy_to_user(argp, &ident, sizeof(ident))) |
172 | return -EFAULT; | 173 | return -EFAULT; |
173 | return 0; | 174 | return 0; |
174 | case WDIOC_GETSTATUS: | 175 | case WDIOC_GETSTATUS: |
@@ -191,22 +192,24 @@ static int scx200_wdt_ioctl(struct inode *inode, struct file *file, | |||
191 | if (put_user(margin, p)) | 192 | if (put_user(margin, p)) |
192 | return -EFAULT; | 193 | return -EFAULT; |
193 | return 0; | 194 | return 0; |
195 | default: | ||
196 | return -ENOTTY; | ||
194 | } | 197 | } |
195 | } | 198 | } |
196 | 199 | ||
197 | static const struct file_operations scx200_wdt_fops = { | 200 | static const struct file_operations scx200_wdt_fops = { |
198 | .owner = THIS_MODULE, | 201 | .owner = THIS_MODULE, |
199 | .llseek = no_llseek, | 202 | .llseek = no_llseek, |
200 | .write = scx200_wdt_write, | 203 | .write = scx200_wdt_write, |
201 | .ioctl = scx200_wdt_ioctl, | 204 | .unlocked_ioctl = scx200_wdt_ioctl, |
202 | .open = scx200_wdt_open, | 205 | .open = scx200_wdt_open, |
203 | .release = scx200_wdt_release, | 206 | .release = scx200_wdt_release, |
204 | }; | 207 | }; |
205 | 208 | ||
206 | static struct miscdevice scx200_wdt_miscdev = { | 209 | static struct miscdevice scx200_wdt_miscdev = { |
207 | .minor = WATCHDOG_MINOR, | 210 | .minor = WATCHDOG_MINOR, |
208 | .name = "watchdog", | 211 | .name = "watchdog", |
209 | .fops = &scx200_wdt_fops, | 212 | .fops = &scx200_wdt_fops, |
210 | }; | 213 | }; |
211 | 214 | ||
212 | static int __init scx200_wdt_init(void) | 215 | static int __init scx200_wdt_init(void) |
@@ -229,8 +232,6 @@ static int __init scx200_wdt_init(void) | |||
229 | scx200_wdt_update_margin(); | 232 | scx200_wdt_update_margin(); |
230 | scx200_wdt_disable(); | 233 | scx200_wdt_disable(); |
231 | 234 | ||
232 | sema_init(&open_semaphore, 1); | ||
233 | |||
234 | r = register_reboot_notifier(&scx200_wdt_notifier); | 235 | r = register_reboot_notifier(&scx200_wdt_notifier); |
235 | if (r) { | 236 | if (r) { |
236 | printk(KERN_ERR NAME ": unable to register reboot notifier"); | 237 | printk(KERN_ERR NAME ": unable to register reboot notifier"); |
@@ -263,7 +264,7 @@ module_exit(scx200_wdt_cleanup); | |||
263 | 264 | ||
264 | /* | 265 | /* |
265 | Local variables: | 266 | Local variables: |
266 | compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules" | 267 | compile-command: "make -k -C ../.. SUBDIRS=drivers/char modules" |
267 | c-basic-offset: 8 | 268 | c-basic-offset: 8 |
268 | End: | 269 | End: |
269 | */ | 270 | */ |
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c index 1277f7e9cc54..824125adf90a 100644 --- a/drivers/watchdog/shwdt.c +++ b/drivers/watchdog/shwdt.c | |||
@@ -28,9 +28,9 @@ | |||
28 | #include <linux/ioport.h> | 28 | #include <linux/ioport.h> |
29 | #include <linux/fs.h> | 29 | #include <linux/fs.h> |
30 | #include <linux/mm.h> | 30 | #include <linux/mm.h> |
31 | #include <asm/io.h> | 31 | #include <linux/io.h> |
32 | #include <asm/uaccess.h> | 32 | #include <linux/uaccess.h> |
33 | #include <asm/watchdog.h> | 33 | #include <linux/watchdog.h> |
34 | 34 | ||
35 | #define PFX "shwdt: " | 35 | #define PFX "shwdt: " |
36 | 36 | ||
@@ -72,6 +72,7 @@ static struct watchdog_info sh_wdt_info; | |||
72 | static char shwdt_expect_close; | 72 | static char shwdt_expect_close; |
73 | static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0); | 73 | static DEFINE_TIMER(timer, sh_wdt_ping, 0, 0); |
74 | static unsigned long next_heartbeat; | 74 | static unsigned long next_heartbeat; |
75 | static DEFINE_SPINLOCK(shwdt_lock); | ||
75 | 76 | ||
76 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ | 77 | #define WATCHDOG_HEARTBEAT 30 /* 30 sec default heartbeat */ |
77 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ | 78 | static int heartbeat = WATCHDOG_HEARTBEAT; /* in seconds */ |
@@ -86,6 +87,9 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
86 | static void sh_wdt_start(void) | 87 | static void sh_wdt_start(void) |
87 | { | 88 | { |
88 | __u8 csr; | 89 | __u8 csr; |
90 | unsigned long flags; | ||
91 | |||
92 | spin_lock_irqsave(&wdt_lock, flags); | ||
89 | 93 | ||
90 | next_heartbeat = jiffies + (heartbeat * HZ); | 94 | next_heartbeat = jiffies + (heartbeat * HZ); |
91 | mod_timer(&timer, next_ping_period(clock_division_ratio)); | 95 | mod_timer(&timer, next_ping_period(clock_division_ratio)); |
@@ -123,6 +127,7 @@ static void sh_wdt_start(void) | |||
123 | csr &= ~RSTCSR_RSTS; | 127 | csr &= ~RSTCSR_RSTS; |
124 | sh_wdt_write_rstcsr(csr); | 128 | sh_wdt_write_rstcsr(csr); |
125 | #endif | 129 | #endif |
130 | spin_unlock_irqrestore(&wdt_lock, flags); | ||
126 | } | 131 | } |
127 | 132 | ||
128 | /** | 133 | /** |
@@ -132,12 +137,16 @@ static void sh_wdt_start(void) | |||
132 | static void sh_wdt_stop(void) | 137 | static void sh_wdt_stop(void) |
133 | { | 138 | { |
134 | __u8 csr; | 139 | __u8 csr; |
140 | unsigned long flags; | ||
141 | |||
142 | spin_lock_irqsave(&wdt_lock, flags); | ||
135 | 143 | ||
136 | del_timer(&timer); | 144 | del_timer(&timer); |
137 | 145 | ||
138 | csr = sh_wdt_read_csr(); | 146 | csr = sh_wdt_read_csr(); |
139 | csr &= ~WTCSR_TME; | 147 | csr &= ~WTCSR_TME; |
140 | sh_wdt_write_csr(csr); | 148 | sh_wdt_write_csr(csr); |
149 | spin_unlock_irqrestore(&wdt_lock, flags); | ||
141 | } | 150 | } |
142 | 151 | ||
143 | /** | 152 | /** |
@@ -146,7 +155,11 @@ static void sh_wdt_stop(void) | |||
146 | */ | 155 | */ |
147 | static inline void sh_wdt_keepalive(void) | 156 | static inline void sh_wdt_keepalive(void) |
148 | { | 157 | { |
158 | unsigned long flags; | ||
159 | |||
160 | spin_lock_irqsave(&wdt_lock, flags); | ||
149 | next_heartbeat = jiffies + (heartbeat * HZ); | 161 | next_heartbeat = jiffies + (heartbeat * HZ); |
162 | spin_unlock_irqrestore(&wdt_lock, flags); | ||
150 | } | 163 | } |
151 | 164 | ||
152 | /** | 165 | /** |
@@ -155,10 +168,14 @@ static inline void sh_wdt_keepalive(void) | |||
155 | */ | 168 | */ |
156 | static int sh_wdt_set_heartbeat(int t) | 169 | static int sh_wdt_set_heartbeat(int t) |
157 | { | 170 | { |
158 | if (unlikely((t < 1) || (t > 3600))) /* arbitrary upper limit */ | 171 | unsigned long flags; |
172 | |||
173 | if (unlikely(t < 1 || t > 3600)) /* arbitrary upper limit */ | ||
159 | return -EINVAL; | 174 | return -EINVAL; |
160 | 175 | ||
176 | spin_lock_irqsave(&wdt_lock, flags); | ||
161 | heartbeat = t; | 177 | heartbeat = t; |
178 | spin_unlock_irqrestore(&wdt_lock, flags); | ||
162 | return 0; | 179 | return 0; |
163 | } | 180 | } |
164 | 181 | ||
@@ -170,6 +187,9 @@ static int sh_wdt_set_heartbeat(int t) | |||
170 | */ | 187 | */ |
171 | static void sh_wdt_ping(unsigned long data) | 188 | static void sh_wdt_ping(unsigned long data) |
172 | { | 189 | { |
190 | unsigned long flags; | ||
191 | |||
192 | spin_lock_irqsave(&wdt_lock, flags); | ||
173 | if (time_before(jiffies, next_heartbeat)) { | 193 | if (time_before(jiffies, next_heartbeat)) { |
174 | __u8 csr; | 194 | __u8 csr; |
175 | 195 | ||
@@ -183,6 +203,7 @@ static void sh_wdt_ping(unsigned long data) | |||
183 | } else | 203 | } else |
184 | printk(KERN_WARNING PFX "Heartbeat lost! Will not ping " | 204 | printk(KERN_WARNING PFX "Heartbeat lost! Will not ping " |
185 | "the watchdog\n"); | 205 | "the watchdog\n"); |
206 | spin_unlock_irqrestore(&wdt_lock, flags); | ||
186 | } | 207 | } |
187 | 208 | ||
188 | /** | 209 | /** |
@@ -310,7 +331,6 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma) | |||
310 | 331 | ||
311 | /** | 332 | /** |
312 | * sh_wdt_ioctl - Query Device | 333 | * sh_wdt_ioctl - Query Device |
313 | * @inode: inode of device | ||
314 | * @file: file handle of device | 334 | * @file: file handle of device |
315 | * @cmd: watchdog command | 335 | * @cmd: watchdog command |
316 | * @arg: argument | 336 | * @arg: argument |
@@ -318,53 +338,51 @@ static int sh_wdt_mmap(struct file *file, struct vm_area_struct *vma) | |||
318 | * Query basic information from the device or ping it, as outlined by the | 338 | * Query basic information from the device or ping it, as outlined by the |
319 | * watchdog API. | 339 | * watchdog API. |
320 | */ | 340 | */ |
321 | static int sh_wdt_ioctl(struct inode *inode, struct file *file, | 341 | static long sh_wdt_ioctl(struct file *file, unsigned int cmd, |
322 | unsigned int cmd, unsigned long arg) | 342 | unsigned long arg) |
323 | { | 343 | { |
324 | int new_heartbeat; | 344 | int new_heartbeat; |
325 | int options, retval = -EINVAL; | 345 | int options, retval = -EINVAL; |
326 | 346 | ||
327 | switch (cmd) { | 347 | switch (cmd) { |
328 | case WDIOC_GETSUPPORT: | 348 | case WDIOC_GETSUPPORT: |
329 | return copy_to_user((struct watchdog_info *)arg, | 349 | return copy_to_user((struct watchdog_info *)arg, |
330 | &sh_wdt_info, | 350 | &sh_wdt_info, sizeof(sh_wdt_info)) ? -EFAULT : 0; |
331 | sizeof(sh_wdt_info)) ? -EFAULT : 0; | 351 | case WDIOC_GETSTATUS: |
332 | case WDIOC_GETSTATUS: | 352 | case WDIOC_GETBOOTSTATUS: |
333 | case WDIOC_GETBOOTSTATUS: | 353 | return put_user(0, (int *)arg); |
334 | return put_user(0, (int *)arg); | 354 | case WDIOC_SETOPTIONS: |
335 | case WDIOC_KEEPALIVE: | 355 | if (get_user(options, (int *)arg)) |
336 | sh_wdt_keepalive(); | 356 | return -EFAULT; |
337 | return 0; | 357 | |
338 | case WDIOC_SETTIMEOUT: | 358 | if (options & WDIOS_DISABLECARD) { |
339 | if (get_user(new_heartbeat, (int *)arg)) | 359 | sh_wdt_stop(); |
340 | return -EFAULT; | 360 | retval = 0; |
341 | 361 | } | |
342 | if (sh_wdt_set_heartbeat(new_heartbeat)) | ||
343 | return -EINVAL; | ||
344 | |||
345 | sh_wdt_keepalive(); | ||
346 | /* Fall */ | ||
347 | case WDIOC_GETTIMEOUT: | ||
348 | return put_user(heartbeat, (int *)arg); | ||
349 | case WDIOC_SETOPTIONS: | ||
350 | if (get_user(options, (int *)arg)) | ||
351 | return -EFAULT; | ||
352 | |||
353 | if (options & WDIOS_DISABLECARD) { | ||
354 | sh_wdt_stop(); | ||
355 | retval = 0; | ||
356 | } | ||
357 | 362 | ||
358 | if (options & WDIOS_ENABLECARD) { | 363 | if (options & WDIOS_ENABLECARD) { |
359 | sh_wdt_start(); | 364 | sh_wdt_start(); |
360 | retval = 0; | 365 | retval = 0; |
361 | } | 366 | } |
362 | 367 | ||
363 | return retval; | 368 | return retval; |
364 | default: | 369 | case WDIOC_KEEPALIVE: |
365 | return -ENOTTY; | 370 | sh_wdt_keepalive(); |
366 | } | 371 | return 0; |
372 | case WDIOC_SETTIMEOUT: | ||
373 | if (get_user(new_heartbeat, (int *)arg)) | ||
374 | return -EFAULT; | ||
375 | |||
376 | if (sh_wdt_set_heartbeat(new_heartbeat)) | ||
377 | return -EINVAL; | ||
367 | 378 | ||
379 | sh_wdt_keepalive(); | ||
380 | /* Fall */ | ||
381 | case WDIOC_GETTIMEOUT: | ||
382 | return put_user(heartbeat, (int *)arg); | ||
383 | default: | ||
384 | return -ENOTTY; | ||
385 | } | ||
368 | return 0; | 386 | return 0; |
369 | } | 387 | } |
370 | 388 | ||
@@ -390,13 +408,13 @@ static const struct file_operations sh_wdt_fops = { | |||
390 | .owner = THIS_MODULE, | 408 | .owner = THIS_MODULE, |
391 | .llseek = no_llseek, | 409 | .llseek = no_llseek, |
392 | .write = sh_wdt_write, | 410 | .write = sh_wdt_write, |
393 | .ioctl = sh_wdt_ioctl, | 411 | .unlocked_ioctl = sh_wdt_ioctl, |
394 | .open = sh_wdt_open, | 412 | .open = sh_wdt_open, |
395 | .release = sh_wdt_close, | 413 | .release = sh_wdt_close, |
396 | .mmap = sh_wdt_mmap, | 414 | .mmap = sh_wdt_mmap, |
397 | }; | 415 | }; |
398 | 416 | ||
399 | static struct watchdog_info sh_wdt_info = { | 417 | static const struct watchdog_info sh_wdt_info = { |
400 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | | 418 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
401 | WDIOF_MAGICCLOSE, | 419 | WDIOF_MAGICCLOSE, |
402 | .firmware_version = 1, | 420 | .firmware_version = 1, |
@@ -422,30 +440,33 @@ static int __init sh_wdt_init(void) | |||
422 | { | 440 | { |
423 | int rc; | 441 | int rc; |
424 | 442 | ||
425 | if ((clock_division_ratio < 0x5) || (clock_division_ratio > 0x7)) { | 443 | if (clock_division_ratio < 0x5 || clock_division_ratio > 0x7) { |
426 | clock_division_ratio = WTCSR_CKS_4096; | 444 | clock_division_ratio = WTCSR_CKS_4096; |
427 | printk(KERN_INFO PFX "clock_division_ratio value must " | 445 | printk(KERN_INFO PFX |
428 | "be 0x5<=x<=0x7, using %d\n", clock_division_ratio); | 446 | "clock_division_ratio value must be 0x5<=x<=0x7, using %d\n", |
447 | clock_division_ratio); | ||
429 | } | 448 | } |
430 | 449 | ||
431 | rc = sh_wdt_set_heartbeat(heartbeat); | 450 | rc = sh_wdt_set_heartbeat(heartbeat); |
432 | if (unlikely(rc)) { | 451 | if (unlikely(rc)) { |
433 | heartbeat = WATCHDOG_HEARTBEAT; | 452 | heartbeat = WATCHDOG_HEARTBEAT; |
434 | printk(KERN_INFO PFX "heartbeat value must " | 453 | printk(KERN_INFO PFX |
435 | "be 1<=x<=3600, using %d\n", heartbeat); | 454 | "heartbeat value must be 1<=x<=3600, using %d\n", |
455 | heartbeat); | ||
436 | } | 456 | } |
437 | 457 | ||
438 | rc = register_reboot_notifier(&sh_wdt_notifier); | 458 | rc = register_reboot_notifier(&sh_wdt_notifier); |
439 | if (unlikely(rc)) { | 459 | if (unlikely(rc)) { |
440 | printk(KERN_ERR PFX "Can't register reboot notifier (err=%d)\n", | 460 | printk(KERN_ERR PFX |
441 | rc); | 461 | "Can't register reboot notifier (err=%d)\n", rc); |
442 | return rc; | 462 | return rc; |
443 | } | 463 | } |
444 | 464 | ||
445 | rc = misc_register(&sh_wdt_miscdev); | 465 | rc = misc_register(&sh_wdt_miscdev); |
446 | if (unlikely(rc)) { | 466 | if (unlikely(rc)) { |
447 | printk(KERN_ERR PFX "Can't register miscdev on " | 467 | printk(KERN_ERR PFX |
448 | "minor=%d (err=%d)\n", sh_wdt_miscdev.minor, rc); | 468 | "Can't register miscdev on minor=%d (err=%d)\n", |
469 | sh_wdt_miscdev.minor, rc); | ||
449 | unregister_reboot_notifier(&sh_wdt_notifier); | 470 | unregister_reboot_notifier(&sh_wdt_notifier); |
450 | return rc; | 471 | return rc; |
451 | } | 472 | } |
@@ -476,10 +497,14 @@ module_param(clock_division_ratio, int, 0); | |||
476 | MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")"); | 497 | MODULE_PARM_DESC(clock_division_ratio, "Clock division ratio. Valid ranges are from 0x5 (1.31ms) to 0x7 (5.25ms). (default=" __MODULE_STRING(clock_division_ratio) ")"); |
477 | 498 | ||
478 | module_param(heartbeat, int, 0); | 499 | module_param(heartbeat, int, 0); |
479 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds. (1<=heartbeat<=3600, default=" __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | 500 | MODULE_PARM_DESC(heartbeat, |
501 | "Watchdog heartbeat in seconds. (1 <= heartbeat <= 3600, default=" | ||
502 | __MODULE_STRING(WATCHDOG_HEARTBEAT) ")"); | ||
480 | 503 | ||
481 | module_param(nowayout, int, 0); | 504 | module_param(nowayout, int, 0); |
482 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 505 | MODULE_PARM_DESC(nowayout, |
506 | "Watchdog cannot be stopped once started (default=" | ||
507 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
483 | 508 | ||
484 | module_init(sh_wdt_init); | 509 | module_init(sh_wdt_init); |
485 | module_exit(sh_wdt_exit); | 510 | module_exit(sh_wdt_exit); |
diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c index 5d2b5ba61414..988ff1d5b4be 100644 --- a/drivers/watchdog/smsc37b787_wdt.c +++ b/drivers/watchdog/smsc37b787_wdt.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * History: | 18 | * History: |
19 | * 2003 - Created version 1.0 for Linux 2.4.x. | 19 | * 2003 - Created version 1.0 for Linux 2.4.x. |
20 | * 2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE | 20 | * 2006 - Ported to Linux 2.6, added nowayout and MAGICCLOSE |
21 | * features. Released version 1.1 | 21 | * features. Released version 1.1 |
22 | * | 22 | * |
23 | * Theory of operation: | 23 | * Theory of operation: |
24 | * | 24 | * |
@@ -55,9 +55,9 @@ | |||
55 | #include <linux/reboot.h> | 55 | #include <linux/reboot.h> |
56 | #include <linux/init.h> | 56 | #include <linux/init.h> |
57 | #include <linux/spinlock.h> | 57 | #include <linux/spinlock.h> |
58 | #include <linux/io.h> | ||
59 | #include <linux/uaccess.h> | ||
58 | 60 | ||
59 | #include <asm/io.h> | ||
60 | #include <asm/uaccess.h> | ||
61 | #include <asm/system.h> | 61 | #include <asm/system.h> |
62 | 62 | ||
63 | /* enable support for minutes as units? */ | 63 | /* enable support for minutes as units? */ |
@@ -71,15 +71,15 @@ | |||
71 | #define UNIT_MINUTE 1 | 71 | #define UNIT_MINUTE 1 |
72 | 72 | ||
73 | #define MODNAME "smsc37b787_wdt: " | 73 | #define MODNAME "smsc37b787_wdt: " |
74 | #define VERSION "1.1" | 74 | #define VERSION "1.1" |
75 | 75 | ||
76 | #define IOPORT 0x3F0 | 76 | #define IOPORT 0x3F0 |
77 | #define IOPORT_SIZE 2 | 77 | #define IOPORT_SIZE 2 |
78 | #define IODEV_NO 8 | 78 | #define IODEV_NO 8 |
79 | 79 | ||
80 | static int unit = UNIT_SECOND; /* timer's unit */ | 80 | static int unit = UNIT_SECOND; /* timer's unit */ |
81 | static int timeout = 60; /* timeout value: default is 60 "units" */ | 81 | static int timeout = 60; /* timeout value: default is 60 "units" */ |
82 | static unsigned long timer_enabled = 0; /* is the timer enabled? */ | 82 | static unsigned long timer_enabled; /* is the timer enabled? */ |
83 | 83 | ||
84 | static char expect_close; /* is the close expected? */ | 84 | static char expect_close; /* is the close expected? */ |
85 | 85 | ||
@@ -93,114 +93,121 @@ static int nowayout = WATCHDOG_NOWAYOUT; | |||
93 | 93 | ||
94 | static inline void open_io_config(void) | 94 | static inline void open_io_config(void) |
95 | { | 95 | { |
96 | outb(0x55, IOPORT); | 96 | outb(0x55, IOPORT); |
97 | mdelay(1); | 97 | mdelay(1); |
98 | outb(0x55, IOPORT); | 98 | outb(0x55, IOPORT); |
99 | } | 99 | } |
100 | 100 | ||
101 | /* lock the IO chip */ | 101 | /* lock the IO chip */ |
102 | static inline void close_io_config(void) | 102 | static inline void close_io_config(void) |
103 | { | 103 | { |
104 | outb(0xAA, IOPORT); | 104 | outb(0xAA, IOPORT); |
105 | } | 105 | } |
106 | 106 | ||
107 | /* select the IO device */ | 107 | /* select the IO device */ |
108 | static inline void select_io_device(unsigned char devno) | 108 | static inline void select_io_device(unsigned char devno) |
109 | { | 109 | { |
110 | outb(0x07, IOPORT); | 110 | outb(0x07, IOPORT); |
111 | outb(devno, IOPORT+1); | 111 | outb(devno, IOPORT+1); |
112 | } | 112 | } |
113 | 113 | ||
114 | /* write to the control register */ | 114 | /* write to the control register */ |
115 | static inline void write_io_cr(unsigned char reg, unsigned char data) | 115 | static inline void write_io_cr(unsigned char reg, unsigned char data) |
116 | { | 116 | { |
117 | outb(reg, IOPORT); | 117 | outb(reg, IOPORT); |
118 | outb(data, IOPORT+1); | 118 | outb(data, IOPORT+1); |
119 | } | 119 | } |
120 | 120 | ||
121 | /* read from the control register */ | 121 | /* read from the control register */ |
122 | static inline char read_io_cr(unsigned char reg) | 122 | static inline char read_io_cr(unsigned char reg) |
123 | { | 123 | { |
124 | outb(reg, IOPORT); | 124 | outb(reg, IOPORT); |
125 | return inb(IOPORT+1); | 125 | return inb(IOPORT+1); |
126 | } | 126 | } |
127 | 127 | ||
128 | /* -- Medium level functions ------------------------------------*/ | 128 | /* -- Medium level functions ------------------------------------*/ |
129 | 129 | ||
130 | static inline void gpio_bit12(unsigned char reg) | 130 | static inline void gpio_bit12(unsigned char reg) |
131 | { | 131 | { |
132 | // -- General Purpose I/O Bit 1.2 -- | 132 | /* -- General Purpose I/O Bit 1.2 -- |
133 | // Bit 0, In/Out: 0 = Output, 1 = Input | 133 | * Bit 0, In/Out: 0 = Output, 1 = Input |
134 | // Bit 1, Polarity: 0 = No Invert, 1 = Invert | 134 | * Bit 1, Polarity: 0 = No Invert, 1 = Invert |
135 | // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable | 135 | * Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable |
136 | // Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17, | 136 | * Bit 3/4, Function select: 00 = GPI/O, 01 = WDT, 10 = P17, |
137 | // 11 = Either Edge Triggered Intr. 2 | 137 | * 11 = Either Edge Triggered Intr. 2 |
138 | // Bit 5/6 (Reserved) | 138 | * Bit 5/6 (Reserved) |
139 | // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain | 139 | * Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain |
140 | write_io_cr(0xE2, reg); | 140 | */ |
141 | write_io_cr(0xE2, reg); | ||
141 | } | 142 | } |
142 | 143 | ||
143 | static inline void gpio_bit13(unsigned char reg) | 144 | static inline void gpio_bit13(unsigned char reg) |
144 | { | 145 | { |
145 | // -- General Purpose I/O Bit 1.3 -- | 146 | /* -- General Purpose I/O Bit 1.3 -- |
146 | // Bit 0, In/Out: 0 = Output, 1 = Input | 147 | * Bit 0, In/Out: 0 = Output, 1 = Input |
147 | // Bit 1, Polarity: 0 = No Invert, 1 = Invert | 148 | * Bit 1, Polarity: 0 = No Invert, 1 = Invert |
148 | // Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable | 149 | * Bit 2, Group Enable Intr.: 0 = Disable, 1 = Enable |
149 | // Bit 3, Function select: 0 = GPI/O, 1 = LED | 150 | * Bit 3, Function select: 0 = GPI/O, 1 = LED |
150 | // Bit 4-6 (Reserved) | 151 | * Bit 4-6 (Reserved) |
151 | // Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain | 152 | * Bit 7, Output Type: 0 = Push Pull Bit, 1 = Open Drain |
152 | write_io_cr(0xE3, reg); | 153 | */ |
154 | write_io_cr(0xE3, reg); | ||
153 | } | 155 | } |
154 | 156 | ||
155 | static inline void wdt_timer_units(unsigned char new_units) | 157 | static inline void wdt_timer_units(unsigned char new_units) |
156 | { | 158 | { |
157 | // -- Watchdog timer units -- | 159 | /* -- Watchdog timer units -- |
158 | // Bit 0-6 (Reserved) | 160 | * Bit 0-6 (Reserved) |
159 | // Bit 7, WDT Time-out Value Units Select | 161 | * Bit 7, WDT Time-out Value Units Select |
160 | // (0 = Minutes, 1 = Seconds) | 162 | * (0 = Minutes, 1 = Seconds) |
161 | write_io_cr(0xF1, new_units); | 163 | */ |
164 | write_io_cr(0xF1, new_units); | ||
162 | } | 165 | } |
163 | 166 | ||
164 | static inline void wdt_timeout_value(unsigned char new_timeout) | 167 | static inline void wdt_timeout_value(unsigned char new_timeout) |
165 | { | 168 | { |
166 | // -- Watchdog Timer Time-out Value -- | 169 | /* -- Watchdog Timer Time-out Value -- |
167 | // Bit 0-7 Binary coded units (0=Disabled, 1..255) | 170 | * Bit 0-7 Binary coded units (0=Disabled, 1..255) |
168 | write_io_cr(0xF2, new_timeout); | 171 | */ |
172 | write_io_cr(0xF2, new_timeout); | ||
169 | } | 173 | } |
170 | 174 | ||
171 | static inline void wdt_timer_conf(unsigned char conf) | 175 | static inline void wdt_timer_conf(unsigned char conf) |
172 | { | 176 | { |
173 | // -- Watchdog timer configuration -- | 177 | /* -- Watchdog timer configuration -- |
174 | // Bit 0 Joystick enable: 0* = No Reset, 1 = Reset WDT upon Gameport I/O | 178 | * Bit 0 Joystick enable: 0* = No Reset, 1 = Reset WDT upon |
175 | // Bit 1 Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr. | 179 | * Gameport I/O |
176 | // Bit 2 Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr. | 180 | * Bit 1 Keyboard enable: 0* = No Reset, 1 = Reset WDT upon KBD Intr. |
177 | // Bit 3 Reset the timer | 181 | * Bit 2 Mouse enable: 0* = No Reset, 1 = Reset WDT upon Mouse Intr |
178 | // (Wrong in SMsC documentation? Given as: PowerLED Timout Enabled) | 182 | * Bit 3 Reset the timer |
179 | // Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled, | 183 | * (Wrong in SMsC documentation? Given as: PowerLED Timout |
180 | // 0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15) | 184 | * Enabled) |
181 | write_io_cr(0xF3, conf); | 185 | * Bit 4-7 WDT Interrupt Mapping: (0000* = Disabled, |
186 | * 0001=IRQ1, 0010=(Invalid), 0011=IRQ3 to 1111=IRQ15) | ||
187 | */ | ||
188 | write_io_cr(0xF3, conf); | ||
182 | } | 189 | } |
183 | 190 | ||
184 | static inline void wdt_timer_ctrl(unsigned char reg) | 191 | static inline void wdt_timer_ctrl(unsigned char reg) |
185 | { | 192 | { |
186 | // -- Watchdog timer control -- | 193 | /* -- Watchdog timer control -- |
187 | // Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured | 194 | * Bit 0 Status Bit: 0 = Timer counting, 1 = Timeout occured |
188 | // Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz | 195 | * Bit 1 Power LED Toggle: 0 = Disable Toggle, 1 = Toggle at 1 Hz |
189 | // Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) | 196 | * Bit 2 Force Timeout: 1 = Forces WD timeout event (self-cleaning) |
190 | // Bit 3 P20 Force Timeout enabled: | 197 | * Bit 3 P20 Force Timeout enabled: |
191 | // 0 = P20 activity does not generate the WD timeout event | 198 | * 0 = P20 activity does not generate the WD timeout event |
192 | // 1 = P20 Allows rising edge of P20, from the keyboard | 199 | * 1 = P20 Allows rising edge of P20, from the keyboard |
193 | // controller, to force the WD timeout event. | 200 | * controller, to force the WD timeout event. |
194 | // Bit 4 (Reserved) | 201 | * Bit 4 (Reserved) |
195 | // -- Soft power management -- | 202 | * -- Soft power management -- |
196 | // Bit 5 Stop Counter: 1 = Stop software power down counter | 203 | * Bit 5 Stop Counter: 1 = Stop software power down counter |
197 | // set via register 0xB8, (self-cleaning) | 204 | * set via register 0xB8, (self-cleaning) |
198 | // (Upon read: 0 = Counter running, 1 = Counter stopped) | 205 | * (Upon read: 0 = Counter running, 1 = Counter stopped) |
199 | // Bit 6 Restart Counter: 1 = Restart software power down counter | 206 | * Bit 6 Restart Counter: 1 = Restart software power down counter |
200 | // set via register 0xB8, (self-cleaning) | 207 | * set via register 0xB8, (self-cleaning) |
201 | // Bit 7 SPOFF: 1 = Force software power down (self-cleaning) | 208 | * Bit 7 SPOFF: 1 = Force software power down (self-cleaning) |
202 | 209 | */ | |
203 | write_io_cr(0xF4, reg); | 210 | write_io_cr(0xF4, reg); |
204 | } | 211 | } |
205 | 212 | ||
206 | /* -- Higher level functions ------------------------------------*/ | 213 | /* -- Higher level functions ------------------------------------*/ |
@@ -209,33 +216,34 @@ static inline void wdt_timer_ctrl(unsigned char reg) | |||
209 | 216 | ||
210 | static void wb_smsc_wdt_initialize(void) | 217 | static void wb_smsc_wdt_initialize(void) |
211 | { | 218 | { |
212 | unsigned char old; | 219 | unsigned char old; |
213 | 220 | ||
214 | spin_lock(&io_lock); | 221 | spin_lock(&io_lock); |
215 | open_io_config(); | 222 | open_io_config(); |
216 | select_io_device(IODEV_NO); | 223 | select_io_device(IODEV_NO); |
217 | 224 | ||
218 | // enable the watchdog | 225 | /* enable the watchdog */ |
219 | gpio_bit13(0x08); // Select pin 80 = LED not GPIO | 226 | gpio_bit13(0x08); /* Select pin 80 = LED not GPIO */ |
220 | gpio_bit12(0x0A); // Set pin 79 = WDT not GPIO/Output/Polarity=Invert | 227 | gpio_bit12(0x0A); /* Set pin 79 = WDT not |
228 | GPIO/Output/Polarity=Invert */ | ||
229 | /* disable the timeout */ | ||
230 | wdt_timeout_value(0); | ||
221 | 231 | ||
222 | // disable the timeout | 232 | /* reset control register */ |
223 | wdt_timeout_value(0); | 233 | wdt_timer_ctrl(0x00); |
224 | 234 | ||
225 | // reset control register | 235 | /* reset configuration register */ |
226 | wdt_timer_ctrl(0x00); | ||
227 | |||
228 | // reset configuration register | ||
229 | wdt_timer_conf(0x00); | 236 | wdt_timer_conf(0x00); |
230 | 237 | ||
231 | // read old (timer units) register | 238 | /* read old (timer units) register */ |
232 | old = read_io_cr(0xF1) & 0x7F; | 239 | old = read_io_cr(0xF1) & 0x7F; |
233 | if (unit == UNIT_SECOND) old |= 0x80; // set to seconds | 240 | if (unit == UNIT_SECOND) |
241 | old |= 0x80; /* set to seconds */ | ||
234 | 242 | ||
235 | // set the watchdog timer units | 243 | /* set the watchdog timer units */ |
236 | wdt_timer_units(old); | 244 | wdt_timer_units(old); |
237 | 245 | ||
238 | close_io_config(); | 246 | close_io_config(); |
239 | spin_unlock(&io_lock); | 247 | spin_unlock(&io_lock); |
240 | } | 248 | } |
241 | 249 | ||
@@ -244,23 +252,23 @@ static void wb_smsc_wdt_initialize(void) | |||
244 | static void wb_smsc_wdt_shutdown(void) | 252 | static void wb_smsc_wdt_shutdown(void) |
245 | { | 253 | { |
246 | spin_lock(&io_lock); | 254 | spin_lock(&io_lock); |
247 | open_io_config(); | 255 | open_io_config(); |
248 | select_io_device(IODEV_NO); | 256 | select_io_device(IODEV_NO); |
249 | 257 | ||
250 | // disable the watchdog | 258 | /* disable the watchdog */ |
251 | gpio_bit13(0x09); | 259 | gpio_bit13(0x09); |
252 | gpio_bit12(0x09); | 260 | gpio_bit12(0x09); |
253 | 261 | ||
254 | // reset watchdog config register | 262 | /* reset watchdog config register */ |
255 | wdt_timer_conf(0x00); | 263 | wdt_timer_conf(0x00); |
256 | 264 | ||
257 | // reset watchdog control register | 265 | /* reset watchdog control register */ |
258 | wdt_timer_ctrl(0x00); | 266 | wdt_timer_ctrl(0x00); |
259 | 267 | ||
260 | // disable timeout | 268 | /* disable timeout */ |
261 | wdt_timeout_value(0x00); | 269 | wdt_timeout_value(0x00); |
262 | 270 | ||
263 | close_io_config(); | 271 | close_io_config(); |
264 | spin_unlock(&io_lock); | 272 | spin_unlock(&io_lock); |
265 | } | 273 | } |
266 | 274 | ||
@@ -269,16 +277,16 @@ static void wb_smsc_wdt_shutdown(void) | |||
269 | static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) | 277 | static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) |
270 | { | 278 | { |
271 | spin_lock(&io_lock); | 279 | spin_lock(&io_lock); |
272 | open_io_config(); | 280 | open_io_config(); |
273 | select_io_device(IODEV_NO); | 281 | select_io_device(IODEV_NO); |
274 | 282 | ||
275 | // set Power LED to blink, if we enable the timeout | 283 | /* set Power LED to blink, if we enable the timeout */ |
276 | wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02); | 284 | wdt_timer_ctrl((new_timeout == 0) ? 0x00 : 0x02); |
277 | 285 | ||
278 | // set timeout value | 286 | /* set timeout value */ |
279 | wdt_timeout_value(new_timeout); | 287 | wdt_timeout_value(new_timeout); |
280 | 288 | ||
281 | close_io_config(); | 289 | close_io_config(); |
282 | spin_unlock(&io_lock); | 290 | spin_unlock(&io_lock); |
283 | } | 291 | } |
284 | 292 | ||
@@ -286,32 +294,32 @@ static void wb_smsc_wdt_set_timeout(unsigned char new_timeout) | |||
286 | 294 | ||
287 | static unsigned char wb_smsc_wdt_get_timeout(void) | 295 | static unsigned char wb_smsc_wdt_get_timeout(void) |
288 | { | 296 | { |
289 | unsigned char set_timeout; | 297 | unsigned char set_timeout; |
290 | 298 | ||
291 | spin_lock(&io_lock); | 299 | spin_lock(&io_lock); |
292 | open_io_config(); | 300 | open_io_config(); |
293 | select_io_device(IODEV_NO); | 301 | select_io_device(IODEV_NO); |
294 | set_timeout = read_io_cr(0xF2); | 302 | set_timeout = read_io_cr(0xF2); |
295 | close_io_config(); | 303 | close_io_config(); |
296 | spin_unlock(&io_lock); | 304 | spin_unlock(&io_lock); |
297 | 305 | ||
298 | return set_timeout; | 306 | return set_timeout; |
299 | } | 307 | } |
300 | 308 | ||
301 | /* disable watchdog */ | 309 | /* disable watchdog */ |
302 | 310 | ||
303 | static void wb_smsc_wdt_disable(void) | 311 | static void wb_smsc_wdt_disable(void) |
304 | { | 312 | { |
305 | // set the timeout to 0 to disable the watchdog | 313 | /* set the timeout to 0 to disable the watchdog */ |
306 | wb_smsc_wdt_set_timeout(0); | 314 | wb_smsc_wdt_set_timeout(0); |
307 | } | 315 | } |
308 | 316 | ||
309 | /* enable watchdog by setting the current timeout */ | 317 | /* enable watchdog by setting the current timeout */ |
310 | 318 | ||
311 | static void wb_smsc_wdt_enable(void) | 319 | static void wb_smsc_wdt_enable(void) |
312 | { | 320 | { |
313 | // set the current timeout... | 321 | /* set the current timeout... */ |
314 | wb_smsc_wdt_set_timeout(timeout); | 322 | wb_smsc_wdt_set_timeout(timeout); |
315 | } | 323 | } |
316 | 324 | ||
317 | /* reset the timer */ | 325 | /* reset the timer */ |
@@ -319,14 +327,14 @@ static void wb_smsc_wdt_enable(void) | |||
319 | static void wb_smsc_wdt_reset_timer(void) | 327 | static void wb_smsc_wdt_reset_timer(void) |
320 | { | 328 | { |
321 | spin_lock(&io_lock); | 329 | spin_lock(&io_lock); |
322 | open_io_config(); | 330 | open_io_config(); |
323 | select_io_device(IODEV_NO); | 331 | select_io_device(IODEV_NO); |
324 | 332 | ||
325 | // reset the timer | 333 | /* reset the timer */ |
326 | wdt_timeout_value(timeout); | 334 | wdt_timeout_value(timeout); |
327 | wdt_timer_conf(0x08); | 335 | wdt_timer_conf(0x08); |
328 | 336 | ||
329 | close_io_config(); | 337 | close_io_config(); |
330 | spin_unlock(&io_lock); | 338 | spin_unlock(&io_lock); |
331 | } | 339 | } |
332 | 340 | ||
@@ -355,7 +363,9 @@ static int wb_smsc_wdt_open(struct inode *inode, struct file *file) | |||
355 | /* Reload and activate timer */ | 363 | /* Reload and activate timer */ |
356 | wb_smsc_wdt_enable(); | 364 | wb_smsc_wdt_enable(); |
357 | 365 | ||
358 | printk(KERN_INFO MODNAME "Watchdog enabled. Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); | 366 | printk(KERN_INFO MODNAME |
367 | "Watchdog enabled. Timeout set to %d %s.\n", | ||
368 | timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); | ||
359 | 369 | ||
360 | return nonseekable_open(inode, file); | 370 | return nonseekable_open(inode, file); |
361 | } | 371 | } |
@@ -367,10 +377,12 @@ static int wb_smsc_wdt_release(struct inode *inode, struct file *file) | |||
367 | /* Shut off the timer. */ | 377 | /* Shut off the timer. */ |
368 | 378 | ||
369 | if (expect_close == 42) { | 379 | if (expect_close == 42) { |
370 | wb_smsc_wdt_disable(); | 380 | wb_smsc_wdt_disable(); |
371 | printk(KERN_INFO MODNAME "Watchdog disabled, sleeping again...\n"); | 381 | printk(KERN_INFO MODNAME |
382 | "Watchdog disabled, sleeping again...\n"); | ||
372 | } else { | 383 | } else { |
373 | printk(KERN_CRIT MODNAME "Unexpected close, not stopping watchdog!\n"); | 384 | printk(KERN_CRIT MODNAME |
385 | "Unexpected close, not stopping watchdog!\n"); | ||
374 | wb_smsc_wdt_reset_timer(); | 386 | wb_smsc_wdt_reset_timer(); |
375 | } | 387 | } |
376 | 388 | ||
@@ -392,10 +404,11 @@ static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data, | |||
392 | /* reset expect flag */ | 404 | /* reset expect flag */ |
393 | expect_close = 0; | 405 | expect_close = 0; |
394 | 406 | ||
395 | /* scan to see whether or not we got the magic character */ | 407 | /* scan to see whether or not we got the |
408 | magic character */ | ||
396 | for (i = 0; i != len; i++) { | 409 | for (i = 0; i != len; i++) { |
397 | char c; | 410 | char c; |
398 | if (get_user(c, data+i)) | 411 | if (get_user(c, data + i)) |
399 | return -EFAULT; | 412 | return -EFAULT; |
400 | if (c == 'V') | 413 | if (c == 'V') |
401 | expect_close = 42; | 414 | expect_close = 42; |
@@ -410,8 +423,8 @@ static ssize_t wb_smsc_wdt_write(struct file *file, const char __user *data, | |||
410 | 423 | ||
411 | /* ioctl => control interface */ | 424 | /* ioctl => control interface */ |
412 | 425 | ||
413 | static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file, | 426 | static long wb_smsc_wdt_ioctl(struct file *file, |
414 | unsigned int cmd, unsigned long arg) | 427 | unsigned int cmd, unsigned long arg) |
415 | { | 428 | { |
416 | int new_timeout; | 429 | int new_timeout; |
417 | 430 | ||
@@ -420,89 +433,73 @@ static int wb_smsc_wdt_ioctl(struct inode *inode, struct file *file, | |||
420 | int __user *i; | 433 | int __user *i; |
421 | } uarg; | 434 | } uarg; |
422 | 435 | ||
423 | static struct watchdog_info ident = { | 436 | static const struct watchdog_info ident = { |
424 | .options = WDIOF_KEEPALIVEPING | | 437 | .options = WDIOF_KEEPALIVEPING | |
425 | WDIOF_SETTIMEOUT | | 438 | WDIOF_SETTIMEOUT | |
426 | WDIOF_MAGICCLOSE, | 439 | WDIOF_MAGICCLOSE, |
427 | .firmware_version = 0, | 440 | .firmware_version = 0, |
428 | .identity = "SMsC 37B787 Watchdog" | 441 | .identity = "SMsC 37B787 Watchdog", |
429 | }; | 442 | }; |
430 | 443 | ||
431 | uarg.i = (int __user *)arg; | 444 | uarg.i = (int __user *)arg; |
432 | 445 | ||
433 | switch (cmd) { | 446 | switch (cmd) { |
434 | default: | 447 | case WDIOC_GETSUPPORT: |
435 | return -ENOTTY; | 448 | return copy_to_user(uarg.ident, &ident, sizeof(ident)) |
436 | 449 | ? -EFAULT : 0; | |
437 | case WDIOC_GETSUPPORT: | 450 | case WDIOC_GETSTATUS: |
438 | return copy_to_user(uarg.ident, &ident, | 451 | return put_user(wb_smsc_wdt_status(), uarg.i); |
439 | sizeof(ident)) ? -EFAULT : 0; | 452 | case WDIOC_GETBOOTSTATUS: |
440 | 453 | return put_user(0, uarg.i); | |
441 | case WDIOC_GETSTATUS: | 454 | case WDIOC_SETOPTIONS: |
442 | return put_user(wb_smsc_wdt_status(), uarg.i); | 455 | { |
443 | 456 | int options, retval = -EINVAL; | |
444 | case WDIOC_GETBOOTSTATUS: | ||
445 | return put_user(0, uarg.i); | ||
446 | |||
447 | case WDIOC_KEEPALIVE: | ||
448 | wb_smsc_wdt_reset_timer(); | ||
449 | return 0; | ||
450 | |||
451 | case WDIOC_SETTIMEOUT: | ||
452 | if (get_user(new_timeout, uarg.i)) | ||
453 | return -EFAULT; | ||
454 | |||
455 | // the API states this is given in secs | ||
456 | if (unit == UNIT_MINUTE) | ||
457 | new_timeout /= 60; | ||
458 | |||
459 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | ||
460 | return -EINVAL; | ||
461 | |||
462 | timeout = new_timeout; | ||
463 | wb_smsc_wdt_set_timeout(timeout); | ||
464 | |||
465 | // fall through and return the new timeout... | ||
466 | |||
467 | case WDIOC_GETTIMEOUT: | ||
468 | |||
469 | new_timeout = timeout; | ||
470 | |||
471 | if (unit == UNIT_MINUTE) | ||
472 | new_timeout *= 60; | ||
473 | |||
474 | return put_user(new_timeout, uarg.i); | ||
475 | |||
476 | case WDIOC_SETOPTIONS: | ||
477 | { | ||
478 | int options, retval = -EINVAL; | ||
479 | |||
480 | if (get_user(options, uarg.i)) | ||
481 | return -EFAULT; | ||
482 | |||
483 | if (options & WDIOS_DISABLECARD) { | ||
484 | wb_smsc_wdt_disable(); | ||
485 | retval = 0; | ||
486 | } | ||
487 | 457 | ||
488 | if (options & WDIOS_ENABLECARD) { | 458 | if (get_user(options, uarg.i)) |
489 | wb_smsc_wdt_enable(); | 459 | return -EFAULT; |
490 | retval = 0; | ||
491 | } | ||
492 | 460 | ||
493 | return retval; | 461 | if (options & WDIOS_DISABLECARD) { |
462 | wb_smsc_wdt_disable(); | ||
463 | retval = 0; | ||
464 | } | ||
465 | if (options & WDIOS_ENABLECARD) { | ||
466 | wb_smsc_wdt_enable(); | ||
467 | retval = 0; | ||
494 | } | 468 | } |
469 | return retval; | ||
470 | } | ||
471 | case WDIOC_KEEPALIVE: | ||
472 | wb_smsc_wdt_reset_timer(); | ||
473 | return 0; | ||
474 | case WDIOC_SETTIMEOUT: | ||
475 | if (get_user(new_timeout, uarg.i)) | ||
476 | return -EFAULT; | ||
477 | /* the API states this is given in secs */ | ||
478 | if (unit == UNIT_MINUTE) | ||
479 | new_timeout /= 60; | ||
480 | if (new_timeout < 0 || new_timeout > MAX_TIMEOUT) | ||
481 | return -EINVAL; | ||
482 | timeout = new_timeout; | ||
483 | wb_smsc_wdt_set_timeout(timeout); | ||
484 | /* fall through and return the new timeout... */ | ||
485 | case WDIOC_GETTIMEOUT: | ||
486 | new_timeout = timeout; | ||
487 | if (unit == UNIT_MINUTE) | ||
488 | new_timeout *= 60; | ||
489 | return put_user(new_timeout, uarg.i); | ||
490 | default: | ||
491 | return -ENOTTY; | ||
495 | } | 492 | } |
496 | } | 493 | } |
497 | 494 | ||
498 | /* -- Notifier funtions -----------------------------------------*/ | 495 | /* -- Notifier funtions -----------------------------------------*/ |
499 | 496 | ||
500 | static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 497 | static int wb_smsc_wdt_notify_sys(struct notifier_block *this, |
498 | unsigned long code, void *unused) | ||
501 | { | 499 | { |
502 | if (code == SYS_DOWN || code == SYS_HALT) | 500 | if (code == SYS_DOWN || code == SYS_HALT) { |
503 | { | 501 | /* set timeout to 0, to avoid possible race-condition */ |
504 | // set timeout to 0, to avoid possible race-condition | 502 | timeout = 0; |
505 | timeout = 0; | ||
506 | wb_smsc_wdt_disable(); | 503 | wb_smsc_wdt_disable(); |
507 | } | 504 | } |
508 | return NOTIFY_DONE; | 505 | return NOTIFY_DONE; |
@@ -510,23 +507,20 @@ static int wb_smsc_wdt_notify_sys(struct notifier_block *this, unsigned long cod | |||
510 | 507 | ||
511 | /* -- Module's structures ---------------------------------------*/ | 508 | /* -- Module's structures ---------------------------------------*/ |
512 | 509 | ||
513 | static const struct file_operations wb_smsc_wdt_fops = | 510 | static const struct file_operations wb_smsc_wdt_fops = { |
514 | { | 511 | .owner = THIS_MODULE, |
515 | .owner = THIS_MODULE, | ||
516 | .llseek = no_llseek, | 512 | .llseek = no_llseek, |
517 | .write = wb_smsc_wdt_write, | 513 | .write = wb_smsc_wdt_write, |
518 | .ioctl = wb_smsc_wdt_ioctl, | 514 | .unlocked_ioctl = wb_smsc_wdt_ioctl, |
519 | .open = wb_smsc_wdt_open, | 515 | .open = wb_smsc_wdt_open, |
520 | .release = wb_smsc_wdt_release, | 516 | .release = wb_smsc_wdt_release, |
521 | }; | 517 | }; |
522 | 518 | ||
523 | static struct notifier_block wb_smsc_wdt_notifier = | 519 | static struct notifier_block wb_smsc_wdt_notifier = { |
524 | { | ||
525 | .notifier_call = wb_smsc_wdt_notify_sys, | 520 | .notifier_call = wb_smsc_wdt_notify_sys, |
526 | }; | 521 | }; |
527 | 522 | ||
528 | static struct miscdevice wb_smsc_wdt_miscdev = | 523 | static struct miscdevice wb_smsc_wdt_miscdev = { |
529 | { | ||
530 | .minor = WATCHDOG_MINOR, | 524 | .minor = WATCHDOG_MINOR, |
531 | .name = "watchdog", | 525 | .name = "watchdog", |
532 | .fops = &wb_smsc_wdt_fops, | 526 | .fops = &wb_smsc_wdt_fops, |
@@ -540,39 +534,44 @@ static int __init wb_smsc_wdt_init(void) | |||
540 | { | 534 | { |
541 | int ret; | 535 | int ret; |
542 | 536 | ||
543 | printk("SMsC 37B787 watchdog component driver " VERSION " initialising...\n"); | 537 | printk(KERN_INFO "SMsC 37B787 watchdog component driver " |
538 | VERSION " initialising...\n"); | ||
544 | 539 | ||
545 | if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { | 540 | if (!request_region(IOPORT, IOPORT_SIZE, "SMsC 37B787 watchdog")) { |
546 | printk(KERN_ERR MODNAME "Unable to register IO port %#x\n", IOPORT); | 541 | printk(KERN_ERR MODNAME "Unable to register IO port %#x\n", |
542 | IOPORT); | ||
547 | ret = -EBUSY; | 543 | ret = -EBUSY; |
548 | goto out_pnp; | 544 | goto out_pnp; |
549 | } | 545 | } |
550 | 546 | ||
551 | // set new maximum, if it's too big | 547 | /* set new maximum, if it's too big */ |
552 | if (timeout > MAX_TIMEOUT) | 548 | if (timeout > MAX_TIMEOUT) |
553 | timeout = MAX_TIMEOUT; | 549 | timeout = MAX_TIMEOUT; |
554 | 550 | ||
555 | // init the watchdog timer | 551 | /* init the watchdog timer */ |
556 | wb_smsc_wdt_initialize(); | 552 | wb_smsc_wdt_initialize(); |
557 | 553 | ||
558 | ret = register_reboot_notifier(&wb_smsc_wdt_notifier); | 554 | ret = register_reboot_notifier(&wb_smsc_wdt_notifier); |
559 | if (ret) { | 555 | if (ret) { |
560 | printk(KERN_ERR MODNAME "Unable to register reboot notifier err = %d\n", ret); | 556 | printk(KERN_ERR MODNAME |
557 | "Unable to register reboot notifier err = %d\n", ret); | ||
561 | goto out_io; | 558 | goto out_io; |
562 | } | 559 | } |
563 | 560 | ||
564 | ret = misc_register(&wb_smsc_wdt_miscdev); | 561 | ret = misc_register(&wb_smsc_wdt_miscdev); |
565 | if (ret) { | 562 | if (ret) { |
566 | printk(KERN_ERR MODNAME "Unable to register miscdev on minor %d\n", WATCHDOG_MINOR); | 563 | printk(KERN_ERR MODNAME |
564 | "Unable to register miscdev on minor %d\n", | ||
565 | WATCHDOG_MINOR); | ||
567 | goto out_rbt; | 566 | goto out_rbt; |
568 | } | 567 | } |
569 | 568 | ||
570 | // output info | 569 | /* output info */ |
571 | printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); | 570 | printk(KERN_INFO MODNAME "Timeout set to %d %s.\n", |
572 | printk(KERN_INFO MODNAME "Watchdog initialized and sleeping (nowayout=%d)...\n", nowayout); | 571 | timeout, (unit == UNIT_SECOND) ? "second(s)" : "minute(s)"); |
573 | 572 | printk(KERN_INFO MODNAME | |
574 | // ret = 0 | 573 | "Watchdog initialized and sleeping (nowayout=%d)...\n", |
575 | 574 | nowayout); | |
576 | out_clean: | 575 | out_clean: |
577 | return ret; | 576 | return ret; |
578 | 577 | ||
@@ -591,8 +590,7 @@ out_pnp: | |||
591 | static void __exit wb_smsc_wdt_exit(void) | 590 | static void __exit wb_smsc_wdt_exit(void) |
592 | { | 591 | { |
593 | /* Stop the timer before we leave */ | 592 | /* Stop the timer before we leave */ |
594 | if (!nowayout) | 593 | if (!nowayout) { |
595 | { | ||
596 | wb_smsc_wdt_shutdown(); | 594 | wb_smsc_wdt_shutdown(); |
597 | printk(KERN_INFO MODNAME "Watchdog disabled.\n"); | 595 | printk(KERN_INFO MODNAME "Watchdog disabled.\n"); |
598 | } | 596 | } |
@@ -601,25 +599,29 @@ static void __exit wb_smsc_wdt_exit(void) | |||
601 | unregister_reboot_notifier(&wb_smsc_wdt_notifier); | 599 | unregister_reboot_notifier(&wb_smsc_wdt_notifier); |
602 | release_region(IOPORT, IOPORT_SIZE); | 600 | release_region(IOPORT, IOPORT_SIZE); |
603 | 601 | ||
604 | printk("SMsC 37B787 watchdog component driver removed.\n"); | 602 | printk(KERN_INFO "SMsC 37B787 watchdog component driver removed.\n"); |
605 | } | 603 | } |
606 | 604 | ||
607 | module_init(wb_smsc_wdt_init); | 605 | module_init(wb_smsc_wdt_init); |
608 | module_exit(wb_smsc_wdt_exit); | 606 | module_exit(wb_smsc_wdt_exit); |
609 | 607 | ||
610 | MODULE_AUTHOR("Sven Anders <anders@anduras.de>"); | 608 | MODULE_AUTHOR("Sven Anders <anders@anduras.de>"); |
611 | MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " VERSION ")"); | 609 | MODULE_DESCRIPTION("Driver for SMsC 37B787 watchdog component (Version " |
610 | VERSION ")"); | ||
612 | MODULE_LICENSE("GPL"); | 611 | MODULE_LICENSE("GPL"); |
613 | 612 | ||
614 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 613 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
615 | 614 | ||
616 | #ifdef SMSC_SUPPORT_MINUTES | 615 | #ifdef SMSC_SUPPORT_MINUTES |
617 | module_param(unit, int, 0); | 616 | module_param(unit, int, 0); |
618 | MODULE_PARM_DESC(unit, "set unit to use, 0=seconds or 1=minutes, default is 0"); | 617 | MODULE_PARM_DESC(unit, |
618 | "set unit to use, 0=seconds or 1=minutes, default is 0"); | ||
619 | #endif | 619 | #endif |
620 | 620 | ||
621 | module_param(timeout, int, 0); | 621 | module_param(timeout, int, 0); |
622 | MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60"); | 622 | MODULE_PARM_DESC(timeout, "range is 1-255 units, default is 60"); |
623 | 623 | ||
624 | module_param(nowayout, int, 0); | 624 | module_param(nowayout, int, 0); |
625 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 625 | MODULE_PARM_DESC(nowayout, |
626 | "Watchdog cannot be stopped once started (default=" | ||
627 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c index 9c3694909243..c650464c5c63 100644 --- a/drivers/watchdog/softdog.c +++ b/drivers/watchdog/softdog.c | |||
@@ -47,19 +47,22 @@ | |||
47 | #include <linux/reboot.h> | 47 | #include <linux/reboot.h> |
48 | #include <linux/init.h> | 48 | #include <linux/init.h> |
49 | #include <linux/jiffies.h> | 49 | #include <linux/jiffies.h> |
50 | 50 | #include <linux/uaccess.h> | |
51 | #include <asm/uaccess.h> | ||
52 | 51 | ||
53 | #define PFX "SoftDog: " | 52 | #define PFX "SoftDog: " |
54 | 53 | ||
55 | #define TIMER_MARGIN 60 /* Default is 60 seconds */ | 54 | #define TIMER_MARGIN 60 /* Default is 60 seconds */ |
56 | static int soft_margin = TIMER_MARGIN; /* in seconds */ | 55 | static int soft_margin = TIMER_MARGIN; /* in seconds */ |
57 | module_param(soft_margin, int, 0); | 56 | module_param(soft_margin, int, 0); |
58 | MODULE_PARM_DESC(soft_margin, "Watchdog soft_margin in seconds. (0<soft_margin<65536, default=" __MODULE_STRING(TIMER_MARGIN) ")"); | 57 | MODULE_PARM_DESC(soft_margin, |
58 | "Watchdog soft_margin in seconds. (0 < soft_margin < 65536, default=" | ||
59 | __MODULE_STRING(TIMER_MARGIN) ")"); | ||
59 | 60 | ||
60 | static int nowayout = WATCHDOG_NOWAYOUT; | 61 | static int nowayout = WATCHDOG_NOWAYOUT; |
61 | module_param(nowayout, int, 0); | 62 | module_param(nowayout, int, 0); |
62 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 63 | MODULE_PARM_DESC(nowayout, |
64 | "Watchdog cannot be stopped once started (default=" | ||
65 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
63 | 66 | ||
64 | #ifdef ONLY_TESTING | 67 | #ifdef ONLY_TESTING |
65 | static int soft_noboot = 1; | 68 | static int soft_noboot = 1; |
@@ -93,8 +96,7 @@ static void watchdog_fire(unsigned long data) | |||
93 | 96 | ||
94 | if (soft_noboot) | 97 | if (soft_noboot) |
95 | printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); | 98 | printk(KERN_CRIT PFX "Triggered - Reboot ignored.\n"); |
96 | else | 99 | else { |
97 | { | ||
98 | printk(KERN_CRIT PFX "Initiating system reboot.\n"); | 100 | printk(KERN_CRIT PFX "Initiating system reboot.\n"); |
99 | emergency_restart(); | 101 | emergency_restart(); |
100 | printk(KERN_CRIT PFX "Reboot didn't ?????\n"); | 102 | printk(KERN_CRIT PFX "Reboot didn't ?????\n"); |
@@ -153,7 +155,8 @@ static int softdog_release(struct inode *inode, struct file *file) | |||
153 | softdog_stop(); | 155 | softdog_stop(); |
154 | module_put(THIS_MODULE); | 156 | module_put(THIS_MODULE); |
155 | } else { | 157 | } else { |
156 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 158 | printk(KERN_CRIT PFX |
159 | "Unexpected close, not stopping watchdog!\n"); | ||
157 | set_bit(0, &orphan_timer); | 160 | set_bit(0, &orphan_timer); |
158 | softdog_keepalive(); | 161 | softdog_keepalive(); |
159 | } | 162 | } |
@@ -162,12 +165,13 @@ static int softdog_release(struct inode *inode, struct file *file) | |||
162 | return 0; | 165 | return 0; |
163 | } | 166 | } |
164 | 167 | ||
165 | static ssize_t softdog_write(struct file *file, const char __user *data, size_t len, loff_t *ppos) | 168 | static ssize_t softdog_write(struct file *file, const char __user *data, |
169 | size_t len, loff_t *ppos) | ||
166 | { | 170 | { |
167 | /* | 171 | /* |
168 | * Refresh the timer. | 172 | * Refresh the timer. |
169 | */ | 173 | */ |
170 | if(len) { | 174 | if (len) { |
171 | if (!nowayout) { | 175 | if (!nowayout) { |
172 | size_t i; | 176 | size_t i; |
173 | 177 | ||
@@ -188,13 +192,13 @@ static ssize_t softdog_write(struct file *file, const char __user *data, size_t | |||
188 | return len; | 192 | return len; |
189 | } | 193 | } |
190 | 194 | ||
191 | static int softdog_ioctl(struct inode *inode, struct file *file, | 195 | static long softdog_ioctl(struct file *file, unsigned int cmd, |
192 | unsigned int cmd, unsigned long arg) | 196 | unsigned long arg) |
193 | { | 197 | { |
194 | void __user *argp = (void __user *)arg; | 198 | void __user *argp = (void __user *)arg; |
195 | int __user *p = argp; | 199 | int __user *p = argp; |
196 | int new_margin; | 200 | int new_margin; |
197 | static struct watchdog_info ident = { | 201 | static const struct watchdog_info ident = { |
198 | .options = WDIOF_SETTIMEOUT | | 202 | .options = WDIOF_SETTIMEOUT | |
199 | WDIOF_KEEPALIVEPING | | 203 | WDIOF_KEEPALIVEPING | |
200 | WDIOF_MAGICCLOSE, | 204 | WDIOF_MAGICCLOSE, |
@@ -202,26 +206,25 @@ static int softdog_ioctl(struct inode *inode, struct file *file, | |||
202 | .identity = "Software Watchdog", | 206 | .identity = "Software Watchdog", |
203 | }; | 207 | }; |
204 | switch (cmd) { | 208 | switch (cmd) { |
205 | default: | 209 | case WDIOC_GETSUPPORT: |
206 | return -ENOTTY; | 210 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
207 | case WDIOC_GETSUPPORT: | 211 | case WDIOC_GETSTATUS: |
208 | return copy_to_user(argp, &ident, | 212 | case WDIOC_GETBOOTSTATUS: |
209 | sizeof(ident)) ? -EFAULT : 0; | 213 | return put_user(0, p); |
210 | case WDIOC_GETSTATUS: | 214 | case WDIOC_KEEPALIVE: |
211 | case WDIOC_GETBOOTSTATUS: | 215 | softdog_keepalive(); |
212 | return put_user(0, p); | 216 | return 0; |
213 | case WDIOC_KEEPALIVE: | 217 | case WDIOC_SETTIMEOUT: |
214 | softdog_keepalive(); | 218 | if (get_user(new_margin, p)) |
215 | return 0; | 219 | return -EFAULT; |
216 | case WDIOC_SETTIMEOUT: | 220 | if (softdog_set_heartbeat(new_margin)) |
217 | if (get_user(new_margin, p)) | 221 | return -EINVAL; |
218 | return -EFAULT; | 222 | softdog_keepalive(); |
219 | if (softdog_set_heartbeat(new_margin)) | 223 | /* Fall */ |
220 | return -EINVAL; | 224 | case WDIOC_GETTIMEOUT: |
221 | softdog_keepalive(); | 225 | return put_user(soft_margin, p); |
222 | /* Fall */ | 226 | default: |
223 | case WDIOC_GETTIMEOUT: | 227 | return -ENOTTY; |
224 | return put_user(soft_margin, p); | ||
225 | } | 228 | } |
226 | } | 229 | } |
227 | 230 | ||
@@ -232,10 +235,9 @@ static int softdog_ioctl(struct inode *inode, struct file *file, | |||
232 | static int softdog_notify_sys(struct notifier_block *this, unsigned long code, | 235 | static int softdog_notify_sys(struct notifier_block *this, unsigned long code, |
233 | void *unused) | 236 | void *unused) |
234 | { | 237 | { |
235 | if(code==SYS_DOWN || code==SYS_HALT) { | 238 | if (code == SYS_DOWN || code == SYS_HALT) |
236 | /* Turn the WDT off */ | 239 | /* Turn the WDT off */ |
237 | softdog_stop(); | 240 | softdog_stop(); |
238 | } | ||
239 | return NOTIFY_DONE; | 241 | return NOTIFY_DONE; |
240 | } | 242 | } |
241 | 243 | ||
@@ -247,7 +249,7 @@ static const struct file_operations softdog_fops = { | |||
247 | .owner = THIS_MODULE, | 249 | .owner = THIS_MODULE, |
248 | .llseek = no_llseek, | 250 | .llseek = no_llseek, |
249 | .write = softdog_write, | 251 | .write = softdog_write, |
250 | .ioctl = softdog_ioctl, | 252 | .unlocked_ioctl = softdog_ioctl, |
251 | .open = softdog_open, | 253 | .open = softdog_open, |
252 | .release = softdog_release, | 254 | .release = softdog_release, |
253 | }; | 255 | }; |
@@ -268,24 +270,27 @@ static int __init watchdog_init(void) | |||
268 | { | 270 | { |
269 | int ret; | 271 | int ret; |
270 | 272 | ||
271 | /* Check that the soft_margin value is within it's range ; if not reset to the default */ | 273 | /* Check that the soft_margin value is within it's range; |
274 | if not reset to the default */ | ||
272 | if (softdog_set_heartbeat(soft_margin)) { | 275 | if (softdog_set_heartbeat(soft_margin)) { |
273 | softdog_set_heartbeat(TIMER_MARGIN); | 276 | softdog_set_heartbeat(TIMER_MARGIN); |
274 | printk(KERN_INFO PFX "soft_margin value must be 0<soft_margin<65536, using %d\n", | 277 | printk(KERN_INFO PFX |
278 | "soft_margin must be 0 < soft_margin < 65536, using %d\n", | ||
275 | TIMER_MARGIN); | 279 | TIMER_MARGIN); |
276 | } | 280 | } |
277 | 281 | ||
278 | ret = register_reboot_notifier(&softdog_notifier); | 282 | ret = register_reboot_notifier(&softdog_notifier); |
279 | if (ret) { | 283 | if (ret) { |
280 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 284 | printk(KERN_ERR PFX |
281 | ret); | 285 | "cannot register reboot notifier (err=%d)\n", ret); |
282 | return ret; | 286 | return ret; |
283 | } | 287 | } |
284 | 288 | ||
285 | ret = misc_register(&softdog_miscdev); | 289 | ret = misc_register(&softdog_miscdev); |
286 | if (ret) { | 290 | if (ret) { |
287 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 291 | printk(KERN_ERR PFX |
288 | WATCHDOG_MINOR, ret); | 292 | "cannot register miscdev on minor=%d (err=%d)\n", |
293 | WATCHDOG_MINOR, ret); | ||
289 | unregister_reboot_notifier(&softdog_notifier); | 294 | unregister_reboot_notifier(&softdog_notifier); |
290 | return ret; | 295 | return ret; |
291 | } | 296 | } |
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c index 57cefef27ce3..dbbc018a5f46 100644 --- a/drivers/watchdog/txx9wdt.c +++ b/drivers/watchdog/txx9wdt.c | |||
@@ -45,27 +45,34 @@ static unsigned long txx9wdt_alive; | |||
45 | static int expect_close; | 45 | static int expect_close; |
46 | static struct txx9_tmr_reg __iomem *txx9wdt_reg; | 46 | static struct txx9_tmr_reg __iomem *txx9wdt_reg; |
47 | static struct clk *txx9_imclk; | 47 | static struct clk *txx9_imclk; |
48 | static DECLARE_LOCK(txx9_lock); | ||
48 | 49 | ||
49 | static void txx9wdt_ping(void) | 50 | static void txx9wdt_ping(void) |
50 | { | 51 | { |
52 | spin_lock(&txx9_lock); | ||
51 | __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); | 53 | __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); |
54 | spin_unlock(&txx9_lock); | ||
52 | } | 55 | } |
53 | 56 | ||
54 | static void txx9wdt_start(void) | 57 | static void txx9wdt_start(void) |
55 | { | 58 | { |
59 | spin_lock(&txx9_lock); | ||
56 | __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra); | 60 | __raw_writel(WD_TIMER_CLK * timeout, &txx9wdt_reg->cpra); |
57 | __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr); | 61 | __raw_writel(WD_TIMER_CCD, &txx9wdt_reg->ccdr); |
58 | __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */ | 62 | __raw_writel(0, &txx9wdt_reg->tisr); /* clear pending interrupt */ |
59 | __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, | 63 | __raw_writel(TXx9_TMTCR_TCE | TXx9_TMTCR_CCDE | TXx9_TMTCR_TMODE_WDOG, |
60 | &txx9wdt_reg->tcr); | 64 | &txx9wdt_reg->tcr); |
61 | __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); | 65 | __raw_writel(TXx9_TMWTMR_TWIE | TXx9_TMWTMR_TWC, &txx9wdt_reg->wtmr); |
66 | spin_unlock(&txx9_lock); | ||
62 | } | 67 | } |
63 | 68 | ||
64 | static void txx9wdt_stop(void) | 69 | static void txx9wdt_stop(void) |
65 | { | 70 | { |
71 | spin_lock(&txx9_lock); | ||
66 | __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr); | 72 | __raw_writel(TXx9_TMWTMR_WDIS, &txx9wdt_reg->wtmr); |
67 | __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE, | 73 | __raw_writel(__raw_readl(&txx9wdt_reg->tcr) & ~TXx9_TMTCR_TCE, |
68 | &txx9wdt_reg->tcr); | 74 | &txx9wdt_reg->tcr); |
75 | spin_unlock(&txx9_lock); | ||
69 | } | 76 | } |
70 | 77 | ||
71 | static int txx9wdt_open(struct inode *inode, struct file *file) | 78 | static int txx9wdt_open(struct inode *inode, struct file *file) |
@@ -120,13 +127,13 @@ static ssize_t txx9wdt_write(struct file *file, const char __user *data, | |||
120 | return len; | 127 | return len; |
121 | } | 128 | } |
122 | 129 | ||
123 | static int txx9wdt_ioctl(struct inode *inode, struct file *file, | 130 | static long txx9wdt_ioctl(struct file *file, unsigned int cmd, |
124 | unsigned int cmd, unsigned long arg) | 131 | unsigned long arg) |
125 | { | 132 | { |
126 | void __user *argp = (void __user *)arg; | 133 | void __user *argp = (void __user *)arg; |
127 | int __user *p = argp; | 134 | int __user *p = argp; |
128 | int new_timeout; | 135 | int new_timeout; |
129 | static struct watchdog_info ident = { | 136 | static const struct watchdog_info ident = { |
130 | .options = WDIOF_SETTIMEOUT | | 137 | .options = WDIOF_SETTIMEOUT | |
131 | WDIOF_KEEPALIVEPING | | 138 | WDIOF_KEEPALIVEPING | |
132 | WDIOF_MAGICCLOSE, | 139 | WDIOF_MAGICCLOSE, |
@@ -135,8 +142,6 @@ static int txx9wdt_ioctl(struct inode *inode, struct file *file, | |||
135 | }; | 142 | }; |
136 | 143 | ||
137 | switch (cmd) { | 144 | switch (cmd) { |
138 | default: | ||
139 | return -ENOTTY; | ||
140 | case WDIOC_GETSUPPORT: | 145 | case WDIOC_GETSUPPORT: |
141 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | 146 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
142 | case WDIOC_GETSTATUS: | 147 | case WDIOC_GETSTATUS: |
@@ -156,6 +161,8 @@ static int txx9wdt_ioctl(struct inode *inode, struct file *file, | |||
156 | /* Fall */ | 161 | /* Fall */ |
157 | case WDIOC_GETTIMEOUT: | 162 | case WDIOC_GETTIMEOUT: |
158 | return put_user(timeout, p); | 163 | return put_user(timeout, p); |
164 | default: | ||
165 | return -ENOTTY; | ||
159 | } | 166 | } |
160 | } | 167 | } |
161 | 168 | ||
@@ -168,22 +175,22 @@ static int txx9wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
168 | } | 175 | } |
169 | 176 | ||
170 | static const struct file_operations txx9wdt_fops = { | 177 | static const struct file_operations txx9wdt_fops = { |
171 | .owner = THIS_MODULE, | 178 | .owner = THIS_MODULE, |
172 | .llseek = no_llseek, | 179 | .llseek = no_llseek, |
173 | .write = txx9wdt_write, | 180 | .write = txx9wdt_write, |
174 | .ioctl = txx9wdt_ioctl, | 181 | .unlocked_ioctl = txx9wdt_ioctl, |
175 | .open = txx9wdt_open, | 182 | .open = txx9wdt_open, |
176 | .release = txx9wdt_release, | 183 | .release = txx9wdt_release, |
177 | }; | 184 | }; |
178 | 185 | ||
179 | static struct miscdevice txx9wdt_miscdev = { | 186 | static struct miscdevice txx9wdt_miscdev = { |
180 | .minor = WATCHDOG_MINOR, | 187 | .minor = WATCHDOG_MINOR, |
181 | .name = "watchdog", | 188 | .name = "watchdog", |
182 | .fops = &txx9wdt_fops, | 189 | .fops = &txx9wdt_fops, |
183 | }; | 190 | }; |
184 | 191 | ||
185 | static struct notifier_block txx9wdt_notifier = { | 192 | static struct notifier_block txx9wdt_notifier = { |
186 | .notifier_call = txx9wdt_notify_sys | 193 | .notifier_call = txx9wdt_notify_sys, |
187 | }; | 194 | }; |
188 | 195 | ||
189 | static int __init txx9wdt_probe(struct platform_device *dev) | 196 | static int __init txx9wdt_probe(struct platform_device *dev) |
diff --git a/drivers/watchdog/w83627hf_wdt.c b/drivers/watchdog/w83627hf_wdt.c index 386492821fc2..69396adaa5c3 100644 --- a/drivers/watchdog/w83627hf_wdt.c +++ b/drivers/watchdog/w83627hf_wdt.c | |||
@@ -37,9 +37,9 @@ | |||
37 | #include <linux/reboot.h> | 37 | #include <linux/reboot.h> |
38 | #include <linux/init.h> | 38 | #include <linux/init.h> |
39 | #include <linux/spinlock.h> | 39 | #include <linux/spinlock.h> |
40 | #include <linux/io.h> | ||
41 | #include <linux/uaccess.h> | ||
40 | 42 | ||
41 | #include <asm/io.h> | ||
42 | #include <asm/uaccess.h> | ||
43 | #include <asm/system.h> | 43 | #include <asm/system.h> |
44 | 44 | ||
45 | #define WATCHDOG_NAME "w83627hf/thf/hg WDT" | 45 | #define WATCHDOG_NAME "w83627hf/thf/hg WDT" |
@@ -57,22 +57,26 @@ MODULE_PARM_DESC(wdt_io, "w83627hf/thf WDT io port (default 0x2E)"); | |||
57 | 57 | ||
58 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | 58 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ |
59 | module_param(timeout, int, 0); | 59 | module_param(timeout, int, 0); |
60 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | 60 | MODULE_PARM_DESC(timeout, |
61 | "Watchdog timeout in seconds. 1 <= timeout <= 255, default=" | ||
62 | __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | ||
61 | 63 | ||
62 | static int nowayout = WATCHDOG_NOWAYOUT; | 64 | static int nowayout = WATCHDOG_NOWAYOUT; |
63 | module_param(nowayout, int, 0); | 65 | module_param(nowayout, int, 0); |
64 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 66 | MODULE_PARM_DESC(nowayout, |
67 | "Watchdog cannot be stopped once started (default=" | ||
68 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
65 | 69 | ||
66 | /* | 70 | /* |
67 | * Kernel methods. | 71 | * Kernel methods. |
68 | */ | 72 | */ |
69 | 73 | ||
70 | #define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ | 74 | #define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ |
71 | #define WDT_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ | 75 | #define WDT_EFIR (wdt_io+0) /* Extended Function Index Register |
76 | (same as EFER) */ | ||
72 | #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ | 77 | #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ |
73 | 78 | ||
74 | static void | 79 | static void w83627hf_select_wd_register(void) |
75 | w83627hf_select_wd_register(void) | ||
76 | { | 80 | { |
77 | unsigned char c; | 81 | unsigned char c; |
78 | outb_p(0x87, WDT_EFER); /* Enter extended function mode */ | 82 | outb_p(0x87, WDT_EFER); /* Enter extended function mode */ |
@@ -93,43 +97,45 @@ w83627hf_select_wd_register(void) | |||
93 | outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ | 97 | outb_p(0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ |
94 | } | 98 | } |
95 | 99 | ||
96 | static void | 100 | static void w83627hf_unselect_wd_register(void) |
97 | w83627hf_unselect_wd_register(void) | ||
98 | { | 101 | { |
99 | outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ | 102 | outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ |
100 | } | 103 | } |
101 | 104 | ||
102 | /* tyan motherboards seem to set F5 to 0x4C ? | 105 | /* tyan motherboards seem to set F5 to 0x4C ? |
103 | * So explicitly init to appropriate value. */ | 106 | * So explicitly init to appropriate value. */ |
104 | static void | 107 | |
105 | w83627hf_init(void) | 108 | static void w83627hf_init(void) |
106 | { | 109 | { |
107 | unsigned char t; | 110 | unsigned char t; |
108 | 111 | ||
109 | w83627hf_select_wd_register(); | 112 | w83627hf_select_wd_register(); |
110 | 113 | ||
111 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ | 114 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ |
112 | t=inb_p(WDT_EFDR); /* read CRF6 */ | 115 | t = inb_p(WDT_EFDR); /* read CRF6 */ |
113 | if (t != 0) { | 116 | if (t != 0) { |
114 | printk (KERN_INFO PFX "Watchdog already running. Resetting timeout to %d sec\n", timeout); | 117 | printk(KERN_INFO PFX |
118 | "Watchdog already running. Resetting timeout to %d sec\n", | ||
119 | timeout); | ||
115 | outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ | 120 | outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ |
116 | } | 121 | } |
117 | 122 | ||
118 | outb_p(0xF5, WDT_EFER); /* Select CRF5 */ | 123 | outb_p(0xF5, WDT_EFER); /* Select CRF5 */ |
119 | t=inb_p(WDT_EFDR); /* read CRF5 */ | 124 | t = inb_p(WDT_EFDR); /* read CRF5 */ |
120 | t&=~0x0C; /* set second mode & disable keyboard turning off watchdog */ | 125 | t &= ~0x0C; /* set second mode & disable keyboard |
126 | turning off watchdog */ | ||
121 | outb_p(t, WDT_EFDR); /* Write back to CRF5 */ | 127 | outb_p(t, WDT_EFDR); /* Write back to CRF5 */ |
122 | 128 | ||
123 | outb_p(0xF7, WDT_EFER); /* Select CRF7 */ | 129 | outb_p(0xF7, WDT_EFER); /* Select CRF7 */ |
124 | t=inb_p(WDT_EFDR); /* read CRF7 */ | 130 | t = inb_p(WDT_EFDR); /* read CRF7 */ |
125 | t&=~0xC0; /* disable keyboard & mouse turning off watchdog */ | 131 | t &= ~0xC0; /* disable keyboard & mouse turning off |
132 | watchdog */ | ||
126 | outb_p(t, WDT_EFDR); /* Write back to CRF7 */ | 133 | outb_p(t, WDT_EFDR); /* Write back to CRF7 */ |
127 | 134 | ||
128 | w83627hf_unselect_wd_register(); | 135 | w83627hf_unselect_wd_register(); |
129 | } | 136 | } |
130 | 137 | ||
131 | static void | 138 | static void wdt_ctrl(int timeout) |
132 | wdt_ctrl(int timeout) | ||
133 | { | 139 | { |
134 | spin_lock(&io_lock); | 140 | spin_lock(&io_lock); |
135 | 141 | ||
@@ -143,32 +149,28 @@ wdt_ctrl(int timeout) | |||
143 | spin_unlock(&io_lock); | 149 | spin_unlock(&io_lock); |
144 | } | 150 | } |
145 | 151 | ||
146 | static int | 152 | static int wdt_ping(void) |
147 | wdt_ping(void) | ||
148 | { | 153 | { |
149 | wdt_ctrl(timeout); | 154 | wdt_ctrl(timeout); |
150 | return 0; | 155 | return 0; |
151 | } | 156 | } |
152 | 157 | ||
153 | static int | 158 | static int wdt_disable(void) |
154 | wdt_disable(void) | ||
155 | { | 159 | { |
156 | wdt_ctrl(0); | 160 | wdt_ctrl(0); |
157 | return 0; | 161 | return 0; |
158 | } | 162 | } |
159 | 163 | ||
160 | static int | 164 | static int wdt_set_heartbeat(int t) |
161 | wdt_set_heartbeat(int t) | ||
162 | { | 165 | { |
163 | if ((t < 1) || (t > 255)) | 166 | if (t < 1 || t > 255) |
164 | return -EINVAL; | 167 | return -EINVAL; |
165 | |||
166 | timeout = t; | 168 | timeout = t; |
167 | return 0; | 169 | return 0; |
168 | } | 170 | } |
169 | 171 | ||
170 | static ssize_t | 172 | static ssize_t wdt_write(struct file *file, const char __user *buf, |
171 | wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 173 | size_t count, loff_t *ppos) |
172 | { | 174 | { |
173 | if (count) { | 175 | if (count) { |
174 | if (!nowayout) { | 176 | if (!nowayout) { |
@@ -178,7 +180,7 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
178 | 180 | ||
179 | for (i = 0; i != count; i++) { | 181 | for (i = 0; i != count; i++) { |
180 | char c; | 182 | char c; |
181 | if (get_user(c, buf+i)) | 183 | if (get_user(c, buf + i)) |
182 | return -EFAULT; | 184 | return -EFAULT; |
183 | if (c == 'V') | 185 | if (c == 'V') |
184 | expect_close = 42; | 186 | expect_close = 42; |
@@ -189,72 +191,61 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
189 | return count; | 191 | return count; |
190 | } | 192 | } |
191 | 193 | ||
192 | static int | 194 | static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
193 | wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
194 | unsigned long arg) | ||
195 | { | 195 | { |
196 | void __user *argp = (void __user *)arg; | 196 | void __user *argp = (void __user *)arg; |
197 | int __user *p = argp; | 197 | int __user *p = argp; |
198 | int new_timeout; | 198 | int new_timeout; |
199 | static struct watchdog_info ident = { | 199 | static struct watchdog_info ident = { |
200 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 200 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
201 | WDIOF_MAGICCLOSE, | ||
201 | .firmware_version = 1, | 202 | .firmware_version = 1, |
202 | .identity = "W83627HF WDT", | 203 | .identity = "W83627HF WDT", |
203 | }; | 204 | }; |
204 | 205 | ||
205 | switch (cmd) { | 206 | switch (cmd) { |
206 | case WDIOC_GETSUPPORT: | 207 | case WDIOC_GETSUPPORT: |
207 | if (copy_to_user(argp, &ident, sizeof(ident))) | 208 | if (copy_to_user(argp, &ident, sizeof(ident))) |
208 | return -EFAULT; | 209 | return -EFAULT; |
209 | break; | 210 | break; |
210 | |||
211 | case WDIOC_GETSTATUS: | 211 | case WDIOC_GETSTATUS: |
212 | case WDIOC_GETBOOTSTATUS: | 212 | case WDIOC_GETBOOTSTATUS: |
213 | return put_user(0, p); | 213 | return put_user(0, p); |
214 | |||
215 | case WDIOC_KEEPALIVE: | ||
216 | wdt_ping(); | ||
217 | break; | ||
218 | |||
219 | case WDIOC_SETTIMEOUT: | ||
220 | if (get_user(new_timeout, p)) | ||
221 | return -EFAULT; | ||
222 | if (wdt_set_heartbeat(new_timeout)) | ||
223 | return -EINVAL; | ||
224 | wdt_ping(); | ||
225 | /* Fall */ | ||
226 | |||
227 | case WDIOC_GETTIMEOUT: | ||
228 | return put_user(timeout, p); | ||
229 | |||
230 | case WDIOC_SETOPTIONS: | 214 | case WDIOC_SETOPTIONS: |
231 | { | 215 | { |
232 | int options, retval = -EINVAL; | 216 | int options, retval = -EINVAL; |
233 | |||
234 | if (get_user(options, p)) | ||
235 | return -EFAULT; | ||
236 | |||
237 | if (options & WDIOS_DISABLECARD) { | ||
238 | wdt_disable(); | ||
239 | retval = 0; | ||
240 | } | ||
241 | |||
242 | if (options & WDIOS_ENABLECARD) { | ||
243 | wdt_ping(); | ||
244 | retval = 0; | ||
245 | } | ||
246 | 217 | ||
247 | return retval; | 218 | if (get_user(options, p)) |
219 | return -EFAULT; | ||
220 | if (options & WDIOS_DISABLECARD) { | ||
221 | wdt_disable(); | ||
222 | retval = 0; | ||
223 | } | ||
224 | if (options & WDIOS_ENABLECARD) { | ||
225 | wdt_ping(); | ||
226 | retval = 0; | ||
227 | } | ||
228 | return retval; | ||
248 | } | 229 | } |
249 | 230 | case WDIOC_KEEPALIVE: | |
231 | wdt_ping(); | ||
232 | break; | ||
233 | case WDIOC_SETTIMEOUT: | ||
234 | if (get_user(new_timeout, p)) | ||
235 | return -EFAULT; | ||
236 | if (wdt_set_heartbeat(new_timeout)) | ||
237 | return -EINVAL; | ||
238 | wdt_ping(); | ||
239 | /* Fall */ | ||
240 | case WDIOC_GETTIMEOUT: | ||
241 | return put_user(timeout, p); | ||
250 | default: | 242 | default: |
251 | return -ENOTTY; | 243 | return -ENOTTY; |
252 | } | 244 | } |
253 | return 0; | 245 | return 0; |
254 | } | 246 | } |
255 | 247 | ||
256 | static int | 248 | static int wdt_open(struct inode *inode, struct file *file) |
257 | wdt_open(struct inode *inode, struct file *file) | ||
258 | { | 249 | { |
259 | if (test_and_set_bit(0, &wdt_is_open)) | 250 | if (test_and_set_bit(0, &wdt_is_open)) |
260 | return -EBUSY; | 251 | return -EBUSY; |
@@ -266,13 +257,13 @@ wdt_open(struct inode *inode, struct file *file) | |||
266 | return nonseekable_open(inode, file); | 257 | return nonseekable_open(inode, file); |
267 | } | 258 | } |
268 | 259 | ||
269 | static int | 260 | static int wdt_close(struct inode *inode, struct file *file) |
270 | wdt_close(struct inode *inode, struct file *file) | ||
271 | { | 261 | { |
272 | if (expect_close == 42) { | 262 | if (expect_close == 42) |
273 | wdt_disable(); | 263 | wdt_disable(); |
274 | } else { | 264 | else { |
275 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 265 | printk(KERN_CRIT PFX |
266 | "Unexpected close, not stopping watchdog!\n"); | ||
276 | wdt_ping(); | 267 | wdt_ping(); |
277 | } | 268 | } |
278 | expect_close = 0; | 269 | expect_close = 0; |
@@ -284,14 +275,12 @@ wdt_close(struct inode *inode, struct file *file) | |||
284 | * Notifier for system down | 275 | * Notifier for system down |
285 | */ | 276 | */ |
286 | 277 | ||
287 | static int | 278 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, |
288 | wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
289 | void *unused) | 279 | void *unused) |
290 | { | 280 | { |
291 | if (code == SYS_DOWN || code == SYS_HALT) { | 281 | if (code == SYS_DOWN || code == SYS_HALT) |
292 | /* Turn the WDT off */ | 282 | wdt_disable(); /* Turn the WDT off */ |
293 | wdt_disable(); | 283 | |
294 | } | ||
295 | return NOTIFY_DONE; | 284 | return NOTIFY_DONE; |
296 | } | 285 | } |
297 | 286 | ||
@@ -303,7 +292,7 @@ static const struct file_operations wdt_fops = { | |||
303 | .owner = THIS_MODULE, | 292 | .owner = THIS_MODULE, |
304 | .llseek = no_llseek, | 293 | .llseek = no_llseek, |
305 | .write = wdt_write, | 294 | .write = wdt_write, |
306 | .ioctl = wdt_ioctl, | 295 | .unlocked_ioctl = wdt_ioctl, |
307 | .open = wdt_open, | 296 | .open = wdt_open, |
308 | .release = wdt_close, | 297 | .release = wdt_close, |
309 | }; | 298 | }; |
@@ -323,8 +312,7 @@ static struct notifier_block wdt_notifier = { | |||
323 | .notifier_call = wdt_notify_sys, | 312 | .notifier_call = wdt_notify_sys, |
324 | }; | 313 | }; |
325 | 314 | ||
326 | static int __init | 315 | static int __init wdt_init(void) |
327 | wdt_init(void) | ||
328 | { | 316 | { |
329 | int ret; | 317 | int ret; |
330 | 318 | ||
@@ -332,12 +320,13 @@ wdt_init(void) | |||
332 | 320 | ||
333 | if (wdt_set_heartbeat(timeout)) { | 321 | if (wdt_set_heartbeat(timeout)) { |
334 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | 322 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); |
335 | printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", | 323 | printk(KERN_INFO PFX |
336 | WATCHDOG_TIMEOUT); | 324 | "timeout value must be 1 <= timeout <= 255, using %d\n", |
325 | WATCHDOG_TIMEOUT); | ||
337 | } | 326 | } |
338 | 327 | ||
339 | if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { | 328 | if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { |
340 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 329 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
341 | wdt_io); | 330 | wdt_io); |
342 | ret = -EIO; | 331 | ret = -EIO; |
343 | goto out; | 332 | goto out; |
@@ -347,20 +336,22 @@ wdt_init(void) | |||
347 | 336 | ||
348 | ret = register_reboot_notifier(&wdt_notifier); | 337 | ret = register_reboot_notifier(&wdt_notifier); |
349 | if (ret != 0) { | 338 | if (ret != 0) { |
350 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 339 | printk(KERN_ERR PFX |
351 | ret); | 340 | "cannot register reboot notifier (err=%d)\n", ret); |
352 | goto unreg_regions; | 341 | goto unreg_regions; |
353 | } | 342 | } |
354 | 343 | ||
355 | ret = misc_register(&wdt_miscdev); | 344 | ret = misc_register(&wdt_miscdev); |
356 | if (ret != 0) { | 345 | if (ret != 0) { |
357 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 346 | printk(KERN_ERR PFX |
358 | WATCHDOG_MINOR, ret); | 347 | "cannot register miscdev on minor=%d (err=%d)\n", |
348 | WATCHDOG_MINOR, ret); | ||
359 | goto unreg_reboot; | 349 | goto unreg_reboot; |
360 | } | 350 | } |
361 | 351 | ||
362 | printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", | 352 | printk(KERN_INFO PFX |
363 | timeout, nowayout); | 353 | "initialized. timeout=%d sec (nowayout=%d)\n", |
354 | timeout, nowayout); | ||
364 | 355 | ||
365 | out: | 356 | out: |
366 | return ret; | 357 | return ret; |
@@ -371,12 +362,11 @@ unreg_regions: | |||
371 | goto out; | 362 | goto out; |
372 | } | 363 | } |
373 | 364 | ||
374 | static void __exit | 365 | static void __exit wdt_exit(void) |
375 | wdt_exit(void) | ||
376 | { | 366 | { |
377 | misc_deregister(&wdt_miscdev); | 367 | misc_deregister(&wdt_miscdev); |
378 | unregister_reboot_notifier(&wdt_notifier); | 368 | unregister_reboot_notifier(&wdt_notifier); |
379 | release_region(wdt_io,1); | 369 | release_region(wdt_io, 1); |
380 | } | 370 | } |
381 | 371 | ||
382 | module_init(wdt_init); | 372 | module_init(wdt_init); |
diff --git a/drivers/watchdog/w83697hf_wdt.c b/drivers/watchdog/w83697hf_wdt.c index 528b882420b6..445d30a01ed3 100644 --- a/drivers/watchdog/w83697hf_wdt.c +++ b/drivers/watchdog/w83697hf_wdt.c | |||
@@ -36,9 +36,9 @@ | |||
36 | #include <linux/reboot.h> | 36 | #include <linux/reboot.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
39 | #include <linux/io.h> | ||
40 | #include <linux/uaccess.h> | ||
39 | 41 | ||
40 | #include <asm/io.h> | ||
41 | #include <asm/uaccess.h> | ||
42 | #include <asm/system.h> | 42 | #include <asm/system.h> |
43 | 43 | ||
44 | #define WATCHDOG_NAME "w83697hf/hg WDT" | 44 | #define WATCHDOG_NAME "w83697hf/hg WDT" |
@@ -53,37 +53,43 @@ static DEFINE_SPINLOCK(io_lock); | |||
53 | /* You must set this - there is no sane way to probe for this board. */ | 53 | /* You must set this - there is no sane way to probe for this board. */ |
54 | static int wdt_io = 0x2e; | 54 | static int wdt_io = 0x2e; |
55 | module_param(wdt_io, int, 0); | 55 | module_param(wdt_io, int, 0); |
56 | MODULE_PARM_DESC(wdt_io, "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)"); | 56 | MODULE_PARM_DESC(wdt_io, |
57 | "w83697hf/hg WDT io port (default 0x2e, 0 = autodetect)"); | ||
57 | 58 | ||
58 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | 59 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ |
59 | module_param(timeout, int, 0); | 60 | module_param(timeout, int, 0); |
60 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255 (default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 61 | MODULE_PARM_DESC(timeout, |
62 | "Watchdog timeout in seconds. 1<= timeout <=255 (default=" | ||
63 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
61 | 64 | ||
62 | static int nowayout = WATCHDOG_NOWAYOUT; | 65 | static int nowayout = WATCHDOG_NOWAYOUT; |
63 | module_param(nowayout, int, 0); | 66 | module_param(nowayout, int, 0); |
64 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 67 | MODULE_PARM_DESC(nowayout, |
68 | "Watchdog cannot be stopped once started (default=" | ||
69 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
65 | 70 | ||
66 | static int early_disable = WATCHDOG_EARLY_DISABLE; | 71 | static int early_disable = WATCHDOG_EARLY_DISABLE; |
67 | module_param(early_disable, int, 0); | 72 | module_param(early_disable, int, 0); |
68 | MODULE_PARM_DESC(early_disable, "Watchdog gets disabled at boot time (default=" __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")"); | 73 | MODULE_PARM_DESC(early_disable, |
74 | "Watchdog gets disabled at boot time (default=" | ||
75 | __MODULE_STRING(WATCHDOG_EARLY_DISABLE) ")"); | ||
69 | 76 | ||
70 | /* | 77 | /* |
71 | * Kernel methods. | 78 | * Kernel methods. |
72 | */ | 79 | */ |
73 | 80 | ||
74 | #define W83697HF_EFER (wdt_io+0) /* Extended Function Enable Register */ | 81 | #define W83697HF_EFER (wdt_io + 0) /* Extended Function Enable Register */ |
75 | #define W83697HF_EFIR (wdt_io+0) /* Extended Function Index Register (same as EFER) */ | 82 | #define W83697HF_EFIR (wdt_io + 0) /* Extended Function Index Register |
76 | #define W83697HF_EFDR (wdt_io+1) /* Extended Function Data Register */ | 83 | (same as EFER) */ |
84 | #define W83697HF_EFDR (wdt_io + 1) /* Extended Function Data Register */ | ||
77 | 85 | ||
78 | static inline void | 86 | static inline void w83697hf_unlock(void) |
79 | w83697hf_unlock(void) | ||
80 | { | 87 | { |
81 | outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */ | 88 | outb_p(0x87, W83697HF_EFER); /* Enter extended function mode */ |
82 | outb_p(0x87, W83697HF_EFER); /* Again according to manual */ | 89 | outb_p(0x87, W83697HF_EFER); /* Again according to manual */ |
83 | } | 90 | } |
84 | 91 | ||
85 | static inline void | 92 | static inline void w83697hf_lock(void) |
86 | w83697hf_lock(void) | ||
87 | { | 93 | { |
88 | outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ | 94 | outb_p(0xAA, W83697HF_EFER); /* Leave extended function mode */ |
89 | } | 95 | } |
@@ -93,41 +99,36 @@ w83697hf_lock(void) | |||
93 | * w83697hf_write_timeout() must be called with the device unlocked. | 99 | * w83697hf_write_timeout() must be called with the device unlocked. |
94 | */ | 100 | */ |
95 | 101 | ||
96 | static unsigned char | 102 | static unsigned char w83697hf_get_reg(unsigned char reg) |
97 | w83697hf_get_reg(unsigned char reg) | ||
98 | { | 103 | { |
99 | outb_p(reg, W83697HF_EFIR); | 104 | outb_p(reg, W83697HF_EFIR); |
100 | return inb_p(W83697HF_EFDR); | 105 | return inb_p(W83697HF_EFDR); |
101 | } | 106 | } |
102 | 107 | ||
103 | static void | 108 | static void w83697hf_set_reg(unsigned char reg, unsigned char data) |
104 | w83697hf_set_reg(unsigned char reg, unsigned char data) | ||
105 | { | 109 | { |
106 | outb_p(reg, W83697HF_EFIR); | 110 | outb_p(reg, W83697HF_EFIR); |
107 | outb_p(data, W83697HF_EFDR); | 111 | outb_p(data, W83697HF_EFDR); |
108 | } | 112 | } |
109 | 113 | ||
110 | static void | 114 | static void w83697hf_write_timeout(int timeout) |
111 | w83697hf_write_timeout(int timeout) | ||
112 | { | 115 | { |
113 | w83697hf_set_reg(0xF4, timeout); /* Write Timeout counter to CRF4 */ | 116 | /* Write Timeout counter to CRF4 */ |
117 | w83697hf_set_reg(0xF4, timeout); | ||
114 | } | 118 | } |
115 | 119 | ||
116 | static void | 120 | static void w83697hf_select_wdt(void) |
117 | w83697hf_select_wdt(void) | ||
118 | { | 121 | { |
119 | w83697hf_unlock(); | 122 | w83697hf_unlock(); |
120 | w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */ | 123 | w83697hf_set_reg(0x07, 0x08); /* Switch to logic device 8 (GPIO2) */ |
121 | } | 124 | } |
122 | 125 | ||
123 | static inline void | 126 | static inline void w83697hf_deselect_wdt(void) |
124 | w83697hf_deselect_wdt(void) | ||
125 | { | 127 | { |
126 | w83697hf_lock(); | 128 | w83697hf_lock(); |
127 | } | 129 | } |
128 | 130 | ||
129 | static void | 131 | static void w83697hf_init(void) |
130 | w83697hf_init(void) | ||
131 | { | 132 | { |
132 | unsigned char bbuf; | 133 | unsigned char bbuf; |
133 | 134 | ||
@@ -136,7 +137,9 @@ w83697hf_init(void) | |||
136 | bbuf = w83697hf_get_reg(0x29); | 137 | bbuf = w83697hf_get_reg(0x29); |
137 | bbuf &= ~0x60; | 138 | bbuf &= ~0x60; |
138 | bbuf |= 0x20; | 139 | bbuf |= 0x20; |
139 | w83697hf_set_reg(0x29, bbuf); /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ | 140 | |
141 | /* Set pin 119 to WDTO# mode (= CR29, WDT0) */ | ||
142 | w83697hf_set_reg(0x29, bbuf); | ||
140 | 143 | ||
141 | bbuf = w83697hf_get_reg(0xF3); | 144 | bbuf = w83697hf_get_reg(0xF3); |
142 | bbuf &= ~0x04; | 145 | bbuf &= ~0x04; |
@@ -145,8 +148,7 @@ w83697hf_init(void) | |||
145 | w83697hf_deselect_wdt(); | 148 | w83697hf_deselect_wdt(); |
146 | } | 149 | } |
147 | 150 | ||
148 | static void | 151 | static void wdt_ping(void) |
149 | wdt_ping(void) | ||
150 | { | 152 | { |
151 | spin_lock(&io_lock); | 153 | spin_lock(&io_lock); |
152 | w83697hf_select_wdt(); | 154 | w83697hf_select_wdt(); |
@@ -157,8 +159,7 @@ wdt_ping(void) | |||
157 | spin_unlock(&io_lock); | 159 | spin_unlock(&io_lock); |
158 | } | 160 | } |
159 | 161 | ||
160 | static void | 162 | static void wdt_enable(void) |
161 | wdt_enable(void) | ||
162 | { | 163 | { |
163 | spin_lock(&io_lock); | 164 | spin_lock(&io_lock); |
164 | w83697hf_select_wdt(); | 165 | w83697hf_select_wdt(); |
@@ -170,8 +171,7 @@ wdt_enable(void) | |||
170 | spin_unlock(&io_lock); | 171 | spin_unlock(&io_lock); |
171 | } | 172 | } |
172 | 173 | ||
173 | static void | 174 | static void wdt_disable(void) |
174 | wdt_disable(void) | ||
175 | { | 175 | { |
176 | spin_lock(&io_lock); | 176 | spin_lock(&io_lock); |
177 | w83697hf_select_wdt(); | 177 | w83697hf_select_wdt(); |
@@ -183,8 +183,7 @@ wdt_disable(void) | |||
183 | spin_unlock(&io_lock); | 183 | spin_unlock(&io_lock); |
184 | } | 184 | } |
185 | 185 | ||
186 | static unsigned char | 186 | static unsigned char wdt_running(void) |
187 | wdt_running(void) | ||
188 | { | 187 | { |
189 | unsigned char t; | 188 | unsigned char t; |
190 | 189 | ||
@@ -199,18 +198,17 @@ wdt_running(void) | |||
199 | return t; | 198 | return t; |
200 | } | 199 | } |
201 | 200 | ||
202 | static int | 201 | static int wdt_set_heartbeat(int t) |
203 | wdt_set_heartbeat(int t) | ||
204 | { | 202 | { |
205 | if ((t < 1) || (t > 255)) | 203 | if (t < 1 || t > 255) |
206 | return -EINVAL; | 204 | return -EINVAL; |
207 | 205 | ||
208 | timeout = t; | 206 | timeout = t; |
209 | return 0; | 207 | return 0; |
210 | } | 208 | } |
211 | 209 | ||
212 | static ssize_t | 210 | static ssize_t wdt_write(struct file *file, const char __user *buf, |
213 | wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 211 | size_t count, loff_t *ppos) |
214 | { | 212 | { |
215 | if (count) { | 213 | if (count) { |
216 | if (!nowayout) { | 214 | if (!nowayout) { |
@@ -220,7 +218,7 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
220 | 218 | ||
221 | for (i = 0; i != count; i++) { | 219 | for (i = 0; i != count; i++) { |
222 | char c; | 220 | char c; |
223 | if (get_user(c, buf+i)) | 221 | if (get_user(c, buf + i)) |
224 | return -EFAULT; | 222 | return -EFAULT; |
225 | if (c == 'V') | 223 | if (c == 'V') |
226 | expect_close = 42; | 224 | expect_close = 42; |
@@ -231,15 +229,14 @@ wdt_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | |||
231 | return count; | 229 | return count; |
232 | } | 230 | } |
233 | 231 | ||
234 | static int | 232 | static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
235 | wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
236 | unsigned long arg) | ||
237 | { | 233 | { |
238 | void __user *argp = (void __user *)arg; | 234 | void __user *argp = (void __user *)arg; |
239 | int __user *p = argp; | 235 | int __user *p = argp; |
240 | int new_timeout; | 236 | int new_timeout; |
241 | static struct watchdog_info ident = { | 237 | static const struct watchdog_info ident = { |
242 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 238 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
239 | | WDIOF_MAGICCLOSE, | ||
243 | .firmware_version = 1, | 240 | .firmware_version = 1, |
244 | .identity = "W83697HF WDT", | 241 | .identity = "W83697HF WDT", |
245 | }; | 242 | }; |
@@ -254,21 +251,6 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
254 | case WDIOC_GETBOOTSTATUS: | 251 | case WDIOC_GETBOOTSTATUS: |
255 | return put_user(0, p); | 252 | return put_user(0, p); |
256 | 253 | ||
257 | case WDIOC_KEEPALIVE: | ||
258 | wdt_ping(); | ||
259 | break; | ||
260 | |||
261 | case WDIOC_SETTIMEOUT: | ||
262 | if (get_user(new_timeout, p)) | ||
263 | return -EFAULT; | ||
264 | if (wdt_set_heartbeat(new_timeout)) | ||
265 | return -EINVAL; | ||
266 | wdt_ping(); | ||
267 | /* Fall */ | ||
268 | |||
269 | case WDIOC_GETTIMEOUT: | ||
270 | return put_user(timeout, p); | ||
271 | |||
272 | case WDIOC_SETOPTIONS: | 254 | case WDIOC_SETOPTIONS: |
273 | { | 255 | { |
274 | int options, retval = -EINVAL; | 256 | int options, retval = -EINVAL; |
@@ -289,14 +271,28 @@ wdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
289 | return retval; | 271 | return retval; |
290 | } | 272 | } |
291 | 273 | ||
274 | case WDIOC_KEEPALIVE: | ||
275 | wdt_ping(); | ||
276 | break; | ||
277 | |||
278 | case WDIOC_SETTIMEOUT: | ||
279 | if (get_user(new_timeout, p)) | ||
280 | return -EFAULT; | ||
281 | if (wdt_set_heartbeat(new_timeout)) | ||
282 | return -EINVAL; | ||
283 | wdt_ping(); | ||
284 | /* Fall */ | ||
285 | |||
286 | case WDIOC_GETTIMEOUT: | ||
287 | return put_user(timeout, p); | ||
288 | |||
292 | default: | 289 | default: |
293 | return -ENOTTY; | 290 | return -ENOTTY; |
294 | } | 291 | } |
295 | return 0; | 292 | return 0; |
296 | } | 293 | } |
297 | 294 | ||
298 | static int | 295 | static int wdt_open(struct inode *inode, struct file *file) |
299 | wdt_open(struct inode *inode, struct file *file) | ||
300 | { | 296 | { |
301 | if (test_and_set_bit(0, &wdt_is_open)) | 297 | if (test_and_set_bit(0, &wdt_is_open)) |
302 | return -EBUSY; | 298 | return -EBUSY; |
@@ -308,13 +304,13 @@ wdt_open(struct inode *inode, struct file *file) | |||
308 | return nonseekable_open(inode, file); | 304 | return nonseekable_open(inode, file); |
309 | } | 305 | } |
310 | 306 | ||
311 | static int | 307 | static int wdt_close(struct inode *inode, struct file *file) |
312 | wdt_close(struct inode *inode, struct file *file) | ||
313 | { | 308 | { |
314 | if (expect_close == 42) { | 309 | if (expect_close == 42) |
315 | wdt_disable(); | 310 | wdt_disable(); |
316 | } else { | 311 | else { |
317 | printk (KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 312 | printk(KERN_CRIT PFX |
313 | "Unexpected close, not stopping watchdog!\n"); | ||
318 | wdt_ping(); | 314 | wdt_ping(); |
319 | } | 315 | } |
320 | expect_close = 0; | 316 | expect_close = 0; |
@@ -326,14 +322,12 @@ wdt_close(struct inode *inode, struct file *file) | |||
326 | * Notifier for system down | 322 | * Notifier for system down |
327 | */ | 323 | */ |
328 | 324 | ||
329 | static int | 325 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, |
330 | wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
331 | void *unused) | 326 | void *unused) |
332 | { | 327 | { |
333 | if (code == SYS_DOWN || code == SYS_HALT) { | 328 | if (code == SYS_DOWN || code == SYS_HALT) |
334 | /* Turn the WDT off */ | 329 | wdt_disable(); /* Turn the WDT off */ |
335 | wdt_disable(); | 330 | |
336 | } | ||
337 | return NOTIFY_DONE; | 331 | return NOTIFY_DONE; |
338 | } | 332 | } |
339 | 333 | ||
@@ -345,7 +339,7 @@ static const struct file_operations wdt_fops = { | |||
345 | .owner = THIS_MODULE, | 339 | .owner = THIS_MODULE, |
346 | .llseek = no_llseek, | 340 | .llseek = no_llseek, |
347 | .write = wdt_write, | 341 | .write = wdt_write, |
348 | .ioctl = wdt_ioctl, | 342 | .unlocked_ioctl = wdt_ioctl, |
349 | .open = wdt_open, | 343 | .open = wdt_open, |
350 | .release = wdt_close, | 344 | .release = wdt_close, |
351 | }; | 345 | }; |
@@ -365,36 +359,38 @@ static struct notifier_block wdt_notifier = { | |||
365 | .notifier_call = wdt_notify_sys, | 359 | .notifier_call = wdt_notify_sys, |
366 | }; | 360 | }; |
367 | 361 | ||
368 | static int | 362 | static int w83697hf_check_wdt(void) |
369 | w83697hf_check_wdt(void) | ||
370 | { | 363 | { |
371 | if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { | 364 | if (!request_region(wdt_io, 2, WATCHDOG_NAME)) { |
372 | printk (KERN_ERR PFX "I/O address 0x%x already in use\n", wdt_io); | 365 | printk(KERN_ERR PFX |
366 | "I/O address 0x%x already in use\n", wdt_io); | ||
373 | return -EIO; | 367 | return -EIO; |
374 | } | 368 | } |
375 | 369 | ||
376 | printk (KERN_DEBUG PFX "Looking for watchdog at address 0x%x\n", wdt_io); | 370 | printk(KERN_DEBUG PFX |
371 | "Looking for watchdog at address 0x%x\n", wdt_io); | ||
377 | w83697hf_unlock(); | 372 | w83697hf_unlock(); |
378 | if (w83697hf_get_reg(0x20) == 0x60) { | 373 | if (w83697hf_get_reg(0x20) == 0x60) { |
379 | printk (KERN_INFO PFX "watchdog found at address 0x%x\n", wdt_io); | 374 | printk(KERN_INFO PFX |
375 | "watchdog found at address 0x%x\n", wdt_io); | ||
380 | w83697hf_lock(); | 376 | w83697hf_lock(); |
381 | return 0; | 377 | return 0; |
382 | } | 378 | } |
383 | w83697hf_lock(); /* Reprotect in case it was a compatible device */ | 379 | /* Reprotect in case it was a compatible device */ |
380 | w83697hf_lock(); | ||
384 | 381 | ||
385 | printk (KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io); | 382 | printk(KERN_INFO PFX "watchdog not found at address 0x%x\n", wdt_io); |
386 | release_region(wdt_io, 2); | 383 | release_region(wdt_io, 2); |
387 | return -EIO; | 384 | return -EIO; |
388 | } | 385 | } |
389 | 386 | ||
390 | static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 }; | 387 | static int w83697hf_ioports[] = { 0x2e, 0x4e, 0x00 }; |
391 | 388 | ||
392 | static int __init | 389 | static int __init wdt_init(void) |
393 | wdt_init(void) | ||
394 | { | 390 | { |
395 | int ret, i, found = 0; | 391 | int ret, i, found = 0; |
396 | 392 | ||
397 | printk (KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); | 393 | printk(KERN_INFO PFX "WDT driver for W83697HF/HG initializing\n"); |
398 | 394 | ||
399 | if (wdt_io == 0) { | 395 | if (wdt_io == 0) { |
400 | /* we will autodetect the W83697HF/HG watchdog */ | 396 | /* we will autodetect the W83697HF/HG watchdog */ |
@@ -409,7 +405,7 @@ wdt_init(void) | |||
409 | } | 405 | } |
410 | 406 | ||
411 | if (!found) { | 407 | if (!found) { |
412 | printk (KERN_ERR PFX "No W83697HF/HG could be found\n"); | 408 | printk(KERN_ERR PFX "No W83697HF/HG could be found\n"); |
413 | ret = -EIO; | 409 | ret = -EIO; |
414 | goto out; | 410 | goto out; |
415 | } | 411 | } |
@@ -417,31 +413,33 @@ wdt_init(void) | |||
417 | w83697hf_init(); | 413 | w83697hf_init(); |
418 | if (early_disable) { | 414 | if (early_disable) { |
419 | if (wdt_running()) | 415 | if (wdt_running()) |
420 | printk (KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n"); | 416 | printk(KERN_WARNING PFX "Stopping previously enabled watchdog until userland kicks in\n"); |
421 | wdt_disable(); | 417 | wdt_disable(); |
422 | } | 418 | } |
423 | 419 | ||
424 | if (wdt_set_heartbeat(timeout)) { | 420 | if (wdt_set_heartbeat(timeout)) { |
425 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | 421 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); |
426 | printk (KERN_INFO PFX "timeout value must be 1<=timeout<=255, using %d\n", | 422 | printk(KERN_INFO PFX |
427 | WATCHDOG_TIMEOUT); | 423 | "timeout value must be 1 <= timeout <= 255, using %d\n", |
424 | WATCHDOG_TIMEOUT); | ||
428 | } | 425 | } |
429 | 426 | ||
430 | ret = register_reboot_notifier(&wdt_notifier); | 427 | ret = register_reboot_notifier(&wdt_notifier); |
431 | if (ret != 0) { | 428 | if (ret != 0) { |
432 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 429 | printk(KERN_ERR PFX |
433 | ret); | 430 | "cannot register reboot notifier (err=%d)\n", ret); |
434 | goto unreg_regions; | 431 | goto unreg_regions; |
435 | } | 432 | } |
436 | 433 | ||
437 | ret = misc_register(&wdt_miscdev); | 434 | ret = misc_register(&wdt_miscdev); |
438 | if (ret != 0) { | 435 | if (ret != 0) { |
439 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 436 | printk(KERN_ERR PFX |
440 | WATCHDOG_MINOR, ret); | 437 | "cannot register miscdev on minor=%d (err=%d)\n", |
438 | WATCHDOG_MINOR, ret); | ||
441 | goto unreg_reboot; | 439 | goto unreg_reboot; |
442 | } | 440 | } |
443 | 441 | ||
444 | printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", | 442 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", |
445 | timeout, nowayout); | 443 | timeout, nowayout); |
446 | 444 | ||
447 | out: | 445 | out: |
@@ -453,8 +451,7 @@ unreg_regions: | |||
453 | goto out; | 451 | goto out; |
454 | } | 452 | } |
455 | 453 | ||
456 | static void __exit | 454 | static void __exit wdt_exit(void) |
457 | wdt_exit(void) | ||
458 | { | 455 | { |
459 | misc_deregister(&wdt_miscdev); | 456 | misc_deregister(&wdt_miscdev); |
460 | unregister_reboot_notifier(&wdt_notifier); | 457 | unregister_reboot_notifier(&wdt_notifier); |
diff --git a/drivers/watchdog/w83877f_wdt.c b/drivers/watchdog/w83877f_wdt.c index f510a3a595e6..24587d2060c4 100644 --- a/drivers/watchdog/w83877f_wdt.c +++ b/drivers/watchdog/w83877f_wdt.c | |||
@@ -23,13 +23,16 @@ | |||
23 | * Added KERN_* tags to printks | 23 | * Added KERN_* tags to printks |
24 | * add CONFIG_WATCHDOG_NOWAYOUT support | 24 | * add CONFIG_WATCHDOG_NOWAYOUT support |
25 | * fix possible wdt_is_open race | 25 | * fix possible wdt_is_open race |
26 | * changed watchdog_info to correctly reflect what the driver offers | 26 | * changed watchdog_info to correctly reflect what |
27 | * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, WDIOC_SETTIMEOUT, | 27 | * the driver offers |
28 | * added WDIOC_GETSTATUS, WDIOC_GETBOOTSTATUS, | ||
29 | * WDIOC_SETTIMEOUT, | ||
28 | * WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls | 30 | * WDIOC_GETTIMEOUT, and WDIOC_SETOPTIONS ioctls |
29 | * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces | 31 | * 09/8 - 2003 [wim@iguana.be] cleanup of trailing spaces |
30 | * added extra printk's for startup problems | 32 | * added extra printk's for startup problems |
31 | * use module_param | 33 | * use module_param |
32 | * made timeout (the emulated heartbeat) a module_param | 34 | * made timeout (the emulated heartbeat) a |
35 | * module_param | ||
33 | * made the keepalive ping an internal subroutine | 36 | * made the keepalive ping an internal subroutine |
34 | * | 37 | * |
35 | * This WDT driver is different from most other Linux WDT | 38 | * This WDT driver is different from most other Linux WDT |
@@ -51,8 +54,8 @@ | |||
51 | #include <linux/notifier.h> | 54 | #include <linux/notifier.h> |
52 | #include <linux/reboot.h> | 55 | #include <linux/reboot.h> |
53 | #include <linux/init.h> | 56 | #include <linux/init.h> |
54 | #include <asm/io.h> | 57 | #include <linux/io.h> |
55 | #include <asm/uaccess.h> | 58 | #include <linux/uaccess.h> |
56 | #include <asm/system.h> | 59 | #include <asm/system.h> |
57 | 60 | ||
58 | #define OUR_NAME "w83877f_wdt" | 61 | #define OUR_NAME "w83877f_wdt" |
@@ -80,14 +83,19 @@ | |||
80 | */ | 83 | */ |
81 | 84 | ||
82 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ | 85 | #define WATCHDOG_TIMEOUT 30 /* 30 sec default timeout */ |
83 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ | 86 | /* in seconds, will be multiplied by HZ to get seconds to wait for a ping */ |
87 | static int timeout = WATCHDOG_TIMEOUT; | ||
84 | module_param(timeout, int, 0); | 88 | module_param(timeout, int, 0); |
85 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. (1<=timeout<=3600, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | 89 | MODULE_PARM_DESC(timeout, |
90 | "Watchdog timeout in seconds. (1<=timeout<=3600, default=" | ||
91 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
86 | 92 | ||
87 | 93 | ||
88 | static int nowayout = WATCHDOG_NOWAYOUT; | 94 | static int nowayout = WATCHDOG_NOWAYOUT; |
89 | module_param(nowayout, int, 0); | 95 | module_param(nowayout, int, 0); |
90 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 96 | MODULE_PARM_DESC(nowayout, |
97 | "Watchdog cannot be stopped once started (default=" | ||
98 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
91 | 99 | ||
92 | static void wdt_timer_ping(unsigned long); | 100 | static void wdt_timer_ping(unsigned long); |
93 | static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); | 101 | static DEFINE_TIMER(timer, wdt_timer_ping, 0, 0); |
@@ -105,8 +113,7 @@ static void wdt_timer_ping(unsigned long data) | |||
105 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL | 113 | /* If we got a heartbeat pulse within the WDT_US_INTERVAL |
106 | * we agree to ping the WDT | 114 | * we agree to ping the WDT |
107 | */ | 115 | */ |
108 | if(time_before(jiffies, next_heartbeat)) | 116 | if (time_before(jiffies, next_heartbeat)) { |
109 | { | ||
110 | /* Ping the WDT */ | 117 | /* Ping the WDT */ |
111 | spin_lock(&wdt_spinlock); | 118 | spin_lock(&wdt_spinlock); |
112 | 119 | ||
@@ -118,9 +125,9 @@ static void wdt_timer_ping(unsigned long data) | |||
118 | 125 | ||
119 | spin_unlock(&wdt_spinlock); | 126 | spin_unlock(&wdt_spinlock); |
120 | 127 | ||
121 | } else { | 128 | } else |
122 | printk(KERN_WARNING PFX "Heartbeat lost! Will not ping the watchdog\n"); | 129 | printk(KERN_WARNING PFX |
123 | } | 130 | "Heartbeat lost! Will not ping the watchdog\n"); |
124 | } | 131 | } |
125 | 132 | ||
126 | /* | 133 | /* |
@@ -181,22 +188,21 @@ static void wdt_keepalive(void) | |||
181 | * /dev/watchdog handling | 188 | * /dev/watchdog handling |
182 | */ | 189 | */ |
183 | 190 | ||
184 | static ssize_t fop_write(struct file * file, const char __user * buf, size_t count, loff_t * ppos) | 191 | static ssize_t fop_write(struct file *file, const char __user *buf, |
192 | size_t count, loff_t *ppos) | ||
185 | { | 193 | { |
186 | /* See if we got the magic character 'V' and reload the timer */ | 194 | /* See if we got the magic character 'V' and reload the timer */ |
187 | if(count) | 195 | if (count) { |
188 | { | 196 | if (!nowayout) { |
189 | if (!nowayout) | ||
190 | { | ||
191 | size_t ofs; | 197 | size_t ofs; |
192 | 198 | ||
193 | /* note: just in case someone wrote the magic character | 199 | /* note: just in case someone wrote the magic |
194 | * five months ago... */ | 200 | character five months ago... */ |
195 | wdt_expect_close = 0; | 201 | wdt_expect_close = 0; |
196 | 202 | ||
197 | /* scan to see whether or not we got the magic character */ | 203 | /* scan to see whether or not we got the |
198 | for(ofs = 0; ofs != count; ofs++) | 204 | magic character */ |
199 | { | 205 | for (ofs = 0; ofs != count; ofs++) { |
200 | char c; | 206 | char c; |
201 | if (get_user(c, buf + ofs)) | 207 | if (get_user(c, buf + ofs)) |
202 | return -EFAULT; | 208 | return -EFAULT; |
@@ -211,10 +217,10 @@ static ssize_t fop_write(struct file * file, const char __user * buf, size_t cou | |||
211 | return count; | 217 | return count; |
212 | } | 218 | } |
213 | 219 | ||
214 | static int fop_open(struct inode * inode, struct file * file) | 220 | static int fop_open(struct inode *inode, struct file *file) |
215 | { | 221 | { |
216 | /* Just in case we're already talking to someone... */ | 222 | /* Just in case we're already talking to someone... */ |
217 | if(test_and_set_bit(0, &wdt_is_open)) | 223 | if (test_and_set_bit(0, &wdt_is_open)) |
218 | return -EBUSY; | 224 | return -EBUSY; |
219 | 225 | ||
220 | /* Good, fire up the show */ | 226 | /* Good, fire up the show */ |
@@ -222,78 +228,78 @@ static int fop_open(struct inode * inode, struct file * file) | |||
222 | return nonseekable_open(inode, file); | 228 | return nonseekable_open(inode, file); |
223 | } | 229 | } |
224 | 230 | ||
225 | static int fop_close(struct inode * inode, struct file * file) | 231 | static int fop_close(struct inode *inode, struct file *file) |
226 | { | 232 | { |
227 | if(wdt_expect_close == 42) | 233 | if (wdt_expect_close == 42) |
228 | wdt_turnoff(); | 234 | wdt_turnoff(); |
229 | else { | 235 | else { |
230 | del_timer(&timer); | 236 | del_timer(&timer); |
231 | printk(KERN_CRIT PFX "device file closed unexpectedly. Will not stop the WDT!\n"); | 237 | printk(KERN_CRIT PFX |
238 | "device file closed unexpectedly. Will not stop the WDT!\n"); | ||
232 | } | 239 | } |
233 | clear_bit(0, &wdt_is_open); | 240 | clear_bit(0, &wdt_is_open); |
234 | wdt_expect_close = 0; | 241 | wdt_expect_close = 0; |
235 | return 0; | 242 | return 0; |
236 | } | 243 | } |
237 | 244 | ||
238 | static int fop_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 245 | static long fop_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
239 | unsigned long arg) | ||
240 | { | 246 | { |
241 | void __user *argp = (void __user *)arg; | 247 | void __user *argp = (void __user *)arg; |
242 | int __user *p = argp; | 248 | int __user *p = argp; |
243 | static struct watchdog_info ident= | 249 | static const struct watchdog_info ident = { |
244 | { | 250 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT |
245 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 251 | | WDIOF_MAGICCLOSE, |
246 | .firmware_version = 1, | 252 | .firmware_version = 1, |
247 | .identity = "W83877F", | 253 | .identity = "W83877F", |
248 | }; | 254 | }; |
249 | 255 | ||
250 | switch(cmd) | 256 | switch (cmd) { |
257 | case WDIOC_GETSUPPORT: | ||
258 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | ||
259 | case WDIOC_GETSTATUS: | ||
260 | case WDIOC_GETBOOTSTATUS: | ||
261 | return put_user(0, p); | ||
262 | case WDIOC_SETOPTIONS: | ||
251 | { | 263 | { |
252 | default: | 264 | int new_options, retval = -EINVAL; |
253 | return -ENOTTY; | ||
254 | case WDIOC_GETSUPPORT: | ||
255 | return copy_to_user(argp, &ident, sizeof(ident))?-EFAULT:0; | ||
256 | case WDIOC_GETSTATUS: | ||
257 | case WDIOC_GETBOOTSTATUS: | ||
258 | return put_user(0, p); | ||
259 | case WDIOC_KEEPALIVE: | ||
260 | wdt_keepalive(); | ||
261 | return 0; | ||
262 | case WDIOC_SETOPTIONS: | ||
263 | { | ||
264 | int new_options, retval = -EINVAL; | ||
265 | |||
266 | if(get_user(new_options, p)) | ||
267 | return -EFAULT; | ||
268 | |||
269 | if(new_options & WDIOS_DISABLECARD) { | ||
270 | wdt_turnoff(); | ||
271 | retval = 0; | ||
272 | } | ||
273 | 265 | ||
274 | if(new_options & WDIOS_ENABLECARD) { | 266 | if (get_user(new_options, p)) |
275 | wdt_startup(); | 267 | return -EFAULT; |
276 | retval = 0; | ||
277 | } | ||
278 | 268 | ||
279 | return retval; | 269 | if (new_options & WDIOS_DISABLECARD) { |
270 | wdt_turnoff(); | ||
271 | retval = 0; | ||
280 | } | 272 | } |
281 | case WDIOC_SETTIMEOUT: | ||
282 | { | ||
283 | int new_timeout; | ||
284 | 273 | ||
285 | if(get_user(new_timeout, p)) | 274 | if (new_options & WDIOS_ENABLECARD) { |
286 | return -EFAULT; | 275 | wdt_startup(); |
276 | retval = 0; | ||
277 | } | ||
287 | 278 | ||
288 | if(new_timeout < 1 || new_timeout > 3600) /* arbitrary upper limit */ | 279 | return retval; |
289 | return -EINVAL; | 280 | } |
281 | case WDIOC_KEEPALIVE: | ||
282 | wdt_keepalive(); | ||
283 | return 0; | ||
284 | case WDIOC_SETTIMEOUT: | ||
285 | { | ||
286 | int new_timeout; | ||
290 | 287 | ||
291 | timeout = new_timeout; | 288 | if (get_user(new_timeout, p)) |
292 | wdt_keepalive(); | 289 | return -EFAULT; |
293 | /* Fall through */ | 290 | |
294 | } | 291 | /* arbitrary upper limit */ |
295 | case WDIOC_GETTIMEOUT: | 292 | if (new_timeout < 1 || new_timeout > 3600) |
296 | return put_user(timeout, p); | 293 | return -EINVAL; |
294 | |||
295 | timeout = new_timeout; | ||
296 | wdt_keepalive(); | ||
297 | /* Fall through */ | ||
298 | } | ||
299 | case WDIOC_GETTIMEOUT: | ||
300 | return put_user(timeout, p); | ||
301 | default: | ||
302 | return -ENOTTY; | ||
297 | } | 303 | } |
298 | } | 304 | } |
299 | 305 | ||
@@ -303,7 +309,7 @@ static const struct file_operations wdt_fops = { | |||
303 | .write = fop_write, | 309 | .write = fop_write, |
304 | .open = fop_open, | 310 | .open = fop_open, |
305 | .release = fop_close, | 311 | .release = fop_close, |
306 | .ioctl = fop_ioctl, | 312 | .unlocked_ioctl = fop_ioctl, |
307 | }; | 313 | }; |
308 | 314 | ||
309 | static struct miscdevice wdt_miscdev = { | 315 | static struct miscdevice wdt_miscdev = { |
@@ -319,7 +325,7 @@ static struct miscdevice wdt_miscdev = { | |||
319 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | 325 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, |
320 | void *unused) | 326 | void *unused) |
321 | { | 327 | { |
322 | if(code==SYS_DOWN || code==SYS_HALT) | 328 | if (code == SYS_DOWN || code == SYS_HALT) |
323 | wdt_turnoff(); | 329 | wdt_turnoff(); |
324 | return NOTIFY_DONE; | 330 | return NOTIFY_DONE; |
325 | } | 331 | } |
@@ -329,8 +335,7 @@ static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | |||
329 | * turn the timebomb registers off. | 335 | * turn the timebomb registers off. |
330 | */ | 336 | */ |
331 | 337 | ||
332 | static struct notifier_block wdt_notifier= | 338 | static struct notifier_block wdt_notifier = { |
333 | { | ||
334 | .notifier_call = wdt_notify_sys, | 339 | .notifier_call = wdt_notify_sys, |
335 | }; | 340 | }; |
336 | 341 | ||
@@ -342,31 +347,29 @@ static void __exit w83877f_wdt_unload(void) | |||
342 | misc_deregister(&wdt_miscdev); | 347 | misc_deregister(&wdt_miscdev); |
343 | 348 | ||
344 | unregister_reboot_notifier(&wdt_notifier); | 349 | unregister_reboot_notifier(&wdt_notifier); |
345 | release_region(WDT_PING,1); | 350 | release_region(WDT_PING, 1); |
346 | release_region(ENABLE_W83877F_PORT,2); | 351 | release_region(ENABLE_W83877F_PORT, 2); |
347 | } | 352 | } |
348 | 353 | ||
349 | static int __init w83877f_wdt_init(void) | 354 | static int __init w83877f_wdt_init(void) |
350 | { | 355 | { |
351 | int rc = -EBUSY; | 356 | int rc = -EBUSY; |
352 | 357 | ||
353 | if(timeout < 1 || timeout > 3600) /* arbitrary upper limit */ | 358 | if (timeout < 1 || timeout > 3600) { /* arbitrary upper limit */ |
354 | { | ||
355 | timeout = WATCHDOG_TIMEOUT; | 359 | timeout = WATCHDOG_TIMEOUT; |
356 | printk(KERN_INFO PFX "timeout value must be 1<=x<=3600, using %d\n", | 360 | printk(KERN_INFO PFX |
357 | timeout); | 361 | "timeout value must be 1 <= x <= 3600, using %d\n", |
362 | timeout); | ||
358 | } | 363 | } |
359 | 364 | ||
360 | if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) | 365 | if (!request_region(ENABLE_W83877F_PORT, 2, "W83877F WDT")) { |
361 | { | ||
362 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | 366 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
363 | ENABLE_W83877F_PORT); | 367 | ENABLE_W83877F_PORT); |
364 | rc = -EIO; | 368 | rc = -EIO; |
365 | goto err_out; | 369 | goto err_out; |
366 | } | 370 | } |
367 | 371 | ||
368 | if (!request_region(WDT_PING, 1, "W8387FF WDT")) | 372 | if (!request_region(WDT_PING, 1, "W8387FF WDT")) { |
369 | { | ||
370 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | 373 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
371 | WDT_PING); | 374 | WDT_PING); |
372 | rc = -EIO; | 375 | rc = -EIO; |
@@ -374,22 +377,22 @@ static int __init w83877f_wdt_init(void) | |||
374 | } | 377 | } |
375 | 378 | ||
376 | rc = register_reboot_notifier(&wdt_notifier); | 379 | rc = register_reboot_notifier(&wdt_notifier); |
377 | if (rc) | 380 | if (rc) { |
378 | { | 381 | printk(KERN_ERR PFX |
379 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 382 | "cannot register reboot notifier (err=%d)\n", rc); |
380 | rc); | ||
381 | goto err_out_region2; | 383 | goto err_out_region2; |
382 | } | 384 | } |
383 | 385 | ||
384 | rc = misc_register(&wdt_miscdev); | 386 | rc = misc_register(&wdt_miscdev); |
385 | if (rc) | 387 | if (rc) { |
386 | { | 388 | printk(KERN_ERR PFX |
387 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 389 | "cannot register miscdev on minor=%d (err=%d)\n", |
388 | wdt_miscdev.minor, rc); | 390 | wdt_miscdev.minor, rc); |
389 | goto err_out_reboot; | 391 | goto err_out_reboot; |
390 | } | 392 | } |
391 | 393 | ||
392 | printk(KERN_INFO PFX "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n", | 394 | printk(KERN_INFO PFX |
395 | "WDT driver for W83877F initialised. timeout=%d sec (nowayout=%d)\n", | ||
393 | timeout, nowayout); | 396 | timeout, nowayout); |
394 | 397 | ||
395 | return 0; | 398 | return 0; |
@@ -397,9 +400,9 @@ static int __init w83877f_wdt_init(void) | |||
397 | err_out_reboot: | 400 | err_out_reboot: |
398 | unregister_reboot_notifier(&wdt_notifier); | 401 | unregister_reboot_notifier(&wdt_notifier); |
399 | err_out_region2: | 402 | err_out_region2: |
400 | release_region(WDT_PING,1); | 403 | release_region(WDT_PING, 1); |
401 | err_out_region1: | 404 | err_out_region1: |
402 | release_region(ENABLE_W83877F_PORT,2); | 405 | release_region(ENABLE_W83877F_PORT, 2); |
403 | err_out: | 406 | err_out: |
404 | return rc; | 407 | return rc; |
405 | } | 408 | } |
diff --git a/drivers/watchdog/w83977f_wdt.c b/drivers/watchdog/w83977f_wdt.c index b209bcd7f789..2525da5080ca 100644 --- a/drivers/watchdog/w83977f_wdt.c +++ b/drivers/watchdog/w83977f_wdt.c | |||
@@ -26,10 +26,10 @@ | |||
26 | #include <linux/watchdog.h> | 26 | #include <linux/watchdog.h> |
27 | #include <linux/notifier.h> | 27 | #include <linux/notifier.h> |
28 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
29 | #include <linux/uaccess.h> | ||
30 | #include <linux/io.h> | ||
29 | 31 | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/system.h> | 32 | #include <asm/system.h> |
32 | #include <asm/uaccess.h> | ||
33 | 33 | ||
34 | #define WATCHDOG_VERSION "1.00" | 34 | #define WATCHDOG_VERSION "1.00" |
35 | #define WATCHDOG_NAME "W83977F WDT" | 35 | #define WATCHDOG_NAME "W83977F WDT" |
@@ -53,13 +53,17 @@ static char expect_close; | |||
53 | static DEFINE_SPINLOCK(spinlock); | 53 | static DEFINE_SPINLOCK(spinlock); |
54 | 54 | ||
55 | module_param(timeout, int, 0); | 55 | module_param(timeout, int, 0); |
56 | MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (15..7635), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); | 56 | MODULE_PARM_DESC(timeout, |
57 | "Watchdog timeout in seconds (15..7635), default=" | ||
58 | __MODULE_STRING(DEFAULT_TIMEOUT) ")"); | ||
57 | module_param(testmode, int, 0); | 59 | module_param(testmode, int, 0); |
58 | MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); | 60 | MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0"); |
59 | 61 | ||
60 | static int nowayout = WATCHDOG_NOWAYOUT; | 62 | static int nowayout = WATCHDOG_NOWAYOUT; |
61 | module_param(nowayout, int, 0); | 63 | module_param(nowayout, int, 0); |
62 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 64 | MODULE_PARM_DESC(nowayout, |
65 | "Watchdog cannot be stopped once started (default=" | ||
66 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
63 | 67 | ||
64 | /* | 68 | /* |
65 | * Start the watchdog | 69 | * Start the watchdog |
@@ -72,8 +76,8 @@ static int wdt_start(void) | |||
72 | spin_lock_irqsave(&spinlock, flags); | 76 | spin_lock_irqsave(&spinlock, flags); |
73 | 77 | ||
74 | /* Unlock the SuperIO chip */ | 78 | /* Unlock the SuperIO chip */ |
75 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 79 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
76 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 80 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
77 | 81 | ||
78 | /* | 82 | /* |
79 | * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. | 83 | * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. |
@@ -81,50 +85,49 @@ static int wdt_start(void) | |||
81 | * F3 is set to enable watchdog LED blink at timeout. | 85 | * F3 is set to enable watchdog LED blink at timeout. |
82 | * F4 is used to just clear the TIMEOUT'ed state (bit 0). | 86 | * F4 is used to just clear the TIMEOUT'ed state (bit 0). |
83 | */ | 87 | */ |
84 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | 88 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
85 | outb_p(0x08,IO_DATA_PORT); | 89 | outb_p(0x08, IO_DATA_PORT); |
86 | outb_p(0xF2,IO_INDEX_PORT); | 90 | outb_p(0xF2, IO_INDEX_PORT); |
87 | outb_p(timeoutW,IO_DATA_PORT); | 91 | outb_p(timeoutW, IO_DATA_PORT); |
88 | outb_p(0xF3,IO_INDEX_PORT); | 92 | outb_p(0xF3, IO_INDEX_PORT); |
89 | outb_p(0x08,IO_DATA_PORT); | 93 | outb_p(0x08, IO_DATA_PORT); |
90 | outb_p(0xF4,IO_INDEX_PORT); | 94 | outb_p(0xF4, IO_INDEX_PORT); |
91 | outb_p(0x00,IO_DATA_PORT); | 95 | outb_p(0x00, IO_DATA_PORT); |
92 | 96 | ||
93 | /* Set device Aux2 active */ | 97 | /* Set device Aux2 active */ |
94 | outb_p(0x30,IO_INDEX_PORT); | 98 | outb_p(0x30, IO_INDEX_PORT); |
95 | outb_p(0x01,IO_DATA_PORT); | 99 | outb_p(0x01, IO_DATA_PORT); |
96 | 100 | ||
97 | /* | 101 | /* |
98 | * Select device Aux1 (dev=7) to set GP16 as the watchdog output | 102 | * Select device Aux1 (dev=7) to set GP16 as the watchdog output |
99 | * (in reg E6) and GP13 as the watchdog LED output (in reg E3). | 103 | * (in reg E6) and GP13 as the watchdog LED output (in reg E3). |
100 | * Map GP16 at pin 119. | 104 | * Map GP16 at pin 119. |
101 | * In test mode watch the bit 0 on F4 to indicate "triggered" or | 105 | * In test mode watch the bit 0 on F4 to indicate "triggered" or |
102 | * check watchdog LED on SBC. | 106 | * check watchdog LED on SBC. |
103 | */ | 107 | */ |
104 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | 108 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
105 | outb_p(0x07,IO_DATA_PORT); | 109 | outb_p(0x07, IO_DATA_PORT); |
106 | if (!testmode) | 110 | if (!testmode) { |
107 | { | ||
108 | unsigned pin_map; | 111 | unsigned pin_map; |
109 | 112 | ||
110 | outb_p(0xE6,IO_INDEX_PORT); | 113 | outb_p(0xE6, IO_INDEX_PORT); |
111 | outb_p(0x0A,IO_DATA_PORT); | 114 | outb_p(0x0A, IO_DATA_PORT); |
112 | outb_p(0x2C,IO_INDEX_PORT); | 115 | outb_p(0x2C, IO_INDEX_PORT); |
113 | pin_map = inb_p(IO_DATA_PORT); | 116 | pin_map = inb_p(IO_DATA_PORT); |
114 | pin_map |= 0x10; | 117 | pin_map |= 0x10; |
115 | pin_map &= ~(0x20); | 118 | pin_map &= ~(0x20); |
116 | outb_p(0x2C,IO_INDEX_PORT); | 119 | outb_p(0x2C, IO_INDEX_PORT); |
117 | outb_p(pin_map,IO_DATA_PORT); | 120 | outb_p(pin_map, IO_DATA_PORT); |
118 | } | 121 | } |
119 | outb_p(0xE3,IO_INDEX_PORT); | 122 | outb_p(0xE3, IO_INDEX_PORT); |
120 | outb_p(0x08,IO_DATA_PORT); | 123 | outb_p(0x08, IO_DATA_PORT); |
121 | 124 | ||
122 | /* Set device Aux1 active */ | 125 | /* Set device Aux1 active */ |
123 | outb_p(0x30,IO_INDEX_PORT); | 126 | outb_p(0x30, IO_INDEX_PORT); |
124 | outb_p(0x01,IO_DATA_PORT); | 127 | outb_p(0x01, IO_DATA_PORT); |
125 | 128 | ||
126 | /* Lock the SuperIO chip */ | 129 | /* Lock the SuperIO chip */ |
127 | outb_p(LOCK_DATA,IO_INDEX_PORT); | 130 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
128 | 131 | ||
129 | spin_unlock_irqrestore(&spinlock, flags); | 132 | spin_unlock_irqrestore(&spinlock, flags); |
130 | 133 | ||
@@ -144,42 +147,41 @@ static int wdt_stop(void) | |||
144 | spin_lock_irqsave(&spinlock, flags); | 147 | spin_lock_irqsave(&spinlock, flags); |
145 | 148 | ||
146 | /* Unlock the SuperIO chip */ | 149 | /* Unlock the SuperIO chip */ |
147 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 150 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
148 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 151 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
149 | 152 | ||
150 | /* | 153 | /* |
151 | * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. | 154 | * Select device Aux2 (device=8) to set watchdog regs F2, F3 and F4. |
152 | * F2 is reset to its default value (watchdog timer disabled). | 155 | * F2 is reset to its default value (watchdog timer disabled). |
153 | * F3 is reset to its default state. | 156 | * F3 is reset to its default state. |
154 | * F4 clears the TIMEOUT'ed state (bit 0) - back to default. | 157 | * F4 clears the TIMEOUT'ed state (bit 0) - back to default. |
155 | */ | 158 | */ |
156 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | 159 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
157 | outb_p(0x08,IO_DATA_PORT); | 160 | outb_p(0x08, IO_DATA_PORT); |
158 | outb_p(0xF2,IO_INDEX_PORT); | 161 | outb_p(0xF2, IO_INDEX_PORT); |
159 | outb_p(0xFF,IO_DATA_PORT); | 162 | outb_p(0xFF, IO_DATA_PORT); |
160 | outb_p(0xF3,IO_INDEX_PORT); | 163 | outb_p(0xF3, IO_INDEX_PORT); |
161 | outb_p(0x00,IO_DATA_PORT); | 164 | outb_p(0x00, IO_DATA_PORT); |
162 | outb_p(0xF4,IO_INDEX_PORT); | 165 | outb_p(0xF4, IO_INDEX_PORT); |
163 | outb_p(0x00,IO_DATA_PORT); | 166 | outb_p(0x00, IO_DATA_PORT); |
164 | outb_p(0xF2,IO_INDEX_PORT); | 167 | outb_p(0xF2, IO_INDEX_PORT); |
165 | outb_p(0x00,IO_DATA_PORT); | 168 | outb_p(0x00, IO_DATA_PORT); |
166 | 169 | ||
167 | /* | 170 | /* |
168 | * Select device Aux1 (dev=7) to set GP16 (in reg E6) and | 171 | * Select device Aux1 (dev=7) to set GP16 (in reg E6) and |
169 | * Gp13 (in reg E3) as inputs. | 172 | * Gp13 (in reg E3) as inputs. |
170 | */ | 173 | */ |
171 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | 174 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
172 | outb_p(0x07,IO_DATA_PORT); | 175 | outb_p(0x07, IO_DATA_PORT); |
173 | if (!testmode) | 176 | if (!testmode) { |
174 | { | 177 | outb_p(0xE6, IO_INDEX_PORT); |
175 | outb_p(0xE6,IO_INDEX_PORT); | 178 | outb_p(0x01, IO_DATA_PORT); |
176 | outb_p(0x01,IO_DATA_PORT); | ||
177 | } | 179 | } |
178 | outb_p(0xE3,IO_INDEX_PORT); | 180 | outb_p(0xE3, IO_INDEX_PORT); |
179 | outb_p(0x01,IO_DATA_PORT); | 181 | outb_p(0x01, IO_DATA_PORT); |
180 | 182 | ||
181 | /* Lock the SuperIO chip */ | 183 | /* Lock the SuperIO chip */ |
182 | outb_p(LOCK_DATA,IO_INDEX_PORT); | 184 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
183 | 185 | ||
184 | spin_unlock_irqrestore(&spinlock, flags); | 186 | spin_unlock_irqrestore(&spinlock, flags); |
185 | 187 | ||
@@ -200,17 +202,17 @@ static int wdt_keepalive(void) | |||
200 | spin_lock_irqsave(&spinlock, flags); | 202 | spin_lock_irqsave(&spinlock, flags); |
201 | 203 | ||
202 | /* Unlock the SuperIO chip */ | 204 | /* Unlock the SuperIO chip */ |
203 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 205 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
204 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 206 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
205 | 207 | ||
206 | /* Select device Aux2 (device=8) to kick watchdog reg F2 */ | 208 | /* Select device Aux2 (device=8) to kick watchdog reg F2 */ |
207 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | 209 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
208 | outb_p(0x08,IO_DATA_PORT); | 210 | outb_p(0x08, IO_DATA_PORT); |
209 | outb_p(0xF2,IO_INDEX_PORT); | 211 | outb_p(0xF2, IO_INDEX_PORT); |
210 | outb_p(timeoutW,IO_DATA_PORT); | 212 | outb_p(timeoutW, IO_DATA_PORT); |
211 | 213 | ||
212 | /* Lock the SuperIO chip */ | 214 | /* Lock the SuperIO chip */ |
213 | outb_p(LOCK_DATA,IO_INDEX_PORT); | 215 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
214 | 216 | ||
215 | spin_unlock_irqrestore(&spinlock, flags); | 217 | spin_unlock_irqrestore(&spinlock, flags); |
216 | 218 | ||
@@ -227,7 +229,7 @@ static int wdt_set_timeout(int t) | |||
227 | 229 | ||
228 | /* | 230 | /* |
229 | * Convert seconds to watchdog counter time units, rounding up. | 231 | * Convert seconds to watchdog counter time units, rounding up. |
230 | * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup | 232 | * On PCM-5335 watchdog units are 30 seconds/step with 15 sec startup |
231 | * value. This information is supplied in the PCM-5335 manual and was | 233 | * value. This information is supplied in the PCM-5335 manual and was |
232 | * checked by me on a real board. This is a bit strange because W83977f | 234 | * checked by me on a real board. This is a bit strange because W83977f |
233 | * datasheet says counter unit is in minutes! | 235 | * datasheet says counter unit is in minutes! |
@@ -241,7 +243,7 @@ static int wdt_set_timeout(int t) | |||
241 | return -EINVAL; | 243 | return -EINVAL; |
242 | 244 | ||
243 | /* | 245 | /* |
244 | * timeout is the timeout in seconds, | 246 | * timeout is the timeout in seconds, |
245 | * timeoutW is the timeout in watchdog counter units. | 247 | * timeoutW is the timeout in watchdog counter units. |
246 | */ | 248 | */ |
247 | timeoutW = tmrval; | 249 | timeoutW = tmrval; |
@@ -261,17 +263,17 @@ static int wdt_get_status(int *status) | |||
261 | spin_lock_irqsave(&spinlock, flags); | 263 | spin_lock_irqsave(&spinlock, flags); |
262 | 264 | ||
263 | /* Unlock the SuperIO chip */ | 265 | /* Unlock the SuperIO chip */ |
264 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 266 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
265 | outb_p(UNLOCK_DATA,IO_INDEX_PORT); | 267 | outb_p(UNLOCK_DATA, IO_INDEX_PORT); |
266 | 268 | ||
267 | /* Select device Aux2 (device=8) to read watchdog reg F4 */ | 269 | /* Select device Aux2 (device=8) to read watchdog reg F4 */ |
268 | outb_p(DEVICE_REGISTER,IO_INDEX_PORT); | 270 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
269 | outb_p(0x08,IO_DATA_PORT); | 271 | outb_p(0x08, IO_DATA_PORT); |
270 | outb_p(0xF4,IO_INDEX_PORT); | 272 | outb_p(0xF4, IO_INDEX_PORT); |
271 | new_status = inb_p(IO_DATA_PORT); | 273 | new_status = inb_p(IO_DATA_PORT); |
272 | 274 | ||
273 | /* Lock the SuperIO chip */ | 275 | /* Lock the SuperIO chip */ |
274 | outb_p(LOCK_DATA,IO_INDEX_PORT); | 276 | outb_p(LOCK_DATA, IO_INDEX_PORT); |
275 | 277 | ||
276 | spin_unlock_irqrestore(&spinlock, flags); | 278 | spin_unlock_irqrestore(&spinlock, flags); |
277 | 279 | ||
@@ -290,7 +292,7 @@ static int wdt_get_status(int *status) | |||
290 | static int wdt_open(struct inode *inode, struct file *file) | 292 | static int wdt_open(struct inode *inode, struct file *file) |
291 | { | 293 | { |
292 | /* If the watchdog is alive we don't need to start it again */ | 294 | /* If the watchdog is alive we don't need to start it again */ |
293 | if( test_and_set_bit(0, &timer_alive) ) | 295 | if (test_and_set_bit(0, &timer_alive)) |
294 | return -EBUSY; | 296 | return -EBUSY; |
295 | 297 | ||
296 | if (nowayout) | 298 | if (nowayout) |
@@ -306,13 +308,13 @@ static int wdt_release(struct inode *inode, struct file *file) | |||
306 | * Shut off the timer. | 308 | * Shut off the timer. |
307 | * Lock it in if it's a module and we set nowayout | 309 | * Lock it in if it's a module and we set nowayout |
308 | */ | 310 | */ |
309 | if (expect_close == 42) | 311 | if (expect_close == 42) { |
310 | { | ||
311 | wdt_stop(); | 312 | wdt_stop(); |
312 | clear_bit(0, &timer_alive); | 313 | clear_bit(0, &timer_alive); |
313 | } else { | 314 | } else { |
314 | wdt_keepalive(); | 315 | wdt_keepalive(); |
315 | printk(KERN_CRIT PFX "unexpected close, not stopping watchdog!\n"); | 316 | printk(KERN_CRIT PFX |
317 | "unexpected close, not stopping watchdog!\n"); | ||
316 | } | 318 | } |
317 | expect_close = 0; | 319 | expect_close = 0; |
318 | return 0; | 320 | return 0; |
@@ -333,24 +335,22 @@ static ssize_t wdt_write(struct file *file, const char __user *buf, | |||
333 | size_t count, loff_t *ppos) | 335 | size_t count, loff_t *ppos) |
334 | { | 336 | { |
335 | /* See if we got the magic character 'V' and reload the timer */ | 337 | /* See if we got the magic character 'V' and reload the timer */ |
336 | if(count) | 338 | if (count) { |
337 | { | 339 | if (!nowayout) { |
338 | if (!nowayout) | ||
339 | { | ||
340 | size_t ofs; | 340 | size_t ofs; |
341 | 341 | ||
342 | /* note: just in case someone wrote the magic character long ago */ | 342 | /* note: just in case someone wrote the |
343 | magic character long ago */ | ||
343 | expect_close = 0; | 344 | expect_close = 0; |
344 | 345 | ||
345 | /* scan to see whether or not we got the magic character */ | 346 | /* scan to see whether or not we got the |
346 | for(ofs = 0; ofs != count; ofs++) | 347 | magic character */ |
347 | { | 348 | for (ofs = 0; ofs != count; ofs++) { |
348 | char c; | 349 | char c; |
349 | if (get_user(c, buf + ofs)) | 350 | if (get_user(c, buf + ofs)) |
350 | return -EFAULT; | 351 | return -EFAULT; |
351 | if (c == 'V') { | 352 | if (c == 'V') |
352 | expect_close = 42; | 353 | expect_close = 42; |
353 | } | ||
354 | } | 354 | } |
355 | } | 355 | } |
356 | 356 | ||
@@ -377,8 +377,7 @@ static struct watchdog_info ident = { | |||
377 | .identity = WATCHDOG_NAME, | 377 | .identity = WATCHDOG_NAME, |
378 | }; | 378 | }; |
379 | 379 | ||
380 | static int wdt_ioctl(struct inode *inode, struct file *file, | 380 | static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
381 | unsigned int cmd, unsigned long arg) | ||
382 | { | 381 | { |
383 | int status; | 382 | int status; |
384 | int new_options, retval = -EINVAL; | 383 | int new_options, retval = -EINVAL; |
@@ -390,13 +389,10 @@ static int wdt_ioctl(struct inode *inode, struct file *file, | |||
390 | 389 | ||
391 | uarg.i = (int __user *)arg; | 390 | uarg.i = (int __user *)arg; |
392 | 391 | ||
393 | switch(cmd) | 392 | switch (cmd) { |
394 | { | ||
395 | default: | ||
396 | return -ENOTTY; | ||
397 | |||
398 | case WDIOC_GETSUPPORT: | 393 | case WDIOC_GETSUPPORT: |
399 | return copy_to_user(uarg.ident, &ident, sizeof(ident)) ? -EFAULT : 0; | 394 | return copy_to_user(uarg.ident, &ident, |
395 | sizeof(ident)) ? -EFAULT : 0; | ||
400 | 396 | ||
401 | case WDIOC_GETSTATUS: | 397 | case WDIOC_GETSTATUS: |
402 | wdt_get_status(&status); | 398 | wdt_get_status(&status); |
@@ -405,12 +401,8 @@ static int wdt_ioctl(struct inode *inode, struct file *file, | |||
405 | case WDIOC_GETBOOTSTATUS: | 401 | case WDIOC_GETBOOTSTATUS: |
406 | return put_user(0, uarg.i); | 402 | return put_user(0, uarg.i); |
407 | 403 | ||
408 | case WDIOC_KEEPALIVE: | ||
409 | wdt_keepalive(); | ||
410 | return 0; | ||
411 | |||
412 | case WDIOC_SETOPTIONS: | 404 | case WDIOC_SETOPTIONS: |
413 | if (get_user (new_options, uarg.i)) | 405 | if (get_user(new_options, uarg.i)) |
414 | return -EFAULT; | 406 | return -EFAULT; |
415 | 407 | ||
416 | if (new_options & WDIOS_DISABLECARD) { | 408 | if (new_options & WDIOS_DISABLECARD) { |
@@ -425,6 +417,10 @@ static int wdt_ioctl(struct inode *inode, struct file *file, | |||
425 | 417 | ||
426 | return retval; | 418 | return retval; |
427 | 419 | ||
420 | case WDIOC_KEEPALIVE: | ||
421 | wdt_keepalive(); | ||
422 | return 0; | ||
423 | |||
428 | case WDIOC_SETTIMEOUT: | 424 | case WDIOC_SETTIMEOUT: |
429 | if (get_user(new_timeout, uarg.i)) | 425 | if (get_user(new_timeout, uarg.i)) |
430 | return -EFAULT; | 426 | return -EFAULT; |
@@ -438,29 +434,30 @@ static int wdt_ioctl(struct inode *inode, struct file *file, | |||
438 | case WDIOC_GETTIMEOUT: | 434 | case WDIOC_GETTIMEOUT: |
439 | return put_user(timeout, uarg.i); | 435 | return put_user(timeout, uarg.i); |
440 | 436 | ||
437 | default: | ||
438 | return -ENOTTY; | ||
439 | |||
441 | } | 440 | } |
442 | } | 441 | } |
443 | 442 | ||
444 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | 443 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, |
445 | void *unused) | 444 | void *unused) |
446 | { | 445 | { |
447 | if (code==SYS_DOWN || code==SYS_HALT) | 446 | if (code == SYS_DOWN || code == SYS_HALT) |
448 | wdt_stop(); | 447 | wdt_stop(); |
449 | return NOTIFY_DONE; | 448 | return NOTIFY_DONE; |
450 | } | 449 | } |
451 | 450 | ||
452 | static const struct file_operations wdt_fops= | 451 | static const struct file_operations wdt_fops = { |
453 | { | ||
454 | .owner = THIS_MODULE, | 452 | .owner = THIS_MODULE, |
455 | .llseek = no_llseek, | 453 | .llseek = no_llseek, |
456 | .write = wdt_write, | 454 | .write = wdt_write, |
457 | .ioctl = wdt_ioctl, | 455 | .unlocked_ioctl = wdt_ioctl, |
458 | .open = wdt_open, | 456 | .open = wdt_open, |
459 | .release = wdt_release, | 457 | .release = wdt_release, |
460 | }; | 458 | }; |
461 | 459 | ||
462 | static struct miscdevice wdt_miscdev= | 460 | static struct miscdevice wdt_miscdev = { |
463 | { | ||
464 | .minor = WATCHDOG_MINOR, | 461 | .minor = WATCHDOG_MINOR, |
465 | .name = "watchdog", | 462 | .name = "watchdog", |
466 | .fops = &wdt_fops, | 463 | .fops = &wdt_fops, |
@@ -474,20 +471,20 @@ static int __init w83977f_wdt_init(void) | |||
474 | { | 471 | { |
475 | int rc; | 472 | int rc; |
476 | 473 | ||
477 | printk(KERN_INFO PFX DRIVER_VERSION); | 474 | printk(KERN_INFO PFX DRIVER_VERSION); |
478 | 475 | ||
479 | /* | 476 | /* |
480 | * Check that the timeout value is within it's range ; | 477 | * Check that the timeout value is within it's range; |
481 | * if not reset to the default | 478 | * if not reset to the default |
482 | */ | 479 | */ |
483 | if (wdt_set_timeout(timeout)) { | 480 | if (wdt_set_timeout(timeout)) { |
484 | wdt_set_timeout(DEFAULT_TIMEOUT); | 481 | wdt_set_timeout(DEFAULT_TIMEOUT); |
485 | printk(KERN_INFO PFX "timeout value must be 15<=timeout<=7635, using %d\n", | 482 | printk(KERN_INFO PFX |
486 | DEFAULT_TIMEOUT); | 483 | "timeout value must be 15 <= timeout <= 7635, using %d\n", |
484 | DEFAULT_TIMEOUT); | ||
487 | } | 485 | } |
488 | 486 | ||
489 | if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) | 487 | if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) { |
490 | { | ||
491 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | 488 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
492 | IO_INDEX_PORT); | 489 | IO_INDEX_PORT); |
493 | rc = -EIO; | 490 | rc = -EIO; |
@@ -495,30 +492,30 @@ static int __init w83977f_wdt_init(void) | |||
495 | } | 492 | } |
496 | 493 | ||
497 | rc = register_reboot_notifier(&wdt_notifier); | 494 | rc = register_reboot_notifier(&wdt_notifier); |
498 | if (rc) | 495 | if (rc) { |
499 | { | 496 | printk(KERN_ERR PFX |
500 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 497 | "cannot register reboot notifier (err=%d)\n", rc); |
501 | rc); | ||
502 | goto err_out_region; | 498 | goto err_out_region; |
503 | } | 499 | } |
504 | 500 | ||
505 | rc = misc_register(&wdt_miscdev); | 501 | rc = misc_register(&wdt_miscdev); |
506 | if (rc) | 502 | if (rc) { |
507 | { | 503 | printk(KERN_ERR PFX |
508 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 504 | "cannot register miscdev on minor=%d (err=%d)\n", |
509 | wdt_miscdev.minor, rc); | 505 | wdt_miscdev.minor, rc); |
510 | goto err_out_reboot; | 506 | goto err_out_reboot; |
511 | } | 507 | } |
512 | 508 | ||
513 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", | 509 | printk(KERN_INFO PFX |
514 | timeout, nowayout, testmode); | 510 | "initialized. timeout=%d sec (nowayout=%d testmode=%d)\n", |
511 | timeout, nowayout, testmode); | ||
515 | 512 | ||
516 | return 0; | 513 | return 0; |
517 | 514 | ||
518 | err_out_reboot: | 515 | err_out_reboot: |
519 | unregister_reboot_notifier(&wdt_notifier); | 516 | unregister_reboot_notifier(&wdt_notifier); |
520 | err_out_region: | 517 | err_out_region: |
521 | release_region(IO_INDEX_PORT,2); | 518 | release_region(IO_INDEX_PORT, 2); |
522 | err_out: | 519 | err_out: |
523 | return rc; | 520 | return rc; |
524 | } | 521 | } |
@@ -528,7 +525,7 @@ static void __exit w83977f_wdt_exit(void) | |||
528 | wdt_stop(); | 525 | wdt_stop(); |
529 | misc_deregister(&wdt_miscdev); | 526 | misc_deregister(&wdt_miscdev); |
530 | unregister_reboot_notifier(&wdt_notifier); | 527 | unregister_reboot_notifier(&wdt_notifier); |
531 | release_region(IO_INDEX_PORT,2); | 528 | release_region(IO_INDEX_PORT, 2); |
532 | } | 529 | } |
533 | 530 | ||
534 | module_init(w83977f_wdt_init); | 531 | module_init(w83977f_wdt_init); |
diff --git a/drivers/watchdog/wafer5823wdt.c b/drivers/watchdog/wafer5823wdt.c index 9e368091f799..68377ae171ff 100644 --- a/drivers/watchdog/wafer5823wdt.c +++ b/drivers/watchdog/wafer5823wdt.c | |||
@@ -1,11 +1,11 @@ | |||
1 | /* | 1 | /* |
2 | * ICP Wafer 5823 Single Board Computer WDT driver | 2 | * ICP Wafer 5823 Single Board Computer WDT driver |
3 | * http://www.icpamerica.com/wafer_5823.php | 3 | * http://www.icpamerica.com/wafer_5823.php |
4 | * May also work on other similar models | 4 | * May also work on other similar models |
5 | * | 5 | * |
6 | * (c) Copyright 2002 Justin Cormack <justin@street-vision.com> | 6 | * (c) Copyright 2002 Justin Cormack <justin@street-vision.com> |
7 | * | 7 | * |
8 | * Release 0.02 | 8 | * Release 0.02 |
9 | * | 9 | * |
10 | * Based on advantechwdt.c which is based on wdt.c. | 10 | * Based on advantechwdt.c which is based on wdt.c. |
11 | * Original copyright messages: | 11 | * Original copyright messages: |
@@ -36,8 +36,8 @@ | |||
36 | #include <linux/reboot.h> | 36 | #include <linux/reboot.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/spinlock.h> | 38 | #include <linux/spinlock.h> |
39 | #include <asm/io.h> | 39 | #include <linux/io.h> |
40 | #include <asm/uaccess.h> | 40 | #include <linux/uaccess.h> |
41 | 41 | ||
42 | #define WATCHDOG_NAME "Wafer 5823 WDT" | 42 | #define WATCHDOG_NAME "Wafer 5823 WDT" |
43 | #define PFX WATCHDOG_NAME ": " | 43 | #define PFX WATCHDOG_NAME ": " |
@@ -50,10 +50,10 @@ static DEFINE_SPINLOCK(wafwdt_lock); | |||
50 | /* | 50 | /* |
51 | * You must set these - there is no sane way to probe for this board. | 51 | * You must set these - there is no sane way to probe for this board. |
52 | * | 52 | * |
53 | * To enable, write the timeout value in seconds (1 to 255) to I/O | 53 | * To enable, write the timeout value in seconds (1 to 255) to I/O |
54 | * port WDT_START, then read the port to start the watchdog. To pat | 54 | * port WDT_START, then read the port to start the watchdog. To pat |
55 | * the dog, read port WDT_STOP to stop the timer, then read WDT_START | 55 | * the dog, read port WDT_STOP to stop the timer, then read WDT_START |
56 | * to restart it again. | 56 | * to restart it again. |
57 | */ | 57 | */ |
58 | 58 | ||
59 | static int wdt_stop = 0x843; | 59 | static int wdt_stop = 0x843; |
@@ -61,11 +61,15 @@ static int wdt_start = 0x443; | |||
61 | 61 | ||
62 | static int timeout = WD_TIMO; /* in seconds */ | 62 | static int timeout = WD_TIMO; /* in seconds */ |
63 | module_param(timeout, int, 0); | 63 | module_param(timeout, int, 0); |
64 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=255, default=" __MODULE_STRING(WD_TIMO) "."); | 64 | MODULE_PARM_DESC(timeout, |
65 | "Watchdog timeout in seconds. 1 <= timeout <= 255, default=" | ||
66 | __MODULE_STRING(WD_TIMO) "."); | ||
65 | 67 | ||
66 | static int nowayout = WATCHDOG_NOWAYOUT; | 68 | static int nowayout = WATCHDOG_NOWAYOUT; |
67 | module_param(nowayout, int, 0); | 69 | module_param(nowayout, int, 0); |
68 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 70 | MODULE_PARM_DESC(nowayout, |
71 | "Watchdog cannot be stopped once started (default=" | ||
72 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
69 | 73 | ||
70 | static void wafwdt_ping(void) | 74 | static void wafwdt_ping(void) |
71 | { | 75 | { |
@@ -83,14 +87,14 @@ static void wafwdt_start(void) | |||
83 | inb_p(wdt_start); | 87 | inb_p(wdt_start); |
84 | } | 88 | } |
85 | 89 | ||
86 | static void | 90 | static void wafwdt_stop(void) |
87 | wafwdt_stop(void) | ||
88 | { | 91 | { |
89 | /* stop watchdog */ | 92 | /* stop watchdog */ |
90 | inb_p(wdt_stop); | 93 | inb_p(wdt_stop); |
91 | } | 94 | } |
92 | 95 | ||
93 | static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t count, loff_t * ppos) | 96 | static ssize_t wafwdt_write(struct file *file, const char __user *buf, |
97 | size_t count, loff_t *ppos) | ||
94 | { | 98 | { |
95 | /* See if we got the magic character 'V' and reload the timer */ | 99 | /* See if we got the magic character 'V' and reload the timer */ |
96 | if (count) { | 100 | if (count) { |
@@ -100,7 +104,8 @@ static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t co | |||
100 | /* In case it was set long ago */ | 104 | /* In case it was set long ago */ |
101 | expect_close = 0; | 105 | expect_close = 0; |
102 | 106 | ||
103 | /* scan to see whether or not we got the magic character */ | 107 | /* scan to see whether or not we got the magic |
108 | character */ | ||
104 | for (i = 0; i != count; i++) { | 109 | for (i = 0; i != count; i++) { |
105 | char c; | 110 | char c; |
106 | if (get_user(c, buf + i)) | 111 | if (get_user(c, buf + i)) |
@@ -109,27 +114,29 @@ static ssize_t wafwdt_write(struct file *file, const char __user *buf, size_t co | |||
109 | expect_close = 42; | 114 | expect_close = 42; |
110 | } | 115 | } |
111 | } | 116 | } |
112 | /* Well, anyhow someone wrote to us, we should return that favour */ | 117 | /* Well, anyhow someone wrote to us, we should |
118 | return that favour */ | ||
113 | wafwdt_ping(); | 119 | wafwdt_ping(); |
114 | } | 120 | } |
115 | return count; | 121 | return count; |
116 | } | 122 | } |
117 | 123 | ||
118 | static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 124 | static long wafwdt_ioctl(struct file *file, unsigned int cmd, |
119 | unsigned long arg) | 125 | unsigned long arg) |
120 | { | 126 | { |
121 | int new_timeout; | 127 | int new_timeout; |
122 | void __user *argp = (void __user *)arg; | 128 | void __user *argp = (void __user *)arg; |
123 | int __user *p = argp; | 129 | int __user *p = argp; |
124 | static struct watchdog_info ident = { | 130 | static const struct watchdog_info ident = { |
125 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE, | 131 | .options = WDIOF_KEEPALIVEPING | WDIOF_SETTIMEOUT | |
132 | WDIOF_MAGICCLOSE, | ||
126 | .firmware_version = 1, | 133 | .firmware_version = 1, |
127 | .identity = "Wafer 5823 WDT", | 134 | .identity = "Wafer 5823 WDT", |
128 | }; | 135 | }; |
129 | 136 | ||
130 | switch (cmd) { | 137 | switch (cmd) { |
131 | case WDIOC_GETSUPPORT: | 138 | case WDIOC_GETSUPPORT: |
132 | if (copy_to_user(argp, &ident, sizeof (ident))) | 139 | if (copy_to_user(argp, &ident, sizeof(ident))) |
133 | return -EFAULT; | 140 | return -EFAULT; |
134 | break; | 141 | break; |
135 | 142 | ||
@@ -137,22 +144,6 @@ static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
137 | case WDIOC_GETBOOTSTATUS: | 144 | case WDIOC_GETBOOTSTATUS: |
138 | return put_user(0, p); | 145 | return put_user(0, p); |
139 | 146 | ||
140 | case WDIOC_KEEPALIVE: | ||
141 | wafwdt_ping(); | ||
142 | break; | ||
143 | |||
144 | case WDIOC_SETTIMEOUT: | ||
145 | if (get_user(new_timeout, p)) | ||
146 | return -EFAULT; | ||
147 | if ((new_timeout < 1) || (new_timeout > 255)) | ||
148 | return -EINVAL; | ||
149 | timeout = new_timeout; | ||
150 | wafwdt_stop(); | ||
151 | wafwdt_start(); | ||
152 | /* Fall */ | ||
153 | case WDIOC_GETTIMEOUT: | ||
154 | return put_user(timeout, p); | ||
155 | |||
156 | case WDIOC_SETOPTIONS: | 147 | case WDIOC_SETOPTIONS: |
157 | { | 148 | { |
158 | int options, retval = -EINVAL; | 149 | int options, retval = -EINVAL; |
@@ -173,6 +164,22 @@ static int wafwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
173 | return retval; | 164 | return retval; |
174 | } | 165 | } |
175 | 166 | ||
167 | case WDIOC_KEEPALIVE: | ||
168 | wafwdt_ping(); | ||
169 | break; | ||
170 | |||
171 | case WDIOC_SETTIMEOUT: | ||
172 | if (get_user(new_timeout, p)) | ||
173 | return -EFAULT; | ||
174 | if ((new_timeout < 1) || (new_timeout > 255)) | ||
175 | return -EINVAL; | ||
176 | timeout = new_timeout; | ||
177 | wafwdt_stop(); | ||
178 | wafwdt_start(); | ||
179 | /* Fall */ | ||
180 | case WDIOC_GETTIMEOUT: | ||
181 | return put_user(timeout, p); | ||
182 | |||
176 | default: | 183 | default: |
177 | return -ENOTTY; | 184 | return -ENOTTY; |
178 | } | 185 | } |
@@ -191,13 +198,13 @@ static int wafwdt_open(struct inode *inode, struct file *file) | |||
191 | return nonseekable_open(inode, file); | 198 | return nonseekable_open(inode, file); |
192 | } | 199 | } |
193 | 200 | ||
194 | static int | 201 | static int wafwdt_close(struct inode *inode, struct file *file) |
195 | wafwdt_close(struct inode *inode, struct file *file) | ||
196 | { | 202 | { |
197 | if (expect_close == 42) { | 203 | if (expect_close == 42) |
198 | wafwdt_stop(); | 204 | wafwdt_stop(); |
199 | } else { | 205 | else { |
200 | printk(KERN_CRIT PFX "WDT device closed unexpectedly. WDT will not stop!\n"); | 206 | printk(KERN_CRIT PFX |
207 | "WDT device closed unexpectedly. WDT will not stop!\n"); | ||
201 | wafwdt_ping(); | 208 | wafwdt_ping(); |
202 | } | 209 | } |
203 | clear_bit(0, &wafwdt_is_open); | 210 | clear_bit(0, &wafwdt_is_open); |
@@ -209,12 +216,11 @@ wafwdt_close(struct inode *inode, struct file *file) | |||
209 | * Notifier for system down | 216 | * Notifier for system down |
210 | */ | 217 | */ |
211 | 218 | ||
212 | static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, void *unused) | 219 | static int wafwdt_notify_sys(struct notifier_block *this, unsigned long code, |
220 | void *unused) | ||
213 | { | 221 | { |
214 | if (code == SYS_DOWN || code == SYS_HALT) { | 222 | if (code == SYS_DOWN || code == SYS_HALT) |
215 | /* Turn the WDT off */ | ||
216 | wafwdt_stop(); | 223 | wafwdt_stop(); |
217 | } | ||
218 | return NOTIFY_DONE; | 224 | return NOTIFY_DONE; |
219 | } | 225 | } |
220 | 226 | ||
@@ -226,7 +232,7 @@ static const struct file_operations wafwdt_fops = { | |||
226 | .owner = THIS_MODULE, | 232 | .owner = THIS_MODULE, |
227 | .llseek = no_llseek, | 233 | .llseek = no_llseek, |
228 | .write = wafwdt_write, | 234 | .write = wafwdt_write, |
229 | .ioctl = wafwdt_ioctl, | 235 | .unlocked_ioctl = wafwdt_ioctl, |
230 | .open = wafwdt_open, | 236 | .open = wafwdt_open, |
231 | .release = wafwdt_close, | 237 | .release = wafwdt_close, |
232 | }; | 238 | }; |
@@ -250,25 +256,28 @@ static int __init wafwdt_init(void) | |||
250 | { | 256 | { |
251 | int ret; | 257 | int ret; |
252 | 258 | ||
253 | printk(KERN_INFO "WDT driver for Wafer 5823 single board computer initialising.\n"); | 259 | printk(KERN_INFO |
260 | "WDT driver for Wafer 5823 single board computer initialising.\n"); | ||
254 | 261 | ||
255 | if (timeout < 1 || timeout > 255) { | 262 | if (timeout < 1 || timeout > 255) { |
256 | timeout = WD_TIMO; | 263 | timeout = WD_TIMO; |
257 | printk (KERN_INFO PFX "timeout value must be 1<=x<=255, using %d\n", | 264 | printk(KERN_INFO PFX |
258 | timeout); | 265 | "timeout value must be 1 <= x <= 255, using %d\n", |
266 | timeout); | ||
259 | } | 267 | } |
260 | 268 | ||
261 | if (wdt_stop != wdt_start) { | 269 | if (wdt_stop != wdt_start) { |
262 | if(!request_region(wdt_stop, 1, "Wafer 5823 WDT")) { | 270 | if (!request_region(wdt_stop, 1, "Wafer 5823 WDT")) { |
263 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 271 | printk(KERN_ERR PFX |
264 | wdt_stop); | 272 | "I/O address 0x%04x already in use\n", |
273 | wdt_stop); | ||
265 | ret = -EIO; | 274 | ret = -EIO; |
266 | goto error; | 275 | goto error; |
267 | } | 276 | } |
268 | } | 277 | } |
269 | 278 | ||
270 | if(!request_region(wdt_start, 1, "Wafer 5823 WDT")) { | 279 | if (!request_region(wdt_start, 1, "Wafer 5823 WDT")) { |
271 | printk (KERN_ERR PFX "I/O address 0x%04x already in use\n", | 280 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", |
272 | wdt_start); | 281 | wdt_start); |
273 | ret = -EIO; | 282 | ret = -EIO; |
274 | goto error2; | 283 | goto error2; |
@@ -276,19 +285,20 @@ static int __init wafwdt_init(void) | |||
276 | 285 | ||
277 | ret = register_reboot_notifier(&wafwdt_notifier); | 286 | ret = register_reboot_notifier(&wafwdt_notifier); |
278 | if (ret != 0) { | 287 | if (ret != 0) { |
279 | printk (KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 288 | printk(KERN_ERR PFX |
280 | ret); | 289 | "cannot register reboot notifier (err=%d)\n", ret); |
281 | goto error3; | 290 | goto error3; |
282 | } | 291 | } |
283 | 292 | ||
284 | ret = misc_register(&wafwdt_miscdev); | 293 | ret = misc_register(&wafwdt_miscdev); |
285 | if (ret != 0) { | 294 | if (ret != 0) { |
286 | printk (KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 295 | printk(KERN_ERR PFX |
287 | WATCHDOG_MINOR, ret); | 296 | "cannot register miscdev on minor=%d (err=%d)\n", |
297 | WATCHDOG_MINOR, ret); | ||
288 | goto error4; | 298 | goto error4; |
289 | } | 299 | } |
290 | 300 | ||
291 | printk (KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", | 301 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", |
292 | timeout, nowayout); | 302 | timeout, nowayout); |
293 | 303 | ||
294 | return ret; | 304 | return ret; |
@@ -307,7 +317,7 @@ static void __exit wafwdt_exit(void) | |||
307 | { | 317 | { |
308 | misc_deregister(&wafwdt_miscdev); | 318 | misc_deregister(&wafwdt_miscdev); |
309 | unregister_reboot_notifier(&wafwdt_notifier); | 319 | unregister_reboot_notifier(&wafwdt_notifier); |
310 | if(wdt_stop != wdt_start) | 320 | if (wdt_stop != wdt_start) |
311 | release_region(wdt_stop, 1); | 321 | release_region(wdt_stop, 1); |
312 | release_region(wdt_start, 1); | 322 | release_region(wdt_start, 1); |
313 | } | 323 | } |
diff --git a/drivers/watchdog/wd501p.h b/drivers/watchdog/wd501p.h index a4504f40394d..db34853c28ae 100644 --- a/drivers/watchdog/wd501p.h +++ b/drivers/watchdog/wd501p.h | |||
@@ -12,7 +12,7 @@ | |||
12 | * http://www.cymru.net | 12 | * http://www.cymru.net |
13 | * | 13 | * |
14 | * This driver is provided under the GNU General Public License, incorporated | 14 | * This driver is provided under the GNU General Public License, incorporated |
15 | * herein by reference. The driver is provided without warranty or | 15 | * herein by reference. The driver is provided without warranty or |
16 | * support. | 16 | * support. |
17 | * | 17 | * |
18 | * Release 0.04. | 18 | * Release 0.04. |
diff --git a/drivers/watchdog/wdrtas.c b/drivers/watchdog/wdrtas.c index 1d64e277567d..5d3b1a8e28b0 100644 --- a/drivers/watchdog/wdrtas.c +++ b/drivers/watchdog/wdrtas.c | |||
@@ -35,9 +35,9 @@ | |||
35 | #include <linux/reboot.h> | 35 | #include <linux/reboot.h> |
36 | #include <linux/types.h> | 36 | #include <linux/types.h> |
37 | #include <linux/watchdog.h> | 37 | #include <linux/watchdog.h> |
38 | #include <linux/uaccess.h> | ||
38 | 39 | ||
39 | #include <asm/rtas.h> | 40 | #include <asm/rtas.h> |
40 | #include <asm/uaccess.h> | ||
41 | 41 | ||
42 | #define WDRTAS_MAGIC_CHAR 42 | 42 | #define WDRTAS_MAGIC_CHAR 42 |
43 | #define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \ | 43 | #define WDRTAS_SUPPORTED_MASK (WDIOF_SETTIMEOUT | \ |
@@ -56,7 +56,7 @@ static int wdrtas_nowayout = 0; | |||
56 | #endif | 56 | #endif |
57 | 57 | ||
58 | static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0); | 58 | static atomic_t wdrtas_miscdev_open = ATOMIC_INIT(0); |
59 | static char wdrtas_expect_close = 0; | 59 | static char wdrtas_expect_close; |
60 | 60 | ||
61 | static int wdrtas_interval; | 61 | static int wdrtas_interval; |
62 | 62 | ||
@@ -86,8 +86,8 @@ static char wdrtas_logbuffer[WDRTAS_LOGBUFFER_LEN]; | |||
86 | * RTAS function set-indicator (surveillance). The unit of interval is | 86 | * RTAS function set-indicator (surveillance). The unit of interval is |
87 | * seconds. | 87 | * seconds. |
88 | */ | 88 | */ |
89 | static int | 89 | |
90 | wdrtas_set_interval(int interval) | 90 | static int wdrtas_set_interval(int interval) |
91 | { | 91 | { |
92 | long result; | 92 | long result; |
93 | static int print_msg = 10; | 93 | static int print_msg = 10; |
@@ -97,7 +97,7 @@ wdrtas_set_interval(int interval) | |||
97 | 97 | ||
98 | result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL, | 98 | result = rtas_call(wdrtas_token_set_indicator, 3, 1, NULL, |
99 | WDRTAS_SURVEILLANCE_IND, 0, interval); | 99 | WDRTAS_SURVEILLANCE_IND, 0, interval); |
100 | if ( (result < 0) && (print_msg) ) { | 100 | if (result < 0 && print_msg) { |
101 | printk(KERN_ERR "wdrtas: setting the watchdog to %i " | 101 | printk(KERN_ERR "wdrtas: setting the watchdog to %i " |
102 | "timeout failed: %li\n", interval, result); | 102 | "timeout failed: %li\n", interval, result); |
103 | print_msg--; | 103 | print_msg--; |
@@ -116,16 +116,14 @@ wdrtas_set_interval(int interval) | |||
116 | * as reported by the RTAS function ibm,get-system-parameter. The unit | 116 | * as reported by the RTAS function ibm,get-system-parameter. The unit |
117 | * of the return value is seconds. | 117 | * of the return value is seconds. |
118 | */ | 118 | */ |
119 | static int | 119 | static int wdrtas_get_interval(int fallback_value) |
120 | wdrtas_get_interval(int fallback_value) | ||
121 | { | 120 | { |
122 | long result; | 121 | long result; |
123 | char value[4]; | 122 | char value[4]; |
124 | 123 | ||
125 | result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL, | 124 | result = rtas_call(wdrtas_token_get_sp, 3, 1, NULL, |
126 | WDRTAS_SP_SPI, (void *)__pa(&value), 4); | 125 | WDRTAS_SP_SPI, (void *)__pa(&value), 4); |
127 | if ( (value[0] != 0) || (value[1] != 2) || (value[3] != 0) || | 126 | if (value[0] != 0 || value[1] != 2 || value[3] != 0 || result < 0) { |
128 | (result < 0) ) { | ||
129 | printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog " | 127 | printk(KERN_WARNING "wdrtas: could not get sp_spi watchdog " |
130 | "timeout (%li). Continuing\n", result); | 128 | "timeout (%li). Continuing\n", result); |
131 | return fallback_value; | 129 | return fallback_value; |
@@ -141,8 +139,7 @@ wdrtas_get_interval(int fallback_value) | |||
141 | * wdrtas_timer_start starts the watchdog by calling the RTAS function | 139 | * wdrtas_timer_start starts the watchdog by calling the RTAS function |
142 | * set-interval (surveillance) | 140 | * set-interval (surveillance) |
143 | */ | 141 | */ |
144 | static void | 142 | static void wdrtas_timer_start(void) |
145 | wdrtas_timer_start(void) | ||
146 | { | 143 | { |
147 | wdrtas_set_interval(wdrtas_interval); | 144 | wdrtas_set_interval(wdrtas_interval); |
148 | } | 145 | } |
@@ -153,8 +150,7 @@ wdrtas_timer_start(void) | |||
153 | * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function | 150 | * wdrtas_timer_stop stops the watchdog timer by calling the RTAS function |
154 | * set-interval (surveillance) | 151 | * set-interval (surveillance) |
155 | */ | 152 | */ |
156 | static void | 153 | static void wdrtas_timer_stop(void) |
157 | wdrtas_timer_stop(void) | ||
158 | { | 154 | { |
159 | wdrtas_set_interval(0); | 155 | wdrtas_set_interval(0); |
160 | } | 156 | } |
@@ -165,8 +161,7 @@ wdrtas_timer_stop(void) | |||
165 | * wdrtas_log_scanned_event prints a message to the log buffer dumping | 161 | * wdrtas_log_scanned_event prints a message to the log buffer dumping |
166 | * the results of the last event-scan call | 162 | * the results of the last event-scan call |
167 | */ | 163 | */ |
168 | static void | 164 | static void wdrtas_log_scanned_event(void) |
169 | wdrtas_log_scanned_event(void) | ||
170 | { | 165 | { |
171 | int i; | 166 | int i; |
172 | 167 | ||
@@ -175,13 +170,13 @@ wdrtas_log_scanned_event(void) | |||
175 | "%02x %02x %02x %02x %02x %02x %02x %02x " | 170 | "%02x %02x %02x %02x %02x %02x %02x %02x " |
176 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", | 171 | "%02x %02x %02x %02x %02x %02x %02x %02x\n", |
177 | (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16), | 172 | (i / 16) + 1, (WDRTAS_LOGBUFFER_LEN / 16), |
178 | wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], | 173 | wdrtas_logbuffer[i + 0], wdrtas_logbuffer[i + 1], |
179 | wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], | 174 | wdrtas_logbuffer[i + 2], wdrtas_logbuffer[i + 3], |
180 | wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], | 175 | wdrtas_logbuffer[i + 4], wdrtas_logbuffer[i + 5], |
181 | wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], | 176 | wdrtas_logbuffer[i + 6], wdrtas_logbuffer[i + 7], |
182 | wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], | 177 | wdrtas_logbuffer[i + 8], wdrtas_logbuffer[i + 9], |
183 | wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], | 178 | wdrtas_logbuffer[i + 10], wdrtas_logbuffer[i + 11], |
184 | wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], | 179 | wdrtas_logbuffer[i + 12], wdrtas_logbuffer[i + 13], |
185 | wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]); | 180 | wdrtas_logbuffer[i + 14], wdrtas_logbuffer[i + 15]); |
186 | } | 181 | } |
187 | 182 | ||
@@ -192,8 +187,7 @@ wdrtas_log_scanned_event(void) | |||
192 | * RTAS function event-scan and repeats these calls as long as there are | 187 | * RTAS function event-scan and repeats these calls as long as there are |
193 | * events available. All events will be dumped. | 188 | * events available. All events will be dumped. |
194 | */ | 189 | */ |
195 | static void | 190 | static void wdrtas_timer_keepalive(void) |
196 | wdrtas_timer_keepalive(void) | ||
197 | { | 191 | { |
198 | long result; | 192 | long result; |
199 | 193 | ||
@@ -218,8 +212,7 @@ wdrtas_timer_keepalive(void) | |||
218 | * wdrtas_get_temperature returns the current temperature in Fahrenheit. It | 212 | * wdrtas_get_temperature returns the current temperature in Fahrenheit. It |
219 | * uses the RTAS call get-sensor-state, token 3 to do so | 213 | * uses the RTAS call get-sensor-state, token 3 to do so |
220 | */ | 214 | */ |
221 | static int | 215 | static int wdrtas_get_temperature(void) |
222 | wdrtas_get_temperature(void) | ||
223 | { | 216 | { |
224 | long result; | 217 | long result; |
225 | int temperature = 0; | 218 | int temperature = 0; |
@@ -243,8 +236,7 @@ wdrtas_get_temperature(void) | |||
243 | * returns a bitmask of defines WDIOF_... as defined in | 236 | * returns a bitmask of defines WDIOF_... as defined in |
244 | * include/linux/watchdog.h | 237 | * include/linux/watchdog.h |
245 | */ | 238 | */ |
246 | static int | 239 | static int wdrtas_get_status(void) |
247 | wdrtas_get_status(void) | ||
248 | { | 240 | { |
249 | return 0; /* TODO */ | 241 | return 0; /* TODO */ |
250 | } | 242 | } |
@@ -255,8 +247,7 @@ wdrtas_get_status(void) | |||
255 | * returns a bitmask of defines WDIOF_... as defined in | 247 | * returns a bitmask of defines WDIOF_... as defined in |
256 | * include/linux/watchdog.h, indicating why the watchdog rebooted the system | 248 | * include/linux/watchdog.h, indicating why the watchdog rebooted the system |
257 | */ | 249 | */ |
258 | static int | 250 | static int wdrtas_get_boot_status(void) |
259 | wdrtas_get_boot_status(void) | ||
260 | { | 251 | { |
261 | return 0; /* TODO */ | 252 | return 0; /* TODO */ |
262 | } | 253 | } |
@@ -276,8 +267,7 @@ wdrtas_get_boot_status(void) | |||
276 | * character 'V'. This character allows the watchdog device to be closed | 267 | * character 'V'. This character allows the watchdog device to be closed |
277 | * properly. | 268 | * properly. |
278 | */ | 269 | */ |
279 | static ssize_t | 270 | static ssize_t wdrtas_write(struct file *file, const char __user *buf, |
280 | wdrtas_write(struct file *file, const char __user *buf, | ||
281 | size_t len, loff_t *ppos) | 271 | size_t len, loff_t *ppos) |
282 | { | 272 | { |
283 | int i; | 273 | int i; |
@@ -306,7 +296,6 @@ out: | |||
306 | 296 | ||
307 | /** | 297 | /** |
308 | * wdrtas_ioctl - ioctl function for the watchdog device | 298 | * wdrtas_ioctl - ioctl function for the watchdog device |
309 | * @inode: inode structure | ||
310 | * @file: file structure | 299 | * @file: file structure |
311 | * @cmd: command for ioctl | 300 | * @cmd: command for ioctl |
312 | * @arg: argument pointer | 301 | * @arg: argument pointer |
@@ -315,16 +304,16 @@ out: | |||
315 | * | 304 | * |
316 | * wdrtas_ioctl implements the watchdog API ioctls | 305 | * wdrtas_ioctl implements the watchdog API ioctls |
317 | */ | 306 | */ |
318 | static int | 307 | |
319 | wdrtas_ioctl(struct inode *inode, struct file *file, | 308 | static long wdrtas_ioctl(struct file *file, unsigned int cmd, |
320 | unsigned int cmd, unsigned long arg) | 309 | unsigned long arg) |
321 | { | 310 | { |
322 | int __user *argp = (void __user *)arg; | 311 | int __user *argp = (void __user *)arg; |
323 | int i; | 312 | int i; |
324 | static struct watchdog_info wdinfo = { | 313 | static struct watchdog_info wdinfo = { |
325 | .options = WDRTAS_SUPPORTED_MASK, | 314 | .options = WDRTAS_SUPPORTED_MASK, |
326 | .firmware_version = 0, | 315 | .firmware_version = 0, |
327 | .identity = "wdrtas" | 316 | .identity = "wdrtas", |
328 | }; | 317 | }; |
329 | 318 | ||
330 | switch (cmd) { | 319 | switch (cmd) { |
@@ -357,9 +346,9 @@ wdrtas_ioctl(struct inode *inode, struct file *file, | |||
357 | wdrtas_timer_keepalive(); | 346 | wdrtas_timer_keepalive(); |
358 | wdrtas_timer_start(); | 347 | wdrtas_timer_start(); |
359 | } | 348 | } |
349 | /* not implemented. Done by H8 | ||
360 | if (i & WDIOS_TEMPPANIC) { | 350 | if (i & WDIOS_TEMPPANIC) { |
361 | /* not implemented. Done by H8 */ | 351 | } */ |
362 | } | ||
363 | return 0; | 352 | return 0; |
364 | 353 | ||
365 | case WDIOC_KEEPALIVE: | 354 | case WDIOC_KEEPALIVE: |
@@ -399,8 +388,7 @@ wdrtas_ioctl(struct inode *inode, struct file *file, | |||
399 | * | 388 | * |
400 | * function called when watchdog device is opened | 389 | * function called when watchdog device is opened |
401 | */ | 390 | */ |
402 | static int | 391 | static int wdrtas_open(struct inode *inode, struct file *file) |
403 | wdrtas_open(struct inode *inode, struct file *file) | ||
404 | { | 392 | { |
405 | /* only open once */ | 393 | /* only open once */ |
406 | if (atomic_inc_return(&wdrtas_miscdev_open) > 1) { | 394 | if (atomic_inc_return(&wdrtas_miscdev_open) > 1) { |
@@ -423,8 +411,7 @@ wdrtas_open(struct inode *inode, struct file *file) | |||
423 | * | 411 | * |
424 | * close function. Always succeeds | 412 | * close function. Always succeeds |
425 | */ | 413 | */ |
426 | static int | 414 | static int wdrtas_close(struct inode *inode, struct file *file) |
427 | wdrtas_close(struct inode *inode, struct file *file) | ||
428 | { | 415 | { |
429 | /* only stop watchdog, if this was announced using 'V' before */ | 416 | /* only stop watchdog, if this was announced using 'V' before */ |
430 | if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR) | 417 | if (wdrtas_expect_close == WDRTAS_MAGIC_CHAR) |
@@ -453,8 +440,7 @@ wdrtas_close(struct inode *inode, struct file *file) | |||
453 | * wdrtas_temp_read gives the temperature to the users by copying this | 440 | * wdrtas_temp_read gives the temperature to the users by copying this |
454 | * value as one byte into the user space buffer. The unit is Fahrenheit... | 441 | * value as one byte into the user space buffer. The unit is Fahrenheit... |
455 | */ | 442 | */ |
456 | static ssize_t | 443 | static ssize_t wdrtas_temp_read(struct file *file, char __user *buf, |
457 | wdrtas_temp_read(struct file *file, char __user *buf, | ||
458 | size_t count, loff_t *ppos) | 444 | size_t count, loff_t *ppos) |
459 | { | 445 | { |
460 | int temperature = 0; | 446 | int temperature = 0; |
@@ -478,8 +464,7 @@ wdrtas_temp_read(struct file *file, char __user *buf, | |||
478 | * | 464 | * |
479 | * function called when temperature device is opened | 465 | * function called when temperature device is opened |
480 | */ | 466 | */ |
481 | static int | 467 | static int wdrtas_temp_open(struct inode *inode, struct file *file) |
482 | wdrtas_temp_open(struct inode *inode, struct file *file) | ||
483 | { | 468 | { |
484 | return nonseekable_open(inode, file); | 469 | return nonseekable_open(inode, file); |
485 | } | 470 | } |
@@ -493,8 +478,7 @@ wdrtas_temp_open(struct inode *inode, struct file *file) | |||
493 | * | 478 | * |
494 | * close function. Always succeeds | 479 | * close function. Always succeeds |
495 | */ | 480 | */ |
496 | static int | 481 | static int wdrtas_temp_close(struct inode *inode, struct file *file) |
497 | wdrtas_temp_close(struct inode *inode, struct file *file) | ||
498 | { | 482 | { |
499 | return 0; | 483 | return 0; |
500 | } | 484 | } |
@@ -509,10 +493,10 @@ wdrtas_temp_close(struct inode *inode, struct file *file) | |||
509 | * | 493 | * |
510 | * wdrtas_reboot stops the watchdog in case of a reboot | 494 | * wdrtas_reboot stops the watchdog in case of a reboot |
511 | */ | 495 | */ |
512 | static int | 496 | static int wdrtas_reboot(struct notifier_block *this, |
513 | wdrtas_reboot(struct notifier_block *this, unsigned long code, void *ptr) | 497 | unsigned long code, void *ptr) |
514 | { | 498 | { |
515 | if ( (code==SYS_DOWN) || (code==SYS_HALT) ) | 499 | if (code == SYS_DOWN || code == SYS_HALT) |
516 | wdrtas_timer_stop(); | 500 | wdrtas_timer_stop(); |
517 | 501 | ||
518 | return NOTIFY_DONE; | 502 | return NOTIFY_DONE; |
@@ -524,7 +508,7 @@ static const struct file_operations wdrtas_fops = { | |||
524 | .owner = THIS_MODULE, | 508 | .owner = THIS_MODULE, |
525 | .llseek = no_llseek, | 509 | .llseek = no_llseek, |
526 | .write = wdrtas_write, | 510 | .write = wdrtas_write, |
527 | .ioctl = wdrtas_ioctl, | 511 | .unlocked_ioctl = wdrtas_ioctl, |
528 | .open = wdrtas_open, | 512 | .open = wdrtas_open, |
529 | .release = wdrtas_close, | 513 | .release = wdrtas_close, |
530 | }; | 514 | }; |
@@ -562,8 +546,7 @@ static struct notifier_block wdrtas_notifier = { | |||
562 | * this watchdog driver. It tolerates, if "get-sensor-state" and | 546 | * this watchdog driver. It tolerates, if "get-sensor-state" and |
563 | * "ibm,get-system-parameter" are not available. | 547 | * "ibm,get-system-parameter" are not available. |
564 | */ | 548 | */ |
565 | static int | 549 | static int wdrtas_get_tokens(void) |
566 | wdrtas_get_tokens(void) | ||
567 | { | 550 | { |
568 | wdrtas_token_get_sensor_state = rtas_token("get-sensor-state"); | 551 | wdrtas_token_get_sensor_state = rtas_token("get-sensor-state"); |
569 | if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) { | 552 | if (wdrtas_token_get_sensor_state == RTAS_UNKNOWN_SERVICE) { |
@@ -603,8 +586,7 @@ wdrtas_get_tokens(void) | |||
603 | * wdrtas_register_devs unregisters the watchdog and temperature watchdog | 586 | * wdrtas_register_devs unregisters the watchdog and temperature watchdog |
604 | * misc devs | 587 | * misc devs |
605 | */ | 588 | */ |
606 | static void | 589 | static void wdrtas_unregister_devs(void) |
607 | wdrtas_unregister_devs(void) | ||
608 | { | 590 | { |
609 | misc_deregister(&wdrtas_miscdev); | 591 | misc_deregister(&wdrtas_miscdev); |
610 | if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) | 592 | if (wdrtas_token_get_sensor_state != RTAS_UNKNOWN_SERVICE) |
@@ -619,8 +601,7 @@ wdrtas_unregister_devs(void) | |||
619 | * wdrtas_register_devs registers the watchdog and temperature watchdog | 601 | * wdrtas_register_devs registers the watchdog and temperature watchdog |
620 | * misc devs | 602 | * misc devs |
621 | */ | 603 | */ |
622 | static int | 604 | static int wdrtas_register_devs(void) |
623 | wdrtas_register_devs(void) | ||
624 | { | 605 | { |
625 | int result; | 606 | int result; |
626 | 607 | ||
@@ -651,8 +632,7 @@ wdrtas_register_devs(void) | |||
651 | * | 632 | * |
652 | * registers the file handlers and the reboot notifier | 633 | * registers the file handlers and the reboot notifier |
653 | */ | 634 | */ |
654 | static int __init | 635 | static int __init wdrtas_init(void) |
655 | wdrtas_init(void) | ||
656 | { | 636 | { |
657 | if (wdrtas_get_tokens()) | 637 | if (wdrtas_get_tokens()) |
658 | return -ENODEV; | 638 | return -ENODEV; |
@@ -680,8 +660,7 @@ wdrtas_init(void) | |||
680 | * | 660 | * |
681 | * unregisters the file handlers and the reboot notifier | 661 | * unregisters the file handlers and the reboot notifier |
682 | */ | 662 | */ |
683 | static void __exit | 663 | static void __exit wdrtas_exit(void) |
684 | wdrtas_exit(void) | ||
685 | { | 664 | { |
686 | if (!wdrtas_nowayout) | 665 | if (!wdrtas_nowayout) |
687 | wdrtas_timer_stop(); | 666 | wdrtas_timer_stop(); |
diff --git a/drivers/watchdog/wdt.c b/drivers/watchdog/wdt.c index 53a6b18bcb9a..deeebb2b13ea 100644 --- a/drivers/watchdog/wdt.c +++ b/drivers/watchdog/wdt.c | |||
@@ -373,8 +373,6 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
373 | #endif /* CONFIG_WDT_501 */ | 373 | #endif /* CONFIG_WDT_501 */ |
374 | 374 | ||
375 | switch (cmd) { | 375 | switch (cmd) { |
376 | default: | ||
377 | return -ENOTTY; | ||
378 | case WDIOC_GETSUPPORT: | 376 | case WDIOC_GETSUPPORT: |
379 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | 377 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
380 | case WDIOC_GETSTATUS: | 378 | case WDIOC_GETSTATUS: |
@@ -394,6 +392,8 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
394 | /* Fall */ | 392 | /* Fall */ |
395 | case WDIOC_GETTIMEOUT: | 393 | case WDIOC_GETTIMEOUT: |
396 | return put_user(heartbeat, p); | 394 | return put_user(heartbeat, p); |
395 | default: | ||
396 | return -ENOTTY; | ||
397 | } | 397 | } |
398 | } | 398 | } |
399 | 399 | ||
diff --git a/drivers/watchdog/wdt285.c b/drivers/watchdog/wdt285.c index 94e2d91c9ac9..c8d7f1b2df02 100644 --- a/drivers/watchdog/wdt285.c +++ b/drivers/watchdog/wdt285.c | |||
@@ -26,10 +26,10 @@ | |||
26 | #include <linux/reboot.h> | 26 | #include <linux/reboot.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/interrupt.h> | 28 | #include <linux/interrupt.h> |
29 | 29 | #include <linux/uaccess.h> | |
30 | #include <asm/irq.h> | 30 | #include <linux/irq.h> |
31 | #include <asm/uaccess.h> | ||
32 | #include <mach/hardware.h> | 31 | #include <mach/hardware.h> |
32 | |||
33 | #include <asm/mach-types.h> | 33 | #include <asm/mach-types.h> |
34 | #include <asm/hardware/dec21285.h> | 34 | #include <asm/hardware/dec21285.h> |
35 | 35 | ||
@@ -115,8 +115,8 @@ static int watchdog_release(struct inode *inode, struct file *file) | |||
115 | return 0; | 115 | return 0; |
116 | } | 116 | } |
117 | 117 | ||
118 | static ssize_t | 118 | static ssize_t watchdog_write(struct file *file, const char *data, |
119 | watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) | 119 | size_t len, loff_t *ppos) |
120 | { | 120 | { |
121 | /* | 121 | /* |
122 | * Refresh the timer. | 122 | * Refresh the timer. |
@@ -127,19 +127,18 @@ watchdog_write(struct file *file, const char *data, size_t len, loff_t *ppos) | |||
127 | return len; | 127 | return len; |
128 | } | 128 | } |
129 | 129 | ||
130 | static struct watchdog_info ident = { | 130 | static const struct watchdog_info ident = { |
131 | .options = WDIOF_SETTIMEOUT, | 131 | .options = WDIOF_SETTIMEOUT, |
132 | .identity = "Footbridge Watchdog", | 132 | .identity = "Footbridge Watchdog", |
133 | }; | 133 | }; |
134 | 134 | ||
135 | static int | 135 | static long watchdog_ioctl(struct file *file, unsigned int cmd, |
136 | watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | 136 | unsigned long arg) |
137 | unsigned long arg) | ||
138 | { | 137 | { |
139 | unsigned int new_margin; | 138 | unsigned int new_margin; |
140 | int ret = -ENOTTY; | 139 | int ret = -ENOTTY; |
141 | 140 | ||
142 | switch(cmd) { | 141 | switch (cmd) { |
143 | case WDIOC_GETSUPPORT: | 142 | case WDIOC_GETSUPPORT: |
144 | ret = 0; | 143 | ret = 0; |
145 | if (copy_to_user((void *)arg, &ident, sizeof(ident))) | 144 | if (copy_to_user((void *)arg, &ident, sizeof(ident))) |
@@ -148,7 +147,7 @@ watchdog_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
148 | 147 | ||
149 | case WDIOC_GETSTATUS: | 148 | case WDIOC_GETSTATUS: |
150 | case WDIOC_GETBOOTSTATUS: | 149 | case WDIOC_GETBOOTSTATUS: |
151 | ret = put_user(0,(int *)arg); | 150 | ret = put_user(0, (int *)arg); |
152 | break; | 151 | break; |
153 | 152 | ||
154 | case WDIOC_KEEPALIVE: | 153 | case WDIOC_KEEPALIVE: |
@@ -182,7 +181,7 @@ static const struct file_operations watchdog_fops = { | |||
182 | .owner = THIS_MODULE, | 181 | .owner = THIS_MODULE, |
183 | .llseek = no_llseek, | 182 | .llseek = no_llseek, |
184 | .write = watchdog_write, | 183 | .write = watchdog_write, |
185 | .ioctl = watchdog_ioctl, | 184 | .unlocked_ioctl = watchdog_ioctl, |
186 | .open = watchdog_open, | 185 | .open = watchdog_open, |
187 | .release = watchdog_release, | 186 | .release = watchdog_release, |
188 | }; | 187 | }; |
@@ -204,11 +203,13 @@ static int __init footbridge_watchdog_init(void) | |||
204 | if (retval < 0) | 203 | if (retval < 0) |
205 | return retval; | 204 | return retval; |
206 | 205 | ||
207 | printk("Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", | 206 | printk(KERN_INFO |
208 | soft_margin); | 207 | "Footbridge Watchdog Timer: 0.01, timer margin: %d sec\n", |
208 | soft_margin); | ||
209 | 209 | ||
210 | if (machine_is_cats()) | 210 | if (machine_is_cats()) |
211 | printk("Warning: Watchdog reset may not work on this machine.\n"); | 211 | printk(KERN_WARN |
212 | "Warning: Watchdog reset may not work on this machine.\n"); | ||
212 | return 0; | 213 | return 0; |
213 | } | 214 | } |
214 | 215 | ||
@@ -223,7 +224,7 @@ MODULE_LICENSE("GPL"); | |||
223 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | 224 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); |
224 | 225 | ||
225 | module_param(soft_margin, int, 0); | 226 | module_param(soft_margin, int, 0); |
226 | MODULE_PARM_DESC(soft_margin,"Watchdog timeout in seconds"); | 227 | MODULE_PARM_DESC(soft_margin, "Watchdog timeout in seconds"); |
227 | 228 | ||
228 | module_init(footbridge_watchdog_init); | 229 | module_init(footbridge_watchdog_init); |
229 | module_exit(footbridge_watchdog_exit); | 230 | module_exit(footbridge_watchdog_exit); |
diff --git a/drivers/watchdog/wdt977.c b/drivers/watchdog/wdt977.c index fb4b876c9fda..60e28d49ff52 100644 --- a/drivers/watchdog/wdt977.c +++ b/drivers/watchdog/wdt977.c | |||
@@ -19,7 +19,8 @@ | |||
19 | * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in | 19 | * 07-Jul-2003 Daniele Bellucci: Audit return code of misc_register in |
20 | * nwwatchdog_init. | 20 | * nwwatchdog_init. |
21 | * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks | 21 | * 25-Oct-2005 Woody Suwalski: Convert addresses to #defs, add spinlocks |
22 | * remove limitiation to be used on Netwinders only | 22 | * remove limitiation to be used on |
23 | * Netwinders only | ||
23 | */ | 24 | */ |
24 | 25 | ||
25 | #include <linux/module.h> | 26 | #include <linux/module.h> |
@@ -33,11 +34,11 @@ | |||
33 | #include <linux/watchdog.h> | 34 | #include <linux/watchdog.h> |
34 | #include <linux/notifier.h> | 35 | #include <linux/notifier.h> |
35 | #include <linux/reboot.h> | 36 | #include <linux/reboot.h> |
37 | #include <linux/io.h> | ||
38 | #include <linux/uaccess.h> | ||
36 | 39 | ||
37 | #include <asm/io.h> | ||
38 | #include <asm/system.h> | 40 | #include <asm/system.h> |
39 | #include <asm/mach-types.h> | 41 | #include <asm/mach-types.h> |
40 | #include <asm/uaccess.h> | ||
41 | 42 | ||
42 | #define WATCHDOG_VERSION "0.04" | 43 | #define WATCHDOG_VERSION "0.04" |
43 | #define WATCHDOG_NAME "Wdt977" | 44 | #define WATCHDOG_NAME "Wdt977" |
@@ -45,7 +46,7 @@ | |||
45 | #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" | 46 | #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" |
46 | 47 | ||
47 | #define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */ | 48 | #define IO_INDEX_PORT 0x370 /* on some systems it can be 0x3F0 */ |
48 | #define IO_DATA_PORT (IO_INDEX_PORT+1) | 49 | #define IO_DATA_PORT (IO_INDEX_PORT + 1) |
49 | 50 | ||
50 | #define UNLOCK_DATA 0x87 | 51 | #define UNLOCK_DATA 0x87 |
51 | #define LOCK_DATA 0xAA | 52 | #define LOCK_DATA 0xAA |
@@ -62,13 +63,16 @@ static char expect_close; | |||
62 | static DEFINE_SPINLOCK(spinlock); | 63 | static DEFINE_SPINLOCK(spinlock); |
63 | 64 | ||
64 | module_param(timeout, int, 0); | 65 | module_param(timeout, int, 0); |
65 | MODULE_PARM_DESC(timeout,"Watchdog timeout in seconds (60..15300), default=" __MODULE_STRING(DEFAULT_TIMEOUT) ")"); | 66 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds (60..15300), default=" |
67 | __MODULE_STRING(DEFAULT_TIMEOUT) ")"); | ||
66 | module_param(testmode, int, 0); | 68 | module_param(testmode, int, 0); |
67 | MODULE_PARM_DESC(testmode,"Watchdog testmode (1 = no reboot), default=0"); | 69 | MODULE_PARM_DESC(testmode, "Watchdog testmode (1 = no reboot), default=0"); |
68 | 70 | ||
69 | static int nowayout = WATCHDOG_NOWAYOUT; | 71 | static int nowayout = WATCHDOG_NOWAYOUT; |
70 | module_param(nowayout, int, 0); | 72 | module_param(nowayout, int, 0); |
71 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 73 | MODULE_PARM_DESC(nowayout, |
74 | "Watchdog cannot be stopped once started (default=" | ||
75 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
72 | 76 | ||
73 | /* | 77 | /* |
74 | * Start the watchdog | 78 | * Start the watchdog |
@@ -95,14 +99,16 @@ static int wdt977_start(void) | |||
95 | outb_p(0xF2, IO_INDEX_PORT); | 99 | outb_p(0xF2, IO_INDEX_PORT); |
96 | outb_p(timeoutM, IO_DATA_PORT); | 100 | outb_p(timeoutM, IO_DATA_PORT); |
97 | outb_p(0xF3, IO_INDEX_PORT); | 101 | outb_p(0xF3, IO_INDEX_PORT); |
98 | outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for kbd/mouse/LED */ | 102 | outb_p(0x00, IO_DATA_PORT); /* another setting is 0E for |
103 | kbd/mouse/LED */ | ||
99 | outb_p(0xF4, IO_INDEX_PORT); | 104 | outb_p(0xF4, IO_INDEX_PORT); |
100 | outb_p(0x00, IO_DATA_PORT); | 105 | outb_p(0x00, IO_DATA_PORT); |
101 | 106 | ||
102 | /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ | 107 | /* At last select device Aux1 (dev=7) and set GP16 as a |
103 | /* in test mode watch the bit 1 on F4 to indicate "triggered" */ | 108 | * watchdog output. In test mode watch the bit 1 on F4 to |
104 | if (!testmode) | 109 | * indicate "triggered" |
105 | { | 110 | */ |
111 | if (!testmode) { | ||
106 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); | 112 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
107 | outb_p(0x07, IO_DATA_PORT); | 113 | outb_p(0x07, IO_DATA_PORT); |
108 | outb_p(0xE6, IO_INDEX_PORT); | 114 | outb_p(0xE6, IO_INDEX_PORT); |
@@ -147,7 +153,8 @@ static int wdt977_stop(void) | |||
147 | outb_p(0xF2, IO_INDEX_PORT); | 153 | outb_p(0xF2, IO_INDEX_PORT); |
148 | outb_p(0x00, IO_DATA_PORT); | 154 | outb_p(0x00, IO_DATA_PORT); |
149 | 155 | ||
150 | /* at last select device Aux1 (dev=7) and set GP16 as a watchdog output */ | 156 | /* at last select device Aux1 (dev=7) and set |
157 | GP16 as a watchdog output */ | ||
151 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); | 158 | outb_p(DEVICE_REGISTER, IO_INDEX_PORT); |
152 | outb_p(0x07, IO_DATA_PORT); | 159 | outb_p(0x07, IO_DATA_PORT); |
153 | outb_p(0xE6, IO_INDEX_PORT); | 160 | outb_p(0xE6, IO_INDEX_PORT); |
@@ -202,16 +209,18 @@ static int wdt977_set_timeout(int t) | |||
202 | tmrval = (t + 59) / 60; | 209 | tmrval = (t + 59) / 60; |
203 | 210 | ||
204 | if (machine_is_netwinder()) { | 211 | if (machine_is_netwinder()) { |
205 | /* we have a hw bug somewhere, so each 977 minute is actually only 30sec | 212 | /* we have a hw bug somewhere, so each 977 minute is actually |
206 | * this limits the max timeout to half of device max of 255 minutes... | 213 | * only 30sec. This limits the max timeout to half of device |
214 | * max of 255 minutes... | ||
207 | */ | 215 | */ |
208 | tmrval += tmrval; | 216 | tmrval += tmrval; |
209 | } | 217 | } |
210 | 218 | ||
211 | if ((tmrval < 1) || (tmrval > 255)) | 219 | if (tmrval < 1 || tmrval > 255) |
212 | return -EINVAL; | 220 | return -EINVAL; |
213 | 221 | ||
214 | /* timeout is the timeout in seconds, timeoutM is the timeout in minutes) */ | 222 | /* timeout is the timeout in seconds, timeoutM is |
223 | the timeout in minutes) */ | ||
215 | timeout = t; | 224 | timeout = t; |
216 | timeoutM = tmrval; | 225 | timeoutM = tmrval; |
217 | return 0; | 226 | return 0; |
@@ -243,7 +252,7 @@ static int wdt977_get_status(int *status) | |||
243 | 252 | ||
244 | spin_unlock_irqrestore(&spinlock, flags); | 253 | spin_unlock_irqrestore(&spinlock, flags); |
245 | 254 | ||
246 | *status=0; | 255 | *status = 0; |
247 | if (new_status & 1) | 256 | if (new_status & 1) |
248 | *status |= WDIOF_CARDRESET; | 257 | *status |= WDIOF_CARDRESET; |
249 | 258 | ||
@@ -258,7 +267,7 @@ static int wdt977_get_status(int *status) | |||
258 | static int wdt977_open(struct inode *inode, struct file *file) | 267 | static int wdt977_open(struct inode *inode, struct file *file) |
259 | { | 268 | { |
260 | /* If the watchdog is alive we don't need to start it again */ | 269 | /* If the watchdog is alive we don't need to start it again */ |
261 | if( test_and_set_bit(0,&timer_alive) ) | 270 | if (test_and_set_bit(0, &timer_alive)) |
262 | return -EBUSY; | 271 | return -EBUSY; |
263 | 272 | ||
264 | if (nowayout) | 273 | if (nowayout) |
@@ -274,13 +283,13 @@ static int wdt977_release(struct inode *inode, struct file *file) | |||
274 | * Shut off the timer. | 283 | * Shut off the timer. |
275 | * Lock it in if it's a module and we set nowayout | 284 | * Lock it in if it's a module and we set nowayout |
276 | */ | 285 | */ |
277 | if (expect_close == 42) | 286 | if (expect_close == 42) { |
278 | { | ||
279 | wdt977_stop(); | 287 | wdt977_stop(); |
280 | clear_bit(0,&timer_alive); | 288 | clear_bit(0, &timer_alive); |
281 | } else { | 289 | } else { |
282 | wdt977_keepalive(); | 290 | wdt977_keepalive(); |
283 | printk(KERN_CRIT PFX "Unexpected close, not stopping watchdog!\n"); | 291 | printk(KERN_CRIT PFX |
292 | "Unexpected close, not stopping watchdog!\n"); | ||
284 | } | 293 | } |
285 | expect_close = 0; | 294 | expect_close = 0; |
286 | return 0; | 295 | return 0; |
@@ -301,17 +310,14 @@ static int wdt977_release(struct inode *inode, struct file *file) | |||
301 | static ssize_t wdt977_write(struct file *file, const char __user *buf, | 310 | static ssize_t wdt977_write(struct file *file, const char __user *buf, |
302 | size_t count, loff_t *ppos) | 311 | size_t count, loff_t *ppos) |
303 | { | 312 | { |
304 | if (count) | 313 | if (count) { |
305 | { | 314 | if (!nowayout) { |
306 | if (!nowayout) | ||
307 | { | ||
308 | size_t i; | 315 | size_t i; |
309 | 316 | ||
310 | /* In case it was set long ago */ | 317 | /* In case it was set long ago */ |
311 | expect_close = 0; | 318 | expect_close = 0; |
312 | 319 | ||
313 | for (i = 0; i != count; i++) | 320 | for (i = 0; i != count; i++) { |
314 | { | ||
315 | char c; | 321 | char c; |
316 | if (get_user(c, buf + i)) | 322 | if (get_user(c, buf + i)) |
317 | return -EFAULT; | 323 | return -EFAULT; |
@@ -326,6 +332,14 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf, | |||
326 | return count; | 332 | return count; |
327 | } | 333 | } |
328 | 334 | ||
335 | static const struct watchdog_info ident = { | ||
336 | .options = WDIOF_SETTIMEOUT | | ||
337 | WDIOF_MAGICCLOSE | | ||
338 | WDIOF_KEEPALIVEPING, | ||
339 | .firmware_version = 1, | ||
340 | .identity = WATCHDOG_NAME, | ||
341 | }; | ||
342 | |||
329 | /* | 343 | /* |
330 | * wdt977_ioctl: | 344 | * wdt977_ioctl: |
331 | * @inode: inode of the device | 345 | * @inode: inode of the device |
@@ -337,16 +351,8 @@ static ssize_t wdt977_write(struct file *file, const char __user *buf, | |||
337 | * according to their available features. | 351 | * according to their available features. |
338 | */ | 352 | */ |
339 | 353 | ||
340 | static struct watchdog_info ident = { | 354 | static long wdt977_ioctl(struct file *file, unsigned int cmd, |
341 | .options = WDIOF_SETTIMEOUT | | 355 | unsigned long arg) |
342 | WDIOF_MAGICCLOSE | | ||
343 | WDIOF_KEEPALIVEPING, | ||
344 | .firmware_version = 1, | ||
345 | .identity = WATCHDOG_NAME, | ||
346 | }; | ||
347 | |||
348 | static int wdt977_ioctl(struct inode *inode, struct file *file, | ||
349 | unsigned int cmd, unsigned long arg) | ||
350 | { | 356 | { |
351 | int status; | 357 | int status; |
352 | int new_options, retval = -EINVAL; | 358 | int new_options, retval = -EINVAL; |
@@ -358,11 +364,7 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, | |||
358 | 364 | ||
359 | uarg.i = (int __user *)arg; | 365 | uarg.i = (int __user *)arg; |
360 | 366 | ||
361 | switch(cmd) | 367 | switch (cmd) { |
362 | { | ||
363 | default: | ||
364 | return -ENOTTY; | ||
365 | |||
366 | case WDIOC_GETSUPPORT: | 368 | case WDIOC_GETSUPPORT: |
367 | return copy_to_user(uarg.ident, &ident, | 369 | return copy_to_user(uarg.ident, &ident, |
368 | sizeof(ident)) ? -EFAULT : 0; | 370 | sizeof(ident)) ? -EFAULT : 0; |
@@ -374,12 +376,8 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, | |||
374 | case WDIOC_GETBOOTSTATUS: | 376 | case WDIOC_GETBOOTSTATUS: |
375 | return put_user(0, uarg.i); | 377 | return put_user(0, uarg.i); |
376 | 378 | ||
377 | case WDIOC_KEEPALIVE: | ||
378 | wdt977_keepalive(); | ||
379 | return 0; | ||
380 | |||
381 | case WDIOC_SETOPTIONS: | 379 | case WDIOC_SETOPTIONS: |
382 | if (get_user (new_options, uarg.i)) | 380 | if (get_user(new_options, uarg.i)) |
383 | return -EFAULT; | 381 | return -EFAULT; |
384 | 382 | ||
385 | if (new_options & WDIOS_DISABLECARD) { | 383 | if (new_options & WDIOS_DISABLECARD) { |
@@ -394,6 +392,10 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, | |||
394 | 392 | ||
395 | return retval; | 393 | return retval; |
396 | 394 | ||
395 | case WDIOC_KEEPALIVE: | ||
396 | wdt977_keepalive(); | ||
397 | return 0; | ||
398 | |||
397 | case WDIOC_SETTIMEOUT: | 399 | case WDIOC_SETTIMEOUT: |
398 | if (get_user(new_timeout, uarg.i)) | 400 | if (get_user(new_timeout, uarg.i)) |
399 | return -EFAULT; | 401 | return -EFAULT; |
@@ -407,29 +409,30 @@ static int wdt977_ioctl(struct inode *inode, struct file *file, | |||
407 | case WDIOC_GETTIMEOUT: | 409 | case WDIOC_GETTIMEOUT: |
408 | return put_user(timeout, uarg.i); | 410 | return put_user(timeout, uarg.i); |
409 | 411 | ||
412 | default: | ||
413 | return -ENOTTY; | ||
414 | |||
410 | } | 415 | } |
411 | } | 416 | } |
412 | 417 | ||
413 | static int wdt977_notify_sys(struct notifier_block *this, unsigned long code, | 418 | static int wdt977_notify_sys(struct notifier_block *this, unsigned long code, |
414 | void *unused) | 419 | void *unused) |
415 | { | 420 | { |
416 | if(code==SYS_DOWN || code==SYS_HALT) | 421 | if (code == SYS_DOWN || code == SYS_HALT) |
417 | wdt977_stop(); | 422 | wdt977_stop(); |
418 | return NOTIFY_DONE; | 423 | return NOTIFY_DONE; |
419 | } | 424 | } |
420 | 425 | ||
421 | static const struct file_operations wdt977_fops= | 426 | static const struct file_operations wdt977_fops = { |
422 | { | ||
423 | .owner = THIS_MODULE, | 427 | .owner = THIS_MODULE, |
424 | .llseek = no_llseek, | 428 | .llseek = no_llseek, |
425 | .write = wdt977_write, | 429 | .write = wdt977_write, |
426 | .ioctl = wdt977_ioctl, | 430 | .unlocked_ioctl = wdt977_ioctl, |
427 | .open = wdt977_open, | 431 | .open = wdt977_open, |
428 | .release = wdt977_release, | 432 | .release = wdt977_release, |
429 | }; | 433 | }; |
430 | 434 | ||
431 | static struct miscdevice wdt977_miscdev= | 435 | static struct miscdevice wdt977_miscdev = { |
432 | { | ||
433 | .minor = WATCHDOG_MINOR, | 436 | .minor = WATCHDOG_MINOR, |
434 | .name = "watchdog", | 437 | .name = "watchdog", |
435 | .fops = &wdt977_fops, | 438 | .fops = &wdt977_fops, |
@@ -443,51 +446,48 @@ static int __init wd977_init(void) | |||
443 | { | 446 | { |
444 | int rc; | 447 | int rc; |
445 | 448 | ||
446 | //if (!machine_is_netwinder()) | ||
447 | // return -ENODEV; | ||
448 | |||
449 | printk(KERN_INFO PFX DRIVER_VERSION); | 449 | printk(KERN_INFO PFX DRIVER_VERSION); |
450 | 450 | ||
451 | /* Check that the timeout value is within it's range ; if not reset to the default */ | 451 | /* Check that the timeout value is within its range; |
452 | if (wdt977_set_timeout(timeout)) | 452 | if not reset to the default */ |
453 | { | 453 | if (wdt977_set_timeout(timeout)) { |
454 | wdt977_set_timeout(DEFAULT_TIMEOUT); | 454 | wdt977_set_timeout(DEFAULT_TIMEOUT); |
455 | printk(KERN_INFO PFX "timeout value must be 60<timeout<15300, using %d\n", | 455 | printk(KERN_INFO PFX |
456 | DEFAULT_TIMEOUT); | 456 | "timeout value must be 60 < timeout < 15300, using %d\n", |
457 | DEFAULT_TIMEOUT); | ||
457 | } | 458 | } |
458 | 459 | ||
459 | /* on Netwinder the IOports are already reserved by | 460 | /* on Netwinder the IOports are already reserved by |
460 | * arch/arm/mach-footbridge/netwinder-hw.c | 461 | * arch/arm/mach-footbridge/netwinder-hw.c |
461 | */ | 462 | */ |
462 | if (!machine_is_netwinder()) | 463 | if (!machine_is_netwinder()) { |
463 | { | 464 | if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) { |
464 | if (!request_region(IO_INDEX_PORT, 2, WATCHDOG_NAME)) | 465 | printk(KERN_ERR PFX |
465 | { | 466 | "I/O address 0x%04x already in use\n", |
466 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | 467 | IO_INDEX_PORT); |
467 | IO_INDEX_PORT); | ||
468 | rc = -EIO; | 468 | rc = -EIO; |
469 | goto err_out; | 469 | goto err_out; |
470 | } | 470 | } |
471 | } | 471 | } |
472 | 472 | ||
473 | rc = register_reboot_notifier(&wdt977_notifier); | 473 | rc = register_reboot_notifier(&wdt977_notifier); |
474 | if (rc) | 474 | if (rc) { |
475 | { | 475 | printk(KERN_ERR PFX |
476 | printk(KERN_ERR PFX "cannot register reboot notifier (err=%d)\n", | 476 | "cannot register reboot notifier (err=%d)\n", rc); |
477 | rc); | ||
478 | goto err_out_region; | 477 | goto err_out_region; |
479 | } | 478 | } |
480 | 479 | ||
481 | rc = misc_register(&wdt977_miscdev); | 480 | rc = misc_register(&wdt977_miscdev); |
482 | if (rc) | 481 | if (rc) { |
483 | { | 482 | printk(KERN_ERR PFX |
484 | printk(KERN_ERR PFX "cannot register miscdev on minor=%d (err=%d)\n", | 483 | "cannot register miscdev on minor=%d (err=%d)\n", |
485 | wdt977_miscdev.minor, rc); | 484 | wdt977_miscdev.minor, rc); |
486 | goto err_out_reboot; | 485 | goto err_out_reboot; |
487 | } | 486 | } |
488 | 487 | ||
489 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n", | 488 | printk(KERN_INFO PFX |
490 | timeout, nowayout, testmode); | 489 | "initialized. timeout=%d sec (nowayout=%d, testmode=%i)\n", |
490 | timeout, nowayout, testmode); | ||
491 | 491 | ||
492 | return 0; | 492 | return 0; |
493 | 493 | ||
@@ -495,7 +495,7 @@ err_out_reboot: | |||
495 | unregister_reboot_notifier(&wdt977_notifier); | 495 | unregister_reboot_notifier(&wdt977_notifier); |
496 | err_out_region: | 496 | err_out_region: |
497 | if (!machine_is_netwinder()) | 497 | if (!machine_is_netwinder()) |
498 | release_region(IO_INDEX_PORT,2); | 498 | release_region(IO_INDEX_PORT, 2); |
499 | err_out: | 499 | err_out: |
500 | return rc; | 500 | return rc; |
501 | } | 501 | } |
@@ -505,7 +505,7 @@ static void __exit wd977_exit(void) | |||
505 | wdt977_stop(); | 505 | wdt977_stop(); |
506 | misc_deregister(&wdt977_miscdev); | 506 | misc_deregister(&wdt977_miscdev); |
507 | unregister_reboot_notifier(&wdt977_notifier); | 507 | unregister_reboot_notifier(&wdt977_notifier); |
508 | release_region(IO_INDEX_PORT,2); | 508 | release_region(IO_INDEX_PORT, 2); |
509 | } | 509 | } |
510 | 510 | ||
511 | module_init(wd977_init); | 511 | module_init(wd977_init); |
diff --git a/drivers/watchdog/wdt_pci.c b/drivers/watchdog/wdt_pci.c index 5d922fd6eafc..ed02bdb38c09 100644 --- a/drivers/watchdog/wdt_pci.c +++ b/drivers/watchdog/wdt_pci.c | |||
@@ -381,7 +381,7 @@ static ssize_t wdtpci_write(struct file *file, const char __user *buf, | |||
381 | 381 | ||
382 | for (i = 0; i != count; i++) { | 382 | for (i = 0; i != count; i++) { |
383 | char c; | 383 | char c; |
384 | if (get_user(c, buf+i)) | 384 | if (get_user(c, buf + i)) |
385 | return -EFAULT; | 385 | return -EFAULT; |
386 | if (c == 'V') | 386 | if (c == 'V') |
387 | expect_close = 42; | 387 | expect_close = 42; |
@@ -428,8 +428,6 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd, | |||
428 | #endif /* CONFIG_WDT_501_PCI */ | 428 | #endif /* CONFIG_WDT_501_PCI */ |
429 | 429 | ||
430 | switch (cmd) { | 430 | switch (cmd) { |
431 | default: | ||
432 | return -ENOTTY; | ||
433 | case WDIOC_GETSUPPORT: | 431 | case WDIOC_GETSUPPORT: |
434 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; | 432 | return copy_to_user(argp, &ident, sizeof(ident)) ? -EFAULT : 0; |
435 | case WDIOC_GETSTATUS: | 433 | case WDIOC_GETSTATUS: |
@@ -449,7 +447,9 @@ static long wdtpci_ioctl(struct file *file, unsigned int cmd, | |||
449 | /* Fall */ | 447 | /* Fall */ |
450 | case WDIOC_GETTIMEOUT: | 448 | case WDIOC_GETTIMEOUT: |
451 | return put_user(heartbeat, p); | 449 | return put_user(heartbeat, p); |
452 | } | 450 | default: |
451 | return -ENOTTY; | ||
452 | } | ||
453 | } | 453 | } |
454 | 454 | ||
455 | /** | 455 | /** |