Linux-i3c Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin
@ 2024-08-13 15:14 Frank Li
  2024-08-13 15:14 ` [PATCH v2 01/11] i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device hotjoin Frank Li
                   ` (10 more replies)
  0 siblings, 11 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:14 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li, stable

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
Changes in v2:
- add help function at i3c: master: svc: manually emit NACK/ACK for hotjoin F
Add below new fix patch
i3c: master: svc: fix possible assignment of the same address to two devices
i3c: master: svc: wait for Manual ACK/NACK Done before next step
i3c: master: svc: use spinlock_saveirq at svc_i3c_master_ibi_work()
i3c: master: svc: need check IBIWON for dynamtica address assign

- Link to v1: https://lore.kernel.org/r/20240724-i3c_fix-v1-0-bfa500b023d6@nxp.com

---
Frank Li (11):
      i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device hotjoin
      i3c: master: Replace hard code 2 with macro I3C_ADDR_SLOT_BITS
      i3c: master: Extend address status bit to 4 and add I3C_ADDR_SLOT_EXT_INIT
      i3c: master: Fix dynamic address leak when 'assigned-address' is present
      i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs()
      i3c: master: svc: use repeat start when IBI WIN happens
      i3c: master: svc: manually emit NACK/ACK for hotjoin
      i3c: master: svc: need check IBIWON for dynamtica address assign
      i3c: master: svc: use spinlock_saveirq at svc_i3c_master_ibi_work()
      i3c: master: svc: wait for Manual ACK/NACK Done before next step
      i3c: master: svc: fix possible assignment of the same address to two devices

 drivers/i3c/master.c                |  66 ++++++++++++++---------
 drivers/i3c/master/svc-i3c-master.c | 102 ++++++++++++++++++++++++++----------
 include/linux/i3c/master.h          |   8 ++-
 3 files changed, 123 insertions(+), 53 deletions(-)
---
base-commit: 41c196e567fb1ea97f68a2ffb7faab451cd90854
change-id: 20240724-i3c_fix-371bf8fa9e00

Best regards,
---
Frank Li <Frank.Li@nxp.com>


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 01/11] i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device hotjoin
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
@ 2024-08-13 15:14 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 02/11] i3c: master: Replace hard code 2 with macro I3C_ADDR_SLOT_BITS Frank Li
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:14 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

When a new device hotjoins, a new dynamic address is assigned.
i3c_master_add_i3c_dev_locked() identifies that the device was previously
attached to the bus and locates the olddev.

i3c_master_add_i3c_dev_locked()
{
    ...
    olddev = i3c_master_search_i3c_dev_duplicate(newdev);
    ...
    if (olddev) {
        ...
        i3c_dev_disable_ibi_locked(olddev);
        ^^^^^^
        The olddev should not receive any commands on the i3c bus as it
        does not exist and has been assigned a new address. This will
        result in NACK or timeout. So remove it.
    }
}

Fixes: 317bacf960a4 ("i3c: master: add enable(disable) hot join in sys entry")
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 7028f03c2c42e..852b32178b722 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2039,10 +2039,8 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
 			ibireq.max_payload_len = olddev->ibi->max_payload_len;
 			ibireq.num_slots = olddev->ibi->num_slots;
 
-			if (olddev->ibi->enabled) {
+			if (olddev->ibi->enabled)
 				enable_ibi = true;
-				i3c_dev_disable_ibi_locked(olddev);
-			}
 
 			i3c_dev_free_ibi_locked(olddev);
 		}

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 02/11] i3c: master: Replace hard code 2 with macro I3C_ADDR_SLOT_BITS
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
  2024-08-13 15:14 ` [PATCH v2 01/11] i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device hotjoin Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 03/11] i3c: master: Extend address status bit to 4 and add I3C_ADDR_SLOT_EXT_INIT Frank Li
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

Replace the hardcoded value 2, which indicates 2 bits for I3C address
status, with the predefined macro I3C_ADDR_SLOT_BITS.

Improve maintainability and extensibility of the code.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master.c       | 4 ++--
 include/linux/i3c/master.h | 4 +++-
 2 files changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 852b32178b722..85c737554c940 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -348,7 +348,7 @@ static enum i3c_addr_slot_status
 i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
 {
 	unsigned long status;
-	int bitpos = addr * 2;
+	int bitpos = addr * I3C_ADDR_SLOT_BITS;
 
 	if (addr > I2C_MAX_ADDR)
 		return I3C_ADDR_SLOT_RSVD;
@@ -362,7 +362,7 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
 static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
 					 enum i3c_addr_slot_status status)
 {
-	int bitpos = addr * 2;
+	int bitpos = addr * I3C_ADDR_SLOT_BITS;
 	unsigned long *ptr;
 
 	if (addr > I2C_MAX_ADDR)
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 074f632868d98..4601b6957f799 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -299,6 +299,8 @@ enum i3c_addr_slot_status {
 	I3C_ADDR_SLOT_STATUS_MASK = 3,
 };
 
+#define I3C_ADDR_SLOT_BITS 2
+
 /**
  * struct i3c_bus - I3C bus object
  * @cur_master: I3C master currently driving the bus. Since I3C is multi-master
@@ -340,7 +342,7 @@ enum i3c_addr_slot_status {
 struct i3c_bus {
 	struct i3c_dev_desc *cur_master;
 	int id;
-	unsigned long addrslots[((I2C_MAX_ADDR + 1) * 2) / BITS_PER_LONG];
+	unsigned long addrslots[((I2C_MAX_ADDR + 1) * I3C_ADDR_SLOT_BITS) / BITS_PER_LONG];
 	enum i3c_bus_mode mode;
 	struct {
 		unsigned long i3c;

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 03/11] i3c: master: Extend address status bit to 4 and add I3C_ADDR_SLOT_EXT_INIT
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
  2024-08-13 15:14 ` [PATCH v2 01/11] i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device hotjoin Frank Li
  2024-08-13 15:15 ` [PATCH v2 02/11] i3c: master: Replace hard code 2 with macro I3C_ADDR_SLOT_BITS Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 04/11] i3c: master: Fix dynamic address leak when 'assigned-address' is present Frank Li
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

Extend the address status bit to 4 and introduce the I3C_ADDR_SLOT_EXT_INIT
macro to indicate that a device prefers a specific address. This is
generally set by the 'assigned-address' in the device tree source (dts)
file.

When an i3c device is removed from the bus, the old address status is set
to FREE, allowing other devices to use the address during hotjoin. The
I3C_ADDR_SLOT_EXT_INIT status indicates that an address is preferred by
some devices. The function i3c_bus_get_free_addr() will first attempt to
use unassigned addresses before searching for assigned addresses of devices
that have been removed from the bus, trying to best match the
'assigned-address'.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master.c       | 43 ++++++++++++++++++++++++++++++++++---------
 include/linux/i3c/master.h |  6 +++++-
 2 files changed, 39 insertions(+), 10 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 85c737554c940..4281f673e08d8 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -345,7 +345,7 @@ const struct bus_type i3c_bus_type = {
 EXPORT_SYMBOL_GPL(i3c_bus_type);
 
 static enum i3c_addr_slot_status
-i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+i3c_bus_get_addr_slot_status_ext(struct i3c_bus *bus, u16 addr)
 {
 	unsigned long status;
 	int bitpos = addr * I3C_ADDR_SLOT_BITS;
@@ -356,11 +356,17 @@ i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
 	status = bus->addrslots[bitpos / BITS_PER_LONG];
 	status >>= bitpos % BITS_PER_LONG;
 
-	return status & I3C_ADDR_SLOT_STATUS_MASK;
+	return status & I3C_ADDR_SLOT_EXT_STATUS_MASK;
 }
 
-static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
-					 enum i3c_addr_slot_status status)
+static enum i3c_addr_slot_status
+i3c_bus_get_addr_slot_status(struct i3c_bus *bus, u16 addr)
+{
+	return i3c_bus_get_addr_slot_status_ext(bus, addr) & I3C_ADDR_SLOT_STATUS_MASK;
+}
+
+static void i3c_bus_set_addr_slot_status_mask(struct i3c_bus *bus, u16 addr,
+					      enum i3c_addr_slot_status status, int mask)
 {
 	int bitpos = addr * I3C_ADDR_SLOT_BITS;
 	unsigned long *ptr;
@@ -369,11 +375,22 @@ static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
 		return;
 
 	ptr = bus->addrslots + (bitpos / BITS_PER_LONG);
-	*ptr &= ~((unsigned long)I3C_ADDR_SLOT_STATUS_MASK <<
-						(bitpos % BITS_PER_LONG));
+	*ptr &= ~((unsigned long)mask << (bitpos % BITS_PER_LONG));
 	*ptr |= (unsigned long)status << (bitpos % BITS_PER_LONG);
 }
 
+static void i3c_bus_set_addr_slot_status(struct i3c_bus *bus, u16 addr,
+					 enum i3c_addr_slot_status status)
+{
+	i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_STATUS_MASK);
+}
+
+static void i3c_bus_set_addr_slot_status_ext(struct i3c_bus *bus, u16 addr,
+					     enum i3c_addr_slot_status status)
+{
+	i3c_bus_set_addr_slot_status_mask(bus, addr, status, I3C_ADDR_SLOT_EXT_STATUS_MASK);
+}
+
 static bool i3c_bus_dev_addr_is_avail(struct i3c_bus *bus, u8 addr)
 {
 	enum i3c_addr_slot_status status;
@@ -388,6 +405,14 @@ static int i3c_bus_get_free_addr(struct i3c_bus *bus, u8 start_addr)
 	enum i3c_addr_slot_status status;
 	u8 addr;
 
+	/* try find an address, which have not pre-allocated by assigned-address */
+	for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
+		status = i3c_bus_get_addr_slot_status_ext(bus, addr);
+		if (status == I3C_ADDR_SLOT_FREE)
+			return addr;
+	}
+
+	/* use pre-allocoated by assigned-address because such device was removed at bus*/
 	for (addr = start_addr; addr < I3C_MAX_ADDR; addr++) {
 		status = i3c_bus_get_addr_slot_status(bus, addr);
 		if (status == I3C_ADDR_SLOT_FREE)
@@ -1906,9 +1931,9 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
 			goto err_rstdaa;
 		}
 
-		i3c_bus_set_addr_slot_status(&master->bus,
-					     i3cboardinfo->init_dyn_addr,
-					     I3C_ADDR_SLOT_I3C_DEV);
+		i3c_bus_set_addr_slot_status_ext(&master->bus,
+						 i3cboardinfo->init_dyn_addr,
+						 I3C_ADDR_SLOT_I3C_DEV | I3C_ADDR_SLOT_EXT_INIT);
 
 		/*
 		 * Only try to create/attach devices that have a static
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 4601b6957f799..c923b76bbc321 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -284,6 +284,8 @@ enum i3c_bus_mode {
  * @I3C_ADDR_SLOT_I2C_DEV: address is assigned to an I2C device
  * @I3C_ADDR_SLOT_I3C_DEV: address is assigned to an I3C device
  * @I3C_ADDR_SLOT_STATUS_MASK: address slot mask
+ * @I3C_ADDR_SLOT_EXT_INIT: the bit mask display of addresses is preferred by some devices,
+ *			    such as the "assigned-address" in device tree source (dts).
  *
  * On an I3C bus, addresses are assigned dynamically, and we need to know which
  * addresses are free to use and which ones are already assigned.
@@ -297,9 +299,11 @@ enum i3c_addr_slot_status {
 	I3C_ADDR_SLOT_I2C_DEV,
 	I3C_ADDR_SLOT_I3C_DEV,
 	I3C_ADDR_SLOT_STATUS_MASK = 3,
+	I3C_ADDR_SLOT_EXT_STATUS_MASK = 7,
+	I3C_ADDR_SLOT_EXT_INIT = BIT(2),
 };
 
-#define I3C_ADDR_SLOT_BITS 2
+#define I3C_ADDR_SLOT_BITS 4
 
 /**
  * struct i3c_bus - I3C bus object

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 04/11] i3c: master: Fix dynamic address leak when 'assigned-address' is present
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (2 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 03/11] i3c: master: Extend address status bit to 4 and add I3C_ADDR_SLOT_EXT_INIT Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 05/11] i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs() Frank Li
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li, stable

If the DTS contains 'assigned-address', a dynamic address leak occurs
during hotjoin events.

Assume a device have assigned-address 0xb.
  - Device issue Hotjoin
  - Call i3c_master_do_daa()
  - Call driver xxx_do_daa()
  - Call i3c_master_get_free_addr() to get dynamic address 0x9
  - i3c_master_add_i3c_dev_locked(0x9)
  -     expected_dyn_addr  = newdev->boardinfo->init_dyn_addr (0xb);
  -     i3c_master_reattach_i3c_dev(newdev(0xb), old_dyn_addr(0x9));
  -         if (dev->info.dyn_addr != old_dyn_addr &&
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 0xb != 0x9 -> TRUE
                (!dev->boardinfo ||
                 ^^^^^^^^^^^^^^^ ->  FALSE
                 dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
                 0xb != 0xb      ->  FALSE
                 ...
                 i3c_bus_set_addr_slot_status(&master->bus, old_dyn_addr,
                                                     I3C_ADDR_SLOT_FREE);
		 ^^^
                 This will be skipped. So old_dyn_addr never free
            }

  - i3c_master_get_free_addr() will return increased sequence number.

Remove dev->info.dyn_addr != dev->boardinfo->init_dyn_addr condition check.
dev->info.dyn_addr should be checked before calling this function because
i3c_master_setnewda_locked() has already been called and the target device
has already accepted dyn_addr. It is too late to check if dyn_addr is free
in i3c_master_reattach_i3c_dev().

Add check to ensure expected_dyn_addr is free before
i3c_master_setnewda_locked().

Fixes: cc3a392d69b6 ("i3c: master: fix for SETDASA and DAA process")
Cc: stable@kernel.org
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master.c | 15 +++++----------
 1 file changed, 5 insertions(+), 10 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 4281f673e08d8..c8eaeada54781 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1531,16 +1531,9 @@ static int i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
 				       u8 old_dyn_addr)
 {
 	struct i3c_master_controller *master = i3c_dev_get_master(dev);
-	enum i3c_addr_slot_status status;
 	int ret;
 
-	if (dev->info.dyn_addr != old_dyn_addr &&
-	    (!dev->boardinfo ||
-	     dev->info.dyn_addr != dev->boardinfo->init_dyn_addr)) {
-		status = i3c_bus_get_addr_slot_status(&master->bus,
-						      dev->info.dyn_addr);
-		if (status != I3C_ADDR_SLOT_FREE)
-			return -EBUSY;
+	if (dev->info.dyn_addr != old_dyn_addr) {
 		i3c_bus_set_addr_slot_status(&master->bus,
 					     dev->info.dyn_addr,
 					     I3C_ADDR_SLOT_I3C_DEV);
@@ -1931,9 +1924,10 @@ static int i3c_master_bus_init(struct i3c_master_controller *master)
 			goto err_rstdaa;
 		}
 
+		/* Not mark as occupied until real device exist in bus */
 		i3c_bus_set_addr_slot_status_ext(&master->bus,
 						 i3cboardinfo->init_dyn_addr,
-						 I3C_ADDR_SLOT_I3C_DEV | I3C_ADDR_SLOT_EXT_INIT);
+						 I3C_ADDR_SLOT_EXT_INIT);
 
 		/*
 		 * Only try to create/attach devices that have a static
@@ -2094,7 +2088,8 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
 	else
 		expected_dyn_addr = newdev->info.dyn_addr;
 
-	if (newdev->info.dyn_addr != expected_dyn_addr) {
+	if (newdev->info.dyn_addr != expected_dyn_addr &&
+	    i3c_bus_get_addr_slot_status(&master->bus, expected_dyn_addr) == I3C_ADDR_SLOT_FREE) {
 		/*
 		 * Try to apply the expected dynamic address. If it fails, keep
 		 * the address assigned by the master.

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 05/11] i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs()
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (3 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 04/11] i3c: master: Fix dynamic address leak when 'assigned-address' is present Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 06/11] i3c: master: svc: use repeat start when IBI WIN happens Frank Li
                   ` (5 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li, stable

if (dev->boardinfo && dev->boardinfo->init_dyn_addr)
                                      ^^^ here check "init_dyn_addr"
	i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr, ...)
						             ^^^^
							free "dyn_addr"
Fix typo "dyn_addr" by replacing it with "init_dyn_addr".

Cc: stable@kernel.org
Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index c8eaeada54781..65642e5afdcfb 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1442,7 +1442,7 @@ static void i3c_master_put_i3c_addrs(struct i3c_dev_desc *dev)
 					     I3C_ADDR_SLOT_FREE);
 
 	if (dev->boardinfo && dev->boardinfo->init_dyn_addr)
-		i3c_bus_set_addr_slot_status(&master->bus, dev->info.dyn_addr,
+		i3c_bus_set_addr_slot_status(&master->bus, dev->boardinfo->init_dyn_addr,
 					     I3C_ADDR_SLOT_FREE);
 }
 

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 06/11] i3c: master: svc: use repeat start when IBI WIN happens
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (4 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 05/11] i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs() Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 07/11] i3c: master: svc: manually emit NACK/ACK for hotjoin Frank Li
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

There is a possibility of an IBI WIN occurring when addressing issues, even
when sending CCC commands. Most of the time, returning -EAGAIN is
acceptable, but the case below becomes highly complex.

When a Hotjoin event occurs:
- i3c_master_do_daa()
  - i3c_master_add_i3c_dev_locked()
    - A dynamic address (e.g., 0x9) is already set during DAA.
    - i3c_master_getpid_locked()
      - Another device issues HJ or IBI here. Returning -EAGAIN causes
        failure in adding the new device. However, the dynamic address(0x9)
        has already been assigned to this device. If another device issues
        HJ, it will get this address 0x9 again, causing two devices on the
        bus to use the same dynamic address 0x9.
      - Attempting to send RSTDAA when the first device fails at
        i3c_master_getpid_locked() could also fail when sending RSTDAA for
        the same reason.

According to the I3C spec, address arbitration only happens at START, never
at REPEAT start. Using repeat start when an IBI WIN occurs simplifies this
case, as i3c_master_getpid_locked() will not return an error when another
device tries to send HJ or IBI.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master/svc-i3c-master.c | 36 ++++++++++++++++++------------------
 1 file changed, 18 insertions(+), 18 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index e80c002991f75..5d19251238ff8 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1099,6 +1099,24 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 		if (ret)
 			goto emit_stop;
 
+		/*
+		 * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a
+		 * Frame with I3C Target Address.
+		 *
+		 * The I3C Controller normally should start a Frame, the Address may be arbitrated,
+		 * and so the Controller shall monitor to see whether an In-Band Interrupt request,
+		 * a Controller Role Request (i.e., Secondary Controller requests to become the
+		 * Active Controller), or a Hot-Join Request has been made.
+		 *
+		 * If missed IBIWON check, the wrong data will be return. When IBIWON happen, issue
+		 * repeat start. Address arbitrate only happen at START, never happen at REPEAT
+		 * start.
+		 */
+		if (SVC_I3C_MSTATUS_IBIWON(reg)) {
+			writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
+			continue;
+		}
+
 		if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) {
 			/*
 			 * According to I3C Spec 1.1.1, 11-Jun-2021, section: 5.1.2.2.3.
@@ -1132,24 +1150,6 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 		}
 	}
 
-	/*
-	 * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a Frame
-	 * with I3C Target Address.
-	 *
-	 * The I3C Controller normally should start a Frame, the Address may be arbitrated, and so
-	 * the Controller shall monitor to see whether an In-Band Interrupt request, a Controller
-	 * Role Request (i.e., Secondary Controller requests to become the Active Controller), or
-	 * a Hot-Join Request has been made.
-	 *
-	 * If missed IBIWON check, the wrong data will be return. When IBIWON happen, return failure
-	 * and yield the above events handler.
-	 */
-	if (SVC_I3C_MSTATUS_IBIWON(reg)) {
-		ret = -EAGAIN;
-		*actual_len = 0;
-		goto emit_stop;
-	}
-
 	if (rnw)
 		ret = svc_i3c_master_read(master, in, xfer_len);
 	else

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 07/11] i3c: master: svc: manually emit NACK/ACK for hotjoin
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (5 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 06/11] i3c: master: svc: use repeat start when IBI WIN happens Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 08/11] i3c: master: svc: need check IBIWON for dynamtica address assign Frank Li
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

When the address is arbitrated at send address, the hardware can auto-send
NACK if it is an IBI. However, manual emission of NACK/ACK is needed for
hot join or controller request events.

Add help function svc_i3c_master_handle_ibi_won() to check event type and
send out NACK if the event is not an IBI.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master/svc-i3c-master.c | 20 +++++++++++++++++++-
 1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 5d19251238ff8..d665639523e3c 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -405,6 +405,24 @@ static void svc_i3c_master_nack_ibi(struct svc_i3c_master *master)
 	       master->regs + SVC_I3C_MCTRL);
 }
 
+static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 mstatus)
+{
+	u32 ibitype;
+
+	ibitype = SVC_I3C_MSTATUS_IBITYPE(mstatus);
+
+	writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
+
+	/* Hardware can't auto emit NACK for hot join and master request */
+	switch (ibitype) {
+	case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
+	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
+		svc_i3c_master_nack_ibi(master);
+	}
+
+	return 0;
+}
+
 static void svc_i3c_master_ibi_work(struct work_struct *work)
 {
 	struct svc_i3c_master *master = container_of(work, struct svc_i3c_master, ibi_work);
@@ -1113,7 +1131,7 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 		 * start.
 		 */
 		if (SVC_I3C_MSTATUS_IBIWON(reg)) {
-			writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
+			svc_i3c_master_handle_ibi_won(master, reg);
 			continue;
 		}
 

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 08/11] i3c: master: svc: need check IBIWON for dynamtica address assign
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (6 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 07/11] i3c: master: svc: manually emit NACK/ACK for hotjoin Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 09/11] i3c: master: svc: use spinlock_saveirq at svc_i3c_master_ibi_work() Frank Li
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

When sending REQUEST_PROC_DAA, emit START and address 7E. Address
arbitration may occur at this time if other devices trigger HJ, IBI, or
CR events.

When IBIWON happen at REQUEST_PROC_DAA, nack IBI request then use repeat
start to continue current dynamtica address assign.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master/svc-i3c-master.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index d665639523e3c..161ccd824443b 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -808,6 +808,9 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 	int ret, i;
 
 	while (true) {
+		/* clean SVC_I3C_MINT_IBIWON w1c bits */
+		writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
+
 		/* SVC_I3C_MCTRL_REQUEST_PROC_DAA have two mode, ENTER DAA or PROCESS DAA.
 		 *
 		 * ENTER DAA:
@@ -859,6 +862,9 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 			ret = svc_i3c_master_readb(master, data, 2);
 			if (ret)
 				break;
+		} else if (SVC_I3C_MSTATUS_IBIWON(reg)) {
+			svc_i3c_master_handle_ibi_won(master, reg);
+			continue;
 		} else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) {
 			if (SVC_I3C_MSTATUS_STATE_IDLE(reg) &&
 			    SVC_I3C_MSTATUS_COMPLETE(reg)) {

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 09/11] i3c: master: svc: use spinlock_saveirq at svc_i3c_master_ibi_work()
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (7 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 08/11] i3c: master: svc: need check IBIWON for dynamtica address assign Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-13 15:15 ` [PATCH v2 10/11] i3c: master: svc: wait for Manual ACK/NACK Done before next step Frank Li
  2024-08-13 15:15 ` [PATCH v2 11/11] i3c: master: svc: fix possible assignment of the same address to two devices Frank Li
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

According to I3C spec ver 1.1, 09-Jun-2021, section 5.1.2.5:

The I3C Controller shall hold SCL Low while the Bus is in I3C/I2C Transfer,
ACK/NACK Phase. But maximum stall time is 100us. We have to disable irq and
schedule during whole I3C transaction, otherwise, I3C bus timeout will
happen if any irq or schedule happen during transaction.

Replace mutex with spinlock_saveirq() to make sure finish whole i3c
transaction without stall SCL more than 100us.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master/svc-i3c-master.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 161ccd824443b..fbb6cef405577 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -432,7 +432,16 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 	u32 status, val;
 	int ret;
 
-	mutex_lock(&master->lock);
+	/*
+	 * According to I3C spec ver 1.1, 09-Jun-2021, section 5.1.2.5:
+	 *
+	 * The I3C Controller shall hold SCL Low while the Bus is in I3C/I2C Transfer, ACK/NACK
+	 * Phase. But maximum stall time is 100us. We have to disable irq and schedule during whole
+	 * I3C transaction, otherwise, I3C bus timeout will happen if any irq or schedule happen
+	 * between transaction..
+	 */
+	guard(spinlock_irqsave)(&master->xferqueue.lock);
+
 	/*
 	 * IBIWON may be set before SVC_I3C_MCTRL_REQUEST_AUTO_IBI, causing
 	 * readl_relaxed_poll_timeout() to return immediately. Consequently,
@@ -452,7 +461,7 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 	       master->regs + SVC_I3C_MCTRL);
 
 	/* Wait for IBIWON, should take approximately 100us */
-	ret = readl_relaxed_poll_timeout(master->regs + SVC_I3C_MSTATUS, val,
+	ret = readl_relaxed_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, val,
 					 SVC_I3C_MSTATUS_IBIWON(val), 0, 1000);
 	if (ret) {
 		dev_err(master->dev, "Timeout when polling for IBIWON\n");
@@ -525,7 +534,6 @@ static void svc_i3c_master_ibi_work(struct work_struct *work)
 
 reenable_ibis:
 	svc_i3c_master_enable_interrupts(master, SVC_I3C_MINT_SLVSTART);
-	mutex_unlock(&master->lock);
 }
 
 static irqreturn_t svc_i3c_master_irq_handler(int irq, void *dev_id)

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 10/11] i3c: master: svc: wait for Manual ACK/NACK Done before next step
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (8 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 09/11] i3c: master: svc: use spinlock_saveirq at svc_i3c_master_ibi_work() Frank Li
@ 2024-08-13 15:15 ` Frank Li
  2024-08-19  5:15   ` Dan Carpenter
  2024-08-13 15:15 ` [PATCH v2 11/11] i3c: master: svc: fix possible assignment of the same address to two devices Frank Li
  10 siblings, 1 reply; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li

Wait for the controller to complete emitting ACK/NACK, otherwise the next
command may be omitted by the hardware.

Add command done check at svc_i3c_master_nack(ack)_ibi() and change return
type to int to indicate wait done timeout.

Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master/svc-i3c-master.c | 29 +++++++++++++++++++++++------
 1 file changed, 23 insertions(+), 6 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index fbb6cef405577..0de95f406c95b 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -384,10 +384,12 @@ static int svc_i3c_master_handle_ibi(struct svc_i3c_master *master,
 	return 0;
 }
 
-static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master,
+static int svc_i3c_master_ack_ibi(struct svc_i3c_master *master,
 				   bool mandatory_byte)
 {
 	unsigned int ibi_ack_nack;
+	int ret;
+	u32 reg;
 
 	ibi_ack_nack = SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK;
 	if (mandatory_byte)
@@ -396,18 +398,31 @@ static void svc_i3c_master_ack_ibi(struct svc_i3c_master *master,
 		ibi_ack_nack |= SVC_I3C_MCTRL_IBIRESP_ACK_WITHOUT_BYTE;
 
 	writel(ibi_ack_nack, master->regs + SVC_I3C_MCTRL);
+
+	ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg,
+					SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000);
+	return ret;
+
 }
 
-static void svc_i3c_master_nack_ibi(struct svc_i3c_master *master)
+static int svc_i3c_master_nack_ibi(struct svc_i3c_master *master)
 {
+	int ret;
+	u32 reg;
+
 	writel(SVC_I3C_MCTRL_REQUEST_IBI_ACKNACK |
 	       SVC_I3C_MCTRL_IBIRESP_NACK,
 	       master->regs + SVC_I3C_MCTRL);
+
+	ret = readl_poll_timeout_atomic(master->regs + SVC_I3C_MSTATUS, reg,
+					SVC_I3C_MSTATUS_MCTRLDONE(reg), 1, 1000);
+	return ret;
 }
 
 static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 mstatus)
 {
 	u32 ibitype;
+	int ret = 0;
 
 	ibitype = SVC_I3C_MSTATUS_IBITYPE(mstatus);
 
@@ -417,10 +432,10 @@ static int svc_i3c_master_handle_ibi_won(struct svc_i3c_master *master, u32 msta
 	switch (ibitype) {
 	case SVC_I3C_MSTATUS_IBITYPE_HOT_JOIN:
 	case SVC_I3C_MSTATUS_IBITYPE_MASTER_REQUEST:
-		svc_i3c_master_nack_ibi(master);
+		ret = svc_i3c_master_nack_ibi(master);
 	}
 
-	return 0;
+	return ret;
 }
 
 static void svc_i3c_master_ibi_work(struct work_struct *work)
@@ -871,7 +886,8 @@ static int svc_i3c_master_do_daa_locked(struct svc_i3c_master *master,
 			if (ret)
 				break;
 		} else if (SVC_I3C_MSTATUS_IBIWON(reg)) {
-			svc_i3c_master_handle_ibi_won(master, reg);
+			if (svc_i3c_master_handle_ibi_won(master, reg))
+				break;
 			continue;
 		} else if (SVC_I3C_MSTATUS_MCTRLDONE(reg)) {
 			if (SVC_I3C_MSTATUS_STATE_IDLE(reg) &&
@@ -1145,7 +1161,8 @@ static int svc_i3c_master_xfer(struct svc_i3c_master *master,
 		 * start.
 		 */
 		if (SVC_I3C_MSTATUS_IBIWON(reg)) {
-			svc_i3c_master_handle_ibi_won(master, reg);
+			if (svc_i3c_master_handle_ibi_won(master, reg))
+				goto emit_stop;
 			continue;
 		}
 

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 11/11] i3c: master: svc: fix possible assignment of the same address to two devices
  2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
                   ` (9 preceding siblings ...)
  2024-08-13 15:15 ` [PATCH v2 10/11] i3c: master: svc: wait for Manual ACK/NACK Done before next step Frank Li
@ 2024-08-13 15:15 ` Frank Li
  10 siblings, 0 replies; 13+ messages in thread
From: Frank Li @ 2024-08-13 15:15 UTC (permalink / raw)
  To: Alexandre Belloni, Boris Brezillon, Parshuram Thombare,
	Greg Kroah-Hartman, Boris Brezillon, Arnd Bergmann, Miquel Raynal,
	Conor Culhane
  Cc: linux-i3c, linux-kernel, imx, Frank Li, stable

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")
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/i3c/master/svc-i3c-master.c | 7 ++-----
 1 file changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index 0de95f406c95b..f47e5f4af68c9 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1041,11 +1041,8 @@ 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;
-	}
+	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);

-- 
2.34.1


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 10/11] i3c: master: svc: wait for Manual ACK/NACK Done before next step
  2024-08-13 15:15 ` [PATCH v2 10/11] i3c: master: svc: wait for Manual ACK/NACK Done before next step Frank Li
@ 2024-08-19  5:15   ` Dan Carpenter
  0 siblings, 0 replies; 13+ messages in thread
From: Dan Carpenter @ 2024-08-19  5:15 UTC (permalink / raw)
  To: oe-kbuild, Frank Li, Alexandre Belloni, Boris Brezillon,
	Parshuram Thombare, Greg Kroah-Hartman, Arnd Bergmann,
	Miquel Raynal, Conor Culhane
  Cc: lkp, oe-kbuild-all, linux-i3c, linux-kernel, imx, Frank Li

Hi Frank,

kernel test robot noticed the following build warnings:

url:    https://github.com/intel-lab-lkp/linux/commits/Frank-Li/i3c-master-Remove-i3c_dev_disable_ibi_locked-olddev-on-device-hotjoin/20240814-234209
base:   41c196e567fb1ea97f68a2ffb7faab451cd90854
patch link:    https://lore.kernel.org/r/20240813-i3c_fix-v2-10-68fe4a050188%40nxp.com
patch subject: [PATCH v2 10/11] i3c: master: svc: wait for Manual ACK/NACK Done before next step
config: x86_64-randconfig-161-20240817 (https://download.01.org/0day-ci/archive/20240818/202408180012.ifcIOjgX-lkp@intel.com/config)
compiler: clang version 18.1.5 (https://github.com/llvm/llvm-project 617a15a9eac96088ae5e9134248d8236e34b91b1)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
| Closes: https://lore.kernel.org/r/202408180012.ifcIOjgX-lkp@intel.com/

New smatch warnings:
drivers/i3c/master/svc-i3c-master.c:1165 svc_i3c_master_xfer() warn: missing error code 'ret'

vim +/ret +1165 drivers/i3c/master/svc-i3c-master.c

dd3c52846d5954a Miquel Raynal 2021-01-21  1123  static int svc_i3c_master_xfer(struct svc_i3c_master *master,
dd3c52846d5954a Miquel Raynal 2021-01-21  1124  			       bool rnw, unsigned int xfer_type, u8 addr,
dd3c52846d5954a Miquel Raynal 2021-01-21  1125  			       u8 *in, const u8 *out, unsigned int xfer_len,
6fb61734a74eaa3 Frank Li      2023-12-01  1126  			       unsigned int *actual_len, bool continued)
dd3c52846d5954a Miquel Raynal 2021-01-21  1127  {
2d15862dfba6bf1 Frank Li      2024-06-03  1128  	int retry = 2;
dd3c52846d5954a Miquel Raynal 2021-01-21  1129  	u32 reg;
dd3c52846d5954a Miquel Raynal 2021-01-21  1130  	int ret;
dd3c52846d5954a Miquel Raynal 2021-01-21  1131  
5e5e3c92e748a6d Frank Li      2023-10-23  1132  	/* clean SVC_I3C_MINT_IBIWON w1c bits */
5e5e3c92e748a6d Frank Li      2023-10-23  1133  	writel(SVC_I3C_MINT_IBIWON, master->regs + SVC_I3C_MSTATUS);
5e5e3c92e748a6d Frank Li      2023-10-23  1134  
2d15862dfba6bf1 Frank Li      2024-06-03  1135  
2d15862dfba6bf1 Frank Li      2024-06-03  1136  	while (retry--) {
dd3c52846d5954a Miquel Raynal 2021-01-21  1137  		writel(SVC_I3C_MCTRL_REQUEST_START_ADDR |
dd3c52846d5954a Miquel Raynal 2021-01-21  1138  		       xfer_type |
dd3c52846d5954a Miquel Raynal 2021-01-21  1139  		       SVC_I3C_MCTRL_IBIRESP_NACK |
dd3c52846d5954a Miquel Raynal 2021-01-21  1140  		       SVC_I3C_MCTRL_DIR(rnw) |
dd3c52846d5954a Miquel Raynal 2021-01-21  1141  		       SVC_I3C_MCTRL_ADDR(addr) |
6fb61734a74eaa3 Frank Li      2023-12-01  1142  		       SVC_I3C_MCTRL_RDTERM(*actual_len),
dd3c52846d5954a Miquel Raynal 2021-01-21  1143  		       master->regs + SVC_I3C_MCTRL);
dd3c52846d5954a Miquel Raynal 2021-01-21  1144  
dd3c52846d5954a Miquel Raynal 2021-01-21  1145  		ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
dd3c52846d5954a Miquel Raynal 2021-01-21  1146  				 SVC_I3C_MSTATUS_MCTRLDONE(reg), 0, 1000);
dd3c52846d5954a Miquel Raynal 2021-01-21  1147  		if (ret)
dd3c52846d5954a Miquel Raynal 2021-01-21  1148  			goto emit_stop;
dd3c52846d5954a Miquel Raynal 2021-01-21  1149  
28a9dc69921b36a Frank Li      2024-08-13  1150  		/*
28a9dc69921b36a Frank Li      2024-08-13  1151  		 * According to I3C spec ver 1.1.1, 5.1.2.2.3 Consequence of Controller Starting a
28a9dc69921b36a Frank Li      2024-08-13  1152  		 * Frame with I3C Target Address.
28a9dc69921b36a Frank Li      2024-08-13  1153  		 *
28a9dc69921b36a Frank Li      2024-08-13  1154  		 * The I3C Controller normally should start a Frame, the Address may be arbitrated,
28a9dc69921b36a Frank Li      2024-08-13  1155  		 * and so the Controller shall monitor to see whether an In-Band Interrupt request,
28a9dc69921b36a Frank Li      2024-08-13  1156  		 * a Controller Role Request (i.e., Secondary Controller requests to become the
28a9dc69921b36a Frank Li      2024-08-13  1157  		 * Active Controller), or a Hot-Join Request has been made.
28a9dc69921b36a Frank Li      2024-08-13  1158  		 *
28a9dc69921b36a Frank Li      2024-08-13  1159  		 * If missed IBIWON check, the wrong data will be return. When IBIWON happen, issue
28a9dc69921b36a Frank Li      2024-08-13  1160  		 * repeat start. Address arbitrate only happen at START, never happen at REPEAT
28a9dc69921b36a Frank Li      2024-08-13  1161  		 * start.
28a9dc69921b36a Frank Li      2024-08-13  1162  		 */
28a9dc69921b36a Frank Li      2024-08-13  1163  		if (SVC_I3C_MSTATUS_IBIWON(reg)) {
4809f19e89760fb Frank Li      2024-08-13  1164  			if (svc_i3c_master_handle_ibi_won(master, reg))
4809f19e89760fb Frank Li      2024-08-13 @1165  				goto emit_stop;

Does this need an error code?

28a9dc69921b36a Frank Li      2024-08-13  1166  			continue;
28a9dc69921b36a Frank Li      2024-08-13  1167  		}
28a9dc69921b36a Frank Li      2024-08-13  1168  
49b472ebc61de3d Clark Wang    2023-05-17  1169  		if (readl(master->regs + SVC_I3C_MERRWARN) & SVC_I3C_MERRWARN_NACK) {
2d15862dfba6bf1 Frank Li      2024-06-03  1170  			/*
2d15862dfba6bf1 Frank Li      2024-06-03  1171  			 * According to I3C Spec 1.1.1, 11-Jun-2021, section: 5.1.2.2.3.
2d15862dfba6bf1 Frank Li      2024-06-03  1172  			 * If the Controller chooses to start an I3C Message with an I3C Dynamic
2d15862dfba6bf1 Frank Li      2024-06-03  1173  			 * Address, then special provisions shall be made because that same I3C
2d15862dfba6bf1 Frank Li      2024-06-03  1174  			 * Target may be initiating an IBI or a Controller Role Request. So, one of
2d15862dfba6bf1 Frank Li      2024-06-03  1175  			 * three things may happen: (skip 1, 2)
2d15862dfba6bf1 Frank Li      2024-06-03  1176  			 *
2d15862dfba6bf1 Frank Li      2024-06-03  1177  			 * 3. The Addresses match and the RnW bits also match, and so neither
2d15862dfba6bf1 Frank Li      2024-06-03  1178  			 * Controller nor Target will ACK since both are expecting the other side to
2d15862dfba6bf1 Frank Li      2024-06-03  1179  			 * provide ACK. As a result, each side might think it had "won" arbitration,
2d15862dfba6bf1 Frank Li      2024-06-03  1180  			 * but neither side would continue, as each would subsequently see that the
2d15862dfba6bf1 Frank Li      2024-06-03  1181  			 * other did not provide ACK.
2d15862dfba6bf1 Frank Li      2024-06-03  1182  			 * ...
2d15862dfba6bf1 Frank Li      2024-06-03  1183  			 * For either value of RnW: Due to the NACK, the Controller shall defer the
2d15862dfba6bf1 Frank Li      2024-06-03  1184  			 * Private Write or Private Read, and should typically transmit the Target
2d15862dfba6bf1 Frank Li      2024-06-03  1185  			 * Address again after a Repeated START (i.e., the next one or any one prior
2d15862dfba6bf1 Frank Li      2024-06-03  1186  			 * to a STOP in the Frame). Since the Address Header following a Repeated
2d15862dfba6bf1 Frank Li      2024-06-03  1187  			 * START is not arbitrated, the Controller will always win (see Section
2d15862dfba6bf1 Frank Li      2024-06-03  1188  			 * 5.1.2.2.4).
2d15862dfba6bf1 Frank Li      2024-06-03  1189  			 */
2d15862dfba6bf1 Frank Li      2024-06-03  1190  			if (retry && addr != 0x7e) {
2d15862dfba6bf1 Frank Li      2024-06-03  1191  				writel(SVC_I3C_MERRWARN_NACK, master->regs + SVC_I3C_MERRWARN);
2d15862dfba6bf1 Frank Li      2024-06-03  1192  			} else {
49b472ebc61de3d Clark Wang    2023-05-17  1193  				ret = -ENXIO;
6d1a19d34e2cc07 Frank Li      2023-12-01  1194  				*actual_len = 0;
49b472ebc61de3d Clark Wang    2023-05-17  1195  				goto emit_stop;
49b472ebc61de3d Clark Wang    2023-05-17  1196  			}
2d15862dfba6bf1 Frank Li      2024-06-03  1197  		} else {
2d15862dfba6bf1 Frank Li      2024-06-03  1198  			break;
2d15862dfba6bf1 Frank Li      2024-06-03  1199  		}
2d15862dfba6bf1 Frank Li      2024-06-03  1200  	}
49b472ebc61de3d Clark Wang    2023-05-17  1201  
dd3c52846d5954a Miquel Raynal 2021-01-21  1202  	if (rnw)
dd3c52846d5954a Miquel Raynal 2021-01-21  1203  		ret = svc_i3c_master_read(master, in, xfer_len);
dd3c52846d5954a Miquel Raynal 2021-01-21  1204  	else
dd3c52846d5954a Miquel Raynal 2021-01-21  1205  		ret = svc_i3c_master_write(master, out, xfer_len);
d5e512574dd2eb0 Clark Wang    2021-12-27  1206  	if (ret < 0)
dd3c52846d5954a Miquel Raynal 2021-01-21  1207  		goto emit_stop;
dd3c52846d5954a Miquel Raynal 2021-01-21  1208  
d5e512574dd2eb0 Clark Wang    2021-12-27  1209  	if (rnw)
6fb61734a74eaa3 Frank Li      2023-12-01  1210  		*actual_len = ret;
d5e512574dd2eb0 Clark Wang    2021-12-27  1211  
dd3c52846d5954a Miquel Raynal 2021-01-21  1212  	ret = readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
dd3c52846d5954a Miquel Raynal 2021-01-21  1213  				 SVC_I3C_MSTATUS_COMPLETE(reg), 0, 1000);
dd3c52846d5954a Miquel Raynal 2021-01-21  1214  	if (ret)
dd3c52846d5954a Miquel Raynal 2021-01-21  1215  		goto emit_stop;
dd3c52846d5954a Miquel Raynal 2021-01-21  1216  
d5e512574dd2eb0 Clark Wang    2021-12-27  1217  	writel(SVC_I3C_MINT_COMPLETE, master->regs + SVC_I3C_MSTATUS);
d5e512574dd2eb0 Clark Wang    2021-12-27  1218  
d5e512574dd2eb0 Clark Wang    2021-12-27  1219  	if (!continued) {
dd3c52846d5954a Miquel Raynal 2021-01-21  1220  		svc_i3c_master_emit_stop(master);
dd3c52846d5954a Miquel Raynal 2021-01-21  1221  
d5e512574dd2eb0 Clark Wang    2021-12-27  1222  		/* Wait idle if stop is sent. */
d5e512574dd2eb0 Clark Wang    2021-12-27  1223  		readl_poll_timeout(master->regs + SVC_I3C_MSTATUS, reg,
d5e512574dd2eb0 Clark Wang    2021-12-27  1224  				   SVC_I3C_MSTATUS_STATE_IDLE(reg), 0, 1000);
d5e512574dd2eb0 Clark Wang    2021-12-27  1225  	}
d5e512574dd2eb0 Clark Wang    2021-12-27  1226  
dd3c52846d5954a Miquel Raynal 2021-01-21  1227  	return 0;
dd3c52846d5954a Miquel Raynal 2021-01-21  1228  
dd3c52846d5954a Miquel Raynal 2021-01-21  1229  emit_stop:
dd3c52846d5954a Miquel Raynal 2021-01-21  1230  	svc_i3c_master_emit_stop(master);
dd3c52846d5954a Miquel Raynal 2021-01-21  1231  	svc_i3c_master_clear_merrwarn(master);
dd3c52846d5954a Miquel Raynal 2021-01-21  1232  
dd3c52846d5954a Miquel Raynal 2021-01-21  1233  	return ret;
dd3c52846d5954a Miquel Raynal 2021-01-21  1234  }

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki


-- 
linux-i3c mailing list
linux-i3c@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-i3c

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2024-08-25  1:18 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-13 15:14 [PATCH v2 00/11] i3c: master: some fix and improvemnt for hotjoin Frank Li
2024-08-13 15:14 ` [PATCH v2 01/11] i3c: master: Remove i3c_dev_disable_ibi_locked(olddev) on device hotjoin Frank Li
2024-08-13 15:15 ` [PATCH v2 02/11] i3c: master: Replace hard code 2 with macro I3C_ADDR_SLOT_BITS Frank Li
2024-08-13 15:15 ` [PATCH v2 03/11] i3c: master: Extend address status bit to 4 and add I3C_ADDR_SLOT_EXT_INIT Frank Li
2024-08-13 15:15 ` [PATCH v2 04/11] i3c: master: Fix dynamic address leak when 'assigned-address' is present Frank Li
2024-08-13 15:15 ` [PATCH v2 05/11] i3c: master: Fix miss free init_dyn_addr at i3c_master_put_i3c_addrs() Frank Li
2024-08-13 15:15 ` [PATCH v2 06/11] i3c: master: svc: use repeat start when IBI WIN happens Frank Li
2024-08-13 15:15 ` [PATCH v2 07/11] i3c: master: svc: manually emit NACK/ACK for hotjoin Frank Li
2024-08-13 15:15 ` [PATCH v2 08/11] i3c: master: svc: need check IBIWON for dynamtica address assign Frank Li
2024-08-13 15:15 ` [PATCH v2 09/11] i3c: master: svc: use spinlock_saveirq at svc_i3c_master_ibi_work() Frank Li
2024-08-13 15:15 ` [PATCH v2 10/11] i3c: master: svc: wait for Manual ACK/NACK Done before next step Frank Li
2024-08-19  5:15   ` Dan Carpenter
2024-08-13 15:15 ` [PATCH v2 11/11] i3c: master: svc: fix possible assignment of the same address to two devices Frank Li

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox