Message ID | 20220614072953.16462-6-njavali@marvell.com |
---|---|
State | Superseded |
Headers | show |
Series | qla2xxx bug fixes | expand |
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 --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,