diff options
Diffstat (limited to 'drivers/watchdog')
-rw-r--r-- | drivers/watchdog/it8712f_wdt.c | 61 | ||||
-rw-r--r-- | drivers/watchdog/it87_wdt.c | 168 |
2 files changed, 134 insertions, 95 deletions
diff --git a/drivers/watchdog/it8712f_wdt.c b/drivers/watchdog/it8712f_wdt.c index 6143f52ba6b8..690144917a4d 100644 --- a/drivers/watchdog/it8712f_wdt.c +++ b/drivers/watchdog/it8712f_wdt.c | |||
@@ -51,7 +51,6 @@ MODULE_PARM_DESC(nowayout, "Disable watchdog shutdown on close"); | |||
51 | 51 | ||
52 | static unsigned long wdt_open; | 52 | static unsigned long wdt_open; |
53 | static unsigned expect_close; | 53 | static unsigned expect_close; |
54 | static spinlock_t io_lock; | ||
55 | static unsigned char revision; | 54 | static unsigned char revision; |
56 | 55 | ||
57 | /* Dog Food address - We use the game port address */ | 56 | /* Dog Food address - We use the game port address */ |
@@ -121,20 +120,26 @@ static inline void superio_select(int ldn) | |||
121 | outb(ldn, VAL); | 120 | outb(ldn, VAL); |
122 | } | 121 | } |
123 | 122 | ||
124 | static inline void superio_enter(void) | 123 | static inline int superio_enter(void) |
125 | { | 124 | { |
126 | spin_lock(&io_lock); | 125 | /* |
126 | * Try to reserve REG and REG + 1 for exclusive access. | ||
127 | */ | ||
128 | if (!request_muxed_region(REG, 2, NAME)) | ||
129 | return -EBUSY; | ||
130 | |||
127 | outb(0x87, REG); | 131 | outb(0x87, REG); |
128 | outb(0x01, REG); | 132 | outb(0x01, REG); |
129 | outb(0x55, REG); | 133 | outb(0x55, REG); |
130 | outb(0x55, REG); | 134 | outb(0x55, REG); |
135 | return 0; | ||
131 | } | 136 | } |
132 | 137 | ||
133 | static inline void superio_exit(void) | 138 | static inline void superio_exit(void) |
134 | { | 139 | { |
135 | outb(0x02, REG); | 140 | outb(0x02, REG); |
136 | outb(0x02, VAL); | 141 | outb(0x02, VAL); |
137 | spin_unlock(&io_lock); | 142 | release_region(REG, 2); |
138 | } | 143 | } |
139 | 144 | ||
140 | static inline void it8712f_wdt_ping(void) | 145 | static inline void it8712f_wdt_ping(void) |
@@ -173,10 +178,13 @@ static int it8712f_wdt_get_status(void) | |||
173 | return 0; | 178 | return 0; |
174 | } | 179 | } |
175 | 180 | ||
176 | static void it8712f_wdt_enable(void) | 181 | static int it8712f_wdt_enable(void) |
177 | { | 182 | { |
183 | int ret = superio_enter(); | ||
184 | if (ret) | ||
185 | return ret; | ||
186 | |||
178 | printk(KERN_DEBUG NAME ": enabling watchdog timer\n"); | 187 | printk(KERN_DEBUG NAME ": enabling watchdog timer\n"); |
179 | superio_enter(); | ||
180 | superio_select(LDN_GPIO); | 188 | superio_select(LDN_GPIO); |
181 | 189 | ||
182 | superio_outb(wdt_control_reg, WDT_CONTROL); | 190 | superio_outb(wdt_control_reg, WDT_CONTROL); |
@@ -186,13 +194,17 @@ static void it8712f_wdt_enable(void) | |||
186 | superio_exit(); | 194 | superio_exit(); |
187 | 195 | ||
188 | it8712f_wdt_ping(); | 196 | it8712f_wdt_ping(); |
197 | |||
198 | return 0; | ||
189 | } | 199 | } |
190 | 200 | ||
191 | static void it8712f_wdt_disable(void) | 201 | static int it8712f_wdt_disable(void) |
192 | { | 202 | { |
193 | printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); | 203 | int ret = superio_enter(); |
204 | if (ret) | ||
205 | return ret; | ||
194 | 206 | ||
195 | superio_enter(); | 207 | printk(KERN_DEBUG NAME ": disabling watchdog timer\n"); |
196 | superio_select(LDN_GPIO); | 208 | superio_select(LDN_GPIO); |
197 | 209 | ||
198 | superio_outb(0, WDT_CONFIG); | 210 | superio_outb(0, WDT_CONFIG); |
@@ -202,6 +214,7 @@ static void it8712f_wdt_disable(void) | |||
202 | superio_outb(0, WDT_TIMEOUT); | 214 | superio_outb(0, WDT_TIMEOUT); |
203 | 215 | ||
204 | superio_exit(); | 216 | superio_exit(); |
217 | return 0; | ||
205 | } | 218 | } |
206 | 219 | ||
207 | static int it8712f_wdt_notify(struct notifier_block *this, | 220 | static int it8712f_wdt_notify(struct notifier_block *this, |
@@ -252,6 +265,7 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, | |||
252 | WDIOF_MAGICCLOSE, | 265 | WDIOF_MAGICCLOSE, |
253 | }; | 266 | }; |
254 | int value; | 267 | int value; |
268 | int ret; | ||
255 | 269 | ||
256 | switch (cmd) { | 270 | switch (cmd) { |
257 | case WDIOC_GETSUPPORT: | 271 | case WDIOC_GETSUPPORT: |
@@ -259,7 +273,9 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, | |||
259 | return -EFAULT; | 273 | return -EFAULT; |
260 | return 0; | 274 | return 0; |
261 | case WDIOC_GETSTATUS: | 275 | case WDIOC_GETSTATUS: |
262 | superio_enter(); | 276 | ret = superio_enter(); |
277 | if (ret) | ||
278 | return ret; | ||
263 | superio_select(LDN_GPIO); | 279 | superio_select(LDN_GPIO); |
264 | 280 | ||
265 | value = it8712f_wdt_get_status(); | 281 | value = it8712f_wdt_get_status(); |
@@ -280,7 +296,9 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, | |||
280 | if (value > (max_units * 60)) | 296 | if (value > (max_units * 60)) |
281 | return -EINVAL; | 297 | return -EINVAL; |
282 | margin = value; | 298 | margin = value; |
283 | superio_enter(); | 299 | ret = superio_enter(); |
300 | if (ret) | ||
301 | return ret; | ||
284 | superio_select(LDN_GPIO); | 302 | superio_select(LDN_GPIO); |
285 | 303 | ||
286 | it8712f_wdt_update_margin(); | 304 | it8712f_wdt_update_margin(); |
@@ -299,10 +317,14 @@ static long it8712f_wdt_ioctl(struct file *file, unsigned int cmd, | |||
299 | 317 | ||
300 | static int it8712f_wdt_open(struct inode *inode, struct file *file) | 318 | static int it8712f_wdt_open(struct inode *inode, struct file *file) |
301 | { | 319 | { |
320 | int ret; | ||
302 | /* only allow one at a time */ | 321 | /* only allow one at a time */ |
303 | if (test_and_set_bit(0, &wdt_open)) | 322 | if (test_and_set_bit(0, &wdt_open)) |
304 | return -EBUSY; | 323 | return -EBUSY; |
305 | it8712f_wdt_enable(); | 324 | |
325 | ret = it8712f_wdt_enable(); | ||
326 | if (ret) | ||
327 | return ret; | ||
306 | return nonseekable_open(inode, file); | 328 | return nonseekable_open(inode, file); |
307 | } | 329 | } |
308 | 330 | ||
@@ -313,7 +335,8 @@ static int it8712f_wdt_release(struct inode *inode, struct file *file) | |||
313 | ": watchdog device closed unexpectedly, will not" | 335 | ": watchdog device closed unexpectedly, will not" |
314 | " disable the watchdog timer\n"); | 336 | " disable the watchdog timer\n"); |
315 | } else if (!nowayout) { | 337 | } else if (!nowayout) { |
316 | it8712f_wdt_disable(); | 338 | if (it8712f_wdt_disable()) |
339 | printk(KERN_WARNING NAME "Watchdog disable failed\n"); | ||
317 | } | 340 | } |
318 | expect_close = 0; | 341 | expect_close = 0; |
319 | clear_bit(0, &wdt_open); | 342 | clear_bit(0, &wdt_open); |
@@ -340,8 +363,10 @@ static int __init it8712f_wdt_find(unsigned short *address) | |||
340 | { | 363 | { |
341 | int err = -ENODEV; | 364 | int err = -ENODEV; |
342 | int chip_type; | 365 | int chip_type; |
366 | int ret = superio_enter(); | ||
367 | if (ret) | ||
368 | return ret; | ||
343 | 369 | ||
344 | superio_enter(); | ||
345 | chip_type = superio_inw(DEVID); | 370 | chip_type = superio_inw(DEVID); |
346 | if (chip_type != IT8712F_DEVID) | 371 | if (chip_type != IT8712F_DEVID) |
347 | goto exit; | 372 | goto exit; |
@@ -382,8 +407,6 @@ static int __init it8712f_wdt_init(void) | |||
382 | { | 407 | { |
383 | int err = 0; | 408 | int err = 0; |
384 | 409 | ||
385 | spin_lock_init(&io_lock); | ||
386 | |||
387 | if (it8712f_wdt_find(&address)) | 410 | if (it8712f_wdt_find(&address)) |
388 | return -ENODEV; | 411 | return -ENODEV; |
389 | 412 | ||
@@ -392,7 +415,11 @@ static int __init it8712f_wdt_init(void) | |||
392 | return -EBUSY; | 415 | return -EBUSY; |
393 | } | 416 | } |
394 | 417 | ||
395 | it8712f_wdt_disable(); | 418 | err = it8712f_wdt_disable(); |
419 | if (err) { | ||
420 | printk(KERN_ERR NAME ": unable to disable watchdog timer.\n"); | ||
421 | goto out; | ||
422 | } | ||
396 | 423 | ||
397 | err = register_reboot_notifier(&it8712f_wdt_notifier); | 424 | err = register_reboot_notifier(&it8712f_wdt_notifier); |
398 | if (err) { | 425 | if (err) { |
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c index b1bc72f9a209..a2d9a1266a23 100644 --- a/drivers/watchdog/it87_wdt.c +++ b/drivers/watchdog/it87_wdt.c | |||
@@ -137,7 +137,6 @@ | |||
137 | 137 | ||
138 | static unsigned int base, gpact, ciract, max_units, chip_type; | 138 | static unsigned int base, gpact, ciract, max_units, chip_type; |
139 | static unsigned long wdt_status; | 139 | static unsigned long wdt_status; |
140 | static DEFINE_SPINLOCK(spinlock); | ||
141 | 140 | ||
142 | static int nogameport = DEFAULT_NOGAMEPORT; | 141 | static int nogameport = DEFAULT_NOGAMEPORT; |
143 | static int exclusive = DEFAULT_EXCLUSIVE; | 142 | static int exclusive = DEFAULT_EXCLUSIVE; |
@@ -163,18 +162,26 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default=" | |||
163 | 162 | ||
164 | /* Superio Chip */ | 163 | /* Superio Chip */ |
165 | 164 | ||
166 | static inline void superio_enter(void) | 165 | static inline int superio_enter(void) |
167 | { | 166 | { |
167 | /* | ||
168 | * Try to reserve REG and REG + 1 for exclusive access. | ||
169 | */ | ||
170 | if (!request_muxed_region(REG, 2, WATCHDOG_NAME)) | ||
171 | return -EBUSY; | ||
172 | |||
168 | outb(0x87, REG); | 173 | outb(0x87, REG); |
169 | outb(0x01, REG); | 174 | outb(0x01, REG); |
170 | outb(0x55, REG); | 175 | outb(0x55, REG); |
171 | outb(0x55, REG); | 176 | outb(0x55, REG); |
177 | return 0; | ||
172 | } | 178 | } |
173 | 179 | ||
174 | static inline void superio_exit(void) | 180 | static inline void superio_exit(void) |
175 | { | 181 | { |
176 | outb(0x02, REG); | 182 | outb(0x02, REG); |
177 | outb(0x02, VAL); | 183 | outb(0x02, VAL); |
184 | release_region(REG, 2); | ||
178 | } | 185 | } |
179 | 186 | ||
180 | static inline void superio_select(int ldn) | 187 | static inline void superio_select(int ldn) |
@@ -255,12 +262,11 @@ static void wdt_keepalive(void) | |||
255 | set_bit(WDTS_KEEPALIVE, &wdt_status); | 262 | set_bit(WDTS_KEEPALIVE, &wdt_status); |
256 | } | 263 | } |
257 | 264 | ||
258 | static void wdt_start(void) | 265 | static int wdt_start(void) |
259 | { | 266 | { |
260 | unsigned long flags; | 267 | int ret = superio_enter(); |
261 | 268 | if (ret) | |
262 | spin_lock_irqsave(&spinlock, flags); | 269 | return ret; |
263 | superio_enter(); | ||
264 | 270 | ||
265 | superio_select(GPIO); | 271 | superio_select(GPIO); |
266 | if (test_bit(WDTS_USE_GP, &wdt_status)) | 272 | if (test_bit(WDTS_USE_GP, &wdt_status)) |
@@ -270,15 +276,15 @@ static void wdt_start(void) | |||
270 | wdt_update_timeout(); | 276 | wdt_update_timeout(); |
271 | 277 | ||
272 | superio_exit(); | 278 | superio_exit(); |
273 | spin_unlock_irqrestore(&spinlock, flags); | 279 | |
280 | return 0; | ||
274 | } | 281 | } |
275 | 282 | ||
276 | static void wdt_stop(void) | 283 | static int wdt_stop(void) |
277 | { | 284 | { |
278 | unsigned long flags; | 285 | int ret = superio_enter(); |
279 | 286 | if (ret) | |
280 | spin_lock_irqsave(&spinlock, flags); | 287 | return ret; |
281 | superio_enter(); | ||
282 | 288 | ||
283 | superio_select(GPIO); | 289 | superio_select(GPIO); |
284 | superio_outb(0x00, WDTCTRL); | 290 | superio_outb(0x00, WDTCTRL); |
@@ -288,7 +294,7 @@ static void wdt_stop(void) | |||
288 | superio_outb(0x00, WDTVALMSB); | 294 | superio_outb(0x00, WDTVALMSB); |
289 | 295 | ||
290 | superio_exit(); | 296 | superio_exit(); |
291 | spin_unlock_irqrestore(&spinlock, flags); | 297 | return 0; |
292 | } | 298 | } |
293 | 299 | ||
294 | /** | 300 | /** |
@@ -303,8 +309,6 @@ static void wdt_stop(void) | |||
303 | 309 | ||
304 | static int wdt_set_timeout(int t) | 310 | static int wdt_set_timeout(int t) |
305 | { | 311 | { |
306 | unsigned long flags; | ||
307 | |||
308 | if (t < 1 || t > max_units * 60) | 312 | if (t < 1 || t > max_units * 60) |
309 | return -EINVAL; | 313 | return -EINVAL; |
310 | 314 | ||
@@ -313,14 +317,15 @@ static int wdt_set_timeout(int t) | |||
313 | else | 317 | else |
314 | timeout = t; | 318 | timeout = t; |
315 | 319 | ||
316 | spin_lock_irqsave(&spinlock, flags); | ||
317 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { | 320 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { |
318 | superio_enter(); | 321 | int ret = superio_enter(); |
322 | if (ret) | ||
323 | return ret; | ||
324 | |||
319 | superio_select(GPIO); | 325 | superio_select(GPIO); |
320 | wdt_update_timeout(); | 326 | wdt_update_timeout(); |
321 | superio_exit(); | 327 | superio_exit(); |
322 | } | 328 | } |
323 | spin_unlock_irqrestore(&spinlock, flags); | ||
324 | return 0; | 329 | return 0; |
325 | } | 330 | } |
326 | 331 | ||
@@ -339,12 +344,12 @@ static int wdt_set_timeout(int t) | |||
339 | 344 | ||
340 | static int wdt_get_status(int *status) | 345 | static int wdt_get_status(int *status) |
341 | { | 346 | { |
342 | unsigned long flags; | ||
343 | |||
344 | *status = 0; | 347 | *status = 0; |
345 | if (testmode) { | 348 | if (testmode) { |
346 | spin_lock_irqsave(&spinlock, flags); | 349 | int ret = superio_enter(); |
347 | superio_enter(); | 350 | if (ret) |
351 | return ret; | ||
352 | |||
348 | superio_select(GPIO); | 353 | superio_select(GPIO); |
349 | if (superio_inb(WDTCTRL) & WDT_ZERO) { | 354 | if (superio_inb(WDTCTRL) & WDT_ZERO) { |
350 | superio_outb(0x00, WDTCTRL); | 355 | superio_outb(0x00, WDTCTRL); |
@@ -353,7 +358,6 @@ static int wdt_get_status(int *status) | |||
353 | } | 358 | } |
354 | 359 | ||
355 | superio_exit(); | 360 | superio_exit(); |
356 | spin_unlock_irqrestore(&spinlock, flags); | ||
357 | } | 361 | } |
358 | if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status)) | 362 | if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status)) |
359 | *status |= WDIOF_KEEPALIVEPING; | 363 | *status |= WDIOF_KEEPALIVEPING; |
@@ -379,9 +383,17 @@ static int wdt_open(struct inode *inode, struct file *file) | |||
379 | if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status)) | 383 | if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status)) |
380 | return -EBUSY; | 384 | return -EBUSY; |
381 | if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) { | 385 | if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) { |
386 | int ret; | ||
382 | if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status)) | 387 | if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status)) |
383 | __module_get(THIS_MODULE); | 388 | __module_get(THIS_MODULE); |
384 | wdt_start(); | 389 | |
390 | ret = wdt_start(); | ||
391 | if (ret) { | ||
392 | clear_bit(WDTS_LOCKED, &wdt_status); | ||
393 | clear_bit(WDTS_TIMER_RUN, &wdt_status); | ||
394 | clear_bit(WDTS_DEV_OPEN, &wdt_status); | ||
395 | return ret; | ||
396 | } | ||
385 | } | 397 | } |
386 | return nonseekable_open(inode, file); | 398 | return nonseekable_open(inode, file); |
387 | } | 399 | } |
@@ -403,7 +415,16 @@ static int wdt_release(struct inode *inode, struct file *file) | |||
403 | { | 415 | { |
404 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { | 416 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { |
405 | if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) { | 417 | if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) { |
406 | wdt_stop(); | 418 | int ret = wdt_stop(); |
419 | if (ret) { | ||
420 | /* | ||
421 | * Stop failed. Just keep the watchdog alive | ||
422 | * and hope nothing bad happens. | ||
423 | */ | ||
424 | set_bit(WDTS_EXPECTED, &wdt_status); | ||
425 | wdt_keepalive(); | ||
426 | return ret; | ||
427 | } | ||
407 | clear_bit(WDTS_TIMER_RUN, &wdt_status); | 428 | clear_bit(WDTS_TIMER_RUN, &wdt_status); |
408 | } else { | 429 | } else { |
409 | wdt_keepalive(); | 430 | wdt_keepalive(); |
@@ -484,7 +505,9 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
484 | &ident, sizeof(ident)) ? -EFAULT : 0; | 505 | &ident, sizeof(ident)) ? -EFAULT : 0; |
485 | 506 | ||
486 | case WDIOC_GETSTATUS: | 507 | case WDIOC_GETSTATUS: |
487 | wdt_get_status(&status); | 508 | rc = wdt_get_status(&status); |
509 | if (rc) | ||
510 | return rc; | ||
488 | return put_user(status, uarg.i); | 511 | return put_user(status, uarg.i); |
489 | 512 | ||
490 | case WDIOC_GETBOOTSTATUS: | 513 | case WDIOC_GETBOOTSTATUS: |
@@ -500,14 +523,22 @@ static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
500 | 523 | ||
501 | switch (new_options) { | 524 | switch (new_options) { |
502 | case WDIOS_DISABLECARD: | 525 | case WDIOS_DISABLECARD: |
503 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) | 526 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { |
504 | wdt_stop(); | 527 | rc = wdt_stop(); |
528 | if (rc) | ||
529 | return rc; | ||
530 | } | ||
505 | clear_bit(WDTS_TIMER_RUN, &wdt_status); | 531 | clear_bit(WDTS_TIMER_RUN, &wdt_status); |
506 | return 0; | 532 | return 0; |
507 | 533 | ||
508 | case WDIOS_ENABLECARD: | 534 | case WDIOS_ENABLECARD: |
509 | if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) | 535 | if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) { |
510 | wdt_start(); | 536 | rc = wdt_start(); |
537 | if (rc) { | ||
538 | clear_bit(WDTS_TIMER_RUN, &wdt_status); | ||
539 | return rc; | ||
540 | } | ||
541 | } | ||
511 | return 0; | 542 | return 0; |
512 | 543 | ||
513 | default: | 544 | default: |
@@ -560,16 +591,17 @@ static int __init it87_wdt_init(void) | |||
560 | int rc = 0; | 591 | int rc = 0; |
561 | int try_gameport = !nogameport; | 592 | int try_gameport = !nogameport; |
562 | u8 chip_rev; | 593 | u8 chip_rev; |
563 | unsigned long flags; | 594 | int gp_rreq_fail = 0; |
564 | 595 | ||
565 | wdt_status = 0; | 596 | wdt_status = 0; |
566 | 597 | ||
567 | spin_lock_irqsave(&spinlock, flags); | 598 | rc = superio_enter(); |
568 | superio_enter(); | 599 | if (rc) |
600 | return rc; | ||
601 | |||
569 | chip_type = superio_inw(CHIPID); | 602 | chip_type = superio_inw(CHIPID); |
570 | chip_rev = superio_inb(CHIPREV) & 0x0f; | 603 | chip_rev = superio_inb(CHIPREV) & 0x0f; |
571 | superio_exit(); | 604 | superio_exit(); |
572 | spin_unlock_irqrestore(&spinlock, flags); | ||
573 | 605 | ||
574 | switch (chip_type) { | 606 | switch (chip_type) { |
575 | case IT8702_ID: | 607 | case IT8702_ID: |
@@ -603,8 +635,9 @@ static int __init it87_wdt_init(void) | |||
603 | return -ENODEV; | 635 | return -ENODEV; |
604 | } | 636 | } |
605 | 637 | ||
606 | spin_lock_irqsave(&spinlock, flags); | 638 | rc = superio_enter(); |
607 | superio_enter(); | 639 | if (rc) |
640 | return rc; | ||
608 | 641 | ||
609 | superio_select(GPIO); | 642 | superio_select(GPIO); |
610 | superio_outb(WDT_TOV1, WDTCFG); | 643 | superio_outb(WDT_TOV1, WDTCFG); |
@@ -620,21 +653,16 @@ static int __init it87_wdt_init(void) | |||
620 | } | 653 | } |
621 | gpact = superio_inb(ACTREG); | 654 | gpact = superio_inb(ACTREG); |
622 | superio_outb(0x01, ACTREG); | 655 | superio_outb(0x01, ACTREG); |
623 | superio_exit(); | ||
624 | spin_unlock_irqrestore(&spinlock, flags); | ||
625 | if (request_region(base, 1, WATCHDOG_NAME)) | 656 | if (request_region(base, 1, WATCHDOG_NAME)) |
626 | set_bit(WDTS_USE_GP, &wdt_status); | 657 | set_bit(WDTS_USE_GP, &wdt_status); |
627 | else | 658 | else |
628 | rc = -EIO; | 659 | gp_rreq_fail = 1; |
629 | } else { | ||
630 | superio_exit(); | ||
631 | spin_unlock_irqrestore(&spinlock, flags); | ||
632 | } | 660 | } |
633 | 661 | ||
634 | /* If we haven't Gameport support, try to get CIR support */ | 662 | /* If we haven't Gameport support, try to get CIR support */ |
635 | if (!test_bit(WDTS_USE_GP, &wdt_status)) { | 663 | if (!test_bit(WDTS_USE_GP, &wdt_status)) { |
636 | if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) { | 664 | if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) { |
637 | if (rc == -EIO) | 665 | if (gp_rreq_fail) |
638 | printk(KERN_ERR PFX | 666 | printk(KERN_ERR PFX |
639 | "I/O Address 0x%04x and 0x%04x" | 667 | "I/O Address 0x%04x and 0x%04x" |
640 | " already in use\n", base, CIR_BASE); | 668 | " already in use\n", base, CIR_BASE); |
@@ -646,21 +674,16 @@ static int __init it87_wdt_init(void) | |||
646 | goto err_out; | 674 | goto err_out; |
647 | } | 675 | } |
648 | base = CIR_BASE; | 676 | base = CIR_BASE; |
649 | spin_lock_irqsave(&spinlock, flags); | ||
650 | superio_enter(); | ||
651 | 677 | ||
652 | superio_select(CIR); | 678 | superio_select(CIR); |
653 | superio_outw(base, BASEREG); | 679 | superio_outw(base, BASEREG); |
654 | superio_outb(0x00, CIR_ILS); | 680 | superio_outb(0x00, CIR_ILS); |
655 | ciract = superio_inb(ACTREG); | 681 | ciract = superio_inb(ACTREG); |
656 | superio_outb(0x01, ACTREG); | 682 | superio_outb(0x01, ACTREG); |
657 | if (rc == -EIO) { | 683 | if (gp_rreq_fail) { |
658 | superio_select(GAMEPORT); | 684 | superio_select(GAMEPORT); |
659 | superio_outb(gpact, ACTREG); | 685 | superio_outb(gpact, ACTREG); |
660 | } | 686 | } |
661 | |||
662 | superio_exit(); | ||
663 | spin_unlock_irqrestore(&spinlock, flags); | ||
664 | } | 687 | } |
665 | 688 | ||
666 | if (timeout < 1 || timeout > max_units * 60) { | 689 | if (timeout < 1 || timeout > max_units * 60) { |
@@ -704,6 +727,7 @@ static int __init it87_wdt_init(void) | |||
704 | "nogameport=%d)\n", chip_type, chip_rev, timeout, | 727 | "nogameport=%d)\n", chip_type, chip_rev, timeout, |
705 | nowayout, testmode, exclusive, nogameport); | 728 | nowayout, testmode, exclusive, nogameport); |
706 | 729 | ||
730 | superio_exit(); | ||
707 | return 0; | 731 | return 0; |
708 | 732 | ||
709 | err_out_reboot: | 733 | err_out_reboot: |
@@ -711,49 +735,37 @@ err_out_reboot: | |||
711 | err_out_region: | 735 | err_out_region: |
712 | release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); | 736 | release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); |
713 | if (!test_bit(WDTS_USE_GP, &wdt_status)) { | 737 | if (!test_bit(WDTS_USE_GP, &wdt_status)) { |
714 | spin_lock_irqsave(&spinlock, flags); | ||
715 | superio_enter(); | ||
716 | superio_select(CIR); | 738 | superio_select(CIR); |
717 | superio_outb(ciract, ACTREG); | 739 | superio_outb(ciract, ACTREG); |
718 | superio_exit(); | ||
719 | spin_unlock_irqrestore(&spinlock, flags); | ||
720 | } | 740 | } |
721 | err_out: | 741 | err_out: |
722 | if (try_gameport) { | 742 | if (try_gameport) { |
723 | spin_lock_irqsave(&spinlock, flags); | ||
724 | superio_enter(); | ||
725 | superio_select(GAMEPORT); | 743 | superio_select(GAMEPORT); |
726 | superio_outb(gpact, ACTREG); | 744 | superio_outb(gpact, ACTREG); |
727 | superio_exit(); | ||
728 | spin_unlock_irqrestore(&spinlock, flags); | ||
729 | } | 745 | } |
730 | 746 | ||
747 | superio_exit(); | ||
731 | return rc; | 748 | return rc; |
732 | } | 749 | } |
733 | 750 | ||
734 | static void __exit it87_wdt_exit(void) | 751 | static void __exit it87_wdt_exit(void) |
735 | { | 752 | { |
736 | unsigned long flags; | 753 | if (superio_enter() == 0) { |
737 | int nolock; | 754 | superio_select(GPIO); |
738 | 755 | superio_outb(0x00, WDTCTRL); | |
739 | nolock = !spin_trylock_irqsave(&spinlock, flags); | 756 | superio_outb(0x00, WDTCFG); |
740 | superio_enter(); | 757 | superio_outb(0x00, WDTVALLSB); |
741 | superio_select(GPIO); | 758 | if (max_units > 255) |
742 | superio_outb(0x00, WDTCTRL); | 759 | superio_outb(0x00, WDTVALMSB); |
743 | superio_outb(0x00, WDTCFG); | 760 | if (test_bit(WDTS_USE_GP, &wdt_status)) { |
744 | superio_outb(0x00, WDTVALLSB); | 761 | superio_select(GAMEPORT); |
745 | if (max_units > 255) | 762 | superio_outb(gpact, ACTREG); |
746 | superio_outb(0x00, WDTVALMSB); | 763 | } else { |
747 | if (test_bit(WDTS_USE_GP, &wdt_status)) { | 764 | superio_select(CIR); |
748 | superio_select(GAMEPORT); | 765 | superio_outb(ciract, ACTREG); |
749 | superio_outb(gpact, ACTREG); | 766 | } |
750 | } else { | 767 | superio_exit(); |
751 | superio_select(CIR); | ||
752 | superio_outb(ciract, ACTREG); | ||
753 | } | 768 | } |
754 | superio_exit(); | ||
755 | if (!nolock) | ||
756 | spin_unlock_irqrestore(&spinlock, flags); | ||
757 | 769 | ||
758 | misc_deregister(&wdt_miscdev); | 770 | misc_deregister(&wdt_miscdev); |
759 | unregister_reboot_notifier(&wdt_notifier); | 771 | unregister_reboot_notifier(&wdt_notifier); |