aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c22
1 files changed, 21 insertions, 1 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 6ac4f32ddcc..335ac8fb525 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -1660,7 +1660,7 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
struct ata_taskfile tf;
unsigned int err_mask = 0;
const char *reason;
- int tried_spinup = 0;
+ int may_fallback = 1, tried_spinup = 0;
int rc;
if (ata_msg_ctl(ap))
@@ -1704,11 +1704,31 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class,
return -ENOENT;
}
+ /* Device or controller might have reported the wrong
+ * device class. Give a shot at the other IDENTIFY if
+ * the current one is aborted by the device.
+ */
+ if (may_fallback &&
+ (err_mask == AC_ERR_DEV) && (tf.feature & ATA_ABORTED)) {
+ may_fallback = 0;
+
+ if (class == ATA_DEV_ATA)
+ class = ATA_DEV_ATAPI;
+ else
+ class = ATA_DEV_ATA;
+ goto retry;
+ }
+
rc = -EIO;
reason = "I/O error";
goto err_out;
}
+ /* Falling back doesn't make sense if ID data was read
+ * successfully at least once.
+ */
+ may_fallback = 0;
+
swap_buf_le16(id, ATA_ID_WORDS);
/* sanity check */