From 322cc782ff399b80323f2900ccdcf2e001724a4f Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Tue, 20 May 2025 12:44:13 +0200 Subject: [PATCH] 5.15-stable patches added patches: usb-typec-altmodes-displayport-create-sysfs-nodes-as-driver-s-default-device-attribute-group.patch usb-typec-fix-pm-usage-counter-imbalance-in-ucsi_ccg_sync_control.patch usb-typec-fix-potential-array-underflow-in-ucsi_ccg_sync_control.patch usb-typec-ucsi-displayport-fix-deadlock.patch --- queue-5.15/series | 4 + ...ver-s-default-device-attribute-group.patch | 92 ++++++++++ ...r-imbalance-in-ucsi_ccg_sync_control.patch | 49 ++++++ ...y-underflow-in-ucsi_ccg_sync_control.patch | 49 ++++++ ...-typec-ucsi-displayport-fix-deadlock.patch | 164 ++++++++++++++++++ 5 files changed, 358 insertions(+) create mode 100644 queue-5.15/usb-typec-altmodes-displayport-create-sysfs-nodes-as-driver-s-default-device-attribute-group.patch create mode 100644 queue-5.15/usb-typec-fix-pm-usage-counter-imbalance-in-ucsi_ccg_sync_control.patch create mode 100644 queue-5.15/usb-typec-fix-potential-array-underflow-in-ucsi_ccg_sync_control.patch create mode 100644 queue-5.15/usb-typec-ucsi-displayport-fix-deadlock.patch diff --git a/queue-5.15/series b/queue-5.15/series index 67eed7f2fc..c116745ca4 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -45,3 +45,7 @@ dmaengine-idxd-fix-memory-leak-in-error-handling-path-of-idxd_setup_engines.patc dmaengine-idxd-fix-memory-leak-in-error-handling-path-of-idxd_setup_groups.patch block-fix-direct-io-nowait-flag-not-work.patch clocksource-i8253-use-raw_spinlock_irqsave-in-clockevent_i8253_disable.patch +usb-typec-ucsi-displayport-fix-deadlock.patch +usb-typec-altmodes-displayport-create-sysfs-nodes-as-driver-s-default-device-attribute-group.patch +usb-typec-fix-potential-array-underflow-in-ucsi_ccg_sync_control.patch +usb-typec-fix-pm-usage-counter-imbalance-in-ucsi_ccg_sync_control.patch diff --git a/queue-5.15/usb-typec-altmodes-displayport-create-sysfs-nodes-as-driver-s-default-device-attribute-group.patch b/queue-5.15/usb-typec-altmodes-displayport-create-sysfs-nodes-as-driver-s-default-device-attribute-group.patch new file mode 100644 index 0000000000..d606080b3d --- /dev/null +++ b/queue-5.15/usb-typec-altmodes-displayport-create-sysfs-nodes-as-driver-s-default-device-attribute-group.patch @@ -0,0 +1,92 @@ +From 165376f6b23e9a779850e750fb2eb06622e5a531 Mon Sep 17 00:00:00 2001 +From: RD Babiera +Date: Thu, 29 Feb 2024 00:11:02 +0000 +Subject: usb: typec: altmodes/displayport: create sysfs nodes as driver's default device attribute group + +From: RD Babiera + +commit 165376f6b23e9a779850e750fb2eb06622e5a531 upstream. + +The DisplayPort driver's sysfs nodes may be present to the userspace before +typec_altmode_set_drvdata() completes in dp_altmode_probe. This means that +a sysfs read can trigger a NULL pointer error by deferencing dp->hpd in +hpd_show or dp->lock in pin_assignment_show, as dev_get_drvdata() returns +NULL in those cases. + +Remove manual sysfs node creation in favor of adding attribute group as +default for devices bound to the driver. The ATTRIBUTE_GROUPS() macro is +not used here otherwise the path to the sysfs nodes is no longer compliant +with the ABI. + +Fixes: 0e3bb7d6894d ("usb: typec: Add driver for DisplayPort alternate mode") +Cc: stable@vger.kernel.org +Signed-off-by: RD Babiera +Link: https://lore.kernel.org/r/20240229001101.3889432-2-rdbabiera@google.com +[Minor conflict resolved due to code context change.] +Signed-off-by: Jianqi Ren +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/altmodes/displayport.c | 18 +++++++++--------- + 1 file changed, 9 insertions(+), 9 deletions(-) + +--- a/drivers/usb/typec/altmodes/displayport.c ++++ b/drivers/usb/typec/altmodes/displayport.c +@@ -521,22 +521,26 @@ static ssize_t pin_assignment_show(struc + } + static DEVICE_ATTR_RW(pin_assignment); + +-static struct attribute *dp_altmode_attrs[] = { ++static struct attribute *displayport_attrs[] = { + &dev_attr_configuration.attr, + &dev_attr_pin_assignment.attr, + NULL + }; + +-static const struct attribute_group dp_altmode_group = { ++static const struct attribute_group displayport_group = { + .name = "displayport", +- .attrs = dp_altmode_attrs, ++ .attrs = displayport_attrs, ++}; ++ ++static const struct attribute_group *displayport_groups[] = { ++ &displayport_group, ++ NULL, + }; + + int dp_altmode_probe(struct typec_altmode *alt) + { + const struct typec_altmode *port = typec_altmode_get_partner(alt); + struct dp_altmode *dp; +- int ret; + + /* FIXME: Port can only be DFP_U. */ + +@@ -547,10 +551,6 @@ int dp_altmode_probe(struct typec_altmod + DP_CAP_PIN_ASSIGN_DFP_D(alt->vdo))) + return -ENODEV; + +- ret = sysfs_create_group(&alt->dev.kobj, &dp_altmode_group); +- if (ret) +- return ret; +- + dp = devm_kzalloc(&alt->dev, sizeof(*dp), GFP_KERNEL); + if (!dp) + return -ENOMEM; +@@ -576,7 +576,6 @@ void dp_altmode_remove(struct typec_altm + { + struct dp_altmode *dp = typec_altmode_get_drvdata(alt); + +- sysfs_remove_group(&alt->dev.kobj, &dp_altmode_group); + cancel_work_sync(&dp->work); + } + EXPORT_SYMBOL_GPL(dp_altmode_remove); +@@ -594,6 +593,7 @@ static struct typec_altmode_driver dp_al + .driver = { + .name = "typec_displayport", + .owner = THIS_MODULE, ++ .dev_groups = displayport_groups, + }, + }; + module_typec_altmode_driver(dp_altmode_driver); diff --git a/queue-5.15/usb-typec-fix-pm-usage-counter-imbalance-in-ucsi_ccg_sync_control.patch b/queue-5.15/usb-typec-fix-pm-usage-counter-imbalance-in-ucsi_ccg_sync_control.patch new file mode 100644 index 0000000000..9c7e5a845a --- /dev/null +++ b/queue-5.15/usb-typec-fix-pm-usage-counter-imbalance-in-ucsi_ccg_sync_control.patch @@ -0,0 +1,49 @@ +From b0e525d7a22ea350e75e2aec22e47fcfafa4cacd Mon Sep 17 00:00:00 2001 +From: GONG Ruiqi +Date: Tue, 7 Jan 2025 09:57:50 +0800 +Subject: usb: typec: fix pm usage counter imbalance in ucsi_ccg_sync_control() + +From: GONG Ruiqi + +commit b0e525d7a22ea350e75e2aec22e47fcfafa4cacd upstream. + +The error handling for the case `con_index == 0` should involve dropping +the pm usage counter, as ucsi_ccg_sync_control() gets it at the +beginning. Fix it. + +Cc: stable +Fixes: e56aac6e5a25 ("usb: typec: fix potential array underflow in ucsi_ccg_sync_control()") +Signed-off-by: GONG Ruiqi +Reviewed-by: Dan Carpenter +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20250107015750.2778646-1-gongruiqi1@huawei.com +Signed-off-by: Greg Kroah-Hartman +[Minor context change fixed.] +Signed-off-by: Bin Lan +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/ucsi/ucsi_ccg.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +--- a/drivers/usb/typec/ucsi/ucsi_ccg.c ++++ b/drivers/usb/typec/ucsi/ucsi_ccg.c +@@ -575,7 +575,7 @@ static int ucsi_ccg_sync_write(struct uc + UCSI_CMD_CONNECTOR_MASK; + if (con_index == 0) { + ret = -EINVAL; +- goto unlock; ++ goto err_put; + } + con = &uc->ucsi->connector[con_index - 1]; + ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val); +@@ -591,8 +591,8 @@ static int ucsi_ccg_sync_write(struct uc + + err_clear_bit: + clear_bit(DEV_CMD_PENDING, &uc->flags); ++err_put: + pm_runtime_put_sync(uc->dev); +-unlock: + mutex_unlock(&uc->lock); + + return ret; diff --git a/queue-5.15/usb-typec-fix-potential-array-underflow-in-ucsi_ccg_sync_control.patch b/queue-5.15/usb-typec-fix-potential-array-underflow-in-ucsi_ccg_sync_control.patch new file mode 100644 index 0000000000..8337443a80 --- /dev/null +++ b/queue-5.15/usb-typec-fix-potential-array-underflow-in-ucsi_ccg_sync_control.patch @@ -0,0 +1,49 @@ +From e56aac6e5a25630645607b6856d4b2a17b2311a5 Mon Sep 17 00:00:00 2001 +From: Dan Carpenter +Date: Mon, 11 Nov 2024 14:08:06 +0300 +Subject: usb: typec: fix potential array underflow in ucsi_ccg_sync_control() + +From: Dan Carpenter + +commit e56aac6e5a25630645607b6856d4b2a17b2311a5 upstream. + +The "command" variable can be controlled by the user via debugfs. The +worry is that if con_index is zero then "&uc->ucsi->connector[con_index +- 1]" would be an array underflow. + +Fixes: 170a6726d0e2 ("usb: typec: ucsi: add support for separate DP altmode devices") +Signed-off-by: Dan Carpenter +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/c69ef0b3-61b0-4dde-98dd-97b97f81d912@stanley.mountain +Signed-off-by: Greg Kroah-Hartman +[ The function ucsi_ccg_sync_write() is renamed to ucsi_ccg_sync_control() + in commit 13f2ec3115c8 ("usb: typec: ucsi:simplify command sending API"). + Apply this patch to ucsi_ccg_sync_write() in 6.1.y accordingly. ] +Signed-off-by: Bin Lan +Signed-off-by: He Zhe +Signed-off-by: Greg Kroah-Hartman +--- + drivers/usb/typec/ucsi/ucsi_ccg.c | 5 +++++ + 1 file changed, 5 insertions(+) + +--- a/drivers/usb/typec/ucsi/ucsi_ccg.c ++++ b/drivers/usb/typec/ucsi/ucsi_ccg.c +@@ -573,6 +573,10 @@ static int ucsi_ccg_sync_write(struct uc + uc->has_multiple_dp) { + con_index = (uc->last_cmd_sent >> 16) & + UCSI_CMD_CONNECTOR_MASK; ++ if (con_index == 0) { ++ ret = -EINVAL; ++ goto unlock; ++ } + con = &uc->ucsi->connector[con_index - 1]; + ucsi_ccg_update_set_new_cam_cmd(uc, con, (u64 *)val); + } +@@ -588,6 +592,7 @@ static int ucsi_ccg_sync_write(struct uc + err_clear_bit: + clear_bit(DEV_CMD_PENDING, &uc->flags); + pm_runtime_put_sync(uc->dev); ++unlock: + mutex_unlock(&uc->lock); + + return ret; diff --git a/queue-5.15/usb-typec-ucsi-displayport-fix-deadlock.patch b/queue-5.15/usb-typec-ucsi-displayport-fix-deadlock.patch new file mode 100644 index 0000000000..29834d745e --- /dev/null +++ b/queue-5.15/usb-typec-ucsi-displayport-fix-deadlock.patch @@ -0,0 +1,164 @@ +From 364618c89d4c57c85e5fc51a2446cd939bf57802 Mon Sep 17 00:00:00 2001 +From: Andrei Kuchynski +Date: Thu, 24 Apr 2025 08:44:28 +0000 +Subject: usb: typec: ucsi: displayport: Fix deadlock + +From: Andrei Kuchynski + +commit 364618c89d4c57c85e5fc51a2446cd939bf57802 upstream. + +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. + +Cc: stable +Fixes: af8622f6a585 ("usb: typec: ucsi: Support for DisplayPort alt mode") +Signed-off-by: Andrei Kuchynski +Reviewed-by: Heikki Krogerus +Link: https://lore.kernel.org/r/20250424084429.3220757-2-akuchynski@chromium.org +Signed-off-by: Greg Kroah-Hartman +--- + 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(-) + +--- a/drivers/usb/typec/ucsi/displayport.c ++++ b/drivers/usb/typec/ucsi/displayport.c +@@ -54,7 +54,8 @@ static int ucsi_displayport_enter(struct + 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 + 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 + 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 + 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 t + 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 t + break; + } + +- mutex_unlock(&dp->con->lock); ++ ucsi_con_mutex_unlock(dp->con); + + return 0; + } +--- a/drivers/usb/typec/ucsi/ucsi.c ++++ b/drivers/usb/typec/ucsi/ucsi.c +@@ -1352,6 +1352,40 @@ void ucsi_set_drvdata(struct ucsi *ucsi, + 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) + * @ops: I/O routines +--- a/drivers/usb/typec/ucsi/ucsi.h ++++ b/drivers/usb/typec/ucsi/ucsi.h +@@ -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); + -- 2.47.3