* [PATCH] libata: handle 0xff status properly
@ 2006-10-09 9:32 Tejun Heo
2006-10-11 16:16 ` Alan Cox
2006-11-01 4:50 ` Jeff Garzik
0 siblings, 2 replies; 3+ messages in thread
From: Tejun Heo @ 2006-10-09 9:32 UTC (permalink / raw)
To: Jeff Garzik, Alan Cox, linux-ide; +Cc: Joe Jin
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>
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 7ab45f4..68e9d0a 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2321,11 +2321,14 @@ static inline void ata_tf_to_host(struct
* Sleep until ATA Status register bit BSY clears,
* or a timeout occurs.
*
- * LOCKING: None.
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ *
+ * RETURNS:
+ * 0 on success, -errno otherwise.
*/
-
-unsigned int ata_busy_sleep (struct ata_port *ap,
- unsigned long tmout_pat, unsigned long tmout)
+int ata_busy_sleep(struct ata_port *ap,
+ unsigned long tmout_pat, unsigned long tmout)
{
unsigned long timer_start, timeout;
u8 status;
@@ -2333,27 +2336,32 @@ unsigned int ata_busy_sleep (struct ata_
status = ata_busy_wait(ap, ATA_BUSY, 300);
timer_start = jiffies;
timeout = timer_start + tmout_pat;
- while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+ while (status != 0xff && (status & ATA_BUSY) &&
+ time_before(jiffies, timeout)) {
msleep(50);
status = ata_busy_wait(ap, ATA_BUSY, 3);
}
- if (status & ATA_BUSY)
+ if (status != 0xff && (status & ATA_BUSY))
ata_port_printk(ap, KERN_WARNING,
"port is slow to respond, please be patient "
"(Status 0x%x)\n", status);
timeout = timer_start + tmout;
- while ((status & ATA_BUSY) && (time_before(jiffies, timeout))) {
+ while (status != 0xff && (status & ATA_BUSY) &&
+ time_before(jiffies, timeout)) {
msleep(50);
status = ata_chk_status(ap);
}
+ if (status == 0xff)
+ return -ENODEV;
+
if (status & ATA_BUSY) {
ata_port_printk(ap, KERN_ERR, "port failed to respond "
"(%lu secs, Status 0x%x)\n",
tmout / HZ, status);
- return 1;
+ return -EBUSY;
}
return 0;
@@ -2444,10 +2452,8 @@ static unsigned int ata_bus_softreset(st
* the bus shows 0xFF because the odd clown forgets the D7
* pulldown resistor.
*/
- if (ata_check_status(ap) == 0xFF) {
- ata_port_printk(ap, KERN_ERR, "SRST failed (status 0xFF)\n");
- return AC_ERR_OTHER;
- }
+ if (ata_check_status(ap) == 0xFF)
+ return 0;
ata_bus_post_reset(ap, devmask);
diff --git a/include/linux/libata.h b/include/linux/libata.h
index df44b09..2306cb8 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -744,9 +744,8 @@ extern int ata_scsi_device_suspend(struc
extern int ata_host_suspend(struct ata_host *host, pm_message_t mesg);
extern void ata_host_resume(struct ata_host *host);
extern int ata_ratelimit(void);
-extern unsigned int ata_busy_sleep(struct ata_port *ap,
- unsigned long timeout_pat,
- unsigned long timeout);
+extern int ata_busy_sleep(struct ata_port *ap,
+ unsigned long timeout_pat, unsigned long timeout);
extern void ata_port_queue_task(struct ata_port *ap, void (*fn)(void *),
void *data, unsigned long delay);
extern u32 ata_wait_register(void __iomem *reg, u32 mask, u32 val,
@@ -1061,7 +1060,7 @@ static inline u8 ata_busy_wait(struct at
udelay(10);
status = ata_chk_status(ap);
max--;
- } while ((status & bits) && (max > 0));
+ } while (status != 0xff && (status & bits) && (max > 0));
return status;
}
@@ -1082,7 +1081,7 @@ static inline u8 ata_wait_idle(struct at
{
u8 status = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 1000);
- if (status & (ATA_BUSY | ATA_DRQ)) {
+ if (status != 0xff && (status & (ATA_BUSY | ATA_DRQ))) {
unsigned long l = ap->ioaddr.status_addr;
if (ata_msg_warn(ap))
printk(KERN_WARNING "ATA: abnormal status 0x%X on port 0x%lX\n",
^ permalink raw reply related [flat|nested] 3+ messages in thread* Re: [PATCH] libata: handle 0xff status properly
2006-10-09 9:32 [PATCH] libata: handle 0xff status properly Tejun Heo
@ 2006-10-11 16:16 ` Alan Cox
2006-11-01 4:50 ` Jeff Garzik
1 sibling, 0 replies; 3+ messages in thread
From: Alan Cox @ 2006-10-11 16:16 UTC (permalink / raw)
To: Tejun Heo; +Cc: Jeff Garzik, linux-ide, Joe Jin
Ar Llu, 2006-10-09 am 18:32 +0900, ysgrifennodd Tejun Heo:
> 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>
Acked-by: Alan Cox <alan@redhat.com>
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] libata: handle 0xff status properly
2006-10-09 9:32 [PATCH] libata: handle 0xff status properly Tejun Heo
2006-10-11 16:16 ` Alan Cox
@ 2006-11-01 4:50 ` Jeff Garzik
1 sibling, 0 replies; 3+ messages in thread
From: Jeff Garzik @ 2006-11-01 4:50 UTC (permalink / raw)
To: Tejun Heo; +Cc: Alan Cox, linux-ide, Joe Jin
Tejun Heo wrote:
> 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>
applied to #upstream
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2006-11-01 4:50 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-10-09 9:32 [PATCH] libata: handle 0xff status properly Tejun Heo
2006-10-11 16:16 ` Alan Cox
2006-11-01 4:50 ` Jeff Garzik
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).