lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <1446237173-15263-1-git-send-email-dianders@chromium.org>
Date:	Fri, 30 Oct 2015 13:32:53 -0700
From:	Douglas Anderson <dianders@...omium.org>
To:	johnyoun@...opsys.com, balbi@...com
Cc:	heiko@...ech.de, gregkh@...uxfoundation.org, lyz@...k-chips.com,
	wulf@...k-chips.com, dinguyen@...nsource.altera.com,
	Douglas Anderson <dianders@...omium.org>,
	linux-usb@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: [PATCH] RFT: usb: dwc2: bus suspend/resume that's not hibernate

This is an attempt to rehash commit 0cf884e819e0 ("usb: dwc2: add bus
suspend/resume for dwc2") on ToT.  That commit was reverted in commit
b0bb9bb6ce01 ("Revert "usb: dwc2: add bus suspend/resume for dwc2"")
because apparently it broke the Altera SOCFPGA.

With all the changes that have happened to dwc2 in the meantime, it's
possible that the Altera SOCFPGA will just magically work with this
change now.  ...and it would be good to get bus suspend/resume
implemented.

Signed-off-by: Douglas Anderson <dianders@...omium.org>
---
I've posted up a bunch of patches recently but tried to keep them in
separate series where it makes sense.  A summary of known patches:
All patches can be found with: https://patchwork.kernel.org/patch/<ID>/

ACKed (thanks!) and not yet landed:
 7453801  usb: dwc2: host: Fix ahbcfg for rk3066
 7467521  usb: dwc2: host: Fix remote wakeup when not in DWC2_L2

Important, not yet reviewed:
 7421171  [1/2] usb: dwc2: host: Fix missing device insertions

Fixes no known issues, not yet reviewed:
 7421181  [2/2] usb: dwc2: host: Clear interrupts before handling them

Optimization to reduce probe time (may require simple rebase):
 7348131  [1/5] usb: dwc2: Restore GUSBCFG in dwc2_get_hwparams()
 7348221  [2/5] usb: dwc2: reset dwc2 core before dwc2_get_hwparams()
 7348191  [3/5] CHROMIUM: usb: dwc2: Avoid double-reset at boot time
 7348211  [4/5] usb: dwc2: Speed dwc2_get_hwparams() on some host-only ports
 7348201  [5/5] usb: dwc2: reduce dwc2 driver probe time
 7355241  usb: dwc2: Avoid more calls to dwc2_core_reset()

Fix host port:
 7529101  usb: dwc2: optionally assert phy "full reset" when waking up
 7529081  ARM: dts: rockchip: Point rk3288 dwc2 usb at the full PHY reset

This patch:
 RFT: usb: dwc2: bus suspend/resume that's not hibernate

Abandoned for now (can't get wakeup to work on mainline):
 6727091  [REPOST,1/3] USB: Export usb_wakeup_enabled_descendants()
 6727101  [REPOST,2/3] Documentation: dt-bindings: Add snps,need-phy-for-wake for dwc2 USB
 6727121  [REPOST,3/3] USB: dwc2: Don't turn off the usbphy in suspend if wakeup is enabled

 drivers/usb/dwc2/hcd.c | 79 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 47 insertions(+), 32 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index e79baf73c234..0771fa667d0f 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2381,6 +2381,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 	unsigned long flags;
 	int ret = 0;
 	u32 hprt0;
+	u32 pcgctl;
 
 	spin_lock_irqsave(&hsotg->lock, flags);
 
@@ -2390,27 +2391,41 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 	if (!HCD_HW_ACCESSIBLE(hcd))
 		goto unlock;
 
-	if (!hsotg->core_params->hibernation)
-		goto skip_power_saving;
-
 	/*
 	 * Drive USB suspend and disable port Power
 	 * if usb bus is not suspended.
 	 */
 	if (!hsotg->bus_suspended) {
 		hprt0 = dwc2_read_hprt0(hsotg);
-		hprt0 |= HPRT0_SUSP;
-		hprt0 &= ~HPRT0_PWR;
-		dwc2_writel(hprt0, hsotg->regs + HPRT0);
+		if (hprt0 & HPRT0_CONNSTS) {
+			hprt0 |= HPRT0_SUSP;
+			if (hsotg->core_params->hibernation)
+				hprt0 &= ~HPRT0_PWR;
+			dwc2_writel(hprt0, hsotg->regs + HPRT0);
+		}
+
+		if (!hsotg->core_params->hibernation) {
+			pcgctl = readl(hsotg->regs + PCGCTL);
+			pcgctl |= PCGCTL_STOPPCLK;
+			writel(pcgctl, hsotg->regs + PCGCTL);
+		}
 	}
 
-	/* Enter hibernation */
-	ret = dwc2_enter_hibernation(hsotg);
-	if (ret) {
-		if (ret != -ENOTSUPP)
-			dev_err(hsotg->dev,
-				"enter hibernation failed\n");
-		goto skip_power_saving;
+	if (hsotg->core_params->hibernation) {
+		/* Enter hibernation */
+		ret = dwc2_enter_hibernation(hsotg);
+		if (ret) {
+			if (ret != -ENOTSUPP)
+				dev_err(hsotg->dev,
+					"enter hibernation failed\n");
+			goto skip_power_saving;
+		}
+
+		/*
+		 * After entering hibernation, hardware is no
+		 * more accessible
+		 */
+		clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	}
 
 	/* Ask phy to be suspended */
@@ -2420,9 +2435,6 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 		spin_lock_irqsave(&hsotg->lock, flags);
 	}
 
-	/* After entering hibernation, hardware is no more accessible */
-	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
 skip_power_saving:
 	hsotg->lx_state = DWC2_L2;
 unlock:
@@ -2435,6 +2447,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 {
 	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
 	unsigned long flags;
+	u32 pcgctl;
 	int ret = 0;
 
 	spin_lock_irqsave(&hsotg->lock, flags);
@@ -2442,17 +2455,6 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 	if (hsotg->lx_state != DWC2_L2)
 		goto unlock;
 
-	if (!hsotg->core_params->hibernation) {
-		hsotg->lx_state = DWC2_L0;
-		goto unlock;
-	}
-
-	/*
-	 * Set HW accessible bit before powering on the controller
-	 * since an interrupt may rise.
-	 */
-	set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
-
 	/*
 	 * Enable power if not already done.
 	 * This must not be spinlocked since duration
@@ -2464,10 +2466,22 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 		spin_lock_irqsave(&hsotg->lock, flags);
 	}
 
-	/* Exit hibernation */
-	ret = dwc2_exit_hibernation(hsotg, true);
-	if (ret && (ret != -ENOTSUPP))
-		dev_err(hsotg->dev, "exit hibernation failed\n");
+	if (hsotg->core_params->hibernation) {
+		/*
+		 * Set HW accessible bit before powering on the controller
+		 * since an interrupt may rise.
+		 */
+		set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+		/* Exit hibernation */
+		ret = dwc2_exit_hibernation(hsotg, true);
+		if (ret && (ret != -ENOTSUPP))
+			dev_err(hsotg->dev, "exit hibernation failed\n");
+	} else {
+		pcgctl = readl(hsotg->regs + PCGCTL);
+		pcgctl &= ~PCGCTL_STOPPCLK;
+		writel(pcgctl, hsotg->regs + PCGCTL);
+	}
 
 	hsotg->lx_state = DWC2_L0;
 
@@ -2480,7 +2494,8 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 		dwc2_port_resume(hsotg);
 	} else {
 		/* Wait for controller to correctly update D+/D- level */
-		usleep_range(3000, 5000);
+		if (hsotg->core_params->hibernation)
+			usleep_range(3000, 5000);
 
 		/*
 		 * Clear Port Enable and Port Status changes.
-- 
2.6.0.rc2.230.g3dd15c0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ