From: Adrian Hunter Date: Fri, 12 Jun 2026 08:01:03 +0000 (+0300) Subject: i3c: master: Prevent reuse of dynamic address on device add failure X-Git-Url: http://git.ipfire.org/index.cgi?a=commitdiff_plain;h=b3ba8383da4d0cff15810e32ea785eceb0a80813;p=thirdparty%2Fkernel%2Flinux.git i3c: master: Prevent reuse of dynamic address on device add failure i3c_master_add_i3c_dev_locked() is called after a device has already been assigned a dynamic address. If the function fails, the address remains marked as free and may be reallocated to another device, leading to address conflicts on the bus. Ensure the address is not marked as free on failure, by updating the address slot state to prevent the address from being re-used. Emit an error message to inform of the failure. Opportunistically remove the !master check because it is impossible. Note, directly resetting the device's dynamic address is no longer an option, since Direct RSTDAA was deprecated from I3C starting from version 1.1 and v1.1 (or later) target devices are meant to NACK it. Fixes: 3a379bbcea0af ("i3c: Add core I3C infrastructure") Signed-off-by: Adrian Hunter Reviewed-by: Frank Li Link: https://patch.msgid.link/20260612080107.11606-4-adrian.hunter@intel.com Signed-off-by: Alexandre Belloni --- diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c index 9f8d99636f69..b45065ecbd48 100644 --- a/drivers/i3c/master.c +++ b/drivers/i3c/master.c @@ -2345,12 +2345,11 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master, bool enable_ibi = false; int ret; - if (!master) - return -EINVAL; - newdev = i3c_master_alloc_i3c_dev(master, &info); - if (IS_ERR(newdev)) - return PTR_ERR(newdev); + if (IS_ERR(newdev)) { + ret = PTR_ERR(newdev); + goto err_prevent_addr_reuse; + } ret = i3c_master_attach_i3c_dev(master, newdev); if (ret) @@ -2472,6 +2471,16 @@ err_detach_dev: err_free_dev: i3c_master_free_i3c_dev(newdev); +err_prevent_addr_reuse: + /* + * Although the device has not been added, the address has been + * assigned. Prevent the address from being used again. + */ + if (i3c_bus_get_addr_slot_status(&master->bus, addr) == I3C_ADDR_SLOT_FREE) + i3c_bus_set_addr_slot_status(&master->bus, addr, I3C_ADDR_SLOT_I3C_DEV); + + dev_err(&master->dev, "Failed to add I3C device at address %u, error %d\n", addr, ret); + return ret; } EXPORT_SYMBOL_GPL(i3c_master_add_i3c_dev_locked);