From owner-freebsd-stable@FreeBSD.ORG Sun Feb 27 22:24:35 2005 Return-Path: Delivered-To: freebsd-stable@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id E005D16A4CF; Sun, 27 Feb 2005 22:24:34 +0000 (GMT) Received: from ylpvm15.prodigy.net (ylpvm15-ext.prodigy.net [207.115.57.46]) by mx1.FreeBSD.org (Postfix) with ESMTP id 6017143D5A; Sun, 27 Feb 2005 22:24:34 +0000 (GMT) (envelope-from nate@root.org) Received: from [10.0.0.115] (adsl-64-171-186-189.dsl.snfc21.pacbell.net [64.171.186.189])j1RMKJki016530; Sun, 27 Feb 2005 17:20:19 -0500 Message-ID: <42224897.7050006@root.org> Date: Sun, 27 Feb 2005 14:24:23 -0800 From: Nate Lawson User-Agent: Mozilla Thunderbird 1.0RC1 (X11/20041205) X-Accept-Language: en-us, en MIME-Version: 1.0 To: current@freebsd.org Content-Type: multipart/mixed; boundary="------------050003020907080907020009" cc: stable@freebsd.org Subject: patch: fix 30 second hang while resuming X-BeenThere: freebsd-stable@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Production branch of FreeBSD source code List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 27 Feb 2005 22:24:35 -0000 This is a multi-part message in MIME format. --------------050003020907080907020009 Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit My system hangs a long time in ata_generic_reset() while resuming. I did some hunting and found that the loop was running for the full 310 * 100 ms (31 seconds). The bug is that the loop never exits when mask goes to 0 even though this is a termination condition (see end of the loop where the code masks off 1 and 2). The attached patch fixes this by exiting when the mask is set to 0 instead of looping the full 31 seconds. This is correct since setting the mask to 0 is how the loop marks master/slave "done". It also has a minor whitespace fix. I recorded the following set of status values (with my patch) so you can see the states the master/slave go through. Each is labeled with the if() check it is associated with. For instance, "stat0 & ATA_S_BUSY" means the first if() triggered and gives further info about the status. "start:" is at the beginning of the for(). It used to print this about 300 times while making no progress at the point labeled [] below: start: mask 0 stat0 50 stat1 0 Here's how it looks with my patch: ata_reinit reset ata0: reset tp1 mask=03 ostat0=80 ostat1=00 start: mask 3 stat0 80 stat1 80 stat0 & ATA_S_BUSY: stat0 80 ad0: stat=0x80 err=0x80 lsb=0x80 msb=0x80 mask == 0x03: stat0 80 stat1 80 err 80 start: mask 3 stat0 80 stat1 80 stat0 & ATA_S_BUSY: stat0 80 ad0: stat=0x80 err=0x80 lsb=0x80 msb=0x80 mask == 0x03: stat0 80 stat1 80 err 80 start: mask 3 stat0 80 stat1 80 stat0 & ATA_S_BUSY: stat0 80 ad0: stat=0x80 err=0x80 lsb=0x80 msb=0x80 mask == 0x03: stat0 80 stat1 80 err 80 start: mask 3 stat0 80 stat1 80 stat0 & ATA_S_BUSY: stat0 80 ad0: stat=0x80 err=0x80 lsb=0x80 msb=0x80 mask == 0x03: stat0 80 stat1 80 err 80 start: mask 3 stat0 80 stat1 80 stat0 & ATA_S_BUSY: stat0 80 ad0: stat=0x80 err=0x80 lsb=0x80 msb=0x80 mask == 0x03: stat0 80 stat1 80 err 80 start: mask 3 stat0 80 stat1 80 stat0 & ATA_S_BUSY: stat0 80 ad0: stat=0x80 err=0x80 lsb=0x80 msb=0x80 mask == 0x03: stat0 80 stat1 80 err 80 start: mask 3 stat0 80 stat1 80 stat0 & ATA_S_BUSY: stat0 80 ad0: stat=0x50 err=0x01 lsb=0x00 msb=0x00 !((mask == 0x03): mask 3 stat0 50 stat1 80 ata0-slave: stat=0x00 err=0x01 lsb=0x00 msb=0x00 mask == 0x03: stat0 50 stat1 0 err 1 [mask set to 0 in both checks, code continues but used to hang here] ata0: reset tp2 stat0=50 stat1=00 devices=0x1 ata0: resetting done .. -- Nate --------------050003020907080907020009 Content-Type: text/plain; name="ata_resume.diff" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="ata_resume.diff" Index: sys/dev/ata/ata-lowlevel.c =================================================================== RCS file: /home/ncvs/src/sys/dev/ata/ata-lowlevel.c,v retrieving revision 1.51 diff -u -r1.51 ata-lowlevel.c --- sys/dev/ata/ata-lowlevel.c 24 Dec 2004 13:38:25 -0000 1.51 +++ sys/dev/ata/ata-lowlevel.c 27 Feb 2005 22:19:30 -0000 @@ -619,8 +619,10 @@ (stat1 == err && lsb == err && msb == err && timeout > 5)) mask &= ~0x02; } + if (mask == 0) + break; ata_udelay(100000); - } + } if (bootverbose) ata_printf(ch, -1, --------------050003020907080907020009--