Re: [PATCH v4 05/10] mpi3mr: Fix performance regression caused by extended IRQ poll sleep
[email protected] Wed, 05 Aug 2026 11:32:37 +0000
| Newsgroups | gmane.linux.scsi |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 3 potential issue(= s) to consider: New issues: - [High] The threaded IRQ polling loop will loop indefinitely if `pend_ios`= becomes negative due to skipped corrupt descriptors. Pre-existing issues: - [High] The admin reply queue path reposts unvalidated DMA addresses to th= e hardware free queue when virtual address lookup fails, causing host memor= y corruption. - [High] Missing release memory barrier when unlocking the `in_use` queue l= ock, allowing race conditions on weakly ordered architectures. -- --- Patch [5]: [PATCH v4 05/10] mpi3mr: Fix performance regression caused b= y extended IRQ poll sleep --- commit 19ca49ca3a484c6837fd5a670f8512d409c2678d Author: Ranjan Kumar <[email protected]> mpi3mr: Fix performance regression caused by extended IRQ poll sleep =20 This patch restores the IRQ poll sleep base to 2 us and introduces bounds checking for request queue IDs to prevent infinite polling. It also adds memory barriers in the admin and operational reply queue processing loops and fixes a panic condition on malformed DMA reply addresses. Link: https://sashiko.dev/#/patchset/20260626114109.43685-1-ranjan.kumar@br= oadcom.com?part=3D5 Link: https://sashiko.dev/#/patchset/20260708183305.244485-1-ranjan.kumar@b= roadcom.com?part=3D5 Link: https://sashiko.dev/#/patchset/20260724102505.115136-1-ranjan.kumar@b= roadcom.com?part=3D5 > diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr= _fw.c > --- a/drivers/scsi/mpi3mr/mpi3mr_fw.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c [ ... ] > @@ -565,15 +578,33 @@ int mpi3mr_process_op_reply_q(struct mpi3mr_ioc *mr= ioc, > reply_desc =3D mpi3mr_get_reply_desc(op_reply_q, reply_ci); > if ((le16_to_cpu(reply_desc->reply_flags) & > MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) !=3D exp_phase) { > + /* Recheck under in_use before releasing, to avoid a reclaim race */ > + dma_rmb(); > + if ((le16_to_cpu(reply_desc->reply_flags) & > + MPI3_REPLY_DESCRIPT_FLAGS_PHASE_MASK) =3D=3D exp_phase) > + goto process_desc; > atomic_dec(&op_reply_q->in_use); [Severity: High] This is a pre-existing issue, but is a release memory barrier missing when unlocking the in_use queue lock? Both here and at the end of mpi3mr_process_op_reply_q(), the lock state is released via atomic_dec(): op_reply_q->ci =3D reply_ci; op_reply_q->ephase =3D exp_phase; atomic_sub(threshold_comps, &op_reply_q->pend_ios); atomic_dec(&op_reply_q->in_use); Since non-value-returning RMW atomic operations like atomic_dec() do not imply memory barriers, could weakly ordered architectures reorder the writes to op_reply_q->ci and op_reply_q->ephase after the in_use decrement? Could this allow another CPU to acquire in_use but read stale values for ci and ephase, causing it to double-process reply descriptors? > return 0; > } [ ... ] > @@ -744,11 +787,12 @@ static irqreturn_t mpi3mr_isr_poll(int irq, void *p= rivdata) > num_op_reply +=3D > mpi3mr_process_op_reply_q(mrioc, > intr_info->op_reply_q); > + if (!atomic_read(&intr_info->op_reply_q->pend_ios)) > + break; [Severity: High] Can pend_ios become negative and cause this loop to run indefinitely? If mpi3mr_process_op_reply_q() encounters a corrupted descriptor: if (unlikely(req_q_idx >=3D mrioc->num_op_req_q)) { ioc_err(mrioc, "Invalid request queue id %d, skipping reply\n", req_q_idx + 1); goto next_reply; } It skips the reply but still increments threshold_comps, which is later subtracted from pend_ios. If the descriptor did not correspond to a tracked host submission, couldn't this decrement pend_ios below zero? Since this exact equality check (!atomic_read) evaluates to false for negative values, will the polling loop fail to break and wait indefinitely? > - usleep_range(MPI3MR_IRQ_POLL_SLEEP, MPI3MR_IRQ_POLL_SLEEP + 1); > + usleep_range(MPI3MR_IRQ_POLL_SLEEP, 10 * MPI3MR_IRQ_POLL_SLEEP); > =20 > - } while (atomic_read(&intr_info->op_reply_q->pend_ios) && > - (num_op_reply < mrioc->max_host_ios)); > + } while (num_op_reply < mrioc->max_host_ios); > =20 > diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr= _os.c > --- a/drivers/scsi/mpi3mr/mpi3mr_os.c > +++ b/drivers/scsi/mpi3mr/mpi3mr_os.c > @@ -3430,8 +3430,12 @@ void mpi3mr_process_op_reply_desc(struct mpi3mr_io= c *mrioc, > scsi_reply =3D mpi3mr_get_reply_virt_addr(mrioc, > *reply_dma); > if (!scsi_reply) { > - panic("%s: scsi_reply is NULL, this shouldn't happen\n", > - mrioc->name); > + ioc_err(mrioc, "scsi_reply is NULL, invalid reply_frame_address\n"); > + /* > + * Do not let the caller repost an address that > + * failed virt-addr lookup back to the hardware. > + */ > + *reply_dma =3D 0; [Severity: High] This isn't a bug introduced by this patch, but does the admin reply queue path suffer from the same unvalidated DMA address issue fixed here for the operational queue? In mpi3mr_process_admin_reply_desc(): def_reply =3D mpi3mr_get_reply_virt_addr(mrioc, *reply_dma); if (!def_reply) goto out; If def_reply is NULL, the function jumps to the out label but fails to clear *reply_dma. Then in mpi3mr_process_admin_reply_q(): mpi3mr_process_admin_reply_desc(mrioc, reply_desc, &reply_dma); if (reply_dma) mpi3mr_repost_reply_buf(mrioc, reply_dma); Will this cause the caller to unknowingly repost the unvalidated, non-zero reply_dma back to the hardware free queue, leading to host memory corruption? > goto out; > } --=20 Sashiko AI review =C2=B7 https://sashiko.dev/#/patchset/20260805110634.3466= [email protected]?part=3D5