libata: Correct IORDY handling
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Tue, 31 Jul 2007 13:01:48 +0000 (14:01 +0100)
committerJeff Garzik <jeff@garzik.org>
Fri, 12 Oct 2007 18:55:32 +0000 (14:55 -0400)
Debugging a report of a problem with an ancient solid state disk showed
up some problems in the IORDY handling

1. We check the wrong bit to see if the device has IORDY
2. Even then some ancient creaking piles of crap don't support
SETXFER at all.

The cases it fixes are obscure and the risk of side effects is slight
but possible. This also moves us slightly closer to supporting original
MFM/RLL disks with libata.

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/ata/libata-core.c
include/linux/ata.h

index 8a79b976f08aa031b40a4c61cea13e6f18e844f3..02425e401a6d22392f93458bd0b455d1d98047bd 100644 (file)
@@ -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);
index c043c1ccf1c5098530bfef18941db54b716131b7..40c7af05fdb99261e3eaa1a5876c5e054a8b2818 100644 (file)
@@ -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)       \