diff mbox series

[v3,4/5] scsi: qla2xxx: avoid sending iocbs when firmware is stopped

Message ID 20200327164711.5358-5-mwilck@suse.com (mailing list archive)
State Superseded
Headers show
Series scsi: qla2xxx: fixes for driver unloading | expand

Commit Message

Martin Wilck March 27, 2020, 4:47 p.m. UTC
From: Martin Wilck <mwilck@suse.com>

Since commit 45235022da99 ("scsi: qla2xxx: Fix driver unload by shutting down chip"),
it is possible that FC commands are scheduled after the adapter firmware
has been shut down. IO sent to the firmware in this situation hangs.
Avoid starting iocbs in this situation.

Fixes: 45235022da99 ("scsi: qla2xxx: Fix driver unload by shutting down chip")
Signed-off-by: Martin Wilck <mwilck@suse.com>
---
 drivers/scsi/qla2xxx/qla_inline.h |  3 +++
 drivers/scsi/qla2xxx/qla_iocb.c   | 23 +++++++++++++++++++++++
 drivers/scsi/qla2xxx/qla_nvme.c   |  3 +++
 3 files changed, 29 insertions(+)
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h
index 364b3db..f4352f1 100644
--- a/drivers/scsi/qla2xxx/qla_inline.h
+++ b/drivers/scsi/qla2xxx/qla_inline.h
@@ -322,6 +322,9 @@  qla_83xx_start_iocbs(struct qla_qpair *qpair)
 {
 	struct req_que *req = qpair->req;
 
+	if (!qpair->vha->hw->flags.fw_started)
+		return;
+
 	req->ring_index++;
 	if (req->ring_index == req->length) {
 		req->ring_index = 0;
diff --git a/drivers/scsi/qla2xxx/qla_iocb.c b/drivers/scsi/qla2xxx/qla_iocb.c
index 182bd68c..587ba35 100644
--- a/drivers/scsi/qla2xxx/qla_iocb.c
+++ b/drivers/scsi/qla2xxx/qla_iocb.c
@@ -459,6 +459,9 @@  qla2x00_start_iocbs(struct scsi_qla_host *vha, struct req_que *req)
 	struct qla_hw_data *ha = vha->hw;
 	device_reg_t *reg = ISP_QUE_REG(ha, req->id);
 
+	if (!ha->flags.fw_started)
+		return;
+
 	if (IS_P3P_TYPE(ha)) {
 		qla82xx_start_iocbs(vha);
 	} else {
@@ -1603,6 +1606,9 @@  qla24xx_start_scsi(srb_t *sp)
 	struct scsi_qla_host *vha = sp->vha;
 	struct qla_hw_data *ha = vha->hw;
 
+	if (!ha->flags.fw_started)
+		return QLA_FUNCTION_FAILED;
+
 	/* Setup device pointers. */
 	req = vha->req;
 
@@ -1740,6 +1746,9 @@  qla24xx_dif_start_scsi(srb_t *sp)
 
 #define QDSS_GOT_Q_SPACE	BIT_0
 
+	if (!ha->flags.fw_started)
+		return QLA_FUNCTION_FAILED;
+
 	/* Only process protection or >16 cdb in this routine */
 	if (scsi_get_prot_op(cmd) == SCSI_PROT_NORMAL) {
 		if (cmd->cmd_len <= 16)
@@ -1921,6 +1930,9 @@  qla2xxx_start_scsi_mq(srb_t *sp)
 	struct qla_hw_data *ha = vha->hw;
 	struct qla_qpair *qpair = sp->qpair;
 
+	if (!ha->flags.fw_started)
+		return QLA_FUNCTION_FAILED;
+
 	/* Acquire qpair specific lock */
 	spin_lock_irqsave(&qpair->qp_lock, flags);
 
@@ -2062,6 +2074,11 @@  qla2xxx_dif_start_scsi_mq(srb_t *sp)
 
 #define QDSS_GOT_Q_SPACE	BIT_0
 
+	if (!ha->flags.fw_started) {
+		cmd->result = DID_NO_CONNECT << 16;
+		return QLA_FUNCTION_FAILED;
+	}
+
 	/* Check for host side state */
 	if (!qpair->online) {
 		cmd->result = DID_NO_CONNECT << 16;
@@ -3224,6 +3241,9 @@  qla82xx_start_scsi(srb_t *sp)
 	struct req_que *req = NULL;
 	struct rsp_que *rsp = NULL;
 
+	if (!ha->flags.fw_started)
+		return QLA_FUNCTION_FAILED;
+
 	/* Setup device pointers. */
 	reg = &ha->iobase->isp82;
 	cmd = GET_CMD_SP(sp);
@@ -3676,6 +3696,9 @@  qla2x00_start_sp(srb_t *sp)
 	void *pkt;
 	unsigned long flags;
 
+	if (!ha->flags.fw_started)
+		return QLA_FUNCTION_FAILED;
+
 	spin_lock_irqsave(qp->qp_lock_ptr, flags);
 	pkt = __qla2x00_alloc_iocbs(sp->qpair, sp);
 	if (!pkt) {
diff --git a/drivers/scsi/qla2xxx/qla_nvme.c b/drivers/scsi/qla2xxx/qla_nvme.c
index 84e2a980..4f36e73 100644
--- a/drivers/scsi/qla2xxx/qla_nvme.c
+++ b/drivers/scsi/qla2xxx/qla_nvme.c
@@ -369,6 +369,9 @@  static inline int qla2x00_start_nvme_mq(srb_t *sp)
 	struct nvmefc_fcp_req *fd = nvme->u.nvme.desc;
 	uint32_t        rval = QLA_SUCCESS;
 
+	if (!ha->flags.fw_started)
+		return QLA_FUNCTION_FAILED;
+
 	/* Setup qpair pointers */
 	req = qpair->req;
 	tot_dsds = fd->sg_cnt;