blob: ad8445ca02be025646d987071d06a680ef649977 [file]
From 6d8530ca84ebdbff4e56c9c5fc513f4a85690223 Mon Sep 17 00:00:00 2001
From: Steven Niu <steven.niu.uj@renesas.com>
Date: Thu, 18 Sep 2025 20:33:53 +0800
Subject: [PATCH 2/2] i3c:i3c-hub: Fix SMBus Agent Rx buf id mismatch
Description:
Sometime the SMBus Agent may report the received data is not in the
expected rx buf when SMBus Agent works as slave device.
Root Cause:
The I3C Hub IBI handler works in greedy mode which handles it all available
events. At the same time, the I3C Hub handler works in workqueue context
and can be preempted by another IBI handler. This requires the i3c hub
event data shall be projected between the mulitple IBI handlers.
Solution:
Add mutex log to make the IBI handlers run sequentially.
Signed-off-by: Steven Niu <steven.niu.uj@renesas.com>
---
drivers/i3c/i3c-hub.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/i3c/i3c-hub.c b/drivers/i3c/i3c-hub.c
index 2c655eb047dd..f2012e50a103 100644
--- a/drivers/i3c/i3c-hub.c
+++ b/drivers/i3c/i3c-hub.c
@@ -369,6 +369,8 @@ struct i3c_hub {
/* protects page access */
struct mutex lock;
+ /* Sequential execution of IBI handler*/
+ struct mutex ibi_lock;
struct delayed_work delayed_work;
@@ -2207,6 +2209,8 @@ static void i3c_hub_ibi(struct i3c_device *i3c,
const struct i3c_hub_ibi_payload *p = NULL;
unsigned int i, dev_stat, target_stat;
+ mutex_lock(&hub->ibi_lock);
+
if (payload->len == sizeof(*p))
p = payload->data;
@@ -2222,7 +2226,7 @@ static void i3c_hub_ibi(struct i3c_device *i3c,
ret = regmap_bulk_read(hub->regmap, HUB_REG_DEV_AND_PORT_IBI_STS, tmp, 2);
if (ret)
- return;
+ goto exit;
dev_stat = tmp[0];
target_stat = tmp[1];
@@ -2253,6 +2257,8 @@ static void i3c_hub_ibi(struct i3c_device *i3c,
i3c_hub_agent_ibi(port->agent);
}
}
+exit:
+ mutex_unlock(&hub->ibi_lock);
}
static const struct i3c_ibi_setup i3c_hub_ibi_setup = {
@@ -2330,6 +2336,7 @@ static int i3c_hub_probe(struct i3c_device *i3cdev)
hub->regmap = regmap;
mutex_init(&hub->lock);
+ mutex_init(&hub->ibi_lock);
/* Disable all slave ports */
i3c_hub_unprotect_register(hub);
--
2.34.1