From: Adrian Hunter <adrian.hunter@intel.com>
To: alexandre.belloni@bootlin.com
Cc: Frank.Li@nxp.com, billy_tsai@aspeedtech.com,
linux-i3c@lists.infradead.org, linux-kernel@vger.kernel.org
Subject: [PATCH 09/17] i3c: mipi-i3c-hci: Process multiple IBIs per interrupt
Date: Mon, 14 Sep 2026 14:29:55 +0300 [thread overview]
Message-ID: <20260914113003.183150-10-adrian.hunter@intel.com> (raw)
In-Reply-To: <20260914113003.183150-1-adrian.hunter@intel.com>
INTR_IBI_READY indicates that one or more IBI Status Descriptors are
present in the IBI ring. After clearing interrupt status, the interrupt
handler processes only a single IBI even though additional IBIs may
already be queued.
The controller does not reassert INTR_IBI_READY solely because entries
remain in the ring after interrupt status has been cleared. Consequently,
the remaining IBIs are not processed until some later interrupt occurs,
and can accumulate if IBIs arrive more often than the interrupt handler
runs.
Process all IBIs that are pending when the handler runs: capture the IBI
enqueue pointer up front and continue until the dequeue pointer reaches
that position.
Fixes: 9ad9a52cce28 ("i3c/master: introduce the mipi-i3c-hci driver")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/i3c/master/mipi-i3c-hci/dma.c | 39 +++++++++++++++++----------
1 file changed, 25 insertions(+), 14 deletions(-)
diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index 5b195978f376..a798b0648922 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -868,25 +868,24 @@ static void hci_dma_recycle_ibi_slot(struct i3c_hci *hci,
i3c_generic_ibi_recycle_slot(dev_ibi->pool, slot);
}
-static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
+static bool hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh,
+ u32 *op1_val, unsigned int enq_ptr)
{
struct hci_rings_data *rings = hci->io_data;
struct i3c_dev_desc *dev;
struct i3c_hci_dev_data *dev_data;
struct hci_dma_dev_ibi_data *dev_ibi;
struct i3c_ibi_slot *slot;
- u32 op1_val, op2_val, ibi_status_error;
- unsigned int ptr, enq_ptr, deq_ptr;
+ u32 ibi_status_error;
+ unsigned int ptr, deq_ptr;
unsigned int ibi_size, ibi_chunks, ibi_data_offset, first_part;
int ibi_addr, last_ptr;
void *ring_ibi_data;
dma_addr_t ring_ibi_data_dma;
- op1_val = rh_reg_read(RING_OPERATION1);
- deq_ptr = FIELD_GET(RING_OP1_IBI_DEQ_PTR, op1_val);
-
- op2_val = rh_reg_read(RING_OPERATION2);
- enq_ptr = FIELD_GET(RING_OP2_IBI_ENQ_PTR, op2_val);
+ deq_ptr = FIELD_GET(RING_OP1_IBI_DEQ_PTR, *op1_val);
+ if (deq_ptr == enq_ptr)
+ return false;
ibi_status_error = 0;
ibi_addr = -1;
@@ -936,7 +935,7 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
dev_dbg(&hci->master.dev,
"no LAST_STATUS available (e=%d d=%d)",
enq_ptr, deq_ptr);
- return;
+ return false;
}
deq_ptr = last_ptr + 1;
deq_ptr %= rh->ibi_status_entries;
@@ -1015,10 +1014,9 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
i3c_master_queue_ibi(dev, slot);
done:
- op1_val = rh_reg_read(RING_OPERATION1);
- op1_val &= ~RING_OP1_IBI_DEQ_PTR;
- op1_val |= FIELD_PREP(RING_OP1_IBI_DEQ_PTR, deq_ptr);
- rh_reg_write(RING_OPERATION1, op1_val);
+ *op1_val &= ~RING_OP1_IBI_DEQ_PTR;
+ *op1_val |= FIELD_PREP(RING_OP1_IBI_DEQ_PTR, deq_ptr);
+ rh_reg_write(RING_OPERATION1, *op1_val);
/* update the chunk pointer */
rh->ibi_chunk_ptr += ibi_chunks;
@@ -1026,6 +1024,19 @@ static void hci_dma_process_ibi(struct i3c_hci *hci, struct hci_rh_data *rh)
/* and tell the hardware about freed chunks */
rh_reg_write(CHUNK_CONTROL, rh_reg_read(CHUNK_CONTROL) + ibi_chunks);
+
+ return true;
+}
+
+static void hci_dma_drain_ibi_ring(struct i3c_hci *hci, struct hci_rh_data *rh)
+{
+ u32 op1_val = rh_reg_read(RING_OPERATION1);
+ u32 op2_val = rh_reg_read(RING_OPERATION2);
+ unsigned int enq_ptr = FIELD_GET(RING_OP2_IBI_ENQ_PTR, op2_val);
+
+ /* Loop is bounded by enq_ptr. Further IBIs will re-assert INTR_IBI_READY */
+ while (hci_dma_process_ibi(hci, rh, &op1_val, enq_ptr))
+ ;
}
static bool hci_dma_irq_handler(struct i3c_hci *hci)
@@ -1047,7 +1058,7 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci)
rh_reg_write(INTR_STATUS, status);
if (status & INTR_IBI_READY)
- hci_dma_process_ibi(hci, rh);
+ hci_dma_drain_ibi_ring(hci, rh);
if (status & (INTR_TRANSFER_COMPLETION | INTR_TRANSFER_ERR))
hci_dma_xfer_done(hci, rh);
if (status & INTR_RING_OP)
--
2.53.0
next prev parent reply other threads:[~2026-09-14 11:30 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-14 11:29 [PATCH 00/17] i3c: Fixes, cleanups and HDR-DDR support Adrian Hunter
2026-09-14 11:29 ` [PATCH 01/17] i3c: master: Fix out-of-bounds read in DMA bounce buffer setup Adrian Hunter
2026-09-14 16:09 ` Frank Li
2026-09-14 11:29 ` [PATCH 02/17] i3c: mipi-i3c-hci: Bounce short reads irrespective of the IOMMU Adrian Hunter
2026-09-14 16:16 ` Frank Li
2026-09-14 11:29 ` [PATCH 03/17] i3c: mipi-i3c-hci-pci: Set drvdata before creating LTR sysfs attribute Adrian Hunter
2026-09-14 16:17 ` Frank Li
2026-09-14 11:29 ` [PATCH 04/17] i3c: master: Match ACPI targets to the correct bus controller instance Adrian Hunter
2026-09-14 16:19 ` Frank Li
2026-09-14 11:29 ` [PATCH 05/17] i3c: master: Remove stale GETSTATUS length check Adrian Hunter
2026-09-14 16:23 ` Frank Li
2026-09-14 11:29 ` [PATCH 06/17] i3c: mipi-i3c-hci: Fix i3c_hci_enable_ibi() error path Adrian Hunter
2026-09-14 16:27 ` Frank Li
2026-09-14 11:29 ` [PATCH 07/17] i3c: mipi-i3c-hci: Send DISEC before disabling IBIs in hardware Adrian Hunter
2026-09-14 16:29 ` Frank Li
2026-09-14 11:29 ` [PATCH 08/17] i3c: mipi-i3c-hci: Fix runtime PM violation in i3c_hci_free_ibi() Adrian Hunter
2026-09-14 11:29 ` Adrian Hunter [this message]
2026-09-14 16:45 ` [PATCH 09/17] i3c: mipi-i3c-hci: Process multiple IBIs per interrupt Frank Li
2026-09-14 11:29 ` [PATCH 10/17] i3c: mipi-i3c-hci: Move DMA suspend/resume callbacks Adrian Hunter
2026-09-14 16:46 ` Frank Li
2026-09-14 11:29 ` [PATCH 11/17] i3c: mipi-i3c-hci: Stop rings gracefully when suspending Adrian Hunter
2026-09-14 16:51 ` Frank Li
2026-09-14 11:29 ` [PATCH 12/17] i3c: mipi-i3c-hci: Fix Response Descriptor DATA_LENGTH mask Adrian Hunter
2026-09-14 16:55 ` Frank Li
2026-09-14 11:29 ` [PATCH 13/17] i3c: mipi-i3c-hci: Remove invalid transfer size limit Adrian Hunter
2026-09-14 16:58 ` Frank Li
2026-09-14 11:30 ` [PATCH 14/17] i3c: mipi-i3c-hci: Remove invalid HDR-BT and Fm/Fm+ definitions Adrian Hunter
2026-09-14 17:00 ` Frank Li
2026-09-14 11:30 ` [PATCH 15/17] i3c: mipi-i3c-hci: Support configurable device NACK retries Adrian Hunter
2026-09-14 11:30 ` [PATCH 16/17] i3c: Restrict HDR modes to those supported by the bus and target Adrian Hunter
2026-09-14 11:30 ` [PATCH 17/17] i3c: mipi-i3c-hci: Add HDR-DDR support Adrian Hunter
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260914113003.183150-10-adrian.hunter@intel.com \
--to=adrian.hunter@intel.com \
--cc=Frank.Li@nxp.com \
--cc=alexandre.belloni@bootlin.com \
--cc=billy_tsai@aspeedtech.com \
--cc=linux-i3c@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®