* [PATCH RFC 0/7] i3c: Support IBI-based system wakeup
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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. This keeps the PCI wakeup state in
sync with the actual requirements of the devices on the busses.
The series is organised as follows:
- Patches 1-4 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 wakeup enabled, and a fix to reject IBI requests from devices that
do not advertise IBI capability.
- Patches 5-7 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.
Adrian Hunter (7):
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 | 41 ++++++++++++++++++++++
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 | 3 ++
7 files changed, 88 insertions(+), 19 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 RFC 0/7] i3c: Support IBI-based system wakeup
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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. This keeps the PCI wakeup state in
sync with the actual requirements of the devices on the busses.
The series is organised as follows:
- Patches 1-4 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 wakeup enabled, and a fix to reject IBI requests from devices that
do not advertise IBI capability.
- Patches 5-7 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.
Adrian Hunter (7):
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 | 41 ++++++++++++++++++++++
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 | 3 ++
7 files changed, 88 insertions(+), 19 deletions(-)
Regards
Adrian
^ permalink raw reply [flat|nested] 22+ messages in thread
* [PATCH RFC 1/7] i3c: master: Support IBI-based wakeup capability
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:05 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
drivers/i3c/master.c | 8 ++++++++
include/linux/i3c/master.h | 2 ++
2 files changed, 10 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index f1be38a640ca..a47e2924bb70 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_wakeup.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
@@ -1930,6 +1931,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);
+
ret = device_register(&desc->dev->dev);
if (ret) {
dev_err(&master->dev,
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 4d2a68793324..af3c35a8e7b6 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -511,6 +511,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
@@ -545,6 +546,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 RFC 1/7] i3c: master: Support IBI-based wakeup capability
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
drivers/i3c/master.c | 8 ++++++++
include/linux/i3c/master.h | 2 ++
2 files changed, 10 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index f1be38a640ca..a47e2924bb70 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -17,6 +17,7 @@
#include <linux/list.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
+#include <linux/pm_wakeup.h>
#include <linux/slab.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
@@ -1930,6 +1931,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);
+
ret = device_register(&desc->dev->dev);
if (ret) {
dev_err(&master->dev,
diff --git a/include/linux/i3c/master.h b/include/linux/i3c/master.h
index 4d2a68793324..af3c35a8e7b6 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -511,6 +511,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
@@ -545,6 +546,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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH RFC 2/7] i3c: master: Report wakeup events for IBIs
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:05 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
drivers/i3c/master.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index a47e2924bb70..a36f9b617cbf 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2994,6 +2994,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
@@ -3007,6 +3010,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 RFC 2/7] i3c: master: Report wakeup events for IBIs
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
drivers/i3c/master.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index a47e2924bb70..a36f9b617cbf 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -2994,6 +2994,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
@@ -3007,6 +3010,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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH RFC 3/7] i3c: master: Add helper to query bus wakeup requirements
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:05 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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.
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>
---
drivers/i3c/master.c | 27 +++++++++++++++++++++++++++
include/linux/i3c/master.h | 1 +
2 files changed, 28 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index a36f9b617cbf..979457e635bd 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1957,6 +1957,33 @@ static void i3c_master_reg_work_fn(struct work_struct *work)
i3c_bus_normaluse_unlock(&master->bus);
}
+/**
+ * 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.
+ *
+ * Return: true if any device may wake the system, 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)) {
+ 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 af3c35a8e7b6..b9f2d84ac276 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -746,6 +746,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 RFC 3/7] i3c: master: Add helper to query bus wakeup requirements
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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.
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>
---
drivers/i3c/master.c | 27 +++++++++++++++++++++++++++
include/linux/i3c/master.h | 1 +
2 files changed, 28 insertions(+)
diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
index a36f9b617cbf..979457e635bd 100644
--- a/drivers/i3c/master.c
+++ b/drivers/i3c/master.c
@@ -1957,6 +1957,33 @@ static void i3c_master_reg_work_fn(struct work_struct *work)
i3c_bus_normaluse_unlock(&master->bus);
}
+/**
+ * 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.
+ *
+ * Return: true if any device may wake the system, 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)) {
+ 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 af3c35a8e7b6..b9f2d84ac276 100644
--- a/include/linux/i3c/master.h
+++ b/include/linux/i3c/master.h
@@ -746,6 +746,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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH RFC 4/7] i3c: master: Reject IBI requests from non-IBI-capable devices
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:05 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
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 RFC 4/7] i3c: master: Reject IBI requests from non-IBI-capable devices
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH RFC 5/7] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:05 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
.../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 RFC 5/7] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
.../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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH RFC 6/7] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev()
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:05 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
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 e80aa1f5722e..4e17b1480362 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 RFC 6/7] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev()
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
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 e80aa1f5722e..4e17b1480362 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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* [PATCH RFC 7/7] i3c: mipi-i3c-hci: Advertise IBI wakeup capability
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:05 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
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 4e17b1480362..55724a986f90 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)
{
@@ -1175,6 +1175,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
* [PATCH RFC 7/7] i3c: mipi-i3c-hci: Advertise IBI wakeup capability
@ 2026-07-01 20:05 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:05 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>
---
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 4e17b1480362..55724a986f90 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)
{
@@ -1175,6 +1175,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
^ permalink raw reply related [flat|nested] 22+ messages in thread
* Re: [PATCH RFC 0/7] i3c: Support IBI-based system wakeup
2026-07-01 20:05 ` Adrian Hunter
@ 2026-07-01 20:15 ` Adrian Hunter
-1 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:15 UTC (permalink / raw)
To: alexandre.belloni; +Cc: Frank.Li, rafael, linux-i3c, linux-kernel
Please ignore this thread, since I managed to put the wrong
email addresses for linux-pm and linux-pci.
I have resent the patch set. Please reply to that instead.
--
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 RFC 0/7] i3c: Support IBI-based system wakeup
@ 2026-07-01 20:15 ` Adrian Hunter
0 siblings, 0 replies; 22+ messages in thread
From: Adrian Hunter @ 2026-07-01 20:15 UTC (permalink / raw)
To: alexandre.belloni; +Cc: Frank.Li, rafael, linux-i3c, linux-kernel
Please ignore this thread, since I managed to put the wrong
email addresses for linux-pm and linux-pci.
I have resent the patch set. Please reply to that instead.
^ permalink raw reply [flat|nested] 22+ messages in thread
* Re: [PATCH RFC 3/7] i3c: master: Add helper to query bus wakeup requirements
2026-07-01 20:05 ` Adrian Hunter
(?)
@ 2026-07-01 20:23 ` sashiko-bot
-1 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-01 20:23 UTC (permalink / raw)
To: Adrian Hunter; +Cc: Frank.Li, linux-i3c, Alexandre Belloni
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] `i3c_master_any_wakeup_enabled()` dereferences a dangling `desc->dev` pointer if a device previously failed to register.
- [High] Concurrent execution of `i3c_master_any_wakeup_enabled` and `i3c_master_reg_work_fn` creates a data race on `desc->dev` due to a shared read lock.
--
commit ed5405b56d89572a46136e7c93b53f6058fa4335
Author: Adrian Hunter <adrian.hunter@intel.com>
i3c: master: Add helper to query bus wakeup requirements
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.
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 a36f9b617cbf7..979457e635bd9 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -1957,6 +1957,33 @@ static void i3c_master_reg_work_fn(struct work_struct *work)
[ ... ]
> +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);
[Severity: High]
Can this race with i3c_master_reg_work_fn() and access uninitialized memory or
a freed pointer?
i3c_master_reg_work_fn() executes in a workqueue and calls
i3c_master_register_new_i3c_devs() while holding i3c_bus_normaluse_lock(),
which only acquires a read lock (down_read(&bus->lock)).
Inside i3c_master_register_new_i3c_devs(), desc->dev is allocated and mutated.
Since i3c_master_any_wakeup_enabled() also acquires the same read lock,
could it run concurrently (e.g. during runtime PM suspend) and read desc->dev
while it is being allocated or freed on the failure path?
> + i3c_bus_for_each_i3cdev(&master->bus, desc) {
> + if (desc->dev && device_may_wakeup(&desc->dev->dev)) {
[Severity: High]
Does this code risk a use-after-free if a device failed to register?
Looking at i3c_master_register_new_i3c_devs(), if device_register() fails,
the error path calls put_device(&desc->dev->dev) which frees the device
structure, but it leaves desc->dev as a dangling pointer.
If i3c_master_any_wakeup_enabled() is called later, could desc->dev evaluate
to true and cause device_may_wakeup() to dereference the freed memory?
> + wakeup = true;
> + break;
> + }
> + }
> + i3c_bus_normaluse_unlock(&master->bus);
> +
> + return wakeup;
> +}
> +EXPORT_SYMBOL_GPL(i3c_master_any_wakeup_enabled);
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701200552.220042-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 RFC 1/7] i3c: master: Support IBI-based wakeup capability
2026-07-01 20:05 ` Adrian Hunter
(?)
@ 2026-07-01 20:26 ` sashiko-bot
-1 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-01 20:26 UTC (permalink / raw)
To: Adrian Hunter; +Cc: linux-i3c, Frank.Li, Alexandre Belloni
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] Dangling pointer and double free on device_register() error path
- [High] Missing of_node_get() causes Use-After-Free of device tree node
--
commit ea80dbce0f5cdda7818e80b6dab51dc68f768d72
Author: Adrian Hunter <adrian.hunter@intel.com>
i3c: master: Support IBI-based wakeup capability
Adds an ibi_wakeup flag to struct i3c_master_controller so controller
drivers can advertise support for IBI-based wakeup. If set, marks
IBI-capable I3C devices as wakeup capable when they are registered.
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index f1be38a640ca1..a47e2924bb701 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
[ ... ]
> @@ -1930,6 +1931,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 isn't a bug introduced by this patch, but does this assignment need to
increment the reference count of the device tree node using of_node_get()?
Currently, the node is assigned directly from desc->boardinfo->of_node.
However, when the I3C device is later released (either via unregistration or
a device_register() failure), i3c_device_release() unconditionally calls
of_node_put(i3cdev->dev.of_node).
Could this consume the reference conceptually owned by boardinfo and lead to
a use-after-free of the device node on repeated hot-plug cycles or
registration failures?
> + /*
> + * 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);
> +
> ret = device_register(&desc->dev->dev);
> if (ret) {
> dev_err(&master->dev,
> "Failed to add I3C device (err = %d)\n", ret);
> put_device(&desc->dev->dev);
> }
[Severity: High]
This is a pre-existing issue, but is it possible for this error path to
leave a dangling pointer that causes a use-after-free later?
If device_register() fails, put_device() frees desc->dev via
i3c_device_release(). However, desc->dev and desc->dev->desc are not
cleared.
If i3c_master_unregister_i3c_devs() is later invoked during driver unbind,
it appears to find the non-NULL pointer and write to freed memory:
i3c_master_unregister_i3c_devs() {
...
i3cdev->dev->desc = NULL;
if (device_is_registered(&i3cdev->dev->dev))
device_unregister(&i3cdev->dev->dev);
else
put_device(&i3cdev->dev->dev);
...
}
and then execute a double-free on the device object. Should this error path
clear desc->dev to prevent this?
> }
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701200552.220042-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 RFC 5/7] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
2026-07-01 20:05 ` Adrian Hunter
(?)
@ 2026-07-01 20:26 ` sashiko-bot
-1 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-01 20:26 UTC (permalink / raw)
To: Adrian Hunter; +Cc: Frank.Li, Alexandre Belloni, linux-i3c
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Dereference of unvalidated `drvdata` in suspend path leads to NULL pointer crash if child driver is unbound.
--
commit 1a652f2d9252aa55258e44d095e09f412a966337
Author: Adrian Hunter <adrian.hunter@intel.com>
i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI
Keep the PCI wakeup state aligned with the wakeup requirements of the devices
served by the controller(s). It checks whether any HCI instance has a
wakeup-enabled I3C device and enables wakeup for the PCI function.
> 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 lead to a NULL pointer
dereference if the child driver is unbound?
If a privileged user unbinds the mipi_i3c_hci driver from a child platform
device via sysfs, drvdata is cleared to NULL.
Because the driver's remove callback does not disable the hardware controller
or clear the HC_CONTROL_BUS_ENABLE register bit,
mipi_i3c_hci_pci_is_operational() can still return true for this device
during a subsequent system suspend.
The PCI suspend instance iterator then passes the potentially unbound device
into this new function, which fetches the NULL drvdata and blindly
dereferences it.
The pre-existing i3c_hci_rpm_suspend() function called earlier in the same
suspend path appears to suffer from the exact same problem:
core.c:i3c_hci_rpm_suspend() {
struct i3c_hci *hci = dev_get_drvdata(dev);
/* Fall back to software reset to disable the bus */
if (i3c_hci_bus_disable(hci))
...
}
Should the suspend path validate that drvdata is non-NULL or that the driver
is actually bound before proceeding with these suspend operations?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701200552.220042-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 RFC 2/7] i3c: master: Report wakeup events for IBIs
2026-07-01 20:05 ` Adrian Hunter
(?)
@ 2026-07-01 20:27 ` sashiko-bot
-1 siblings, 0 replies; 22+ messages in thread
From: sashiko-bot @ 2026-07-01 20:27 UTC (permalink / raw)
To: Adrian Hunter; +Cc: linux-i3c, Frank.Li, Alexandre Belloni
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
New issues:
- [High] Unconditional dereference of `dev->dev` in `i3c_master_queue_ibi()` causes a NULL pointer dereference or use-after-free when an IBI interrupt triggers during master controller teardown.
Pre-existing issues:
- [High] Dangling pointer left in `desc->dev` when `device_register()` fails, leading to UAF and double free during teardown.
- [High] A TOCTOU race in `i3c_master_queue_ibi()` allows `dev->ibi` to be accessed and modified after it has been freed by a concurrent driver unbind.
--
commit 88b3910e92d2416ef1cb5400ef8ee3bbdd8200c5
Author: Adrian Hunter <adrian.hunter@intel.com>
i3c: master: Report wakeup events for IBIs
This commit allows an I3C device configured as a wakeup source to wake the
system via an In-Band Interrupt (IBI). When an IBI is queued, a wakeup event is
recorded with a 100 ms processing interval to allow the driver time to process
it.
> diff --git a/drivers/i3c/master.c b/drivers/i3c/master.c
> index a47e2924bb701..a36f9b617cbf7 100644
> --- a/drivers/i3c/master.c
> +++ b/drivers/i3c/master.c
> @@ -2994,6 +2994,9 @@ static void i3c_master_unregister_i3c_devs(struct i3c_master_controller *master)
> }
> }
[Severity: High]
This isn't a bug introduced by this patch, but looking at how devices are
unregistered here in i3c_master_unregister_i3c_devs():
i3cdev->dev->desc = NULL;
if (device_is_registered(&i3cdev->dev->dev))
device_unregister(&i3cdev->dev->dev);
else
put_device(&i3cdev->dev->dev);
i3cdev->dev = NULL;
Is there a risk of a double free if device_register() fails earlier in
i3c_master_register_new_i3c_devs()?
If the error path in registration calls put_device(&desc->dev->dev) but fails
to set desc->dev to NULL, this teardown loop will later find the dangling
pointer, perform a use-after-free write setting desc to NULL, and call
put_device() again on freed memory.
>
> +/* 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
> @@ -3007,6 +3010,9 @@ void i3c_master_queue_ibi(struct i3c_dev_desc *dev, struct i3c_ibi_slot *slot)
> if (!dev->ibi || !slot)
> return;
[Severity: High]
This isn't a bug introduced by this patch, but is it possible for dev->ibi to
be freed concurrently?
If i3c_dev_free_ibi_locked() executes kfree(dev->ibi) and sets dev->ibi = NULL
during device unbind without calling synchronize_irq() to wait for running
interrupts to finish:
Could an ISR running concurrently on another CPU pass the if (!dev->ibi) check
above, get delayed, and then access dev->ibi in the atomic_inc() below after
it has been freed?
>
> + if (device_may_wakeup(&dev->dev->dev))
> + pm_wakeup_event(&dev->dev->dev, I3C_WAKEUP_PROCESSING_TIME_MS);
> +
[Severity: High]
Does this code introduce a NULL pointer dereference or use-after-free risk
during master controller teardown?
During unregistration, i3c_master_unregister_i3c_devs() nullifies
i3cdev->dev->desc and sets i3cdev->dev = NULL. Because the unregistration code
nullifies dev->desc early, the driver's .remove() callback might silently fail
to clean up and disable the IBI hardware interrupt.
If the interrupt remains active and fires, the ISR will call
i3c_master_queue_ibi(). Since this new code unconditionally dereferences
dev->dev without verifying it is not NULL, wouldn't this cause an immediate
kernel oops?
> atomic_inc(&dev->ibi->pending_ibis);
> queue_work(dev->ibi->wq, &slot->work);
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260701200552.220042-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
end of thread, other threads:[~2026-07-01 20:27 UTC | newest]
Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-01 20:05 [PATCH RFC 0/7] i3c: Support IBI-based system wakeup Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:05 ` [PATCH RFC 1/7] i3c: master: Support IBI-based wakeup capability Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:26 ` sashiko-bot
2026-07-01 20:05 ` [PATCH RFC 2/7] i3c: master: Report wakeup events for IBIs Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:27 ` sashiko-bot
2026-07-01 20:05 ` [PATCH RFC 3/7] i3c: master: Add helper to query bus wakeup requirements Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:23 ` sashiko-bot
2026-07-01 20:05 ` [PATCH RFC 4/7] i3c: master: Reject IBI requests from non-IBI-capable devices Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:05 ` [PATCH RFC 5/7] i3c: mipi-i3c-hci-pci: Propagate I3C wakeup requirements to PCI Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:26 ` sashiko-bot
2026-07-01 20:05 ` [PATCH RFC 6/7] i3c: mipi-i3c-hci: Factor out i3c_hci_sysdev() Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:05 ` [PATCH RFC 7/7] i3c: mipi-i3c-hci: Advertise IBI wakeup capability Adrian Hunter
2026-07-01 20:05 ` Adrian Hunter
2026-07-01 20:15 ` [PATCH RFC 0/7] i3c: Support IBI-based system wakeup Adrian Hunter
2026-07-01 20:15 ` Adrian Hunter
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.