[RFC 20/22] xhci: Fixes for suspend/resume of shared HCDs.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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.

If the host is resumed, and the power session is not lost, then make sure
to set the state of each host controller to what it was before.  (NOTE:
this code is on an unreachable code path, and I'm waiting on a formal
patch from Andiry to fix it.)

Signed-off-by: Sarah Sharp <sarah.a.sharp@xxxxxxxxxxxxxxx>
---
 drivers/usb/host/xhci-pci.c |    3 ++-
 drivers/usb/host/xhci.c     |   24 ++++++++++++++++++------
 2 files changed, 20 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 69c235f..63bd55b 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -157,7 +157,8 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 	struct xhci_hcd	*xhci = hcd_to_xhci(hcd);
 	int	retval = 0;
 
-	if (hcd->state != HC_STATE_SUSPENDED)
+	if (hcd->state != HC_STATE_SUSPENDED ||
+			hcd->shared_hcd->state != HC_STATE_SUSPENDED)
 		return -EINVAL;
 
 	retval = xhci_suspend(xhci);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index e3e5eea..0a5d168 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -680,6 +680,7 @@ int xhci_suspend(struct xhci_hcd *xhci)
 
 	spin_lock_irq(&xhci->lock);
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->shared_hcd->flags);
 	/* step 1: stop endpoint */
 	/* skipped assuming that port suspend has done */
 
@@ -730,9 +731,12 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 	u32			command, temp = 0;
 	struct usb_hcd		*hcd = xhci_to_hcd(xhci);
 	struct usb_hcd		*secondary_hcd;
-	int	old_state, retval;
+	int primary_hcd_old_state;
+	int secondary_hcd_old_state;
+	int retval;
 
-	old_state = hcd->state;
+	primary_hcd_old_state = hcd->primary_hcd->state;
+	secondary_hcd_old_state = hcd->primary_hcd->shared_hcd->state;
 	/* Wait a bit if either of the roothubs need to settle from the
 	 * transistion into bus suspend.
 	 */
@@ -811,10 +815,14 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
 
 		xhci_dbg(xhci, "Start the secondary HCD\n");
 		retval = xhci_run(secondary_hcd);
-		if (!retval)
+		if (!retval) {
 			set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+			set_bit(HCD_FLAG_HW_ACCESSIBLE,
+					&hcd->shared_hcd->flags);
+		}
 failed_restart:
 		hcd->state = HC_STATE_SUSPENDED;
+		hcd->shared_hcd->state = HC_STATE_SUSPENDED;
 		return retval;
 	}
 
@@ -835,10 +843,14 @@ failed_restart:
 	 */
 
 	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-	if (!hibernated)
-		hcd->state = old_state;
-	else
+	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->shared_hcd->flags);
+	if (!hibernated) {
+		hcd->primary_hcd->state = primary_hcd_old_state;
+		hcd->primary_hcd->shared_hcd->state = secondary_hcd_old_state;
+	} else {
 		hcd->state = HC_STATE_SUSPENDED;
+		hcd->shared_hcd->state = HC_STATE_SUSPENDED;
+	}
 
 	spin_unlock_irq(&xhci->lock);
 	return 0;
-- 
1.6.3.3

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux