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 11/17] i3c: mipi-i3c-hci: Stop rings gracefully when suspending
Date: Mon, 14 Sep 2026 14:29:57 +0300 [thread overview]
Message-ID: <20260914113003.183150-12-adrian.hunter@intel.com> (raw)
In-Reply-To: <20260914113003.183150-1-adrian.hunter@intel.com>
hci_dma_suspend() tore the rings down with a single write of zero to
RH_RING_CONTROL, clearing the RS and ENABLE fields together and without
waiting for the ring to stop. I3C HCI v1.1 section 6.1.2 separates those
steps: clear RS for all running Ring Bundles, and only then clear ENABLE
for all enabled Ring Bundles.
The ring registers were also written outside hci->lock, while the
interrupt handler, which takes that lock, could still be running on
another CPU. i3c_hci_sync_irq_inactive() was called only afterwards.
Finally, an IBI can still be sitting in the IBI Status Ring when suspend
runs. Clearing HC_CONTROL.BUS_ENABLE is deferred: per the description of
that field, if a disable request occurs while receiving an IBI, the
actual disabling does not occur until reception of the IBI is complete.
Instead, clear RS under hci->lock, wait for RING_STATUS_RUNNING to clear,
and make the interrupt handler inactive. Only then disable the ring
interrupt signals, drain anything left in the IBI ring, and clear ENABLE.
Fixes: 816958720443 ("i3c: mipi-i3c-hci: Add DMA suspend and resume support")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
drivers/i3c/master/mipi-i3c-hci/dma.c | 46 ++++++++++++++++++++++++---
1 file changed, 42 insertions(+), 4 deletions(-)
diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index ec4b469abd33..9c163ee4d215 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -15,6 +15,7 @@
#include <linux/errno.h>
#include <linux/i3c/master.h>
#include <linux/io.h>
+#include <linux/iopoll.h>
#include "hci.h"
#include "cmd.h"
@@ -1052,19 +1053,56 @@ static bool hci_dma_irq_handler(struct i3c_hci *hci)
return handled;
}
+#define RING_STOP_TIMEOUT_US (100 * USEC_PER_MSEC)
+#define RING_STOP_SLEEP_US 100
+
static void hci_dma_suspend(struct i3c_hci *hci)
{
struct hci_rings_data *rings = hci->io_data;
int n = rings ? rings->total : 0;
+ struct hci_rh_data *rh;
+ u32 regval;
- for (int i = 0; i < n; i++) {
- struct hci_rh_data *rh = &rings->headers[i];
+ /* Gracefully stop the rings */
+ scoped_guard(spinlock_irqsave, &hci->lock) {
+ for (int i = 0; i < n; i++) {
+ rh = &rings->headers[i];
+ regval = rh_reg_read(RING_CONTROL);
+ if (regval & RING_CTRL_RUN_STOP)
+ rh_reg_write(RING_CONTROL, regval & ~RING_CTRL_RUN_STOP);
+ }
+ }
- rh_reg_write(INTR_SIGNAL_ENABLE, 0);
- rh_reg_write(RING_CONTROL, 0);
+ /* Wait for actual stop */
+ for (int i = 0; i < n; i++) {
+ rh = &rings->headers[i];
+ if (readx_poll_timeout(readl, rh->regs + RH_RING_STATUS, regval,
+ !(regval & RING_STATUS_RUNNING),
+ RING_STOP_SLEEP_US, RING_STOP_TIMEOUT_US))
+ dev_err(&hci->master.dev, "%s: Ring did not stop, status %#x\n",
+ __func__, regval);
}
+ /*
+ * With the rings stopped, no more IBIs can be received. Flush and make
+ * the interrupt handler inactive.
+ */
i3c_hci_sync_irq_inactive(hci);
+
+ /* Disable interrupt signals and disable the rings */
+ scoped_guard(spinlock_irqsave, &hci->lock)
+ for (int i = 0; i < n; i++) {
+ rh = &rings->headers[i];
+ rh_reg_write(INTR_SIGNAL_ENABLE, 0);
+ /*
+ * Be absolutely certain there is no unprocessed IBI.
+ * hci_dma_drain_ibi_ring() will do nothing if there is
+ * none.
+ */
+ if (i < IBI_RINGS)
+ hci_dma_drain_ibi_ring(hci, rh);
+ rh_reg_write(RING_CONTROL, 0);
+ }
}
static void hci_dma_resume(struct i3c_hci *hci)
--
2.53.0
--
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c
next prev parent reply other threads:[~2026-09-14 11:30 UTC|newest]
Thread overview: 45+ 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 11:45 ` sashiko-bot
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 11:50 ` sashiko-bot
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 11:46 ` sashiko-bot
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:58 ` sashiko-bot
2026-09-14 11:29 ` [PATCH 09/17] i3c: mipi-i3c-hci: Process multiple IBIs per interrupt Adrian Hunter
2026-09-14 16:45 ` Frank Li
2026-09-15 9:36 ` Adrian Hunter
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 ` Adrian Hunter [this message]
2026-09-14 16:51 ` [PATCH 11/17] i3c: mipi-i3c-hci: Stop rings gracefully when suspending 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 11:48 ` sashiko-bot
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 11:49 ` sashiko-bot
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:56 ` sashiko-bot
2026-09-14 18:21 ` Frank Li
2026-09-15 9:41 ` 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 18:26 ` Frank Li
2026-09-14 11:30 ` [PATCH 17/17] i3c: mipi-i3c-hci: Add HDR-DDR support Adrian Hunter
2026-09-14 11:54 ` sashiko-bot
2026-09-14 12:54 ` Adrian Hunter
2026-09-14 18:32 ` Frank Li
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-12-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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.