ahci: fix hang on failed softreset
authorTejun Heo <tj@kernel.org>
Fri, 27 Aug 2010 09:09:15 +0000 (11:09 +0200)
committerJeff Garzik <jgarzik@redhat.com>
Thu, 9 Sep 2010 18:19:18 +0000 (14:19 -0400)
ahci_do_softreset() compared the current time and deadline in reverse
when calculating timeout for SRST issue.  The result is that if
@deadline is in future, SRST is issued with 0 timeout, which hasn't
caused any problem because it later waits for DRDY with the correct
timeout.  If deadline is already exceeded by the time SRST is about to
be issued, the timeout calculation underflows and if the device
doesn't respond, timeout doesn't trigger for a _very_ long time.

Reverse the incorrect comparison order.

Signed-off-by: Tejun Heo <tj@kernel.org>
Reported-by: Anssi Hannula <anssi.hannula@iki.fi>
Tested-by: Gwendal Grignou <gwendal@google.com>
Cc: stable@kernel.org
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/ata/libahci.c

index 666850d31df2c304b9d1409e21e20355d52f2a65..68dc6785472f86932f769029ae6046a0dffeec47 100644 (file)
@@ -1326,7 +1326,7 @@ int ahci_do_softreset(struct ata_link *link, unsigned int *class,
        /* issue the first D2H Register FIS */
        msecs = 0;
        now = jiffies;
-       if (time_after(now, deadline))
+       if (time_after(deadline, now))
                msecs = jiffies_to_msecs(deadline - now);
 
        tf.ctl |= ATA_SRST;