summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-10-25 15:51:57 +0900
committerGreg Kroah-Hartman <gregkh@suse.de>2007-11-16 09:30:25 -0800
commit28254520f46eeadda8834de0ccf31613caee998f (patch)
tree96cc5c4d508744b9d0fe4c4c7146e86d0ea2b637
parent653ffa9b066dfb423baf6c14b2a2061a8c7b96c8 (diff)
downloadlwn-28254520f46eeadda8834de0ccf31613caee998f.tar.gz
lwn-28254520f46eeadda8834de0ccf31613caee998f.zip
libata: backport ATA_FLAG_NO_SRST and ATA_FLAG_ASSUME_ATA
Differs from mainline, but the functionality is already there. Backport ATA_FLAG_NO_SRST and ATA_FLAG_ASSUME_ATA. These are originally link flags (ATA_LFLAG_*) but link abstraction doesn't exist on 2.6.23, so make it port flags. This is for the following workaround for ASUS P5W DH Deluxe. These new flags don't introduce any behavior change unless set and nobody sets them yet. Signed-off-by: Tejun Heo <htejun@gmail.com> Cc: Jeff Garzik <jeff@garzik.org> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r--drivers/ata/libata-eh.c32
-rw-r--r--include/linux/libata.h2
2 files changed, 26 insertions, 8 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index ac6ceed4bb60..6ebdbd8b4c0b 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1759,9 +1759,11 @@ static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
return 0;
}
-static int ata_eh_followup_srst_needed(int rc, int classify,
- const unsigned int *classes)
+static int ata_eh_followup_srst_needed(struct ata_port *ap, int rc,
+ int classify, const unsigned int *classes)
{
+ if (ap->flags & ATA_FLAG_NO_SRST)
+ return 0;
if (rc == -EAGAIN)
return 1;
if (rc != 0)
@@ -1792,7 +1794,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
*/
action = ehc->i.action;
ehc->i.action &= ~ATA_EH_RESET_MASK;
- if (softreset && (!hardreset || (!sata_set_spd_needed(ap) &&
+ if (softreset && (!hardreset || (!(ap->flags & ATA_FLAG_NO_SRST) &&
+ !sata_set_spd_needed(ap) &&
!(action & ATA_EH_HARDRESET))))
ehc->i.action |= ATA_EH_SOFTRESET;
else
@@ -1855,7 +1858,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
rc = ata_do_reset(ap, reset, classes, deadline);
if (reset == hardreset &&
- ata_eh_followup_srst_needed(rc, classify, classes)) {
+ ata_eh_followup_srst_needed(ap, rc, classify, classes)) {
/* okay, let's do follow-up softreset */
reset = softreset;
@@ -1870,8 +1873,8 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
rc = ata_do_reset(ap, reset, classes, deadline);
- if (rc == 0 && classify &&
- classes[0] == ATA_DEV_UNKNOWN) {
+ if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN &&
+ !(ap->flags & ATA_FLAG_ASSUME_ATA)) {
ata_port_printk(ap, KERN_ERR,
"classification failed\n");
rc = -EINVAL;
@@ -1879,6 +1882,10 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
}
}
+ /* if we skipped follow-up srst, clear rc */
+ if (rc == -EAGAIN)
+ rc = 0;
+
if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
unsigned long now = jiffies;
@@ -1906,8 +1913,17 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
/* After the reset, the device state is PIO 0 and the
* controller state is undefined. Record the mode.
*/
- for (i = 0; i < ATA_MAX_DEVICES; i++)
- ap->device[i].pio_mode = XFER_PIO_0;
+ for (i = 0; i < ata_port_max_devices(ap); i++) {
+ struct ata_device *dev = &ap->device[i];
+
+ dev->pio_mode = XFER_PIO_0;
+
+ if (ata_port_offline(ap))
+ continue;
+
+ if (ap->flags & ATA_FLAG_ASSUME_ATA)
+ classes[dev->devno] = ATA_DEV_ATA;
+ }
/* record current link speed */
if (sata_scr_read(ap, SCR_STATUS, &sstatus) == 0)
diff --git a/include/linux/libata.h b/include/linux/libata.h
index a67bb9075e9b..9ccca8f0a47a 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -177,6 +177,8 @@ enum {
ATA_FLAG_IGN_SIMPLEX = (1 << 15), /* ignore SIMPLEX */
ATA_FLAG_NO_IORDY = (1 << 16), /* controller lacks iordy */
ATA_FLAG_ACPI_SATA = (1 << 17), /* need native SATA ACPI layout */
+ ATA_FLAG_NO_SRST = (1 << 18),
+ ATA_FLAG_ASSUME_ATA = (1 << 19),
/* The following flag belongs to ap->pflags but is kept in
* ap->flags because it's referenced in many LLDs and will be