From: Greg Kroah-Hartman Date: Tue, 17 Mar 2026 14:54:11 +0000 (+0100) Subject: 6.19-stable patches X-Git-Tag: v6.18.19~29 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=9efa52c6147425a02dc178def367e967482ad677;p=thirdparty%2Fkernel%2Fstable-queue.git 6.19-stable patches added patches: i3c-mipi-i3c-hci-add-missing-tid-field-to-no-op-command-descriptor.patch i3c-mipi-i3c-hci-consolidate-spinlocks.patch i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in-dma-dequeue.patch i3c-mipi-i3c-hci-factor-out-dma-mapping-from-queuing-path.patch i3c-mipi-i3c-hci-fix-race-in-dma-ring-dequeue.patch i3c-mipi-i3c-hci-restart-dma-ring-correctly-after-dequeue-abort.patch i3c-mipi-i3c-hci-use-etimedout-instead-of-etime-for-timeout-errors.patch --- diff --git a/queue-6.19/i3c-mipi-i3c-hci-add-missing-tid-field-to-no-op-command-descriptor.patch b/queue-6.19/i3c-mipi-i3c-hci-add-missing-tid-field-to-no-op-command-descriptor.patch new file mode 100644 index 0000000000..afa85c363d --- /dev/null +++ b/queue-6.19/i3c-mipi-i3c-hci-add-missing-tid-field-to-no-op-command-descriptor.patch @@ -0,0 +1,54 @@ +From ec3cfd835f7c4bbd23bc9ad909d2fdc772a578bb Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 6 Mar 2026 09:24:46 +0200 +Subject: i3c: mipi-i3c-hci: Add missing TID field to no-op command descriptor + +From: Adrian Hunter + +commit ec3cfd835f7c4bbd23bc9ad909d2fdc772a578bb upstream. + +The internal control command descriptor used for no-op commands includes a +Transaction ID (TID) field, but the no-op command constructed in +hci_dma_dequeue_xfer() omitted it. As a result, the hardware receives a +no-op descriptor without the expected TID. + +This bug has gone unnoticed because the TID is currently not validated in +the no-op completion path, but the descriptor format requires it to be +present. + +Add the missing TID field when generating a no-op descriptor so that its +layout matches the defined command structure. + +Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20260306072451.11131-10-adrian.hunter@intel.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master/mipi-i3c-hci/cmd.h | 1 + + drivers/i3c/master/mipi-i3c-hci/dma.c | 2 +- + 2 files changed, 2 insertions(+), 1 deletion(-) + +--- a/drivers/i3c/master/mipi-i3c-hci/cmd.h ++++ b/drivers/i3c/master/mipi-i3c-hci/cmd.h +@@ -17,6 +17,7 @@ + #define CMD_0_TOC W0_BIT_(31) + #define CMD_0_ROC W0_BIT_(30) + #define CMD_0_ATTR W0_MASK(2, 0) ++#define CMD_0_TID W0_MASK(6, 3) + + /* + * Response Descriptor Structure +--- a/drivers/i3c/master/mipi-i3c-hci/dma.c ++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c +@@ -510,7 +510,7 @@ static bool hci_dma_dequeue_xfer(struct + u32 *ring_data = rh->xfer + rh->xfer_struct_sz * idx; + + /* store no-op cmd descriptor */ +- *ring_data++ = FIELD_PREP(CMD_0_ATTR, 0x7); ++ *ring_data++ = FIELD_PREP(CMD_0_ATTR, 0x7) | FIELD_PREP(CMD_0_TID, xfer->cmd_tid); + *ring_data++ = 0; + if (hci->cmd == &mipi_i3c_hci_cmd_v2) { + *ring_data++ = 0; diff --git a/queue-6.19/i3c-mipi-i3c-hci-consolidate-spinlocks.patch b/queue-6.19/i3c-mipi-i3c-hci-consolidate-spinlocks.patch new file mode 100644 index 0000000000..b4ca93f336 --- /dev/null +++ b/queue-6.19/i3c-mipi-i3c-hci-consolidate-spinlocks.patch @@ -0,0 +1,196 @@ +From fa12bb903bc3ed1826e355d267fe134bde95e23c Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 6 Mar 2026 09:24:41 +0200 +Subject: i3c: mipi-i3c-hci: Consolidate spinlocks + +From: Adrian Hunter + +commit fa12bb903bc3ed1826e355d267fe134bde95e23c upstream. + +The MIPI I3C HCI driver currently uses separate spinlocks for different +contexts (PIO vs. DMA rings). This split is unnecessary and complicates +upcoming fixes. The driver does not support concurrent PIO and DMA +operation, and it only supports a single DMA ring, so a single lock is +sufficient for all paths. + +Introduce a unified spinlock in struct i3c_hci, switch both PIO and DMA +code to use it, and remove the per-context locks. + +No functional change is intended in this patch. + +Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20260306072451.11131-5-adrian.hunter@intel.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master/mipi-i3c-hci/core.c | 2 ++ + drivers/i3c/master/mipi-i3c-hci/dma.c | 14 ++++++-------- + drivers/i3c/master/mipi-i3c-hci/hci.h | 1 + + drivers/i3c/master/mipi-i3c-hci/pio.c | 16 +++++++--------- + 4 files changed, 16 insertions(+), 17 deletions(-) + +--- a/drivers/i3c/master/mipi-i3c-hci/core.c ++++ b/drivers/i3c/master/mipi-i3c-hci/core.c +@@ -631,6 +631,8 @@ static int i3c_hci_init(struct i3c_hci * + if (ret) + return ret; + ++ spin_lock_init(&hci->lock); ++ + /* + * Now let's reset the hardware. + * SOFT_RST must be clear before we write to it. +--- a/drivers/i3c/master/mipi-i3c-hci/dma.c ++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c +@@ -133,7 +133,6 @@ struct hci_rh_data { + unsigned int xfer_struct_sz, resp_struct_sz, ibi_status_sz, ibi_chunk_sz; + unsigned int done_ptr, ibi_chunk_ptr; + struct hci_xfer **src_xfers; +- spinlock_t lock; + struct completion op_done; + }; + +@@ -240,7 +239,6 @@ static int hci_dma_init(struct i3c_hci * + goto err_out; + rh = &rings->headers[i]; + rh->regs = hci->base_regs + offset; +- spin_lock_init(&rh->lock); + init_completion(&rh->op_done); + + rh->xfer_entries = XFER_RING_ENTRIES; +@@ -470,12 +468,12 @@ static int hci_dma_queue_xfer(struct i3c + } + + /* take care to update the hardware enqueue pointer atomically */ +- spin_lock_irq(&rh->lock); ++ spin_lock_irq(&hci->lock); + op1_val = rh_reg_read(RING_OPERATION1); + op1_val &= ~RING_OP1_CR_ENQ_PTR; + op1_val |= FIELD_PREP(RING_OP1_CR_ENQ_PTR, enqueue_ptr); + rh_reg_write(RING_OPERATION1, op1_val); +- spin_unlock_irq(&rh->lock); ++ spin_unlock_irq(&hci->lock); + + return 0; + } +@@ -573,12 +571,12 @@ static void hci_dma_xfer_done(struct i3c + } + + /* take care to update the software dequeue pointer atomically */ +- spin_lock(&rh->lock); ++ spin_lock(&hci->lock); + op1_val = rh_reg_read(RING_OPERATION1); + op1_val &= ~RING_OP1_CR_SW_DEQ_PTR; + op1_val |= FIELD_PREP(RING_OP1_CR_SW_DEQ_PTR, done_ptr); + rh_reg_write(RING_OPERATION1, op1_val); +- spin_unlock(&rh->lock); ++ spin_unlock(&hci->lock); + } + + static int hci_dma_request_ibi(struct i3c_hci *hci, struct i3c_dev_desc *dev, +@@ -759,12 +757,12 @@ static void hci_dma_process_ibi(struct i + + done: + /* take care to update the ibi dequeue pointer atomically */ +- spin_lock(&rh->lock); ++ spin_lock(&hci->lock); + 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); +- spin_unlock(&rh->lock); ++ spin_unlock(&hci->lock); + + /* update the chunk pointer */ + rh->ibi_chunk_ptr += ibi_chunks; +--- a/drivers/i3c/master/mipi-i3c-hci/hci.h ++++ b/drivers/i3c/master/mipi-i3c-hci/hci.h +@@ -45,6 +45,7 @@ struct i3c_hci { + const struct hci_io_ops *io; + void *io_data; + const struct hci_cmd_ops *cmd; ++ spinlock_t lock; + atomic_t next_cmd_tid; + u32 caps; + unsigned int quirks; +--- a/drivers/i3c/master/mipi-i3c-hci/pio.c ++++ b/drivers/i3c/master/mipi-i3c-hci/pio.c +@@ -124,7 +124,6 @@ struct hci_pio_ibi_data { + }; + + struct hci_pio_data { +- spinlock_t lock; + struct hci_xfer *curr_xfer, *xfer_queue; + struct hci_xfer *curr_rx, *rx_queue; + struct hci_xfer *curr_tx, *tx_queue; +@@ -146,7 +145,6 @@ static int hci_pio_init(struct i3c_hci * + return -ENOMEM; + + hci->io_data = pio; +- spin_lock_init(&pio->lock); + + size_val = pio_reg_read(QUEUE_SIZE); + dev_info(&hci->master.dev, "CMD/RESP FIFO = %ld entries\n", +@@ -609,7 +607,7 @@ static int hci_pio_queue_xfer(struct i3c + xfer[i].data_left = xfer[i].data_len; + } + +- spin_lock_irq(&pio->lock); ++ spin_lock_irq(&hci->lock); + prev_queue_tail = pio->xfer_queue; + pio->xfer_queue = &xfer[n - 1]; + if (pio->curr_xfer) { +@@ -623,7 +621,7 @@ static int hci_pio_queue_xfer(struct i3c + pio_reg_read(INTR_STATUS), + pio_reg_read(INTR_SIGNAL_ENABLE)); + } +- spin_unlock_irq(&pio->lock); ++ spin_unlock_irq(&hci->lock); + return 0; + } + +@@ -694,14 +692,14 @@ static bool hci_pio_dequeue_xfer(struct + struct hci_pio_data *pio = hci->io_data; + int ret; + +- spin_lock_irq(&pio->lock); ++ spin_lock_irq(&hci->lock); + dev_dbg(&hci->master.dev, "n=%d status=%#x/%#x", n, + pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); + dev_dbg(&hci->master.dev, "main_status = %#x/%#x", + readl(hci->base_regs + 0x20), readl(hci->base_regs + 0x28)); + + ret = hci_pio_dequeue_xfer_common(hci, pio, xfer, n); +- spin_unlock_irq(&pio->lock); ++ spin_unlock_irq(&hci->lock); + return ret; + } + +@@ -994,13 +992,13 @@ static bool hci_pio_irq_handler(struct i + struct hci_pio_data *pio = hci->io_data; + u32 status; + +- spin_lock(&pio->lock); ++ spin_lock(&hci->lock); + status = pio_reg_read(INTR_STATUS); + dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", + status, pio->enabled_irqs); + status &= pio->enabled_irqs | STAT_LATENCY_WARNINGS; + if (!status) { +- spin_unlock(&pio->lock); ++ spin_unlock(&hci->lock); + return false; + } + +@@ -1036,7 +1034,7 @@ static bool hci_pio_irq_handler(struct i + pio_reg_write(INTR_SIGNAL_ENABLE, pio->enabled_irqs); + dev_dbg(&hci->master.dev, "PIO_INTR_STATUS %#x/%#x", + pio_reg_read(INTR_STATUS), pio_reg_read(INTR_SIGNAL_ENABLE)); +- spin_unlock(&pio->lock); ++ spin_unlock(&hci->lock); + return true; + } + diff --git a/queue-6.19/i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in-dma-dequeue.patch b/queue-6.19/i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in-dma-dequeue.patch new file mode 100644 index 0000000000..2c9338956a --- /dev/null +++ b/queue-6.19/i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in-dma-dequeue.patch @@ -0,0 +1,73 @@ +From b795e68bf3073d67bebbb5a44d93f49efc5b8cc7 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 6 Mar 2026 09:24:45 +0200 +Subject: i3c: mipi-i3c-hci: Correct RING_CTRL_ABORT handling in DMA dequeue + +From: Adrian Hunter + +commit b795e68bf3073d67bebbb5a44d93f49efc5b8cc7 upstream. + +The logic used to abort the DMA ring contains several flaws: + + 1. The driver unconditionally issues a ring abort even when the ring has + already stopped. + 2. The completion used to wait for abort completion is never + re-initialized, resulting in incorrect wait behavior. + 3. The abort sequence unintentionally clears RING_CTRL_ENABLE, which + resets hardware ring pointers and disrupts the controller state. + 4. If the ring is already stopped, the abort operation should be + considered successful without attempting further action. + +Fix the abort handling by checking whether the ring is running before +issuing an abort, re-initializing the completion when needed, ensuring that +RING_CTRL_ENABLE remains asserted during abort, and treating an already +stopped ring as a successful condition. + +Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20260306072451.11131-9-adrian.hunter@intel.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master/mipi-i3c-hci/dma.c | 25 ++++++++++++++++--------- + 1 file changed, 16 insertions(+), 9 deletions(-) + +--- a/drivers/i3c/master/mipi-i3c-hci/dma.c ++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c +@@ -485,18 +485,25 @@ static bool hci_dma_dequeue_xfer(struct + struct hci_rh_data *rh = &rings->headers[xfer_list[0].ring_number]; + unsigned int i; + bool did_unqueue = false; ++ u32 ring_status; + + guard(mutex)(&hci->control_mutex); + +- /* stop the ring */ +- rh_reg_write(RING_CONTROL, RING_CTRL_ABORT); +- if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) { +- /* +- * We're deep in it if ever this condition is ever met. +- * Hardware might still be writing to memory, etc. +- */ +- dev_crit(&hci->master.dev, "unable to abort the ring\n"); +- WARN_ON(1); ++ ring_status = rh_reg_read(RING_STATUS); ++ if (ring_status & RING_STATUS_RUNNING) { ++ /* stop the ring */ ++ reinit_completion(&rh->op_done); ++ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_ABORT); ++ wait_for_completion_timeout(&rh->op_done, HZ); ++ ring_status = rh_reg_read(RING_STATUS); ++ if (ring_status & RING_STATUS_RUNNING) { ++ /* ++ * We're deep in it if ever this condition is ever met. ++ * Hardware might still be writing to memory, etc. ++ */ ++ dev_crit(&hci->master.dev, "unable to abort the ring\n"); ++ WARN_ON(1); ++ } + } + + for (i = 0; i < n; i++) { diff --git a/queue-6.19/i3c-mipi-i3c-hci-factor-out-dma-mapping-from-queuing-path.patch b/queue-6.19/i3c-mipi-i3c-hci-factor-out-dma-mapping-from-queuing-path.patch new file mode 100644 index 0000000000..adb64a821f --- /dev/null +++ b/queue-6.19/i3c-mipi-i3c-hci-factor-out-dma-mapping-from-queuing-path.patch @@ -0,0 +1,116 @@ +From f3bcbfe1b8b0b836b772927f75f8cb6e759eb00a Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 6 Mar 2026 09:24:40 +0200 +Subject: i3c: mipi-i3c-hci: Factor out DMA mapping from queuing path + +From: Adrian Hunter + +commit f3bcbfe1b8b0b836b772927f75f8cb6e759eb00a upstream. + +Prepare for fixing a race in the DMA ring enqueue path when handling +parallel transfers. Move all DMA mapping out of hci_dma_queue_xfer() +and into a new helper that performs the mapping up front. + +This refactoring allows the upcoming fix to extend the spinlock coverage +around the enqueue operation without performing DMA mapping under the +spinlock. + +No functional change is intended in this patch. + +Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20260306072451.11131-4-adrian.hunter@intel.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master/mipi-i3c-hci/dma.c | 49 ++++++++++++++++++++++------------ + 1 file changed, 33 insertions(+), 16 deletions(-) + +--- a/drivers/i3c/master/mipi-i3c-hci/dma.c ++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c +@@ -375,6 +375,33 @@ static void hci_dma_unmap_xfer(struct i3 + } + } + ++static struct i3c_dma *hci_dma_map_xfer(struct device *dev, struct hci_xfer *xfer) ++{ ++ enum dma_data_direction dir = xfer->rnw ? DMA_FROM_DEVICE : DMA_TO_DEVICE; ++ bool need_bounce = device_iommu_mapped(dev) && xfer->rnw && (xfer->data_len & 3); ++ ++ return i3c_master_dma_map_single(dev, xfer->data, xfer->data_len, need_bounce, dir); ++} ++ ++static int hci_dma_map_xfer_list(struct i3c_hci *hci, struct device *dev, ++ struct hci_xfer *xfer_list, int n) ++{ ++ for (int i = 0; i < n; i++) { ++ struct hci_xfer *xfer = xfer_list + i; ++ ++ if (!xfer->data) ++ continue; ++ ++ xfer->dma = hci_dma_map_xfer(dev, xfer); ++ if (!xfer->dma) { ++ hci_dma_unmap_xfer(hci, xfer_list, i); ++ return -ENOMEM; ++ } ++ } ++ ++ return 0; ++} ++ + static int hci_dma_queue_xfer(struct i3c_hci *hci, + struct hci_xfer *xfer_list, int n) + { +@@ -382,6 +409,11 @@ static int hci_dma_queue_xfer(struct i3c + struct hci_rh_data *rh; + unsigned int i, ring, enqueue_ptr; + u32 op1_val, op2_val; ++ int ret; ++ ++ ret = hci_dma_map_xfer_list(hci, rings->sysdev, xfer_list, n); ++ if (ret) ++ return ret; + + /* For now we only use ring 0 */ + ring = 0; +@@ -392,9 +424,6 @@ static int hci_dma_queue_xfer(struct i3c + for (i = 0; i < n; i++) { + struct hci_xfer *xfer = xfer_list + i; + u32 *ring_data = rh->xfer + rh->xfer_struct_sz * enqueue_ptr; +- enum dma_data_direction dir = xfer->rnw ? DMA_FROM_DEVICE : +- DMA_TO_DEVICE; +- bool need_bounce; + + /* store cmd descriptor */ + *ring_data++ = xfer->cmd_desc[0]; +@@ -413,18 +442,6 @@ static int hci_dma_queue_xfer(struct i3c + + /* 2nd and 3rd words of Data Buffer Descriptor Structure */ + if (xfer->data) { +- need_bounce = device_iommu_mapped(rings->sysdev) && +- xfer->rnw && +- xfer->data_len != ALIGN(xfer->data_len, 4); +- xfer->dma = i3c_master_dma_map_single(rings->sysdev, +- xfer->data, +- xfer->data_len, +- need_bounce, +- dir); +- if (!xfer->dma) { +- hci_dma_unmap_xfer(hci, xfer_list, i); +- return -ENOMEM; +- } + *ring_data++ = lower_32_bits(xfer->dma->addr); + *ring_data++ = upper_32_bits(xfer->dma->addr); + } else { +@@ -447,7 +464,7 @@ static int hci_dma_queue_xfer(struct i3c + op2_val = rh_reg_read(RING_OPERATION2); + if (enqueue_ptr == FIELD_GET(RING_OP2_CR_DEQ_PTR, op2_val)) { + /* the ring is full */ +- hci_dma_unmap_xfer(hci, xfer_list, i + 1); ++ hci_dma_unmap_xfer(hci, xfer_list, n); + return -EBUSY; + } + } diff --git a/queue-6.19/i3c-mipi-i3c-hci-fix-race-in-dma-ring-dequeue.patch b/queue-6.19/i3c-mipi-i3c-hci-fix-race-in-dma-ring-dequeue.patch new file mode 100644 index 0000000000..86252bae9c --- /dev/null +++ b/queue-6.19/i3c-mipi-i3c-hci-fix-race-in-dma-ring-dequeue.patch @@ -0,0 +1,66 @@ +From 1dca8aee80eea76d2aae21265de5dd64f6ba0f09 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 6 Mar 2026 09:24:43 +0200 +Subject: i3c: mipi-i3c-hci: Fix race in DMA ring dequeue + +From: Adrian Hunter + +commit 1dca8aee80eea76d2aae21265de5dd64f6ba0f09 upstream. + +The HCI DMA dequeue path (hci_dma_dequeue_xfer()) may be invoked for +multiple transfers that timeout around the same time. However, the +function is not serialized and can race with itself. + +When a timeout occurs, hci_dma_dequeue_xfer() stops the ring, processes +incomplete transfers, and then restarts the ring. If another timeout +triggers a parallel call into the same function, the two instances may +interfere with each other - stopping or restarting the ring at unexpected +times. + +Add a mutex so that hci_dma_dequeue_xfer() is serialized with respect to +itself. + +Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20260306072451.11131-7-adrian.hunter@intel.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master/mipi-i3c-hci/core.c | 1 + + drivers/i3c/master/mipi-i3c-hci/dma.c | 2 ++ + drivers/i3c/master/mipi-i3c-hci/hci.h | 1 + + 3 files changed, 4 insertions(+) + +--- a/drivers/i3c/master/mipi-i3c-hci/core.c ++++ b/drivers/i3c/master/mipi-i3c-hci/core.c +@@ -632,6 +632,7 @@ static int i3c_hci_init(struct i3c_hci * + return ret; + + spin_lock_init(&hci->lock); ++ mutex_init(&hci->control_mutex); + + /* + * Now let's reset the hardware. +--- a/drivers/i3c/master/mipi-i3c-hci/dma.c ++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c +@@ -486,6 +486,8 @@ static bool hci_dma_dequeue_xfer(struct + unsigned int i; + bool did_unqueue = false; + ++ guard(mutex)(&hci->control_mutex); ++ + /* stop the ring */ + rh_reg_write(RING_CONTROL, RING_CTRL_ABORT); + if (wait_for_completion_timeout(&rh->op_done, HZ) == 0) { +--- a/drivers/i3c/master/mipi-i3c-hci/hci.h ++++ b/drivers/i3c/master/mipi-i3c-hci/hci.h +@@ -46,6 +46,7 @@ struct i3c_hci { + void *io_data; + const struct hci_cmd_ops *cmd; + spinlock_t lock; ++ struct mutex control_mutex; + atomic_t next_cmd_tid; + u32 caps; + unsigned int quirks; diff --git a/queue-6.19/i3c-mipi-i3c-hci-restart-dma-ring-correctly-after-dequeue-abort.patch b/queue-6.19/i3c-mipi-i3c-hci-restart-dma-ring-correctly-after-dequeue-abort.patch new file mode 100644 index 0000000000..575162c5e9 --- /dev/null +++ b/queue-6.19/i3c-mipi-i3c-hci-restart-dma-ring-correctly-after-dequeue-abort.patch @@ -0,0 +1,41 @@ +From b6d586431ae20d5157ee468d0ef62ad26798ef13 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 6 Mar 2026 09:24:47 +0200 +Subject: i3c: mipi-i3c-hci: Restart DMA ring correctly after dequeue abort + +From: Adrian Hunter + +commit b6d586431ae20d5157ee468d0ef62ad26798ef13 upstream. + +The DMA dequeue path attempts to restart the ring after aborting an +in-flight transfer, but the current sequence is incomplete. The controller +must be brought out of the aborted state and the ring control registers +must be programmed in the correct order: first clearing ABORT, then +re-enabling the ring and asserting RUN_STOP to resume operation. + +Add the missing controller resume step and update the ring control writes +so that the ring is restarted using the proper sequence. + +Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20260306072451.11131-11-adrian.hunter@intel.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master/mipi-i3c-hci/dma.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/i3c/master/mipi-i3c-hci/dma.c ++++ b/drivers/i3c/master/mipi-i3c-hci/dma.c +@@ -528,7 +528,9 @@ static bool hci_dma_dequeue_xfer(struct + } + + /* restart the ring */ ++ mipi_i3c_hci_resume(hci); + rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE); ++ rh_reg_write(RING_CONTROL, RING_CTRL_ENABLE | RING_CTRL_RUN_STOP); + + return did_unqueue; + } diff --git a/queue-6.19/i3c-mipi-i3c-hci-use-etimedout-instead-of-etime-for-timeout-errors.patch b/queue-6.19/i3c-mipi-i3c-hci-use-etimedout-instead-of-etime-for-timeout-errors.patch new file mode 100644 index 0000000000..3d834e105a --- /dev/null +++ b/queue-6.19/i3c-mipi-i3c-hci-use-etimedout-instead-of-etime-for-timeout-errors.patch @@ -0,0 +1,78 @@ +From 4167b8914463132654e01e16259847d097f8a7f7 Mon Sep 17 00:00:00 2001 +From: Adrian Hunter +Date: Fri, 6 Mar 2026 09:24:38 +0200 +Subject: i3c: mipi-i3c-hci: Use ETIMEDOUT instead of ETIME for timeout errors + +From: Adrian Hunter + +commit 4167b8914463132654e01e16259847d097f8a7f7 upstream. + +The MIPI I3C HCI driver currently returns -ETIME for various timeout +conditions, while other I3C master drivers consistently use -ETIMEDOUT +for the same class of errors. Align the HCI driver with the rest of the +subsystem by replacing all uses of -ETIME with -ETIMEDOUT. + +Fixes: 9ad9a52cce282 ("i3c/master: introduce the mipi-i3c-hci driver") +Cc: stable@vger.kernel.org +Signed-off-by: Adrian Hunter +Reviewed-by: Frank Li +Link: https://patch.msgid.link/20260306072451.11131-2-adrian.hunter@intel.com +Signed-off-by: Alexandre Belloni +Signed-off-by: Greg Kroah-Hartman +--- + drivers/i3c/master/mipi-i3c-hci/cmd_v1.c | 2 +- + drivers/i3c/master/mipi-i3c-hci/cmd_v2.c | 2 +- + drivers/i3c/master/mipi-i3c-hci/core.c | 6 +++--- + 3 files changed, 5 insertions(+), 5 deletions(-) + +--- a/drivers/i3c/master/mipi-i3c-hci/cmd_v1.c ++++ b/drivers/i3c/master/mipi-i3c-hci/cmd_v1.c +@@ -336,7 +336,7 @@ static int hci_cmd_v1_daa(struct i3c_hci + hci->io->queue_xfer(hci, xfer, 1); + if (!wait_for_completion_timeout(&done, HZ) && + hci->io->dequeue_xfer(hci, xfer, 1)) { +- ret = -ETIME; ++ ret = -ETIMEDOUT; + break; + } + if ((RESP_STATUS(xfer->response) == RESP_ERR_ADDR_HEADER || +--- a/drivers/i3c/master/mipi-i3c-hci/cmd_v2.c ++++ b/drivers/i3c/master/mipi-i3c-hci/cmd_v2.c +@@ -277,7 +277,7 @@ static int hci_cmd_v2_daa(struct i3c_hci + hci->io->queue_xfer(hci, xfer, 2); + if (!wait_for_completion_timeout(&done, HZ) && + hci->io->dequeue_xfer(hci, xfer, 2)) { +- ret = -ETIME; ++ ret = -ETIMEDOUT; + break; + } + if (RESP_STATUS(xfer[0].response) != RESP_SUCCESS) { +--- a/drivers/i3c/master/mipi-i3c-hci/core.c ++++ b/drivers/i3c/master/mipi-i3c-hci/core.c +@@ -230,7 +230,7 @@ static int i3c_hci_send_ccc_cmd(struct i + goto out; + if (!wait_for_completion_timeout(&done, HZ) && + hci->io->dequeue_xfer(hci, xfer, nxfers)) { +- ret = -ETIME; ++ ret = -ETIMEDOUT; + goto out; + } + for (i = prefixed; i < nxfers; i++) { +@@ -309,7 +309,7 @@ static int i3c_hci_i3c_xfers(struct i3c_ + goto out; + if (!wait_for_completion_timeout(&done, HZ) && + hci->io->dequeue_xfer(hci, xfer, nxfers)) { +- ret = -ETIME; ++ ret = -ETIMEDOUT; + goto out; + } + for (i = 0; i < nxfers; i++) { +@@ -357,7 +357,7 @@ static int i3c_hci_i2c_xfers(struct i2c_ + goto out; + if (!wait_for_completion_timeout(&done, m->i2c.timeout) && + hci->io->dequeue_xfer(hci, xfer, nxfers)) { +- ret = -ETIME; ++ ret = -ETIMEDOUT; + goto out; + } + for (i = 0; i < nxfers; i++) { diff --git a/queue-6.19/series b/queue-6.19/series index 884d1154d2..83bc6827cd 100644 --- a/queue-6.19/series +++ b/queue-6.19/series @@ -362,3 +362,10 @@ iio-imu-inv_icm42600-fix-odr-switch-to-the-same-value.patch iio-imu-inv_icm42600-fix-odr-switch-when-turning-buffer-off.patch iio-proximity-hx9023s-fix-assignment-order-for-__counted_by.patch iio-proximity-hx9023s-protect-against-division-by-zero-in-set_samp_freq.patch +i3c-mipi-i3c-hci-use-etimedout-instead-of-etime-for-timeout-errors.patch +i3c-mipi-i3c-hci-factor-out-dma-mapping-from-queuing-path.patch +i3c-mipi-i3c-hci-consolidate-spinlocks.patch +i3c-mipi-i3c-hci-restart-dma-ring-correctly-after-dequeue-abort.patch +i3c-mipi-i3c-hci-add-missing-tid-field-to-no-op-command-descriptor.patch +i3c-mipi-i3c-hci-fix-race-in-dma-ring-dequeue.patch +i3c-mipi-i3c-hci-correct-ring_ctrl_abort-handling-in-dma-dequeue.patch