Skip to content

Commit

Permalink
usb: xhci: Disable runtime PM suspend for quirky controllers
Browse files Browse the repository at this point in the history
commit c8476fb855434c733099079063990e5bfa7ecad6 upstream.

If a USB controller with XHCI_RESET_ON_RESUME goes to runtime suspend,
a reset will be performed upon runtime resume. Any previously suspended
devices attached to the controller will be re-enumerated at this time.
This will cause problems, for example, if an open system call on the
device triggered the resume (the open call will fail).

Note that this change is only relevant when persist_enabled is not set
for USB devices.

This patch should be backported to kernels as old as 3.0, that
contain the commit c877b3b "xhci: Add
reset on resume quirk for asrock p67 host".

Signed-off-by: Shawn Nematbakhsh <[email protected]>
Signed-off-by: Sarah Sharp <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>
Signed-off-by: bgn9000 <[email protected]>
  • Loading branch information
snematbakhsh authored and bgn9000 committed Oct 15, 2013
1 parent d693d5e commit 04a3f6c
Showing 1 changed file with 22 additions and 0 deletions.
22 changes: 22 additions & 0 deletions drivers/usb/host/xhci.c
Original file line number Diff line number Diff line change
Expand Up @@ -2777,10 +2777,21 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct xhci_virt_device *virt_dev;
struct device *dev = hcd->self.controller;
unsigned long flags;
u32 state;
int i, ret;

#ifndef CONFIG_USB_DEFAULT_PERSIST
/*
* We called pm_runtime_get_noresume when the device was attached.
* Decrement the counter here to allow controller to runtime suspend
* if no devices remain.
*/
if (xhci->quirks & XHCI_RESET_ON_RESUME)
pm_runtime_put_noidle(dev);
#endif

ret = xhci_check_args(hcd, udev, NULL, 0, true, __func__);
/* If the host is halted due to driver unload, we still need to free the
* device.
Expand Down Expand Up @@ -2847,6 +2858,7 @@ static int xhci_reserve_host_control_ep_resources(struct xhci_hcd *xhci)
int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
struct device *dev = hcd->self.controller;
unsigned long flags;
int timeleft;
int ret;
Expand Down Expand Up @@ -2899,6 +2911,16 @@ int xhci_alloc_dev(struct usb_hcd *hcd, struct usb_device *udev)
goto disable_slot;
}
udev->slot_id = xhci->slot_id;

#ifndef CONFIG_USB_DEFAULT_PERSIST
/*
* If resetting upon resume, we can't put the controller into runtime
* suspend if there is a device attached.
*/
if (xhci->quirks & XHCI_RESET_ON_RESUME)
pm_runtime_get_noresume(dev);
#endif

/* Is this a LS or FS device under a HS hub? */
/* Hub or peripherial? */
return 1;
Expand Down

0 comments on commit 04a3f6c

Please sign in to comment.