diff options
author | Tejun Heo <htejun@gmail.com> | 2006-05-31 05:27:59 -0400 |
---|---|---|
committer | Tejun Heo <htejun@gmail.com> | 2006-05-31 05:27:59 -0400 |
commit | e8e008e7b5ed8c65675cc9b3e778b8bb909f65ab (patch) | |
tree | 88ab9cff204c3a09630b145835bb0f7576a72791 /drivers | |
parent | 135da34573f6d3bab2976a75063f7232a4311a74 (diff) |
[PATCH] sata_sil24: update sil24_hardreset()
Use phy debouncing instead of unconditional wait after DEV_RST and
make sil24_hardreset() to request followup SRST as that's the only way
to wait for !BSY. Note that the original implementation never worked
- if the cached status was !BSY, ata_busy_sleep() finished
immediately; otherwise, it timed out regardless of the actual device
status.
Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/scsi/sata_sil24.c | 26 |
1 files changed, 14 insertions, 12 deletions
diff --git a/drivers/scsi/sata_sil24.c b/drivers/scsi/sata_sil24.c index a39e8d0332c6..4a830903393d 100644 --- a/drivers/scsi/sata_sil24.c +++ b/drivers/scsi/sata_sil24.c | |||
@@ -591,7 +591,7 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) | |||
591 | { | 591 | { |
592 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; | 592 | void __iomem *port = (void __iomem *)ap->ioaddr.cmd_addr; |
593 | const char *reason; | 593 | const char *reason; |
594 | int tout_msec; | 594 | int tout_msec, rc; |
595 | u32 tmp; | 595 | u32 tmp; |
596 | 596 | ||
597 | /* sil24 does the right thing(tm) without any protection */ | 597 | /* sil24 does the right thing(tm) without any protection */ |
@@ -605,10 +605,14 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) | |||
605 | tmp = ata_wait_register(port + PORT_CTRL_STAT, | 605 | tmp = ata_wait_register(port + PORT_CTRL_STAT, |
606 | PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); | 606 | PORT_CS_DEV_RST, PORT_CS_DEV_RST, 10, tout_msec); |
607 | 607 | ||
608 | /* SStatus oscillates between zero and valid status for short | 608 | /* SStatus oscillates between zero and valid status after |
609 | * duration after DEV_RST, give it time to settle. | 609 | * DEV_RST, debounce it. |
610 | */ | 610 | */ |
611 | msleep(100); | 611 | rc = sata_phy_debounce(ap, sata_deb_timing_before_fsrst); |
612 | if (rc) { | ||
613 | reason = "PHY debouncing failed"; | ||
614 | goto err; | ||
615 | } | ||
612 | 616 | ||
613 | if (tmp & PORT_CS_DEV_RST) { | 617 | if (tmp & PORT_CS_DEV_RST) { |
614 | if (ata_port_offline(ap)) | 618 | if (ata_port_offline(ap)) |
@@ -617,15 +621,13 @@ static int sil24_hardreset(struct ata_port *ap, unsigned int *class) | |||
617 | goto err; | 621 | goto err; |
618 | } | 622 | } |
619 | 623 | ||
620 | if (ata_busy_sleep(ap, ATA_TMOUT_BOOT_QUICK, ATA_TMOUT_BOOT)) { | 624 | /* Sil24 doesn't store signature FIS after hardreset, so we |
621 | reason = "device not ready"; | 625 | * can't wait for BSY to clear. Some devices take a long time |
622 | goto err; | 626 | * to get ready and those devices will choke if we don't wait |
623 | } | 627 | * for BSY clearance here. Tell libata to perform follow-up |
624 | 628 | * softreset. | |
625 | /* sil24 doesn't report device class code after hardreset, | ||
626 | * leave *class alone. | ||
627 | */ | 629 | */ |
628 | return 0; | 630 | return -EAGAIN; |
629 | 631 | ||
630 | err: | 632 | err: |
631 | ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); | 633 | ata_port_printk(ap, KERN_ERR, "hardreset failed (%s)\n", reason); |