summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrei Kuchynski <akuchynski@chromium.org>2025-03-05 11:17:39 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2025-04-07 10:05:46 +0200
commit7a735a8a46f6ebf898bbefd96659ca5da798bce0 (patch)
treec2e5b3ded623a284cc1441350511f4b8bcd11e71
parent03fa71e97e9bb116993ec1d51b8a6fe776db0984 (diff)
downloadlinux-7a735a8a46f6ebf898bbefd96659ca5da798bce0.tar.gz
linux-7a735a8a46f6ebf898bbefd96659ca5da798bce0.tar.bz2
linux-7a735a8a46f6ebf898bbefd96659ca5da798bce0.zip
usb: typec: ucsi: Fix NULL pointer access
commit b13abcb7ddd8d38de769486db5bd917537b32ab1 upstream. Resources should be released only after all threads that utilize them have been destroyed. This commit ensures that resources are not released prematurely by waiting for the associated workqueue to complete before deallocating them. Cc: stable <stable@kernel.org> Fixes: b9aa02ca39a4 ("usb: typec: ucsi: Add polling mechanism for partner tasks like alt mode checking") Signed-off-by: Andrei Kuchynski <akuchynski@chromium.org> Reviewed-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Link: https://lore.kernel.org/r/20250305111739.1489003-2-akuchynski@chromium.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index 9c82dc94da81..2adf5fdc0c56 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -1313,11 +1313,11 @@ static int ucsi_init(struct ucsi *ucsi)
err_unregister:
for (con = connector; con->port; con++) {
+ if (con->wq)
+ destroy_workqueue(con->wq);
ucsi_unregister_partner(con);
ucsi_unregister_altmodes(con, UCSI_RECIPIENT_CON);
ucsi_unregister_port_psy(con);
- if (con->wq)
- destroy_workqueue(con->wq);
typec_unregister_port(con->port);
con->port = NULL;
}
@@ -1479,10 +1479,6 @@ void ucsi_unregister(struct ucsi *ucsi)
for (i = 0; i < ucsi->cap.num_connectors; i++) {
cancel_work_sync(&ucsi->connector[i].work);
- ucsi_unregister_partner(&ucsi->connector[i]);
- ucsi_unregister_altmodes(&ucsi->connector[i],
- UCSI_RECIPIENT_CON);
- ucsi_unregister_port_psy(&ucsi->connector[i]);
if (ucsi->connector[i].wq) {
struct ucsi_work *uwork;
@@ -1497,6 +1493,11 @@ void ucsi_unregister(struct ucsi *ucsi)
mutex_unlock(&ucsi->connector[i].lock);
destroy_workqueue(ucsi->connector[i].wq);
}
+
+ ucsi_unregister_partner(&ucsi->connector[i]);
+ ucsi_unregister_altmodes(&ucsi->connector[i],
+ UCSI_RECIPIENT_CON);
+ ucsi_unregister_port_psy(&ucsi->connector[i]);
typec_unregister_port(ucsi->connector[i].port);
}