aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c6
-rw-r--r--include/linux/ata.h2
2 files changed, 6 insertions, 2 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 8a79b976f08..02425e401a6 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2759,7 +2759,11 @@ static int ata_dev_set_mode(struct ata_device *dev)
/* Old CFA may refuse this command, which is just fine */
if (dev->xfer_shift == ATA_SHIFT_PIO && ata_id_is_cfa(dev->id))
err_mask &= ~AC_ERR_DEV;
-
+ /* Some very old devices and some bad newer ones fail any kind of
+ SET_XFERMODE request but support PIO0-2 timings and no IORDY */
+ if (dev->xfer_shift == ATA_SHIFT_PIO && !ata_id_has_iordy(dev->id) &&
+ dev->pio_mode <= XFER_PIO_2)
+ err_mask &= ~AC_ERR_DEV;
if (err_mask) {
ata_dev_printk(dev, KERN_ERR, "failed to set xfermode "
"(err_mask=0x%x)\n", err_mask);
diff --git a/include/linux/ata.h b/include/linux/ata.h
index c043c1ccf1c..40c7af05fdb 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -358,7 +358,7 @@ struct ata_taskfile {
#define ata_id_removeable(id) ((id)[0] & (1 << 7))
#define ata_id_has_dword_io(id) ((id)[50] & (1 << 0))
#define ata_id_iordy_disable(id) ((id)[49] & (1 << 10))
-#define ata_id_has_iordy(id) ((id)[49] & (1 << 9))
+#define ata_id_has_iordy(id) ((id)[49] & (1 << 11))
#define ata_id_u32(id,n) \
(((u32) (id)[(n) + 1] << 16) | ((u32) (id)[(n)]))
#define ata_id_u64(id,n) \