aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-10-09 05:32:15 -0400
committerJeff Garzik <jeff@garzik.org>2006-12-01 22:40:28 -0500
commitd1adc1bbd6dde3e05a91e2d3e6ab42d202ea61d5 (patch)
tree49d88b2f55bb88e5334979b418296af384149cda /drivers/ata
parenta20c9e820864e18b59d2a4f2f04e8b6053986c95 (diff)
[PATCH] libata: handle 0xff status properly
libata waits for !BSY even when the status register reports 0xff. This causes long boot delays when D8 isn't pulled down properly. This patch does the followings. * don't wait if status register is 0xff in all wait functions * make ata_busy_sleep() return 0 on success and -errno on failure. -ENODEV is returned on 0xff status and -EBUSY on other failures. * make ata_bus_softreset() succeed on 0xff status. 0xff status is not reset failure. It indicates no device. This removes unnecessary retries on such ports. Note that the code change assumes unoccupied port reporting 0xff status does not produce valid device signature. Signed-off-by: Tejun Heo <htejun@gmail.com> Cc: Joe Jin <lkmaillist@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-core.c30
1 files changed, 18 insertions, 12 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index b4fbfebafd26..d2336673601c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2328,11 +2328,14 @@ static inline void ata_tf_to_host(struct ata_port *ap,
2328 * Sleep until ATA Status register bit BSY clears, 2328 * Sleep until ATA Status register bit BSY clears,
2329 * or a timeout occurs. 2329 * or a timeout occurs.
2330 * 2330 *
2331 * LOCKING: None. 2331 * LOCKING:
2332 * Kernel thread context (may sleep).
2333 *
2334 * RETURNS:
2335 * 0 on success, -errno otherwise.
2332 */ 2336 */
2333 2337int ata_busy_sleep(struct ata_port *ap,
2334unsigned int ata_busy_sleep (struct ata_port *ap, 2338 unsigned long tmout_pat, unsigned long tmout)
2335 unsigned long tmout_pat, unsigned long tmout)
2336{ 2339{
2337 unsigned long timer_start, timeout; 2340 unsigned long timer_start, timeout;
2338 u8 status; 2341 u8 status;
@@ -2340,27 +2343,32 @@ unsigned int ata_busy_sleep (struct ata_port *ap,
2340 status = ata_busy_wait(ap, ATA_BUSY, 300); 2343 status = ata_busy_wait(ap, ATA_BUSY, 300);
2341 timer_start = jiffies; 2344 timer_start = jiffies;
2342 timeout = timer_start + tmout_pat; 2345 timeout = timer_start + tmout_pat;
2343 while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { 2346 while (status != 0xff && (status & ATA_BUSY) &&
2347 time_before(jiffies, timeout)) {
2344 msleep(50); 2348 msleep(50);
2345 status = ata_busy_wait(ap, ATA_BUSY, 3); 2349 status = ata_busy_wait(ap, ATA_BUSY, 3);
2346 } 2350 }
2347 2351
2348 if (status & ATA_BUSY) 2352 if (status != 0xff && (status & ATA_BUSY))
2349 ata_port_printk(ap, KERN_WARNING, 2353 ata_port_printk(ap, KERN_WARNING,
2350 "port is slow to respond, please be patient " 2354 "port is slow to respond, please be patient "
2351 "(Status 0x%x)\n", status); 2355 "(Status 0x%x)\n", status);
2352 2356
2353 timeout = timer_start + tmout; 2357 timeout = timer_start + tmout;
2354 while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) { 2358 while (status != 0xff && (status & ATA_BUSY) &&
2359 time_before(jiffies, timeout)) {
2355 msleep(50); 2360 msleep(50);
2356 status = ata_chk_status(ap); 2361 status = ata_chk_status(ap);
2357 } 2362 }
2358 2363
2364 if (status == 0xff)
2365 return -ENODEV;
2366
2359 if (status & ATA_BUSY) { 2367 if (status & ATA_BUSY) {
2360 ata_port_printk(ap, KERN_ERR, "port failed to respond " 2368 ata_port_printk(ap, KERN_ERR, "port failed to respond "
2361 "(%lu secs, Status 0x%x)\n", 2369 "(%lu secs, Status 0x%x)\n",
2362 tmout / HZ, status); 2370 tmout / HZ, status);
2363 return 1; 2371 return -EBUSY;
2364 } 2372 }
2365 2373
2366 return 0; 2374 return 0;
@@ -2451,10 +2459,8 @@ static unsigned int ata_bus_softreset(struct ata_port *ap,
2451 * the bus shows 0xFF because the odd clown forgets the D7 2459 * the bus shows 0xFF because the odd clown forgets the D7
2452 * pulldown resistor. 2460 * pulldown resistor.
2453 */ 2461 */
2454 if (ata_check_status(ap) == 0xFF) { 2462 if (ata_check_status(ap) == 0xFF)
2455 ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n"); 2463 return 0;
2456 return AC_ERR_OTHER;
2457 }
2458 2464
2459 ata_bus_post_reset(ap, devmask); 2465 ata_bus_post_reset(ap, devmask);
2460 2466