return 0;
 }
 
-static int ata_eh_followup_srst_needed(int rc, int classify,
+static int ata_eh_followup_srst_needed(struct ata_link *link,
+                                      int rc, int classify,
                                       const unsigned int *classes)
 {
+       if (link->flags & ATA_LFLAG_NO_SRST)
+               return 0;
        if (rc == -EAGAIN)
                return 1;
        if (rc != 0)
                return 0;
-       if (classify && classes[0] == ATA_DEV_UNKNOWN)
+       if (classify && !(link->flags & ATA_LFLAG_ASSUME_CLASS) &&
+           classes[0] == ATA_DEV_UNKNOWN)
                return 1;
        return 0;
 }
         */
        action = ehc->i.action;
        ehc->i.action &= ~ATA_EH_RESET_MASK;
-       if (softreset && (!hardreset || (!sata_set_spd_needed(link) &&
+       if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) &&
+                                        !sata_set_spd_needed(link) &&
                                         !(action & ATA_EH_HARDRESET))))
                ehc->i.action |= ATA_EH_SOFTRESET;
        else
        rc = ata_do_reset(link, reset, classes, deadline);
 
        if (reset == hardreset &&
-           ata_eh_followup_srst_needed(rc, classify, classes)) {
+           ata_eh_followup_srst_needed(link, rc, classify, classes)) {
                /* okay, let's do follow-up softreset */
                reset = softreset;
 
                ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
                rc = ata_do_reset(link, reset, classes, deadline);
 
-               if (rc == 0 && classify &&
-                   classes[0] == ATA_DEV_UNKNOWN) {
+               if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN &&
+                   !(link->flags & ATA_LFLAG_ASSUME_CLASS)) {
                        ata_link_printk(link, KERN_ERR,
                                        "classification failed\n");
                        rc = -EINVAL;
                }
        }
 
+       /* if we skipped follow-up srst, clear rc */
+       if (rc == -EAGAIN)
+               rc = 0;
+
        if (rc && try < ARRAY_SIZE(ata_eh_reset_timeouts)) {
                unsigned long now = jiffies;
 
        if (rc == 0) {
                u32 sstatus;
 
-               /* After the reset, the device state is PIO 0 and the
-                * controller state is undefined.  Record the mode.
-                */
-               ata_link_for_each_dev(dev, link)
+               ata_link_for_each_dev(dev, link) {
+                       /* After the reset, the device state is PIO 0
+                        * and the controller state is undefined.
+                        * Record the mode.
+                        */
                        dev->pio_mode = XFER_PIO_0;
 
+                       if (ata_link_offline(link))
+                               continue;
+
+                       /* apply class override and convert UNKNOWN to NONE */
+                       if (link->flags & ATA_LFLAG_ASSUME_ATA)
+                               classes[dev->devno] = ATA_DEV_ATA;
+                       else if (link->flags & ATA_LFLAG_ASSUME_SEMB)
+                               classes[dev->devno] = ATA_DEV_SEMB_UNSUP; /* not yet */
+                       else if (classes[dev->devno] == ATA_DEV_UNKNOWN)
+                               classes[dev->devno] = ATA_DEV_NONE;
+               }
+
                /* record current link speed */
                if (sata_scr_read(link, SCR_STATUS, &sstatus) == 0)
                        link->sata_spd = (sstatus >> 4) & 0xf;
 
        ATA_LFLAG_HRST_TO_RESUME = (1 << 0), /* hardreset to resume link */
        ATA_LFLAG_SKIP_D2H_BSY  = (1 << 1), /* can't wait for the first D2H
                                             * Register FIS clearing BSY */
+       ATA_LFLAG_NO_SRST       = (1 << 2), /* avoid softreset */
+       ATA_LFLAG_ASSUME_ATA    = (1 << 3), /* assume ATA class */
+       ATA_LFLAG_ASSUME_SEMB   = (1 << 4), /* assume SEMB class */
+       ATA_LFLAG_ASSUME_CLASS  = ATA_LFLAG_ASSUME_ATA | ATA_LFLAG_ASSUME_SEMB,
 
        /* struct ata_port flags */
        ATA_FLAG_SLAVE_POSS     = (1 << 0), /* host supports slave dev */