Commit 3b2ac810 authored by Frank Li's avatar Frank Li Committed by Alexandre Belloni
Browse files

i3c: master: svc: fix possible assignment of the same address to two devices



svc_i3c_master_do_daa() {
    ...
    for (i = 0; i < dev_nb; i++) {
        ret = i3c_master_add_i3c_dev_locked(m, addrs[i]);
        if (ret)
            goto rpm_out;
    }
}

If two devices (A and B) are detected in DAA and address 0xa is assigned to
device A and 0xb to device B, a failure in i3c_master_add_i3c_dev_locked()
for device A (addr: 0xa) could prevent device B (addr: 0xb) from being
registered on the bus. The I3C stack might still consider 0xb a free
address. If a subsequent Hotjoin occurs, 0xb might be assigned to Device A,
causing both devices A and B to use the same address 0xb, violating the I3C
specification.

The return value for i3c_master_add_i3c_dev_locked() should not be checked
because subsequent steps will scan the entire I3C bus, independent of
whether i3c_master_add_i3c_dev_locked() returns success.

If device A registration fails, there is still a chance to register device
B. i3c_master_add_i3c_dev_locked() can reset DAA if a failure occurs while
retrieving device information.

Cc: stable@kernel.org
Fixes: 317bacf9 ("i3c: master: add enable(disable) hot join in sys entry")
Reviewed-by: default avatarMiquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20241002-svc-i3c-hj-v6-6-7e6e1d3569ae@nxp.com


Signed-off-by: default avatarAlexandre Belloni <alexandre.belloni@bootlin.com>
parent 3ca52919
Loading
Loading
Loading
Loading
+21 −6
Original line number Diff line number Diff line
@@ -1103,12 +1103,27 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
	if (ret)
		goto rpm_out;

	/* Register all devices who participated to the core */
	for (i = 0; i < dev_nb; i++) {
		ret = i3c_master_add_i3c_dev_locked(m, addrs[i]);
		if (ret)
			goto rpm_out;
	}
	/*
	 * Register all devices who participated to the core
	 *
	 * If two devices (A and B) are detected in DAA and address 0xa is assigned to
	 * device A and 0xb to device B, a failure in i3c_master_add_i3c_dev_locked()
	 * for device A (addr: 0xa) could prevent device B (addr: 0xb) from being
	 * registered on the bus. The I3C stack might still consider 0xb a free
	 * address. If a subsequent Hotjoin occurs, 0xb might be assigned to Device A,
	 * causing both devices A and B to use the same address 0xb, violating the I3C
	 * specification.
	 *
	 * The return value for i3c_master_add_i3c_dev_locked() should not be checked
	 * because subsequent steps will scan the entire I3C bus, independent of
	 * whether i3c_master_add_i3c_dev_locked() returns success.
	 *
	 * If device A registration fails, there is still a chance to register device
	 * B. i3c_master_add_i3c_dev_locked() can reset DAA if a failure occurs while
	 * retrieving device information.
	 */
	for (i = 0; i < dev_nb; i++)
		i3c_master_add_i3c_dev_locked(m, addrs[i]);

	/* Configure IBI auto-rules */
	ret = svc_i3c_update_ibirules(master);