FAILED: patch "[PATCH] usb: typec: ucsi: displayport: Fix deadlock" failed to apply to 5.15-stable tree
Subsystems (3)
[email protected]
maintainerThe patch below does not apply to the 5.15-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-5.15.y
git checkout FETCH_HEAD
git cherry-pick -x 364618c89d4c57c85e5fc51a2446cd939bf57802
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025051221-pacifist-liability-19cf@gregkh' --subject-prefix 'PATCH 5.15.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 364618c89d4c57c85e5fc51a2446cd939bf57802 Mon Sep 17 00:00:00 2001
From: Andrei Kuchynski <[email protected]>
Date: Thu, 24 Apr 2025 08:44:28 +0000
Subject: [PATCH] usb: typec: ucsi: displayport: Fix deadlock
This patch introduces the ucsi_con_mutex_lock / ucsi_con_mutex_unlock functions to the UCSI driver. ucsi_con_mutex_lock ensures the connector mutex is only locked if a connection is established and the partner pointer is valid. This resolves a deadlock scenario where ucsi_displayport_remove_partner holds con->mutex waiting for dp_altmode_work to complete while dp_altmode_work attempts to acquire it.
drivers/usb/typec/ucsi/displayport.c +11 -8
@@ -54,7 +54,8 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)u8 cur =0 ;int ret; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override && dp->initialized) {const struct typec_altmode *p =typec_altmode_get_partner (alt);
@@ -100,7 +101,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)schedule_work (&dp->work); ret =0 ; err_unlock: -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return ret; }
@@ -112,7 +113,8 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)u64 command;int ret =0 ; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override) {const struct typec_altmode *p =typec_altmode_get_partner (alt);
@@ -144,7 +146,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)schedule_work (&dp->work); out_unlock: -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return ret; }
@@ -202,20 +204,21 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,int cmd =PD_VDO_CMD (header);int svdm_version; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override && dp->initialized) {const struct typec_altmode *p =typec_altmode_get_partner (alt);dev_warn (&p->dev,"firmware doesn't support alternate mode overriding\n" ); -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return -EOPNOTSUPP ; } svdm_version =typec_altmode_get_svdm_version (alt);if (svdm_version <0 ) { -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return svdm_version; }
@@ -259,7 +262,7 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,break ; } -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return 0 ; }
drivers/usb/typec/ucsi/ucsi.c +34 -0
@@ -1922,6 +1922,40 @@ void ucsi_set_drvdata(struct ucsi *ucsi, void *data) }EXPORT_SYMBOL_GPL (ucsi_set_drvdata); +/** +* ucsi_con_mutex_lock - Acquire the connector mutex +* @con: The connector interface to lock +* +* Returns true on success, false if the connector is disconnected +*/ +bool ucsi_con_mutex_lock (struct ucsi_connector *con) +{ +bool mutex_locked = false; +bool connected = true; + +while (connected && !mutex_locked) { + mutex_locked =mutex_trylock (&con->lock) !=0 ; + connected =UCSI_CONSTAT (con,CONNECTED ); +if (connected && !mutex_locked) +msleep (20 ); + } + + connected = connected && con->partner; +if (!connected && mutex_locked) +mutex_unlock (&con->lock); + +return connected; +} + +/** +* ucsi_con_mutex_unlock - Release the connector mutex +* @con: The connector interface to unlock +*/ +void ucsi_con_mutex_unlock (struct ucsi_connector *con) +{ +mutex_unlock (&con->lock); +} +/** * ucsi_create - Allocate UCSI instance * @dev: Device interface to the PPM (Platform Policy Manager)
drivers/usb/typec/ucsi/ucsi.h +2 -0
@@ -94,6 +94,8 @@ int ucsi_register(struct ucsi *ucsi);void ucsi_unregister (struct ucsi *ucsi);void *ucsi_get_drvdata (struct ucsi *ucsi);void ucsi_set_drvdata (struct ucsi *ucsi,void *data); +bool ucsi_con_mutex_lock (struct ucsi_connector *con); +void ucsi_con_mutex_unlock (struct ucsi_connector *con);void ucsi_connector_change (struct ucsi *ucsi,u8 num);
PATCH 1/1 usb: typec: ucsi: displayport: Fix deadlock
This patch introduces the ucsi_con_mutex_lock / ucsi_con_mutex_unlock functions to the UCSI driver. ucsi_con_mutex_lock ensures the connector mutex is only locked if a connection is established and the partner pointer is valid. This resolves a deadlock scenario where ucsi_displayport_remove_partner holds con->mutex waiting for dp_altmode_work to complete while dp_altmode_work attempts to acquire it.
--- drivers/usb/typec/ucsi/displayport.c | 19 +++++++++------- drivers/usb/typec/ucsi/ucsi.c | 34 ++++++++++++++++++++++++++++ drivers/usb/typec/ucsi/ucsi.h | 3 +++ 3 files changed, 48 insertions(+), 8 deletions(-)
drivers/usb/typec/ucsi/displayport.c +11 -8
@@ -54,7 +54,8 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)u8 cur =0 ;int ret; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override && dp->initialized) {const struct typec_altmode *p =typec_altmode_get_partner (alt);
@@ -100,7 +101,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)schedule_work (&dp->work); ret =0 ; err_unlock: -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return ret; }
@@ -112,7 +113,8 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)u64 command;int ret =0 ; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override) {const struct typec_altmode *p =typec_altmode_get_partner (alt);
@@ -144,7 +146,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)schedule_work (&dp->work); out_unlock: -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return ret; }
@@ -202,20 +204,21 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,int cmd =PD_VDO_CMD (header);int svdm_version; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override && dp->initialized) {const struct typec_altmode *p =typec_altmode_get_partner (alt);dev_warn (&p->dev,"firmware doesn't support alternate mode overriding\n" ); -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return -EOPNOTSUPP ; } svdm_version =typec_altmode_get_svdm_version (alt);if (svdm_version <0 ) { -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return svdm_version; }
@@ -259,7 +262,7 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,break ; } -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return 0 ; }
drivers/usb/typec/ucsi/ucsi.c +34 -0
@@ -1351,6 +1351,40 @@ void ucsi_set_drvdata(struct ucsi *ucsi, void *data) }EXPORT_SYMBOL_GPL (ucsi_set_drvdata); +/** +* ucsi_con_mutex_lock - Acquire the connector mutex +* @con: The connector interface to lock +* +* Returns true on success, false if the connector is disconnected +*/ +bool ucsi_con_mutex_lock (struct ucsi_connector *con) +{ +bool mutex_locked = false; +bool connected = true; + +while (connected && !mutex_locked) { + mutex_locked =mutex_trylock (&con->lock) !=0 ; + connected = con->status.flags &UCSI_CONSTAT_CONNECTED ; +if (connected && !mutex_locked) +msleep (20 ); + } + + connected = connected && con->partner; +if (!connected && mutex_locked) +mutex_unlock (&con->lock); + +return connected; +} + +/** +* ucsi_con_mutex_unlock - Release the connector mutex +* @con: The connector interface to unlock +*/ +void ucsi_con_mutex_unlock (struct ucsi_connector *con) +{ +mutex_unlock (&con->lock); +} +/** * ucsi_create - Allocate UCSI instance * @dev: Device interface to the PPM (Platform Policy Manager)
drivers/usb/typec/ucsi/ucsi.h +3 -0
@@ -15,6 +15,7 @@struct ucsi ;struct ucsi_altmode ; +struct ucsi_connector ;/* UCSI offsets (Bytes) */ #define UCSI_VERSION 0
@@ -62,6 +63,8 @@ int ucsi_register(struct ucsi *ucsi);void ucsi_unregister (struct ucsi *ucsi);void *ucsi_get_drvdata (struct ucsi *ucsi);void ucsi_set_drvdata (struct ucsi *ucsi,void *data); +bool ucsi_con_mutex_lock (struct ucsi_connector *con); +void ucsi_con_mutex_unlock (struct ucsi_connector *con);void ucsi_connector_change (struct ucsi *ucsi,u8 num);
Signature · 1 line
2.49.0.1045.g170613ef41-goog
Re: [PATCH 5.15.y] usb: typec: ucsi: displayport: Fix deadlock
[ Sasha's backport helper bot ]
Hi,
Summary of potential issues:
⚠️ Found matching upstream commit but patch is missing proper reference to it
Found matching upstream commit: 364618c89d4c57c85e5fc51a2446cd939bf57802
Status in newer kernel trees:
6.14.y | Present (different SHA1: 64ae1063347e)
6.12.y | Not found
6.6.y | Not found
6.1.y | Not found
Note: The patch differs from the upstream commit:
---
1: 364618c89d4c5 ! 1: d6f6410c4cc3c usb: typec: ucsi: displayport: Fix deadlock
@@ Commit message
+ Change-Id: I72e0a5893a259321df1f38e54af36e61cbdc60a2
+ (cherry picked from commit 364618c89d4c57c85e5fc51a2446cd939bf57802)
## drivers/usb/typec/ucsi/displayport.c ##
@@ drivers/usb/typec/ucsi/displayport.c: static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
@@ drivers/usb/typec/ucsi/ucsi.c: void ucsi_set_drvdata(struct ucsi *ucsi, void *da
+
+ while (connected && !mutex_locked) {
+ mutex_locked = mutex_trylock(&con->lock) != 0;
-+ connected = UCSI_CONSTAT(con, CONNECTED);
++ connected = con->status.flags & UCSI_CONSTAT_CONNECTED;
+ if (connected && !mutex_locked)
+ msleep(20);
+ }
@@ drivers/usb/typec/ucsi/ucsi.c: void ucsi_set_drvdata(struct ucsi *ucsi, void *da
* @dev: Device interface to the PPM (Platform Policy Manager)
## drivers/usb/typec/ucsi/ucsi.h ##
+@@
+
+ struct ucsi;
+ struct ucsi_altmode;
++struct ucsi_connector;
+
+ /* UCSI offsets (Bytes) */
+ #define UCSI_VERSION 0
@@ drivers/usb/typec/ucsi/ucsi.h: int ucsi_register(struct ucsi *ucsi);
void ucsi_unregister(struct ucsi *ucsi);
void *ucsi_get_drvdata(struct ucsi *ucsi);
---
Results of testing on various branches:
| Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-5.15.y | Success | Success |
PATCH 1/1 usb: typec: ucsi: displayport: Fix deadlock
In reply to [email protected]This patch introduces the ucsi_con_mutex_lock / ucsi_con_mutex_unlock functions to the UCSI driver. ucsi_con_mutex_lock ensures the connector mutex is only locked if a connection is established and the partner pointer is valid. This resolves a deadlock scenario where ucsi_displayport_remove_partner holds con->mutex waiting for dp_altmode_work to complete while dp_altmode_work attempts to acquire it.
--- drivers/usb/typec/ucsi/displayport.c | 19 +++++++++------- drivers/usb/typec/ucsi/ucsi.c | 34 ++++++++++++++++++++++++++++ drivers/usb/typec/ucsi/ucsi.h | 3 +++ 3 files changed, 48 insertions(+), 8 deletions(-)
drivers/usb/typec/ucsi/displayport.c +11 -8
@@ -54,7 +54,8 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)u8 cur =0 ;int ret; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override && dp->initialized) {const struct typec_altmode *p =typec_altmode_get_partner (alt);
@@ -100,7 +101,7 @@ static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)schedule_work (&dp->work); ret =0 ; err_unlock: -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return ret; }
@@ -112,7 +113,8 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)u64 command;int ret =0 ; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override) {const struct typec_altmode *p =typec_altmode_get_partner (alt);
@@ -144,7 +146,7 @@ static int ucsi_displayport_exit(struct typec_altmode *alt)schedule_work (&dp->work); out_unlock: -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return ret; }
@@ -202,20 +204,21 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,int cmd =PD_VDO_CMD (header);int svdm_version; -mutex_lock (&dp->con->lock); +if (!ucsi_con_mutex_lock (dp->con)) +return -ENOTCONN ;if (!dp->override && dp->initialized) {const struct typec_altmode *p =typec_altmode_get_partner (alt);dev_warn (&p->dev,"firmware doesn't support alternate mode overriding\n" ); -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return -EOPNOTSUPP ; } svdm_version =typec_altmode_get_svdm_version (alt);if (svdm_version <0 ) { -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return svdm_version; }
@@ -259,7 +262,7 @@ static int ucsi_displayport_vdm(struct typec_altmode *alt,break ; } -mutex_unlock (&dp->con->lock); +ucsi_con_mutex_unlock (dp->con);return 0 ; }
drivers/usb/typec/ucsi/ucsi.c +34 -0
@@ -1351,6 +1351,40 @@ void ucsi_set_drvdata(struct ucsi *ucsi, void *data) }EXPORT_SYMBOL_GPL (ucsi_set_drvdata); +/** +* ucsi_con_mutex_lock - Acquire the connector mutex +* @con: The connector interface to lock +* +* Returns true on success, false if the connector is disconnected +*/ +bool ucsi_con_mutex_lock (struct ucsi_connector *con) +{ +bool mutex_locked = false; +bool connected = true; + +while (connected && !mutex_locked) { + mutex_locked =mutex_trylock (&con->lock) !=0 ; + connected = con->status.flags &UCSI_CONSTAT_CONNECTED ; +if (connected && !mutex_locked) +msleep (20 ); + } + + connected = connected && con->partner; +if (!connected && mutex_locked) +mutex_unlock (&con->lock); + +return connected; +} + +/** +* ucsi_con_mutex_unlock - Release the connector mutex +* @con: The connector interface to unlock +*/ +void ucsi_con_mutex_unlock (struct ucsi_connector *con) +{ +mutex_unlock (&con->lock); +} +/** * ucsi_create - Allocate UCSI instance * @dev: Device interface to the PPM (Platform Policy Manager)
drivers/usb/typec/ucsi/ucsi.h +3 -0
@@ -15,6 +15,7 @@struct ucsi ;struct ucsi_altmode ; +struct ucsi_connector ;/* UCSI offsets (Bytes) */ #define UCSI_VERSION 0
@@ -62,6 +63,8 @@ int ucsi_register(struct ucsi *ucsi);void ucsi_unregister (struct ucsi *ucsi);void *ucsi_get_drvdata (struct ucsi *ucsi);void ucsi_set_drvdata (struct ucsi *ucsi,void *data); +bool ucsi_con_mutex_lock (struct ucsi_connector *con); +void ucsi_con_mutex_unlock (struct ucsi_connector *con);void ucsi_connector_change (struct ucsi *ucsi,u8 num);
Signature · 1 line
2.49.0.1101.gccaa498523-goog
Sasha Levin
maintainerRe: [PATCH 5.15.y] usb: typec: ucsi: displayport: Fix deadlock
[ Sasha's backport helper bot ]
Hi,
Summary of potential issues:
⚠️ Found matching upstream commit but patch is missing proper reference to it
Found matching upstream commit: 364618c89d4c57c85e5fc51a2446cd939bf57802
Status in newer kernel trees:
6.14.y | Present (different SHA1: 61fc1a8e1e10)
6.12.y | Not found
6.6.y | Not found
6.1.y | Not found
Note: The patch differs from the upstream commit:
---
1: 364618c89d4c5 ! 1: caf9dc6a5a533 usb: typec: ucsi: displayport: Fix deadlock
@@ Commit message
Reviewed-by: Heikki Krogerus <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Greg Kroah-Hartman <[email protected]>
+ (cherry picked from commit 364618c89d4c57c85e5fc51a2446cd939bf57802)
## drivers/usb/typec/ucsi/displayport.c ##
@@ drivers/usb/typec/ucsi/displayport.c: static int ucsi_displayport_enter(struct typec_altmode *alt, u32 *vdo)
@@ drivers/usb/typec/ucsi/ucsi.c: void ucsi_set_drvdata(struct ucsi *ucsi, void *da
+
+ while (connected && !mutex_locked) {
+ mutex_locked = mutex_trylock(&con->lock) != 0;
-+ connected = UCSI_CONSTAT(con, CONNECTED);
++ connected = con->status.flags & UCSI_CONSTAT_CONNECTED;
+ if (connected && !mutex_locked)
+ msleep(20);
+ }
@@ drivers/usb/typec/ucsi/ucsi.c: void ucsi_set_drvdata(struct ucsi *ucsi, void *da
* @dev: Device interface to the PPM (Platform Policy Manager)
## drivers/usb/typec/ucsi/ucsi.h ##
+@@
+
+ struct ucsi;
+ struct ucsi_altmode;
++struct ucsi_connector;
+
+ /* UCSI offsets (Bytes) */
+ #define UCSI_VERSION 0
@@ drivers/usb/typec/ucsi/ucsi.h: int ucsi_register(struct ucsi *ucsi);
void ucsi_unregister(struct ucsi *ucsi);
void *ucsi_get_drvdata(struct ucsi *ucsi);---
Results of testing on various branches:
| Branch | Patch Apply | Build Test | |---------------------------|-------------|------------| | stable/linux-5.15.y | Success | Success |