Linux-i3c Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH V2 0/8] i3c: Support IBI-based system wakeup
@ 2026-07-28 15:53 Adrian Hunter
  2026-07-28 15:53 ` [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration Adrian Hunter
                   ` (7 more replies)
  0 siblings, 8 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

Hi

Intel LPSS I3C controllers support up to two I3C busses and can wake the
system from an In-Band Interrupt (IBI) via a PCI PME.  Today that wakeup
capability lives only at the PCI function, with no way to express which
I3C device is actually responsible for waking the system, and no way for
user space to enable or disable wakeup on a per-device basis.

This series pushes the wakeup capability down to the individual I3C
devices and then aggregates the resulting wakeup state back up to the PCI
device.

An IBI-capable I3C device on a bus whose controller can wake the system
is marked as wakeup capable, so it can be managed through the standard
device wakeup framework (e.g. via power/wakeup in sysfs).  When such a
device is enabled for wakeup, a wakeup event is reported each time it
queues an IBI.

At suspend time, the mipi-i3c-hci PCI driver aggregates the wakeup
configuration of the I3C devices across its HCI instances (up to two I3C
busses) and enables PCI wakeup (PME) only when at least one attached I3C
device is enabled as a wakeup source and has IBI enabled.  This keeps
the PCI wakeup state in sync with the actual requirements of the devices
on the busses.

The series is organised as follows:

 - Patch 1 fixes a pre-existing recursive acquisition of the bus rwsem
   in i3c_master_register_new_i3c_devs().  The remaining patches add
   work to that same function, so the locking is corrected first.

 - Patches 2-5 add the generic I3C core support: an ibi_wakeup flag for
   controllers, marking IBI-capable devices as wakeup capable, reporting
   wakeup events on IBIs, a helper to query whether any device on a bus
   has both wakeup and IBI enabled, and a fix to reject IBI requests
   from devices that do not advertise IBI capability.

 - Patches 6-8 wire this up for the mipi-i3c-hci driver: propagate the
   aggregated I3C wakeup requirements to the PCI function, factor out
   i3c_hci_sysdev() for the shared device lookup, and advertise IBI
   wakeup capability when the underlying system device can wake the
   system.

Note, since the PCI wakeup state is now derived from the wakeup
configuration of the attached I3C devices, the PCI device's
power/wakeup sysfs attribute no longer provides independent wakeup
control.


Changes in V2:

    Dropped the RFC tag.

    i3c: master: Fix recursive locking during device registration
	New patch

    i3c: master: Support IBI-based wakeup capability
	Dropped the redundant #include <linux/pm_wakeup.h>.  That header
	must not be included directly, and linux/device.h, which is
	already included, provides device_set_wakeup_capable().

    i3c: master: Add helper to query bus wakeup requirements
	i3c_master_any_wakeup_enabled() now also requires the device to
	have IBI enabled, not just system wakeup enabled, so that a
	device with no active IBI request does not keep PCI PME enabled.
	desc->ibi_lock is taken while checking.  The commit message and
	kernel-doc are updated to match.

    Rebased onto i3c/next.


Adrian Hunter (8):
      i3c: master: Fix recursive locking during device registration
      i3c: master: Support IBI-based wakeup capability
      i3c: master: Report wakeup events for IBIs
      i3c: master: Add helper to query bus wakeup requirements
      i3c: master: Reject IBI requests from non-IBI-capable devices
      i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
      i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev()
      i3c: mipi-i3c-hci: Advertise IBI wakeup capability

 drivers/i3c/device.c                               |  8 ++-
 drivers/i3c/master.c                               | 84 +++++++++++++++++++---
 drivers/i3c/master/mipi-i3c-hci/core.c             | 15 ++++
 drivers/i3c/master/mipi-i3c-hci/dma.c              | 15 +---
 drivers/i3c/master/mipi-i3c-hci/hci.h              |  2 +
 drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c | 23 +++++-
 include/linux/i3c/master.h                         |  5 ++
 7 files changed, 123 insertions(+), 29 deletions(-)


Regards
Adrian

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

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

* [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 16:19   ` sashiko-bot
  2026-07-28 15:53 ` [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability Adrian Hunter
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

i3c_master_register_new_i3c_devs() registers newly discovered devices
while holding i3c_bus_normaluse_lock(), a down_read().  device_register()
can immediately probe the device, and probe callbacks typically invoke
I3C helpers that take i3c_bus_normaluse_lock() again, leading to a
recursive acquisition of the same rwsem.  rwsems do not support recursive
read locking and can deadlock when a writer is waiting.  See the
"Recursive read locks" section of Documentation/locking/lockdep-design.rst.

For example, with Intel LPSS I3C, LOCKDEP generates a WARNING like:
  # echo intel-lpss-i3c.0 > /sys/bus/platform/drivers/mipi-i3c-hci/unbind
  # echo intel-lpss-i3c.0 > /sys/bus/platform/drivers/mipi-i3c-hci/bind
  WARNING: possible recursive locking detected
  kworker/5:1/94 is trying to acquire lock:
  ffff88811c810d78 (&i3cbus->lock){++++}-{4:4}, at: i3c_device_match_id+0x45/0x370
  but task is already holding lock:
  ffff88811c810d78 (&i3cbus->lock){++++}-{4:4}, at: i3c_master_reg_work_fn+0x21/0x5f0

Fix this by separating device creation from device registration.
Populate desc->dev under the maintenance lock, collect the devices that
still need registration into a local list, then release the lock before
calling device_register().  Finally retake the lock and clean up any
devices that failed to register.

Use the maintenance lock rather than the normal-use lock while adding
device objects.  A write-side maintenance lock prevents readers from
observing a partially initialized desc->dev during initial device
population, or desc->dev disappearing if registration fails.

The local list requires a list node, so add a list node member to struct
i3c_device.

Fixes: 3a379bbcea0a ("i3c: Add core I3C infrastructure")
Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---


Changes in V2:

	New patch


 drivers/i3c/master.c       | 45 ++++++++++++++++++++++++++++----------
 include/linux/i3c/master.h |  2 ++
 2 files changed, 35 insertions(+), 12 deletions(-)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index fd3e79d10c84..874f6e11b296 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1973,12 +1973,21 @@ static int i3c_master_early_i3c_dev_add(struct i3c_master_controller *master,
 static void
 i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
 {
+	struct i3c_device *i3cdev, *tmp;
 	struct i3c_dev_desc *desc;
+	LIST_HEAD(i3c_unreg_devs);
 	int ret;
 
 	if (!master->init_done)
 		return;
 
+	i3c_bus_maintenance_lock(&master->bus);
+
+	if (master->shutting_down) {
+		i3c_bus_maintenance_unlock(&master->bus);
+		return;
+	}
+
 	i3c_bus_for_each_i3cdev(&master->bus, desc) {
 		if (desc->dev || !desc->info.dyn_addr || desc == master->this)
 			continue;
@@ -1999,25 +2008,37 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
 		if (desc->boardinfo)
 			desc->dev->dev.of_node = desc->boardinfo->of_node;
 
-		ret = device_register(&desc->dev->dev);
-		if (ret) {
-			dev_err(&master->dev,
-				"Failed to add I3C device (err = %d)\n", ret);
-			desc->dev->desc = NULL;
-			put_device(&desc->dev->dev);
-			desc->dev = NULL;
-		}
+		list_add_tail(&desc->dev->node, &i3c_unreg_devs);
+	}
+
+	i3c_bus_maintenance_unlock(&master->bus);
+
+	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
+		ret = device_register(&i3cdev->dev);
+		if (ret)
+			dev_err(&master->dev, "Failed to add I3C device (err = %d)\n", ret);
+		else
+			list_del_init(&i3cdev->node);
+	}
+
+	i3c_bus_maintenance_lock(&master->bus);
+
+	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
+		list_del(&i3cdev->node);
+		desc = i3cdev->desc;
+		i3cdev->desc = NULL;
+		put_device(&i3cdev->dev);
+		desc->dev = NULL;
 	}
+
+	i3c_bus_maintenance_unlock(&master->bus);
 }
 
 static void i3c_master_reg_work_fn(struct work_struct *work)
 {
 	struct i3c_master_controller *master = container_of(work, typeof(*master), reg_work);
 
-	i3c_bus_normaluse_lock(&master->bus);
-	if (!master->shutting_down)
-		i3c_master_register_new_i3c_devs(master);
-	i3c_bus_normaluse_unlock(&master->bus);
+	i3c_master_register_new_i3c_devs(master);
 }
 
 /**
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 4d2a68793324..fa1c98f0f5c1 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -228,6 +228,7 @@ struct i3c_dev_desc {
  *	  every time the I3C device is rediscovered with a different dynamic
  *	  address assigned
  * @bus: I3C bus this device is attached to
+ * @node: unregistered device list node
  *
  * I3C device object exposed to I3C device drivers. The takes care of linking
  * this object to the relevant &struct_i3c_dev_desc one.
@@ -238,6 +239,7 @@ struct i3c_device {
 	struct device dev;
 	struct i3c_dev_desc *desc;
 	struct i3c_bus *bus;
+	struct list_head node;
 };
 
 /*
-- 
2.53.0


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

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

* [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
  2026-07-28 15:53 ` [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 16:32   ` sashiko-bot
  2026-07-28 15:53 ` [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs Adrian Hunter
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

An I3C controller acts as a bus controller for one or more I3C devices.
If the controller can wake the system in response to an In-Band
Interrupt (IBI), then any device on that bus that is capable of
generating IBIs can potentially be used as a wakeup source.

Add an ibi_wakeup flag to struct i3c_master_controller so controller
drivers can advertise support for IBI-based wakeup.

If set, mark IBI-capable I3C devices as wakeup capable when they are
registered, allowing wakeup management through the standard device
wakeup framework.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
Reviewed-by: Frank Li <Frank.Li@nxp.com>
---


Changes in V2:

	Dropped the redundant #include <linux/pm_wakeup.h>.  That header
	must not be included directly, and linux/device.h, which is
	already included, provides device_set_wakeup_capable().


 drivers/i3c/master.c       | 7 +++++++
 include/linux/i3c/master.h | 2 ++
 2 files changed, 9 insertions(+)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 874f6e11b296..cf3345265ac0 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2008,6 +2008,13 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
 		if (desc->boardinfo)
 			desc->dev->dev.of_node = desc->boardinfo->of_node;
 
+		/*
+		 * In the case of IBI wakeup, any IBI-capable device can
+		 * wakeup.
+		 */
+		if (master->ibi_wakeup && (desc->info.bcr & I3C_BCR_IBI_REQ_CAP))
+			device_set_wakeup_capable(&desc->dev->dev, true);
+
 		list_add_tail(&desc->dev->node, &i3c_unreg_devs);
 	}
 
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index fa1c98f0f5c1..99f89fef7653 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -513,6 +513,7 @@ struct i3c_master_controller_ops {
  * @hotjoin: true if the master support hotjoin
  * @rpm_allowed: true if Runtime PM allowed
  * @rpm_ibi_allowed: true if IBI and Hot-Join allowed while runtime suspended
+ * @ibi_wakeup: IBI can wakeup the system
  * @shutting_down: set to true when master begins shutdown or unregister
  * @boardinfo.i3c: list of I3C  boardinfo objects
  * @boardinfo.i2c: list of I2C boardinfo objects
@@ -547,6 +548,7 @@ struct i3c_master_controller {
 	unsigned int hotjoin: 1;
 	unsigned int rpm_allowed: 1;
 	unsigned int rpm_ibi_allowed: 1;
+	unsigned int ibi_wakeup: 1;
 	bool shutting_down;
 	struct {
 		struct list_head i3c;
-- 
2.53.0


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

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

* [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
  2026-07-28 15:53 ` [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration Adrian Hunter
  2026-07-28 15:53 ` [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 16:47   ` sashiko-bot
  2026-07-28 15:53 ` [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements Adrian Hunter
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

An I3C device configured as a wakeup source can wake the system by
generating an In-Band Interrupt (IBI).

When an IBI is queued for processing, record a wakeup event for the
device if wakeup is enabled.  Use a 100 ms processing interval to give
the I3C device driver time to process the IBI.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---


Changes in V2:

	None


 drivers/i3c/master.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index cf3345265ac0..9d56ca08569a 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -3085,6 +3085,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
 	}
 }
 
+/* Approximate time for IBI handler to run */
+#define I3C_WAKEUP_PROCESSING_TIME_MS 100
+
 /**
  * i3c_master_queue_ibi() - Queue an IBI
  * @dev: the device this IBI is coming from
@@ -3098,6 +3101,9 @@ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
 	if (!dev->ibi || !slot)
 		return;
 
+	if (device_may_wakeup(&dev->dev->dev))
+		pm_wakeup_event(&dev->dev->dev, I3C_WAKEUP_PROCESSING_TIME_MS);
+
 	atomic_inc(&dev->ibi->pending_ibis);
 	queue_work(dev->ibi->wq, &slot->work);
 }
-- 
2.53.0


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

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

* [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
                   ` (2 preceding siblings ...)
  2026-07-28 15:53 ` [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 16:57   ` sashiko-bot
  2026-07-28 20:03   ` Frank Li
  2026-07-28 15:53 ` [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices Adrian Hunter
                   ` (3 subsequent siblings)
  7 siblings, 2 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

Add i3c_master_any_wakeup_enabled(), which iterates over the devices on
an I3C bus and reports whether any of them are enabled for system
wakeup and have IBI enabled.

Controller drivers can use this helper to determine whether wakeup
support must remain available while the system is suspended.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---


Changes in V2:

	i3c_master_any_wakeup_enabled() now also requires the device to
	have IBI enabled, not just system wakeup enabled, so that a
	device with no active IBI request does not keep PCI PME enabled.
	desc->ibi_lock is taken while checking.  The commit message and
	kernel-doc are updated to match.


 drivers/i3c/master.c       | 30 ++++++++++++++++++++++++++++++
 include/linux/i3c/master.h |  1 +
 2 files changed, 31 insertions(+)

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index 9d56ca08569a..dd49652425b4 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2048,6 +2048,36 @@ static void i3c_master_reg_work_fn(struct work_struct *work)
 	i3c_master_register_new_i3c_devs(master);
 }
 
+/**
+ * i3c_master_any_wakeup_enabled() - check if any device can wake the system
+ * @master: I3C master controller
+ *
+ * Iterate over devices on the bus and return true if any device has
+ * system wakeup enabled and IBI enabled.
+ *
+ * Return: true if any device may wake the system via IBI, false otherwise.
+ */
+bool i3c_master_any_wakeup_enabled(struct i3c_master_controller *master)
+{
+	struct i3c_dev_desc *desc;
+	bool wakeup = false;
+
+	i3c_bus_normaluse_lock(&master->bus);
+	i3c_bus_for_each_i3cdev(&master->bus, desc) {
+		if (!desc->dev || !device_may_wakeup(&desc->dev->dev))
+			continue;
+		guard(mutex)(&desc->ibi_lock);
+		if (desc->ibi && desc->ibi->enabled) {
+			wakeup = true;
+			break;
+		}
+	}
+	i3c_bus_normaluse_unlock(&master->bus);
+
+	return wakeup;
+}
+EXPORT_SYMBOL_GPL(i3c_master_any_wakeup_enabled);
+
 /**
  * i3c_master_dma_map_single() - Map buffer for single DMA transfer
  * @dev: device object of a device doing DMA
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 99f89fef7653..d8cdc7ff2459 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -748,6 +748,7 @@ void i3c_generic_ibi_recycle_slot(struct i3c_generic_ibi_pool *pool,
 				  struct i3c_ibi_slot *slot);
 
 void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot);
+bool i3c_master_any_wakeup_enabled(struct i3c_master_controller *master);
 
 struct i3c_ibi_slot *i3c_master_get_free_ibi_slot(struct i3c_dev_desc *dev);
 
-- 
2.53.0


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

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

* [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
                   ` (3 preceding siblings ...)
  2026-07-28 15:53 ` [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 17:06   ` sashiko-bot
  2026-07-28 20:05   ` Frank Li
  2026-07-28 15:53 ` [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI Adrian Hunter
                   ` (2 subsequent siblings)
  7 siblings, 2 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

i3c_device_request_ibi() does not verify that a device advertises IBI
support before attempting to set up IBI handling.

Add a check for I3C_BCR_IBI_REQ_CAP and fail with -EOPNOTSUPP when IBI
support is not reported by the device.  This keeps IBI setup consistent
with other IBI-related functionality, such as exposing wakeup capability
only for IBI-capable devices.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---


Changes in V2:

	None


 drivers/i3c/device.c | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
index 101eaa77de68..307ca6dc04ca 100644
--- a/drivers/i3c/device.c
+++ b/drivers/i3c/device.c
@@ -205,12 +205,14 @@ int i3c_device_request_ibi(struct i3c_device *dev,
 		return ret;
 
 	i3c_bus_normaluse_lock(dev->bus);
-	if (dev->desc) {
+	if (!dev->desc) {
+		ret = -ENOENT;
+	} else if (!(dev->desc->info.bcr & I3C_BCR_IBI_REQ_CAP)) {
+		ret = -EOPNOTSUPP;
+	} else {
 		mutex_lock(&dev->desc->ibi_lock);
 		ret = i3c_dev_request_ibi_locked(dev->desc, req);
 		mutex_unlock(&dev->desc->ibi_lock);
-	} else {
-		ret = -ENOENT;
 	}
 	i3c_bus_normaluse_unlock(dev->bus);
 
-- 
2.53.0


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

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

* [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
                   ` (4 preceding siblings ...)
  2026-07-28 15:53 ` [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 17:18   ` sashiko-bot
  2026-07-28 15:53 ` [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() Adrian Hunter
  2026-07-28 15:53 ` [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability Adrian Hunter
  7 siblings, 1 reply; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

Keep the PCI wakeup state aligned with the wakeup requirements of the
devices served by the controller(s).

The PCI function is the wakeup source for HCI instances exposed beneath
it.  However, wakeup is only needed when at least one attached I3C device
is enabled as a wakeup source.

During suspend, check whether any HCI instance has a wakeup-enabled I3C
device and enable wakeup for the PCI function only in that case.
Otherwise leave PCI wakeup disabled.

Note, the suspend callback is used for both system and runtime suspend.
Although this change may update the PCI wakeup state during runtime
suspend, it does so only when the required wakeup state changes.
Moreover, PCI wakeup-capable devices already have PME wakeup armed for
runtime suspend, so changing the wakeup-enabled state does not affect
runtime PM wakeup behavior.

Note also, since the PCI wakeup state is derived from the wakeup
configuration of the attached I3C devices, the PCI device power/wakeup
sysfs attribute no longer provides independent wakeup control.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---


Changes in V2:

	None


 .../master/mipi-i3c-hci/mipi-i3c-hci-pci.c    | 23 +++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
index 5a9e2a43eff8..2b3bf6fa74f2 100644
--- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
+++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
@@ -265,6 +265,8 @@ static bool mipi_i3c_hci_pci_is_operational(struct device *dev, bool update)
 struct mipi_i3c_hci_pci_pm_data {
 	struct device *dev[INST_MAX];
 	int dev_cnt;
+	bool can_wakeup;
+	bool may_wakeup;
 };
 
 static bool mipi_i3c_hci_pci_is_mfd(struct device *dev)
@@ -272,6 +274,13 @@ static bool mipi_i3c_hci_pci_is_mfd(struct device *dev)
 	return dev_is_platform(dev) && mfd_get_cell(to_platform_device(dev));
 }
 
+static bool mipi_i3c_hci_pci_any_wakeup_enabled(struct device *dev)
+{
+	struct i3c_hci *hci = dev_get_drvdata(dev);
+
+	return i3c_master_any_wakeup_enabled(&hci->master);
+}
+
 static int mipi_i3c_hci_pci_suspend_instance(struct device *dev, void *data)
 {
 	struct mipi_i3c_hci_pci_pm_data *pm_data = data;
@@ -287,6 +296,9 @@ static int mipi_i3c_hci_pci_suspend_instance(struct device *dev, void *data)
 
 	pm_data->dev[pm_data->dev_cnt++] = dev;
 
+	if (pm_data->can_wakeup && mipi_i3c_hci_pci_any_wakeup_enabled(dev))
+		pm_data->may_wakeup = true;
+
 	return 0;
 }
 
@@ -317,12 +329,19 @@ static int mipi_i3c_hci_pci_suspend(struct device *dev)
 	if (!hci->info->control_instance_pm)
 		return 0;
 
+	pm_data.can_wakeup = device_can_wakeup(dev);
+
 	ret = device_for_each_child_reverse(dev, &pm_data, mipi_i3c_hci_pci_suspend_instance);
-	if (ret)
+	if (ret) {
 		for (int i = 0; i < pm_data.dev_cnt; i++)
 			i3c_hci_rpm_resume(pm_data.dev[i]);
+		return ret;
+	}
 
-	return ret;
+	if (device_may_wakeup(dev) != pm_data.may_wakeup)
+		device_set_wakeup_enable(dev, pm_data.may_wakeup);
+
+	return 0;
 }
 
 static int mipi_i3c_hci_pci_resume(struct device *dev)
-- 
2.53.0


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

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

* [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev()
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
                   ` (5 preceding siblings ...)
  2026-07-28 15:53 ` [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 17:22   ` sashiko-bot
  2026-07-28 20:10   ` Frank Li
  2026-07-28 15:53 ` [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability Adrian Hunter
  7 siblings, 2 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

The MIPI I3C HCI driver needs to identify the underlying system device
used for DMA mapping and PM operations. The logic for determining that
device is currently embedded in the DMA implementation.

Factor this code out into i3c_hci_sysdev() so it can be shared by other
parts of the driver and keep the device-selection logic in one place.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---


Changes in V2:

	None


 drivers/i3c/master/mipi-i3c-hci/core.c | 12 ++++++++++++
 drivers/i3c/master/mipi-i3c-hci/dma.c  | 15 +--------------
 drivers/i3c/master/mipi-i3c-hci/hci.h  |  2 ++
 3 files changed, 15 insertions(+), 14 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index cfe9b5390b56..0212c9e984cf 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/iopoll.h>
 #include <linux/module.h>
+#include <linux/pci.h>
 #include <linux/platform_data/mipi-i3c-hci.h>
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
@@ -117,6 +118,17 @@ static inline struct i3c_hci *to_i3c_hci(struct i3c_master_controller *m)
 	return container_of(m, struct i3c_hci, master);
 }
 
+/*
+ * Determine the device that does PM / DMA and has IOMMU setup done for it in
+ * case of enabled IOMMU (for use with the DMA API).
+ * Such device is either "mipi-i3c-hci" platform device (OF/ACPI enumeration)
+ * parent or grandparent (PCI enumeration).
+ */
+struct device *i3c_hci_sysdev(struct device *dev)
+{
+	return dev->parent && dev_is_pci(dev->parent) ? dev->parent : dev;
+}
+
 static void i3c_hci_set_master_dyn_addr(struct i3c_hci *hci)
 {
 	reg_write(MASTER_DEVICE_ADDR,
diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
index 0672ed1132f8..7c2b20474130 100644
--- a/drivers/i3c/master/mipi-i3c-hci/dma.c
+++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
@@ -15,7 +15,6 @@
 #include <linux/errno.h>
 #include <linux/i3c/master.h>
 #include <linux/io.h>
-#include <linux/pci.h>
 
 #include "hci.h"
 #include "cmd.h"
@@ -301,23 +300,11 @@ static int hci_dma_init(struct i3c_hci *hci)
 {
 	struct hci_rings_data *rings;
 	struct hci_rh_data *rh;
-	struct device *sysdev;
 	u32 regval;
 	unsigned int i, nr_rings, xfers_sz, resps_sz;
 	unsigned int ibi_status_ring_sz, ibi_data_ring_sz;
 	int ret;
 
-	/*
-	 * Set pointer to a physical device that does DMA and has IOMMU setup
-	 * done for it in case of enabled IOMMU and use it with the DMA API.
-	 * Here such device is either
-	 * "mipi-i3c-hci" platform device (OF/ACPI enumeration) parent or
-	 * grandparent (PCI enumeration).
-	 */
-	sysdev = hci->master.dev.parent;
-	if (sysdev->parent && dev_is_pci(sysdev->parent))
-		sysdev = sysdev->parent;
-
 	regval = rhs_reg_read(CONTROL);
 	nr_rings = FIELD_GET(MAX_HEADER_COUNT_CAP, regval);
 	dev_dbg(&hci->master.dev, "%d DMA rings available\n", nr_rings);
@@ -332,7 +319,7 @@ static int hci_dma_init(struct i3c_hci *hci)
 		return -ENOMEM;
 	hci->io_data = rings;
 	rings->total = nr_rings;
-	rings->sysdev = sysdev;
+	rings->sysdev = i3c_hci_sysdev(hci->master.dev.parent);
 
 	for (i = 0; i < rings->total; i++) {
 		u32 offset = rhs_reg_read(RHn_OFFSET(i));
diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
index b3d9803b1968..b8d2a3d680f8 100644
--- a/drivers/i3c/master/mipi-i3c-hci/hci.h
+++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
@@ -184,6 +184,8 @@ void amd_set_resp_buf_thld(struct i3c_hci *hci);
 void i3c_hci_sync_irq_inactive(struct i3c_hci *hci);
 int i3c_hci_process_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n);
 
+struct device *i3c_hci_sysdev(struct device *dev);
+
 #define DEFAULT_AUTOSUSPEND_DELAY_MS 1000
 
 int i3c_hci_rpm_suspend(struct device *dev);
-- 
2.53.0


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

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

* [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability
  2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
                   ` (6 preceding siblings ...)
  2026-07-28 15:53 ` [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() Adrian Hunter
@ 2026-07-28 15:53 ` Adrian Hunter
  2026-07-28 17:25   ` sashiko-bot
  2026-07-28 20:12   ` Frank Li
  7 siblings, 2 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-28 15:53 UTC (permalink / raw)
  To: alexandre.belloni
  Cc: Frank.Li, rafael, linux-i3c, linux-kernel, linux-pci, linux-pm

Set master->ibi_wakeup during probe when the associated system device
advertises wakeup capability, allowing the I3C core to mark IBI-capable
I3C devices as wakeup capable.

Tweak the comment for i3c_hci_sysdev() to mention the new usage.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---


Changes in V2:

	None


 drivers/i3c/master/mipi-i3c-hci/core.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index 0212c9e984cf..5d92cf0645ef 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -120,9 +120,9 @@ static inline struct i3c_hci *to_i3c_hci(struct i3c_master_controller *m)
 
 /*
  * Determine the device that does PM / DMA and has IOMMU setup done for it in
- * case of enabled IOMMU (for use with the DMA API).
- * Such device is either "mipi-i3c-hci" platform device (OF/ACPI enumeration)
- * parent or grandparent (PCI enumeration).
+ * case of enabled IOMMU (for use with the DMA API). It is also used to check
+ * for wakeup capability. Such device is either "mipi-i3c-hci" platform device
+ * (OF/ACPI enumeration) parent or grandparent (PCI enumeration).
  */
 struct device *i3c_hci_sysdev(struct device *dev)
 {
@@ -1176,6 +1176,9 @@ static int i3c_hci_probe(struct platform_device *pdev)
 	if (hci->quirks & HCI_QUIRK_RPM_IBI_ALLOWED)
 		hci->master.rpm_ibi_allowed = true;
 
+	if (device_can_wakeup(i3c_hci_sysdev(&pdev->dev)))
+		hci->master.ibi_wakeup = true;
+
 	return i3c_master_register(&hci->master, &pdev->dev, &i3c_hci_ops, false);
 }
 
-- 
2.53.0


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

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

* Re: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration
  2026-07-28 15:53 ` [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration Adrian Hunter
@ 2026-07-28 16:19   ` sashiko-bot
  2026-07-28 19:56     ` Frank Li
  0 siblings, 1 reply; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 16:19 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: Frank.Li, linux-pci, linux-i3c, Alexandre Belloni

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [High] Dropping the bus maintenance lock around device_register() exposes i3c_device_uevent() and driver probe functions to a Use-After-Free if a concurrent DAA replaces the device.

Pre-existing issues:
- [High] i3c_device_uevent() leaks uninitialized stack memory to userspace when i3cdev->desc is NULL.
--

--- Patch [1]: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration ---
commit 33a4dcd6c5626faef95bc7cd02ec4c56c6710c78
Author: Adrian Hunter <adrian.hunter@intel.com>

i3c: master: Fix recursive locking during device registration

This commit separates device creation from registration to fix a recursive
locking issue. It drops the bus maintenance lock around device_register()
to prevent deadlocks when probe callbacks invoke I3C helpers.

diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index fd3e79d10c840..874f6e11b296d 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
[ ... ]
> @@ -1999,25 +2008,37 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
>  		if (desc->boardinfo)
>  			desc->dev->dev.of_node = desc->boardinfo->of_node;
>  
> -		ret = device_register(&desc->dev->dev);
> -		if (ret) {
> -			dev_err(&master->dev,
> -				"Failed to add I3C device (err = %d)\n", ret);
> -			desc->dev->desc = NULL;
> -			put_device(&desc->dev->dev);
> -			desc->dev = NULL;
> -		}
> +		list_add_tail(&desc->dev->node, &i3c_unreg_devs);
> +	}
> +
> +	i3c_bus_maintenance_unlock(&master->bus);
> +
> +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
> +		ret = device_register(&i3cdev->dev);

[Severity: High]
Does dropping the maintenance lock around device_register() expose
i3c_device_uevent() and driver probes to a use-after-free?

If a concurrent I3C hot-join event or a sysfs write to do_daa occurs while
device_register() is running without the lock,
__i3c_master_add_i3c_dev_locked() could find a duplicate PID:

__i3c_master_add_i3c_dev_locked() {
        olddev = i3c_master_search_i3c_dev_duplicate(newdev);
        if (olddev) {
                newdev->dev = olddev->dev;
                if (newdev->dev)
                        newdev->dev->desc = newdev;
                ...
                i3c_master_detach_i3c_dev(olddev);
                i3c_master_free_i3c_dev(olddev);
        }
}

Meanwhile, device_register() triggers a KOBJ_ADD uevent. i3c_device_uevent()
reads i3cdev->desc locklessly:

i3c_device_uevent() {
        if (i3cdev->desc)
                devinfo = i3cdev->desc->info;
}

Could this lead to i3c_device_uevent() or driver probe functions dereferencing
the old descriptor while it is being freed?

> +		if (ret)
> +			dev_err(&master->dev, "Failed to add I3C device (err = %d)\n", ret);
> +		else
> +			list_del_init(&i3cdev->node);
> +	}
> +
> +	i3c_bus_maintenance_lock(&master->bus);
> +
> +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
> +		list_del(&i3cdev->node);
> +		desc = i3cdev->desc;
> +		i3cdev->desc = NULL;

[Severity: High]
This is a pre-existing issue, but does setting i3cdev->desc to NULL before
unregistration or cleanup lead to leaking uninitialized stack memory in
i3c_device_uevent()?

When a device is unregistered (or if registration fails and triggers a uevent),
i3cdev->desc is set to NULL. This bypasses the initialization of devinfo
in i3c_device_uevent():

i3c_device_uevent() {
        struct i3c_device_info devinfo;
        u16 manuf, part, ext;

        if (i3cdev->desc)
                devinfo = i3cdev->desc->info;

        manuf = I3C_PID_MANUF_ID(devinfo.pid);
        ...
        return add_uevent_var(env, "MODALIAS=i3c:dcr%02Xmanuf%04X",
                              devinfo.dcr, manuf);
}

Since devinfo is uninitialized on the stack when desc is NULL, could this
broadcast uninitialized kernel stack data to userspace processes listening
to netlink uevents?

> +		put_device(&i3cdev->dev);
> +		desc->dev = NULL;
>  	}
> +
> +	i3c_bus_maintenance_unlock(&master->bus);
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=1

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

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

* Re: [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability
  2026-07-28 15:53 ` [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability Adrian Hunter
@ 2026-07-28 16:32   ` sashiko-bot
  0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 16:32 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-i3c, Frank.Li, linux-pci, Alexandre Belloni

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Missing `of_node_get()` when assigning `boardinfo->of_node` to the device, causing reference count corruption when the device is released.
--

--- Patch [2]: [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability ---
commit a4a974dcadbb70afc57836a361635db60b65ebde
Author: Adrian Hunter <adrian.hunter@intel.com>

i3c: master: Support IBI-based wakeup capability

This commit adds an ibi_wakeup flag to struct i3c_master_controller to
allow controller drivers to advertise support for IBI-based wakeup. It also
marks IBI-capable I3C devices as wakeup capable during registration.

> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index 874f6e11b296d..cf3345265ac0b 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2008,6 +2008,13 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
>  		if (desc->boardinfo)
>  			desc->dev->dev.of_node = desc->boardinfo->of_node;

[Severity: High]
This is a pre-existing issue, but does this assignment miss an
of_node_get()?

It looks like boardinfo->of_node holds a reference count acquired in
of_i3c_master_add_i3c_boardinfo():

    boardinfo->of_node = of_node_get(node);

However, when this pointer is copied to desc->dev->dev.of_node here, the
reference count is not incremented. Later, when the device is released,
i3c_device_release() unconditionally drops a reference:

    of_node_put(i3cdev->dev.of_node);

If the device registration fails or if it is later unregistered (e.g., due
to a hot-remove event), this would drain the reference conceptually owned
by boardinfo. 

If the device is then recreated during a subsequent hot-join, could
boardinfo reassign the now-freed of_node pointer and cause a use-after-free
and double-free on the next release?

>  
> +		/*
> +		 * In the case of IBI wakeup, any IBI-capable device can
> +		 * wakeup.
> +		 */
> +		if (master->ibi_wakeup && (desc->info.bcr & I3C_BCR_IBI_REQ_CAP))
> +			device_set_wakeup_capable(&desc->dev->dev, true);
> +
>  		list_add_tail(&desc->dev->node, &i3c_unreg_devs);
>  	}
>

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=2

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

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

* Re: [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs
  2026-07-28 15:53 ` [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs Adrian Hunter
@ 2026-07-28 16:47   ` sashiko-bot
  0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 16:47 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-pci, Alexandre Belloni, linux-i3c, Frank.Li

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:

New issues:
- [High] Concurrent execution of `i3c_master_queue_ibi()` and device unregistration leads to a NULL pointer dereference or Use-After-Free on `dev->dev`.

Pre-existing issues:
- [High] Concurrently accessing `dev->ibi` and its workqueue without synchronization leads to Use-After-Free.
--

--- Patch [3]: [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs ---
commit 1c61ec6aa53c785eceea38530075c6fa6b7794f2
Author: Adrian Hunter <adrian.hunter@intel.com>

i3c: master: Report wakeup events for IBIs

This commit records a wakeup event using pm_wakeup_event() when an
In-Band Interrupt (IBI) is queued for processing and the device has
wakeup enabled. It uses a 100 ms processing interval.

> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index cf3345265ac0b..9d56ca08569a1 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c

[ ... ]

> @@ -3098,6 +3101,9 @@ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
>  	if (!dev->ibi || !slot)
>  		return;
>  
> +	if (device_may_wakeup(&dev->dev->dev))
> +		pm_wakeup_event(&dev->dev->dev, I3C_WAKEUP_PROCESSING_TIME_MS);
> +

[Severity: High]
Does this introduce a regression where a race condition with device
unregistration could lead to a NULL pointer dereference or use-after-free
on dev->dev?

If an IBI fires and i3c_master_queue_ibi() executes concurrently with
device unregistration (for example, during driver module removal or
hot-unplug), i3c_master_unregister_i3c_devs() can free dev->dev and set it
to NULL:

drivers/i3c/master.c:i3c_master_unregister_i3c_devs() {
	...
		if (device_is_registered(&i3cdev->dev->dev))
			device_unregister(&i3cdev->dev->dev);
		else
			put_device(&i3cdev->dev->dev);
		i3cdev->dev = NULL;
	...
}

If i3c_master_queue_ibi() passes the lockless if (!dev->ibi) check just
before the unregistration runs, could the subsequent call to
device_may_wakeup() dereference a freed or NULL pointer?


>  	atomic_inc(&dev->ibi->pending_ibis);
>  	queue_work(dev->ibi->wq, &slot->work);
>  }

[Severity: High]
This is a pre-existing issue, but can accessing dev->ibi and its workqueue
here race with IBI teardown and cause a use-after-free?

If i3c_master_queue_ibi() passes the if (!dev->ibi) check, and concurrently
the driver is unbound, i3c_dev_free_ibi_locked() will destroy the workqueue
and free dev->ibi:

drivers/i3c/master.c:i3c_dev_free_ibi_locked() {
	...
	if (dev->ibi->wq) {
		destroy_workqueue(dev->ibi->wq);
		dev->ibi->wq = NULL;
	}

	kfree(dev->ibi);
	dev->ibi = NULL;
	...
}

Could the interrupt handler then continue execution and call atomic_inc()
and queue_work() using the recently freed dev->ibi struct and destroyed
workqueue?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=3

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

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

* Re: [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements
  2026-07-28 15:53 ` [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements Adrian Hunter
@ 2026-07-28 16:57   ` sashiko-bot
  2026-07-28 20:03   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 16:57 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-pci, linux-i3c, Frank.Li, Alexandre Belloni

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Lockless access to other devices' `ibi` structures in `adi_i3c_master_disable_ibi()` leads to Use-After-Free.
--

--- Patch [4]: [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements ---
commit 26d68568db9401a6324a05672a046e8465035dde
Author: Adrian Hunter <adrian.hunter@intel.com>

i3c: master: Add helper to query bus wakeup requirements

Adds i3c_master_any_wakeup_enabled() to iterate over devices on an I3C
bus and report whether any are enabled for system wakeup and have ibi
enabled. Controller drivers can use this helper to determine whether
wakeup support must remain available while the system is suspended.

> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index 9d56ca08569a1..dd49652425b48 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c

[ ... ]

> @@ -2048,6 +2048,36 @@ static void i3c_master_reg_work_fn(struct work_struct *work)
>  	i3c_master_register_new_i3c_devs(master);
>  }
>  
> +/**
> + * i3c_master_any_wakeup_enabled() - check if any device can wake the system
> + * @master: I3C master controller
> + *
> + * Iterate over devices on the bus and return true if any device has
> + * system wakeup enabled and IBI enabled.
> + *
> + * Return: true if any device may wake the system via IBI, false otherwise.
> + */
> +bool i3c_master_any_wakeup_enabled(struct i3c_master_controller *master)
> +{
> +	struct i3c_dev_desc *desc;
> +	bool wakeup = false;
> +
> +	i3c_bus_normaluse_lock(&master->bus);
> +	i3c_bus_for_each_i3cdev(&master->bus, desc) {
> +		if (!desc->dev || !device_may_wakeup(&desc->dev->dev))
> +			continue;
> +		guard(mutex)(&desc->ibi_lock);

[Severity: High]
This is a pre-existing issue, but seeing the correct locking here in
i3c_master_any_wakeup_enabled() brings to mind a similar loop in
adi_i3c_master_disable_ibi() in drivers/i3c/master/adi-i3c-master.c.

Does that loop also need to hold the ibi_lock? It currently accesses
i3cdev->ibi of other devices on the bus without holding their respective
ibi_lock:

drivers/i3c/master/adi-i3c-master.c:adi_i3c_master_disable_ibi() {
    ...
    i3c_bus_for_each_i3cdev(&m->bus, i3cdev) {
        if (dev != i3cdev && i3cdev->ibi)
            enabled |= i3cdev->ibi->enabled;
    }
    ...
}

Could this lead to a use-after-free if another device's ibi resources are
concurrently freed? For example, if i3c_device_free_ibi() is called for
another device during concurrent unbinds, it takes the same bus read lock
but could free the ibi pointer while this loop is evaluating
i3cdev->ibi->enabled.

> +		if (desc->ibi && desc->ibi->enabled) {
> +			wakeup = true;
> +			break;
> +		}
> +	}
> +	i3c_bus_normaluse_unlock(&master->bus);
> +
> +	return wakeup;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=4

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

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

* Re: [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices
  2026-07-28 15:53 ` [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices Adrian Hunter
@ 2026-07-28 17:06   ` sashiko-bot
  2026-07-28 20:05   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 17:06 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-pci, Alexandre Belloni, linux-i3c, Frank.Li

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] Leaked workqueue in `i3c_dev_request_ibi_locked()` when `master->ops->request_ibi()` fails.
--

--- Patch [5]: [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices ---
commit d69e542b87c33e0789e410767b2ee354fe000c28
Author: Adrian Hunter <adrian.hunter@intel.com>
i3c: master: Reject IBI requests from non-IBI-capable devices

This commit adds a check in i3c_device_request_ibi() to ensure a device
reports IBI support before attempting to set up IBI handling. If the device
does not advertise I3C_BCR_IBI_REQ_CAP, it now fails with -EOPNOTSUPP.

> diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
> index 101eaa77de686..307ca6dc04ca0 100644
> --- a/drivers/i3c/device.c
> +++ b/drivers/i3c/device.c
> @@ -205,12 +205,14 @@ int i3c_device_request_ibi(struct i3c_device *dev,
>  		return ret;
>  
>  	i3c_bus_normaluse_lock(dev->bus);
> -	if (dev->desc) {
> +	if (!dev->desc) {
> +		ret = -ENOENT;
> +	} else if (!(dev->desc->info.bcr & I3C_BCR_IBI_REQ_CAP)) {
> +		ret = -EOPNOTSUPP;
> +	} else {
>  		mutex_lock(&dev->desc->ibi_lock);
>  		ret = i3c_dev_request_ibi_locked(dev->desc, req);

[Severity: High]
This is a pre-existing issue, but does i3c_dev_request_ibi_locked() leak the
allocated workqueue if the master's request_ibi callback fails?

Looking at i3c_dev_request_ibi_locked() in drivers/i3c/master.c:

	ibi->wq = alloc_ordered_workqueue(dev_name(i3cdev_to_dev(dev->dev)),
					  WQ_MEM_RECLAIM);
	if (!ibi->wq) {
		kfree(ibi);
		return -ENOMEM;
	}
	...
	ret = master->ops->request_ibi(dev, req);
	if (ret) {
		kfree(ibi);
		dev->ibi = NULL;
	}

If master->ops->request_ibi() returns an error, the error path frees ibi
but doesn't call destroy_workqueue(ibi->wq).

If a device probe repeatedly fails at this step, could this result in a
workqueue and memory leak?

>  		mutex_unlock(&dev->desc->ibi_lock);
> -	} else {
> -		ret = -ENOENT;
>  	}
>  	i3c_bus_normaluse_unlock(dev->bus);

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=5

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

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

* Re: [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
  2026-07-28 15:53 ` [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI Adrian Hunter
@ 2026-07-28 17:18   ` sashiko-bot
  0 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 17:18 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-pci, linux-i3c, Frank.Li, Alexandre Belloni

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

New issues:
- [High] Modifying device wakeup state dynamically during the suspend callback violates PM architecture, overrides sysfs UAPI, and triggers allocations and PM core warnings during system transitions.
- [Medium] The driver violates MFD architectural guidelines by dynamically allocating the `mfd_cell` array, calling MFD APIs outside `drivers/mfd/`, and the patch introduces a bespoke accessor that tightly couples parent and child drivers.

Pre-existing issues:
- [High] Unbound child devices cause a NULL pointer dereference and guaranteed kernel panic during the parent's suspend loop.
--

--- Patch [6]: [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI ---
commit bd9a09f1c602f19882ed3fc13b554af06b2d2298
Author: Adrian Hunter <adrian.hunter@intel.com>

i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI

This commit updates the PCI function's wakeup state based on the wakeup
requirements of the I3C devices attached to the HCI instances during suspend.
It checks if any attached device is enabled as a wakeup source and updates
the PCI device's wakeup capability accordingly.

> diff --git a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
> index 5a9e2a43eff8d..2b3bf6fa74f29 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/mipi-i3c-hci-pci.c
> @@ -272,6 +274,13 @@ static bool mipi_i3c_hci_pci_is_mfd(struct device *dev)
>  	return dev_is_platform(dev) && mfd_get_cell(to_platform_device(dev));
>  }
>  
> +static bool mipi_i3c_hci_pci_any_wakeup_enabled(struct device *dev)
> +{
> +	struct i3c_hci *hci = dev_get_drvdata(dev);
> +
> +	return i3c_master_any_wakeup_enabled(&hci->master);
> +}

[Severity: High]
This is a pre-existing issue, but does this code handle unbound child devices
safely?

If the child platform driver is unbound manually via sysfs, or if it fails
to probe, dev_get_drvdata() will return NULL. If the hardware bus was left
enabled, mipi_i3c_hci_pci_is_operational() can still return true. The parent's
suspend loop will then pass the device here, and to the existing
i3c_hci_rpm_suspend() function, where both will unconditionally dereference
the NULL pointer.

Could a check for a NULL hci pointer be added to prevent a kernel panic
during suspend?

[Severity: Medium]
Does this custom accessor bypass MFD architectural guidelines?

The MFD subsystem rules specify that parent drivers should not use custom
accessors to dig into the private driver data of child devices. Here, the
parent driver is directly extracting the child's internal state (&hci->master)
instead of using standard APIs.

Could this state propagation be handled through standard device PM wake
APIs rather than directly coupling the parent and child drivers?

[ ... ]

> @@ -317,12 +329,19 @@ static int mipi_i3c_hci_pci_suspend(struct device *dev)
>  	if (!hci->info->control_instance_pm)
>  		return 0;
>  
> +	pm_data.can_wakeup = device_can_wakeup(dev);
> +
>  	ret = device_for_each_child_reverse(dev, &pm_data, mipi_i3c_hci_pci_suspend_instance);
> -	if (ret)
> +	if (ret) {
>  		for (int i = 0; i < pm_data.dev_cnt; i++)
>  			i3c_hci_rpm_resume(pm_data.dev[i]);
> +		return ret;
> +	}
>  
> -	return ret;
> +	if (device_may_wakeup(dev) != pm_data.may_wakeup)
> +		device_set_wakeup_enable(dev, pm_data.may_wakeup);

[Severity: High]
Is it safe to call device_set_wakeup_enable() during the suspend execution
path?

Calling this function during a system suspend triggers memory allocations
via kzalloc(..., GFP_KERNEL) and registers sysfs nodes while the PM transition
is actively in progress. This triggers the PM core warning "Suspicious
device_wakeup_enable() during system transition!" and introduces memory
deadlock risks.

Additionally, does this unconditionally override the user's explicit PM policy
configured via the power/wakeup sysfs attribute?

> +
> +	return 0;
>  }

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=6

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

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

* Re: [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev()
  2026-07-28 15:53 ` [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() Adrian Hunter
@ 2026-07-28 17:22   ` sashiko-bot
  2026-07-28 20:10   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 17:22 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-i3c, Frank.Li, Alexandre Belloni, linux-pci

> The MIPI I3C HCI driver needs to identify the underlying system device
> used for DMA mapping and PM operations. The logic for determining that
> device is currently embedded in the DMA implementation.
> 
> Factor this code out into i3c_hci_sysdev() so it can be shared by other
> parts of the driver and keep the device-selection logic in one place.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=7


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

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

* Re: [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability
  2026-07-28 15:53 ` [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability Adrian Hunter
@ 2026-07-28 17:25   ` sashiko-bot
  2026-07-28 20:12   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-28 17:25 UTC (permalink / raw)
  To: Adrian Hunter; +Cc: linux-i3c, Alexandre Belloni, Frank.Li, linux-pci

> Set master->ibi_wakeup during probe when the associated system device
> advertises wakeup capability, allowing the I3C core to mark IBI-capable
> I3C devices as wakeup capable.
> 
> Tweak the comment for i3c_hci_sysdev() to mention the new usage.
> 
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>

Sashiko has reviewed this patch and found no issues. It looks great!

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=8


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

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

* Re: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration
  2026-07-28 16:19   ` sashiko-bot
@ 2026-07-28 19:56     ` Frank Li
  0 siblings, 0 replies; 22+ messages in thread
From: Frank Li @ 2026-07-28 19:56 UTC (permalink / raw)
  To: sashiko-reviews
  Cc: Adrian Hunter, Frank.Li, linux-pci, linux-i3c, Alexandre Belloni

On Tue, Jul 28, 2026 at 04:19:35PM +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> New issues:
> - [High] Dropping the bus maintenance lock around device_register() exposes i3c_device_uevent() and driver probe functions to a Use-After-Free if a concurrent DAA replaces the device.
>
> Pre-existing issues:
> - [High] i3c_device_uevent() leaks uninitialized stack memory to userspace when i3cdev->desc is NULL.
> --
>
> --- Patch [1]: [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration ---
> commit 33a4dcd6c5626faef95bc7cd02ec4c56c6710c78
> Author: Adrian Hunter <adrian.hunter@intel.com>
>
> i3c: master: Fix recursive locking during device registration
>
> This commit separates device creation from registration to fix a recursive
> locking issue. It drops the bus maintenance lock around device_register()
> to prevent deadlocks when probe callbacks invoke I3C helpers.
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index fd3e79d10c840..874f6e11b296d 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> [ ... ]
> > @@ -1999,25 +2008,37 @@ i3c_master_register_new_i3c_devs(struct i3c_master_controller *master)
> >  		if (desc->boardinfo)
> >  			desc->dev->dev.of_node = desc->boardinfo->of_node;
> >
> > -		ret = device_register(&desc->dev->dev);
> > -		if (ret) {
> > -			dev_err(&master->dev,
> > -				"Failed to add I3C device (err = %d)\n", ret);
> > -			desc->dev->desc = NULL;
> > -			put_device(&desc->dev->dev);
> > -			desc->dev = NULL;
> > -		}
> > +		list_add_tail(&desc->dev->node, &i3c_unreg_devs);
> > +	}
> > +
> > +	i3c_bus_maintenance_unlock(&master->bus);
> > +
> > +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
> > +		ret = device_register(&i3cdev->dev);
>
> [Severity: High]
> Does dropping the maintenance lock around device_register() expose
> i3c_device_uevent() and driver probes to a use-after-free?

look like make sense.

Frank

>
> If a concurrent I3C hot-join event or a sysfs write to do_daa occurs while
> device_register() is running without the lock,
> __i3c_master_add_i3c_dev_locked() could find a duplicate PID:
>
> __i3c_master_add_i3c_dev_locked() {
>         olddev = i3c_master_search_i3c_dev_duplicate(newdev);
>         if (olddev) {
>                 newdev->dev = olddev->dev;
>                 if (newdev->dev)
>                         newdev->dev->desc = newdev;
>                 ...
>                 i3c_master_detach_i3c_dev(olddev);
>                 i3c_master_free_i3c_dev(olddev);
>         }
> }
>
> Meanwhile, device_register() triggers a KOBJ_ADD uevent. i3c_device_uevent()
> reads i3cdev->desc locklessly:
>
> i3c_device_uevent() {
>         if (i3cdev->desc)
>                 devinfo = i3cdev->desc->info;
> }
>
> Could this lead to i3c_device_uevent() or driver probe functions dereferencing
> the old descriptor while it is being freed?
>
> > +		if (ret)
> > +			dev_err(&master->dev, "Failed to add I3C device (err = %d)\n", ret);
> > +		else
> > +			list_del_init(&i3cdev->node);
> > +	}
> > +
> > +	i3c_bus_maintenance_lock(&master->bus);
> > +
> > +	list_for_each_entry_safe(i3cdev, tmp, &i3c_unreg_devs, node) {
> > +		list_del(&i3cdev->node);
> > +		desc = i3cdev->desc;
> > +		i3cdev->desc = NULL;
>
> [Severity: High]
> This is a pre-existing issue, but does setting i3cdev->desc to NULL before
> unregistration or cleanup lead to leaking uninitialized stack memory in
> i3c_device_uevent()?
>
> When a device is unregistered (or if registration fails and triggers a uevent),
> i3cdev->desc is set to NULL. This bypasses the initialization of devinfo
> in i3c_device_uevent():
>
> i3c_device_uevent() {
>         struct i3c_device_info devinfo;
>         u16 manuf, part, ext;
>
>         if (i3cdev->desc)
>                 devinfo = i3cdev->desc->info;
>
>         manuf = I3C_PID_MANUF_ID(devinfo.pid);
>         ...
>         return add_uevent_var(env, "MODALIAS=i3c:dcr%02Xmanuf%04X",
>                               devinfo.dcr, manuf);
> }
>
> Since devinfo is uninitialized on the stack when desc is NULL, could this
> broadcast uninitialized kernel stack data to userspace processes listening
> to netlink uevents?
>
> > +		put_device(&i3cdev->dev);
> > +		desc->dev = NULL;
> >  	}
> > +
> > +	i3c_bus_maintenance_unlock(&master->bus);
> >  }
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260728155308.142713-1-adrian.hunter@intel.com?part=1

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

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

* Re: [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements
  2026-07-28 15:53 ` [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements Adrian Hunter
  2026-07-28 16:57   ` sashiko-bot
@ 2026-07-28 20:03   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: Frank Li @ 2026-07-28 20:03 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: alexandre.belloni, Frank.Li, rafael, linux-i3c, linux-kernel,
	linux-pci, linux-pm

On Tue, Jul 28, 2026 at 06:53:04PM +0300, Adrian Hunter wrote:
> Add i3c_master_any_wakeup_enabled(), which iterates over the devices on
> an I3C bus and reports whether any of them are enabled for system
> wakeup and have IBI enabled.
>
> Controller drivers can use this helper to determine whether wakeup
> support must remain available while the system is suspended.
>
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>
>
> Changes in V2:
>
> 	i3c_master_any_wakeup_enabled() now also requires the device to
> 	have IBI enabled, not just system wakeup enabled, so that a
> 	device with no active IBI request does not keep PCI PME enabled.
> 	desc->ibi_lock is taken while checking.  The commit message and
> 	kernel-doc are updated to match.
>
>
>  drivers/i3c/master.c       | 30 ++++++++++++++++++++++++++++++
>  include/linux/i3c/master.h |  1 +
>  2 files changed, 31 insertions(+)
>
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index 9d56ca08569a..dd49652425b4 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2048,6 +2048,36 @@ static void i3c_master_reg_work_fn(struct work_struct *work)
>  	i3c_master_register_new_i3c_devs(master);
>  }
>
> +/**
> + * i3c_master_any_wakeup_enabled() - check if any device can wake the system
> + * @master: I3C master controller
> + *
> + * Iterate over devices on the bus and return true if any device has
> + * system wakeup enabled and IBI enabled.
> + *
> + * Return: true if any device may wake the system via IBI, false otherwise.
> + */
> +bool i3c_master_any_wakeup_enabled(struct i3c_master_controller *master)
> +{

This check most like introdouce rise condition.

if (i3c_master_any_wakeup_enabled())
	do_some_thing()

no lock protection, so between check i3c_master_any_wakeup_enabled() and
do_some_thing(), condtion may be changed.

Frank

> +	struct i3c_dev_desc *desc;
> +	bool wakeup = false;
> +
> +	i3c_bus_normaluse_lock(&master->bus);
> +	i3c_bus_for_each_i3cdev(&master->bus, desc) {
> +		if (!desc->dev || !device_may_wakeup(&desc->dev->dev))
> +			continue;
> +		guard(mutex)(&desc->ibi_lock);
> +		if (desc->ibi && desc->ibi->enabled) {
> +			wakeup = true;
> +			break;
> +		}
> +	}
> +	i3c_bus_normaluse_unlock(&master->bus);
> +
> +	return wakeup;
> +}
> +EXPORT_SYMBOL_GPL(i3c_master_any_wakeup_enabled);
> +
>  /**
>   * i3c_master_dma_map_single() - Map buffer for single DMA transfer
>   * @dev: device object of a device doing DMA
> diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
> index 99f89fef7653..d8cdc7ff2459 100644
> --- a/include/linux/i3c/master.h
> +++ b/include/linux/i3c/master.h
> @@ -748,6 +748,7 @@ void i3c_generic_ibi_recycle_slot(struct i3c_generic_ibi_pool *pool,
>  				  struct i3c_ibi_slot *slot);
>
>  void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot);
> +bool i3c_master_any_wakeup_enabled(struct i3c_master_controller *master);
>
>  struct i3c_ibi_slot *i3c_master_get_free_ibi_slot(struct i3c_dev_desc *dev);
>
> --
> 2.53.0
>

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

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

* Re: [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices
  2026-07-28 15:53 ` [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices Adrian Hunter
  2026-07-28 17:06   ` sashiko-bot
@ 2026-07-28 20:05   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: Frank Li @ 2026-07-28 20:05 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: alexandre.belloni, Frank.Li, rafael, linux-i3c, linux-kernel,
	linux-pci, linux-pm

On Tue, Jul 28, 2026 at 06:53:05PM +0300, Adrian Hunter wrote:
> i3c_device_request_ibi() does not verify that a device advertises IBI
> support before attempting to set up IBI handling.
>
> Add a check for I3C_BCR_IBI_REQ_CAP and fail with -EOPNOTSUPP when IBI
> support is not reported by the device.  This keeps IBI setup consistent
> with other IBI-related functionality, such as exposing wakeup capability
> only for IBI-capable devices.
>
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>
>
> Changes in V2:
>
> 	None
>
>
>  drivers/i3c/device.c | 8 +++++---
>  1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/device.c b/drivers/i3c/device.c
> index 101eaa77de68..307ca6dc04ca 100644
> --- a/drivers/i3c/device.c
> +++ b/drivers/i3c/device.c
> @@ -205,12 +205,14 @@ int i3c_device_request_ibi(struct i3c_device *dev,
>  		return ret;
>
>  	i3c_bus_normaluse_lock(dev->bus);
> -	if (dev->desc) {
> +	if (!dev->desc) {
> +		ret = -ENOENT;
> +	} else if (!(dev->desc->info.bcr & I3C_BCR_IBI_REQ_CAP)) {
> +		ret = -EOPNOTSUPP;
> +	} else {
>  		mutex_lock(&dev->desc->ibi_lock);
>  		ret = i3c_dev_request_ibi_locked(dev->desc, req);
>  		mutex_unlock(&dev->desc->ibi_lock);
> -	} else {
> -		ret = -ENOENT;
>  	}
>  	i3c_bus_normaluse_unlock(dev->bus);
>
> --
> 2.53.0
>

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

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

* Re: [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev()
  2026-07-28 15:53 ` [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() Adrian Hunter
  2026-07-28 17:22   ` sashiko-bot
@ 2026-07-28 20:10   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: Frank Li @ 2026-07-28 20:10 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: alexandre.belloni, Frank.Li, rafael, linux-i3c, linux-kernel,
	linux-pci, linux-pm

On Tue, Jul 28, 2026 at 06:53:07PM +0300, Adrian Hunter wrote:
> The MIPI I3C HCI driver needs to identify the underlying system device
> used for DMA mapping and PM operations. The logic for determining that
> device is currently embedded in the DMA implementation.
>
> Factor this code out into i3c_hci_sysdev() so it can be shared by other
> parts of the driver and keep the device-selection logic in one place.
>
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---
>
>
> Changes in V2:
>
> 	None
>
>
>  drivers/i3c/master/mipi-i3c-hci/core.c | 12 ++++++++++++
>  drivers/i3c/master/mipi-i3c-hci/dma.c  | 15 +--------------
>  drivers/i3c/master/mipi-i3c-hci/hci.h  |  2 ++
>  3 files changed, 15 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index cfe9b5390b56..0212c9e984cf 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -15,6 +15,7 @@
>  #include <linux/interrupt.h>
>  #include <linux/iopoll.h>
>  #include <linux/module.h>
> +#include <linux/pci.h>
>  #include <linux/platform_data/mipi-i3c-hci.h>
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
> @@ -117,6 +118,17 @@ static inline struct i3c_hci *to_i3c_hci(struct i3c_master_controller *m)
>  	return container_of(m, struct i3c_hci, master);
>  }
>
> +/*
> + * Determine the device that does PM / DMA and has IOMMU setup done for it in
> + * case of enabled IOMMU (for use with the DMA API).
> + * Such device is either "mipi-i3c-hci" platform device (OF/ACPI enumeration)
> + * parent or grandparent (PCI enumeration).
> + */
> +struct device *i3c_hci_sysdev(struct device *dev)

Is it simpler if argument is struct i3c_hci *hci

Frank

> +{
> +	return dev->parent && dev_is_pci(dev->parent) ? dev->parent : dev;
> +}
> +
>  static void i3c_hci_set_master_dyn_addr(struct i3c_hci *hci)
>  {
>  	reg_write(MASTER_DEVICE_ADDR,
> diff --git a/drivers/i3c/master/mipi-i3c-hci/dma.c b/drivers/i3c/master/mipi-i3c-hci/dma.c
> index 0672ed1132f8..7c2b20474130 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/dma.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/dma.c
> @@ -15,7 +15,6 @@
>  #include <linux/errno.h>
>  #include <linux/i3c/master.h>
>  #include <linux/io.h>
> -#include <linux/pci.h>
>
>  #include "hci.h"
>  #include "cmd.h"
> @@ -301,23 +300,11 @@ static int hci_dma_init(struct i3c_hci *hci)
>  {
>  	struct hci_rings_data *rings;
>  	struct hci_rh_data *rh;
> -	struct device *sysdev;
>  	u32 regval;
>  	unsigned int i, nr_rings, xfers_sz, resps_sz;
>  	unsigned int ibi_status_ring_sz, ibi_data_ring_sz;
>  	int ret;
>
> -	/*
> -	 * Set pointer to a physical device that does DMA and has IOMMU setup
> -	 * done for it in case of enabled IOMMU and use it with the DMA API.
> -	 * Here such device is either
> -	 * "mipi-i3c-hci" platform device (OF/ACPI enumeration) parent or
> -	 * grandparent (PCI enumeration).
> -	 */
> -	sysdev = hci->master.dev.parent;
> -	if (sysdev->parent && dev_is_pci(sysdev->parent))
> -		sysdev = sysdev->parent;
> -
>  	regval = rhs_reg_read(CONTROL);
>  	nr_rings = FIELD_GET(MAX_HEADER_COUNT_CAP, regval);
>  	dev_dbg(&hci->master.dev, "%d DMA rings available\n", nr_rings);
> @@ -332,7 +319,7 @@ static int hci_dma_init(struct i3c_hci *hci)
>  		return -ENOMEM;
>  	hci->io_data = rings;
>  	rings->total = nr_rings;
> -	rings->sysdev = sysdev;
> +	rings->sysdev = i3c_hci_sysdev(hci->master.dev.parent);
>
>  	for (i = 0; i < rings->total; i++) {
>  		u32 offset = rhs_reg_read(RHn_OFFSET(i));
> diff --git a/drivers/i3c/master/mipi-i3c-hci/hci.h b/drivers/i3c/master/mipi-i3c-hci/hci.h
> index b3d9803b1968..b8d2a3d680f8 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/hci.h
> +++ b/drivers/i3c/master/mipi-i3c-hci/hci.h
> @@ -184,6 +184,8 @@ void amd_set_resp_buf_thld(struct i3c_hci *hci);
>  void i3c_hci_sync_irq_inactive(struct i3c_hci *hci);
>  int i3c_hci_process_xfer(struct i3c_hci *hci, struct hci_xfer *xfer, int n);
>
> +struct device *i3c_hci_sysdev(struct device *dev);
> +
>  #define DEFAULT_AUTOSUSPEND_DELAY_MS 1000
>
>  int i3c_hci_rpm_suspend(struct device *dev);
> --
> 2.53.0
>

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

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

* Re: [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability
  2026-07-28 15:53 ` [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability Adrian Hunter
  2026-07-28 17:25   ` sashiko-bot
@ 2026-07-28 20:12   ` Frank Li
  1 sibling, 0 replies; 22+ messages in thread
From: Frank Li @ 2026-07-28 20:12 UTC (permalink / raw)
  To: Adrian Hunter
  Cc: alexandre.belloni, Frank.Li, rafael, linux-i3c, linux-kernel,
	linux-pci, linux-pm

On Tue, Jul 28, 2026 at 06:53:08PM +0300, Adrian Hunter wrote:
> Set master->ibi_wakeup during probe when the associated system device
> advertises wakeup capability, allowing the I3C core to mark IBI-capable
> I3C devices as wakeup capable.
>
> Tweak the comment for i3c_hci_sysdev() to mention the new usage.
>
> Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
> ---

Reviewed-by: Frank Li <Frank.Li@nxp.com>

>
>
> Changes in V2:
>
> 	None
>
>
>  drivers/i3c/master/mipi-i3c-hci/core.c | 9 ++++++---
>  1 file changed, 6 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
> index 0212c9e984cf..5d92cf0645ef 100644
> --- a/drivers/i3c/master/mipi-i3c-hci/core.c
> +++ b/drivers/i3c/master/mipi-i3c-hci/core.c
> @@ -120,9 +120,9 @@ static inline struct i3c_hci *to_i3c_hci(struct i3c_master_controller *m)
>
>  /*
>   * Determine the device that does PM / DMA and has IOMMU setup done for it in
> - * case of enabled IOMMU (for use with the DMA API).
> - * Such device is either "mipi-i3c-hci" platform device (OF/ACPI enumeration)
> - * parent or grandparent (PCI enumeration).
> + * case of enabled IOMMU (for use with the DMA API). It is also used to check
> + * for wakeup capability. Such device is either "mipi-i3c-hci" platform device
> + * (OF/ACPI enumeration) parent or grandparent (PCI enumeration).
>   */
>  struct device *i3c_hci_sysdev(struct device *dev)
>  {
> @@ -1176,6 +1176,9 @@ static int i3c_hci_probe(struct platform_device *pdev)
>  	if (hci->quirks & HCI_QUIRK_RPM_IBI_ALLOWED)
>  		hci->master.rpm_ibi_allowed = true;
>
> +	if (device_can_wakeup(i3c_hci_sysdev(&pdev->dev)))
> +		hci->master.ibi_wakeup = true;
> +
>  	return i3c_master_register(&hci->master, &pdev->dev, &i3c_hci_ops, false);
>  }
>
> --
> 2.53.0
>

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

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

end of thread, other threads:[~2026-07-28 20:12 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-28 15:53 [PATCH V2 0/8] i3c: Support IBI-based system wakeup Adrian Hunter
2026-07-28 15:53 ` [PATCH V2 1/8] i3c: master: Fix recursive locking during device registration Adrian Hunter
2026-07-28 16:19   ` sashiko-bot
2026-07-28 19:56     ` Frank Li
2026-07-28 15:53 ` [PATCH V2 2/8] i3c: master: Support IBI-based wakeup capability Adrian Hunter
2026-07-28 16:32   ` sashiko-bot
2026-07-28 15:53 ` [PATCH V2 3/8] i3c: master: Report wakeup events for IBIs Adrian Hunter
2026-07-28 16:47   ` sashiko-bot
2026-07-28 15:53 ` [PATCH V2 4/8] i3c: master: Add helper to query bus wakeup requirements Adrian Hunter
2026-07-28 16:57   ` sashiko-bot
2026-07-28 20:03   ` Frank Li
2026-07-28 15:53 ` [PATCH V2 5/8] i3c: master: Reject IBI requests from non-IBI-capable devices Adrian Hunter
2026-07-28 17:06   ` sashiko-bot
2026-07-28 20:05   ` Frank Li
2026-07-28 15:53 ` [PATCH V2 6/8] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI Adrian Hunter
2026-07-28 17:18   ` sashiko-bot
2026-07-28 15:53 ` [PATCH V2 7/8] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() Adrian Hunter
2026-07-28 17:22   ` sashiko-bot
2026-07-28 20:10   ` Frank Li
2026-07-28 15:53 ` [PATCH V2 8/8] i3c: mipi-i3c-hci: Advertise IBI wakeup capability Adrian Hunter
2026-07-28 17:25   ` sashiko-bot
2026-07-28 20:12   ` Frank Li

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