diff options
author | 2025-08-01 18:40:41 +0100 | |
---|---|---|
committer | 2025-08-13 17:15:45 +0200 | |
commit | 202ad1aaca777dc7fd24f459f5f808f5abd2bfda (patch) | |
tree | bab370a4339bcceebf78a7b45fd81d488b4b4fa6 | |
parent | usb: quirks: Add DELAY_INIT quick for another SanDisk 3.2Gen1 Flash Drive (diff) | |
download | wireguard-linux-202ad1aaca777dc7fd24f459f5f808f5abd2bfda.tar.xz wireguard-linux-202ad1aaca777dc7fd24f459f5f808f5abd2bfda.zip |
usb: gadget: tegra-xudc: fix PM use count underflow
Upon resume from system suspend, the PM runtime core issues the
following warning:
tegra-xudc 3550000.usb: Runtime PM usage count underflow!
This is because tegra_xudc_resume() unconditionally calls
schedule_work(&xudc->usb_role_sw_work) whether or not anything has
changed, which causes tegra_xudc_device_mode_off() to be called
even when we're already in that mode.
Keep track of the current state of "device_mode", and only schedule
this work if it has changed from the hardware state on resume.
Signed-off-by: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
Link: https://lore.kernel.org/r/E1uhtkH-007KDZ-JT@rmk-PC.armlinux.org.uk
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/usb/gadget/udc/tegra-xudc.c | 9 |
1 files changed, 7 insertions, 2 deletions
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c index 2957316fd3d0..1d3085cc9d22 100644 --- a/drivers/usb/gadget/udc/tegra-xudc.c +++ b/drivers/usb/gadget/udc/tegra-xudc.c @@ -502,6 +502,7 @@ struct tegra_xudc { struct clk_bulk_data *clks; bool device_mode; + bool current_device_mode; struct work_struct usb_role_sw_work; struct phy **usb3_phy; @@ -715,6 +716,8 @@ static void tegra_xudc_device_mode_on(struct tegra_xudc *xudc) phy_set_mode_ext(xudc->curr_utmi_phy, PHY_MODE_USB_OTG, USB_ROLE_DEVICE); + + xudc->current_device_mode = true; } static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc) @@ -725,6 +728,8 @@ static void tegra_xudc_device_mode_off(struct tegra_xudc *xudc) dev_dbg(xudc->dev, "device mode off\n"); + xudc->current_device_mode = false; + connected = !!(xudc_readl(xudc, PORTSC) & PORTSC_CCS); reinit_completion(&xudc->disconnect_complete); @@ -4044,10 +4049,10 @@ static int __maybe_unused tegra_xudc_resume(struct device *dev) spin_lock_irqsave(&xudc->lock, flags); xudc->suspended = false; + if (xudc->device_mode != xudc->current_device_mode) + schedule_work(&xudc->usb_role_sw_work); spin_unlock_irqrestore(&xudc->lock, flags); - schedule_work(&xudc->usb_role_sw_work); - pm_runtime_enable(dev); return 0; |