Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
i3c: master: svc: fix possible assignment of the same address to two …
Browse files Browse the repository at this point in the history
…devices

commit 3b2ac81 upstream.

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: [email protected]
Fixes: 317bacf ("i3c: master: add enable(disable) hot join in sys entry")
Reviewed-by: Miquel Raynal <[email protected]>
Signed-off-by: Frank Li <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexandre Belloni <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
  • Loading branch information
nxpfrankli authored and gregkh committed Dec 12, 2024
1 parent 536a1c3 commit 8d49435
Showing 1 changed file with 21 additions and 6 deletions.
27 changes: 21 additions & 6 deletions drivers/i3c/master/svc-i3c-master.c
Original file line number Diff line number Diff line change
Expand Up @@ -1018,12 +1018,27 @@ static int svc_i3c_master_do_daa(struct i3c_master_controller *m)
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);
Expand Down

0 comments on commit 8d49435

Please sign in to comment.