tf.protocol = ATA_PROT_PIO;
 
+       /* presence detection using polling IDENTIFY? */
+       if (flags & ATA_READID_DETECT)
+               tf.flags |= ATA_TFLAG_POLLING;
+
        err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
                                     id, sizeof(id[0]) * ATA_ID_WORDS);
        if (err_mask) {
+               if ((flags & ATA_READID_DETECT) &&
+                   (err_mask & AC_ERR_NODEV_HINT)) {
+                       DPRINTK("ata%u.%d: NODEV after polling detection\n",
+                               ap->id, dev->devno);
+                       return -ENOENT;
+               }
+
                rc = -EIO;
                reason = "I/O error";
                goto err_out;
                                        /* device stops HSM for abort/error */
                                        qc->err_mask |= AC_ERR_DEV;
                                else
-                                       /* HSM violation. Let EH handle this */
-                                       qc->err_mask |= AC_ERR_HSM;
+                                       /* HSM violation. Let EH handle this.
+                                        * Phantom devices also trigger this
+                                        * condition.  Mark hint.
+                                        */
+                                       qc->err_mask |= AC_ERR_HSM |
+                                                       AC_ERR_NODEV_HINT;
 
                                ap->hsm_task_state = HSM_ST_ERR;
                                goto fsm_start;
 
                           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) {
                                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;
+                       }
                }
        }
 
 
 enum {
        /* flags for ata_dev_read_id() */
        ATA_READID_POSTRESET    = (1 << 0), /* reading ID after reset */
+       ATA_READID_DETECT       = (1 << 1), /* perform presence detection
+                                            * using polling IDENTIFY */
 };
 
 extern struct workqueue_struct *ata_aux_wq;
 
        ATA_FLAG_SKIP_D2H_BSY   = (1 << 12), /* can't wait for the first D2H
                                              * Register FIS clearing BSY */
        ATA_FLAG_DEBUGMSG       = (1 << 13),
+       ATA_FLAG_DETECT_POLLING = (1 << 14), /* detect device presence by
+                                             * polling IDENTIFY */
 
        /* The following flag belongs to ap->pflags but is kept in
         * ap->flags because it's referenced in many LLDs and will be
        AC_ERR_SYSTEM           = (1 << 6), /* system error */
        AC_ERR_INVALID          = (1 << 7), /* invalid argument */
        AC_ERR_OTHER            = (1 << 8), /* unknown */
+       AC_ERR_NODEV_HINT       = (1 << 9), /* polling device detection hint */
 };
 
 /* forward declarations */