From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1764028AbZFORmR (ORCPT ); Mon, 15 Jun 2009 13:42:17 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752927AbZFORmC (ORCPT ); Mon, 15 Jun 2009 13:42:02 -0400 Received: from mail.lippert-at.com ([62.80.22.186]:22230 "EHLO domex.lippertembedded.de" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1752412AbZFORmB (ORCPT ); Mon, 15 Jun 2009 13:42:01 -0400 X-Greylist: delayed 488 seconds by postgrey-1.27 at vger.kernel.org; Mon, 15 Jun 2009 13:42:01 EDT Message-ID: <4A368600.5030009@LiPPERTEmbedded.de> Date: Mon, 15 Jun 2009 19:33:52 +0200 From: Jens Rottmann User-Agent: Thunderbird 1.5.0.14 (Windows/20071210) MIME-Version: 1.0 To: linux-parport@lists.infradead.org CC: linux-kernel@vger.kernel.org Subject: [PATCH] parport_pc: after superio probing restore original register values Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit X-OriginalArrivalTime: 15 Jun 2009 17:34:32.0687 (UTC) FILETIME=[8B45D7F0:01C9EDDF] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 --- Patch is against Linus' current git tree. --- linux-2.6.30-git8/drivers/parport/parport_pc.c +++ conservative-superio-probing/drivers/parport/parport_pc.c @@ -1471,11 +1471,13 @@ static void __devinit decode_smsc(int ef 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); @@ -1495,6 +1497,8 @@ static void __devinit winbond_check(int 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 */ @@ -1505,11 +1509,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); @@ -1528,6 +1536,10 @@ static void __devinit winbond_check2(int 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 */ @@ -1538,11 +1550,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); @@ -1566,6 +1580,8 @@ static void __devinit smsc_check(int io, 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 */ @@ -1602,11 +1618,12 @@ static void __devinit detect_and_report_ 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); @@ -1626,8 +1643,10 @@ static void __devinit detect_and_report_ 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 */ _