aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/ata/libata-core.c19
-rw-r--r--drivers/ata/libata-eh.c23
-rw-r--r--drivers/ata/libata.h2
-rw-r--r--include/linux/libata.h3
4 files changed, 40 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 {
42enum { 42enum {
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
47extern struct workqueue_struct *ata_aux_wq; 49extern struct workqueue_struct *ata_aux_wq;
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 36e233cc3886..9080789913f7 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -176,6 +176,8 @@ enum {
176 ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H 176 ATA_FLAG_SKIP_D2H_BSY = (1 << 12), /* can't wait for the first D2H
177 * Register FIS clearing BSY */ 177 * Register FIS clearing BSY */
178 ATA_FLAG_DEBUGMSG = (1 << 13), 178 ATA_FLAG_DEBUGMSG = (1 << 13),
179 ATA_FLAG_DETECT_POLLING = (1 << 14), /* detect device presence by
180 * polling IDENTIFY */
179 181
180 /* The following flag belongs to ap->pflags but is kept in 182 /* The following flag belongs to ap->pflags but is kept in
181 * ap->flags because it's referenced in many LLDs and will be 183 * ap->flags because it's referenced in many LLDs and will be
@@ -335,6 +337,7 @@ enum ata_completion_errors {
335 AC_ERR_SYSTEM = (1 << 6), /* system error */ 337 AC_ERR_SYSTEM = (1 << 6), /* system error */
336 AC_ERR_INVALID = (1 << 7), /* invalid argument */ 338 AC_ERR_INVALID = (1 << 7), /* invalid argument */
337 AC_ERR_OTHER = (1 << 8), /* unknown */ 339 AC_ERR_OTHER = (1 << 8), /* unknown */
340 AC_ERR_NODEV_HINT = (1 << 9), /* polling device detection hint */
338}; 341};
339 342
340/* forward declarations */ 343/* forward declarations */