Commit e2434dc1 authored by Jens Rottmann's avatar Jens Rottmann Committed by Linus Torvalds

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: default avatarJens Rottmann <JRottmann@LiPPERTEmbedded.de>
Signed-off-by: default avatarAlan Cox <alan@linux.intel.com>
Cc: <stable@kernel.org>
Acked-by: default avatarJeff Garzik <jgarzik@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 752a4787
...@@ -1471,11 +1471,13 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) ...@@ -1471,11 +1471,13 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev)
static void __devinit winbond_check(int io, int key) static void __devinit winbond_check(int io, int key)
{ {
int devid, devrev, oldid, x_devid, x_devrev, x_oldid; int origval, devid, devrev, oldid, x_devid, x_devrev, x_oldid;
if (!request_region(io, 3, __func__)) if (!request_region(io, 3, __func__))
return; return;
origval = inb(io); /* Save original value */
/* First probe without key */ /* First probe without key */
outb(0x20, io); outb(0x20, io);
x_devid = inb(io + 1); x_devid = inb(io + 1);
...@@ -1495,6 +1497,8 @@ static void __devinit winbond_check(int io, int key) ...@@ -1495,6 +1497,8 @@ static void __devinit winbond_check(int io, int key)
oldid = inb(io + 1); oldid = inb(io + 1);
outb(0xaa, io); /* Magic Seal */ outb(0xaa, io); /* Magic Seal */
outb(origval, io); /* in case we poked some entirely different hardware */
if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid)) if ((x_devid == devid) && (x_devrev == devrev) && (x_oldid == oldid))
goto out; /* protection against false positives */ goto out; /* protection against false positives */
...@@ -1505,11 +1509,15 @@ out: ...@@ -1505,11 +1509,15 @@ out:
static void __devinit winbond_check2(int io, int key) static void __devinit winbond_check2(int io, int key)
{ {
int devid, devrev, oldid, x_devid, x_devrev, x_oldid; int origval[3], devid, devrev, oldid, x_devid, x_devrev, x_oldid;
if (!request_region(io, 3, __func__)) if (!request_region(io, 3, __func__))
return; return;
origval[0] = inb(io); /* Save original values */
origval[1] = inb(io + 1);
origval[2] = inb(io + 2);
/* First probe without the key */ /* First probe without the key */
outb(0x20, io + 2); outb(0x20, io + 2);
x_devid = inb(io + 2); x_devid = inb(io + 2);
...@@ -1528,6 +1536,10 @@ static void __devinit winbond_check2(int io, int key) ...@@ -1528,6 +1536,10 @@ static void __devinit winbond_check2(int io, int key)
oldid = inb(io + 2); oldid = inb(io + 2);
outb(0xaa, io); /* Magic Seal */ outb(0xaa, io); /* Magic Seal */
outb(origval[0], io); /* in case we poked some entirely different hardware */
outb(origval[1], io + 1);
outb(origval[2], io + 2);
if (x_devid == devid && x_devrev == devrev && x_oldid == oldid) if (x_devid == devid && x_devrev == devrev && x_oldid == oldid)
goto out; /* protection against false positives */ goto out; /* protection against false positives */
...@@ -1538,11 +1550,13 @@ out: ...@@ -1538,11 +1550,13 @@ out:
static void __devinit smsc_check(int io, int key) static void __devinit smsc_check(int io, int key)
{ {
int id, rev, oldid, oldrev, x_id, x_rev, x_oldid, x_oldrev; int origval, id, rev, oldid, oldrev, x_id, x_rev, x_oldid, x_oldrev;
if (!request_region(io, 3, __func__)) if (!request_region(io, 3, __func__))
return; return;
origval = inb(io); /* Save original value */
/* First probe without the key */ /* First probe without the key */
outb(0x0d, io); outb(0x0d, io);
x_oldid = inb(io + 1); x_oldid = inb(io + 1);
...@@ -1566,6 +1580,8 @@ static void __devinit smsc_check(int io, int key) ...@@ -1566,6 +1580,8 @@ static void __devinit smsc_check(int io, int key)
rev = inb(io + 1); rev = inb(io + 1);
outb(0xaa, io); /* Magic Seal */ outb(0xaa, io); /* Magic Seal */
outb(origval, io); /* in case we poked some entirely different hardware */
if (x_id == id && x_oldrev == oldrev && if (x_id == id && x_oldrev == oldrev &&
x_oldid == oldid && x_rev == rev) x_oldid == oldid && x_rev == rev)
goto out; /* protection against false positives */ goto out; /* protection against false positives */
...@@ -1602,11 +1618,12 @@ static void __devinit detect_and_report_smsc(void) ...@@ -1602,11 +1618,12 @@ static void __devinit detect_and_report_smsc(void)
static void __devinit detect_and_report_it87(void) static void __devinit detect_and_report_it87(void)
{ {
u16 dev; u16 dev;
u8 r; u8 origval, r;
if (verbose_probing) if (verbose_probing)
printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n"); printk(KERN_DEBUG "IT8705 Super-IO detection, now testing port 2E ...\n");
if (!request_region(0x2e, 1, __func__)) if (!request_region(0x2e, 2, __func__))
return; return;
origval = inb(0x2e); /* Save original value */
outb(0x87, 0x2e); outb(0x87, 0x2e);
outb(0x01, 0x2e); outb(0x01, 0x2e);
outb(0x55, 0x2e); outb(0x55, 0x2e);
...@@ -1626,8 +1643,10 @@ static void __devinit detect_and_report_it87(void) ...@@ -1626,8 +1643,10 @@ static void __devinit detect_and_report_it87(void)
outb(r | 8, 0x2F); outb(r | 8, 0x2F);
outb(0x02, 0x2E); /* Lock */ outb(0x02, 0x2E); /* Lock */
outb(0x02, 0x2F); outb(0x02, 0x2F);
} else {
outb(origval, 0x2e); /* Oops, sorry to disturb */
} }
release_region(0x2e, 1); release_region(0x2e, 2);
} }
#endif /* CONFIG_PARPORT_PC_SUPERIO */ #endif /* CONFIG_PARPORT_PC_SUPERIO */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment