diff options
Diffstat (limited to 'drivers/ata')
-rw-r--r-- | drivers/ata/libata-core.c | 19 | ||||
-rw-r--r-- | drivers/ata/libata-eh.c | 23 | ||||
-rw-r--r-- | drivers/ata/libata.h | 2 |
3 files changed, 37 insertions, 7 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; |
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, | |||
1667 | ata_class_enabled(ehc->classes[dev->devno])) { | 1667 | ata_class_enabled(ehc->classes[dev->devno])) { |
1668 | dev->class = ehc->classes[dev->devno]; | 1668 | dev->class = ehc->classes[dev->devno]; |
1669 | 1669 | ||
1670 | if (ap->flags & ATA_FLAG_DETECT_POLLING) | ||
1671 | readid_flags |= ATA_READID_DETECT; | ||
1672 | |||
1670 | rc = ata_dev_read_id(dev, &dev->class, readid_flags, | 1673 | rc = ata_dev_read_id(dev, &dev->class, readid_flags, |
1671 | dev->id); | 1674 | dev->id); |
1672 | if (rc == 0) { | 1675 | if (rc == 0) { |
1673 | ehc->i.flags |= ATA_EHI_PRINTINFO; | 1676 | ehc->i.flags |= ATA_EHI_PRINTINFO; |
1674 | rc = ata_dev_configure(dev); | 1677 | rc = ata_dev_configure(dev); |
1675 | ehc->i.flags &= ~ATA_EHI_PRINTINFO; | 1678 | ehc->i.flags &= ~ATA_EHI_PRINTINFO; |
1679 | } else if (rc == -ENOENT) { | ||
1680 | /* IDENTIFY was issued to non-existent | ||
1681 | * device. No need to reset. Just | ||
1682 | * thaw and kill the device. | ||
1683 | */ | ||
1684 | ata_eh_thaw_port(ap); | ||
1685 | dev->class = ATA_DEV_UNKNOWN; | ||
1686 | rc = 0; | ||
1676 | } | 1687 | } |
1677 | 1688 | ||
1678 | if (rc) { | 1689 | if (rc) { |
@@ -1680,12 +1691,14 @@ static int ata_eh_revalidate_and_attach(struct ata_port *ap, | |||
1680 | break; | 1691 | break; |
1681 | } | 1692 | } |
1682 | 1693 | ||
1683 | spin_lock_irqsave(ap->lock, flags); | 1694 | if (ata_dev_enabled(dev)) { |
1684 | ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; | 1695 | spin_lock_irqsave(ap->lock, flags); |
1685 | spin_unlock_irqrestore(ap->lock, flags); | 1696 | ap->pflags |= ATA_PFLAG_SCSI_HOTPLUG; |
1697 | spin_unlock_irqrestore(ap->lock, flags); | ||
1686 | 1698 | ||
1687 | /* new device discovered, configure transfer mode */ | 1699 | /* new device discovered, configure xfermode */ |
1688 | ehc->i.flags |= ATA_EHI_SETMODE; | 1700 | ehc->i.flags |= ATA_EHI_SETMODE; |
1701 | } | ||
1689 | } | 1702 | } |
1690 | } | 1703 | } |
1691 | 1704 | ||
diff --git a/drivers/ata/libata.h b/drivers/ata/libata.h index bb98390aa01a..be2ac39f013b 100644 --- a/drivers/ata/libata.h +++ b/drivers/ata/libata.h | |||
@@ -42,6 +42,8 @@ struct ata_scsi_args { | |||
42 | enum { | 42 | enum { |
43 | /* flags for ata_dev_read_id() */ | 43 | /* flags for ata_dev_read_id() */ |
44 | ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ | 44 | ATA_READID_POSTRESET = (1 << 0), /* reading ID after reset */ |
45 | ATA_READID_DETECT = (1 << 1), /* perform presence detection | ||
46 | * using polling IDENTIFY */ | ||
45 | }; | 47 | }; |
46 | 48 | ||
47 | extern struct workqueue_struct *ata_aux_wq; | 49 | extern struct workqueue_struct *ata_aux_wq; |