diff mbox series

[05/11] qla2xxx: Fix crash due to stale srb access around IO timeouts

Message ID 20220614072953.16462-6-njavali@marvell.com
State Superseded
Headers show
Series qla2xxx bug fixes | expand

Commit Message

Nilesh Javali June 14, 2022, 7:29 a.m. UTC
From: Arun Easi <aeasi@marvell.com>

Ensure srb is returned during IO timeout error escalation. If that is
not possible fail the escalation path.

Following crash stack was seen:

BUG: unable to handle kernel paging request at 0000002f56aa90f8
IP: qla_chk_edif_rx_sa_delete_pending+0x14/0x30 [qla2xxx]
Call Trace:
 ? qla2x00_status_entry+0x19f/0x1c50 [qla2xxx]
 ? qla2x00_start_sp+0x116/0x1170 [qla2xxx]
 ? dma_pool_alloc+0x1d6/0x210
 ? mempool_alloc+0x54/0x130
 ? qla24xx_process_response_queue+0x548/0x12b0 [qla2xxx]
 ? qla_do_work+0x2d/0x40 [qla2xxx]
 ? process_one_work+0x14c/0x390

Fixes: d74595278f4a ("scsi: qla2xxx: Add multiple queue pair functionality.)
Cc: stable@vger.kernel.org
Signed-off-by: Arun Easi <aeasi@marvell.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
---
 drivers/scsi/qla2xxx/qla_os.c | 41 +++++++++++++++++++++++++----------
 1 file changed, 30 insertions(+), 11 deletions(-)

Comments

Nilesh Javali June 16, 2022, 5:29 a.m. UTC | #1
Hi Martin,

I have a v2 of this patch with additional change.
Please ignore this series and I will send the v2.

Thanks,
Nilesh

> -----Original Message-----
> From: Nilesh Javali <njavali@marvell.com>
> Sent: Tuesday, June 14, 2022 1:00 PM
> To: martin.petersen@oracle.com
> Cc: linux-scsi@vger.kernel.org; GR-QLogic-Storage-Upstream <GR-QLogic-
> Storage-Upstream@marvell.com>
> Subject: [PATCH 05/11] qla2xxx: Fix crash due to stale srb access around IO
> timeouts
> 
> From: Arun Easi <aeasi@marvell.com>
> 
> Ensure srb is returned during IO timeout error escalation. If that is
> not possible fail the escalation path.
> 
> Following crash stack was seen:
> 
> BUG: unable to handle kernel paging request at 0000002f56aa90f8
> IP: qla_chk_edif_rx_sa_delete_pending+0x14/0x30 [qla2xxx]
> Call Trace:
>  ? qla2x00_status_entry+0x19f/0x1c50 [qla2xxx]
>  ? qla2x00_start_sp+0x116/0x1170 [qla2xxx]
>  ? dma_pool_alloc+0x1d6/0x210
>  ? mempool_alloc+0x54/0x130
>  ? qla24xx_process_response_queue+0x548/0x12b0 [qla2xxx]
>  ? qla_do_work+0x2d/0x40 [qla2xxx]
>  ? process_one_work+0x14c/0x390
> 
> Fixes: d74595278f4a ("scsi: qla2xxx: Add multiple queue pair functionality.)
> Cc: stable@vger.kernel.org
> Signed-off-by: Arun Easi <aeasi@marvell.com>
> Signed-off-by: Nilesh Javali <njavali@marvell.com>
> ---
>  drivers/scsi/qla2xxx/qla_os.c | 41 +++++++++++++++++++++++++----------
>  1 file changed, 30 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
> index 210fb5c52421..2fd4f4268ba8 100644
> --- a/drivers/scsi/qla2xxx/qla_os.c
> +++ b/drivers/scsi/qla2xxx/qla_os.c
> @@ -1342,21 +1342,20 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
>  /*
>   * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED.
>   */
> -int
> -qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned
> int t,
> -	uint64_t l, enum nexus_wait_type type)
> +static int
> +__qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair,
> unsigned int t,
> +				       uint64_t l, enum nexus_wait_type type)
>  {
>  	int cnt, match, status;
>  	unsigned long flags;
> -	struct qla_hw_data *ha = vha->hw;
> -	struct req_que *req;
> +	scsi_qla_host_t *vha = qpair->vha;
> +	struct req_que *req = qpair->req;
>  	srb_t *sp;
>  	struct scsi_cmnd *cmd;
> 
>  	status = QLA_SUCCESS;
> 
> -	spin_lock_irqsave(&ha->hardware_lock, flags);
> -	req = vha->req;
> +	spin_lock_irqsave(qpair->qp_lock_ptr, flags);
>  	for (cnt = 1; status == QLA_SUCCESS &&
>  		cnt < req->num_outstanding_cmds; cnt++) {
>  		sp = req->outstanding_cmds[cnt];
> @@ -1383,12 +1382,32 @@
> qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned
> int t,
>  		if (!match)
>  			continue;
> 
> -		spin_unlock_irqrestore(&ha->hardware_lock, flags);
> +		spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
>  		status = qla2x00_eh_wait_on_command(cmd);
> -		spin_lock_irqsave(&ha->hardware_lock, flags);
> +		spin_lock_irqsave(qpair->qp_lock_ptr, flags);
>  	}
> -	spin_unlock_irqrestore(&ha->hardware_lock, flags);
> +	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
> +
> +	return status;
> +}
> +
> +int
> +qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned
> int t,
> +				     uint64_t l, enum nexus_wait_type type)
> +{
> +	struct qla_qpair *qpair;
> +	struct qla_hw_data *ha = vha->hw;
> +	int i, status = QLA_SUCCESS;
> 
> +	status = __qla2x00_eh_wait_for_pending_commands(ha-
> >base_qpair, t, l,
> +							type);
> +	for (i = 0; status == QLA_SUCCESS && i < ha->max_qpairs; i++) {
> +		qpair = ha->queue_pair_map[i];
> +		if (!qpair)
> +			continue;
> +		status = __qla2x00_eh_wait_for_pending_commands(qpair,
> t, l,
> +								type);
> +	}
>  	return status;
>  }
> 
> @@ -1425,7 +1444,7 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
>  		return err;
> 
>  	if (fcport->deleted)
> -		return SUCCESS;
> +		return FAILED;
> 
>  	ql_log(ql_log_info, vha, 0x8009,
>  	    "DEVICE RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", vha-
> >host_no,
> --
> 2.19.0.rc0
diff mbox series

Patch

diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 210fb5c52421..2fd4f4268ba8 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -1342,21 +1342,20 @@  qla2xxx_eh_abort(struct scsi_cmnd *cmd)
 /*
  * Returns: QLA_SUCCESS or QLA_FUNCTION_FAILED.
  */
-int
-qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
-	uint64_t l, enum nexus_wait_type type)
+static int
+__qla2x00_eh_wait_for_pending_commands(struct qla_qpair *qpair, unsigned int t,
+				       uint64_t l, enum nexus_wait_type type)
 {
 	int cnt, match, status;
 	unsigned long flags;
-	struct qla_hw_data *ha = vha->hw;
-	struct req_que *req;
+	scsi_qla_host_t *vha = qpair->vha;
+	struct req_que *req = qpair->req;
 	srb_t *sp;
 	struct scsi_cmnd *cmd;
 
 	status = QLA_SUCCESS;
 
-	spin_lock_irqsave(&ha->hardware_lock, flags);
-	req = vha->req;
+	spin_lock_irqsave(qpair->qp_lock_ptr, flags);
 	for (cnt = 1; status == QLA_SUCCESS &&
 		cnt < req->num_outstanding_cmds; cnt++) {
 		sp = req->outstanding_cmds[cnt];
@@ -1383,12 +1382,32 @@  qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
 		if (!match)
 			continue;
 
-		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+		spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
 		status = qla2x00_eh_wait_on_command(cmd);
-		spin_lock_irqsave(&ha->hardware_lock, flags);
+		spin_lock_irqsave(qpair->qp_lock_ptr, flags);
 	}
-	spin_unlock_irqrestore(&ha->hardware_lock, flags);
+	spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+	return status;
+}
+
+int
+qla2x00_eh_wait_for_pending_commands(scsi_qla_host_t *vha, unsigned int t,
+				     uint64_t l, enum nexus_wait_type type)
+{
+	struct qla_qpair *qpair;
+	struct qla_hw_data *ha = vha->hw;
+	int i, status = QLA_SUCCESS;
 
+	status = __qla2x00_eh_wait_for_pending_commands(ha->base_qpair, t, l,
+							type);
+	for (i = 0; status == QLA_SUCCESS && i < ha->max_qpairs; i++) {
+		qpair = ha->queue_pair_map[i];
+		if (!qpair)
+			continue;
+		status = __qla2x00_eh_wait_for_pending_commands(qpair, t, l,
+								type);
+	}
 	return status;
 }
 
@@ -1425,7 +1444,7 @@  qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
 		return err;
 
 	if (fcport->deleted)
-		return SUCCESS;
+		return FAILED;
 
 	ql_log(ql_log_info, vha, 0x8009,
 	    "DEVICE RESET ISSUED nexus=%ld:%d:%llu cmd=%p.\n", vha->host_no,