[PATCH v4 04/16] i3c: renesas: Reconfigure the DATBAS register on re-attach
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Fri Jun 12 09:24:30 PDT 2026
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Hardware transfers are not aborted on software timeout, permanently desynchronizing the bus state and precipitating severe memory corruption.
- [High] Hardware DAA implementation erroneously assumes free device slots are contiguous, assigning already-in-use addresses to new devices under fragmented slot conditions.
- [High] Ignored completion timeout returns in `renesas_i3c_i2c_xfers` lead to silent operational failures.
- [High] Undefined behavior in dynamic `GENMASK` generation causes false phantom device attachment.
--
commit 80894950fcbc5a0242a4c816117f647e2715af0b
Author: Claudiu Beznea <claudiu.beznea.uj at bp.renesas.com>
i3c: renesas: Reconfigure the DATBAS register on re-attach
This commit reconfigures the DATBAS register during re-attach to handle
cases where a device changes its position in the i3c->addrs[] array. It
ensures the correct Device Address Table Basic Register is used and
updates software caches.
> diff --git a/drivers/i3c/master/renesas-i3c.c b/drivers/i3c/master/renesas-i3c.c
> index 7d448936b74c1..4b81c32b1fdec 100644
> --- a/drivers/i3c/master/renesas-i3c.c
> +++ b/drivers/i3c/master/renesas-i3c.c
[ ... ]
> @@ -892,10 +892,26 @@ static int renesas_i3c_reattach_i3c_dev(struct i3c_dev_desc *dev,
> struct i3c_master_controller *m = i3c_dev_get_master(dev);
> struct renesas_i3c *i3c = to_renesas_i3c(m);
> struct renesas_i3c_i2c_dev_data *data = i3c_dev_get_master_data(dev);
> + int pos;
> +
> + pos = renesas_i3c_get_free_pos(i3c);
> +
> + if (data->index > pos && pos >= 0) {
> + renesas_writel(i3c->regs, DATBAS(data->index), 0);
> + i3c->addrs[data->index] = 0;
> + i3c->free_pos |= BIT(data->index);
> +
> + data->index = pos;
> + i3c->free_pos &= ~BIT(data->index);
> + }
>
> i3c->addrs[data->index] = dev->info.dyn_addr ? dev->info.dyn_addr :
> dev->info.static_addr;
>
> + renesas_writel(i3c->regs, DATBAS(data->index),
> + DATBAS_DVSTAD(dev->info.static_addr) |
> + datbas_dvdyad_with_parity(i3c->addrs[data->index]));
> +
> return 0;
> }
[Severity: High]
This isn't a bug introduced by this patch, but looking at renesas_i3c_daa()
in this file, is it possible for the hardware to overwrite an active device
if slots are fragmented?
In renesas_i3c_daa():
cmd->cmd0 = NCMDQP_CMD_ATTR(NCMDQP_ADDR_ASSGN) | NCMDQP_ROC |
NCMDQP_TID(I3C_COMMAND_ADDRESS_ASSIGNMENT) |
NCMDQP_CMD(I3C_CCC_ENTDAA) | NCMDQP_DEV_INDEX(ret) |
NCMDQP_DEV_COUNT(i3c->maxdevs - ret) | NCMDQP_TOC;
The code passes i3c->maxdevs - ret to NCMDQP_DEV_COUNT, assuming all
subsequent slots are free. If slot 1 is free but slot 2 is in use, could the
hardware increment its internal DATBAS index and overwrite the active device
in slot 2 when multiple new devices respond to ENTDAA?
[Severity: Critical]
This is a pre-existing issue, but I have a question about how hardware aborts
are handled on software timeout.
When wait_for_completion_timeout() expires in renesas_i3c_wait_xfer():
time_left = wait_for_completion_timeout(&xfer->comp, msecs_to_jiffies(1000));
if (!time_left)
renesas_i3c_dequeue_xfer(i3c, xfer);
The xfer is dequeued, but the hardware transfer doesn't appear to be aborted.
If a new transfer is enqueued, and the hardware eventually completes the
timed-out transfer, could renesas_i3c_resp_isr() blindly apply the late
response to the new transfer buffer?
xfer = i3c->xferqueue.cur;
...
if (NDBSTLV0_RDBLV(renesas_readl(i3c->regs, NDBSTLV0)) && !cmd->err)
bytes_remaining = data_len - cmd->rx_count;
i3c_readl_fifo(i3c->regs + NTDTBP0, cmd->rx_buf, bytes_remaining);
Does this create a scenario where i3c_readl_fifo() copies data into the new
cmd->rx_buf based on the old data_len, potentially causing a buffer overflow?
[Severity: High]
This isn't a bug introduced by this patch, but does the I2C transfer logic
mask completion timeouts?
In renesas_i3c_i2c_xfers():
time_left = wait_for_completion_timeout(&xfer->comp, m->i2c.timeout);
if (!time_left)
xfer_failed = true;
if (cmd->err)
break;
If the timeout expires, xfer_failed is set to true but cmd->err remains 0
because the ISR never executed. Since cmd->err is 0, the loop does not break,
which seems like it could cause the driver to continue to the next message
and eventually return 0, masking the timeout.
[Severity: High]
This is a pre-existing issue, but can the dynamic mask generation in
renesas_i3c_daa() result in phantom device attachments?
In renesas_i3c_daa(), when configuring the mask for new devices:
newdevs = GENMASK(i3c->maxdevs - cmd->rx_count - 1, first_i3c_pos);
If no devices respond to the ENTDAA command, cmd->rx_count is set to
i3c->maxdevs - ret. If ret is 0, this makes the upper bound of GENMASK
evaluate to -1. Would executing GENMASK(-1, 0) evaluate to ~0UL and cause
the driver to iterate over all bits, falsely registering phantom devices
via i3c_master_add_i3c_dev_locked()?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260612160458.3102106-1-claudiu.beznea@kernel.org?part=4
More information about the linux-i3c
mailing list