Date: Sun, 27 Feb 2005 14:24:23 -0800 From: Nate Lawson <nate@root.org> To: current@freebsd.org Cc: stable@freebsd.org Subject: patch: fix 30 second hang while resuming Message-ID: <42224897.7050006@root.org>
next in thread | raw e-mail | index | archive | help
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<ATA_MASTER> 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--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?42224897.7050006>