patch: fix 30 second hang while resuming
Nate Lawson
nate at root.org
Sun Jul 3 00:38:03 GMT 2005
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
-------------- next part --------------
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,
-------------- next part --------------
_______________________________________________
freebsd-current at freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-current
To unsubscribe, send any mail to "freebsd-current-unsubscribe at freebsd.org"
More information about the freebsd-stable
mailing list