diff options
author | Tejun Heo <htejun@gmail.com> | 2006-11-10 04:08:10 -0500 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-12-01 22:45:55 -0500 |
commit | 55a8e2c83ce50548dfef74bb19dfe2b809cb3099 (patch) | |
tree | 1d5ed12c49a254364f9009e9cdbf4609b92f3afb /drivers/ata/libata-core.c | |
parent | bff0464769f2a1bd348265de704471747378e247 (diff) |
[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-core.c')
-rw-r--r-- | drivers/ata/libata-core.c | 19 |
1 files changed, 17 insertions, 2 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 090abe443820..21f8d61e5879 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c | |||
@@ -1272,9 +1272,20 @@ int ata_dev_read_id(struct ata_device *dev, unsigned int *p_class, | |||
1272 | 1272 | ||
1273 | tf.protocol = ATA_PROT_PIO; | 1273 | tf.protocol = ATA_PROT_PIO; |
1274 | 1274 | ||
1275 | /* presence detection using polling IDENTIFY? */ | ||
1276 | if (flags & ATA_READID_DETECT) | ||
1277 | tf.flags |= ATA_TFLAG_POLLING; | ||
1278 | |||
1275 | err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, | 1279 | err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE, |
1276 | id, sizeof(id[0]) * ATA_ID_WORDS); | 1280 | id, sizeof(id[0]) * ATA_ID_WORDS); |
1277 | if (err_mask) { | 1281 | if (err_mask) { |
1282 | if ((flags & ATA_READID_DETECT) && | ||
1283 | (err_mask & AC_ERR_NODEV_HINT)) { | ||
1284 | DPRINTK("ata%u.%d: NODEV after polling detection\n", | ||
1285 | ap->id, dev->devno); | ||
1286 | return -ENOENT; | ||
1287 | } | ||
1288 | |||
1278 | rc = -EIO; | 1289 | rc = -EIO; |
1279 | reason = "I/O error"; | 1290 | reason = "I/O error"; |
1280 | goto err_out; | 1291 | goto err_out; |
@@ -4285,8 +4296,12 @@ fsm_start: | |||
4285 | /* device stops HSM for abort/error */ | 4296 | /* device stops HSM for abort/error */ |
4286 | qc->err_mask |= AC_ERR_DEV; | 4297 | qc->err_mask |= AC_ERR_DEV; |
4287 | else | 4298 | else |
4288 | /* HSM violation. Let EH handle this */ | 4299 | /* HSM violation. Let EH handle this. |
4289 | qc->err_mask |= AC_ERR_HSM; | 4300 | * Phantom devices also trigger this |
4301 | * condition. Mark hint. | ||
4302 | */ | ||
4303 | qc->err_mask |= AC_ERR_HSM | | ||
4304 | AC_ERR_NODEV_HINT; | ||
4290 | 4305 | ||
4291 | ap->hsm_task_state = HSM_ST_ERR; | 4306 | ap->hsm_task_state = HSM_ST_ERR; |
4292 | goto fsm_start; | 4307 | goto fsm_start; |