Skip site navigation (1)Skip section navigation (2)
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>