Re: [PATCH V3 14/16] i3c: mipi-i3c-hci: Base timeouts on actual transfer start time

From: Frank Li

Date: Tue May 12 2026 - 14:21:07 EST


On Mon, May 04, 2026 at 02:33:50PM +0300, Adrian Hunter wrote:
> Transfer timeouts are currently measured from the point where a transfer
> list is queued to the controller. This can cause transfers to time out
> before they have actually started, if earlier queued transfers consume
> the timeout interval.
>
> Fix this by recording when a transfer reaches the head of the queue and
> adjusting the timeout calculation to start from that point. The existing
> low-overhead completion-based timeout mechanism is preserved, but care is
> taken to ensure the transfer start time is consistently recorded for both
> PIO and DMA paths.
>
> This prevents premature timeouts while retaining efficient timeout
> handling.
>
> Signed-off-by: Adrian Hunter <adrian.hunter@xxxxxxxxx>
> ---
>
>
> Changes in V3:
>
> None
>
> Changes in V2:
> Do not flag the next transfer as started when there is an error
> which halts the controller
> Instead flag it started at the end of hci_dma_dequeue_xfer()
> Use hci_start_xfer() in pio.c
>
>
> drivers/i3c/master/mipi-i3c-hci/core.c | 19 ++++++++++++++++++-
> drivers/i3c/master/mipi-i3c-hci/dma.c | 19 ++++++++++++++++++-
> drivers/i3c/master/mipi-i3c-hci/hci.h | 11 +++++++++++
> drivers/i3c/master/mipi-i3c-hci/pio.c | 1 +
> 4 files changed, 48 insertions(+), 2 deletions(-)
>
...
>
> #include <linux/io.h>
> +#include <linux/jiffies.h>
>
> /* 32-bit word aware bit and mask macros */
> #define W0_MASK(h, l) GENMASK((h) - 0, (l) - 0)
> @@ -88,11 +89,13 @@ struct hci_xfer {
> u32 cmd_desc[4];
> u32 response;
> bool rnw;
> + bool started;
> void *data;
> unsigned int data_len;
> unsigned int cmd_tid;
> struct completion *completion;
> unsigned long timeout;
> + unsigned long start_time;

it'd better to add unit for start_time

Frank
> union {
> struct {
> /* PIO specific */
> @@ -123,6 +126,14 @@ static inline void hci_free_xfer(struct hci_xfer *xfer, unsigned int n)
> kfree(xfer);
> }
>
> +static inline void hci_start_xfer(struct hci_xfer *xfer)
> +{
> + if (!xfer->started) {
> + xfer->started = true;
> + xfer->start_time = jiffies;
> + }
> +}
> +
> /* This abstracts PIO vs DMA operations */
> struct hci_io_ops {
> bool (*irq_handler)(struct i3c_hci *hci);
> diff --git a/drivers/i3c/master/mipi-i3c-hci/pio.c b/drivers/i3c/master/mipi-i3c-hci/pio.c
> index 8f48a81e65ab..6b8cc5f2b4d2 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/pio.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/pio.c
> @@ -605,6 +605,7 @@ static bool hci_pio_process_cmd(struct i3c_hci *hci, struct hci_pio_data *pio)
> * Finally send the command.
> */
> hci_pio_write_cmd(hci, pio->curr_xfer);
> + hci_start_xfer(pio->curr_xfer);
> /*
> * And move on.
> */
> --
> 2.51.0
>