summaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2006-11-10 10:08:10 +0100
committerJeff Garzik <jeff@garzik.org>2006-12-02 04:45:55 +0100
commit55a8e2c83ce50548dfef74bb19dfe2b809cb3099 (patch)
tree1d5ed12c49a254364f9009e9cdbf4609b92f3afb /drivers/ata/libata-eh.c
parent[PATCH] libata: convert @post_reset to @flags in ata_dev_read_id() (diff)
downloadlinux-55a8e2c83ce50548dfef74bb19dfe2b809cb3099.tar.xz
linux-55a8e2c83ce50548dfef74bb19dfe2b809cb3099.zip
[PATCH] libata: implement presence detection via polling IDENTIFY
On some controllers (ICHs in piix mode), there is *NO* reliable way to determine device presence other than issuing IDENTIFY and see how the transaction proceeds by watching the TF status register. libata acted this way before irq-pio and phantom devices caused very little problem but now that IDENTIFY is performed using IRQ drive PIO, such phantom devices now result in multiple 30sec timeouts during boot. This patch implements ATA_FLAG_DETECT_POLLING. If a LLD sets this flag, libata core issues the initial IDENTIFY in polling mode and if the initial data transfer fails w/ HSM violation, the port is considered to be empty thus replicating the old libata and IDE behavior. Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c23
1 files changed, 18 insertions, 5 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 755fc68b5374..e69f3df2ea39 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1667,12 +1667,23 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
ata_class_enabled(ehc->classes[dev->devno])) {
dev->class = ehc->classes[dev->devno];
+ if (ap->flags & ATA_FLAG_DETECT_POLLING)
+ readid_flags |= ATA_READID_DETECT;
+
rc = ata_dev_read_id(dev, &dev->class, readid_flags,
dev->id);
if (rc == 0) {
ehc->i.flags |= ATA_EHI_PRINTINFO;
rc = ata_dev_configure(dev);
ehc->i.flags &= ~ATA_EHI_PRINTINFO;
+ } else if (rc == -ENOENT) {
+ /* IDENTIFY was issued to non-existent
+ * device. No need to reset. Just
+ * thaw and kill the device.
+ */
+ ata_eh_thaw_port(ap);
+ dev->class = ATA_DEV_UNKNOWN;
+ rc = 0;
}
if (rc) {
@@ -1680,12 +1691,14 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap,
break;
}
- spin_lock_irqsave(ap->lock, flags);
- ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
- spin_unlock_irqrestore(ap->lock, flags);
+ if (ata_dev_enabled(dev)) {
+ spin_lock_irqsave(ap->lock, flags);
+ ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG;
+ spin_unlock_irqrestore(ap->lock, flags);
- /* new device discovered, configure transfer mode */
- ehc->i.flags |= ATA_EHI_SETMODE;
+ /* new device discovered, configure xfermode */
+ ehc->i.flags |= ATA_EHI_SETMODE;
+ }
}
}