[SCSI] bnx2fc: Fixed the handling for the SCSI retry delay
authorEddie Wai <eddie.wai@broadcom.com>
Wed, 11 Dec 2013 23:30:22 +0000 (15:30 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Sat, 15 Mar 2014 17:17:47 +0000 (10:17 -0700)
SCSI retry delay upon SAM_STAT_BUSY/_SET_FULL was not being handled
in bnx2fc.  This patch adds such handling by returning TARGET_BUSY
to the SCSI ML for the corresponding LUN until the retry timer expires.

Signed-off-by: Eddie Wai <eddie.wai@broadcom.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/bnx2fc/bnx2fc.h
drivers/scsi/bnx2fc/bnx2fc_io.c
drivers/scsi/bnx2fc/bnx2fc_tgt.c

index 1ebf3fb683e6c623fc8982d53bdb77479cd37fa8..2e984e3af24a6ddfc9dfe7438e3438de3b13be3e 100644 (file)
@@ -367,6 +367,7 @@ struct bnx2fc_rport {
        atomic_t num_active_ios;
        u32 flush_in_prog;
        unsigned long timestamp;
+       unsigned long retry_delay_timestamp;
        struct list_head free_task_list;
        struct bnx2fc_cmd *pending_queue[BNX2FC_SQ_WQES_MAX+1];
        struct list_head active_cmd_queue;
index ed880891cb7c4b7c038ee73aac032b77108377d4..d2cabc9bede8ca5393e638ebb4f5807ee2f2fad3 100644 (file)
@@ -1871,7 +1871,15 @@ int bnx2fc_queuecommand(struct Scsi_Host *host,
                rc = SCSI_MLQUEUE_TARGET_BUSY;
                goto exit_qcmd;
        }
-
+       if (tgt->retry_delay_timestamp) {
+               if (time_after(jiffies, tgt->retry_delay_timestamp)) {
+                       tgt->retry_delay_timestamp = 0;
+               } else {
+                       /* If retry_delay timer is active, flow off the ML */
+                       rc = SCSI_MLQUEUE_TARGET_BUSY;
+                       goto exit_qcmd;
+               }
+       }
        io_req = bnx2fc_cmd_alloc(tgt);
        if (!io_req) {
                rc = SCSI_MLQUEUE_HOST_BUSY;
@@ -1961,6 +1969,15 @@ void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
                                 " fcp_resid = 0x%x\n",
                                io_req->cdb_status, io_req->fcp_resid);
                        sc_cmd->result = (DID_OK << 16) | io_req->cdb_status;
+
+                       if (io_req->cdb_status == SAM_STAT_TASK_SET_FULL ||
+                           io_req->cdb_status == SAM_STAT_BUSY) {
+                               /* Set the jiffies + retry_delay_timer * 100ms
+                                  for the rport/tgt */
+                               tgt->retry_delay_timestamp = jiffies +
+                                       fcp_rsp->retry_delay_timer * HZ / 10;
+                       }
+
                }
                if (io_req->fcp_resid)
                        scsi_set_resid(sc_cmd, io_req->fcp_resid);
index 4d93177dfb530c4446d959bd97fb71cd5dee86d1..68948b72fafa0ef1516191d626abc3e1d5ae03ea 100644 (file)
@@ -386,6 +386,7 @@ static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
        tgt->rq_prod_idx = 0x8000;
        tgt->rq_cons_idx = 0;
        atomic_set(&tgt->num_active_ios, 0);
+       tgt->retry_delay_timestamp = 0;
 
        if (rdata->flags & FC_RP_FLAGS_RETRY &&
            rdata->ids.roles & FC_RPORT_ROLE_FCP_TARGET &&