This is a note to let you know that I've just added the patch titled usb: musb: Fix runtime PM race in musb_queue_resume_work to the 5.10-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: usb-musb-fix-runtime-pm-race-in-musb_queue_resume_work.patch and it can be found in the queue-5.10 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. >From 0eaa1a3714db34a59ce121de5733c3909c529463 Mon Sep 17 00:00:00 2001 From: Paul Cercueil <paul@xxxxxxxxxxxxxxx> Date: Sat, 23 Jan 2021 14:24:59 +0000 Subject: usb: musb: Fix runtime PM race in musb_queue_resume_work From: Paul Cercueil <paul@xxxxxxxxxxxxxxx> commit 0eaa1a3714db34a59ce121de5733c3909c529463 upstream. musb_queue_resume_work() would call the provided callback if the runtime PM status was 'active'. Otherwise, it would enqueue the request if the hardware was still suspended (musb->is_runtime_suspended is true). This causes a race with the runtime PM handlers, as it is possible to be in the case where the runtime PM status is not yet 'active', but the hardware has been awaken (PM resume function has been called). When hitting the race, the resume work was not enqueued, which probably triggered other bugs further down the stack. For instance, a telnet connection on Ingenic SoCs would result in a 50/50 chance of a segmentation fault somewhere in the musb code. Rework the code so that either we call the callback directly if (musb->is_runtime_suspended == 0), or enqueue the query otherwise. Fixes: ea2f35c01d5e ("usb: musb: Fix sleeping function called from invalid context for hdrc glue") Cc: stable@xxxxxxxxxxxxxxx # v4.9+ Tested-by: Tony Lindgren <tony@xxxxxxxxxxx> Reviewed-by: Tony Lindgren <tony@xxxxxxxxxxx> Signed-off-by: Paul Cercueil <paul@xxxxxxxxxxxxxxx> Link: https://lore.kernel.org/r/20210123142502.16980-1-paul@xxxxxxxxxxxxxxx Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> --- drivers/usb/musb/musb_core.c | 31 +++++++++++++++++-------------- 1 file changed, 17 insertions(+), 14 deletions(-) --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2240,32 +2240,35 @@ int musb_queue_resume_work(struct musb * { struct musb_pending_work *w; unsigned long flags; + bool is_suspended; int error; if (WARN_ON(!callback)) return -EINVAL; - if (pm_runtime_active(musb->controller)) - return callback(musb, data); + spin_lock_irqsave(&musb->list_lock, flags); + is_suspended = musb->is_runtime_suspended; - w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC); - if (!w) - return -ENOMEM; + if (is_suspended) { + w = devm_kzalloc(musb->controller, sizeof(*w), GFP_ATOMIC); + if (!w) { + error = -ENOMEM; + goto out_unlock; + } + + w->callback = callback; + w->data = data; - w->callback = callback; - w->data = data; - spin_lock_irqsave(&musb->list_lock, flags); - if (musb->is_runtime_suspended) { list_add_tail(&w->node, &musb->pending_list); error = 0; - } else { - dev_err(musb->controller, "could not add resume work %p\n", - callback); - devm_kfree(musb->controller, w); - error = -EINPROGRESS; } + +out_unlock: spin_unlock_irqrestore(&musb->list_lock, flags); + if (!is_suspended) + error = callback(musb, data); + return error; } EXPORT_SYMBOL_GPL(musb_queue_resume_work); Patches currently in stable-queue which might be from paul@xxxxxxxxxxxxxxx are queue-5.10/usb-musb-fix-runtime-pm-race-in-musb_queue_resume_work.patch queue-5.10/mips-ingenic-disable-hptlb-for-d0-xburst-cpus-too.patch queue-5.10/seccomp-add-missing-return-in-non-void-function.patch