mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
usb: dwc3: Properly set system wakeup
commitf9aa41130a
upstream. If the device is configured for system wakeup, then make sure that the xHCI driver knows about it and make sure to permit wakeup only at the appropriate time. For host mode, if the controller goes through the dwc3 code path, then a child xHCI platform device is created. Make sure the platform device also inherits the wakeup setting for xHCI to enable remote wakeup. For device mode, make sure to disable system wakeup if no gadget driver is bound. We may experience unwanted system wakeup due to the wakeup signal from the controller PMU detecting connection/disconnection when in low power (D3). E.g. In the case of Steam Deck, the PCI PME prevents the system staying in suspend. Cc: stable@vger.kernel.org Reported-by: Guilherme G. Piccoli <gpiccoli@igalia.com> Closes: https://lore.kernel.org/linux-usb/70a7692d-647c-9be7-00a6-06fc60f77294@igalia.com/T/#mf00d6669c2eff7b308d1162acd1d66c09f0853c7 Fixes:d07e8819a0
("usb: dwc3: add xHCI Host support") Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com> Tested-by: Sanath S <Sanath.S@amd.com> Tested-by: Guilherme G. Piccoli <gpiccoli@igalia.com> # Steam Deck Link: https://lore.kernel.org/r/667cfda7009b502e08462c8fb3f65841d103cc0a.1709865476.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
840c1f3337
commit
4794c68c6a
@ -1507,6 +1507,8 @@ static void dwc3_get_properties(struct dwc3 *dwc)
|
||||
else
|
||||
dwc->sysdev = dwc->dev;
|
||||
|
||||
dwc->sys_wakeup = device_may_wakeup(dwc->sysdev);
|
||||
|
||||
ret = device_property_read_string(dev, "usb-psy-name", &usb_psy_name);
|
||||
if (ret >= 0) {
|
||||
dwc->usb_psy = power_supply_get_by_name(usb_psy_name);
|
||||
|
@ -1127,6 +1127,7 @@ struct dwc3_scratchpad_array {
|
||||
* 3 - Reserved
|
||||
* @dis_metastability_quirk: set to disable metastability quirk.
|
||||
* @dis_split_quirk: set to disable split boundary.
|
||||
* @sys_wakeup: set if the device may do system wakeup.
|
||||
* @wakeup_configured: set if the device is configured for remote wakeup.
|
||||
* @suspended: set to track suspend event due to U3/L2.
|
||||
* @imod_interval: set the interrupt moderation interval in 250ns
|
||||
@ -1350,6 +1351,7 @@ struct dwc3 {
|
||||
|
||||
unsigned dis_split_quirk:1;
|
||||
unsigned async_callbacks:1;
|
||||
unsigned sys_wakeup:1;
|
||||
unsigned wakeup_configured:1;
|
||||
unsigned suspended:1;
|
||||
|
||||
|
@ -2968,6 +2968,9 @@ static int dwc3_gadget_start(struct usb_gadget *g,
|
||||
dwc->gadget_driver = driver;
|
||||
spin_unlock_irqrestore(&dwc->lock, flags);
|
||||
|
||||
if (dwc->sys_wakeup)
|
||||
device_wakeup_enable(dwc->sysdev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2983,6 +2986,9 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
|
||||
struct dwc3 *dwc = gadget_to_dwc(g);
|
||||
unsigned long flags;
|
||||
|
||||
if (dwc->sys_wakeup)
|
||||
device_wakeup_disable(dwc->sysdev);
|
||||
|
||||
spin_lock_irqsave(&dwc->lock, flags);
|
||||
dwc->gadget_driver = NULL;
|
||||
dwc->max_cfg_eps = 0;
|
||||
@ -4664,6 +4670,10 @@ int dwc3_gadget_init(struct dwc3 *dwc)
|
||||
else
|
||||
dwc3_gadget_set_speed(dwc->gadget, dwc->maximum_speed);
|
||||
|
||||
/* No system wakeup if no gadget driver bound */
|
||||
if (dwc->sys_wakeup)
|
||||
device_wakeup_disable(dwc->sysdev);
|
||||
|
||||
return 0;
|
||||
|
||||
err5:
|
||||
|
@ -123,6 +123,14 @@ int dwc3_host_init(struct dwc3 *dwc)
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dwc->sys_wakeup) {
|
||||
/* Restore wakeup setting if switched from device */
|
||||
device_wakeup_enable(dwc->sysdev);
|
||||
|
||||
/* Pass on wakeup setting to the new xhci platform device */
|
||||
device_init_wakeup(&xhci->dev, true);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
platform_device_put(xhci);
|
||||
@ -131,6 +139,9 @@ err:
|
||||
|
||||
void dwc3_host_exit(struct dwc3 *dwc)
|
||||
{
|
||||
if (dwc->sys_wakeup)
|
||||
device_init_wakeup(&dwc->xhci->dev, false);
|
||||
|
||||
platform_device_unregister(dwc->xhci);
|
||||
dwc->xhci = NULL;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user