summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2008-11-13 02:04:46 +0100
committerJeff Garzik <jgarzik@redhat.com>2008-11-15 00:51:57 +0100
commit6a6b97d360702b98c02c7fca4c4e088dcf3a2985 (patch)
tree6b0d6a504c11bbea7096706065c31bd12e7d7e78
parentMerge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jba... (diff)
downloadlinux-6a6b97d360702b98c02c7fca4c4e088dcf3a2985.tar.xz
linux-6a6b97d360702b98c02c7fca4c4e088dcf3a2985.zip
libata: improve phantom device detection
Currently libata uses four methods to detect device presence. 1. PHY status if available. 2. TF register R/W test (only promotes presence, never demotes) 3. device signature after reset 4. IDENTIFY failure detection in SFF state machine Combination of the above works well in most cases but recently there have been a few reports where a phantom device causes unnecessary delay during probe. In both cases, PHY status wasn't available. In one case, it passed #2 and #3 and failed IDENTIFY with ATA_ERR which didn't qualify as #4. The other failed #2 but as it passed #3 and #4, it still caused failure. In both cases, phantom device reported diagnostic failure, so these cases can be safely worked around by considering any !ATA_DRQ IDENTIFY failure as NODEV_HINT if diagnostic failure is set. Signed-off-by: Tejun Heo <tj@kernel.org> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/ata/libata-sff.c13
1 files changed, 11 insertions, 2 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 4b4739486327..9033d164c4ec 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -1227,10 +1227,19 @@ fsm_start:
/* ATA PIO protocol */
if (unlikely((status & ATA_DRQ) == 0)) {
/* handle BSY=0, DRQ=0 as error */
- if (likely(status & (ATA_ERR | ATA_DF)))
+ if (likely(status & (ATA_ERR | ATA_DF))) {
/* device stops HSM for abort/error */
qc->err_mask |= AC_ERR_DEV;
- else {
+
+ /* If diagnostic failed and this is
+ * IDENTIFY, it's likely a phantom
+ * device. Mark hint.
+ */
+ if (qc->dev->horkage &
+ ATA_HORKAGE_DIAGNOSTIC)
+ qc->err_mask |=
+ AC_ERR_NODEV_HINT;
+ } else {
/* HSM violation. Let EH handle this.
* Phantom devices also trigger this
* condition. Mark hint.