diff options
author | Jens Rottmann <JRottmann@LiPPERTEmbedded.de> | 2009-06-22 11:51:49 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-06-22 14:28:59 -0400 |
commit | e2434dc1c19412639dd047a4d4eff8ed0e5d0d50 (patch) | |
tree | aa723d51dedc8c404205877c9885af09906e6d18 /drivers/parport/parport_pc.c | |
parent | 752a4787511bf7515f99609ff4ae52341b5bfcde (diff) |
parport_pc: after superio probing restore original register values
CONFIG_PARPORT_PC_SUPERIO probes for various superio chips by writing
byte sequences to a set of different potential I/O ranges. But the
probed ranges are not exclusive to parallel ports. Some of our boards
just happen to have a watchdog in one of them. Took us almost a week
to figure out why some distros reboot without warning after running
flawlessly for 3 hours. For exactly 170 = 0xAA minutes, that is ...
Fixed by restoring original values after probing. Also fixed too small
request_region() in detect_and_report_it87().
Signed-off-by: Jens Rottmann <JRottmann@LiPPERTEmbedded.de>
Signed-off-by: Alan Cox <alan@linux.intel.com>
Cc: <stable@kernel.org>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/parport/parport_pc.c')
-rw-r--r-- | drivers/parport/parport_pc.c | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/drivers/parport/parport_pc.c b/drivers/parport/parport_pc.c index 151bf5bc8afe..7f1cca701c11 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c | |||
@@ -1471,11 +1471,13 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) | |||
1471 | 1471 | ||
1472 | static void __devinit winbond_check(int io, int key) | 1472 | static void __devinit winbond_check(int io, int key) |
1473 | { | 1473 | { |
1474 | int devid, devrev, oldid, x_devid, x_devrev, x_oldid; | 1474 | int origval, devid, devrev, oldid, x_devid, x_devrev, x_oldid; |
1475 | 1475 | ||
1476 | if (!request_region(io, 3, __func__)) | 1476 | if (!request_region(io, 3, __func__)) |
1477 | return; | 1477 | return; |
1478 | 1478 | ||
1479 | origval = inb(io); /* Save original value */ | ||
1480 | |||
1479 | /* First probe without key */ | 1481 | /* First probe without key */ |
1480 | outb(0x20, io); | 1482 | outb(0x20, io); |
1481 | x_devid = inb(io + 1); | 1483 | x_devid = inb(io + 1); |
@@ -1495,6 +1497,8 @@ static void __devinit winbond_check(int io, int key) | |||
1495 | oldid = inb(io + 1); | 1497 | oldid = inb(io + 1); |
1496 | outb(0xaa, io); /* Magic Seal */ | 1498 | outb(0xaa, io); /* Magic Seal */ |
1497 | 1499 | ||
1500 | outb(origval, io); /* in case we poked some entirely different hardware */ | ||
1501 | |||
1498 | if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) | 1502 | if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) |
1499 | goto out; /* protection against false positives */ | 1503 | goto out; /* protection against false positives */ |
1500 | 1504 | ||
@@ -1505,11 +1509,15 @@ out: | |||
1505 | 1509 | ||
1506 | static void __devinit winbond_check2(int io, int key) | 1510 | static void __devinit winbond_check2(int io, int key) |
1507 | { | 1511 | { |
1508 | int devid, devrev, oldid, x_devid, x_devrev, x_oldid; | 1512 | int origval[3], devid, devrev, oldid, x_devid, x_devrev, x_oldid; |
1509 | 1513 | ||
1510 | if (!request_region(io, 3, __func__)) | 1514 | if (!request_region(io, 3, __func__)) |
1511 | return; | 1515 | return; |
1512 | 1516 | ||
1517 | origval[0] = inb(io); /* Save original values */ | ||
1518 | origval[1] = inb(io + 1); | ||
1519 | origval[2] = inb(io + 2); | ||
1520 | |||
1513 | /* First probe without the key */ | 1521 | /* First probe without the key */ |
1514 | outb(0x20, io + 2); | 1522 | outb(0x20, io + 2); |
1515 | x_devid = inb(io + 2); | 1523 | x_devid = inb(io + 2); |
@@ -1528,6 +1536,10 @@ static void __devinit winbond_check2(int io, int key) | |||
1528 | oldid = inb(io + 2); | 1536 | oldid = inb(io + 2); |
1529 | outb(0xaa, io); /* Magic Seal */ | 1537 | outb(0xaa, io); /* Magic Seal */ |
1530 | 1538 | ||
1539 | outb(origval[0], io); /* in case we poked some entirely different hardware */ | ||
1540 | outb(origval[1], io + 1); | ||
1541 | outb(origval[2], io + 2); | ||
1542 | |||
1531 | if (x_devid == devid && x_devrev == devrev && x_oldid == oldid) | 1543 | if (x_devid == devid && x_devrev == devrev && x_oldid == oldid) |
1532 | goto out; /* protection against false positives */ | 1544 | goto out; /* protection against false positives */ |
1533 | 1545 | ||
@@ -1538,11 +1550,13 @@ out: | |||
1538 | 1550 | ||
1539 | static void __devinit smsc_check(int io, int key) | 1551 | static void __devinit smsc_check(int io, int key) |
1540 | { | 1552 | { |
1541 | int id, rev, oldid, oldrev, x_id, x_rev, x_oldid, x_oldrev; | 1553 | int origval, id, rev, oldid, oldrev, x_id, x_rev, x_oldid, x_oldrev; |
1542 | 1554 | ||
1543 | if (!request_region(io, 3, __func__)) | 1555 | if (!request_region(io, 3, __func__)) |
1544 | return; | 1556 | return; |
1545 | 1557 | ||
1558 | origval = inb(io); /* Save original value */ | ||
1559 | |||
1546 | /* First probe without the key */ | 1560 | /* First probe without the key */ |
1547 | outb(0x0d, io); | 1561 | outb(0x0d, io); |
1548 | x_oldid = inb(io + 1); | 1562 | x_oldid = inb(io + 1); |
@@ -1566,6 +1580,8 @@ static void __devinit smsc_check(int io, int key) | |||
1566 | rev = inb(io + 1); | 1580 | rev = inb(io + 1); |
1567 | outb(0xaa, io); /* Magic Seal */ | 1581 | outb(0xaa, io); /* Magic Seal */ |
1568 | 1582 | ||
1583 | outb(origval, io); /* in case we poked some entirely different hardware */ | ||
1584 | |||
1569 | if (x_id == id && x_oldrev == oldrev && | 1585 | if (x_id == id && x_oldrev == oldrev && |
1570 | x_oldid == oldid && x_rev == rev) | 1586 | x_oldid == oldid && x_rev == rev) |
1571 | goto out; /* protection against false positives */ | 1587 | goto out; /* protection against false positives */ |
@@ -1602,11 +1618,12 @@ static void __devinit detect_and_report_smsc(void) | |||
1602 | static void __devinit detect_and_report_it87(void) | 1618 | static void __devinit detect_and_report_it87(void) |
1603 | { | 1619 | { |
1604 | u16 dev; | 1620 | u16 dev; |
1605 | u8 r; | 1621 | u8 origval, r; |
1606 | if (verbose_probing) | 1622 | if (verbose_probing) |
1607 | printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n"); | 1623 | printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n"); |
1608 | if (!request_region(0x2e, 1, __func__)) | 1624 | if (!request_region(0x2e, 2, __func__)) |
1609 | return; | 1625 | return; |
1626 | origval = inb(0x2e); /* Save original value */ | ||
1610 | outb(0x87, 0x2e); | 1627 | outb(0x87, 0x2e); |
1611 | outb(0x01, 0x2e); | 1628 | outb(0x01, 0x2e); |
1612 | outb(0x55, 0x2e); | 1629 | outb(0x55, 0x2e); |
@@ -1626,8 +1643,10 @@ static void __devinit detect_and_report_it87(void) | |||
1626 | outb(r | 8, 0x2F); | 1643 | outb(r | 8, 0x2F); |
1627 | outb(0x02, 0x2E); /* Lock */ | 1644 | outb(0x02, 0x2E); /* Lock */ |
1628 | outb(0x02, 0x2F); | 1645 | outb(0x02, 0x2F); |
1646 | } else { | ||
1647 | outb(origval, 0x2e); /* Oops, sorry to disturb */ | ||
1629 | } | 1648 | } |
1630 | release_region(0x2e, 1); | 1649 | release_region(0x2e, 2); |
1631 | } | 1650 | } |
1632 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ | 1651 | #endif /* CONFIG_PARPORT_PC_SUPERIO */ |
1633 | 1652 | ||