summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFrank Li <Frank.Li@nxp.com>2024-10-02 10:50:38 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-12-09 10:41:06 +0100
commit34a55b54845d01f60b614153ed6ff2c13c96cf15 (patch)
treeb410d3cf6ff6595fb2503c1e0db4658314ef905c
parent0e8ab955c6d06f9d907761c07c02d1492f0a8ac1 (diff)
i3c: master: svc: fix possible assignment of the same address to two devices
commit 3b2ac810d86eb96e882db80a3320a3848b133208 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: stable@kernel.org Fixes: 317bacf960a4 ("i3c: master: add enable(disable) hot join in sys entry") Reviewed-by: Miquel Raynal <miquel.raynal@bootlin.com> Signed-off-by: Frank Li <Frank.Li@nxp.com> Link: https://lore.kernel.org/r/20241002-svc-i3c-hj-v6-6-7e6e1d3569ae@nxp.com Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/i3c/master/svc-i3c-master.c27
1 files changed, 21 insertions, 6 deletions
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 130cec4ee307..dfe11b60251e 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1056,12 +1056,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);