[SCSI] qla2xxx: Proper cleanup of pass through commands when firmware returns error.
authorGiridhar Malavali <giridhar.malavali@qlogic.com>
Fri, 18 Nov 2011 17:03:08 +0000 (09:03 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Thu, 15 Dec 2011 06:55:02 +0000 (10:55 +0400)
[jejb: fixed up checkpatch and casting errors]
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: Chad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla2xxx/qla_isr.c
drivers/scsi/qla2xxx/qla_os.c

index b6023e9636eade1d1bc0b7a713100ec3b047f625..6426c7ed9ccc1ac67a0650f1b3483763247c59f9 100644 (file)
@@ -1895,6 +1895,45 @@ qla2x00_status_cont_entry(struct rsp_que *rsp, sts_cont_entry_t *pkt)
        }
 }
 
+static int
+qla2x00_free_sp_ctx(scsi_qla_host_t *vha, srb_t *sp)
+{
+       struct qla_hw_data *ha = vha->hw;
+       struct srb_ctx *ctx;
+
+       if (!sp->ctx)
+               return 1;
+
+       ctx = sp->ctx;
+
+       if (ctx->type == SRB_LOGIN_CMD ||
+           ctx->type == SRB_LOGOUT_CMD ||
+           ctx->type == SRB_TM_CMD) {
+               ctx->u.iocb_cmd->done(sp);
+               return 0;
+       } else if (ctx->type == SRB_ADISC_CMD) {
+               ctx->u.iocb_cmd->free(sp);
+               return 0;
+       } else {
+               struct fc_bsg_job *bsg_job;
+
+               bsg_job = ctx->u.bsg_job;
+               if (ctx->type == SRB_ELS_CMD_HST ||
+                   ctx->type == SRB_CT_CMD)
+                       kfree(sp->fcport);
+
+               bsg_job->reply->reply_data.ctels_reply.status =
+                   FC_CTELS_STATUS_OK;
+               bsg_job->reply->result = DID_ERROR << 16;
+               bsg_job->reply->reply_payload_rcv_len = 0;
+               kfree(sp->ctx);
+               mempool_free(sp, ha->srb_mempool);
+               bsg_job->job_done(bsg_job);
+               return 0;
+       }
+       return 1;
+}
+
 /**
  * qla2x00_error_entry() - Process an error entry.
  * @ha: SCSI driver HA context
@@ -1905,7 +1944,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
 {
        srb_t *sp;
        struct qla_hw_data *ha = vha->hw;
-       uint32_t handle = LSW(pkt->handle);
+       const char func[] = "ERROR-IOCB";
        uint16_t que = MSW(pkt->handle);
        struct req_que *req = ha->req_q_map[que];
 
@@ -1928,28 +1967,20 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
                ql_dbg(ql_dbg_async, vha, 0x502f,
                    "UNKNOWN flag error.\n");
 
-       /* Validate handle. */
-       if (handle < MAX_OUTSTANDING_COMMANDS)
-               sp = req->outstanding_cmds[handle];
-       else
-               sp = NULL;
-
+       sp = qla2x00_get_sp_from_handle(vha, func, req, pkt);
        if (sp) {
-               /* Free outstanding command slot. */
-               req->outstanding_cmds[handle] = NULL;
-
-               /* Bad payload or header */
-               if (pkt->entry_status &
-                   (RF_INV_E_ORDER | RF_INV_E_COUNT |
-                    RF_INV_E_PARAM | RF_INV_E_TYPE)) {
-                       sp->cmd->result = DID_ERROR << 16;
-               } else if (pkt->entry_status & RF_BUSY) {
-                       sp->cmd->result = DID_BUS_BUSY << 16;
-               } else {
-                       sp->cmd->result = DID_ERROR << 16;
+               if (qla2x00_free_sp_ctx(vha, sp)) {
+                       if (pkt->entry_status &
+                           (RF_INV_E_ORDER | RF_INV_E_COUNT |
+                            RF_INV_E_PARAM | RF_INV_E_TYPE)) {
+                               sp->cmd->result = DID_ERROR << 16;
+                       } else if (pkt->entry_status & RF_BUSY) {
+                               sp->cmd->result = DID_BUS_BUSY << 16;
+                       } else {
+                               sp->cmd->result = DID_ERROR << 16;
+                       }
+                       qla2x00_sp_compl(ha, sp);
                }
-               qla2x00_sp_compl(ha, sp);
-
        } else if (pkt->entry_type == COMMAND_A64_TYPE || pkt->entry_type ==
                COMMAND_TYPE || pkt->entry_type == COMMAND_TYPE_7
                || pkt->entry_type == COMMAND_TYPE_6) {
index ae1699f6854dad17ae98b4666756178a4666a455..c9a74521b402f9f1b7b755e80be9ee24cf1cd95b 100644 (file)
@@ -3690,16 +3690,6 @@ qla2x00_sp_free_dma(srb_t *sp)
                sp->flags &= ~SRB_CRC_CTX_DMA_VALID;
        }
 
-       CMD_SP(cmd) = NULL;
-}
-
-static void
-qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp)
-{
-       struct scsi_cmnd *cmd = sp->cmd;
-
-       qla2x00_sp_free_dma(sp);
-
        if (sp->flags & SRB_FCP_CMND_DMA_VALID) {
                struct ct6_dsd *ctx = sp->ctx;
                dma_pool_free(ha->fcp_cmnd_dma_pool, ctx->fcp_cmnd,
@@ -3711,6 +3701,15 @@ qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp)
                sp->ctx = NULL;
        }
 
+       CMD_SP(cmd) = NULL;
+}
+
+static void
+qla2x00_sp_final_compl(struct qla_hw_data *ha, srb_t *sp)
+{
+       struct scsi_cmnd *cmd = sp->cmd;
+
+       qla2x00_sp_free_dma(sp);
        mempool_free(sp, ha->srb_mempool);
        cmd->scsi_done(cmd);
 }