patch "usb: chipidea: core: fix possible concurrent when switch role" added to usb-linus
Subsystems (3)
This is a note to let you know that I've just added the patch titled
usb: chipidea: core: fix possible concurrent when switch role
to my usb git tree which can be found at
git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb.git
in the usb-linus branch.
The patch will show up in the next release of the linux-next tree (usually sometime within the next 24 hours during the week.)
The patch will hopefully also be merged in Linus's tree for the next -rc kernel release.
If you have any questions about this process, please let me know.
From 451b15ed138ec15bffbebb58a00ebdd884c3e659 Mon Sep 17 00:00:00 2001
From: Xu Yang <[email protected]>
Date: Fri, 17 Mar 2023 14:15:16 +0800
Subject: usb: chipidea: core: fix possible concurrent when switch role
The user may call role_store() when driver is handling ci_handle_id_switch() which is triggerred by otg event or power lost event. Unfortunately, the controller may go into chaos in this case. Fix this by protecting it with mutex lock.
--- drivers/usb/chipidea/ci.h | 2 ++ drivers/usb/chipidea/core.c | 8 +++++++- drivers/usb/chipidea/otg.c | 5 ++++- 3 files changed, 13 insertions(+), 2 deletions(-)
drivers/usb/chipidea/ci.h +2 -0
@@ -208,6 +208,7 @@ struct hw_bank {* @in_lpm: if the core in low power mode * @wakeup_int: if wakeup interrupt occur * @rev: The revision number for controller +* @mutex: protect code from concorrent running when doing role switch */ struct ci_hdrc {struct device *dev;
@@ -260,6 +261,7 @@ struct ci_hdrc {bool in_lpm;bool wakeup_int;enum ci_revision rev; +struct mutex mutex; };static inline struct ci_role_driver *ci_role (struct ci_hdrc *ci)
drivers/usb/chipidea/core.c +7 -1
@@ -987,8 +987,12 @@ static ssize_t role_store(struct device *dev,if (role ==CI_ROLE_END )return -EINVAL ; -if (role == ci->role) +mutex_lock (&ci->mutex); + +if (role == ci->role) { +mutex_unlock (&ci->mutex);return n; + }pm_runtime_get_sync (dev);disable_irq (ci->irq);
@@ -998,6 +1002,7 @@ static ssize_t role_store(struct device *dev,ci_handle_vbus_change (ci);enable_irq (ci->irq);pm_runtime_put_sync (dev); +mutex_unlock (&ci->mutex);return (ret ==0 ) ? n : ret; }
@@ -1033,6 +1038,7 @@ static int ci_hdrc_probe(struct platform_device *pdev)return -ENOMEM ;spin_lock_init (&ci->lock); +mutex_init (&ci->mutex); ci->dev = dev; ci->platdata =dev_get_platdata (dev); ci->imx28_write_fix = !!(ci->platdata->flags &
drivers/usb/chipidea/otg.c +4 -1
@@ -167,8 +167,10 @@ static int hw_wait_vbus_lower_bsv(struct ci_hdrc *ci)void ci_handle_id_switch (struct ci_hdrc *ci) { -enum ci_role role =ci_otg_role (ci); +enum ci_role role; +mutex_lock (&ci->mutex); + role =ci_otg_role (ci);if (role != ci->role) {dev_dbg (ci->dev,"switching from %s to %s\n" ,ci_role (ci)->name, ci->roles[role]->name);
@@ -198,6 +200,7 @@ void ci_handle_id_switch(struct ci_hdrc *ci)if (role ==CI_ROLE_GADGET )ci_handle_vbus_change (ci); } +mutex_unlock (&ci->mutex); }/** * ci_otg_work - perform otg (vbus/id) event handle
Signature · 1 line
2.40.0