Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit c4631191 authored by Giridhar Malavali's avatar Giridhar Malavali Committed by James Bottomley
Browse files

[SCSI] qla2xxx: Proper cleanup of pass through commands when firmware returns error.



[jejb: fixed up checkpatch and casting errors]
Signed-off-by: default avatarGiridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: default avatarChad Dupuis <chad.dupuis@qlogic.com>
Signed-off-by: default avatarJames Bottomley <JBottomley@Parallels.com>
parent cfb0919c
Loading
Loading
Loading
Loading
+52 −21
Original line number Diff line number Diff line
@@ -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,17 +1967,9 @@ 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 (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)) {
@@ -1949,7 +1980,7 @@ qla2x00_error_entry(scsi_qla_host_t *vha, struct rsp_que *rsp, sts_entry_t *pkt)
				sp->cmd->result = DID_ERROR << 16;
			}
			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) {
+9 −10
Original line number Diff line number Diff line
@@ -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);
}