summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorPrashanth K <prashanth.k@oss.qualcomm.com>2026-09-16 09:58:08 +0530
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2026-10-01 07:13:01 +0200
commit6c51f09c6db5868a5090e8dd4d7764660c87f1ad (patch)
tree8018f84573993498f6cfc9cf18cea082aa7b1097 /drivers
parent9062d50e75c24dc7911be05c9b1719b3b256af15 (diff)
downloadlinux-stable-6c51f09c6db5868a5090e8dd4d7764660c87f1ad.tar.gz
linux-stable-6c51f09c6db5868a5090e8dd4d7764660c87f1ad.zip
usb: typec: ucsi: Get the connector fwnode based on reg value
ucsi_find_fwnode() currently maps UCSI connectors to Device tree connector nodes based on the order in which connector child nodes are described in DT. This can fail because the ordering of child nodes isn't guaranteed in Device-tree. For example, DTB may contain connector@1 before connector@0, causing connector numbers to be associated with the wrong fwnode. As a result, role switch and Type-C notifications can be delivered to the wrong remote endpoints. Fix this by using the "reg" property of each connector to match its corresponding fwnode. While at it, if the reg property isn't present, then fall back to the old method. Fixes: c1b0bc2dabfa ("usb: typec: Add support for UCSI interface") Cc: stable <stable@kernel.org> Signed-off-by: Prashanth K <prashanth.k@oss.qualcomm.com> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://patch.msgid.link/20260916042808.2879079-1-prashanth.k@oss.qualcomm.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index bef3f9b71..c1450639c 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1801,10 +1801,21 @@ static struct fwnode_handle *ucsi_find_fwnode(struct ucsi_connector *con)
{
struct fwnode_handle *fwnode;
int i = 1;
+ int ret;
+ u32 port;
- device_for_each_child_node(con->ucsi->dev, fwnode)
- if (i++ == con->num)
- return fwnode;
+ device_for_each_child_node(con->ucsi->dev, fwnode) {
+ ret = fwnode_property_read_u32(fwnode, "reg", &port);
+ if (ret < 0) {
+ if (i == con->num)
+ return fwnode;
+ } else {
+ if (port == con->num - 1)
+ return fwnode;
+ }
+
+ i++;
+ }
return NULL;
}