#define TPGS_SUPPORT_LBA_DEPENDENT     0x10
 #define TPGS_SUPPORT_OFFLINE           0x40
 #define TPGS_SUPPORT_TRANSITION                0x80
+#define TPGS_SUPPORT_ALL               0xdf
 
 #define RTPG_FMT_MASK                  0x70
 #define RTPG_FMT_EXT_HDR               0x10
        int                     tpgs;
        int                     state;
        int                     pref;
+       int                     valid_states;
        unsigned                flags; /* used for optimizing STPG */
        unsigned char           transition_tmo;
        unsigned long           expiry;
        pg->group_id = group_id;
        pg->tpgs = tpgs;
        pg->state = SCSI_ACCESS_STATE_OPTIMAL;
+       pg->valid_states = TPGS_SUPPORT_ALL;
        if (optimize_stpg)
                pg->flags |= ALUA_OPTIMIZE_STPG;
        kref_init(&pg->kref);
 {
        struct scsi_sense_hdr sense_hdr;
        struct alua_port_group *tmp_pg;
-       int len, k, off, valid_states = 0, bufflen = ALUA_RTPG_SIZE;
+       int len, k, off, bufflen = ALUA_RTPG_SIZE;
        unsigned char *desc, *buff;
        unsigned err, retval;
        unsigned int tpg_desc_tbl_off;
        retval = submit_rtpg(sdev, buff, bufflen, &sense_hdr, pg->flags);
 
        if (retval) {
+               /*
+                * Some (broken) implementations have a habit of returning
+                * an error during things like firmware update etc.
+                * But if the target only supports active/optimized there's
+                * not much we can do; it's not that we can switch paths
+                * or anything.
+                * So ignore any errors to avoid spurious failures during
+                * path failover.
+                */
+               if ((pg->valid_states & ~TPGS_SUPPORT_OPTIMIZED) == 0) {
+                       sdev_printk(KERN_INFO, sdev,
+                                   "%s: ignoring rtpg result %d\n",
+                                   ALUA_DH_NAME, retval);
+                       kfree(buff);
+                       return SCSI_DH_OK;
+               }
                if (!scsi_sense_valid(&sense_hdr)) {
                        sdev_printk(KERN_INFO, sdev,
                                    "%s: rtpg failed, result %d\n",
                                        rcu_read_unlock();
                                }
                                if (tmp_pg == pg)
-                                       valid_states = desc[1];
+                                       tmp_pg->valid_states = desc[1];
                                spin_unlock_irqrestore(&tmp_pg->lock, flags);
                        }
                        kref_put(&tmp_pg->kref, release_port_group);
                    "%s: port group %02x state %c %s supports %c%c%c%c%c%c%c\n",
                    ALUA_DH_NAME, pg->group_id, print_alua_state(pg->state),
                    pg->pref ? "preferred" : "non-preferred",
-                   valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
-                   valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
-                   valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
-                   valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
-                   valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
-                   valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
-                   valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
+                   pg->valid_states&TPGS_SUPPORT_TRANSITION?'T':'t',
+                   pg->valid_states&TPGS_SUPPORT_OFFLINE?'O':'o',
+                   pg->valid_states&TPGS_SUPPORT_LBA_DEPENDENT?'L':'l',
+                   pg->valid_states&TPGS_SUPPORT_UNAVAILABLE?'U':'u',
+                   pg->valid_states&TPGS_SUPPORT_STANDBY?'S':'s',
+                   pg->valid_states&TPGS_SUPPORT_NONOPTIMIZED?'N':'n',
+                   pg->valid_states&TPGS_SUPPORT_OPTIMIZED?'A':'a');
 
        switch (pg->state) {
        case SCSI_ACCESS_STATE_TRANSITIONING: