static struct {
        enum fc_port_state      value;
        char                    *name;
+       int                     matchlen;
 } fc_port_state_names[] = {
-       { FC_PORTSTATE_UNKNOWN,         "Unknown" },
-       { FC_PORTSTATE_NOTPRESENT,      "Not Present" },
-       { FC_PORTSTATE_ONLINE,          "Online" },
-       { FC_PORTSTATE_OFFLINE,         "Offline" },
-       { FC_PORTSTATE_BLOCKED,         "Blocked" },
-       { FC_PORTSTATE_BYPASSED,        "Bypassed" },
-       { FC_PORTSTATE_DIAGNOSTICS,     "Diagnostics" },
-       { FC_PORTSTATE_LINKDOWN,        "Linkdown" },
-       { FC_PORTSTATE_ERROR,           "Error" },
-       { FC_PORTSTATE_LOOPBACK,        "Loopback" },
-       { FC_PORTSTATE_DELETED,         "Deleted" },
+       { FC_PORTSTATE_UNKNOWN,         "Unknown", 7},
+       { FC_PORTSTATE_NOTPRESENT,      "Not Present", 11 },
+       { FC_PORTSTATE_ONLINE,          "Online", 6 },
+       { FC_PORTSTATE_OFFLINE,         "Offline", 7 },
+       { FC_PORTSTATE_BLOCKED,         "Blocked", 7 },
+       { FC_PORTSTATE_BYPASSED,        "Bypassed", 8 },
+       { FC_PORTSTATE_DIAGNOSTICS,     "Diagnostics", 11 },
+       { FC_PORTSTATE_LINKDOWN,        "Linkdown", 8 },
+       { FC_PORTSTATE_ERROR,           "Error", 5 },
+       { FC_PORTSTATE_LOOPBACK,        "Loopback", 8 },
+       { FC_PORTSTATE_DELETED,         "Deleted", 7 },
+       { FC_PORTSTATE_MARGINAL,        "Marginal", 8 },
 };
 fc_enum_name_search(port_state, fc_port_state, fc_port_state_names)
+fc_enum_name_match(port_state, fc_port_state, fc_port_state_names)
 #define FC_PORTSTATE_MAX_NAMELEN       20
 
 
                if (rport->scsi_target_id == -1)
                        continue;
 
-               if (rport->port_state != FC_PORTSTATE_ONLINE)
+               if ((rport->port_state != FC_PORTSTATE_ONLINE) &&
+                       (rport->port_state != FC_PORTSTATE_MARGINAL))
                        continue;
 
                if ((channel == rport->channel) &&
 
        spin_lock_irqsave(shost->host_lock, flags);
 
-       if (rport->port_state != FC_PORTSTATE_ONLINE) {
+       if ((rport->port_state != FC_PORTSTATE_ONLINE) &&
+               (rport->port_state != FC_PORTSTATE_MARGINAL)) {
                spin_unlock_irqrestore(shost->host_lock, flags);
                return;
        }
         * target, validate it still is. If not, tear down the
         * scsi_target on it.
         */
-       if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+       if (((rport->port_state == FC_PORTSTATE_ONLINE) ||
+               (rport->port_state == FC_PORTSTATE_MARGINAL)) &&
            (rport->scsi_target_id != -1) &&
            !(rport->roles & FC_PORT_ROLE_FCP_TARGET)) {
                dev_printk(KERN_ERR, &rport->dev,
        struct fc_internal *i = to_fc_internal(shost->transportt);
        unsigned long flags;
 
-       if ((rport->port_state == FC_PORTSTATE_ONLINE) &&
+       if (((rport->port_state == FC_PORTSTATE_ONLINE) ||
+               (rport->port_state == FC_PORTSTATE_MARGINAL)) &&
            (rport->roles & FC_PORT_ROLE_FCP_TARGET) &&
            !(i->f->disable_target_scan)) {
                scsi_scan_target(&rport->dev, rport->channel,
 }
 EXPORT_SYMBOL(fc_block_scsi_eh);
 
+/*
+ * fc_eh_should_retry_cmd - Checks if the cmd should be retried or not
+ * @scmd:        The SCSI command to be checked
+ *
+ * This checks the rport state to decide if a cmd is
+ * retryable.
+ *
+ * Returns: true if the rport state is not in marginal state.
+ */
+bool fc_eh_should_retry_cmd(struct scsi_cmnd *scmd)
+{
+       struct fc_rport *rport = starget_to_rport(scsi_target(scmd->device));
+
+       if ((rport->port_state != FC_PORTSTATE_ONLINE) &&
+               (scmd->request->cmd_flags & REQ_FAILFAST_TRANSPORT)) {
+               set_host_byte(scmd, DID_TRANSPORT_MARGINAL);
+               return false;
+       }
+       return true;
+}
+EXPORT_SYMBOL_GPL(fc_eh_should_retry_cmd);
+
 /**
  * fc_vport_setup - allocates and creates a FC virtual port.
  * @shost:     scsi host the virtual port is connected to.
            !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
                return BLK_STS_RESOURCE;
 
-       if (rport->port_state != FC_PORTSTATE_ONLINE)
+       if ((rport->port_state != FC_PORTSTATE_ONLINE) &&
+               (rport->port_state != FC_PORTSTATE_MARGINAL))
                return BLK_STS_IOERR;
 
        return BLK_STS_OK;