aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/watchdog
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/watchdog')
-rw-r--r--drivers/watchdog/it8712f_wdt.c61
-rw-r--r--drivers/watchdog/it87_wdt.c168
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
52static unsigned long wdt_open; 52static unsigned long wdt_open;
53static unsigned expect_close; 53static unsigned expect_close;
54static spinlock_t io_lock;
55static unsigned char revision; 54static 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
124static inline void superio_enter(void) 123static 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
133static inline void superio_exit(void) 138static 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
140static inline void it8712f_wdt_ping(void) 145static 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
176static void it8712f_wdt_enable(void) 181static 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
191static void it8712f_wdt_disable(void) 201static 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
207static int it8712f_wdt_notify(struct notifier_block *this, 220static 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
300static int it8712f_wdt_open(struct inode *inode, struct file *file) 318static 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
138static unsigned int base, gpact, ciract, max_units, chip_type; 138static unsigned int base, gpact, ciract, max_units, chip_type;
139static unsigned long wdt_status; 139static unsigned long wdt_status;
140static DEFINE_SPINLOCK(spinlock);
141 140
142static int nogameport = DEFAULT_NOGAMEPORT; 141static int nogameport = DEFAULT_NOGAMEPORT;
143static int exclusive = DEFAULT_EXCLUSIVE; 142static 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
166static inline void superio_enter(void) 165static 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
174static inline void superio_exit(void) 180static 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
180static inline void superio_select(int ldn) 187static 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
258static void wdt_start(void) 265static 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
276static void wdt_stop(void) 283static 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
304static int wdt_set_timeout(int t) 310static 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
340static int wdt_get_status(int *status) 345static 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
709err_out_reboot: 733err_out_reboot:
@@ -711,49 +735,37 @@ err_out_reboot:
711err_out_region: 735err_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 }
721err_out: 741err_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
734static void __exit it87_wdt_exit(void) 751static 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);