Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

xhci: Fixes for suspend/resume of shared HCDs.

Make sure the HCD_FLAG_HW_ACCESSIBLE flag is mirrored by both roothubs,
since it refers to whether the shared hardware is accessible. Make sure
each bus is marked as suspended by setting usb_hcd->state to
HC_STATE_SUSPENDED when the PCI host controller is resumed.

Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>

+13 -4
+2 -1
drivers/usb/host/xhci-pci.c
··· 225 225 struct xhci_hcd *xhci = hcd_to_xhci(hcd); 226 226 int retval = 0; 227 227 228 - if (hcd->state != HC_STATE_SUSPENDED) 228 + if (hcd->state != HC_STATE_SUSPENDED || 229 + xhci->shared_hcd->state != HC_STATE_SUSPENDED) 229 230 return -EINVAL; 230 231 231 232 retval = xhci_suspend(xhci);
+4 -2
drivers/usb/host/xhci-ring.c
··· 2256 2256 irqreturn_t xhci_msi_irq(int irq, struct usb_hcd *hcd) 2257 2257 { 2258 2258 irqreturn_t ret; 2259 + struct xhci_hcd *xhci; 2259 2260 2261 + xhci = hcd_to_xhci(hcd); 2260 2262 set_bit(HCD_FLAG_SAW_IRQ, &hcd->flags); 2261 - if (hcd->shared_hcd) 2262 - set_bit(HCD_FLAG_SAW_IRQ, &hcd->shared_hcd->flags); 2263 + if (xhci->shared_hcd) 2264 + set_bit(HCD_FLAG_SAW_IRQ, &xhci->shared_hcd->flags); 2263 2265 2264 2266 ret = xhci_irq(hcd); 2265 2267
+7 -1
drivers/usb/host/xhci.c
··· 681 681 682 682 spin_lock_irq(&xhci->lock); 683 683 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 684 + clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); 684 685 /* step 1: stop endpoint */ 685 686 /* skipped assuming that port suspend has done */ 686 687 ··· 812 811 813 812 xhci_dbg(xhci, "Start the secondary HCD\n"); 814 813 retval = xhci_run(secondary_hcd); 815 - if (!retval) 814 + if (!retval) { 816 815 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 816 + set_bit(HCD_FLAG_HW_ACCESSIBLE, 817 + &xhci->shared_hcd->flags); 818 + } 817 819 failed_restart: 818 820 hcd->state = HC_STATE_SUSPENDED; 821 + xhci->shared_hcd->state = HC_STATE_SUSPENDED; 819 822 return retval; 820 823 } 821 824 ··· 840 835 */ 841 836 842 837 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 838 + set_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags); 843 839 844 840 spin_unlock_irq(&xhci->lock); 845 841 return 0;