patch: fix 30 second hang while resuming

From: Nate Lawson (nate_at_root.org)
Date: 02/27/05

  • Next message: Nate Lawson: "patch: fix ata panic with Thinkpad CD and DVD drives"
    Date: Sun, 27 Feb 2005 14:24:23 -0800
    To: current@freebsd.org
    
    
    

    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
    
    

    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,

    
    

    _______________________________________________
    freebsd-current@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-current
    To unsubscribe, send any mail to "freebsd-current-unsubscribe@freebsd.org"

    
    

    _______________________________________________
    freebsd-stable@freebsd.org mailing list
    http://lists.freebsd.org/mailman/listinfo/freebsd-stable
    To unsubscribe, send any mail to "freebsd-stable-unsubscribe@freebsd.org"


  • Next message: Nate Lawson: "patch: fix ata panic with Thinkpad CD and DVD drives"

    Relevant Pages

    • Re: how to simplify/shorten this loop of bit shifting code?
      ... (See original for longer description and original code and variable ... The mask is apparently 0x0f, then 0xf0, ... If the loop is expected to run for relatively many 4-bit "nybbles", ... Unrolling the "do not mask" loop is ugly, but just for illustration, ...
      (comp.lang.c)
    • patch: fix 30 second hang while resuming
      ... My system hangs a long time in ata_generic_resetwhile resuming. ... The bug is that the loop never exits when mask ... The attached patch fixes this by exiting when the mask is set to 0 ... I recorded the following set of status values (with my patch) so you can ...
      (freebsd-current)
    • patch: fix 30 second hang while resuming
      ... My system hangs a long time in ata_generic_resetwhile resuming. ... The bug is that the loop never exits when mask ... The attached patch fixes this by exiting when the mask is set to 0 ... I recorded the following set of status values (with my patch) so you can ...
      (freebsd-stable)
    • Re: Nested loop with no overlap
      ... Hilay Selivansky wrote: ... > My solution so far is to write a very long if in lowest loop checking ... a4 loop index performs a single shift and mask if-test to weed out its ... from actual loop overhead as well (you still want to do the "deduce the ...
      (comp.programming)
    • Re: possible overflow?
      ... > 'mask' has a single bit set, each loop it's shifted one position. ... > If you add one to that, you get the ASCII value of the character 1. ...
      (comp.programming)