Message ID | 20230801114057.27039-1-njavali@marvell.com |
---|---|
Headers | show |
Series | qla2xxx driver misc features | expand |
On 8/1/23 04:40, Nilesh Javali wrote: > From: Quinn Tran <qutran@marvell.com> > > The storage was not draining io's and the work load > is not spread out across different CPU's evenly. This led to > FW resource counters getting over run on the busy CPU. This > overrun prevented error recovery from happening in a timely > manner. > > By switching the counter to atomic, it allows the count to > be little more accurate to prevent the overrun. > > Cc: stable@vger.kernel.org > Fixes: da7c21b72aa8 ("scsi: qla2xxx: Fix command flush during TMF") > Signed-off-by: Quinn Tran <qutran@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_def.h | 11 ++++++ > drivers/scsi/qla2xxx/qla_dfs.c | 10 ++++++ > drivers/scsi/qla2xxx/qla_init.c | 8 +++++ > drivers/scsi/qla2xxx/qla_inline.h | 57 ++++++++++++++++++++++++++++++- > drivers/scsi/qla2xxx/qla_os.c | 5 +-- > 5 files changed, 88 insertions(+), 3 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h > index 5882e61141e6..b5ec15bbce99 100644 > --- a/drivers/scsi/qla2xxx/qla_def.h > +++ b/drivers/scsi/qla2xxx/qla_def.h > @@ -3770,6 +3770,16 @@ struct qla_fw_resources { > u16 pad; > }; > > +struct qla_fw_res { > + u16 iocb_total; > + u16 iocb_limit; > + atomic_t iocb_used; > + > + u16 exch_total; > + u16 exch_limit; > + atomic_t exch_used; > +}; > + > #define QLA_IOCB_PCT_LIMIT 95 > > struct qla_buf_pool { > @@ -4829,6 +4839,7 @@ struct qla_hw_data { > u8 edif_post_stop_cnt_down; > struct qla_vp_map *vp_map; > struct qla_nvme_fc_rjt lsrjt; > + struct qla_fw_res fwres ____cacheline_aligned; > }; > > #define RX_ELS_SIZE (roundup(sizeof(struct enode) + ELS_MAX_PAYLOAD, SMP_CACHE_BYTES)) > diff --git a/drivers/scsi/qla2xxx/qla_dfs.c b/drivers/scsi/qla2xxx/qla_dfs.c > index 1925cc6897b6..f060e593685d 100644 > --- a/drivers/scsi/qla2xxx/qla_dfs.c > +++ b/drivers/scsi/qla2xxx/qla_dfs.c > @@ -276,6 +276,16 @@ qla_dfs_fw_resource_cnt_show(struct seq_file *s, void *unused) > > seq_printf(s, "estimate exchange used[%d] high water limit [%d] n", > exch_used, ha->base_qpair->fwres.exch_limit); > + > + if (ql2xenforce_iocb_limit == 2) { > + iocbs_used = atomic_read(&ha->fwres.iocb_used); > + exch_used = atomic_read(&ha->fwres.exch_used); > + seq_printf(s, " estimate iocb2 used [%d] high water limit [%d]\n", > + iocbs_used, ha->fwres.iocb_limit); > + > + seq_printf(s, " estimate exchange2 used[%d] high water limit [%d] \n", > + exch_used, ha->fwres.exch_limit); > + } > } > > return 0; > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c > index ddc9b54f5703..7faf2109228e 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -4214,6 +4214,14 @@ void qla_init_iocb_limit(scsi_qla_host_t *vha) > ha->queue_pair_map[i]->fwres.exch_used = 0; > } > } > + > + ha->fwres.iocb_total = ha->orig_fw_iocb_count; > + ha->fwres.iocb_limit = (ha->orig_fw_iocb_count * QLA_IOCB_PCT_LIMIT) / 100; > + ha->fwres.exch_total = ha->orig_fw_xcb_count; > + ha->fwres.exch_limit = (ha->orig_fw_xcb_count * QLA_IOCB_PCT_LIMIT) / 100; > + > + atomic_set(&ha->fwres.iocb_used, 0); > + atomic_set(&ha->fwres.exch_used, 0); > } > > void qla_adjust_iocb_limit(scsi_qla_host_t *vha) > diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h > index 0167e85ba058..0556969f6dc1 100644 > --- a/drivers/scsi/qla2xxx/qla_inline.h > +++ b/drivers/scsi/qla2xxx/qla_inline.h > @@ -386,6 +386,7 @@ enum { > RESOURCE_IOCB = BIT_0, > RESOURCE_EXCH = BIT_1, /* exchange */ > RESOURCE_FORCE = BIT_2, > + RESOURCE_HA = BIT_3, > }; > > static inline int > @@ -393,7 +394,7 @@ qla_get_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores) > { > u16 iocbs_used, i; > u16 exch_used; > - struct qla_hw_data *ha = qp->vha->hw; > + struct qla_hw_data *ha = qp->hw; > > if (!ql2xenforce_iocb_limit) { > iores->res_type = RESOURCE_NONE; > @@ -428,15 +429,69 @@ qla_get_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores) > return -ENOSPC; > } > } > + > + if (ql2xenforce_iocb_limit == 2) { > + if ((iores->iocb_cnt + atomic_read(&ha->fwres.iocb_used)) >= > + ha->fwres.iocb_limit) { > + iores->res_type = RESOURCE_NONE; > + return -ENOSPC; > + } > + > + if (iores->res_type & RESOURCE_EXCH) { > + if ((iores->exch_cnt + atomic_read(&ha->fwres.exch_used)) >= > + ha->fwres.exch_limit) { > + iores->res_type = RESOURCE_NONE; > + return -ENOSPC; > + } > + } > + } > + > force: > qp->fwres.iocbs_used += iores->iocb_cnt; > qp->fwres.exch_used += iores->exch_cnt; > + if (ql2xenforce_iocb_limit == 2) { > + atomic_add(iores->iocb_cnt, &ha->fwres.iocb_used); > + atomic_add(iores->exch_cnt, &ha->fwres.exch_used); > + iores->res_type |= RESOURCE_HA; > + } > return 0; > } > > +/* > + * decrement to zero. This routine will not decrement below zero > + * @v: pointer of type atomic_t > + * @amount: amount to decrement from v > + */ > +static void qla_atomic_dtz(atomic_t *v, int amount) > +{ > + int c, old, dec; > + > + c = atomic_read(v); > + for (;;) { > + dec = c - amount; > + if (unlikely(dec < 0)) > + dec = 0; > + > + old = atomic_cmpxchg((v), c, dec); > + if (likely(old == c)) > + break; > + c = old; > + } > +} > + > static inline void > qla_put_fw_resources(struct qla_qpair *qp, struct iocb_resource *iores) > { > + struct qla_hw_data *ha = qp->hw; > + > + if (iores->res_type & RESOURCE_HA) { > + if (iores->res_type & RESOURCE_IOCB) > + qla_atomic_dtz(&ha->fwres.iocb_used, iores->iocb_cnt); > + > + if (iores->res_type & RESOURCE_EXCH) > + qla_atomic_dtz(&ha->fwres.exch_used, iores->exch_cnt); > + } > + > if (iores->res_type & RESOURCE_IOCB) { > if (qp->fwres.iocbs_used >= iores->iocb_cnt) { > qp->fwres.iocbs_used -= iores->iocb_cnt; > diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c > index a18bcc86a21a..7da13607e239 100644 > --- a/drivers/scsi/qla2xxx/qla_os.c > +++ b/drivers/scsi/qla2xxx/qla_os.c > @@ -44,10 +44,11 @@ module_param(ql2xfulldump_on_mpifail, int, S_IRUGO | S_IWUSR); > MODULE_PARM_DESC(ql2xfulldump_on_mpifail, > "Set this to take full dump on MPI hang."); > > -int ql2xenforce_iocb_limit = 1; > +int ql2xenforce_iocb_limit = 2; > module_param(ql2xenforce_iocb_limit, int, S_IRUGO | S_IWUSR); > MODULE_PARM_DESC(ql2xenforce_iocb_limit, > - "Enforce IOCB throttling, to avoid FW congestion. (default: 1)"); > + "Enforce IOCB throttling, to avoid FW congestion. (default: 2) " > + "1: track usage per queue, 2: track usage per adapter"); > > /* > * CT6 CTX allocation cache Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
On 8/1/23 04:40, Nilesh Javali wrote: > From: Quinn Tran <qutran@marvell.com> > > TMF was returned with an error code. The error code was not > preserved to be returned to upper layer. Instead, the error code > from the Marker was returned. > > Preserve error code from TMF and return it to upper layer. > > Cc: stable@vger.kernel.org > Fixes: da7c21b72aa8 ("scsi: qla2xxx: Fix command flush during TMF") > Signed-off-by: Quinn Tran <qutran@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_init.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c > index 7faf2109228e..3ab90c159034 100644 > --- a/drivers/scsi/qla2xxx/qla_init.c > +++ b/drivers/scsi/qla2xxx/qla_init.c > @@ -2223,6 +2223,8 @@ __qla2x00_async_tm_cmd(struct tmf_arg *arg) > rval = QLA_FUNCTION_FAILED; > } > } > + if (tm_iocb->u.tmf.data) > + rval = tm_iocb->u.tmf.data; > > done_free_sp: > /* ref: INIT */ Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
On 8/1/23 04:40, Nilesh Javali wrote: > From: Bikash Hazarika <bhazarika@marvell.com> > > Following Call Trace was observed, > > localhost kernel: nvme nvme0: NVME-FC{0}: controller connect complete > localhost kernel: BUG: using smp_processor_id() in preemptible [00000000] code: kworker/u129:4/75092 > localhost kernel: nvme nvme0: NVME-FC{0}: new ctrl: NQN "nqn.1992-08.com.netapp:sn.b42d198afb4d11ecad6d00a098d6abfa:subsystem.PR_Channel2022_RH84_subsystem_291" > localhost kernel: caller is qla_nvme_post_cmd+0x216/0x1380 [qla2xxx] > localhost kernel: CPU: 6 PID: 75092 Comm: kworker/u129:4 Kdump: loaded Tainted: G B W OE --------- --- 5.14.0-70.22.1.el9_0.x86_64+debug #1 > localhost kernel: Hardware name: HPE ProLiant XL420 Gen10/ProLiant XL420 Gen10, BIOS U39 01/13/2022 > localhost kernel: Workqueue: nvme-wq nvme_async_event_work [nvme_core] > localhost kernel: Call Trace: > localhost kernel: dump_stack_lvl+0x57/0x7d > localhost kernel: check_preemption_disabled+0xc8/0xd0 > localhost kernel: qla_nvme_post_cmd+0x216/0x1380 [qla2xxx] > > Use raw_smp_processor_id api instead of smp_processor_id > > Cc: stable@vger.kernel.org > Signed-off-by: Bikash Hazarika <bhazarika@marvell.com> > Signed-off-by: Nilesh Javali <njavali@marvell.com> > --- > drivers/scsi/qla2xxx/qla_inline.h | 2 +- > drivers/scsi/qla2xxx/qla_isr.c | 6 +++--- > drivers/scsi/qla2xxx/qla_target.c | 2 +- > drivers/scsi/qla2xxx/tcm_qla2xxx.c | 4 ++-- > 4 files changed, 7 insertions(+), 7 deletions(-) > > diff --git a/drivers/scsi/qla2xxx/qla_inline.h b/drivers/scsi/qla2xxx/qla_inline.h > index 0556969f6dc1..a4a56ab0ba74 100644 > --- a/drivers/scsi/qla2xxx/qla_inline.h > +++ b/drivers/scsi/qla2xxx/qla_inline.h > @@ -577,7 +577,7 @@ fcport_is_bigger(fc_port_t *fcport) > static inline struct qla_qpair * > qla_mapq_nvme_select_qpair(struct qla_hw_data *ha, struct qla_qpair *qpair) > { > - int cpuid = smp_processor_id(); > + int cpuid = raw_smp_processor_id(); > > if (qpair->cpuid != cpuid && > ha->qp_cpu_map[cpuid]) { > diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c > index e98788191897..01fc300d640f 100644 > --- a/drivers/scsi/qla2xxx/qla_isr.c > +++ b/drivers/scsi/qla2xxx/qla_isr.c > @@ -3965,7 +3965,7 @@ void qla24xx_process_response_queue(struct scsi_qla_host *vha, > if (!ha->flags.fw_started) > return; > > - if (rsp->qpair->cpuid != smp_processor_id() || !rsp->qpair->rcv_intr) { > + if (rsp->qpair->cpuid != raw_smp_processor_id() || !rsp->qpair->rcv_intr) { > rsp->qpair->rcv_intr = 1; > > if (!rsp->qpair->cpu_mapped) > @@ -4468,7 +4468,7 @@ qla2xxx_msix_rsp_q(int irq, void *dev_id) > } > ha = qpair->hw; > > - queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work); > + queue_work_on(raw_smp_processor_id(), ha->wq, &qpair->q_work); > > return IRQ_HANDLED; > } > @@ -4494,7 +4494,7 @@ qla2xxx_msix_rsp_q_hs(int irq, void *dev_id) > wrt_reg_dword(®->hccr, HCCRX_CLR_RISC_INT); > spin_unlock_irqrestore(&ha->hardware_lock, flags); > > - queue_work_on(smp_processor_id(), ha->wq, &qpair->q_work); > + queue_work_on(raw_smp_processor_id(), ha->wq, &qpair->q_work); > > return IRQ_HANDLED; > } > diff --git a/drivers/scsi/qla2xxx/qla_target.c b/drivers/scsi/qla2xxx/qla_target.c > index 2b815a9928ea..9278713c3021 100644 > --- a/drivers/scsi/qla2xxx/qla_target.c > +++ b/drivers/scsi/qla2xxx/qla_target.c > @@ -4425,7 +4425,7 @@ static int qlt_handle_cmd_for_atio(struct scsi_qla_host *vha, > queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, &cmd->work); > } else if (ha->msix_count) { > if (cmd->atio.u.isp24.fcp_cmnd.rddata) > - queue_work_on(smp_processor_id(), qla_tgt_wq, > + queue_work_on(raw_smp_processor_id(), qla_tgt_wq, > &cmd->work); > else > queue_work_on(cmd->se_cmd.cpuid, qla_tgt_wq, > diff --git a/drivers/scsi/qla2xxx/tcm_qla2xxx.c b/drivers/scsi/qla2xxx/tcm_qla2xxx.c > index 3b5ba4b47b3b..9566f0384353 100644 > --- a/drivers/scsi/qla2xxx/tcm_qla2xxx.c > +++ b/drivers/scsi/qla2xxx/tcm_qla2xxx.c > @@ -310,7 +310,7 @@ static void tcm_qla2xxx_free_cmd(struct qla_tgt_cmd *cmd) > cmd->trc_flags |= TRC_CMD_DONE; > > INIT_WORK(&cmd->work, tcm_qla2xxx_complete_free); > - queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); > + queue_work_on(raw_smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); > } > > /* > @@ -547,7 +547,7 @@ static void tcm_qla2xxx_handle_data(struct qla_tgt_cmd *cmd) > cmd->trc_flags |= TRC_DATA_IN; > cmd->cmd_in_wq = 1; > INIT_WORK(&cmd->work, tcm_qla2xxx_handle_data_work); > - queue_work_on(smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); > + queue_work_on(raw_smp_processor_id(), tcm_qla2xxx_free_wq, &cmd->work); > } > > static int tcm_qla2xxx_chk_dif_tags(uint32_t tag) Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>