diff options
author | Jens Rottmann <JRottmann@LiPPERTEmbedded.de> | 2009-06-22 16:51:49 +0100 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2009-07-02 16:31:56 -0700 |
commit | 301c1074fae4197b12a9c36db8bc38480b51c283 (patch) | |
tree | dc4b0215a4703df2e17540c25788a835daad3f3a /drivers | |
parent | fe05dfbd8f652ac0ef0d30d9498066bb9b8da0e0 (diff) |
parport_pc: after superio probing restore original register values
commit e2434dc1c19412639dd047a4d4eff8ed0e5d0d50 upstream.
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>
Acked-by: Jeff Garzik <jgarzik@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-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 8a846adf1dcf..65cf9c35ef33 100644 --- a/drivers/parport/parport_pc.c +++ b/drivers/parport/parport_pc.c @@ -1413,11 +1413,13 @@ static void __devinit decode_smsc(int efer, int key, int devid, int devrev) 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__)) return; + origval = inb(io); /* Save original value */ + /* First probe without key */ outb(0x20,io); x_devid=inb(io+1); @@ -1437,6 +1439,8 @@ static void __devinit winbond_check(int io, int key) oldid=inb(io+1); 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)) goto out; /* protection against false positives */ @@ -1447,11 +1451,15 @@ out: 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__)) return; + origval[0] = inb(io); /* Save original values */ + origval[1] = inb(io + 1); + origval[2] = inb(io + 2); + /* First probe without the key */ outb(0x20,io+2); x_devid=inb(io+2); @@ -1470,6 +1478,10 @@ static void __devinit winbond_check2(int io,int key) oldid=inb(io+2); 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)) goto out; /* protection against false positives */ @@ -1480,11 +1492,13 @@ out: 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__)) return; + origval = inb(io); /* Save original value */ + /* First probe without the key */ outb(0x0d,io); x_oldid=inb(io+1); @@ -1508,6 +1522,8 @@ static void __devinit smsc_check(int io, int key) rev=inb(io+1); outb(0xaa,io); /* Magic Seal */ + outb(origval, io); /* in case we poked some entirely different hardware */ + if ((x_id == id) && (x_oldrev == oldrev) && (x_oldid == oldid) && (x_rev == rev)) goto out; /* protection against false positives */ @@ -1544,11 +1560,12 @@ static void __devinit detect_and_report_smsc (void) static void __devinit detect_and_report_it87(void) { u16 dev; - u8 r; + u8 origval, r; if (verbose_probing) 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; + origval = inb(0x2e); /* Save original value */ outb(0x87, 0x2e); outb(0x01, 0x2e); outb(0x55, 0x2e); @@ -1568,8 +1585,10 @@ static void __devinit detect_and_report_it87(void) outb(r | 8, 0x2F); outb(0x02, 0x2E); /* Lock */ outb(0x02, 0x2F); + } else { + outb(origval, 0x2e); /* Oops, sorry to disturb */ } - release_region(0x2e, 1); + release_region(0x2e, 2); } #endif /* CONFIG_PARPORT_PC_SUPERIO */ |