diff options
author | Tejun Heo <htejun@gmail.com> | 2006-10-09 05:32:15 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-01 22:40:28 -0500 |
commit | d1adc1bbd6dde3e05a91e2d3e6ab42d202ea61d5 (patch) | |
tree | 49d88b2f55bb88e5334979b418296af384149cda /include/linux | |
parent | a20c9e820864e18b59d2a4f2f04e8b6053986c95 (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 'include/linux')
-rw-r--r-- | include/linux/libata.h | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h index 2300fcc37f80..6c003d852a88 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -746,9 +746,8 @@ extern int ata_scsi_device_suspend(struct scsi_device *, pm_message_t mesg); | |||
746 | extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); | 746 | extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg); |
747 | extern void ata_host_resume(struct ata_host *host); | 747 | extern void ata_host_resume(struct ata_host *host); |
748 | extern int ata_ratelimit(void); | 748 | extern int ata_ratelimit(void); |
749 | extern unsigned int ata_busy_sleep(struct ata_port *ap, | 749 | extern int ata_busy_sleep(struct ata_port *ap, |
750 | unsigned long timeout_pat, | 750 | unsigned long timeout_pat, unsigned long timeout); |
751 | unsigned long timeout); | ||
752 | extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), | 751 | extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *), |
753 | void *data, unsigned long delay); | 752 | void *data, unsigned long delay); |
754 | extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, | 753 | extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val, |
@@ -1064,7 +1063,7 @@ static inline u8 ata_busy_wait(struct ata_port *ap, unsigned int bits, | |||
1064 | udelay(10); | 1063 | udelay(10); |
1065 | status = ata_chk_status(ap); | 1064 | status = ata_chk_status(ap); |
1066 | max--; | 1065 | max--; |
1067 | } while ((status & bits) && (max > 0)); | 1066 | } while (status != 0xff && (status & bits) && (max > 0)); |
1068 | 1067 | ||
1069 | return status; | 1068 | return status; |
1070 | } | 1069 | } |
@@ -1085,7 +1084,7 @@ static inline u8 ata_wait_idle(struct ata_port *ap) | |||
1085 | { | 1084 | { |
1086 | u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); | 1085 | u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000); |
1087 | 1086 | ||
1088 | if (status & (ATA_BUSY | ATA_DRQ)) { | 1087 | if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) { |
1089 | unsigned long l = ap->ioaddr.status_addr; | 1088 | unsigned long l = ap->ioaddr.status_addr; |
1090 | if (ata_msg_warn(ap)) | 1089 | if (ata_msg_warn(ap)) |
1091 | printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n", | 1090 | printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n", |