--- /dev/null
+From ec27386de23a511008c53aa2f3434ad180a3ca9a Mon Sep 17 00:00:00 2001
+From: Andrei Kuchynski <akuchynski@chromium.org>
+Date: Fri, 21 Mar 2025 14:37:26 +0000
+Subject: usb: typec: class: Fix NULL pointer access
+
+From: Andrei Kuchynski <akuchynski@chromium.org>
+
+commit ec27386de23a511008c53aa2f3434ad180a3ca9a upstream.
+
+Concurrent calls to typec_partner_unlink_device can lead to a NULL pointer
+dereference. This patch adds a mutex to protect USB device pointers and
+prevent this issue. The same mutex protects both the device pointers and
+the partner device registration.
+
+Cc: stable@vger.kernel.org
+Fixes: 59de2a56d127 ("usb: typec: Link enumerated USB devices with Type-C partner")
+Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org>
+Reviewed-by: Benson Leung <bleung@chromium.org>
+Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://lore.kernel.org/r/20250321143728.4092417-2-akuchynski@chromium.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/class.c | 15 +++++++++++++--
+ drivers/usb/typec/class.h | 1 +
+ 2 files changed, 14 insertions(+), 2 deletions(-)
+
+--- a/drivers/usb/typec/class.c
++++ b/drivers/usb/typec/class.c
+@@ -932,6 +932,7 @@ struct typec_partner *typec_register_par
+ partner->dev.type = &typec_partner_dev_type;
+ dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev));
+
++ mutex_lock(&port->partner_link_lock);
+ ret = device_register(&partner->dev);
+ if (ret) {
+ dev_err(&port->dev, "failed to register partner (%d)\n", ret);
+@@ -943,6 +944,7 @@ struct typec_partner *typec_register_par
+ typec_partner_link_device(partner, port->usb2_dev);
+ if (port->usb3_dev)
+ typec_partner_link_device(partner, port->usb3_dev);
++ mutex_unlock(&port->partner_link_lock);
+
+ return partner;
+ }
+@@ -963,12 +965,14 @@ void typec_unregister_partner(struct typ
+
+ port = to_typec_port(partner->dev.parent);
+
++ mutex_lock(&port->partner_link_lock);
+ if (port->usb2_dev)
+ typec_partner_unlink_device(partner, port->usb2_dev);
+ if (port->usb3_dev)
+ typec_partner_unlink_device(partner, port->usb3_dev);
+
+ device_unregister(&partner->dev);
++ mutex_unlock(&port->partner_link_lock);
+ }
+ EXPORT_SYMBOL_GPL(typec_unregister_partner);
+
+@@ -1862,25 +1866,30 @@ static struct typec_partner *typec_get_p
+ static void typec_partner_attach(struct typec_connector *con, struct device *dev)
+ {
+ struct typec_port *port = container_of(con, struct typec_port, con);
+- struct typec_partner *partner = typec_get_partner(port);
++ struct typec_partner *partner;
+ struct usb_device *udev = to_usb_device(dev);
+
++ mutex_lock(&port->partner_link_lock);
+ if (udev->speed < USB_SPEED_SUPER)
+ port->usb2_dev = dev;
+ else
+ port->usb3_dev = dev;
+
++ partner = typec_get_partner(port);
+ if (partner) {
+ typec_partner_link_device(partner, dev);
+ put_device(&partner->dev);
+ }
++ mutex_unlock(&port->partner_link_lock);
+ }
+
+ static void typec_partner_deattach(struct typec_connector *con, struct device *dev)
+ {
+ struct typec_port *port = container_of(con, struct typec_port, con);
+- struct typec_partner *partner = typec_get_partner(port);
++ struct typec_partner *partner;
+
++ mutex_lock(&port->partner_link_lock);
++ partner = typec_get_partner(port);
+ if (partner) {
+ typec_partner_unlink_device(partner, dev);
+ put_device(&partner->dev);
+@@ -1890,6 +1899,7 @@ static void typec_partner_deattach(struc
+ port->usb2_dev = NULL;
+ else if (port->usb3_dev == dev)
+ port->usb3_dev = NULL;
++ mutex_unlock(&port->partner_link_lock);
+ }
+
+ /**
+@@ -2425,6 +2435,7 @@ struct typec_port *typec_register_port(s
+
+ ida_init(&port->mode_ids);
+ mutex_init(&port->port_type_lock);
++ mutex_init(&port->partner_link_lock);
+
+ port->id = id;
+ port->ops = cap->ops;
+--- a/drivers/usb/typec/class.h
++++ b/drivers/usb/typec/class.h
+@@ -56,6 +56,7 @@ struct typec_port {
+ enum typec_pwr_opmode pwr_opmode;
+ enum typec_port_type port_type;
+ struct mutex port_type_lock;
++ struct mutex partner_link_lock;
+
+ enum typec_orientation orientation;
+ struct typec_switch *sw;