| From c763801e0d53bb79531c7b2a9a7699b95362ad08 Mon Sep 17 00:00:00 2001 |
| From: Eugene Huang <eugene.ty.huang@fii-na.corp-partner.google.com> |
| Date: Tue, 20 May 2025 16:49:33 +0800 |
| Subject: [PATCH] Fix the i3c hub node mismatch issue |
| |
| 1.Limit the hub driver to finding the hub node within its parent node |
| |
| Signed-off-by: Eugene Huang <eugene.ty.huang@fii-na.corp-partner.google.com> |
| --- |
| drivers/i3c/i3c-hub.c | 26 +++++++++++--------------- |
| 1 file changed, 11 insertions(+), 15 deletions(-) |
| |
| diff --git a/drivers/i3c/i3c-hub.c b/drivers/i3c/i3c-hub.c |
| index 1d2dd05b9..0728e08c8 100644 |
| --- a/drivers/i3c/i3c-hub.c |
| +++ b/drivers/i3c/i3c-hub.c |
| @@ -285,7 +285,6 @@ |
| |
| static const bool ibi_paranoia = true; |
| static DEFINE_MUTEX(hub_lock); |
| -static struct device_node *last_node; |
| |
| /* mapping of part_id register to device-specific data */ |
| static const struct i3c_hub_devdata { |
| @@ -1891,10 +1890,10 @@ static int i3c_hub_read_id(struct i3c_hub *hub) |
| |
| static struct device_node *i3c_hub_get_dt_hub_node(struct i3c_hub *hub) |
| { |
| - struct device_node *node = hub->i3cdev->dev.parent->of_node; |
| + struct device_node *dev_node = hub->i3cdev->dev.parent->of_node; |
| + struct device_node *hub_node = NULL; |
| struct device_node *matched_node = NULL; |
| int max_ids_matched; |
| - struct device_node *hub_node, *from; |
| int node_ids_matched; |
| u8 dcr; |
| u32 id_csel, id_cp1, id_tpx; |
| @@ -1902,19 +1901,11 @@ static struct device_node *i3c_hub_get_dt_hub_node(struct i3c_hub *hub) |
| |
| max_ids_matched = 0; |
| |
| - from = last_node ? last_node : node; |
| - hub_node = NULL; |
| - while (1) { |
| - hub_node = of_find_node_by_name(from, "hub"); |
| - if (!hub_node) |
| - break; |
| - |
| + for_each_child_of_node(dev_node, hub_node){ |
| ret = of_property_read_u8(hub_node, "dcr", &dcr); |
| if (ret || dcr != I3C_DCR_HUB) |
| continue; |
| |
| - from = hub_node; |
| - |
| node_ids_matched = 1; |
| ret = of_property_read_u32(hub_node, "id-csel", &id_csel); |
| if (ret == 0 && id_csel == (u32)hub->hub_pin_sel_id) |
| @@ -1929,17 +1920,20 @@ static struct device_node *i3c_hub_get_dt_hub_node(struct i3c_hub *hub) |
| node_ids_matched += 1; |
| |
| if (node_ids_matched > max_ids_matched) { |
| - matched_node = hub_node; |
| + if (matched_node) |
| + of_node_put(matched_node); |
| + |
| max_ids_matched = node_ids_matched; |
| + of_node_get(hub_node); |
| + matched_node = hub_node; |
| } |
| } |
| |
| if (!matched_node) { |
| dev_err(&hub->i3cdev->dev, "Node NOT matched\n"); |
| - return matched_node; |
| + return NULL; |
| } |
| |
| - last_node = matched_node; |
| /* Find the proper node, update the id values in the node*/ |
| ret = of_property_read_u32(matched_node, "id-csel", &id_csel); |
| hub->hub_dt_sel_id = ret == 0 ? id_csel : -1; |
| @@ -2297,6 +2291,8 @@ static void i3c_hub_remove(struct i3c_device *i3cdev) |
| if (hub->ports[i].bridge) |
| i3c_master_unregister(&hub->ports[i].bridge->i3c); |
| } |
| + |
| + of_node_put(hub->of_node); |
| } |
| |
| static struct i3c_driver i3c_hub = { |
| -- |
| 2.34.1 |
| |