]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
usb: dwc2: gadget: Fix spin_lock/unlock mismatch in dwc2_hsotg_udc_stop()
authorJuno Choi <juno.choi@lge.com>
Tue, 24 Mar 2026 01:49:10 +0000 (10:49 +0900)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 30 Mar 2026 15:05:07 +0000 (17:05 +0200)
dwc2_gadget_exit_clock_gating() internally calls call_gadget() macro,
which expects hsotg->lock to be held since it does spin_unlock/spin_lock
around the gadget driver callback invocation.

However, dwc2_hsotg_udc_stop() calls dwc2_gadget_exit_clock_gating()
without holding the lock. This leads to:
 - spin_unlock on a lock that is not held (undefined behavior)
 - The lock remaining held after dwc2_gadget_exit_clock_gating() returns,
   causing a deadlock when spin_lock_irqsave() is called later in the
   same function.

Fix this by acquiring hsotg->lock before calling
dwc2_gadget_exit_clock_gating() and releasing it afterwards, which
satisfies the locking requirement of the call_gadget() macro.

Fixes: af076a41f8a2 ("usb: dwc2: also exit clock_gating when stopping udc while suspended")
Cc: stable <stable@kernel.org>
Signed-off-by: Juno Choi <juno.choi@lge.com>
Link: https://patch.msgid.link/20260324014910.2798425-1-juno.choi@lge.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/dwc2/gadget.c

index d216e26c787b0fb58d9adadf9693bc8a1c1ffd64..c8b02c27d27d4f109f565aeea8f0089e66734856 100644 (file)
@@ -4607,7 +4607,9 @@ static int dwc2_hsotg_udc_stop(struct usb_gadget *gadget)
        /* Exit clock gating when driver is stopped. */
        if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE &&
            hsotg->bus_suspended && !hsotg->params.no_clock_gating) {
+               spin_lock_irqsave(&hsotg->lock, flags);
                dwc2_gadget_exit_clock_gating(hsotg, 0);
+               spin_unlock_irqrestore(&hsotg->lock, flags);
        }
 
        /* all endpoints should be shutdown */