diff options
-rw-r--r-- | drivers/watchdog/advantechwdt.c | 135 |
1 files changed, 62 insertions, 73 deletions
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c index 8121cc247343..220d238ee427 100644 --- a/drivers/watchdog/advantechwdt.c +++ b/drivers/watchdog/advantechwdt.c | |||
@@ -72,35 +72,35 @@ MODULE_PARM_DESC(wdt_start, "Advantech WDT 'start' io port (default 0x443)"); | |||
72 | 72 | ||
73 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | 73 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ |
74 | module_param(timeout, int, 0); | 74 | module_param(timeout, int, 0); |
75 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds. 1<= timeout <=63, default=" __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | 75 | MODULE_PARM_DESC(timeout, |
76 | "Watchdog timeout in seconds. 1<= timeout <=63, default=" | ||
77 | __MODULE_STRING(WATCHDOG_TIMEOUT) "."); | ||
76 | 78 | ||
77 | static int nowayout = WATCHDOG_NOWAYOUT; | 79 | static int nowayout = WATCHDOG_NOWAYOUT; |
78 | module_param(nowayout, int, 0); | 80 | module_param(nowayout, int, 0); |
79 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | 81 | MODULE_PARM_DESC(nowayout, |
82 | "Watchdog cannot be stopped once started (default=" | ||
83 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
80 | 84 | ||
81 | /* | 85 | /* |
82 | * Watchdog Operations | 86 | * Watchdog Operations |
83 | */ | 87 | */ |
84 | 88 | ||
85 | static void | 89 | static void advwdt_ping(void) |
86 | advwdt_ping(void) | ||
87 | { | 90 | { |
88 | /* Write a watchdog value */ | 91 | /* Write a watchdog value */ |
89 | outb_p(timeout, wdt_start); | 92 | outb_p(timeout, wdt_start); |
90 | } | 93 | } |
91 | 94 | ||
92 | static void | 95 | static void advwdt_disable(void) |
93 | advwdt_disable(void) | ||
94 | { | 96 | { |
95 | inb_p(wdt_stop); | 97 | inb_p(wdt_stop); |
96 | } | 98 | } |
97 | 99 | ||
98 | static int | 100 | static int advwdt_set_heartbeat(int t) |
99 | advwdt_set_heartbeat(int t) | ||
100 | { | 101 | { |
101 | if ((t < 1) || (t > 63)) | 102 | if (t < 1 || t > 63) |
102 | return -EINVAL; | 103 | return -EINVAL; |
103 | |||
104 | timeout = t; | 104 | timeout = t; |
105 | return 0; | 105 | return 0; |
106 | } | 106 | } |
@@ -109,8 +109,8 @@ advwdt_set_heartbeat(int t) | |||
109 | * /dev/watchdog handling | 109 | * /dev/watchdog handling |
110 | */ | 110 | */ |
111 | 111 | ||
112 | static ssize_t | 112 | 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) | 113 | size_t count, loff_t *ppos) |
114 | { | 114 | { |
115 | if (count) { | 115 | if (count) { |
116 | if (!nowayout) { | 116 | if (!nowayout) { |
@@ -131,9 +131,7 @@ advwdt_write(struct file *file, const char __user *buf, size_t count, loff_t *pp | |||
131 | return count; | 131 | return count; |
132 | } | 132 | } |
133 | 133 | ||
134 | static int | 134 | 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 | { | 135 | { |
138 | int new_timeout; | 136 | int new_timeout; |
139 | void __user *argp = (void __user *)arg; | 137 | void __user *argp = (void __user *)arg; |
@@ -146,57 +144,50 @@ advwdt_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | |||
146 | 144 | ||
147 | switch (cmd) { | 145 | switch (cmd) { |
148 | case WDIOC_GETSUPPORT: | 146 | case WDIOC_GETSUPPORT: |
149 | if (copy_to_user(argp, &ident, sizeof(ident))) | 147 | if (copy_to_user(argp, &ident, sizeof(ident))) |
150 | return -EFAULT; | 148 | return -EFAULT; |
151 | break; | 149 | break; |
152 | 150 | ||
153 | case WDIOC_GETSTATUS: | 151 | case WDIOC_GETSTATUS: |
154 | case WDIOC_GETBOOTSTATUS: | 152 | case WDIOC_GETBOOTSTATUS: |
155 | return put_user(0, p); | 153 | return put_user(0, p); |
156 | 154 | ||
157 | case WDIOC_KEEPALIVE: | 155 | case WDIOC_KEEPALIVE: |
158 | advwdt_ping(); | 156 | advwdt_ping(); |
159 | break; | 157 | break; |
160 | 158 | ||
161 | case WDIOC_SETTIMEOUT: | 159 | case WDIOC_SETTIMEOUT: |
162 | if (get_user(new_timeout, p)) | 160 | if (get_user(new_timeout, p)) |
163 | return -EFAULT; | 161 | return -EFAULT; |
164 | if (advwdt_set_heartbeat(new_timeout)) | 162 | if (advwdt_set_heartbeat(new_timeout)) |
165 | return -EINVAL; | 163 | return -EINVAL; |
166 | advwdt_ping(); | 164 | advwdt_ping(); |
167 | /* Fall */ | 165 | /* Fall */ |
168 | |||
169 | case WDIOC_GETTIMEOUT: | 166 | case WDIOC_GETTIMEOUT: |
170 | return put_user(timeout, p); | 167 | return put_user(timeout, p); |
171 | |||
172 | case WDIOC_SETOPTIONS: | 168 | case WDIOC_SETOPTIONS: |
173 | { | 169 | { |
174 | int options, retval = -EINVAL; | 170 | int options, retval = -EINVAL; |
175 | |||
176 | if (get_user(options, p)) | ||
177 | return -EFAULT; | ||
178 | 171 | ||
179 | if (options & WDIOS_DISABLECARD) { | 172 | if (get_user(options, p)) |
180 | advwdt_disable(); | 173 | return -EFAULT; |
181 | retval = 0; | 174 | if (options & WDIOS_DISABLECARD) { |
182 | } | 175 | advwdt_disable(); |
183 | 176 | retval = 0; | |
184 | if (options & WDIOS_ENABLECARD) { | 177 | } |
185 | advwdt_ping(); | 178 | if (options & WDIOS_ENABLECARD) { |
186 | retval = 0; | 179 | advwdt_ping(); |
187 | } | 180 | retval = 0; |
188 | 181 | } | |
189 | return retval; | 182 | return retval; |
190 | } | 183 | } |
191 | |||
192 | default: | 184 | default: |
193 | return -ENOTTY; | 185 | return -ENOTTY; |
194 | } | 186 | } |
195 | return 0; | 187 | return 0; |
196 | } | 188 | } |
197 | 189 | ||
198 | static int | 190 | static int advwdt_open(struct inode *inode, struct file *file) |
199 | advwdt_open(struct inode *inode, struct file *file) | ||
200 | { | 191 | { |
201 | if (test_and_set_bit(0, &advwdt_is_open)) | 192 | if (test_and_set_bit(0, &advwdt_is_open)) |
202 | return -EBUSY; | 193 | return -EBUSY; |
@@ -214,7 +205,8 @@ advwdt_close(struct inode *inode, struct file *file) | |||
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,8 +285,7 @@ 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); |
@@ -304,8 +295,7 @@ advwdt_remove(struct platform_device *dev) | |||
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,8 +311,7 @@ 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 | ||
@@ -332,7 +321,8 @@ advwdt_init(void) | |||
332 | if (err) | 321 | if (err) |
333 | return err; | 322 | return err; |
334 | 323 | ||
335 | advwdt_platform_device = platform_device_register_simple(DRV_NAME, -1, NULL, 0); | 324 | advwdt_platform_device = platform_device_register_simple(DRV_NAME, |
325 | -1, NULL, 0); | ||
336 | if (IS_ERR(advwdt_platform_device)) { | 326 | if (IS_ERR(advwdt_platform_device)) { |
337 | err = PTR_ERR(advwdt_platform_device); | 327 | err = PTR_ERR(advwdt_platform_device); |
338 | goto unreg_platform_driver; | 328 | goto unreg_platform_driver; |
@@ -345,8 +335,7 @@ unreg_platform_driver: | |||
345 | return err; | 335 | return err; |
346 | } | 336 | } |
347 | 337 | ||
348 | static void __exit | 338 | static void __exit advwdt_exit(void) |
349 | advwdt_exit(void) | ||
350 | { | 339 | { |
351 | platform_device_unregister(advwdt_platform_device); | 340 | platform_device_unregister(advwdt_platform_device); |
352 | platform_driver_unregister(&advwdt_driver); | 341 | platform_driver_unregister(&advwdt_driver); |