All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
@ 2019-04-19 11:23 Artur Petrosyan
  2019-04-25 12:43 ` Felipe Balbi
  0 siblings, 1 reply; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:23 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

This patch set, fixes and improves partial power down and hibernation power
saving modes. Also, adds support for entering/exiting hibernation by
system issued suspend/resume.

This series contains patches which were submitted to LKML. However, a part
of those patches didn't reach to LKML because of local issue related to
smtp server.

The patches which reached to LKML are:

- usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
- usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
- usb: dwc2: Fix suspend state in host mode for partial power down.
- usb: dwc2: Fix wakeup detected and session request interrupt handlers.
- usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
- usb: dwc2: Fix dwc2_restore_device_registers() function.

The patches which didn't reach to LKML are:

- usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
- usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
- usb: dwc2: Clear fifo_map when resetting core.
- usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
- usb: dwc2: Fix hibernation between host and device modes.
- usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
- usb: dwc2: Add default param to control power optimization.
- usb: dwc2: Reset DEVADDR after exiting gadget hibernation.

Submitting all of the patches together in this version.

Changes from V0:
 - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
   "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
   interrupt handlers.


Artur Petrosyan (14):
  usb: dwc2: Fix dwc2_restore_device_registers() function.
  usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
  usb: dwc2: Fix wakeup detected and session request interrupt handlers.
  usb: dwc2: Fix suspend state in host mode for partial power down.
  usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
    function.
  usb: dwc2: Add part. power down exit from
    dwc2_conn_id_status_change().
  usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
  usb: dwc2: Add default param to control power optimization.
  usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
  usb: dwc2: Fix hibernation between host and device modes.
  usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
  usb: dwc2: Clear fifo_map when resetting core.
  usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
  usb: dwc2: Add enter/exit hibernation from system issued
    suspend/resume

 drivers/usb/dwc2/core.c      |  20 +++++
 drivers/usb/dwc2/core.h      |   3 +
 drivers/usb/dwc2/core_intr.c | 179 ++++++++++++++++++++++++++-----------------
 drivers/usb/dwc2/debugfs.c   |   2 +
 drivers/usb/dwc2/gadget.c    |  16 +++-
 drivers/usb/dwc2/hcd.c       | 151 +++++++++++++++++++++++++-----------
 drivers/usb/dwc2/params.c    |  19 +++--
 7 files changed, 269 insertions(+), 121 deletions(-)

-- 
2.11.0


^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,01/14] usb: dwc2: Fix dwc2_restore_device_registers() function.
@ 2019-04-19 11:23 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:23 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

- Added backup of DCFG register.
- Added Set the Power-On Programming done bit.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 6812a8a3a98b..dcb0fbb8bc42 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5004,6 +5004,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
 {
 	struct dwc2_dregs_backup *dr;
 	int i;
+	u32 dctl;
 
 	dev_dbg(hsotg->dev, "%s\n", __func__);
 
@@ -5019,6 +5020,15 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
 	if (!remote_wakeup)
 		dwc2_writel(hsotg, dr->dctl, DCTL);
 
+	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {
+		dwc2_writel(hsotg, dr->dcfg, DCFG);
+
+		/* Set the Power-On Programming done bit */
+		dctl = dwc2_readl(hsotg, DCTL);
+		dctl |= DCTL_PWRONPRGDONE;
+		dwc2_writel(hsotg, dctl, DCTL);
+	}
+
 	dwc2_writel(hsotg, dr->daintmsk, DAINTMSK);
 	dwc2_writel(hsotg, dr->diepmsk, DIEPMSK);
 	dwc2_writel(hsotg, dr->doepmsk, DOEPMSK);

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 01/14] usb: dwc2: Fix dwc2_restore_device_registers() function.
@ 2019-04-19 11:23 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:23 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

- Added backup of DCFG register.
- Added Set the Power-On Programming done bit.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 6812a8a3a98b..dcb0fbb8bc42 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5004,6 +5004,7 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
 {
 	struct dwc2_dregs_backup *dr;
 	int i;
+	u32 dctl;
 
 	dev_dbg(hsotg->dev, "%s\n", __func__);
 
@@ -5019,6 +5020,15 @@ int dwc2_restore_device_registers(struct dwc2_hsotg *hsotg, int remote_wakeup)
 	if (!remote_wakeup)
 		dwc2_writel(hsotg, dr->dctl, DCTL);
 
+	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_PARTIAL) {
+		dwc2_writel(hsotg, dr->dcfg, DCFG);
+
+		/* Set the Power-On Programming done bit */
+		dctl = dwc2_readl(hsotg, DCTL);
+		dctl |= DCTL_PWRONPRGDONE;
+		dwc2_writel(hsotg, dctl, DCTL);
+	}
+
 	dwc2_writel(hsotg, dr->daintmsk, DAINTMSK);
 	dwc2_writel(hsotg, dr->diepmsk, DIEPMSK);
 	dwc2_writel(hsotg, dr->doepmsk, DOEPMSK);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,02/14] usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
@ 2019-04-19 11:23 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:23 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Added dev_dbg() messages when entering and exiting from
partial power down. It is now more visible when core
enters partial power down and when exits form it.

Debug messages are added in the following functions.
- dwc2_exit_partial_power_down()
- dwc2_enter_partial_power_down()

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core.c | 8 ++++++++
 1 file changed, 8 insertions(+)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 55d5ae2a7ec7..fb471d18a3de 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -141,6 +141,8 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
 	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
 		return -ENOTSUPP;
 
+	dev_dbg(hsotg->dev, "Exiting of Partial Power Down started.\n");
+
 	pcgcctl = dwc2_readl(hsotg, PCGCTL);
 	pcgcctl &= ~PCGCTL_STOPPCLK;
 	dwc2_writel(hsotg, pcgcctl, PCGCTL);
@@ -178,6 +180,8 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
 		}
 	}
 
+	dev_dbg(hsotg->dev, "Exit Partial Power Down completes here.\n");
+
 	return ret;
 }
 
@@ -194,6 +198,8 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 	if (!hsotg->params.power_down)
 		return -ENOTSUPP;
 
+	dev_dbg(hsotg->dev, "Start of Partial Power Down completed\n");
+
 	/* Backup all registers */
 	ret = dwc2_backup_global_registers(hsotg);
 	if (ret) {
@@ -238,6 +244,8 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 	pcgcctl |= PCGCTL_STOPPCLK;
 	dwc2_writel(hsotg, pcgcctl, PCGCTL);
 
+	dev_dbg(hsotg->dev, "Partial Power Down completed\n");
+
 	return ret;
 }
 

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 02/14] usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
@ 2019-04-19 11:23 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:23 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Added dev_dbg() messages when entering and exiting from
partial power down. It is now more visible when core
enters partial power down and when exits form it.

Debug messages are added in the following functions.
- dwc2_exit_partial_power_down()
- dwc2_enter_partial_power_down()

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core.c | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 55d5ae2a7ec7..fb471d18a3de 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -141,6 +141,8 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
 	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
 		return -ENOTSUPP;
 
+	dev_dbg(hsotg->dev, "Exiting of Partial Power Down started.\n");
+
 	pcgcctl = dwc2_readl(hsotg, PCGCTL);
 	pcgcctl &= ~PCGCTL_STOPPCLK;
 	dwc2_writel(hsotg, pcgcctl, PCGCTL);
@@ -178,6 +180,8 @@ int dwc2_exit_partial_power_down(struct dwc2_hsotg *hsotg, bool restore)
 		}
 	}
 
+	dev_dbg(hsotg->dev, "Exit Partial Power Down completes here.\n");
+
 	return ret;
 }
 
@@ -194,6 +198,8 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 	if (!hsotg->params.power_down)
 		return -ENOTSUPP;
 
+	dev_dbg(hsotg->dev, "Start of Partial Power Down completed\n");
+
 	/* Backup all registers */
 	ret = dwc2_backup_global_registers(hsotg);
 	if (ret) {
@@ -238,6 +244,8 @@ int dwc2_enter_partial_power_down(struct dwc2_hsotg *hsotg)
 	pcgcctl |= PCGCTL_STOPPCLK;
 	dwc2_writel(hsotg, pcgcctl, PCGCTL);
 
+	dev_dbg(hsotg->dev, "Partial Power Down completed\n");
+
 	return ret;
 }
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers.
@ 2019-04-19 11:23 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:23 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

In host mode port power must be turned on when wakeup
detected or session request interrupt is detected.
Because, otherwise core wouldn't exit form partial
power down.

- Turned on the port power by setting HPRT0_PWR bit.

- Called dwc2_hcd_connect() function after enabling
  the power of the port.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 19ae2595f1c3..06f8022b1bdb 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -312,6 +312,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 {
 	int ret;
+	u32 hprt0;
 
 	/* Clear interrupt */
 	dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
@@ -320,7 +321,9 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 		hsotg->lx_state);
 
 	if (dwc2_is_device_mode(hsotg)) {
-		if (hsotg->lx_state == DWC2_L2) {
+		if (hsotg->lx_state == DWC2_L2 &&
+		    hsotg->params.power_down ==
+		    DWC2_POWER_DOWN_PARAM_PARTIAL) {
 			ret = dwc2_exit_partial_power_down(hsotg, true);
 			if (ret && (ret != -ENOTSUPP))
 				dev_err(hsotg->dev,
@@ -332,6 +335,14 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 		 * established
 		 */
 		dwc2_hsotg_disconnect(hsotg);
+	} else {
+		/* Turn on the port power bit. */
+		hprt0 = dwc2_read_hprt0(hsotg);
+		hprt0 |= HPRT0_PWR;
+		dwc2_writel(hsotg, hprt0, HPRT0);
+
+		/* Connect hcd after port power is set. */
+		dwc2_hcd_connect(hsotg);
 	}
 }
 
@@ -396,6 +407,7 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
 static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 {
 	int ret;
+	u32 hprt0;
 
 	/* Clear interrupt */
 	dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
@@ -426,8 +438,6 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 		/* Change to L0 state */
 		hsotg->lx_state = DWC2_L0;
 	} else {
-		if (hsotg->params.power_down)
-			return;
 
 		if (hsotg->lx_state != DWC2_L1) {
 			u32 pcgcctl = dwc2_readl(hsotg, PCGCTL);
@@ -435,6 +445,15 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 			/* Restart the Phy Clock */
 			pcgcctl &= ~PCGCTL_STOPPCLK;
 			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+			/* Turn on the port power bit. */
+			hprt0 = dwc2_read_hprt0(hsotg);
+			hprt0 |= HPRT0_PWR;
+			dwc2_writel(hsotg, hprt0, HPRT0);
+
+			/* Connect hcd. */
+			dwc2_hcd_connect(hsotg);
+
 			mod_timer(&hsotg->wkp_timer,
 				  jiffies + msecs_to_jiffies(71));
 		} else {

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers.
@ 2019-04-19 11:23 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:23 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

In host mode port power must be turned on when wakeup
detected or session request interrupt is detected.
Because, otherwise core wouldn't exit form partial
power down.

- Turned on the port power by setting HPRT0_PWR bit.

- Called dwc2_hcd_connect() function after enabling
  the power of the port.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 25 ++++++++++++++++++++++---
 1 file changed, 22 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 19ae2595f1c3..06f8022b1bdb 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -312,6 +312,7 @@ static void dwc2_handle_conn_id_status_change_intr(struct dwc2_hsotg *hsotg)
 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 {
 	int ret;
+	u32 hprt0;
 
 	/* Clear interrupt */
 	dwc2_writel(hsotg, GINTSTS_SESSREQINT, GINTSTS);
@@ -320,7 +321,9 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 		hsotg->lx_state);
 
 	if (dwc2_is_device_mode(hsotg)) {
-		if (hsotg->lx_state == DWC2_L2) {
+		if (hsotg->lx_state == DWC2_L2 &&
+		    hsotg->params.power_down ==
+		    DWC2_POWER_DOWN_PARAM_PARTIAL) {
 			ret = dwc2_exit_partial_power_down(hsotg, true);
 			if (ret && (ret != -ENOTSUPP))
 				dev_err(hsotg->dev,
@@ -332,6 +335,14 @@ static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 		 * established
 		 */
 		dwc2_hsotg_disconnect(hsotg);
+	} else {
+		/* Turn on the port power bit. */
+		hprt0 = dwc2_read_hprt0(hsotg);
+		hprt0 |= HPRT0_PWR;
+		dwc2_writel(hsotg, hprt0, HPRT0);
+
+		/* Connect hcd after port power is set. */
+		dwc2_hcd_connect(hsotg);
 	}
 }
 
@@ -396,6 +407,7 @@ static void dwc2_wakeup_from_lpm_l1(struct dwc2_hsotg *hsotg)
 static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 {
 	int ret;
+	u32 hprt0;
 
 	/* Clear interrupt */
 	dwc2_writel(hsotg, GINTSTS_WKUPINT, GINTSTS);
@@ -426,8 +438,6 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 		/* Change to L0 state */
 		hsotg->lx_state = DWC2_L0;
 	} else {
-		if (hsotg->params.power_down)
-			return;
 
 		if (hsotg->lx_state != DWC2_L1) {
 			u32 pcgcctl = dwc2_readl(hsotg, PCGCTL);
@@ -435,6 +445,15 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
 			/* Restart the Phy Clock */
 			pcgcctl &= ~PCGCTL_STOPPCLK;
 			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+			/* Turn on the port power bit. */
+			hprt0 = dwc2_read_hprt0(hsotg);
+			hprt0 |= HPRT0_PWR;
+			dwc2_writel(hsotg, hprt0, HPRT0);
+
+			/* Connect hcd. */
+			dwc2_hcd_connect(hsotg);
+
 			mod_timer(&hsotg->wkp_timer,
 				  jiffies + msecs_to_jiffies(71));
 		} else {
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

- In dwc2_port_suspend() function added waiting for the
  HPRT0.PrtSusp register field to be set.

- In _dwc2_hcd_suspend() function added checking of
  "hsotg->flags.b.port_connect_status" port connection
  status if port connection status is 0 then skipping
  power saving (entering partial power down mode).
  Because if there is no device connected there would
  be no need to enter partial power down mode.

- Added "hsotg->bus_suspended = true" beceuse after
  entering partial power down in host mode the
  bus_suspended flag must be set.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index dd82fa516f3f..1d18258b5ff8 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3479,6 +3479,10 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
 	hprt0 |= HPRT0_SUSP;
 	dwc2_writel(hsotg, hprt0, HPRT0);
 
+	/* Wait for the HPRT0.PrtSusp register field to be set */
+	if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
+		dev_warn(hsotg->dev, "Suspend wasn't generated\n");
+
 	hsotg->bus_suspended = true;
 
 	/*
@@ -4488,7 +4492,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 	if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
+	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	    hsotg->flags.b.port_connect_status == 0)
 		goto skip_power_saving;
 
 	/*
@@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 		goto skip_power_saving;
 	}
 
+	hsotg->bus_suspended = true;
+
 	/* Ask phy to be suspended */
 	if (!IS_ERR_OR_NULL(hsotg->uphy)) {
 		spin_unlock_irqrestore(&hsotg->lock, flags);

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

- In dwc2_port_suspend() function added waiting for the
  HPRT0.PrtSusp register field to be set.

- In _dwc2_hcd_suspend() function added checking of
  "hsotg->flags.b.port_connect_status" port connection
  status if port connection status is 0 then skipping
  power saving (entering partial power down mode).
  Because if there is no device connected there would
  be no need to enter partial power down mode.

- Added "hsotg->bus_suspended = true" beceuse after
  entering partial power down in host mode the
  bus_suspended flag must be set.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index dd82fa516f3f..1d18258b5ff8 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3479,6 +3479,10 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
 	hprt0 |= HPRT0_SUSP;
 	dwc2_writel(hsotg, hprt0, HPRT0);
 
+	/* Wait for the HPRT0.PrtSusp register field to be set */
+	if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
+		dev_warn(hsotg->dev, "Suspend wasn't generated\n");
+
 	hsotg->bus_suspended = true;
 
 	/*
@@ -4488,7 +4492,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 	if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
+	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	    hsotg->flags.b.port_connect_status == 0)
 		goto skip_power_saving;
 
 	/*
@@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 		goto skip_power_saving;
 	}
 
+	hsotg->bus_suspended = true;
+
 	/* Ask phy to be suspended */
 	if (!IS_ERR_OR_NULL(hsotg->uphy)) {
 		spin_unlock_irqrestore(&hsotg->lock, flags);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,05/14] usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Added port connection status checking which prevents exiting from
Partial Power Down mode from _dwc2_hcd_resume() when no entering
to Partial Power Down mode happened.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 1d18258b5ff8..8367902a47eb 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4544,6 +4544,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
 	unsigned long flags;
 	int ret = 0;
+	u32 hprt0;
+
+	hprt0 = dwc2_read_hprt0(hsotg);
 
 	spin_lock_irqsave(&hsotg->lock, flags);
 
@@ -4553,7 +4556,8 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 	if (hsotg->lx_state != DWC2_L2)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
+	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	    hprt0 & HPRT0_CONNSTS) {
 		hsotg->lx_state = DWC2_L0;
 		goto unlock;
 	}

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 05/14] usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Added port connection status checking which prevents exiting from
Partial Power Down mode from _dwc2_hcd_resume() when no entering
to Partial Power Down mode happened.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 1d18258b5ff8..8367902a47eb 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4544,6 +4544,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
 	unsigned long flags;
 	int ret = 0;
+	u32 hprt0;
+
+	hprt0 = dwc2_read_hprt0(hsotg);
 
 	spin_lock_irqsave(&hsotg->lock, flags);
 
@@ -4553,7 +4556,8 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 	if (hsotg->lx_state != DWC2_L2)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
+	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	    hprt0 & HPRT0_CONNSTS) {
 		hsotg->lx_state = DWC2_L0;
 		goto unlock;
 	}
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,06/14] usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Before changing to connector B exiting from Partial
Power Down is required.

- Added exiting from Partial Power Down mode when
  connector ID status changes to "connId B".
  Because if connector ID status changed to B connector
  while core was in partial power down mode, HANG would
  accrue from a soft reset.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 8367902a47eb..54450fa352cf 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3348,6 +3348,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 						wf_otg);
 	u32 count = 0;
 	u32 gotgctl;
+	u32 pcgcctl;
 	unsigned long flags;
 
 	dev_dbg(hsotg->dev, "%s()\n", __func__);
@@ -3387,6 +3388,23 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 		if (count > 250)
 			dev_err(hsotg->dev,
 				"Connection id status change timed out\n");
+
+		if (hsotg->params.power_down ==
+		    DWC2_POWER_DOWN_PARAM_PARTIAL &&
+		    hsotg->lx_state == DWC2_L2) {
+			pcgcctl = dwc2_readl(hsotg, PCGCTL);
+			pcgcctl &= ~PCGCTL_STOPPCLK;
+			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+			pcgcctl = dwc2_readl(hsotg, PCGCTL);
+			pcgcctl &= ~PCGCTL_PWRCLMP;
+			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+			pcgcctl = dwc2_readl(hsotg, PCGCTL);
+			pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
+			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+		}
+
 		hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 		dwc2_core_init(hsotg, false);
 		dwc2_enable_global_interrupts(hsotg);

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 06/14] usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Before changing to connector B exiting from Partial
Power Down is required.

- Added exiting from Partial Power Down mode when
  connector ID status changes to "connId B".
  Because if connector ID status changed to B connector
  while core was in partial power down mode, HANG would
  accrue from a soft reset.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 8367902a47eb..54450fa352cf 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3348,6 +3348,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 						wf_otg);
 	u32 count = 0;
 	u32 gotgctl;
+	u32 pcgcctl;
 	unsigned long flags;
 
 	dev_dbg(hsotg->dev, "%s()\n", __func__);
@@ -3387,6 +3388,23 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 		if (count > 250)
 			dev_err(hsotg->dev,
 				"Connection id status change timed out\n");
+
+		if (hsotg->params.power_down ==
+		    DWC2_POWER_DOWN_PARAM_PARTIAL &&
+		    hsotg->lx_state == DWC2_L2) {
+			pcgcctl = dwc2_readl(hsotg, PCGCTL);
+			pcgcctl &= ~PCGCTL_STOPPCLK;
+			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+			pcgcctl = dwc2_readl(hsotg, PCGCTL);
+			pcgcctl &= ~PCGCTL_PWRCLMP;
+			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+
+			pcgcctl = dwc2_readl(hsotg, PCGCTL);
+			pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
+			dwc2_writel(hsotg, pcgcctl, PCGCTL);
+		}
+
 		hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 		dwc2_core_init(hsotg, false);
 		dwc2_enable_global_interrupts(hsotg);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,07/14] usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Initially resetting device address was done in dwc2_hsotg_irq()
interrupt handler. However, when core is hibernated USB RESET
is not handled in dwc2_hsotg_irq() handler, instead USB RESET
interrupt is handled in dwc2_handle_gpwrdn_intr() handler.

- Added reset device address to zero when core exits from gadget
  hibernation.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 4 ++++
 1 file changed, 4 insertions(+)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index dcb0fbb8bc42..8c3e1f1c1b0f 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5234,6 +5234,10 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 	/* Restore GUSBCFG, DCFG and DCTL */
 	dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG);
 	dwc2_writel(hsotg, dr->dcfg, DCFG);
+
+	/* On USB Reset, reset device address to zero */
+	if (reset)
+		dwc2_clear_bit(hsotg, DCFG, DCFG_DEVADDR_MASK);
 	dwc2_writel(hsotg, dr->dctl, DCTL);
 
 	/* De-assert Wakeup Logic */

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 07/14] usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Initially resetting device address was done in dwc2_hsotg_irq()
interrupt handler. However, when core is hibernated USB RESET
is not handled in dwc2_hsotg_irq() handler, instead USB RESET
interrupt is handled in dwc2_handle_gpwrdn_intr() handler.

- Added reset device address to zero when core exits from gadget
  hibernation.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/gadget.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index dcb0fbb8bc42..8c3e1f1c1b0f 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -5234,6 +5234,10 @@ int dwc2_gadget_exit_hibernation(struct dwc2_hsotg *hsotg,
 	/* Restore GUSBCFG, DCFG and DCTL */
 	dwc2_writel(hsotg, gr->gusbcfg, GUSBCFG);
 	dwc2_writel(hsotg, dr->dcfg, DCFG);
+
+	/* On USB Reset, reset device address to zero */
+	if (reset)
+		dwc2_clear_bit(hsotg, DCFG, DCFG_DEVADDR_MASK);
 	dwc2_writel(hsotg, dr->dctl, DCTL);
 
 	/* De-assert Wakeup Logic */
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

- Added a default param "power_saving" to enable or
  disable hibernation or partial power down features.

- Printed hibernation param in hw_params_show and
  power_saving param in params_show.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/core.h    |  3 +++
 drivers/usb/dwc2/debugfs.c |  2 ++
 drivers/usb/dwc2/params.c  | 19 +++++++++++++------
 3 files changed, 18 insertions(+), 6 deletions(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 30bab8463c96..9221933ab64e 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -373,6 +373,8 @@ enum dwc2_ep0_state {
  *                      case.
  *                      0 - No (default)
  *                      1 - Yes
+ * @power_saving:	Specifies if power saving is enabled or not. If it is
+ *			enabled power_down functionality will be enabled.
  * @power_down:         Specifies whether the controller support power_down.
  *			If power_down is enabled, the controller will enter
  *			power_down in both peripheral and host mode when
@@ -469,6 +471,7 @@ struct dwc2_core_params {
 	bool uframe_sched;
 	bool external_id_pin_ctl;
 
+	unsigned int power_saving:1;
 	int power_down;
 #define DWC2_POWER_DOWN_PARAM_NONE		0
 #define DWC2_POWER_DOWN_PARAM_PARTIAL		1
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
index 7f62f4cdc265..8b27cf0b682b 100644
--- a/drivers/usb/dwc2/debugfs.c
+++ b/drivers/usb/dwc2/debugfs.c
@@ -695,6 +695,7 @@ static int params_show(struct seq_file *seq, void *v)
 	print_param_hex(seq, p, ahbcfg);
 	print_param(seq, p, uframe_sched);
 	print_param(seq, p, external_id_pin_ctl);
+	print_param(seq, p, power_saving);
 	print_param(seq, p, power_down);
 	print_param(seq, p, lpm);
 	print_param(seq, p, lpm_clock_gating);
@@ -746,6 +747,7 @@ static int hw_params_show(struct seq_file *seq, void *v)
 	print_param(seq, hw, num_dev_perio_in_ep);
 	print_param(seq, hw, total_fifo_size);
 	print_param(seq, hw, power_optimized);
+	print_param(seq, hw, hibernation);
 	print_param(seq, hw, utmi_phy_data_width);
 	print_param_hex(seq, hw, snpsid);
 	print_param_hex(seq, hw, dev_ep_dirs);
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 24ff5f21cb25..d7cc336aa1b7 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -263,12 +263,18 @@ static void dwc2_set_param_power_down(struct dwc2_hsotg *hsotg)
 {
 	int val;
 
-	if (hsotg->hw_params.hibernation)
-		val = 2;
-	else if (hsotg->hw_params.power_optimized)
-		val = 1;
-	else
-		val = 0;
+	if (!hsotg->params.power_saving) {
+		val = DWC2_POWER_DOWN_PARAM_NONE;
+		dev_dbg(hsotg->dev, "%s: Power saving is disabled.\n",
+			__func__);
+	} else {
+		if (hsotg->hw_params.hibernation)
+			val = DWC2_POWER_DOWN_PARAM_HIBERNATION;
+		else if (hsotg->hw_params.power_optimized)
+			val = DWC2_POWER_DOWN_PARAM_PARTIAL;
+		else
+			val = DWC2_POWER_DOWN_PARAM_NONE;
+	}
 
 	hsotg->params.power_down = val;
 }
@@ -290,6 +296,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
 	dwc2_set_param_phy_type(hsotg);
 	dwc2_set_param_speed(hsotg);
 	dwc2_set_param_phy_utmi_width(hsotg);
+	p->power_saving = true;
 	dwc2_set_param_power_down(hsotg);
 	p->phy_ulpi_ddr = false;
 	p->phy_ulpi_ext_vbus = false;

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

- Added a default param "power_saving" to enable or
  disable hibernation or partial power down features.

- Printed hibernation param in hw_params_show and
  power_saving param in params_show.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/core.h    |  3 +++
 drivers/usb/dwc2/debugfs.c |  2 ++
 drivers/usb/dwc2/params.c  | 19 +++++++++++++------
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 30bab8463c96..9221933ab64e 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -373,6 +373,8 @@ enum dwc2_ep0_state {
  *                      case.
  *                      0 - No (default)
  *                      1 - Yes
+ * @power_saving:	Specifies if power saving is enabled or not. If it is
+ *			enabled power_down functionality will be enabled.
  * @power_down:         Specifies whether the controller support power_down.
  *			If power_down is enabled, the controller will enter
  *			power_down in both peripheral and host mode when
@@ -469,6 +471,7 @@ struct dwc2_core_params {
 	bool uframe_sched;
 	bool external_id_pin_ctl;
 
+	unsigned int power_saving:1;
 	int power_down;
 #define DWC2_POWER_DOWN_PARAM_NONE		0
 #define DWC2_POWER_DOWN_PARAM_PARTIAL		1
diff --git a/drivers/usb/dwc2/debugfs.c b/drivers/usb/dwc2/debugfs.c
index 7f62f4cdc265..8b27cf0b682b 100644
--- a/drivers/usb/dwc2/debugfs.c
+++ b/drivers/usb/dwc2/debugfs.c
@@ -695,6 +695,7 @@ static int params_show(struct seq_file *seq, void *v)
 	print_param_hex(seq, p, ahbcfg);
 	print_param(seq, p, uframe_sched);
 	print_param(seq, p, external_id_pin_ctl);
+	print_param(seq, p, power_saving);
 	print_param(seq, p, power_down);
 	print_param(seq, p, lpm);
 	print_param(seq, p, lpm_clock_gating);
@@ -746,6 +747,7 @@ static int hw_params_show(struct seq_file *seq, void *v)
 	print_param(seq, hw, num_dev_perio_in_ep);
 	print_param(seq, hw, total_fifo_size);
 	print_param(seq, hw, power_optimized);
+	print_param(seq, hw, hibernation);
 	print_param(seq, hw, utmi_phy_data_width);
 	print_param_hex(seq, hw, snpsid);
 	print_param_hex(seq, hw, dev_ep_dirs);
diff --git a/drivers/usb/dwc2/params.c b/drivers/usb/dwc2/params.c
index 24ff5f21cb25..d7cc336aa1b7 100644
--- a/drivers/usb/dwc2/params.c
+++ b/drivers/usb/dwc2/params.c
@@ -263,12 +263,18 @@ static void dwc2_set_param_power_down(struct dwc2_hsotg *hsotg)
 {
 	int val;
 
-	if (hsotg->hw_params.hibernation)
-		val = 2;
-	else if (hsotg->hw_params.power_optimized)
-		val = 1;
-	else
-		val = 0;
+	if (!hsotg->params.power_saving) {
+		val = DWC2_POWER_DOWN_PARAM_NONE;
+		dev_dbg(hsotg->dev, "%s: Power saving is disabled.\n",
+			__func__);
+	} else {
+		if (hsotg->hw_params.hibernation)
+			val = DWC2_POWER_DOWN_PARAM_HIBERNATION;
+		else if (hsotg->hw_params.power_optimized)
+			val = DWC2_POWER_DOWN_PARAM_PARTIAL;
+		else
+			val = DWC2_POWER_DOWN_PARAM_NONE;
+	}
 
 	hsotg->params.power_down = val;
 }
@@ -290,6 +296,7 @@ static void dwc2_set_default_params(struct dwc2_hsotg *hsotg)
 	dwc2_set_param_phy_type(hsotg);
 	dwc2_set_param_speed(hsotg);
 	dwc2_set_param_phy_utmi_width(hsotg);
+	p->power_saving = true;
 	dwc2_set_param_power_down(hsotg);
 	p->phy_ulpi_ddr = false;
 	p->phy_ulpi_ext_vbus = false;
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

To avoid working in two modes (partial power down
and hibernation) changed conditions for entering
partial power down or hibernation.

Instead of checking hw_params.power_optimized and
hw_params.hibernation now checking power_down
param which already set to one of the options
(Hibernation or Partial Power Down) based on
OTG_EN_PWROPT.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 06f8022b1bdb..fc465707b7a1 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -517,14 +517,15 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
 			return;
 		}
 		if (dsts & DSTS_SUSPSTS) {
-			if (hsotg->hw_params.power_optimized) {
+			switch (hsotg->params.power_down) {
+			case DWC2_POWER_DOWN_PARAM_PARTIAL:
 				ret = dwc2_enter_partial_power_down(hsotg);
 				if (ret) {
 					if (ret != -ENOTSUPP)
 						dev_err(hsotg->dev,
 							"%s: enter partial_power_down failed\n",
 							__func__);
-					goto skip_power_saving;
+					break;
 				}
 
 				udelay(100);
@@ -532,16 +533,16 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
 				/* Ask phy to be suspended */
 				if (!IS_ERR_OR_NULL(hsotg->uphy))
 					usb_phy_set_suspend(hsotg->uphy, true);
-			}
-
-			if (hsotg->hw_params.hibernation) {
+				break;
+			case DWC2_POWER_DOWN_PARAM_HIBERNATION:
 				ret = dwc2_enter_hibernation(hsotg, 0);
 				if (ret && ret != -ENOTSUPP)
 					dev_err(hsotg->dev,
 						"%s: enter hibernation failed\n",
 						__func__);
+				break;
 			}
-skip_power_saving:
+
 			/*
 			 * Change to L2 (suspend) state before releasing
 			 * spinlock

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
@ 2019-04-19 11:24 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:24 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

To avoid working in two modes (partial power down
and hibernation) changed conditions for entering
partial power down or hibernation.

Instead of checking hw_params.power_optimized and
hw_params.hibernation now checking power_down
param which already set to one of the options
(Hibernation or Partial Power Down) based on
OTG_EN_PWROPT.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 06f8022b1bdb..fc465707b7a1 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -517,14 +517,15 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
 			return;
 		}
 		if (dsts & DSTS_SUSPSTS) {
-			if (hsotg->hw_params.power_optimized) {
+			switch (hsotg->params.power_down) {
+			case DWC2_POWER_DOWN_PARAM_PARTIAL:
 				ret = dwc2_enter_partial_power_down(hsotg);
 				if (ret) {
 					if (ret != -ENOTSUPP)
 						dev_err(hsotg->dev,
 							"%s: enter partial_power_down failed\n",
 							__func__);
-					goto skip_power_saving;
+					break;
 				}
 
 				udelay(100);
@@ -532,16 +533,16 @@ static void dwc2_handle_usb_suspend_intr(struct dwc2_hsotg *hsotg)
 				/* Ask phy to be suspended */
 				if (!IS_ERR_OR_NULL(hsotg->uphy))
 					usb_phy_set_suspend(hsotg->uphy, true);
-			}
-
-			if (hsotg->hw_params.hibernation) {
+				break;
+			case DWC2_POWER_DOWN_PARAM_HIBERNATION:
 				ret = dwc2_enter_hibernation(hsotg, 0);
 				if (ret && ret != -ENOTSUPP)
 					dev_err(hsotg->dev,
 						"%s: enter hibernation failed\n",
 						__func__);
+				break;
 			}
-skip_power_saving:
+
 			/*
 			 * Change to L2 (suspend) state before releasing
 			 * spinlock
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,10/14] usb: dwc2: Fix hibernation between host and device modes.
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

When core is in hibernation in host mode and a device cable
was connected than driver exited from device hibernation.
However, registers saved for host mode and when exited from
device hibernation register restore would be done for device
register which was wrong because there was no device registers
stored to restore.

- Added dwc_handle_gpwrdn_disc_det() function which handles
  gpwrdn disconnect detect flow and exits hibernation
  without restoring the registers.
- Updated exiting from hibernation in GPWRDN_STS_CHGINT with
  calling dwc_handle_gpwrdn_disc_det() function. Here no register
  is restored which is the solution described above.
- Increased the waiting timeout for HPRT0.PrtSusp register field
  to be set. Because on HiKey 960 board HPRT0.PrtSusp wasn't
  generated with the existing timeout.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 139 ++++++++++++++++++++++++-------------------
 drivers/usb/dwc2/hcd.c       |   2 +-
 2 files changed, 80 insertions(+), 61 deletions(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index fc465707b7a1..40d296d9b6fb 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -662,6 +662,70 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
 		return 0;
 }
 
+/**
+ * This function handles the gpwrdn disconnect detect.
+ * Exits hibernation without restoring registers.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @gpwrdn: GPWRDN register
+ */
+static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
+					      u32 gpwrdn)
+{
+	u32 gpwrdn_tmp;
+
+	/* Switch-on voltage to the core */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Reset core */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Disable Power Down Clamp */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Deassert reset core */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Disable PMU interrupt */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+
+	/* De-assert Wakeup Logic */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PMUACTV;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+
+	hsotg->hibernated = 0;
+
+	if (gpwrdn & GPWRDN_IDSTS) {
+		hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+		dwc2_core_init(hsotg, false);
+		dwc2_enable_global_interrupts(hsotg);
+		dwc2_hsotg_core_init_disconnected(hsotg, false);
+		dwc2_hsotg_core_connect(hsotg);
+	} else {
+		hsotg->op_state = OTG_STATE_A_HOST;
+
+		/* Initialize the Core for Host mode */
+		dwc2_core_init(hsotg, false);
+		dwc2_enable_global_interrupts(hsotg);
+		dwc2_hcd_start(hsotg);
+	}
+}
+
 /*
  * GPWRDN interrupt handler.
  *
@@ -683,60 +747,12 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
 
 	if ((gpwrdn & GPWRDN_DISCONN_DET) &&
 	    (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
-		u32 gpwrdn_tmp;
-
 		dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
-
-		/* Switch-on voltage to the core */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Reset core */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Disable Power Down Clamp */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Deassert reset core */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Disable PMU interrupt */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-
-		/* De-assert Wakeup Logic */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PMUACTV;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-
-		hsotg->hibernated = 0;
-
-		if (gpwrdn & GPWRDN_IDSTS) {
-			hsotg->op_state = OTG_STATE_B_PERIPHERAL;
-			dwc2_core_init(hsotg, false);
-			dwc2_enable_global_interrupts(hsotg);
-			dwc2_hsotg_core_init_disconnected(hsotg, false);
-			dwc2_hsotg_core_connect(hsotg);
-		} else {
-			hsotg->op_state = OTG_STATE_A_HOST;
-
-			/* Initialize the Core for Host mode */
-			dwc2_core_init(hsotg, false);
-			dwc2_enable_global_interrupts(hsotg);
-			dwc2_hcd_start(hsotg);
-		}
+		/*
+		 * Call disconnect detect function to exit from
+		 * hibernation
+		 */
+		dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
 	}
 
 	if ((gpwrdn & GPWRDN_LNSTSCHG) &&
@@ -752,22 +768,25 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
 			}
 		}
 	}
+
 	if ((gpwrdn & GPWRDN_RST_DET) && (gpwrdn & GPWRDN_RST_DET_MSK)) {
 		dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
 		if (!linestate && (gpwrdn & GPWRDN_BSESSVLD))
 			dwc2_exit_hibernation(hsotg, 0, 1, 0);
 	}
+
 	if ((gpwrdn & GPWRDN_STS_CHGINT) &&
-	    (gpwrdn & GPWRDN_STS_CHGINT_MSK) && linestate) {
+	    (gpwrdn & GPWRDN_STS_CHGINT_MSK)) {
 		dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
 		if (hsotg->hw_params.hibernation &&
 		    hsotg->hibernated) {
-			if (gpwrdn & GPWRDN_IDSTS) {
-				dwc2_exit_hibernation(hsotg, 0, 0, 0);
-				call_gadget(hsotg, resume);
-			} else {
-				dwc2_exit_hibernation(hsotg, 1, 0, 1);
-			}
+			/*
+			 * As GPWRDN_STS_CHGINT exit from hibernation flow is
+			 * the same as in GPWRDN_DISCONN_DET flow. Call
+			 * disconnect detect helper function to exit from
+			 * hibernation.
+			 */
+			dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
 		}
 	}
 }
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 54450fa352cf..45d4a3e1ebd2 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5570,7 +5570,7 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
 	dwc2_writel(hsotg, hprt0, HPRT0);
 
 	/* Wait for the HPRT0.PrtSusp register field to be set */
-	if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
+	if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 5000))
 		dev_warn(hsotg->dev, "Suspend wasn't generated\n");
 
 	/*

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 10/14] usb: dwc2: Fix hibernation between host and device modes.
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

When core is in hibernation in host mode and a device cable
was connected than driver exited from device hibernation.
However, registers saved for host mode and when exited from
device hibernation register restore would be done for device
register which was wrong because there was no device registers
stored to restore.

- Added dwc_handle_gpwrdn_disc_det() function which handles
  gpwrdn disconnect detect flow and exits hibernation
  without restoring the registers.
- Updated exiting from hibernation in GPWRDN_STS_CHGINT with
  calling dwc_handle_gpwrdn_disc_det() function. Here no register
  is restored which is the solution described above.
- Increased the waiting timeout for HPRT0.PrtSusp register field
  to be set. Because on HiKey 960 board HPRT0.PrtSusp wasn't
  generated with the existing timeout.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 139 ++++++++++++++++++++++++-------------------
 drivers/usb/dwc2/hcd.c       |   2 +-
 2 files changed, 80 insertions(+), 61 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index fc465707b7a1..40d296d9b6fb 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -662,6 +662,70 @@ static u32 dwc2_read_common_intr(struct dwc2_hsotg *hsotg)
 		return 0;
 }
 
+/**
+ * This function handles the gpwrdn disconnect detect.
+ * Exits hibernation without restoring registers.
+ *
+ * @hsotg: Programming view of DWC_otg controller
+ * @gpwrdn: GPWRDN register
+ */
+static inline void dwc_handle_gpwrdn_disc_det(struct dwc2_hsotg *hsotg,
+					      u32 gpwrdn)
+{
+	u32 gpwrdn_tmp;
+
+	/* Switch-on voltage to the core */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Reset core */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Disable Power Down Clamp */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Deassert reset core */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+	udelay(10);
+
+	/* Disable PMU interrupt */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+
+	/* De-assert Wakeup Logic */
+	gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
+	gpwrdn_tmp &= ~GPWRDN_PMUACTV;
+	dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
+
+	hsotg->hibernated = 0;
+
+	if (gpwrdn & GPWRDN_IDSTS) {
+		hsotg->op_state = OTG_STATE_B_PERIPHERAL;
+		dwc2_core_init(hsotg, false);
+		dwc2_enable_global_interrupts(hsotg);
+		dwc2_hsotg_core_init_disconnected(hsotg, false);
+		dwc2_hsotg_core_connect(hsotg);
+	} else {
+		hsotg->op_state = OTG_STATE_A_HOST;
+
+		/* Initialize the Core for Host mode */
+		dwc2_core_init(hsotg, false);
+		dwc2_enable_global_interrupts(hsotg);
+		dwc2_hcd_start(hsotg);
+	}
+}
+
 /*
  * GPWRDN interrupt handler.
  *
@@ -683,60 +747,12 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
 
 	if ((gpwrdn & GPWRDN_DISCONN_DET) &&
 	    (gpwrdn & GPWRDN_DISCONN_DET_MSK) && !linestate) {
-		u32 gpwrdn_tmp;
-
 		dev_dbg(hsotg->dev, "%s: GPWRDN_DISCONN_DET\n", __func__);
-
-		/* Switch-on voltage to the core */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PWRDNSWTCH;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Reset core */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PWRDNRSTN;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Disable Power Down Clamp */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PWRDNCLMP;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Deassert reset core */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp |= GPWRDN_PWRDNRSTN;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-		udelay(10);
-
-		/* Disable PMU interrupt */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PMUINTSEL;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-
-		/* De-assert Wakeup Logic */
-		gpwrdn_tmp = dwc2_readl(hsotg, GPWRDN);
-		gpwrdn_tmp &= ~GPWRDN_PMUACTV;
-		dwc2_writel(hsotg, gpwrdn_tmp, GPWRDN);
-
-		hsotg->hibernated = 0;
-
-		if (gpwrdn & GPWRDN_IDSTS) {
-			hsotg->op_state = OTG_STATE_B_PERIPHERAL;
-			dwc2_core_init(hsotg, false);
-			dwc2_enable_global_interrupts(hsotg);
-			dwc2_hsotg_core_init_disconnected(hsotg, false);
-			dwc2_hsotg_core_connect(hsotg);
-		} else {
-			hsotg->op_state = OTG_STATE_A_HOST;
-
-			/* Initialize the Core for Host mode */
-			dwc2_core_init(hsotg, false);
-			dwc2_enable_global_interrupts(hsotg);
-			dwc2_hcd_start(hsotg);
-		}
+		/*
+		 * Call disconnect detect function to exit from
+		 * hibernation
+		 */
+		dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
 	}
 
 	if ((gpwrdn & GPWRDN_LNSTSCHG) &&
@@ -752,22 +768,25 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
 			}
 		}
 	}
+
 	if ((gpwrdn & GPWRDN_RST_DET) && (gpwrdn & GPWRDN_RST_DET_MSK)) {
 		dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
 		if (!linestate && (gpwrdn & GPWRDN_BSESSVLD))
 			dwc2_exit_hibernation(hsotg, 0, 1, 0);
 	}
+
 	if ((gpwrdn & GPWRDN_STS_CHGINT) &&
-	    (gpwrdn & GPWRDN_STS_CHGINT_MSK) && linestate) {
+	    (gpwrdn & GPWRDN_STS_CHGINT_MSK)) {
 		dev_dbg(hsotg->dev, "%s: GPWRDN_STS_CHGINT\n", __func__);
 		if (hsotg->hw_params.hibernation &&
 		    hsotg->hibernated) {
-			if (gpwrdn & GPWRDN_IDSTS) {
-				dwc2_exit_hibernation(hsotg, 0, 0, 0);
-				call_gadget(hsotg, resume);
-			} else {
-				dwc2_exit_hibernation(hsotg, 1, 0, 1);
-			}
+			/*
+			 * As GPWRDN_STS_CHGINT exit from hibernation flow is
+			 * the same as in GPWRDN_DISCONN_DET flow. Call
+			 * disconnect detect helper function to exit from
+			 * hibernation.
+			 */
+			dwc_handle_gpwrdn_disc_det(hsotg, gpwrdn);
 		}
 	}
 }
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 54450fa352cf..45d4a3e1ebd2 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -5570,7 +5570,7 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg)
 	dwc2_writel(hsotg, hprt0, HPRT0);
 
 	/* Wait for the HPRT0.PrtSusp register field to be set */
-	if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
+	if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 5000))
 		dev_warn(hsotg->dev, "Suspend wasn't generated\n");
 
 	/*
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,11/14] usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

When device cable is disconnected core receives suspend
interrupt and enters hibernation. After entering
into hibernation GPWRDN_RST_DET and GPWRDN_STS_CHGINT
interrupts are asserted.

From cable disconnection we need to exit from hibernation
either by GPWRDN_RST_DET or GPWRDN_STS_CHGINT. If we exit
from hibernation by GPWRDN_STS_CHGINT, DEVADDR will not be
reset. But we need to exit gadget hibernation properly
with resetting the DEVADDR as reset accrued.

- Allowed exit from gadget hibernation from
  GPWRDN_RST_DET by checking only linestate.
- Setting hsotg->lx_state = DWC2_L0 in dwc2_hsotg_irq
  GINTSTS_RESETDET flow without checking if lx_state == DWC2_L2

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 2 +-
 drivers/usb/dwc2/gadget.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 40d296d9b6fb..cb827a5e1bfb 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -771,7 +771,7 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
 
 	if ((gpwrdn & GPWRDN_RST_DET) && (gpwrdn & GPWRDN_RST_DET_MSK)) {
 		dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
-		if (!linestate && (gpwrdn & GPWRDN_BSESSVLD))
+		if (!linestate)
 			dwc2_exit_hibernation(hsotg, 0, 1, 0);
 	}
 
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 8c3e1f1c1b0f..b35c966d4f63 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3637,8 +3637,8 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
 		/* This event must be used only if controller is suspended */
 		if (hsotg->lx_state == DWC2_L2) {
 			dwc2_exit_partial_power_down(hsotg, true);
-			hsotg->lx_state = DWC2_L0;
 		}
+		hsotg->lx_state = DWC2_L0;
 	}
 
 	if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 11/14] usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

When device cable is disconnected core receives suspend
interrupt and enters hibernation. After entering
into hibernation GPWRDN_RST_DET and GPWRDN_STS_CHGINT
interrupts are asserted.

From cable disconnection we need to exit from hibernation
either by GPWRDN_RST_DET or GPWRDN_STS_CHGINT. If we exit
from hibernation by GPWRDN_STS_CHGINT, DEVADDR will not be
reset. But we need to exit gadget hibernation properly
with resetting the DEVADDR as reset accrued.

- Allowed exit from gadget hibernation from
  GPWRDN_RST_DET by checking only linestate.
- Setting hsotg->lx_state = DWC2_L0 in dwc2_hsotg_irq
  GINTSTS_RESETDET flow without checking if lx_state == DWC2_L2

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core_intr.c | 2 +-
 drivers/usb/dwc2/gadget.c    | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 40d296d9b6fb..cb827a5e1bfb 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -771,7 +771,7 @@ static void dwc2_handle_gpwrdn_intr(struct dwc2_hsotg *hsotg)
 
 	if ((gpwrdn & GPWRDN_RST_DET) && (gpwrdn & GPWRDN_RST_DET_MSK)) {
 		dev_dbg(hsotg->dev, "%s: GPWRDN_RST_DET\n", __func__);
-		if (!linestate && (gpwrdn & GPWRDN_BSESSVLD))
+		if (!linestate)
 			dwc2_exit_hibernation(hsotg, 0, 1, 0);
 	}
 
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 8c3e1f1c1b0f..b35c966d4f63 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3637,8 +3637,8 @@ static irqreturn_t dwc2_hsotg_irq(int irq, void *pw)
 		/* This event must be used only if controller is suspended */
 		if (hsotg->lx_state == DWC2_L2) {
 			dwc2_exit_partial_power_down(hsotg, true);
-			hsotg->lx_state = DWC2_L0;
 		}
+		hsotg->lx_state = DWC2_L0;
 	}
 
 	if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,12/14] usb: dwc2: Clear fifo_map when resetting core.
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

If core enters host hibernation when switching from
device mode to host mode disconnection of host cable
asserts a WARNING in dwc2_hsotg_init_fifo() that
fifo_map is not cleared.

To avoid the WARNING, fifo_map should be cleared
in dwc2_core_reset() function.

- Cleared fifo_map when resetting the core.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core.c | 6 ++++++
 1 file changed, 6 insertions(+)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fb471d18a3de..fbbd6a2f10ad 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -532,6 +532,12 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
 	greset |= GRSTCTL_CSFTRST;
 	dwc2_writel(hsotg, greset, GRSTCTL);
 
+	/* Clear fifo_map */
+	#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
+		IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+	hsotg->fifo_map = 0;
+	#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
+
 	if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_CSFTRST, 50)) {
 		dev_warn(hsotg->dev, "%s: HANG! Soft Reset timeout GRSTCTL GRSTCTL_CSFTRST\n",
 			 __func__);

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 12/14] usb: dwc2: Clear fifo_map when resetting core.
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

If core enters host hibernation when switching from
device mode to host mode disconnection of host cable
asserts a WARNING in dwc2_hsotg_init_fifo() that
fifo_map is not cleared.

To avoid the WARNING, fifo_map should be cleared
in dwc2_core_reset() function.

- Cleared fifo_map when resetting the core.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fb471d18a3de..fbbd6a2f10ad 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -532,6 +532,12 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
 	greset |= GRSTCTL_CSFTRST;
 	dwc2_writel(hsotg, greset, GRSTCTL);
 
+	/* Clear fifo_map */
+	#if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
+		IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
+	hsotg->fifo_map = 0;
+	#endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */
+
 	if (dwc2_hsotg_wait_bit_clear(hsotg, GRSTCTL, GRSTCTL_CSFTRST, 50)) {
 		dev_warn(hsotg->dev, "%s: HANG! Soft Reset timeout GRSTCTL GRSTCTL_CSFTRST\n",
 			 __func__);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,13/14] usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

When hibernation exit is performed the dwc2_hib_restore_common()
function is called. In that function we wait until GINTSTS_RESTOREDONE
bit is set. However, after the setting of that bit we get a lot of
(dwc2_hsotg_irq:) interrupts which indicates that (GINTSTS.RstrDoneInt)
restore done interrupt is asserted.

To avoid restore done interrupt storm after restore is generated
clear GINTSTS_RESTOREDONE bit in GINTSTS register.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core.c | 6 ++++++
 1 file changed, 6 insertions(+)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fbbd6a2f10ad..18ea0d896e12 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -382,6 +382,12 @@ void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup,
 			__func__);
 	} else {
 		dev_dbg(hsotg->dev, "restore done  generated here\n");
+
+		/*
+		 * To avoid restore done interrupt storm after restore is
+		 * generated clear GINTSTS_RESTOREDONE bit.
+		 */
+		dwc2_writel(hsotg, GINTSTS_RESTOREDONE, GINTSTS);
 	}
 }
 

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 13/14] usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

When hibernation exit is performed the dwc2_hib_restore_common()
function is called. In that function we wait until GINTSTS_RESTOREDONE
bit is set. However, after the setting of that bit we get a lot of
(dwc2_hsotg_irq:) interrupts which indicates that (GINTSTS.RstrDoneInt)
restore done interrupt is asserted.

To avoid restore done interrupt storm after restore is generated
clear GINTSTS_RESTOREDONE bit in GINTSTS register.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/core.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fbbd6a2f10ad..18ea0d896e12 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -382,6 +382,12 @@ void dwc2_hib_restore_common(struct dwc2_hsotg *hsotg, int rem_wakeup,
 			__func__);
 	} else {
 		dev_dbg(hsotg->dev, "restore done  generated here\n");
+
+		/*
+		 * To avoid restore done interrupt storm after restore is
+		 * generated clear GINTSTS_RESTOREDONE bit.
+		 */
+		dwc2_writel(hsotg, GINTSTS_RESTOREDONE, GINTSTS);
 	}
 }
 
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Added a new flow of entering and exiting hibernation when PC is
hibernated or suspended.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
 1 file changed, 81 insertions(+), 47 deletions(-)

-- 
2.11.0

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 45d4a3e1ebd2..f1e92a287cb1 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 	if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
 	    hsotg->flags.b.port_connect_status == 0)
 		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(hsotg, hprt0, HPRT0);
-		spin_unlock_irqrestore(&hsotg->lock, flags);
-		dwc2_vbus_supply_exit(hsotg);
-		spin_lock_irqsave(&hsotg->lock, flags);
-	}
+	switch (hsotg->params.power_down) {
+	case DWC2_POWER_DOWN_PARAM_PARTIAL:
+		/*
+		 * 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(hsotg, hprt0, HPRT0);
+			spin_unlock_irqrestore(&hsotg->lock, flags);
+			dwc2_vbus_supply_exit(hsotg);
+			spin_lock_irqsave(&hsotg->lock, flags);
+		}
 
-	/* Enter partial_power_down */
-	ret = dwc2_enter_partial_power_down(hsotg);
-	if (ret) {
-		if (ret != -ENOTSUPP)
-			dev_err(hsotg->dev,
-				"enter partial_power_down failed\n");
+		/* Enter partial_power_down */
+		ret = dwc2_enter_partial_power_down(hsotg);
+		if (ret) {
+			if (ret != -ENOTSUPP)
+				dev_err(hsotg->dev,
+					"enter partial_power_down failed\n");
+			goto skip_power_saving;
+		}
+		hsotg->bus_suspended = true;
+		break;
+	case DWC2_POWER_DOWN_PARAM_HIBERNATION:
+		if (!hsotg->bus_suspended) {
+			/* Enter hibernation */
+			spin_unlock_irqrestore(&hsotg->lock, flags);
+			ret = dwc2_enter_hibernation(hsotg, 1);
+			spin_lock_irqsave(&hsotg->lock, flags);
+			if (ret && ret != -ENOTSUPP)
+				dev_err(hsotg->dev,
+					"%s: enter hibernation failed\n",
+					__func__);
+		} else {
+			goto skip_power_saving;
+		}
+		break;
+	default:
 		goto skip_power_saving;
 	}
 
-	hsotg->bus_suspended = true;
-
 	/* Ask phy to be suspended */
 	if (!IS_ERR_OR_NULL(hsotg->uphy)) {
 		spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 	int ret = 0;
 	u32 hprt0;
 
-	hprt0 = dwc2_read_hprt0(hsotg);
-
 	spin_lock_irqsave(&hsotg->lock, flags);
 
-	if (dwc2_is_device_mode(hsotg))
+	if (!hsotg->bus_suspended)
 		goto unlock;
 
 	if (hsotg->lx_state != DWC2_L2)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	hprt0 = dwc2_read_hprt0(hsotg);
+
+	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
 	    hprt0 & HPRT0_CONNSTS) {
 		hsotg->lx_state = DWC2_L0;
 		goto unlock;
@@ -4597,36 +4616,51 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 		spin_lock_irqsave(&hsotg->lock, flags);
 	}
 
-	/* Exit partial_power_down */
-	ret = dwc2_exit_partial_power_down(hsotg, true);
-	if (ret && (ret != -ENOTSUPP))
-		dev_err(hsotg->dev, "exit partial_power_down failed\n");
+	switch (hsotg->params.power_down) {
+	case DWC2_POWER_DOWN_PARAM_PARTIAL:
 
-	hsotg->lx_state = DWC2_L0;
+		/* Exit partial_power_down */
+		ret = dwc2_exit_partial_power_down(hsotg, true);
+		if (ret && (ret != -ENOTSUPP))
+			dev_err(hsotg->dev, "exit partial_power_down failed\n");
 
-	spin_unlock_irqrestore(&hsotg->lock, flags);
+		hsotg->lx_state = DWC2_L0;
 
-	if (hsotg->bus_suspended) {
-		spin_lock_irqsave(&hsotg->lock, flags);
-		hsotg->flags.b.port_suspend_change = 1;
 		spin_unlock_irqrestore(&hsotg->lock, flags);
-		dwc2_port_resume(hsotg);
-	} else {
-		dwc2_vbus_supply_init(hsotg);
 
-		/* Wait for controller to correctly update D+/D- level */
-		usleep_range(3000, 5000);
+		if (hsotg->bus_suspended) {
+			spin_lock_irqsave(&hsotg->lock, flags);
+			hsotg->flags.b.port_suspend_change = 1;
+			spin_unlock_irqrestore(&hsotg->lock, flags);
+			dwc2_port_resume(hsotg);
+		} else {
+			dwc2_vbus_supply_init(hsotg);
 
-		/*
-		 * Clear Port Enable and Port Status changes.
-		 * Enable Port Power.
-		 */
-		dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
+			/* Wait for controller to correctly update D+/D- level */
+			usleep_range(3000, 5000);
+
+			/*
+			 * Clear Port Enable and Port Status changes.
+			 * Enable Port Power.
+			 */
+			dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
 				HPRT0_ENACHG, HPRT0);
-		/* Wait for controller to detect Port Connect */
-		usleep_range(5000, 7000);
+			/* Wait for controller to detect Port Connect */
+			usleep_range(5000, 7000);
+		}
+		break;
+	case DWC2_POWER_DOWN_PARAM_HIBERNATION:
+
+		/* Exit host hibernation. */
+		if (hsotg->hibernated)
+			dwc2_exit_hibernation(hsotg, 0, 0, 1);
+		break;
+	default:
+		goto unlock;
 	}
 
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
 	return ret;
 unlock:
 	spin_unlock_irqrestore(&hsotg->lock, flags);

^ permalink raw reply related	[flat|nested] 84+ messages in thread

* [PATCH v1 14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-19 11:25 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-19 11:25 UTC (permalink / raw)
  To: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

Added a new flow of entering and exiting hibernation when PC is
hibernated or suspended.

Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
---
 drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
 1 file changed, 81 insertions(+), 47 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 45d4a3e1ebd2..f1e92a287cb1 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 	if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
 	    hsotg->flags.b.port_connect_status == 0)
 		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(hsotg, hprt0, HPRT0);
-		spin_unlock_irqrestore(&hsotg->lock, flags);
-		dwc2_vbus_supply_exit(hsotg);
-		spin_lock_irqsave(&hsotg->lock, flags);
-	}
+	switch (hsotg->params.power_down) {
+	case DWC2_POWER_DOWN_PARAM_PARTIAL:
+		/*
+		 * 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(hsotg, hprt0, HPRT0);
+			spin_unlock_irqrestore(&hsotg->lock, flags);
+			dwc2_vbus_supply_exit(hsotg);
+			spin_lock_irqsave(&hsotg->lock, flags);
+		}
 
-	/* Enter partial_power_down */
-	ret = dwc2_enter_partial_power_down(hsotg);
-	if (ret) {
-		if (ret != -ENOTSUPP)
-			dev_err(hsotg->dev,
-				"enter partial_power_down failed\n");
+		/* Enter partial_power_down */
+		ret = dwc2_enter_partial_power_down(hsotg);
+		if (ret) {
+			if (ret != -ENOTSUPP)
+				dev_err(hsotg->dev,
+					"enter partial_power_down failed\n");
+			goto skip_power_saving;
+		}
+		hsotg->bus_suspended = true;
+		break;
+	case DWC2_POWER_DOWN_PARAM_HIBERNATION:
+		if (!hsotg->bus_suspended) {
+			/* Enter hibernation */
+			spin_unlock_irqrestore(&hsotg->lock, flags);
+			ret = dwc2_enter_hibernation(hsotg, 1);
+			spin_lock_irqsave(&hsotg->lock, flags);
+			if (ret && ret != -ENOTSUPP)
+				dev_err(hsotg->dev,
+					"%s: enter hibernation failed\n",
+					__func__);
+		} else {
+			goto skip_power_saving;
+		}
+		break;
+	default:
 		goto skip_power_saving;
 	}
 
-	hsotg->bus_suspended = true;
-
 	/* Ask phy to be suspended */
 	if (!IS_ERR_OR_NULL(hsotg->uphy)) {
 		spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 	int ret = 0;
 	u32 hprt0;
 
-	hprt0 = dwc2_read_hprt0(hsotg);
-
 	spin_lock_irqsave(&hsotg->lock, flags);
 
-	if (dwc2_is_device_mode(hsotg))
+	if (!hsotg->bus_suspended)
 		goto unlock;
 
 	if (hsotg->lx_state != DWC2_L2)
 		goto unlock;
 
-	if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
+	hprt0 = dwc2_read_hprt0(hsotg);
+
+	if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
 	    hprt0 & HPRT0_CONNSTS) {
 		hsotg->lx_state = DWC2_L0;
 		goto unlock;
@@ -4597,36 +4616,51 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 		spin_lock_irqsave(&hsotg->lock, flags);
 	}
 
-	/* Exit partial_power_down */
-	ret = dwc2_exit_partial_power_down(hsotg, true);
-	if (ret && (ret != -ENOTSUPP))
-		dev_err(hsotg->dev, "exit partial_power_down failed\n");
+	switch (hsotg->params.power_down) {
+	case DWC2_POWER_DOWN_PARAM_PARTIAL:
 
-	hsotg->lx_state = DWC2_L0;
+		/* Exit partial_power_down */
+		ret = dwc2_exit_partial_power_down(hsotg, true);
+		if (ret && (ret != -ENOTSUPP))
+			dev_err(hsotg->dev, "exit partial_power_down failed\n");
 
-	spin_unlock_irqrestore(&hsotg->lock, flags);
+		hsotg->lx_state = DWC2_L0;
 
-	if (hsotg->bus_suspended) {
-		spin_lock_irqsave(&hsotg->lock, flags);
-		hsotg->flags.b.port_suspend_change = 1;
 		spin_unlock_irqrestore(&hsotg->lock, flags);
-		dwc2_port_resume(hsotg);
-	} else {
-		dwc2_vbus_supply_init(hsotg);
 
-		/* Wait for controller to correctly update D+/D- level */
-		usleep_range(3000, 5000);
+		if (hsotg->bus_suspended) {
+			spin_lock_irqsave(&hsotg->lock, flags);
+			hsotg->flags.b.port_suspend_change = 1;
+			spin_unlock_irqrestore(&hsotg->lock, flags);
+			dwc2_port_resume(hsotg);
+		} else {
+			dwc2_vbus_supply_init(hsotg);
 
-		/*
-		 * Clear Port Enable and Port Status changes.
-		 * Enable Port Power.
-		 */
-		dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
+			/* Wait for controller to correctly update D+/D- level */
+			usleep_range(3000, 5000);
+
+			/*
+			 * Clear Port Enable and Port Status changes.
+			 * Enable Port Power.
+			 */
+			dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
 				HPRT0_ENACHG, HPRT0);
-		/* Wait for controller to detect Port Connect */
-		usleep_range(5000, 7000);
+			/* Wait for controller to detect Port Connect */
+			usleep_range(5000, 7000);
+		}
+		break;
+	case DWC2_POWER_DOWN_PARAM_HIBERNATION:
+
+		/* Exit host hibernation. */
+		if (hsotg->hibernated)
+			dwc2_exit_hibernation(hsotg, 0, 0, 1);
+		break;
+	default:
+		goto unlock;
 	}
 
+	spin_unlock_irqrestore(&hsotg->lock, flags);
+
 	return ret;
 unlock:
 	spin_unlock_irqrestore(&hsotg->lock, flags);
-- 
2.11.0


^ permalink raw reply related	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-19 11:23 [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes Artur Petrosyan
@ 2019-04-25 12:43 ` Felipe Balbi
  2019-04-25 14:00   ` Artur Petrosyan
  0 siblings, 1 reply; 84+ messages in thread
From: Felipe Balbi @ 2019-04-25 12:43 UTC (permalink / raw)
  To: Artur Petrosyan, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb
  Cc: John Youn, Artur Petrosyan

[-- Attachment #1: Type: text/plain, Size: 2770 bytes --]

Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
> This patch set, fixes and improves partial power down and hibernation power
> saving modes. Also, adds support for entering/exiting hibernation by
> system issued suspend/resume.
>
> This series contains patches which were submitted to LKML. However, a part
> of those patches didn't reach to LKML because of local issue related to
> smtp server.
>
> The patches which reached to LKML are:
>
> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
> - usb: dwc2: Fix suspend state in host mode for partial power down.
> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
> - usb: dwc2: Fix dwc2_restore_device_registers() function.
>
> The patches which didn't reach to LKML are:
>
> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
> - usb: dwc2: Clear fifo_map when resetting core.
> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
> - usb: dwc2: Fix hibernation between host and device modes.
> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
> - usb: dwc2: Add default param to control power optimization.
> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>
> Submitting all of the patches together in this version.
>
> Changes from V0:
>  - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
>    "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
>    interrupt handlers.
>
>
> Artur Petrosyan (14):
>   usb: dwc2: Fix dwc2_restore_device_registers() function.
>   usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>   usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>   usb: dwc2: Fix suspend state in host mode for partial power down.
>   usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
>     function.
>   usb: dwc2: Add part. power down exit from
>     dwc2_conn_id_status_change().
>   usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>   usb: dwc2: Add default param to control power optimization.
>   usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>   usb: dwc2: Fix hibernation between host and device modes.
>   usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>   usb: dwc2: Clear fifo_map when resetting core.
>   usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>   usb: dwc2: Add enter/exit hibernation from system issued
>     suspend/resume

patches don't apply.

-- 
balbi

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-25 12:43 ` Felipe Balbi
@ 2019-04-25 14:00   ` Artur Petrosyan
  2019-04-25 20:12     ` Doug Anderson
  0 siblings, 1 reply; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-25 14:00 UTC (permalink / raw)
  To: Felipe Balbi, Artur Petrosyan, Greg Kroah-Hartman,
	Minas Harutyunyan, linux-usb
  Cc: John Youn

Hi,

On 4/25/2019 16:43, Felipe Balbi wrote:
> Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
>> This patch set, fixes and improves partial power down and hibernation power
>> saving modes. Also, adds support for entering/exiting hibernation by
>> system issued suspend/resume.
>>
>> This series contains patches which were submitted to LKML. However, a part
>> of those patches didn't reach to LKML because of local issue related to
>> smtp server.
>>
>> The patches which reached to LKML are:
>>
>> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
>> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
>> - usb: dwc2: Fix suspend state in host mode for partial power down.
>> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>> - usb: dwc2: Fix dwc2_restore_device_registers() function.
>>
>> The patches which didn't reach to LKML are:
>>
>> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
>> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>> - usb: dwc2: Clear fifo_map when resetting core.
>> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>> - usb: dwc2: Fix hibernation between host and device modes.
>> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>> - usb: dwc2: Add default param to control power optimization.
>> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>
>> Submitting all of the patches together in this version.
>>
>> Changes from V0:
>>   - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
>>     "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
>>     interrupt handlers.
>>
>>
>> Artur Petrosyan (14):
>>    usb: dwc2: Fix dwc2_restore_device_registers() function.
>>    usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>>    usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>    usb: dwc2: Fix suspend state in host mode for partial power down.
>>    usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
>>      function.
>>    usb: dwc2: Add part. power down exit from
>>      dwc2_conn_id_status_change().
>>    usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>    usb: dwc2: Add default param to control power optimization.
>>    usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>>    usb: dwc2: Fix hibernation between host and device modes.
>>    usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>>    usb: dwc2: Clear fifo_map when resetting core.
>>    usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>>    usb: dwc2: Add enter/exit hibernation from system issued
>>      suspend/resume
> 
> patches don't apply.
> 

Do we need to wait for Minas's acknowledge or there is problem related 
to the patches?

-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-25 14:00   ` Artur Petrosyan
@ 2019-04-25 20:12     ` Doug Anderson
  2019-04-26  7:10       ` Artur Petrosyan
  0 siblings, 1 reply; 84+ messages in thread
From: Doug Anderson @ 2019-04-25 20:12 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn, LKML

Hi,

On Thu, Apr 25, 2019 at 7:01 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/25/2019 16:43, Felipe Balbi wrote:
> > Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
> >> This patch set, fixes and improves partial power down and hibernation power
> >> saving modes. Also, adds support for entering/exiting hibernation by
> >> system issued suspend/resume.
> >>
> >> This series contains patches which were submitted to LKML. However, a part
> >> of those patches didn't reach to LKML because of local issue related to
> >> smtp server.
> >>
> >> The patches which reached to LKML are:
> >>
> >> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
> >> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
> >> - usb: dwc2: Fix suspend state in host mode for partial power down.
> >> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> >> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
> >> - usb: dwc2: Fix dwc2_restore_device_registers() function.
> >>
> >> The patches which didn't reach to LKML are:
> >>
> >> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
> >> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
> >> - usb: dwc2: Clear fifo_map when resetting core.
> >> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
> >> - usb: dwc2: Fix hibernation between host and device modes.
> >> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
> >> - usb: dwc2: Add default param to control power optimization.
> >> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
> >>
> >> Submitting all of the patches together in this version.
> >>
> >> Changes from V0:
> >>   - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
> >>     "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
> >>     interrupt handlers.
> >>
> >>
> >> Artur Petrosyan (14):
> >>    usb: dwc2: Fix dwc2_restore_device_registers() function.
> >>    usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
> >>    usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> >>    usb: dwc2: Fix suspend state in host mode for partial power down.
> >>    usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
> >>      function.
> >>    usb: dwc2: Add part. power down exit from
> >>      dwc2_conn_id_status_change().
> >>    usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
> >>    usb: dwc2: Add default param to control power optimization.
> >>    usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
> >>    usb: dwc2: Fix hibernation between host and device modes.
> >>    usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
> >>    usb: dwc2: Clear fifo_map when resetting core.
> >>    usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
> >>    usb: dwc2: Add enter/exit hibernation from system issued
> >>      suspend/resume
> >
> > patches don't apply.
> >
>
> Do we need to wait for Minas's acknowledge or there is problem related
> to the patches?

It looks like the problem is that my patches won the race and Felipe
applied them before yours.  Thus, presumably, it'll be up to you to
rebase your patches atop mine and re-submit.  Specifically, you can
do:

git remote add linux_usb_balbi
git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
git fetch linux_usb_balbi
git checkout linux_usb_balbi/testing/next

If you do that and then try to apply your patches you'll find that
they no longer apply.  AKA try running:

for patch in 10909749 10909737 10909739 10909745 10909533 \
   10909531 10909747 10909535 10909523 10909741 10909525 \
   10909751 10909527 10909743; do
  curl -L https://patchwork.kernel.org/patch/${patch}/mbox | git am
done

You'll see:

> Applying: usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> error: patch failed: drivers/usb/dwc2/core_intr.c:435
> error: drivers/usb/dwc2/core_intr.c: patch does not apply
> Patch failed at 0001 usb: dwc2: Fix wakeup detected and session request interrupt handlers.

NOTE: before reposting it might be a good idea to apply the last 3
patches in my series as per [1] before sending up your series.  Since
Felipe has already applied patches #1 and #2 in that series presumably
he'll also apply #3 - #5.

I know it'a also up to me to try testing our your patches.  It's still
on my list to give it a shot...

[1] https://lkml.kernel.org/r/CAD=FV=WA07+gUkVvsikN=iDHZLUJQtzjkKtiBHAEDw4gLNWY7w@mail.gmail.com

P.S: It's helpful if you CC LKML on patches and discussions about
them.  That allows the magic "permalink via message ID" on
lkml.kernel.org and also allows your patches to be found on
lore.kernel.org/patchwork/

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-25 20:12     ` Doug Anderson
@ 2019-04-26  7:10       ` Artur Petrosyan
  2019-04-26 16:01         ` Doug Anderson
  0 siblings, 1 reply; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-26  7:10 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn, LKML

Hi Doug,

On 4/26/2019 00:13, Doug Anderson wrote:
> Hi,
> 
> On Thu, Apr 25, 2019 at 7:01 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/25/2019 16:43, Felipe Balbi wrote:
>>> Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
>>>> This patch set, fixes and improves partial power down and hibernation power
>>>> saving modes. Also, adds support for entering/exiting hibernation by
>>>> system issued suspend/resume.
>>>>
>>>> This series contains patches which were submitted to LKML. However, a part
>>>> of those patches didn't reach to LKML because of local issue related to
>>>> smtp server.
>>>>
>>>> The patches which reached to LKML are:
>>>>
>>>> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
>>>> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
>>>> - usb: dwc2: Fix suspend state in host mode for partial power down.
>>>> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>>>> - usb: dwc2: Fix dwc2_restore_device_registers() function.
>>>>
>>>> The patches which didn't reach to LKML are:
>>>>
>>>> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
>>>> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>>>> - usb: dwc2: Clear fifo_map when resetting core.
>>>> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>>>> - usb: dwc2: Fix hibernation between host and device modes.
>>>> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>>>> - usb: dwc2: Add default param to control power optimization.
>>>> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>>>
>>>> Submitting all of the patches together in this version.
>>>>
>>>> Changes from V0:
>>>>    - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
>>>>      "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
>>>>      interrupt handlers.
>>>>
>>>>
>>>> Artur Petrosyan (14):
>>>>     usb: dwc2: Fix dwc2_restore_device_registers() function.
>>>>     usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>>>>     usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>>     usb: dwc2: Fix suspend state in host mode for partial power down.
>>>>     usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
>>>>       function.
>>>>     usb: dwc2: Add part. power down exit from
>>>>       dwc2_conn_id_status_change().
>>>>     usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>>>     usb: dwc2: Add default param to control power optimization.
>>>>     usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>>>>     usb: dwc2: Fix hibernation between host and device modes.
>>>>     usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>>>>     usb: dwc2: Clear fifo_map when resetting core.
>>>>     usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>>>>     usb: dwc2: Add enter/exit hibernation from system issued
>>>>       suspend/resume
>>>
>>> patches don't apply.
>>>
>>
>> Do we need to wait for Minas's acknowledge or there is problem related
>> to the patches?
> 
> It looks like the problem is that my patches won the race and Felipe
> applied them before yours.  Thus, presumably, it'll be up to you to
> rebase your patches atop mine and re-submit.  Specifically, you can
> do:
> 
> git remote add linux_usb_balbi
> git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
> git fetch linux_usb_balbi
> git checkout linux_usb_balbi/testing/next
> 
> If you do that and then try to apply your patches you'll find that
> they no longer apply.  AKA try running:
> 
> for patch in 10909749 10909737 10909739 10909745 10909533 \
>     10909531 10909747 10909535 10909523 10909741 10909525 \
>     10909751 10909527 10909743; do
>    curl -L https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_-24-257Bpatch-257D_mbox&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=aWT1hYtXeIeY8ClQ0sNYxwkmJFKDz4iaa4DchNwx3_w&e= | git am
> done
> 
> You'll see:
> 
>> Applying: usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>> error: patch failed: drivers/usb/dwc2/core_intr.c:435
>> error: drivers/usb/dwc2/core_intr.c: patch does not apply
>> Patch failed at 0001 usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> 
> NOTE: before reposting it might be a good idea to apply the last 3
> patches in my series as per [1] before sending up your series.  Since
> Felipe has already applied patches #1 and #2 in that series presumably
> he'll also apply #3 - #5.
> 
> I know it'a also up to me to try testing our your patches.  It's still
> on my list to give it a shot...
> 
> [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_CAD-3DFV-3DWA07-2BgUkVvsikN-3DiDHZLUJQtzjkKtiBHAEDw4gLNWY7w-40mail.gmail.com&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=9QP_h5ZlnT7ayUE1_6EVEgu8FaI3_kWm9xuzs1qrvdI&e=
> 
> P.S: It's helpful if you CC LKML on patches and discussions about
> them.  That allows the magic "permalink via message ID" on
> lkml.kernel.org and also allows your patches to be found on
> lore.kernel.org/patchwork/
> 
> -Doug
> 

Besides the issue that comes from the patch "usb: dwc2: Fix wakeup 
detected and session request interrupt handlers." there is one more 
serious conflict with one of your patches.

So the patch "usb: dwc2: bus suspend/resume for hosts with 
DWC2_POWER_DOWN_PARAM_NONE" have had also been added to the 
"balbi/testing/next" before my patch series which conflicts with two of 
my patches.

1. usb: dwc2: Fix suspend state in host mode for partial power down.
2. usb: dwc2: Add enter/exit hibernation from system issued suspend/resume

This patch introduced by you "usb: dwc2: bus suspend/resume for hosts 
with DWC2_POWER_DOWN_PARAM_NONE" got a little bit of issue. It 
eliminates entering hibernation through system issued suspend by 
checking "if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL)" 
. As per the patch you mention that it fixes suspend/resume flow for 
Altera SOCFPGA and Chrome OS 3.14 kernel tree. I assume that the board 
has the Partial Power Down enabled core that is why it works out. 
However, we don't just support the Partial Power Down feature enabled 
cores. We also support Hibernation feature enabled cores.

The patch set that had been introduced by me which includes "usb: dwc2: 
Add enter/exit hibernation from system issued suspend/resume" patch adds 
support for both hibernation and Partial Power Down feature enabled 
cores and fixes several of Partial Power Down and hibernation related 
issues.

This patch set may fix all of the issues related with Altera SOCFPGA or
Chrome OS 3.14 kernel tree.

That is why we asked you to test the patch set before we could ACK or 
have chance to debug your patch deeper to see the help of it and to 
provide you information related to it.

So now I can rebase my changes to the "balbi/testing/next" but I will 
have to take the logic of skipping Hibernation out otherwise we will 
have problems with hibernation enabled cores.

We can ask Balbi to permanently suspend adding of the patch "usb: dwc2: 
bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE" and my 
patch series to his "testing/next". After you can have a chance to test 
my patch series we can see if the patches are acknowledged and ask Balbi 
  to add them.

-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-26  7:10       ` Artur Petrosyan
@ 2019-04-26 16:01         ` Doug Anderson
  2019-04-26 21:06           ` Doug Anderson
  2019-04-29  8:44           ` Artur Petrosyan
  0 siblings, 2 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 16:01 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn, LKML

Hi,

On Fri, Apr 26, 2019 at 12:11 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi Doug,
>
> On 4/26/2019 00:13, Doug Anderson wrote:
> > Hi,
> >
> > On Thu, Apr 25, 2019 at 7:01 AM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> Hi,
> >>
> >> On 4/25/2019 16:43, Felipe Balbi wrote:
> >>> Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
> >>>> This patch set, fixes and improves partial power down and hibernation power
> >>>> saving modes. Also, adds support for entering/exiting hibernation by
> >>>> system issued suspend/resume.
> >>>>
> >>>> This series contains patches which were submitted to LKML. However, a part
> >>>> of those patches didn't reach to LKML because of local issue related to
> >>>> smtp server.
> >>>>
> >>>> The patches which reached to LKML are:
> >>>>
> >>>> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
> >>>> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
> >>>> - usb: dwc2: Fix suspend state in host mode for partial power down.
> >>>> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> >>>> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
> >>>> - usb: dwc2: Fix dwc2_restore_device_registers() function.
> >>>>
> >>>> The patches which didn't reach to LKML are:
> >>>>
> >>>> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
> >>>> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
> >>>> - usb: dwc2: Clear fifo_map when resetting core.
> >>>> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
> >>>> - usb: dwc2: Fix hibernation between host and device modes.
> >>>> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
> >>>> - usb: dwc2: Add default param to control power optimization.
> >>>> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
> >>>>
> >>>> Submitting all of the patches together in this version.
> >>>>
> >>>> Changes from V0:
> >>>>    - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
> >>>>      "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
> >>>>      interrupt handlers.
> >>>>
> >>>>
> >>>> Artur Petrosyan (14):
> >>>>     usb: dwc2: Fix dwc2_restore_device_registers() function.
> >>>>     usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
> >>>>     usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> >>>>     usb: dwc2: Fix suspend state in host mode for partial power down.
> >>>>     usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
> >>>>       function.
> >>>>     usb: dwc2: Add part. power down exit from
> >>>>       dwc2_conn_id_status_change().
> >>>>     usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
> >>>>     usb: dwc2: Add default param to control power optimization.
> >>>>     usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
> >>>>     usb: dwc2: Fix hibernation between host and device modes.
> >>>>     usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
> >>>>     usb: dwc2: Clear fifo_map when resetting core.
> >>>>     usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
> >>>>     usb: dwc2: Add enter/exit hibernation from system issued
> >>>>       suspend/resume
> >>>
> >>> patches don't apply.
> >>>
> >>
> >> Do we need to wait for Minas's acknowledge or there is problem related
> >> to the patches?
> >
> > It looks like the problem is that my patches won the race and Felipe
> > applied them before yours.  Thus, presumably, it'll be up to you to
> > rebase your patches atop mine and re-submit.  Specifically, you can
> > do:
> >
> > git remote add linux_usb_balbi
> > git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
> > git fetch linux_usb_balbi
> > git checkout linux_usb_balbi/testing/next
> >
> > If you do that and then try to apply your patches you'll find that
> > they no longer apply.  AKA try running:
> >
> > for patch in 10909749 10909737 10909739 10909745 10909533 \
> >     10909531 10909747 10909535 10909523 10909741 10909525 \
> >     10909751 10909527 10909743; do
> >    curl -L https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_-24-257Bpatch-257D_mbox&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=aWT1hYtXeIeY8ClQ0sNYxwkmJFKDz4iaa4DchNwx3_w&e= | git am
> > done
> >
> > You'll see:
> >
> >> Applying: usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> >> error: patch failed: drivers/usb/dwc2/core_intr.c:435
> >> error: drivers/usb/dwc2/core_intr.c: patch does not apply
> >> Patch failed at 0001 usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> >
> > NOTE: before reposting it might be a good idea to apply the last 3
> > patches in my series as per [1] before sending up your series.  Since
> > Felipe has already applied patches #1 and #2 in that series presumably
> > he'll also apply #3 - #5.
> >
> > I know it'a also up to me to try testing our your patches.  It's still
> > on my list to give it a shot...
> >
> > [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_CAD-3DFV-3DWA07-2BgUkVvsikN-3DiDHZLUJQtzjkKtiBHAEDw4gLNWY7w-40mail.gmail.com&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=9QP_h5ZlnT7ayUE1_6EVEgu8FaI3_kWm9xuzs1qrvdI&e=
> >
> > P.S: It's helpful if you CC LKML on patches and discussions about
> > them.  That allows the magic "permalink via message ID" on
> > lkml.kernel.org and also allows your patches to be found on
> > lore.kernel.org/patchwork/
> >
> > -Doug
> >
>
> Besides the issue that comes from the patch "usb: dwc2: Fix wakeup
> detected and session request interrupt handlers." there is one more
> serious conflict with one of your patches.
>
> So the patch "usb: dwc2: bus suspend/resume for hosts with
> DWC2_POWER_DOWN_PARAM_NONE" have had also been added to the
> "balbi/testing/next" before my patch series which conflicts with two of
> my patches.
>
> 1. usb: dwc2: Fix suspend state in host mode for partial power down.
> 2. usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
>
> This patch introduced by you "usb: dwc2: bus suspend/resume for hosts
> with DWC2_POWER_DOWN_PARAM_NONE" got a little bit of issue. It
> eliminates entering hibernation through system issued suspend by
> checking "if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL)"

To be fair, the patch does not make entering hibernation worse, does
it?  Specifically, I'll point to this part of the diff:

- if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
+ if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) {

As you can see, if power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION the
flow for this "if" test is exactly the same before and after my patch.


> . As per the patch you mention that it fixes suspend/resume flow for
> Altera SOCFPGA and Chrome OS 3.14 kernel tree. I assume that the board
> has the Partial Power Down enabled core that is why it works out.

I mentioned some of this in my cover letter [1].  To rehash, I said
"Turning on partial power down on rk3288 doesn't "just work".  I don't
get hotplug events.  This is despite dwc2 auto-detecting that we are
power optimized."

...it is certainly possible that partial power down would work on
rk3288 if someone had the time to debug it.

NOTE: I don't have an Altera SOCFPGA, but I'll mention that a previous
iteration of my patch (written by Kever Yang at Rockchip) was reverted
because it _broke_ Altera SOCFPGAS.  Given my requests to test the new
version have been met with silence, I'm inclined to land this and hope
it's all good.  If there are problems then hopefully some actual
details can be provided.  Last time there were none provided.


> However, we don't just support the Partial Power Down feature enabled
> cores. We also support Hibernation feature enabled cores.

Sure, but the code that is actually landed upstream (even before my
series) almost certainly doesn't function for Hibernation.  As pointed
out above the entire "_dwc2_hcd_suspend()" function had a great big:

if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
  goto skip_power_saving;

...which, as far as I could tell, meant that Hibernation could not
possible work.


> The patch set that had been introduced by me which includes "usb: dwc2:
> Add enter/exit hibernation from system issued suspend/resume" patch adds
> support for both hibernation and Partial Power Down feature enabled
> cores and fixes several of Partial Power Down and hibernation related
> issues.
>
> This patch set may fix all of the issues related with Altera SOCFPGA or
> Chrome OS 3.14 kernel tree.
>
> That is why we asked you to test the patch set before we could ACK or
> have chance to debug your patch deeper to see the help of it and to
> provide you information related to it.

It may well fix my problems and maybe I can use partial power down
now.  That'd be nice.  It was on my list and I would have worked on it
last week except that your patches weren't on the mailing list then.
...so I moved on to some other work.  To avoid context switching too
much I needed to get to a stopping point before testing your patches.
I was hoping to have some nice rebased patches from you to test today,
but maybe I'll try a hand at rebasing them myself.

NOTE also that though I ported this change from the Chrome OS 3.14
kernel tree, I'm actually currently working on the Chrome OS 4.19
tree.  I also made sure to test the changes on mainline Linux.


> So now I can rebase my changes to the "balbi/testing/next" but I will
> have to take the logic of skipping Hibernation out otherwise we will
> have problems with hibernation enabled cores.

As per above, please have a careful look at my patches and you'll see
that I was not introducing code that skipped hibernation.  I was
keeping the same flow as the old code that skipped hibernation.  So if
you are making hibernation work there should be no problems removing
that.


> We can ask Balbi to permanently suspend adding of the patch "usb: dwc2:
> bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE" and my
> patch series to his "testing/next". After you can have a chance to test
> my patch series we can see if the patches are acknowledged and ask Balbi
>   to add them.

Personally I'd prefer if Felipe finished landing my series and then
you rebased atop it.  As I said I'm convinced I'm not making your
hibernation case any worse.  If you know of actual things that are
made worse by my series then that would be a reason not to land it,
but so far I haven't been convinced.


[1] https://lkml.kernel.org/r/20190418001356.124334-2-dianders@chromium.org

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers.
@ 2019-04-26 20:44 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:44 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> @@ -426,8 +438,6 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
>                 /* Change to L0 state */
>                 hsotg->lx_state = DWC2_L0;
>         } else {
> -               if (hsotg->params.power_down)
> -                       return;
>

nit: you leave an odd blank line here.  Please delete it.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers.
@ 2019-04-26 20:44 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:44 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> @@ -426,8 +438,6 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
>                 /* Change to L0 state */
>                 hsotg->lx_state = DWC2_L0;
>         } else {
> -               if (hsotg->params.power_down)
> -                       return;
>

nit: you leave an odd blank line here.  Please delete it.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-26 20:44 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:44 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> - In dwc2_port_suspend() function added waiting for the
>   HPRT0.PrtSusp register field to be set.
>
> - In _dwc2_hcd_suspend() function added checking of
>   "hsotg->flags.b.port_connect_status" port connection
>   status if port connection status is 0 then skipping
>   power saving (entering partial power down mode).
>   Because if there is no device connected there would
>   be no need to enter partial power down mode.
>
> - Added "hsotg->bus_suspended = true" beceuse after

s/beceuse/because

>   entering partial power down in host mode the
>   bus_suspended flag must be set.

The above statement sounds to me like trying to win an argument by
saying "I'm right because I'm right."  Can you give more details about
why "bus_suspended" must be set?  See below also.


> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index dd82fa516f3f..1d18258b5ff8 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -3479,6 +3479,10 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
>         hprt0 |= HPRT0_SUSP;
>         dwc2_writel(hsotg, hprt0, HPRT0);
>
> +       /* Wait for the HPRT0.PrtSusp register field to be set */
> +       if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
> +               dev_warn(hsotg->dev, "Suspend wasn't generated\n");
> +
>         hsotg->bus_suspended = true;
>
>         /*
> @@ -4488,7 +4492,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>         if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>                 goto unlock;
>
> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
> +       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> +           hsotg->flags.b.port_connect_status == 0)
>                 goto skip_power_saving;
>
>         /*
> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>                 goto skip_power_saving;
>         }
>
> +       hsotg->bus_suspended = true;
> +

I'm a bit unsure about this.  Specifically I note that
_dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
Does that now become dead code?

...I talk about this a bit more in my review of ("usb: dwc2: Add
enter/exit hibernation from system issued suspend/resume")


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-26 20:44 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:44 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> - In dwc2_port_suspend() function added waiting for the
>   HPRT0.PrtSusp register field to be set.
>
> - In _dwc2_hcd_suspend() function added checking of
>   "hsotg->flags.b.port_connect_status" port connection
>   status if port connection status is 0 then skipping
>   power saving (entering partial power down mode).
>   Because if there is no device connected there would
>   be no need to enter partial power down mode.
>
> - Added "hsotg->bus_suspended = true" beceuse after

s/beceuse/because

>   entering partial power down in host mode the
>   bus_suspended flag must be set.

The above statement sounds to me like trying to win an argument by
saying "I'm right because I'm right."  Can you give more details about
why "bus_suspended" must be set?  See below also.


> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 9 ++++++++-
>  1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index dd82fa516f3f..1d18258b5ff8 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -3479,6 +3479,10 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
>         hprt0 |= HPRT0_SUSP;
>         dwc2_writel(hsotg, hprt0, HPRT0);
>
> +       /* Wait for the HPRT0.PrtSusp register field to be set */
> +       if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
> +               dev_warn(hsotg->dev, "Suspend wasn't generated\n");
> +
>         hsotg->bus_suspended = true;
>
>         /*
> @@ -4488,7 +4492,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>         if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>                 goto unlock;
>
> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
> +       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> +           hsotg->flags.b.port_connect_status == 0)
>                 goto skip_power_saving;
>
>         /*
> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>                 goto skip_power_saving;
>         }
>
> +       hsotg->bus_suspended = true;
> +

I'm a bit unsure about this.  Specifically I note that
_dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
Does that now become dead code?

...I talk about this a bit more in my review of ("usb: dwc2: Add
enter/exit hibernation from system issued suspend/resume")


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,05/14] usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
@ 2019-04-26 20:45 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:45 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Added port connection status checking which prevents exiting from
> Partial Power Down mode from _dwc2_hcd_resume() when no entering
> to Partial Power Down mode happened.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 1d18258b5ff8..8367902a47eb 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -4544,6 +4544,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>         struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
>         unsigned long flags;
>         int ret = 0;
> +       u32 hprt0;
> +
> +       hprt0 = dwc2_read_hprt0(hsotg);
>
>         spin_lock_irqsave(&hsotg->lock, flags);

In this patch you put the reading of hprt0 before the spinlock (which
seems wrong) and then you move it after the spinlock in the last patch
in the series, AKA ("usb: dwc2: Add enter/exit hibernation from system
issued suspend/resume").  Can you just put it in the right place here
so you don't need to move it in a later patch?


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 05/14] usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
@ 2019-04-26 20:45 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:45 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Added port connection status checking which prevents exiting from
> Partial Power Down mode from _dwc2_hcd_resume() when no entering
> to Partial Power Down mode happened.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 6 +++++-
>  1 file changed, 5 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 1d18258b5ff8..8367902a47eb 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -4544,6 +4544,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>         struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
>         unsigned long flags;
>         int ret = 0;
> +       u32 hprt0;
> +
> +       hprt0 = dwc2_read_hprt0(hsotg);
>
>         spin_lock_irqsave(&hsotg->lock, flags);

In this patch you put the reading of hprt0 before the spinlock (which
seems wrong) and then you move it after the spinlock in the last patch
in the series, AKA ("usb: dwc2: Add enter/exit hibernation from system
issued suspend/resume").  Can you just put it in the right place here
so you don't need to move it in a later patch?


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,06/14] usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
@ 2019-04-26 20:45 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:45 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Before changing to connector B exiting from Partial
> Power Down is required.
>
> - Added exiting from Partial Power Down mode when
>   connector ID status changes to "connId B".
>   Because if connector ID status changed to B connector
>   while core was in partial power down mode, HANG would
>   accrue from a soft reset.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 8367902a47eb..54450fa352cf 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -3348,6 +3348,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>                                                 wf_otg);
>         u32 count = 0;
>         u32 gotgctl;
> +       u32 pcgcctl;
>         unsigned long flags;
>
>         dev_dbg(hsotg->dev, "%s()\n", __func__);
> @@ -3387,6 +3388,23 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>                 if (count > 250)
>                         dev_err(hsotg->dev,
>                                 "Connection id status change timed out\n");
> +
> +               if (hsotg->params.power_down ==
> +                   DWC2_POWER_DOWN_PARAM_PARTIAL &&
> +                   hsotg->lx_state == DWC2_L2) {
> +                       pcgcctl = dwc2_readl(hsotg, PCGCTL);
> +                       pcgcctl &= ~PCGCTL_STOPPCLK;
> +                       dwc2_writel(hsotg, pcgcctl, PCGCTL);
> +
> +                       pcgcctl = dwc2_readl(hsotg, PCGCTL);
> +                       pcgcctl &= ~PCGCTL_PWRCLMP;
> +                       dwc2_writel(hsotg, pcgcctl, PCGCTL);
> +
> +                       pcgcctl = dwc2_readl(hsotg, PCGCTL);
> +                       pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
> +                       dwc2_writel(hsotg, pcgcctl, PCGCTL);

You really need to read it over and over?  ...and you really can't
just write this all at once?

...if this really needs to be separate steps, do you need a delay
between them or can they just happen as fast as possible?

As far as I can tell from the programming guide I've seen, you:

1. Don't need to read it over and over again.

2. Should delay 10 PHY clock cycles after the writes


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 06/14] usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
@ 2019-04-26 20:45 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:45 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Before changing to connector B exiting from Partial
> Power Down is required.
>
> - Added exiting from Partial Power Down mode when
>   connector ID status changes to "connId B".
>   Because if connector ID status changed to B connector
>   while core was in partial power down mode, HANG would
>   accrue from a soft reset.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 18 ++++++++++++++++++
>  1 file changed, 18 insertions(+)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 8367902a47eb..54450fa352cf 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -3348,6 +3348,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>                                                 wf_otg);
>         u32 count = 0;
>         u32 gotgctl;
> +       u32 pcgcctl;
>         unsigned long flags;
>
>         dev_dbg(hsotg->dev, "%s()\n", __func__);
> @@ -3387,6 +3388,23 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>                 if (count > 250)
>                         dev_err(hsotg->dev,
>                                 "Connection id status change timed out\n");
> +
> +               if (hsotg->params.power_down ==
> +                   DWC2_POWER_DOWN_PARAM_PARTIAL &&
> +                   hsotg->lx_state == DWC2_L2) {
> +                       pcgcctl = dwc2_readl(hsotg, PCGCTL);
> +                       pcgcctl &= ~PCGCTL_STOPPCLK;
> +                       dwc2_writel(hsotg, pcgcctl, PCGCTL);
> +
> +                       pcgcctl = dwc2_readl(hsotg, PCGCTL);
> +                       pcgcctl &= ~PCGCTL_PWRCLMP;
> +                       dwc2_writel(hsotg, pcgcctl, PCGCTL);
> +
> +                       pcgcctl = dwc2_readl(hsotg, PCGCTL);
> +                       pcgcctl &= ~PCGCTL_RSTPDWNMODULE;
> +                       dwc2_writel(hsotg, pcgcctl, PCGCTL);

You really need to read it over and over?  ...and you really can't
just write this all at once?

...if this really needs to be separate steps, do you need a delay
between them or can they just happen as fast as possible?

As far as I can tell from the programming guide I've seen, you:

1. Don't need to read it over and over again.

2. Should delay 10 PHY clock cycles after the writes


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-26 20:46 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:46 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> - Added a default param "power_saving" to enable or
>   disable hibernation or partial power down features.
>
> - Printed hibernation param in hw_params_show and
>   power_saving param in params_show.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
> ---
>  drivers/usb/dwc2/core.h    |  3 +++
>  drivers/usb/dwc2/debugfs.c |  2 ++
>  drivers/usb/dwc2/params.c  | 19 +++++++++++++------
>  3 files changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> index 30bab8463c96..9221933ab64e 100644
> --- a/drivers/usb/dwc2/core.h
> +++ b/drivers/usb/dwc2/core.h
> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
>   *                      case.
>   *                      0 - No (default)
>   *                      1 - Yes
> + * @power_saving:      Specifies if power saving is enabled or not. If it is
> + *                     enabled power_down functionality will be enabled.
>   * @power_down:         Specifies whether the controller support power_down.
>   *                     If power_down is enabled, the controller will enter
>   *                     power_down in both peripheral and host mode when

Why are you adding a new parameter?  power_saving should be exactly
the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
anywhere you need it.

Having two parameters like you're doing is just asking for them to get
out of sync.  ...and, in fact, I think they will get out of sync.  On
rk3288, for instance:

-> dwc2_set_default_params()
---> power_saving = true
---> dwc2_set_param_power_down()
-----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
-> set_params(), which is actually dwc2_set_rk_params()
---> power_down = 0


...so at the end of dwc2_init_params() you will have power_saving =
true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
bad.  ...and, in fact:

# grep '^power' /sys/kernel/debug/*.usb/params
/sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
/sys/kernel/debug/ff540000.usb/params:power_down                    : 0
/sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
/sys/kernel/debug/ff580000.usb/params:power_down                    : 0


...so while you could fix all of the various set_params() functions,
it seems better to just drop this patch since I don't think it buys
anything.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-26 20:46 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:46 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> - Added a default param "power_saving" to enable or
>   disable hibernation or partial power down features.
>
> - Printed hibernation param in hw_params_show and
>   power_saving param in params_show.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
> ---
>  drivers/usb/dwc2/core.h    |  3 +++
>  drivers/usb/dwc2/debugfs.c |  2 ++
>  drivers/usb/dwc2/params.c  | 19 +++++++++++++------
>  3 files changed, 18 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> index 30bab8463c96..9221933ab64e 100644
> --- a/drivers/usb/dwc2/core.h
> +++ b/drivers/usb/dwc2/core.h
> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
>   *                      case.
>   *                      0 - No (default)
>   *                      1 - Yes
> + * @power_saving:      Specifies if power saving is enabled or not. If it is
> + *                     enabled power_down functionality will be enabled.
>   * @power_down:         Specifies whether the controller support power_down.
>   *                     If power_down is enabled, the controller will enter
>   *                     power_down in both peripheral and host mode when

Why are you adding a new parameter?  power_saving should be exactly
the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
anywhere you need it.

Having two parameters like you're doing is just asking for them to get
out of sync.  ...and, in fact, I think they will get out of sync.  On
rk3288, for instance:

-> dwc2_set_default_params()
---> power_saving = true
---> dwc2_set_param_power_down()
-----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
-> set_params(), which is actually dwc2_set_rk_params()
---> power_down = 0


...so at the end of dwc2_init_params() you will have power_saving =
true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
bad.  ...and, in fact:

# grep '^power' /sys/kernel/debug/*.usb/params
/sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
/sys/kernel/debug/ff540000.usb/params:power_down                    : 0
/sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
/sys/kernel/debug/ff580000.usb/params:power_down                    : 0


...so while you could fix all of the various set_params() functions,
it seems better to just drop this patch since I don't think it buys
anything.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
@ 2019-04-26 20:51 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:51 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> To avoid working in two modes (partial power down
> and hibernation) changed conditions for entering
> partial power down or hibernation.
>
> Instead of checking hw_params.power_optimized and
> hw_params.hibernation now checking power_down
> param which already set to one of the options
> (Hibernation or Partial Power Down) based on
> OTG_EN_PWROPT.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
> ---
>  drivers/usb/dwc2/core_intr.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)

In general I'm in support of this patch--it's cleaner and gets rid of
a needless goto \o/

...but you don't go far enough.  You can fully get rid of all of the
"-ENOTSUPP" stuff.  I've actually picked my patches and yours atop
Felipe's "testing/next" tree and you can find it here:

https://chromium.googlesource.com/chromiumos/third_party/kernel/+log/refs/sandbox/dianders/190426-dwc2-stuff

...as part of that I've included a patch ("usb: dwc2: Get rid of
useless error checks for hibernation/partial power down"), AKA:

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/0c924f736e2f7c1bb02531aa33c04a3ae5f4fc4c

Feel free to squash that into your patch or add it to your series if
you like it.  Note that patch points out that there's are still some
instances where calling dwc2_exit_partial_power_down() might still
happen in a case where it's not obvious if we were in partial power
down mode and made me wonder if there might be some bugs there.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
@ 2019-04-26 20:51 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:51 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> To avoid working in two modes (partial power down
> and hibernation) changed conditions for entering
> partial power down or hibernation.
>
> Instead of checking hw_params.power_optimized and
> hw_params.hibernation now checking power_down
> param which already set to one of the options
> (Hibernation or Partial Power Down) based on
> OTG_EN_PWROPT.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
> ---
>  drivers/usb/dwc2/core_intr.c | 13 +++++++------
>  1 file changed, 7 insertions(+), 6 deletions(-)

In general I'm in support of this patch--it's cleaner and gets rid of
a needless goto \o/

...but you don't go far enough.  You can fully get rid of all of the
"-ENOTSUPP" stuff.  I've actually picked my patches and yours atop
Felipe's "testing/next" tree and you can find it here:

https://chromium.googlesource.com/chromiumos/third_party/kernel/+log/refs/sandbox/dianders/190426-dwc2-stuff

...as part of that I've included a patch ("usb: dwc2: Get rid of
useless error checks for hibernation/partial power down"), AKA:

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/0c924f736e2f7c1bb02531aa33c04a3ae5f4fc4c

Feel free to squash that into your patch or add it to your series if
you like it.  Note that patch points out that there's are still some
instances where calling dwc2_exit_partial_power_down() might still
happen in a case where it's not obvious if we were in partial power
down mode and made me wonder if there might be some bugs there.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,12/14] usb: dwc2: Clear fifo_map when resetting core.
@ 2019-04-26 20:51 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:51 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:06 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> If core enters host hibernation when switching from
> device mode to host mode disconnection of host cable
> asserts a WARNING in dwc2_hsotg_init_fifo() that
> fifo_map is not cleared.
>
> To avoid the WARNING, fifo_map should be cleared
> in dwc2_core_reset() function.
>
> - Cleared fifo_map when resetting the core.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/core.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
> index fb471d18a3de..fbbd6a2f10ad 100644
> --- a/drivers/usb/dwc2/core.c
> +++ b/drivers/usb/dwc2/core.c
> @@ -532,6 +532,12 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
>         greset |= GRSTCTL_CSFTRST;
>         dwc2_writel(hsotg, greset, GRSTCTL);
>
> +       /* Clear fifo_map */
> +       #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
> +               IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
> +       hsotg->fifo_map = 0;
> +       #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */

Please please no sprinkling "#if" statements in code like this.  Here
lies the way to madness.  The right way to do this in the style of the
Linux kernel is to add a function that is a "static inline" no-op when
the options are compiled out.

As one example you can see my recent patch:

https://lkml.kernel.org/r/20190425154021.4465-1-dianders@chromium.org



-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 12/14] usb: dwc2: Clear fifo_map when resetting core.
@ 2019-04-26 20:51 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 20:51 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:06 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> If core enters host hibernation when switching from
> device mode to host mode disconnection of host cable
> asserts a WARNING in dwc2_hsotg_init_fifo() that
> fifo_map is not cleared.
>
> To avoid the WARNING, fifo_map should be cleared
> in dwc2_core_reset() function.
>
> - Cleared fifo_map when resetting the core.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/core.c | 6 ++++++
>  1 file changed, 6 insertions(+)
>
> diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
> index fb471d18a3de..fbbd6a2f10ad 100644
> --- a/drivers/usb/dwc2/core.c
> +++ b/drivers/usb/dwc2/core.c
> @@ -532,6 +532,12 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
>         greset |= GRSTCTL_CSFTRST;
>         dwc2_writel(hsotg, greset, GRSTCTL);
>
> +       /* Clear fifo_map */
> +       #if IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) || \
> +               IS_ENABLED(CONFIG_USB_DWC2_DUAL_ROLE)
> +       hsotg->fifo_map = 0;
> +       #endif /* CONFIG_USB_DWC2_PERIPHERAL || CONFIG_USB_DWC2_DUAL_ROLE */

Please please no sprinkling "#if" statements in code like this.  Here
lies the way to madness.  The right way to do this in the style of the
Linux kernel is to add a function that is a "static inline" no-op when
the options are compiled out.

As one example you can see my recent patch:

https://lkml.kernel.org/r/20190425154021.4465-1-dianders@chromium.org



-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-26 21:00 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 21:00 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Added a new flow of entering and exiting hibernation when PC is
> hibernated or suspended.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
>  1 file changed, 81 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 45d4a3e1ebd2..f1e92a287cb1 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>         if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>                 goto unlock;
>
> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>             hsotg->flags.b.port_connect_status == 0)
>                 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(hsotg, hprt0, HPRT0);
> -               spin_unlock_irqrestore(&hsotg->lock, flags);
> -               dwc2_vbus_supply_exit(hsotg);
> -               spin_lock_irqsave(&hsotg->lock, flags);
> -       }
> +       switch (hsotg->params.power_down) {
> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
> +               /*
> +                * 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(hsotg, hprt0, HPRT0);
> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> +                       dwc2_vbus_supply_exit(hsotg);
> +                       spin_lock_irqsave(&hsotg->lock, flags);
> +               }
>
> -       /* Enter partial_power_down */
> -       ret = dwc2_enter_partial_power_down(hsotg);
> -       if (ret) {
> -               if (ret != -ENOTSUPP)
> -                       dev_err(hsotg->dev,
> -                               "enter partial_power_down failed\n");
> +               /* Enter partial_power_down */
> +               ret = dwc2_enter_partial_power_down(hsotg);
> +               if (ret) {
> +                       if (ret != -ENOTSUPP)
> +                               dev_err(hsotg->dev,
> +                                       "enter partial_power_down failed\n");
> +                       goto skip_power_saving;
> +               }
> +               hsotg->bus_suspended = true;
> +               break;
> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
> +               if (!hsotg->bus_suspended) {

Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
call dwc2_enter_partial_power_down() even if bus_suspended is true,
but for hibernate you don't call dwc2_enter_hibernation()?


> +                       /* Enter hibernation */
> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> +                       ret = dwc2_enter_hibernation(hsotg, 1);
> +                       spin_lock_irqsave(&hsotg->lock, flags);
> +                       if (ret && ret != -ENOTSUPP)
> +                               dev_err(hsotg->dev,
> +                                       "%s: enter hibernation failed\n",
> +                                       __func__);

nit: no __func__ in dev_xxx() error messages.  The device plus the
message should be enough.  Only resort to __func__ if you're forced to
do an error message without a "struct device *".

nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP

Also, presumably you want to match the error handling in
DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
you see an error?


> +               } else {
> +                       goto skip_power_saving;
> +               }
> +               break;
> +       default:
>                 goto skip_power_saving;
>         }
>
> -       hsotg->bus_suspended = true;
> -

It's a bit weird to remove this, but I guess it just got moved to the
partial power down case?  ...and in the hibernate case you're relying
on the hibernate function to set this?  Yet another frustratingly
asymmetric code structure...


>         /* Ask phy to be suspended */
>         if (!IS_ERR_OR_NULL(hsotg->uphy)) {
>                 spin_unlock_irqrestore(&hsotg->lock, flags);
> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>         int ret = 0;
>         u32 hprt0;
>
> -       hprt0 = dwc2_read_hprt0(hsotg);
> -
>         spin_lock_irqsave(&hsotg->lock, flags);
>
> -       if (dwc2_is_device_mode(hsotg))
> +       if (!hsotg->bus_suspended)

As per my comments above I don't have a good grasp on what
"bus_suspended" is for.  ...that being said, if your change here is
actually correct then you probably (?) want to remove the "if
(hsotg->bus_suspended)" check later in this same function.

Said another way, you've now got code that looks like:

if (!hsotg->bus_suspended)
  goto exit;

/* code that I think doesn't touch bus_suspended */

if (hsotg->bus_suspended) {
  /* do something */
} else {
  /* do something else */
}

Presumably the "do something" is now dead code?


>                 goto unlock;
>
>         if (hsotg->lx_state != DWC2_L2)
>                 goto unlock;
>
> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> +       hprt0 = dwc2_read_hprt0(hsotg);
> +
> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>             hprt0 & HPRT0_CONNSTS) {
>                 hsotg->lx_state = DWC2_L0;
>                 goto unlock;
> @@ -4597,36 +4616,51 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>                 spin_lock_irqsave(&hsotg->lock, flags);
>         }
>
> -       /* Exit partial_power_down */
> -       ret = dwc2_exit_partial_power_down(hsotg, true);
> -       if (ret && (ret != -ENOTSUPP))
> -               dev_err(hsotg->dev, "exit partial_power_down failed\n");
> +       switch (hsotg->params.power_down) {
> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>
> -       hsotg->lx_state = DWC2_L0;
> +               /* Exit partial_power_down */
> +               ret = dwc2_exit_partial_power_down(hsotg, true);
> +               if (ret && (ret != -ENOTSUPP))
> +                       dev_err(hsotg->dev, "exit partial_power_down failed\n");
>
> -       spin_unlock_irqrestore(&hsotg->lock, flags);
> +               hsotg->lx_state = DWC2_L0;
>
> -       if (hsotg->bus_suspended) {
> -               spin_lock_irqsave(&hsotg->lock, flags);
> -               hsotg->flags.b.port_suspend_change = 1;
>                 spin_unlock_irqrestore(&hsotg->lock, flags);
> -               dwc2_port_resume(hsotg);
> -       } else {
> -               dwc2_vbus_supply_init(hsotg);
>
> -               /* Wait for controller to correctly update D+/D- level */
> -               usleep_range(3000, 5000);
> +               if (hsotg->bus_suspended) {
> +                       spin_lock_irqsave(&hsotg->lock, flags);
> +                       hsotg->flags.b.port_suspend_change = 1;
> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> +                       dwc2_port_resume(hsotg);
> +               } else {
> +                       dwc2_vbus_supply_init(hsotg);
>
> -               /*
> -                * Clear Port Enable and Port Status changes.
> -                * Enable Port Power.
> -                */
> -               dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
> +                       /* Wait for controller to correctly update D+/D- level */
> +                       usleep_range(3000, 5000);
> +
> +                       /*
> +                        * Clear Port Enable and Port Status changes.
> +                        * Enable Port Power.
> +                        */
> +                       dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
>                                 HPRT0_ENACHG, HPRT0);
> -               /* Wait for controller to detect Port Connect */
> -               usleep_range(5000, 7000);
> +                       /* Wait for controller to detect Port Connect */
> +                       usleep_range(5000, 7000);
> +               }
> +               break;
> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
> +
> +               /* Exit host hibernation. */
> +               if (hsotg->hibernated)
> +                       dwc2_exit_hibernation(hsotg, 0, 0, 1);
> +               break;
> +       default:
> +               goto unlock;
>         }
>
> +       spin_unlock_irqrestore(&hsotg->lock, flags);
> +

I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
applying your patch series.  As far as I can tell your switch
statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
twice.  Is that really legit?



NOTE: in case it helps you, I've attempted to rebase this atop my
series.  Please double-check that I didn't mess anything up, though.

https://chromium.googlesource.com/chromiumos/third_party/kernel/+log/refs/sandbox/dianders/190426-dwc2-stuff


...with that a quick test seems to show that partial power down is
sorta working on rk3288 now.  I _think_ I saw one case where hotplug
failed but I've seen several where it works.  ...unfortunately it
seems to break when I do hotplug on the port where I have
"snps,reset-phy-on-wake" set.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-26 21:00 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 21:00 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Added a new flow of entering and exiting hibernation when PC is
> hibernated or suspended.
>
> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> ---
>  drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
>  1 file changed, 81 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index 45d4a3e1ebd2..f1e92a287cb1 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>         if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>                 goto unlock;
>
> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>             hsotg->flags.b.port_connect_status == 0)
>                 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(hsotg, hprt0, HPRT0);
> -               spin_unlock_irqrestore(&hsotg->lock, flags);
> -               dwc2_vbus_supply_exit(hsotg);
> -               spin_lock_irqsave(&hsotg->lock, flags);
> -       }
> +       switch (hsotg->params.power_down) {
> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
> +               /*
> +                * 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(hsotg, hprt0, HPRT0);
> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> +                       dwc2_vbus_supply_exit(hsotg);
> +                       spin_lock_irqsave(&hsotg->lock, flags);
> +               }
>
> -       /* Enter partial_power_down */
> -       ret = dwc2_enter_partial_power_down(hsotg);
> -       if (ret) {
> -               if (ret != -ENOTSUPP)
> -                       dev_err(hsotg->dev,
> -                               "enter partial_power_down failed\n");
> +               /* Enter partial_power_down */
> +               ret = dwc2_enter_partial_power_down(hsotg);
> +               if (ret) {
> +                       if (ret != -ENOTSUPP)
> +                               dev_err(hsotg->dev,
> +                                       "enter partial_power_down failed\n");
> +                       goto skip_power_saving;
> +               }
> +               hsotg->bus_suspended = true;
> +               break;
> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
> +               if (!hsotg->bus_suspended) {

Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
call dwc2_enter_partial_power_down() even if bus_suspended is true,
but for hibernate you don't call dwc2_enter_hibernation()?


> +                       /* Enter hibernation */
> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> +                       ret = dwc2_enter_hibernation(hsotg, 1);
> +                       spin_lock_irqsave(&hsotg->lock, flags);
> +                       if (ret && ret != -ENOTSUPP)
> +                               dev_err(hsotg->dev,
> +                                       "%s: enter hibernation failed\n",
> +                                       __func__);

nit: no __func__ in dev_xxx() error messages.  The device plus the
message should be enough.  Only resort to __func__ if you're forced to
do an error message without a "struct device *".

nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP

Also, presumably you want to match the error handling in
DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
you see an error?


> +               } else {
> +                       goto skip_power_saving;
> +               }
> +               break;
> +       default:
>                 goto skip_power_saving;
>         }
>
> -       hsotg->bus_suspended = true;
> -

It's a bit weird to remove this, but I guess it just got moved to the
partial power down case?  ...and in the hibernate case you're relying
on the hibernate function to set this?  Yet another frustratingly
asymmetric code structure...


>         /* Ask phy to be suspended */
>         if (!IS_ERR_OR_NULL(hsotg->uphy)) {
>                 spin_unlock_irqrestore(&hsotg->lock, flags);
> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>         int ret = 0;
>         u32 hprt0;
>
> -       hprt0 = dwc2_read_hprt0(hsotg);
> -
>         spin_lock_irqsave(&hsotg->lock, flags);
>
> -       if (dwc2_is_device_mode(hsotg))
> +       if (!hsotg->bus_suspended)

As per my comments above I don't have a good grasp on what
"bus_suspended" is for.  ...that being said, if your change here is
actually correct then you probably (?) want to remove the "if
(hsotg->bus_suspended)" check later in this same function.

Said another way, you've now got code that looks like:

if (!hsotg->bus_suspended)
  goto exit;

/* code that I think doesn't touch bus_suspended */

if (hsotg->bus_suspended) {
  /* do something */
} else {
  /* do something else */
}

Presumably the "do something" is now dead code?


>                 goto unlock;
>
>         if (hsotg->lx_state != DWC2_L2)
>                 goto unlock;
>
> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> +       hprt0 = dwc2_read_hprt0(hsotg);
> +
> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>             hprt0 & HPRT0_CONNSTS) {
>                 hsotg->lx_state = DWC2_L0;
>                 goto unlock;
> @@ -4597,36 +4616,51 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>                 spin_lock_irqsave(&hsotg->lock, flags);
>         }
>
> -       /* Exit partial_power_down */
> -       ret = dwc2_exit_partial_power_down(hsotg, true);
> -       if (ret && (ret != -ENOTSUPP))
> -               dev_err(hsotg->dev, "exit partial_power_down failed\n");
> +       switch (hsotg->params.power_down) {
> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>
> -       hsotg->lx_state = DWC2_L0;
> +               /* Exit partial_power_down */
> +               ret = dwc2_exit_partial_power_down(hsotg, true);
> +               if (ret && (ret != -ENOTSUPP))
> +                       dev_err(hsotg->dev, "exit partial_power_down failed\n");
>
> -       spin_unlock_irqrestore(&hsotg->lock, flags);
> +               hsotg->lx_state = DWC2_L0;
>
> -       if (hsotg->bus_suspended) {
> -               spin_lock_irqsave(&hsotg->lock, flags);
> -               hsotg->flags.b.port_suspend_change = 1;
>                 spin_unlock_irqrestore(&hsotg->lock, flags);
> -               dwc2_port_resume(hsotg);
> -       } else {
> -               dwc2_vbus_supply_init(hsotg);
>
> -               /* Wait for controller to correctly update D+/D- level */
> -               usleep_range(3000, 5000);
> +               if (hsotg->bus_suspended) {
> +                       spin_lock_irqsave(&hsotg->lock, flags);
> +                       hsotg->flags.b.port_suspend_change = 1;
> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> +                       dwc2_port_resume(hsotg);
> +               } else {
> +                       dwc2_vbus_supply_init(hsotg);
>
> -               /*
> -                * Clear Port Enable and Port Status changes.
> -                * Enable Port Power.
> -                */
> -               dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
> +                       /* Wait for controller to correctly update D+/D- level */
> +                       usleep_range(3000, 5000);
> +
> +                       /*
> +                        * Clear Port Enable and Port Status changes.
> +                        * Enable Port Power.
> +                        */
> +                       dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
>                                 HPRT0_ENACHG, HPRT0);
> -               /* Wait for controller to detect Port Connect */
> -               usleep_range(5000, 7000);
> +                       /* Wait for controller to detect Port Connect */
> +                       usleep_range(5000, 7000);
> +               }
> +               break;
> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
> +
> +               /* Exit host hibernation. */
> +               if (hsotg->hibernated)
> +                       dwc2_exit_hibernation(hsotg, 0, 0, 1);
> +               break;
> +       default:
> +               goto unlock;
>         }
>
> +       spin_unlock_irqrestore(&hsotg->lock, flags);
> +

I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
applying your patch series.  As far as I can tell your switch
statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
twice.  Is that really legit?



NOTE: in case it helps you, I've attempted to rebase this atop my
series.  Please double-check that I didn't mess anything up, though.

https://chromium.googlesource.com/chromiumos/third_party/kernel/+log/refs/sandbox/dianders/190426-dwc2-stuff


...with that a quick test seems to show that partial power down is
sorta working on rk3288 now.  I _think_ I saw one case where hotplug
failed but I've seen several where it works.  ...unfortunately it
seems to break when I do hotplug on the port where I have
"snps,reset-phy-on-wake" set.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-26 16:01         ` Doug Anderson
@ 2019-04-26 21:06           ` Doug Anderson
  2019-04-29 12:05             ` Artur Petrosyan
  2019-04-29  8:44           ` Artur Petrosyan
  1 sibling, 1 reply; 84+ messages in thread
From: Doug Anderson @ 2019-04-26 21:06 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn, LKML

Hi,

On Fri, Apr 26, 2019 at 9:01 AM Doug Anderson <dianders@chromium.org> wrote:
>
> Hi,
>
> On Fri, Apr 26, 2019 at 12:11 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
> >
> > Hi Doug,
> >
> > On 4/26/2019 00:13, Doug Anderson wrote:
> > > Hi,
> > >
> > > On Thu, Apr 25, 2019 at 7:01 AM Artur Petrosyan
> > > <Arthur.Petrosyan@synopsys.com> wrote:
> > >>
> > >> Hi,
> > >>
> > >> On 4/25/2019 16:43, Felipe Balbi wrote:
> > >>> Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
> > >>>> This patch set, fixes and improves partial power down and hibernation power
> > >>>> saving modes. Also, adds support for entering/exiting hibernation by
> > >>>> system issued suspend/resume.
> > >>>>
> > >>>> This series contains patches which were submitted to LKML. However, a part
> > >>>> of those patches didn't reach to LKML because of local issue related to
> > >>>> smtp server.
> > >>>>
> > >>>> The patches which reached to LKML are:
> > >>>>
> > >>>> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
> > >>>> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
> > >>>> - usb: dwc2: Fix suspend state in host mode for partial power down.
> > >>>> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> > >>>> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
> > >>>> - usb: dwc2: Fix dwc2_restore_device_registers() function.
> > >>>>
> > >>>> The patches which didn't reach to LKML are:
> > >>>>
> > >>>> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
> > >>>> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
> > >>>> - usb: dwc2: Clear fifo_map when resetting core.
> > >>>> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
> > >>>> - usb: dwc2: Fix hibernation between host and device modes.
> > >>>> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
> > >>>> - usb: dwc2: Add default param to control power optimization.
> > >>>> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
> > >>>>
> > >>>> Submitting all of the patches together in this version.
> > >>>>
> > >>>> Changes from V0:
> > >>>>    - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
> > >>>>      "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
> > >>>>      interrupt handlers.
> > >>>>
> > >>>>
> > >>>> Artur Petrosyan (14):
> > >>>>     usb: dwc2: Fix dwc2_restore_device_registers() function.
> > >>>>     usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
> > >>>>     usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> > >>>>     usb: dwc2: Fix suspend state in host mode for partial power down.
> > >>>>     usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
> > >>>>       function.
> > >>>>     usb: dwc2: Add part. power down exit from
> > >>>>       dwc2_conn_id_status_change().
> > >>>>     usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
> > >>>>     usb: dwc2: Add default param to control power optimization.
> > >>>>     usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
> > >>>>     usb: dwc2: Fix hibernation between host and device modes.
> > >>>>     usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
> > >>>>     usb: dwc2: Clear fifo_map when resetting core.
> > >>>>     usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
> > >>>>     usb: dwc2: Add enter/exit hibernation from system issued
> > >>>>       suspend/resume
> > >>>
> > >>> patches don't apply.
> > >>>
> > >>
> > >> Do we need to wait for Minas's acknowledge or there is problem related
> > >> to the patches?
> > >
> > > It looks like the problem is that my patches won the race and Felipe
> > > applied them before yours.  Thus, presumably, it'll be up to you to
> > > rebase your patches atop mine and re-submit.  Specifically, you can
> > > do:
> > >
> > > git remote add linux_usb_balbi
> > > git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
> > > git fetch linux_usb_balbi
> > > git checkout linux_usb_balbi/testing/next
> > >
> > > If you do that and then try to apply your patches you'll find that
> > > they no longer apply.  AKA try running:
> > >
> > > for patch in 10909749 10909737 10909739 10909745 10909533 \
> > >     10909531 10909747 10909535 10909523 10909741 10909525 \
> > >     10909751 10909527 10909743; do
> > >    curl -L https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_-24-257Bpatch-257D_mbox&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=aWT1hYtXeIeY8ClQ0sNYxwkmJFKDz4iaa4DchNwx3_w&e= | git am
> > > done
> > >
> > > You'll see:
> > >
> > >> Applying: usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> > >> error: patch failed: drivers/usb/dwc2/core_intr.c:435
> > >> error: drivers/usb/dwc2/core_intr.c: patch does not apply
> > >> Patch failed at 0001 usb: dwc2: Fix wakeup detected and session request interrupt handlers.
> > >
> > > NOTE: before reposting it might be a good idea to apply the last 3
> > > patches in my series as per [1] before sending up your series.  Since
> > > Felipe has already applied patches #1 and #2 in that series presumably
> > > he'll also apply #3 - #5.
> > >
> > > I know it'a also up to me to try testing our your patches.  It's still
> > > on my list to give it a shot...
> > >
> > > [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_CAD-3DFV-3DWA07-2BgUkVvsikN-3DiDHZLUJQtzjkKtiBHAEDw4gLNWY7w-40mail.gmail.com&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=9QP_h5ZlnT7ayUE1_6EVEgu8FaI3_kWm9xuzs1qrvdI&e=
> > >
> > > P.S: It's helpful if you CC LKML on patches and discussions about
> > > them.  That allows the magic "permalink via message ID" on
> > > lkml.kernel.org and also allows your patches to be found on
> > > lore.kernel.org/patchwork/
> > >
> > > -Doug
> > >
> >
> > Besides the issue that comes from the patch "usb: dwc2: Fix wakeup
> > detected and session request interrupt handlers." there is one more
> > serious conflict with one of your patches.
> >
> > So the patch "usb: dwc2: bus suspend/resume for hosts with
> > DWC2_POWER_DOWN_PARAM_NONE" have had also been added to the
> > "balbi/testing/next" before my patch series which conflicts with two of
> > my patches.
> >
> > 1. usb: dwc2: Fix suspend state in host mode for partial power down.
> > 2. usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
> >
> > This patch introduced by you "usb: dwc2: bus suspend/resume for hosts
> > with DWC2_POWER_DOWN_PARAM_NONE" got a little bit of issue. It
> > eliminates entering hibernation through system issued suspend by
> > checking "if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL)"
>
> To be fair, the patch does not make entering hibernation worse, does
> it?  Specifically, I'll point to this part of the diff:
>
> - if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
> + if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) {
>
> As you can see, if power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION the
> flow for this "if" test is exactly the same before and after my patch.
>
>
> > . As per the patch you mention that it fixes suspend/resume flow for
> > Altera SOCFPGA and Chrome OS 3.14 kernel tree. I assume that the board
> > has the Partial Power Down enabled core that is why it works out.
>
> I mentioned some of this in my cover letter [1].  To rehash, I said
> "Turning on partial power down on rk3288 doesn't "just work".  I don't
> get hotplug events.  This is despite dwc2 auto-detecting that we are
> power optimized."
>
> ...it is certainly possible that partial power down would work on
> rk3288 if someone had the time to debug it.
>
> NOTE: I don't have an Altera SOCFPGA, but I'll mention that a previous
> iteration of my patch (written by Kever Yang at Rockchip) was reverted
> because it _broke_ Altera SOCFPGAS.  Given my requests to test the new
> version have been met with silence, I'm inclined to land this and hope
> it's all good.  If there are problems then hopefully some actual
> details can be provided.  Last time there were none provided.
>
>
> > However, we don't just support the Partial Power Down feature enabled
> > cores. We also support Hibernation feature enabled cores.
>
> Sure, but the code that is actually landed upstream (even before my
> series) almost certainly doesn't function for Hibernation.  As pointed
> out above the entire "_dwc2_hcd_suspend()" function had a great big:
>
> if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
>   goto skip_power_saving;
>
> ...which, as far as I could tell, meant that Hibernation could not
> possible work.
>
>
> > The patch set that had been introduced by me which includes "usb: dwc2:
> > Add enter/exit hibernation from system issued suspend/resume" patch adds
> > support for both hibernation and Partial Power Down feature enabled
> > cores and fixes several of Partial Power Down and hibernation related
> > issues.
> >
> > This patch set may fix all of the issues related with Altera SOCFPGA or
> > Chrome OS 3.14 kernel tree.
> >
> > That is why we asked you to test the patch set before we could ACK or
> > have chance to debug your patch deeper to see the help of it and to
> > provide you information related to it.
>
> It may well fix my problems and maybe I can use partial power down
> now.  That'd be nice.  It was on my list and I would have worked on it
> last week except that your patches weren't on the mailing list then.
> ...so I moved on to some other work.  To avoid context switching too
> much I needed to get to a stopping point before testing your patches.
> I was hoping to have some nice rebased patches from you to test today,
> but maybe I'll try a hand at rebasing them myself.
>
> NOTE also that though I ported this change from the Chrome OS 3.14
> kernel tree, I'm actually currently working on the Chrome OS 4.19
> tree.  I also made sure to test the changes on mainline Linux.
>
>
> > So now I can rebase my changes to the "balbi/testing/next" but I will
> > have to take the logic of skipping Hibernation out otherwise we will
> > have problems with hibernation enabled cores.
>
> As per above, please have a careful look at my patches and you'll see
> that I was not introducing code that skipped hibernation.  I was
> keeping the same flow as the old code that skipped hibernation.  So if
> you are making hibernation work there should be no problems removing
> that.
>
>
> > We can ask Balbi to permanently suspend adding of the patch "usb: dwc2:
> > bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE" and my
> > patch series to his "testing/next". After you can have a chance to test
> > my patch series we can see if the patches are acknowledged and ask Balbi
> >   to add them.
>
> Personally I'd prefer if Felipe finished landing my series and then
> you rebased atop it.  As I said I'm convinced I'm not making your
> hibernation case any worse.  If you know of actual things that are
> made worse by my series then that would be a reason not to land it,
> but so far I haven't been convinced.
>
>
> [1] https://lkml.kernel.org/r/20190418001356.124334-2-dianders@chromium.org

To add a bit of breadcrumbs, I did the rebase atop my patches and also
did some basic review of yours.  Other than a few nits I think I found
at least one bug where you're unlocking a spinlock twice in the
partial power down case.

I continue to be convinced that the right thing to do is to finish
landing my series and then once you've spun yours atop mine we can
look at landing it.

Here's all my picks atop Felipe's tree that show how I resolved
things:  https://chromium.googlesource.com/chromiumos/third_party/kernel/+log/refs/sandbox/dianders/190426-dwc2-stuff


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-26 16:01         ` Doug Anderson
  2019-04-26 21:06           ` Doug Anderson
@ 2019-04-29  8:44           ` Artur Petrosyan
  1 sibling, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29  8:44 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn, LKML

Hi,

On 4/26/2019 20:02, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 26, 2019 at 12:11 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi Doug,
>>
>> On 4/26/2019 00:13, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Thu, Apr 25, 2019 at 7:01 AM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> On 4/25/2019 16:43, Felipe Balbi wrote:
>>>>> Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
>>>>>> This patch set, fixes and improves partial power down and hibernation power
>>>>>> saving modes. Also, adds support for entering/exiting hibernation by
>>>>>> system issued suspend/resume.
>>>>>>
>>>>>> This series contains patches which were submitted to LKML. However, a part
>>>>>> of those patches didn't reach to LKML because of local issue related to
>>>>>> smtp server.
>>>>>>
>>>>>> The patches which reached to LKML are:
>>>>>>
>>>>>> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
>>>>>> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
>>>>>> - usb: dwc2: Fix suspend state in host mode for partial power down.
>>>>>> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>>>> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>>>>>> - usb: dwc2: Fix dwc2_restore_device_registers() function.
>>>>>>
>>>>>> The patches which didn't reach to LKML are:
>>>>>>
>>>>>> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
>>>>>> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>>>>>> - usb: dwc2: Clear fifo_map when resetting core.
>>>>>> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>>>>>> - usb: dwc2: Fix hibernation between host and device modes.
>>>>>> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>>>>>> - usb: dwc2: Add default param to control power optimization.
>>>>>> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>>>>>
>>>>>> Submitting all of the patches together in this version.
>>>>>>
>>>>>> Changes from V0:
>>>>>>     - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
>>>>>>       "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
>>>>>>       interrupt handlers.
>>>>>>
>>>>>>
>>>>>> Artur Petrosyan (14):
>>>>>>      usb: dwc2: Fix dwc2_restore_device_registers() function.
>>>>>>      usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>>>>>>      usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>>>>      usb: dwc2: Fix suspend state in host mode for partial power down.
>>>>>>      usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
>>>>>>        function.
>>>>>>      usb: dwc2: Add part. power down exit from
>>>>>>        dwc2_conn_id_status_change().
>>>>>>      usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>>>>>      usb: dwc2: Add default param to control power optimization.
>>>>>>      usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>>>>>>      usb: dwc2: Fix hibernation between host and device modes.
>>>>>>      usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>>>>>>      usb: dwc2: Clear fifo_map when resetting core.
>>>>>>      usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>>>>>>      usb: dwc2: Add enter/exit hibernation from system issued
>>>>>>        suspend/resume
>>>>>
>>>>> patches don't apply.
>>>>>
>>>>
>>>> Do we need to wait for Minas's acknowledge or there is problem related
>>>> to the patches?
>>>
>>> It looks like the problem is that my patches won the race and Felipe
>>> applied them before yours.  Thus, presumably, it'll be up to you to
>>> rebase your patches atop mine and re-submit.  Specifically, you can
>>> do:
>>>
>>> git remote add linux_usb_balbi
>>> git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
>>> git fetch linux_usb_balbi
>>> git checkout linux_usb_balbi/testing/next
>>>
>>> If you do that and then try to apply your patches you'll find that
>>> they no longer apply.  AKA try running:
>>>
>>> for patch in 10909749 10909737 10909739 10909745 10909533 \
>>>      10909531 10909747 10909535 10909523 10909741 10909525 \
>>>      10909751 10909527 10909743; do
>>>     curl -L https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_-24-257Bpatch-257D_mbox&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=aWT1hYtXeIeY8ClQ0sNYxwkmJFKDz4iaa4DchNwx3_w&e= | git am
>>> done
>>>
>>> You'll see:
>>>
>>>> Applying: usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>> error: patch failed: drivers/usb/dwc2/core_intr.c:435
>>>> error: drivers/usb/dwc2/core_intr.c: patch does not apply
>>>> Patch failed at 0001 usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>
>>> NOTE: before reposting it might be a good idea to apply the last 3
>>> patches in my series as per [1] before sending up your series.  Since
>>> Felipe has already applied patches #1 and #2 in that series presumably
>>> he'll also apply #3 - #5.
>>>
>>> I know it'a also up to me to try testing our your patches.  It's still
>>> on my list to give it a shot...
>>>
>>> [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_CAD-3DFV-3DWA07-2BgUkVvsikN-3DiDHZLUJQtzjkKtiBHAEDw4gLNWY7w-40mail.gmail.com&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=9QP_h5ZlnT7ayUE1_6EVEgu8FaI3_kWm9xuzs1qrvdI&e=
>>>
>>> P.S: It's helpful if you CC LKML on patches and discussions about
>>> them.  That allows the magic "permalink via message ID" on
>>> lkml.kernel.org and also allows your patches to be found on
>>> lore.kernel.org/patchwork/
>>>
>>> -Doug
>>>
>>
>> Besides the issue that comes from the patch "usb: dwc2: Fix wakeup
>> detected and session request interrupt handlers." there is one more
>> serious conflict with one of your patches.
>>
>> So the patch "usb: dwc2: bus suspend/resume for hosts with
>> DWC2_POWER_DOWN_PARAM_NONE" have had also been added to the
>> "balbi/testing/next" before my patch series which conflicts with two of
>> my patches.
>>
>> 1. usb: dwc2: Fix suspend state in host mode for partial power down.
>> 2. usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
>>
>> This patch introduced by you "usb: dwc2: bus suspend/resume for hosts
>> with DWC2_POWER_DOWN_PARAM_NONE" got a little bit of issue. It
>> eliminates entering hibernation through system issued suspend by
>> checking "if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL)"
> 
> To be fair, the patch does not make entering hibernation worse, does
> it?  Specifically, I'll point to this part of the diff:
>  > - if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
> + if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) {
> 
> As you can see, if power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION the
> flow for this "if" test is exactly the same before and after my patch.
> 
> 

 From the point of making hibernation worse no it doesn't.

>> . As per the patch you mention that it fixes suspend/resume flow for
>> Altera SOCFPGA and Chrome OS 3.14 kernel tree. I assume that the board
>> has the Partial Power Down enabled core that is why it works out.
> 
> I mentioned some of this in my cover letter [1].  To rehash, I said
> "Turning on partial power down on rk3288 doesn't "just work".  I don't
> get hotplug events.  This is despite dwc2 auto-detecting that we are
> power optimized."
> 

Have you tested your patch on any board?


> ...it is certainly possible that partial power down would work on
> rk3288 if someone had the time to debug it.
> 
> NOTE: I don't have an Altera SOCFPGA, but I'll mention that a previous
> iteration of my patch (written by Kever Yang at Rockchip) was reverted
> because it _broke_ Altera SOCFPGAS.  Given my requests to test the new
> version have been met with silence, I'm inclined to land this and hope
> it's all good.  If there are problems then hopefully some actual
> details can be provided.  Last time there were none provided.
> 
>  >> However, we don't just support the Partial Power Down feature enabled
>> cores. We also support Hibernation feature enabled cores.
> 
> Sure, but the code that is actually landed upstream (even before my
> series) almost certainly doesn't function for Hibernation.  As pointed
> out above the entire "_dwc2_hcd_suspend()" function had a great big:
> 
> if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
>    goto skip_power_saving;
> 
> ...which, as far as I could tell, meant that Hibernation could not
> possible work.
> 
> 
>> The patch set that had been introduced by me which includes "usb: dwc2:
>> Add enter/exit hibernation from system issued suspend/resume" patch adds
>> support for both hibernation and Partial Power Down feature enabled
>> cores and fixes several of Partial Power Down and hibernation related
>> issues.
>>
>> This patch set may fix all of the issues related with Altera SOCFPGA or
>> Chrome OS 3.14 kernel tree.
>>
>> That is why we asked you to test the patch set before we could ACK or
>> have chance to debug your patch deeper to see the help of it and to
>> provide you information related to it.
> 
> It may well fix my problems and maybe I can use partial power down
> now.  That'd be nice.  It was on my list and I would have worked on it
> last week except that your patches weren't on the mailing list then.
> ...so I moved on to some other work.  To avoid context switching too
> much I needed to get to a stopping point before testing your patches.
> I was hoping to have some nice rebased patches from you to test today,
> but maybe I'll try a hand at rebasing them myself.
> 
> NOTE also that though I ported this change from the Chrome OS 3.14
> kernel tree, I'm actually currently working on the Chrome OS 4.19
> tree.  I also made sure to test the changes on mainline Linux.
> 
> 
>> So now I can rebase my changes to the "balbi/testing/next" but I will
>> have to take the logic of skipping Hibernation out otherwise we will
>> have problems with hibernation enabled cores.
> 
> As per above, please have a careful look at my patches and you'll see
> that I was not introducing code that skipped hibernation.  I was
> keeping the same flow as the old code that skipped hibernation.  So if
> you are making hibernation work there should be no problems removing
> that.
> 
> 
Ok so after rebase it may be removed.

>> We can ask Balbi to permanently suspend adding of the patch "usb: dwc2:
>> bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE" and my
>> patch series to his "testing/next". After you can have a chance to test
>> my patch series we can see if the patches are acknowledged and ask Balbi
>>    to add them.
> 
> Personally I'd prefer if Felipe finished landing my series and then
> you rebased atop it.  As I said I'm convinced I'm not making your
> hibernation case any worse.  If you know of actual things that are
> made worse by my series then that would be a reason not to land it,
> but so far I haven't been convinced > [1] 
https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_20190418001356.124334-2D2-2Ddianders-40chromium.org&d=DwIFaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=Bgo5YsUKytageORysPEnHFDC2KH68gUT5GSuZFXYBiU&s=5X1sj6qNMNW85zQbTzXJuKIgH74L-P8LsGfSi66MjDE&e=
> 
I have had a look on your patch and made some comments.

Also, tested your patch "usb: dwc2: bus suspend/resume for hosts with 
DWC2_POWER_DOWN_PARAM_NONE" on HAPS-DX. With this patch or without it 
when I have a device connected core  enters to partial power down and 
doesn't exit from it. The attached device cannot be used.



-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers.
@ 2019-04-29 10:54 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 10:54 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 00:44, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> @@ -426,8 +438,6 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
>>                  /* Change to L0 state */
>>                  hsotg->lx_state = DWC2_L0;
>>          } else {
>> -               if (hsotg->params.power_down)
>> -                       return;
>>
> 
> nit: you leave an odd blank line here.  Please delete it.
> 
> -Doug
> 

Agree with this thank you for the review.

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers.
@ 2019-04-29 10:54 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 10:54 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 00:44, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> @@ -426,8 +438,6 @@ static void dwc2_handle_wakeup_detected_intr(struct dwc2_hsotg *hsotg)
>>                  /* Change to L0 state */
>>                  hsotg->lx_state = DWC2_L0;
>>          } else {
>> -               if (hsotg->params.power_down)
>> -                       return;
>>
> 
> nit: you leave an odd blank line here.  Please delete it.
> 
> -Doug
> 

Agree with this thank you for the review.

-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-29 11:03 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 11:03 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 00:45, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> - In dwc2_port_suspend() function added waiting for the
>>    HPRT0.PrtSusp register field to be set.
>>
>> - In _dwc2_hcd_suspend() function added checking of
>>    "hsotg->flags.b.port_connect_status" port connection
>>    status if port connection status is 0 then skipping
>>    power saving (entering partial power down mode).
>>    Because if there is no device connected there would
>>    be no need to enter partial power down mode.
>>
>> - Added "hsotg->bus_suspended = true" beceuse after
> 
> s/beceuse/because
> 
>>    entering partial power down in host mode the
>>    bus_suspended flag must be set.
> 
> The above statement sounds to me like trying to win an argument by
> saying "I'm right because I'm right."  Can you give more details about
> why "bus_suspended" must be set?  See below also.
> 
There is no intention of winning any argument.
Are you familiar with "bus_suspended" flag ? have you looked at what is 
it used for ?

  * @bus_suspended:	True if bus is suspended

So when entering to hibernation is performed bus is suspended. To 
indicate that "hsotg->bus_suspended" is assigned to true.

> 
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> ---
>>   drivers/usb/dwc2/hcd.c | 9 ++++++++-
>>   1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
>> index dd82fa516f3f..1d18258b5ff8 100644
>> --- a/drivers/usb/dwc2/hcd.c
>> +++ b/drivers/usb/dwc2/hcd.c
>> @@ -3479,6 +3479,10 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
>>          hprt0 |= HPRT0_SUSP;
>>          dwc2_writel(hsotg, hprt0, HPRT0);
>>
>> +       /* Wait for the HPRT0.PrtSusp register field to be set */
>> +       if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
>> +               dev_warn(hsotg->dev, "Suspend wasn't generated\n");
>> +
>>          hsotg->bus_suspended = true;
>>
>>          /*
>> @@ -4488,7 +4492,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>          if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>>                  goto unlock;
>>
>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
>> +       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>> +           hsotg->flags.b.port_connect_status == 0)
>>                  goto skip_power_saving;
>>
>>          /*
>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>                  goto skip_power_saving;
>>          }
>>
>> +       hsotg->bus_suspended = true;
>> +
> 
> I'm a bit unsure about this.  Specifically I note that
> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
> Does that now become dead code?
No it doesn't became a dead code.
> 
> ...I talk about this a bit more in my review of ("usb: dwc2: Add
> enter/exit hibernation from system issued suspend/resume")
> 
> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-29 11:03 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 11:03 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 00:45, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> - In dwc2_port_suspend() function added waiting for the
>>    HPRT0.PrtSusp register field to be set.
>>
>> - In _dwc2_hcd_suspend() function added checking of
>>    "hsotg->flags.b.port_connect_status" port connection
>>    status if port connection status is 0 then skipping
>>    power saving (entering partial power down mode).
>>    Because if there is no device connected there would
>>    be no need to enter partial power down mode.
>>
>> - Added "hsotg->bus_suspended = true" beceuse after
> 
> s/beceuse/because
> 
>>    entering partial power down in host mode the
>>    bus_suspended flag must be set.
> 
> The above statement sounds to me like trying to win an argument by
> saying "I'm right because I'm right."  Can you give more details about
> why "bus_suspended" must be set?  See below also.
> 
There is no intention of winning any argument.
Are you familiar with "bus_suspended" flag ? have you looked at what is 
it used for ?

  * @bus_suspended:	True if bus is suspended

So when entering to hibernation is performed bus is suspended. To 
indicate that "hsotg->bus_suspended" is assigned to true.

> 
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> ---
>>   drivers/usb/dwc2/hcd.c | 9 ++++++++-
>>   1 file changed, 8 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
>> index dd82fa516f3f..1d18258b5ff8 100644
>> --- a/drivers/usb/dwc2/hcd.c
>> +++ b/drivers/usb/dwc2/hcd.c
>> @@ -3479,6 +3479,10 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, u16 windex)
>>          hprt0 |= HPRT0_SUSP;
>>          dwc2_writel(hsotg, hprt0, HPRT0);
>>
>> +       /* Wait for the HPRT0.PrtSusp register field to be set */
>> +       if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000))
>> +               dev_warn(hsotg->dev, "Suspend wasn't generated\n");
>> +
>>          hsotg->bus_suspended = true;
>>
>>          /*
>> @@ -4488,7 +4492,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>          if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>>                  goto unlock;
>>
>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
>> +       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>> +           hsotg->flags.b.port_connect_status == 0)
>>                  goto skip_power_saving;
>>
>>          /*
>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>                  goto skip_power_saving;
>>          }
>>
>> +       hsotg->bus_suspended = true;
>> +
> 
> I'm a bit unsure about this.  Specifically I note that
> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
> Does that now become dead code?
No it doesn't became a dead code.
> 
> ...I talk about this a bit more in my review of ("usb: dwc2: Add
> enter/exit hibernation from system issued suspend/resume")
> 
> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-29 11:29 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 11:29 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 00:46, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> - Added a default param "power_saving" to enable or
>>    disable hibernation or partial power down features.
>>
>> - Printed hibernation param in hw_params_show and
>>    power_saving param in params_show.
>>
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
>> ---
>>   drivers/usb/dwc2/core.h    |  3 +++
>>   drivers/usb/dwc2/debugfs.c |  2 ++
>>   drivers/usb/dwc2/params.c  | 19 +++++++++++++------
>>   3 files changed, 18 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
>> index 30bab8463c96..9221933ab64e 100644
>> --- a/drivers/usb/dwc2/core.h
>> +++ b/drivers/usb/dwc2/core.h
>> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
>>    *                      case.
>>    *                      0 - No (default)
>>    *                      1 - Yes
>> + * @power_saving:      Specifies if power saving is enabled or not. If it is
>> + *                     enabled power_down functionality will be enabled.
>>    * @power_down:         Specifies whether the controller support power_down.
>>    *                     If power_down is enabled, the controller will enter
>>    *                     power_down in both peripheral and host mode when
> 
> Why are you adding a new parameter?  power_saving should be exactly
> the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
> anywhere you need it.
Customers should have a parameter using which they will disable entire 
power saving hibernation and Partial Power Down support.

power_down is used to see which power saving mode we got 
(hibernation/partial power down).

> 
> Having two parameters like you're doing is just asking for them to get
> out of sync.  ...and, in fact, I think they will get out of sync.  On
> rk3288, for instance:
> 
> -> dwc2_set_default_params()
> ---> power_saving = true
> ---> dwc2_set_param_power_down()
> -----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
> -> set_params(), which is actually dwc2_set_rk_params()
> ---> power_down = 0
Setting power_down = 0  is a wrong and old option of disabling power 
saving feature because if we set power_down = 0 then it shows that there 
is no support for any power saving mode. That is why this patch is 
introduced to provide an easier way of disabling power saving modes.
> 
> 
> ...so at the end of dwc2_init_params() you will have power_saving =
> true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
> bad.  ...and, in fact:
> 
> # grep '^power' /sys/kernel/debug/*.usb/params
> /sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
> /sys/kernel/debug/ff540000.usb/params:power_down                    : 0
> /sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
> /sys/kernel/debug/ff580000.usb/params:power_down                    : 0
> 
> 
> ...so while you could fix all of the various set_params() functions,
> it seems better to just drop this patch since I don't think it buys
> anything.
I don't think we should drop this patch. Because, it is introducing the 
correct way of disabling power saving (hibernation/partial power down 
modes). Explanation is listed above.

> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-29 11:29 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 11:29 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 00:46, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> - Added a default param "power_saving" to enable or
>>    disable hibernation or partial power down features.
>>
>> - Printed hibernation param in hw_params_show and
>>    power_saving param in params_show.
>>
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
>> ---
>>   drivers/usb/dwc2/core.h    |  3 +++
>>   drivers/usb/dwc2/debugfs.c |  2 ++
>>   drivers/usb/dwc2/params.c  | 19 +++++++++++++------
>>   3 files changed, 18 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
>> index 30bab8463c96..9221933ab64e 100644
>> --- a/drivers/usb/dwc2/core.h
>> +++ b/drivers/usb/dwc2/core.h
>> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
>>    *                      case.
>>    *                      0 - No (default)
>>    *                      1 - Yes
>> + * @power_saving:      Specifies if power saving is enabled or not. If it is
>> + *                     enabled power_down functionality will be enabled.
>>    * @power_down:         Specifies whether the controller support power_down.
>>    *                     If power_down is enabled, the controller will enter
>>    *                     power_down in both peripheral and host mode when
> 
> Why are you adding a new parameter?  power_saving should be exactly
> the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
> anywhere you need it.
Customers should have a parameter using which they will disable entire 
power saving hibernation and Partial Power Down support.

power_down is used to see which power saving mode we got 
(hibernation/partial power down).

> 
> Having two parameters like you're doing is just asking for them to get
> out of sync.  ...and, in fact, I think they will get out of sync.  On
> rk3288, for instance:
> 
> -> dwc2_set_default_params()
> ---> power_saving = true
> ---> dwc2_set_param_power_down()
> -----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
> -> set_params(), which is actually dwc2_set_rk_params()
> ---> power_down = 0
Setting power_down = 0  is a wrong and old option of disabling power 
saving feature because if we set power_down = 0 then it shows that there 
is no support for any power saving mode. That is why this patch is 
introduced to provide an easier way of disabling power saving modes.
> 
> 
> ...so at the end of dwc2_init_params() you will have power_saving =
> true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
> bad.  ...and, in fact:
> 
> # grep '^power' /sys/kernel/debug/*.usb/params
> /sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
> /sys/kernel/debug/ff540000.usb/params:power_down                    : 0
> /sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
> /sys/kernel/debug/ff580000.usb/params:power_down                    : 0
> 
> 
> ...so while you could fix all of the various set_params() functions,
> it seems better to just drop this patch since I don't think it buys
> anything.
I don't think we should drop this patch. Because, it is introducing the 
correct way of disabling power saving (hibernation/partial power down 
modes). Explanation is listed above.

> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
@ 2019-04-29 11:35 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 11:35 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 4/27/2019 00:52, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> To avoid working in two modes (partial power down
>> and hibernation) changed conditions for entering
>> partial power down or hibernation.
>>
>> Instead of checking hw_params.power_optimized and
>> hw_params.hibernation now checking power_down
>> param which already set to one of the options
>> (Hibernation or Partial Power Down) based on
>> OTG_EN_PWROPT.
>>
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
>> ---
>>   drivers/usb/dwc2/core_intr.c | 13 +++++++------
>>   1 file changed, 7 insertions(+), 6 deletions(-)
> 
> In general I'm in support of this patch--it's cleaner and gets rid of
> a needless goto \o/
> 
> ...but you don't go far enough.  You can fully get rid of all of the
> "-ENOTSUPP" stuff.  I've actually picked my patches and yours atop
> Felipe's "testing/next" tree and you can find it here:
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2Blog_refs_sandbox_dianders_190426-2Ddwc2-2Dstuff&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=WBAPjgkB_xB8UlcsYvQdxyxg2a3wC70A-jrd4IucYKw&s=6HkWJc-CszWClXSA1Ja9AupZVe7Qb4VTMofH8yTmj0o&e=
> 
> ...as part of that I've included a patch ("usb: dwc2: Get rid of
> useless error checks for hibernation/partial power down"), AKA:
Have you tested the patch? on which platform?
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2B_0c924f736e2f7c1bb02531aa33c04a3ae5f4fc4c&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=WBAPjgkB_xB8UlcsYvQdxyxg2a3wC70A-jrd4IucYKw&s=pm6jeDE--3WsqgUui0ZU15vcvHZRQ05jA8mvP1LohS0&e=
> 
> Feel free to squash that into your patch or add it to your series if
> you like it.  Note that patch points out that there's are still some
> instances where calling dwc2_exit_partial_power_down() might still
> happen in a case where it's not obvious if we were in partial power
> down mode and made me wonder if there might be some bugs there.
I will test it too. In case it is fully ok and has no issues. I will let 
you know.

> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
@ 2019-04-29 11:35 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 11:35 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 4/27/2019 00:52, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> To avoid working in two modes (partial power down
>> and hibernation) changed conditions for entering
>> partial power down or hibernation.
>>
>> Instead of checking hw_params.power_optimized and
>> hw_params.hibernation now checking power_down
>> param which already set to one of the options
>> (Hibernation or Partial Power Down) based on
>> OTG_EN_PWROPT.
>>
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
>> ---
>>   drivers/usb/dwc2/core_intr.c | 13 +++++++------
>>   1 file changed, 7 insertions(+), 6 deletions(-)
> 
> In general I'm in support of this patch--it's cleaner and gets rid of
> a needless goto \o/
> 
> ...but you don't go far enough.  You can fully get rid of all of the
> "-ENOTSUPP" stuff.  I've actually picked my patches and yours atop
> Felipe's "testing/next" tree and you can find it here:
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2Blog_refs_sandbox_dianders_190426-2Ddwc2-2Dstuff&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=WBAPjgkB_xB8UlcsYvQdxyxg2a3wC70A-jrd4IucYKw&s=6HkWJc-CszWClXSA1Ja9AupZVe7Qb4VTMofH8yTmj0o&e=
> 
> ...as part of that I've included a patch ("usb: dwc2: Get rid of
> useless error checks for hibernation/partial power down"), AKA:
Have you tested the patch? on which platform?
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2B_0c924f736e2f7c1bb02531aa33c04a3ae5f4fc4c&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=WBAPjgkB_xB8UlcsYvQdxyxg2a3wC70A-jrd4IucYKw&s=pm6jeDE--3WsqgUui0ZU15vcvHZRQ05jA8mvP1LohS0&e=
> 
> Feel free to squash that into your patch or add it to your series if
> you like it.  Note that patch points out that there's are still some
> instances where calling dwc2_exit_partial_power_down() might still
> happen in a case where it's not obvious if we were in partial power
> down mode and made me wonder if there might be some bugs there.
I will test it too. In case it is fully ok and has no issues. I will let 
you know.

> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-29 12:01 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 12:01 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 01:01, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Added a new flow of entering and exiting hibernation when PC is
>> hibernated or suspended.
>>
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> ---
>>   drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
>>   1 file changed, 81 insertions(+), 47 deletions(-)
>>
>> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
>> index 45d4a3e1ebd2..f1e92a287cb1 100644
>> --- a/drivers/usb/dwc2/hcd.c
>> +++ b/drivers/usb/dwc2/hcd.c
>> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>          if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>>                  goto unlock;
>>
>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>>              hsotg->flags.b.port_connect_status == 0)
>>                  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(hsotg, hprt0, HPRT0);
>> -               spin_unlock_irqrestore(&hsotg->lock, flags);
>> -               dwc2_vbus_supply_exit(hsotg);
>> -               spin_lock_irqsave(&hsotg->lock, flags);
>> -       }
>> +       switch (hsotg->params.power_down) {
>> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>> +               /*
>> +                * 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(hsotg, hprt0, HPRT0);
>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +                       dwc2_vbus_supply_exit(hsotg);
>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>> +               }
>>
>> -       /* Enter partial_power_down */
>> -       ret = dwc2_enter_partial_power_down(hsotg);
>> -       if (ret) {
>> -               if (ret != -ENOTSUPP)
>> -                       dev_err(hsotg->dev,
>> -                               "enter partial_power_down failed\n");
>> +               /* Enter partial_power_down */
>> +               ret = dwc2_enter_partial_power_down(hsotg);
>> +               if (ret) {
>> +                       if (ret != -ENOTSUPP)
>> +                               dev_err(hsotg->dev,
>> +                                       "enter partial_power_down failed\n");
>> +                       goto skip_power_saving;
>> +               }
>> +               hsotg->bus_suspended = true;
>> +               break;
>> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
>> +               if (!hsotg->bus_suspended) {
> 
> Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
> call dwc2_enter_partial_power_down() even if bus_suspended is true,
> but for hibernate you don't call dwc2_enter_hibernation()?
For Hibernation I do call dwc2_enter_hibernation().

> 
> 
>> +                       /* Enter hibernation */
>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +                       ret = dwc2_enter_hibernation(hsotg, 1);
>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>> +                       if (ret && ret != -ENOTSUPP)
>> +                               dev_err(hsotg->dev,
>> +                                       "%s: enter hibernation failed\n",
>> +                                       __func__);
> 
> nit: no __func__ in dev_xxx() error messages.  The device plus the
> message should be enough.  Only resort to __func__ if you're forced to
> do an error message without a "struct device *".
This code comes form previous implementations I have not touched it not 
to back anything.

> 
> nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP
> 
> Also, presumably you want to match the error handling in
> DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
> you see an error?
When there is an error power_saving should be skipped.

> 
> 
>> +               } else {
>> +                       goto skip_power_saving;
>> +               }
>> +               break;
>> +       default:
>>                  goto skip_power_saving;
>>          }
>>
>> -       hsotg->bus_suspended = true;
>> -
> 
> It's a bit weird to remove this, but I guess it just got moved to the
> partial power down case?  ...and in the hibernate case you're relying
> on the hibernate function to set this?  Yet another frustratingly
> asymmetric code structure...Enter hibernation implements setting bus_suspend so I don't touch this.
Actually this patch set fixes issues it doesn't clean up everything 
related to hibernation or partial power down.

> 
> 
>>          /* Ask phy to be suspended */
>>          if (!IS_ERR_OR_NULL(hsotg->uphy)) {
>>                  spin_unlock_irqrestore(&hsotg->lock, flags);
>> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>>          int ret = 0;
>>          u32 hprt0;
>>
>> -       hprt0 = dwc2_read_hprt0(hsotg);
>> -
>>          spin_lock_irqsave(&hsotg->lock, flags);
>>
>> -       if (dwc2_is_device_mode(hsotg))
>> +       if (!hsotg->bus_suspended)
> 
> As per my comments above I don't have a good grasp on what
> "bus_suspended" is for.  ...that being said, if your change here is
> actually correct then you probably (?) want to remove the "if
> (hsotg->bus_suspended)" check later in this same function.
> 
> Said another way, you've now got code that looks like:
> 
> if (!hsotg->bus_suspended)
>    goto exit;
> 
> /* code that I think doesn't touch bus_suspended */
> 
> if (hsotg->bus_suspended) {
>    /* do something */
> } else {
>    /* do something else */
> }
> 
> Presumably the "do something" is now dead code?
> 
That part is not dad because if hsotg->bus_suspended is true 
resuming/exiting from suspend/partial power down/hibernation should be 
performed.
On the other hand if hsotg->bus_suspended is false there is no need to 
resume.

So of course if core is not suspended the code responsible for resuming 
should not be called. In that sense the code can be called dead.

> 
>>                  goto unlock;
>>
>>          if (hsotg->lx_state != DWC2_L2)
>>                  goto unlock;
>>
>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>> +       hprt0 = dwc2_read_hprt0(hsotg);
>> +
>> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>>              hprt0 & HPRT0_CONNSTS) {
>>                  hsotg->lx_state = DWC2_L0;
>>                  goto unlock;
>> @@ -4597,36 +4616,51 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>>                  spin_lock_irqsave(&hsotg->lock, flags);
>>          }
>>
>> -       /* Exit partial_power_down */
>> -       ret = dwc2_exit_partial_power_down(hsotg, true);
>> -       if (ret && (ret != -ENOTSUPP))
>> -               dev_err(hsotg->dev, "exit partial_power_down failed\n");
>> +       switch (hsotg->params.power_down) {
>> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>>
>> -       hsotg->lx_state = DWC2_L0;
>> +               /* Exit partial_power_down */
>> +               ret = dwc2_exit_partial_power_down(hsotg, true);
>> +               if (ret && (ret != -ENOTSUPP))
>> +                       dev_err(hsotg->dev, "exit partial_power_down failed\n");
>>
>> -       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +               hsotg->lx_state = DWC2_L0;
>>
>> -       if (hsotg->bus_suspended) {
>> -               spin_lock_irqsave(&hsotg->lock, flags);
>> -               hsotg->flags.b.port_suspend_change = 1;
>>                  spin_unlock_irqrestore(&hsotg->lock, flags);
>> -               dwc2_port_resume(hsotg);
>> -       } else {
>> -               dwc2_vbus_supply_init(hsotg);
>>
>> -               /* Wait for controller to correctly update D+/D- level */
>> -               usleep_range(3000, 5000);
>> +               if (hsotg->bus_suspended) {
>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>> +                       hsotg->flags.b.port_suspend_change = 1;
>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +                       dwc2_port_resume(hsotg);
>> +               } else {
>> +                       dwc2_vbus_supply_init(hsotg);
>>
>> -               /*
>> -                * Clear Port Enable and Port Status changes.
>> -                * Enable Port Power.
>> -                */
>> -               dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
>> +                       /* Wait for controller to correctly update D+/D- level */
>> +                       usleep_range(3000, 5000);
>> +
>> +                       /*
>> +                        * Clear Port Enable and Port Status changes.
>> +                        * Enable Port Power.
>> +                        */
>> +                       dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
>>                                  HPRT0_ENACHG, HPRT0);
>> -               /* Wait for controller to detect Port Connect */
>> -               usleep_range(5000, 7000);
>> +                       /* Wait for controller to detect Port Connect */
>> +                       usleep_range(5000, 7000);
>> +               }
>> +               break;
>> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
>> +
>> +               /* Exit host hibernation. */
>> +               if (hsotg->hibernated)
>> +                       dwc2_exit_hibernation(hsotg, 0, 0, 1);
>> +               break;
>> +       default:
>> +               goto unlock;
>>          }
>>
>> +       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +
> 
> I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
> applying your patch series.  As far as I can tell your switch
> statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
> spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
> twice.  Is that really legit?
I have tested the patches on HAPS-DX and Linaro HiKey 960 boards.

> 
> 
> 
> NOTE: in case it helps you, I've attempted to rebase this atop my
> series.  Please double-check that I didn't mess anything up, though
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2Blog_refs_sandbox_dianders_190426-2Ddwc2-2Dstuff&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=2xJPvFyQhKsjBCMYd6_Kpb7_r7HPUAoeJHcQmBH80Gc&s=wEgbdpKgC9t9CfXpI8awXLos9GuRcsNEkpW09dgMxiw&e=
> 
> 
> ...with that a quick test seems to show that partial power down is
> sorta working on rk3288 now.  I _think_ I saw one case where hotplug
> failed but I've seen several where it works.  ...unfortunately it
> seems to break when I do hotplug on the port where I have
> "snps,reset-phy-on-wake" set.
You can provide debug logs for that scenario I will try to help you fix 
issues with that.

> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-29 12:01 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 12:01 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/27/2019 01:01, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Added a new flow of entering and exiting hibernation when PC is
>> hibernated or suspended.
>>
>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>> ---
>>   drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
>>   1 file changed, 81 insertions(+), 47 deletions(-)
>>
>> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
>> index 45d4a3e1ebd2..f1e92a287cb1 100644
>> --- a/drivers/usb/dwc2/hcd.c
>> +++ b/drivers/usb/dwc2/hcd.c
>> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>          if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>>                  goto unlock;
>>
>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>>              hsotg->flags.b.port_connect_status == 0)
>>                  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(hsotg, hprt0, HPRT0);
>> -               spin_unlock_irqrestore(&hsotg->lock, flags);
>> -               dwc2_vbus_supply_exit(hsotg);
>> -               spin_lock_irqsave(&hsotg->lock, flags);
>> -       }
>> +       switch (hsotg->params.power_down) {
>> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>> +               /*
>> +                * 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(hsotg, hprt0, HPRT0);
>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +                       dwc2_vbus_supply_exit(hsotg);
>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>> +               }
>>
>> -       /* Enter partial_power_down */
>> -       ret = dwc2_enter_partial_power_down(hsotg);
>> -       if (ret) {
>> -               if (ret != -ENOTSUPP)
>> -                       dev_err(hsotg->dev,
>> -                               "enter partial_power_down failed\n");
>> +               /* Enter partial_power_down */
>> +               ret = dwc2_enter_partial_power_down(hsotg);
>> +               if (ret) {
>> +                       if (ret != -ENOTSUPP)
>> +                               dev_err(hsotg->dev,
>> +                                       "enter partial_power_down failed\n");
>> +                       goto skip_power_saving;
>> +               }
>> +               hsotg->bus_suspended = true;
>> +               break;
>> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
>> +               if (!hsotg->bus_suspended) {
> 
> Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
> call dwc2_enter_partial_power_down() even if bus_suspended is true,
> but for hibernate you don't call dwc2_enter_hibernation()?
For Hibernation I do call dwc2_enter_hibernation().

> 
> 
>> +                       /* Enter hibernation */
>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +                       ret = dwc2_enter_hibernation(hsotg, 1);
>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>> +                       if (ret && ret != -ENOTSUPP)
>> +                               dev_err(hsotg->dev,
>> +                                       "%s: enter hibernation failed\n",
>> +                                       __func__);
> 
> nit: no __func__ in dev_xxx() error messages.  The device plus the
> message should be enough.  Only resort to __func__ if you're forced to
> do an error message without a "struct device *".
This code comes form previous implementations I have not touched it not 
to back anything.

> 
> nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP
> 
> Also, presumably you want to match the error handling in
> DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
> you see an error?
When there is an error power_saving should be skipped.

> 
> 
>> +               } else {
>> +                       goto skip_power_saving;
>> +               }
>> +               break;
>> +       default:
>>                  goto skip_power_saving;
>>          }
>>
>> -       hsotg->bus_suspended = true;
>> -
> 
> It's a bit weird to remove this, but I guess it just got moved to the
> partial power down case?  ...and in the hibernate case you're relying
> on the hibernate function to set this?  Yet another frustratingly
> asymmetric code structure...Enter hibernation implements setting bus_suspend so I don't touch this.
Actually this patch set fixes issues it doesn't clean up everything 
related to hibernation or partial power down.

> 
> 
>>          /* Ask phy to be suspended */
>>          if (!IS_ERR_OR_NULL(hsotg->uphy)) {
>>                  spin_unlock_irqrestore(&hsotg->lock, flags);
>> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>>          int ret = 0;
>>          u32 hprt0;
>>
>> -       hprt0 = dwc2_read_hprt0(hsotg);
>> -
>>          spin_lock_irqsave(&hsotg->lock, flags);
>>
>> -       if (dwc2_is_device_mode(hsotg))
>> +       if (!hsotg->bus_suspended)
> 
> As per my comments above I don't have a good grasp on what
> "bus_suspended" is for.  ...that being said, if your change here is
> actually correct then you probably (?) want to remove the "if
> (hsotg->bus_suspended)" check later in this same function.
> 
> Said another way, you've now got code that looks like:
> 
> if (!hsotg->bus_suspended)
>    goto exit;
> 
> /* code that I think doesn't touch bus_suspended */
> 
> if (hsotg->bus_suspended) {
>    /* do something */
> } else {
>    /* do something else */
> }
> 
> Presumably the "do something" is now dead code?
> 
That part is not dad because if hsotg->bus_suspended is true 
resuming/exiting from suspend/partial power down/hibernation should be 
performed.
On the other hand if hsotg->bus_suspended is false there is no need to 
resume.

So of course if core is not suspended the code responsible for resuming 
should not be called. In that sense the code can be called dead.

> 
>>                  goto unlock;
>>
>>          if (hsotg->lx_state != DWC2_L2)
>>                  goto unlock;
>>
>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>> +       hprt0 = dwc2_read_hprt0(hsotg);
>> +
>> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>>              hprt0 & HPRT0_CONNSTS) {
>>                  hsotg->lx_state = DWC2_L0;
>>                  goto unlock;
>> @@ -4597,36 +4616,51 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>>                  spin_lock_irqsave(&hsotg->lock, flags);
>>          }
>>
>> -       /* Exit partial_power_down */
>> -       ret = dwc2_exit_partial_power_down(hsotg, true);
>> -       if (ret && (ret != -ENOTSUPP))
>> -               dev_err(hsotg->dev, "exit partial_power_down failed\n");
>> +       switch (hsotg->params.power_down) {
>> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>>
>> -       hsotg->lx_state = DWC2_L0;
>> +               /* Exit partial_power_down */
>> +               ret = dwc2_exit_partial_power_down(hsotg, true);
>> +               if (ret && (ret != -ENOTSUPP))
>> +                       dev_err(hsotg->dev, "exit partial_power_down failed\n");
>>
>> -       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +               hsotg->lx_state = DWC2_L0;
>>
>> -       if (hsotg->bus_suspended) {
>> -               spin_lock_irqsave(&hsotg->lock, flags);
>> -               hsotg->flags.b.port_suspend_change = 1;
>>                  spin_unlock_irqrestore(&hsotg->lock, flags);
>> -               dwc2_port_resume(hsotg);
>> -       } else {
>> -               dwc2_vbus_supply_init(hsotg);
>>
>> -               /* Wait for controller to correctly update D+/D- level */
>> -               usleep_range(3000, 5000);
>> +               if (hsotg->bus_suspended) {
>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>> +                       hsotg->flags.b.port_suspend_change = 1;
>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +                       dwc2_port_resume(hsotg);
>> +               } else {
>> +                       dwc2_vbus_supply_init(hsotg);
>>
>> -               /*
>> -                * Clear Port Enable and Port Status changes.
>> -                * Enable Port Power.
>> -                */
>> -               dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
>> +                       /* Wait for controller to correctly update D+/D- level */
>> +                       usleep_range(3000, 5000);
>> +
>> +                       /*
>> +                        * Clear Port Enable and Port Status changes.
>> +                        * Enable Port Power.
>> +                        */
>> +                       dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
>>                                  HPRT0_ENACHG, HPRT0);
>> -               /* Wait for controller to detect Port Connect */
>> -               usleep_range(5000, 7000);
>> +                       /* Wait for controller to detect Port Connect */
>> +                       usleep_range(5000, 7000);
>> +               }
>> +               break;
>> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
>> +
>> +               /* Exit host hibernation. */
>> +               if (hsotg->hibernated)
>> +                       dwc2_exit_hibernation(hsotg, 0, 0, 1);
>> +               break;
>> +       default:
>> +               goto unlock;
>>          }
>>
>> +       spin_unlock_irqrestore(&hsotg->lock, flags);
>> +
> 
> I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
> applying your patch series.  As far as I can tell your switch
> statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
> spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
> twice.  Is that really legit?
I have tested the patches on HAPS-DX and Linaro HiKey 960 boards.

> 
> 
> 
> NOTE: in case it helps you, I've attempted to rebase this atop my
> series.  Please double-check that I didn't mess anything up, though
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2Blog_refs_sandbox_dianders_190426-2Ddwc2-2Dstuff&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=2xJPvFyQhKsjBCMYd6_Kpb7_r7HPUAoeJHcQmBH80Gc&s=wEgbdpKgC9t9CfXpI8awXLos9GuRcsNEkpW09dgMxiw&e=
> 
> 
> ...with that a quick test seems to show that partial power down is
> sorta working on rk3288 now.  I _think_ I saw one case where hotplug
> failed but I've seen several where it works.  ...unfortunately it
> seems to break when I do hotplug on the port where I have
> "snps,reset-phy-on-wake" set.
You can provide debug logs for that scenario I will try to help you fix 
issues with that.

> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-26 21:06           ` Doug Anderson
@ 2019-04-29 12:05             ` Artur Petrosyan
  2019-04-29 17:43               ` Doug Anderson
  0 siblings, 1 reply; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-29 12:05 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn, LKML

Hi,

On 4/27/2019 01:06, Doug Anderson wrote:
> Hi,
> 
> On Fri, Apr 26, 2019 at 9:01 AM Doug Anderson <dianders@chromium.org> wrote:
>>
>> Hi,
>>
>> On Fri, Apr 26, 2019 at 12:11 AM Artur Petrosyan
>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>
>>> Hi Doug,
>>>
>>> On 4/26/2019 00:13, Doug Anderson wrote:
>>>> Hi,
>>>>
>>>> On Thu, Apr 25, 2019 at 7:01 AM Artur Petrosyan
>>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>>
>>>>> Hi,
>>>>>
>>>>> On 4/25/2019 16:43, Felipe Balbi wrote:
>>>>>> Artur Petrosyan <Arthur.Petrosyan@synopsys.com> writes:
>>>>>>> This patch set, fixes and improves partial power down and hibernation power
>>>>>>> saving modes. Also, adds support for entering/exiting hibernation by
>>>>>>> system issued suspend/resume.
>>>>>>>
>>>>>>> This series contains patches which were submitted to LKML. However, a part
>>>>>>> of those patches didn't reach to LKML because of local issue related to
>>>>>>> smtp server.
>>>>>>>
>>>>>>> The patches which reached to LKML are:
>>>>>>>
>>>>>>> - usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change().
>>>>>>> - usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function.
>>>>>>> - usb: dwc2: Fix suspend state in host mode for partial power down.
>>>>>>> - usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>>>>> - usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>>>>>>> - usb: dwc2: Fix dwc2_restore_device_registers() function.
>>>>>>>
>>>>>>> The patches which didn't reach to LKML are:
>>>>>>>
>>>>>>> - usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
>>>>>>> - usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>>>>>>> - usb: dwc2: Clear fifo_map when resetting core.
>>>>>>> - usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>>>>>>> - usb: dwc2: Fix hibernation between host and device modes.
>>>>>>> - usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>>>>>>> - usb: dwc2: Add default param to control power optimization.
>>>>>>> - usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>>>>>>
>>>>>>> Submitting all of the patches together in this version.
>>>>>>>
>>>>>>> Changes from V0:
>>>>>>>     - Replaced 1 with DWC2_POWER_DOWN_PARAM_PARTIAL in commit
>>>>>>>       "9eed02b9fe96 usb: dwc2: Fix wakeup detected and session request
>>>>>>>       interrupt handlers.
>>>>>>>
>>>>>>>
>>>>>>> Artur Petrosyan (14):
>>>>>>>      usb: dwc2: Fix dwc2_restore_device_registers() function.
>>>>>>>      usb: dwc2: Add descriptive debug messages for Partial Power Down mode.
>>>>>>>      usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>>>>>      usb: dwc2: Fix suspend state in host mode for partial power down.
>>>>>>>      usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume()
>>>>>>>        function.
>>>>>>>      usb: dwc2: Add part. power down exit from
>>>>>>>        dwc2_conn_id_status_change().
>>>>>>>      usb: dwc2: Reset DEVADDR after exiting gadget hibernation.
>>>>>>>      usb: dwc2: Add default param to control power optimization.
>>>>>>>      usb: dwc2: Update dwc2_handle_usb_suspend_intr function.
>>>>>>>      usb: dwc2: Fix hibernation between host and device modes.
>>>>>>>      usb: dwc2: Allow exiting hibernation from gpwrdn rst detect
>>>>>>>      usb: dwc2: Clear fifo_map when resetting core.
>>>>>>>      usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated.
>>>>>>>      usb: dwc2: Add enter/exit hibernation from system issued
>>>>>>>        suspend/resume
>>>>>>
>>>>>> patches don't apply.
>>>>>>
>>>>>
>>>>> Do we need to wait for Minas's acknowledge or there is problem related
>>>>> to the patches?
>>>>
>>>> It looks like the problem is that my patches won the race and Felipe
>>>> applied them before yours.  Thus, presumably, it'll be up to you to
>>>> rebase your patches atop mine and re-submit.  Specifically, you can
>>>> do:
>>>>
>>>> git remote add linux_usb_balbi
>>>> git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
>>>> git fetch linux_usb_balbi
>>>> git checkout linux_usb_balbi/testing/next
>>>>
>>>> If you do that and then try to apply your patches you'll find that
>>>> they no longer apply.  AKA try running:
>>>>
>>>> for patch in 10909749 10909737 10909739 10909745 10909533 \
>>>>      10909531 10909747 10909535 10909523 10909741 10909525 \
>>>>      10909751 10909527 10909743; do
>>>>     curl -L https://urldefense.proofpoint.com/v2/url?u=https-3A__patchwork.kernel.org_patch_-24-257Bpatch-257D_mbox&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=aWT1hYtXeIeY8ClQ0sNYxwkmJFKDz4iaa4DchNwx3_w&e= | git am
>>>> done
>>>>
>>>> You'll see:
>>>>
>>>>> Applying: usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>>> error: patch failed: drivers/usb/dwc2/core_intr.c:435
>>>>> error: drivers/usb/dwc2/core_intr.c: patch does not apply
>>>>> Patch failed at 0001 usb: dwc2: Fix wakeup detected and session request interrupt handlers.
>>>>
>>>> NOTE: before reposting it might be a good idea to apply the last 3
>>>> patches in my series as per [1] before sending up your series.  Since
>>>> Felipe has already applied patches #1 and #2 in that series presumably
>>>> he'll also apply #3 - #5.
>>>>
>>>> I know it'a also up to me to try testing our your patches.  It's still
>>>> on my list to give it a shot...
>>>>
>>>> [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_CAD-3DFV-3DWA07-2BgUkVvsikN-3DiDHZLUJQtzjkKtiBHAEDw4gLNWY7w-40mail.gmail.com&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=gzzEDEbxflLMgk9I-7Re9ytRMvyc_B8iZEmg2xGZN5E&s=9QP_h5ZlnT7ayUE1_6EVEgu8FaI3_kWm9xuzs1qrvdI&e=
>>>>
>>>> P.S: It's helpful if you CC LKML on patches and discussions about
>>>> them.  That allows the magic "permalink via message ID" on
>>>> lkml.kernel.org and also allows your patches to be found on
>>>> lore.kernel.org/patchwork/
>>>>
>>>> -Doug
>>>>
>>>
>>> Besides the issue that comes from the patch "usb: dwc2: Fix wakeup
>>> detected and session request interrupt handlers." there is one more
>>> serious conflict with one of your patches.
>>>
>>> So the patch "usb: dwc2: bus suspend/resume for hosts with
>>> DWC2_POWER_DOWN_PARAM_NONE" have had also been added to the
>>> "balbi/testing/next" before my patch series which conflicts with two of
>>> my patches.
>>>
>>> 1. usb: dwc2: Fix suspend state in host mode for partial power down.
>>> 2. usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
>>>
>>> This patch introduced by you "usb: dwc2: bus suspend/resume for hosts
>>> with DWC2_POWER_DOWN_PARAM_NONE" got a little bit of issue. It
>>> eliminates entering hibernation through system issued suspend by
>>> checking "if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL)"
>>
>> To be fair, the patch does not make entering hibernation worse, does
>> it?  Specifically, I'll point to this part of the diff:
>>
>> - if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL) {
>> + if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) {
>>
>> As you can see, if power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION the
>> flow for this "if" test is exactly the same before and after my patch.
>>
>>
>>> . As per the patch you mention that it fixes suspend/resume flow for
>>> Altera SOCFPGA and Chrome OS 3.14 kernel tree. I assume that the board
>>> has the Partial Power Down enabled core that is why it works out.
>>
>> I mentioned some of this in my cover letter [1].  To rehash, I said
>> "Turning on partial power down on rk3288 doesn't "just work".  I don't
>> get hotplug events.  This is despite dwc2 auto-detecting that we are
>> power optimized."
>>
>> ...it is certainly possible that partial power down would work on
>> rk3288 if someone had the time to debug it.
>>
>> NOTE: I don't have an Altera SOCFPGA, but I'll mention that a previous
>> iteration of my patch (written by Kever Yang at Rockchip) was reverted
>> because it _broke_ Altera SOCFPGAS.  Given my requests to test the new
>> version have been met with silence, I'm inclined to land this and hope
>> it's all good.  If there are problems then hopefully some actual
>> details can be provided.  Last time there were none provided.
>>
>>
>>> However, we don't just support the Partial Power Down feature enabled
>>> cores. We also support Hibernation feature enabled cores.
>>
>> Sure, but the code that is actually landed upstream (even before my
>> series) almost certainly doesn't function for Hibernation.  As pointed
>> out above the entire "_dwc2_hcd_suspend()" function had a great big:
>>
>> if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL)
>>    goto skip_power_saving;
>>
>> ...which, as far as I could tell, meant that Hibernation could not
>> possible work.
>>
>>
>>> The patch set that had been introduced by me which includes "usb: dwc2:
>>> Add enter/exit hibernation from system issued suspend/resume" patch adds
>>> support for both hibernation and Partial Power Down feature enabled
>>> cores and fixes several of Partial Power Down and hibernation related
>>> issues.
>>>
>>> This patch set may fix all of the issues related with Altera SOCFPGA or
>>> Chrome OS 3.14 kernel tree.
>>>
>>> That is why we asked you to test the patch set before we could ACK or
>>> have chance to debug your patch deeper to see the help of it and to
>>> provide you information related to it.
>>
>> It may well fix my problems and maybe I can use partial power down
>> now.  That'd be nice.  It was on my list and I would have worked on it
>> last week except that your patches weren't on the mailing list then.
>> ...so I moved on to some other work.  To avoid context switching too
>> much I needed to get to a stopping point before testing your patches.
>> I was hoping to have some nice rebased patches from you to test today,
>> but maybe I'll try a hand at rebasing them myself.
>>
>> NOTE also that though I ported this change from the Chrome OS 3.14
>> kernel tree, I'm actually currently working on the Chrome OS 4.19
>> tree.  I also made sure to test the changes on mainline Linux.
>>
>>
>>> So now I can rebase my changes to the "balbi/testing/next" but I will
>>> have to take the logic of skipping Hibernation out otherwise we will
>>> have problems with hibernation enabled cores.
>>
>> As per above, please have a careful look at my patches and you'll see
>> that I was not introducing code that skipped hibernation.  I was
>> keeping the same flow as the old code that skipped hibernation.  So if
>> you are making hibernation work there should be no problems removing
>> that.
>>
>>
>>> We can ask Balbi to permanently suspend adding of the patch "usb: dwc2:
>>> bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE" and my
>>> patch series to his "testing/next". After you can have a chance to test
>>> my patch series we can see if the patches are acknowledged and ask Balbi
>>>    to add them.
>>
>> Personally I'd prefer if Felipe finished landing my series and then
>> you rebased atop it.  As I said I'm convinced I'm not making your
>> hibernation case any worse.  If you know of actual things that are
>> made worse by my series then that would be a reason not to land it,
>> but so far I haven't been convinced.
>>
>>
>> [1] https://urldefense.proofpoint.com/v2/url?u=https-3A__lkml.kernel.org_r_20190418001356.124334-2D2-2Ddianders-40chromium.org&d=DwIFaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=mdz-R9O5TUR_zXEeeCZO2341dvcwZro2cedCZzIIans&s=6qAU20vyvZqIWdkRGSUWEdiTr57arbJf2uHECkCuwQg&e=
> 
> To add a bit of breadcrumbs, I did the rebase atop my patches and also
> did some basic review of yours.  Other than a few nits I think I found
> at least one bug where you're unlocking a spinlock twice in the
> partial power down case.
Yeah thank you so much for the review it really helps to make 
conclusions on the implementations. I have tested those patches on 
HAPS-DX platform and have not got any problem. Hibernation and partial 
power down flows are working ok.
> 
> I continue to be convinced that the right thing to do is to finish
> landing my series and then once you've spun yours atop mine we can
> look at landing it.
> 
> Here's all my picks atop Felipe's tree that show how I resolved
> things:  https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2Blog_refs_sandbox_dianders_190426-2Ddwc2-2Dstuff&d=DwIFaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=mdz-R9O5TUR_zXEeeCZO2341dvcwZro2cedCZzIIans&s=mVfBGtiMQg2XVHXmGCWcd584g0DYRH1JDVnEnJWE6P8&e=
> 
> 
> -Doug
> 

I will make my changes then will go ahead and rebase.


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-29 17:35 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-29 17:35 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/27/2019 00:45, Doug Anderson wrote:
> > Hi,
> >
> > On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> - In dwc2_port_suspend() function added waiting for the
> >>    HPRT0.PrtSusp register field to be set.
> >>
> >> - In _dwc2_hcd_suspend() function added checking of
> >>    "hsotg->flags.b.port_connect_status" port connection
> >>    status if port connection status is 0 then skipping
> >>    power saving (entering partial power down mode).
> >>    Because if there is no device connected there would
> >>    be no need to enter partial power down mode.
> >>
> >> - Added "hsotg->bus_suspended = true" beceuse after
> >
> > s/beceuse/because
> >
> >>    entering partial power down in host mode the
> >>    bus_suspended flag must be set.
> >
> > The above statement sounds to me like trying to win an argument by
> > saying "I'm right because I'm right."  Can you give more details about
> > why "bus_suspended" must be set?  See below also.
> >
> There is no intention of winning any argument.

I was trying to say that your statement does not convey any
information about the "why".  It just says: "I now set this variable
because it needs to be set".  This tells me nothing useful because
presumably if it did't need to be set then you wouldn't have set it.
I want to know more information about how the code was broken before
you did this.  What specifically requires this variable to be set?


> Are you familiar with "bus_suspended" flag ? have you looked at what is
> it used for ?
>
>   * @bus_suspended:     True if bus is suspended
>
> So when entering to hibernation is performed bus is suspended. To
> indicate that "hsotg->bus_suspended" is assigned to true.

Perhaps you can help me understand what the difference is between
"port suspend" and "bus suspend" on dwc2.  I think this is where my
confusion lies since there are functions for both and they do subtly
different things.  ...but both functions set bus_suspended.


> >> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
> >>                  goto skip_power_saving;
> >>          }
> >>
> >> +       hsotg->bus_suspended = true;
> >> +
> >
> > I'm a bit unsure about this.  Specifically I note that
> > _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
> > Does that now become dead code?
> No it doesn't became a dead code.

Can you explain when it gets triggered, then?


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-29 17:35 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-29 17:35 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/27/2019 00:45, Doug Anderson wrote:
> > Hi,
> >
> > On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> - In dwc2_port_suspend() function added waiting for the
> >>    HPRT0.PrtSusp register field to be set.
> >>
> >> - In _dwc2_hcd_suspend() function added checking of
> >>    "hsotg->flags.b.port_connect_status" port connection
> >>    status if port connection status is 0 then skipping
> >>    power saving (entering partial power down mode).
> >>    Because if there is no device connected there would
> >>    be no need to enter partial power down mode.
> >>
> >> - Added "hsotg->bus_suspended = true" beceuse after
> >
> > s/beceuse/because
> >
> >>    entering partial power down in host mode the
> >>    bus_suspended flag must be set.
> >
> > The above statement sounds to me like trying to win an argument by
> > saying "I'm right because I'm right."  Can you give more details about
> > why "bus_suspended" must be set?  See below also.
> >
> There is no intention of winning any argument.

I was trying to say that your statement does not convey any
information about the "why".  It just says: "I now set this variable
because it needs to be set".  This tells me nothing useful because
presumably if it did't need to be set then you wouldn't have set it.
I want to know more information about how the code was broken before
you did this.  What specifically requires this variable to be set?


> Are you familiar with "bus_suspended" flag ? have you looked at what is
> it used for ?
>
>   * @bus_suspended:     True if bus is suspended
>
> So when entering to hibernation is performed bus is suspended. To
> indicate that "hsotg->bus_suspended" is assigned to true.

Perhaps you can help me understand what the difference is between
"port suspend" and "bus suspend" on dwc2.  I think this is where my
confusion lies since there are functions for both and they do subtly
different things.  ...but both functions set bus_suspended.


> >> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
> >>                  goto skip_power_saving;
> >>          }
> >>
> >> +       hsotg->bus_suspended = true;
> >> +
> >
> > I'm a bit unsure about this.  Specifically I note that
> > _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
> > Does that now become dead code?
> No it doesn't became a dead code.

Can you explain when it gets triggered, then?


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-29 17:40 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-29 17:40 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Mon, Apr 29, 2019 at 4:30 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/27/2019 00:46, Doug Anderson wrote:
> > Hi,
> >
> > On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> - Added a default param "power_saving" to enable or
> >>    disable hibernation or partial power down features.
> >>
> >> - Printed hibernation param in hw_params_show and
> >>    power_saving param in params_show.
> >>
> >> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> >> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
> >> ---
> >>   drivers/usb/dwc2/core.h    |  3 +++
> >>   drivers/usb/dwc2/debugfs.c |  2 ++
> >>   drivers/usb/dwc2/params.c  | 19 +++++++++++++------
> >>   3 files changed, 18 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> >> index 30bab8463c96..9221933ab64e 100644
> >> --- a/drivers/usb/dwc2/core.h
> >> +++ b/drivers/usb/dwc2/core.h
> >> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
> >>    *                      case.
> >>    *                      0 - No (default)
> >>    *                      1 - Yes
> >> + * @power_saving:      Specifies if power saving is enabled or not. If it is
> >> + *                     enabled power_down functionality will be enabled.
> >>    * @power_down:         Specifies whether the controller support power_down.
> >>    *                     If power_down is enabled, the controller will enter
> >>    *                     power_down in both peripheral and host mode when
> >
> > Why are you adding a new parameter?  power_saving should be exactly
> > the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
> > anywhere you need it.
> Customers should have a parameter using which they will disable entire
> power saving hibernation and Partial Power Down support.
>
> power_down is used to see which power saving mode we got
> (hibernation/partial power down).
>
> >
> > Having two parameters like you're doing is just asking for them to get
> > out of sync.  ...and, in fact, I think they will get out of sync.  On
> > rk3288, for instance:
> >
> > -> dwc2_set_default_params()
> > ---> power_saving = true
> > ---> dwc2_set_param_power_down()
> > -----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
> > -> set_params(), which is actually dwc2_set_rk_params()
> > ---> power_down = 0
> Setting power_down = 0  is a wrong and old option of disabling power
> saving feature because if we set power_down = 0 then it shows that there
> is no support for any power saving mode. That is why this patch is
> introduced to provide an easier way of disabling power saving modes.

If setting "power_down = 0" is wrong then please update your patch to
remove all the mainline code that sets power_down to 0.  Presumably
this means you'd want to convert that code over to using "power_saving
= False".  Perhaps then I can see your vision of how this works more
clearly.

NOTE: I'm curious how you envision what someone would do if they had a
core that supported hibernation but they only wanted to enable partial
power down.  I guess then they'd have to set "power_saving = True" and
then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
vision of the world is:


// Example 1: Core supports power savings but we want disabled
// (no code since this is the default)

// Example 2: Pick the best power saving available
params->power_saving = True

// Example 3: Supports hibernation, but we only want partial:
params->power_saving = True
params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL


My vision of the world is:

// Example 1: Core supports power savings but we want disabled
params->power_down = DWC2_POWER_DOWN_PARAM_NONE

// Example 2: Pick the best power saving available
// (no code since this is the default)

// Example 3: Supports hibernation, but we only want partial:
params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL


I like that in my vision of the world "pick the best" is the default
(though I suppose we need to fix the driver so it actually works) and
that there's only one variable so you don't have extra confusion.


> > ...so at the end of dwc2_init_params() you will have power_saving =
> > true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
> > bad.  ...and, in fact:
> >
> > # grep '^power' /sys/kernel/debug/*.usb/params
> > /sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
> > /sys/kernel/debug/ff540000.usb/params:power_down                    : 0
> > /sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
> > /sys/kernel/debug/ff580000.usb/params:power_down                    : 0
> >
> >
> > ...so while you could fix all of the various set_params() functions,
> > it seems better to just drop this patch since I don't think it buys
> > anything.
> I don't think we should drop this patch. Because, it is introducing the
> correct way of disabling power saving (hibernation/partial power down
> modes). Explanation is listed above.

I personally see no benefit still.  It's just as clear to me for
someone to set "power_down = DWC2_POWER_DOWN_PARAM_NONE" as it is to
set "power_savings = False".

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-29 17:40 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-29 17:40 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Mon, Apr 29, 2019 at 4:30 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/27/2019 00:46, Doug Anderson wrote:
> > Hi,
> >
> > On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> - Added a default param "power_saving" to enable or
> >>    disable hibernation or partial power down features.
> >>
> >> - Printed hibernation param in hw_params_show and
> >>    power_saving param in params_show.
> >>
> >> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> >> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
> >> ---
> >>   drivers/usb/dwc2/core.h    |  3 +++
> >>   drivers/usb/dwc2/debugfs.c |  2 ++
> >>   drivers/usb/dwc2/params.c  | 19 +++++++++++++------
> >>   3 files changed, 18 insertions(+), 6 deletions(-)
> >>
> >> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> >> index 30bab8463c96..9221933ab64e 100644
> >> --- a/drivers/usb/dwc2/core.h
> >> +++ b/drivers/usb/dwc2/core.h
> >> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
> >>    *                      case.
> >>    *                      0 - No (default)
> >>    *                      1 - Yes
> >> + * @power_saving:      Specifies if power saving is enabled or not. If it is
> >> + *                     enabled power_down functionality will be enabled.
> >>    * @power_down:         Specifies whether the controller support power_down.
> >>    *                     If power_down is enabled, the controller will enter
> >>    *                     power_down in both peripheral and host mode when
> >
> > Why are you adding a new parameter?  power_saving should be exactly
> > the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
> > anywhere you need it.
> Customers should have a parameter using which they will disable entire
> power saving hibernation and Partial Power Down support.
>
> power_down is used to see which power saving mode we got
> (hibernation/partial power down).
>
> >
> > Having two parameters like you're doing is just asking for them to get
> > out of sync.  ...and, in fact, I think they will get out of sync.  On
> > rk3288, for instance:
> >
> > -> dwc2_set_default_params()
> > ---> power_saving = true
> > ---> dwc2_set_param_power_down()
> > -----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
> > -> set_params(), which is actually dwc2_set_rk_params()
> > ---> power_down = 0
> Setting power_down = 0  is a wrong and old option of disabling power
> saving feature because if we set power_down = 0 then it shows that there
> is no support for any power saving mode. That is why this patch is
> introduced to provide an easier way of disabling power saving modes.

If setting "power_down = 0" is wrong then please update your patch to
remove all the mainline code that sets power_down to 0.  Presumably
this means you'd want to convert that code over to using "power_saving
= False".  Perhaps then I can see your vision of how this works more
clearly.

NOTE: I'm curious how you envision what someone would do if they had a
core that supported hibernation but they only wanted to enable partial
power down.  I guess then they'd have to set "power_saving = True" and
then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
vision of the world is:


// Example 1: Core supports power savings but we want disabled
// (no code since this is the default)

// Example 2: Pick the best power saving available
params->power_saving = True

// Example 3: Supports hibernation, but we only want partial:
params->power_saving = True
params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL


My vision of the world is:

// Example 1: Core supports power savings but we want disabled
params->power_down = DWC2_POWER_DOWN_PARAM_NONE

// Example 2: Pick the best power saving available
// (no code since this is the default)

// Example 3: Supports hibernation, but we only want partial:
params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL


I like that in my vision of the world "pick the best" is the default
(though I suppose we need to fix the driver so it actually works) and
that there's only one variable so you don't have extra confusion.


> > ...so at the end of dwc2_init_params() you will have power_saving =
> > true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
> > bad.  ...and, in fact:
> >
> > # grep '^power' /sys/kernel/debug/*.usb/params
> > /sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
> > /sys/kernel/debug/ff540000.usb/params:power_down                    : 0
> > /sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
> > /sys/kernel/debug/ff580000.usb/params:power_down                    : 0
> >
> >
> > ...so while you could fix all of the various set_params() functions,
> > it seems better to just drop this patch since I don't think it buys
> > anything.
> I don't think we should drop this patch. Because, it is introducing the
> correct way of disabling power saving (hibernation/partial power down
> modes). Explanation is listed above.

I personally see no benefit still.  It's just as clear to me for
someone to set "power_down = DWC2_POWER_DOWN_PARAM_NONE" as it is to
set "power_savings = False".

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-29 17:42 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-29 17:42 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Mon, Apr 29, 2019 at 5:01 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/27/2019 01:01, Doug Anderson wrote:
> > Hi,
> >
> > On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> Added a new flow of entering and exiting hibernation when PC is
> >> hibernated or suspended.
> >>
> >> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> >> ---
> >>   drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
> >>   1 file changed, 81 insertions(+), 47 deletions(-)
> >>
> >> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> >> index 45d4a3e1ebd2..f1e92a287cb1 100644
> >> --- a/drivers/usb/dwc2/hcd.c
> >> +++ b/drivers/usb/dwc2/hcd.c
> >> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
> >>          if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
> >>                  goto unlock;
> >>
> >> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> >> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
> >>              hsotg->flags.b.port_connect_status == 0)
> >>                  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(hsotg, hprt0, HPRT0);
> >> -               spin_unlock_irqrestore(&hsotg->lock, flags);
> >> -               dwc2_vbus_supply_exit(hsotg);
> >> -               spin_lock_irqsave(&hsotg->lock, flags);
> >> -       }
> >> +       switch (hsotg->params.power_down) {
> >> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
> >> +               /*
> >> +                * 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(hsotg, hprt0, HPRT0);
> >> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> >> +                       dwc2_vbus_supply_exit(hsotg);
> >> +                       spin_lock_irqsave(&hsotg->lock, flags);
> >> +               }
> >>
> >> -       /* Enter partial_power_down */
> >> -       ret = dwc2_enter_partial_power_down(hsotg);
> >> -       if (ret) {
> >> -               if (ret != -ENOTSUPP)
> >> -                       dev_err(hsotg->dev,
> >> -                               "enter partial_power_down failed\n");
> >> +               /* Enter partial_power_down */
> >> +               ret = dwc2_enter_partial_power_down(hsotg);
> >> +               if (ret) {
> >> +                       if (ret != -ENOTSUPP)
> >> +                               dev_err(hsotg->dev,
> >> +                                       "enter partial_power_down failed\n");
> >> +                       goto skip_power_saving;
> >> +               }
> >> +               hsotg->bus_suspended = true;
> >> +               break;
> >> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
> >> +               if (!hsotg->bus_suspended) {
> >
> > Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
> > call dwc2_enter_partial_power_down() even if bus_suspended is true,
> > but for hibernate you don't call dwc2_enter_hibernation()?
> For Hibernation I do call dwc2_enter_hibernation().

Maybe you didn't understand the question.  I'll be clearer.

Imagine _dwc2_hcd_suspend() is called but "bus_suspended" is already
true at the start of the function.

If we're in DWC2_POWER_DOWN_PARAM_PARTIAL, _dwc2_hcd_suspend() _will_
call dwc2_enter_partial_power_down()

If we're in DWC2_POWER_DOWN_PARAM_HIBERNATION, _dwc2_hcd_suspend()
_will NOT_ call dwc2_enter_partial_power_down()


This is all part of the whole asymmetry between PARTIAL and
HIBERNATION that makes it hard to understand.


> >> +                       /* Enter hibernation */
> >> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> >> +                       ret = dwc2_enter_hibernation(hsotg, 1);
> >> +                       spin_lock_irqsave(&hsotg->lock, flags);
> >> +                       if (ret && ret != -ENOTSUPP)
> >> +                               dev_err(hsotg->dev,
> >> +                                       "%s: enter hibernation failed\n",
> >> +                                       __func__);
> >
> > nit: no __func__ in dev_xxx() error messages.  The device plus the
> > message should be enough.  Only resort to __func__ if you're forced to
> > do an error message without a "struct device *".
> This code comes form previous implementations I have not touched it not
> to back anything.

Please fix.  Even if you had internal code that did this it still
needs to be fixed when going upstream.  It is highly unlikely you'll
break something when removing something like this.



> > nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP
> >
> > Also, presumably you want to match the error handling in
> > DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
> > you see an error?
> When there is an error power_saving should be skipped.

OK, so you agree?


> >> +               } else {
> >> +                       goto skip_power_saving;
> >> +               }
> >> +               break;
> >> +       default:
> >>                  goto skip_power_saving;
> >>          }
> >>
> >> -       hsotg->bus_suspended = true;
> >> -
> >
> > It's a bit weird to remove this, but I guess it just got moved to the
> > partial power down case?  ...and in the hibernate case you're relying
> > on the hibernate function to set this?  Yet another frustratingly
> > asymmetric code structure...
> Enter hibernation implements setting bus_suspend so I don't touch this.
> Actually this patch set fixes issues it doesn't clean up everything
> related to hibernation or partial power down.

Yet more asymmetry.


> >>          /* Ask phy to be suspended */
> >>          if (!IS_ERR_OR_NULL(hsotg->uphy)) {
> >>                  spin_unlock_irqrestore(&hsotg->lock, flags);
> >> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
> >>          int ret = 0;
> >>          u32 hprt0;
> >>
> >> -       hprt0 = dwc2_read_hprt0(hsotg);
> >> -
> >>          spin_lock_irqsave(&hsotg->lock, flags);
> >>
> >> -       if (dwc2_is_device_mode(hsotg))
> >> +       if (!hsotg->bus_suspended)
> >
> > As per my comments above I don't have a good grasp on what
> > "bus_suspended" is for.  ...that being said, if your change here is
> > actually correct then you probably (?) want to remove the "if
> > (hsotg->bus_suspended)" check later in this same function.
> >
> > Said another way, you've now got code that looks like:
> >
> > if (!hsotg->bus_suspended)
> >    goto exit;
> >
> > /* code that I think doesn't touch bus_suspended */
> >
> > if (hsotg->bus_suspended) {
> >    /* do something */
> > } else {
> >    /* do something else */
> > }
> >
> > Presumably the "do something" is now dead code?
> >
> That part is not dad because if hsotg->bus_suspended is true
> resuming/exiting from suspend/partial power down/hibernation should be
> performed.
> On the other hand if hsotg->bus_suspended is false there is no need to
> resume.
>
> So of course if core is not suspended the code responsible for resuming
> should not be called. In that sense the code can be called dead.

I think I didn't explain it well.  Does this patch help you?

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4e84efdbeb74bcb8b24e2b1fea24153981acc185%5E%21/


> >> +       spin_unlock_irqrestore(&hsotg->lock, flags);
> >> +
> >
> > I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
> > applying your patch series.  As far as I can tell your switch
> > statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
> > spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
> > twice.  Is that really legit?
> I have tested the patches on HAPS-DX and Linaro HiKey 960 boards.

How is it possible that you don't end up spin unlocking more than
once?  This seems like a pretty serious problem.

My guess is that whatever tests you ran didn't actually exercise this
function.  Personally I could only get it to exercise by doing
suspend/resume.

...and when I did, sure enough I saw:

BUG: spinlock already unlocked on CPU#2, kworker/u8:32/5812


> > ...with that a quick test seems to show that partial power down is
> > sorta working on rk3288 now.  I _think_ I saw one case where hotplug
> > failed but I've seen several where it works.  ...unfortunately it
> > seems to break when I do hotplug on the port where I have
> > "snps,reset-phy-on-wake" set.
> You can provide debug logs for that scenario I will try to help you fix
> issues with that.

All you need to do is make sure you run the function
_dwc2_hcd_suspend() with power down mode set to
"DWC2_POWER_DOWN_PARAM_PARTIAL".  ...or walk through the code and see
that spin_unlock_irqrestore() will certainly be called twice.



-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-29 17:42 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-29 17:42 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Mon, Apr 29, 2019 at 5:01 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/27/2019 01:01, Doug Anderson wrote:
> > Hi,
> >
> > On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> Added a new flow of entering and exiting hibernation when PC is
> >> hibernated or suspended.
> >>
> >> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
> >> ---
> >>   drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
> >>   1 file changed, 81 insertions(+), 47 deletions(-)
> >>
> >> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> >> index 45d4a3e1ebd2..f1e92a287cb1 100644
> >> --- a/drivers/usb/dwc2/hcd.c
> >> +++ b/drivers/usb/dwc2/hcd.c
> >> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
> >>          if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
> >>                  goto unlock;
> >>
> >> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
> >> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
> >>              hsotg->flags.b.port_connect_status == 0)
> >>                  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(hsotg, hprt0, HPRT0);
> >> -               spin_unlock_irqrestore(&hsotg->lock, flags);
> >> -               dwc2_vbus_supply_exit(hsotg);
> >> -               spin_lock_irqsave(&hsotg->lock, flags);
> >> -       }
> >> +       switch (hsotg->params.power_down) {
> >> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
> >> +               /*
> >> +                * 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(hsotg, hprt0, HPRT0);
> >> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> >> +                       dwc2_vbus_supply_exit(hsotg);
> >> +                       spin_lock_irqsave(&hsotg->lock, flags);
> >> +               }
> >>
> >> -       /* Enter partial_power_down */
> >> -       ret = dwc2_enter_partial_power_down(hsotg);
> >> -       if (ret) {
> >> -               if (ret != -ENOTSUPP)
> >> -                       dev_err(hsotg->dev,
> >> -                               "enter partial_power_down failed\n");
> >> +               /* Enter partial_power_down */
> >> +               ret = dwc2_enter_partial_power_down(hsotg);
> >> +               if (ret) {
> >> +                       if (ret != -ENOTSUPP)
> >> +                               dev_err(hsotg->dev,
> >> +                                       "enter partial_power_down failed\n");
> >> +                       goto skip_power_saving;
> >> +               }
> >> +               hsotg->bus_suspended = true;
> >> +               break;
> >> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
> >> +               if (!hsotg->bus_suspended) {
> >
> > Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
> > call dwc2_enter_partial_power_down() even if bus_suspended is true,
> > but for hibernate you don't call dwc2_enter_hibernation()?
> For Hibernation I do call dwc2_enter_hibernation().

Maybe you didn't understand the question.  I'll be clearer.

Imagine _dwc2_hcd_suspend() is called but "bus_suspended" is already
true at the start of the function.

If we're in DWC2_POWER_DOWN_PARAM_PARTIAL, _dwc2_hcd_suspend() _will_
call dwc2_enter_partial_power_down()

If we're in DWC2_POWER_DOWN_PARAM_HIBERNATION, _dwc2_hcd_suspend()
_will NOT_ call dwc2_enter_partial_power_down()


This is all part of the whole asymmetry between PARTIAL and
HIBERNATION that makes it hard to understand.


> >> +                       /* Enter hibernation */
> >> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
> >> +                       ret = dwc2_enter_hibernation(hsotg, 1);
> >> +                       spin_lock_irqsave(&hsotg->lock, flags);
> >> +                       if (ret && ret != -ENOTSUPP)
> >> +                               dev_err(hsotg->dev,
> >> +                                       "%s: enter hibernation failed\n",
> >> +                                       __func__);
> >
> > nit: no __func__ in dev_xxx() error messages.  The device plus the
> > message should be enough.  Only resort to __func__ if you're forced to
> > do an error message without a "struct device *".
> This code comes form previous implementations I have not touched it not
> to back anything.

Please fix.  Even if you had internal code that did this it still
needs to be fixed when going upstream.  It is highly unlikely you'll
break something when removing something like this.



> > nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP
> >
> > Also, presumably you want to match the error handling in
> > DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
> > you see an error?
> When there is an error power_saving should be skipped.

OK, so you agree?


> >> +               } else {
> >> +                       goto skip_power_saving;
> >> +               }
> >> +               break;
> >> +       default:
> >>                  goto skip_power_saving;
> >>          }
> >>
> >> -       hsotg->bus_suspended = true;
> >> -
> >
> > It's a bit weird to remove this, but I guess it just got moved to the
> > partial power down case?  ...and in the hibernate case you're relying
> > on the hibernate function to set this?  Yet another frustratingly
> > asymmetric code structure...
> Enter hibernation implements setting bus_suspend so I don't touch this.
> Actually this patch set fixes issues it doesn't clean up everything
> related to hibernation or partial power down.

Yet more asymmetry.


> >>          /* Ask phy to be suspended */
> >>          if (!IS_ERR_OR_NULL(hsotg->uphy)) {
> >>                  spin_unlock_irqrestore(&hsotg->lock, flags);
> >> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
> >>          int ret = 0;
> >>          u32 hprt0;
> >>
> >> -       hprt0 = dwc2_read_hprt0(hsotg);
> >> -
> >>          spin_lock_irqsave(&hsotg->lock, flags);
> >>
> >> -       if (dwc2_is_device_mode(hsotg))
> >> +       if (!hsotg->bus_suspended)
> >
> > As per my comments above I don't have a good grasp on what
> > "bus_suspended" is for.  ...that being said, if your change here is
> > actually correct then you probably (?) want to remove the "if
> > (hsotg->bus_suspended)" check later in this same function.
> >
> > Said another way, you've now got code that looks like:
> >
> > if (!hsotg->bus_suspended)
> >    goto exit;
> >
> > /* code that I think doesn't touch bus_suspended */
> >
> > if (hsotg->bus_suspended) {
> >    /* do something */
> > } else {
> >    /* do something else */
> > }
> >
> > Presumably the "do something" is now dead code?
> >
> That part is not dad because if hsotg->bus_suspended is true
> resuming/exiting from suspend/partial power down/hibernation should be
> performed.
> On the other hand if hsotg->bus_suspended is false there is no need to
> resume.
>
> So of course if core is not suspended the code responsible for resuming
> should not be called. In that sense the code can be called dead.

I think I didn't explain it well.  Does this patch help you?

https://chromium.googlesource.com/chromiumos/third_party/kernel/+/4e84efdbeb74bcb8b24e2b1fea24153981acc185%5E%21/


> >> +       spin_unlock_irqrestore(&hsotg->lock, flags);
> >> +
> >
> > I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
> > applying your patch series.  As far as I can tell your switch
> > statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
> > spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
> > twice.  Is that really legit?
> I have tested the patches on HAPS-DX and Linaro HiKey 960 boards.

How is it possible that you don't end up spin unlocking more than
once?  This seems like a pretty serious problem.

My guess is that whatever tests you ran didn't actually exercise this
function.  Personally I could only get it to exercise by doing
suspend/resume.

...and when I did, sure enough I saw:

BUG: spinlock already unlocked on CPU#2, kworker/u8:32/5812


> > ...with that a quick test seems to show that partial power down is
> > sorta working on rk3288 now.  I _think_ I saw one case where hotplug
> > failed but I've seen several where it works.  ...unfortunately it
> > seems to break when I do hotplug on the port where I have
> > "snps,reset-phy-on-wake" set.
> You can provide debug logs for that scenario I will try to help you fix
> issues with that.

All you need to do is make sure you run the function
_dwc2_hcd_suspend() with power down mode set to
"DWC2_POWER_DOWN_PARAM_PARTIAL".  ...or walk through the code and see
that spin_unlock_irqrestore() will certainly be called twice.



-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes.
  2019-04-29 12:05             ` Artur Petrosyan
@ 2019-04-29 17:43               ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-29 17:43 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn, LKML

Hi,

On Mon, Apr 29, 2019 at 5:05 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> > To add a bit of breadcrumbs, I did the rebase atop my patches and also
> > did some basic review of yours.  Other than a few nits I think I found
> > at least one bug where you're unlocking a spinlock twice in the
> > partial power down case.
> Yeah thank you so much for the review it really helps to make
> conclusions on the implementations. I have tested those patches on
> HAPS-DX platform and have not got any problem. Hibernation and partial
> power down flows are working ok.

Do you happen to have any boards that have "OTG_EN_PWROPT = 0"?  I'd
love testing of my patch series with that.


> > I continue to be convinced that the right thing to do is to finish
> > landing my series and then once you've spun yours atop mine we can
> > look at landing it.
> >
> > Here's all my picks atop Felipe's tree that show how I resolved
> > things:  https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2Blog_refs_sandbox_dianders_190426-2Ddwc2-2Dstuff&d=DwIFaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=mdz-R9O5TUR_zXEeeCZO2341dvcwZro2cedCZzIIans&s=mVfBGtiMQg2XVHXmGCWcd584g0DYRH1JDVnEnJWE6P8&e=
> >
> >
> > -Doug
> >
>
> I will make my changes then will go ahead and rebase.

Thanks!


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-30  7:10 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-30  7:10 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/29/2019 21:35, Doug Anderson wrote:
> Hi,
> 
> On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/27/2019 00:45, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> - In dwc2_port_suspend() function added waiting for the
>>>>     HPRT0.PrtSusp register field to be set.
>>>>
>>>> - In _dwc2_hcd_suspend() function added checking of
>>>>     "hsotg->flags.b.port_connect_status" port connection
>>>>     status if port connection status is 0 then skipping
>>>>     power saving (entering partial power down mode).
>>>>     Because if there is no device connected there would
>>>>     be no need to enter partial power down mode.
>>>>
>>>> - Added "hsotg->bus_suspended = true" beceuse after
>>>
>>> s/beceuse/because
>>>
>>>>     entering partial power down in host mode the
>>>>     bus_suspended flag must be set.
>>>
>>> The above statement sounds to me like trying to win an argument by
>>> saying "I'm right because I'm right."  Can you give more details about
>>> why "bus_suspended" must be set?  See below also.
>>>
>> There is no intention of winning any argument.
> 
> I was trying to say that your statement does not convey any
> information about the "why".  It just says: "I now set this variable
> because it needs to be set".  This tells me nothing useful because
> presumably if it did't need to be set then you wouldn't have set it.
> I want to know more information about how the code was broken before
> you did this.  What specifically requires this variable to be set?
Specifically that variable is set when core enters to hibernation or 
partial power down.
> 
> 
>> Are you familiar with "bus_suspended" flag ? have you looked at what is
>> it used for ?
>>
>>    * @bus_suspended:     True if bus is suspended
>>
>> So when entering to hibernation is performed bus is suspended. To
>> indicate that "hsotg->bus_suspended" is assigned to true.
> 
> Perhaps you can help me understand what the difference is between
> "port suspend" and "bus suspend" on dwc2.  I think this is where my
> confusion lies since there are functions for both and they do subtly
> different things.  ...but both functions set bus_suspended.
dwc2_port_suspend() is a function which is called when set port feature
"USB_PORT_FEAT_SUSPEND" is asserted. Yet, bus_suspended is a variable. 
That variable should be set any time that host enters to hibernation or 
partial power down.

> 
> 
>>>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>>>                   goto skip_power_saving;
>>>>           }
>>>>
>>>> +       hsotg->bus_suspended = true;
>>>> +
>>>
>>> I'm a bit unsure about this.  Specifically I note that
>>> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
>>> Does that now become dead code?
>> No it doesn't became a dead code.
> 
> Can you explain when it gets triggered, then?
_dwc2_hcd_resume() is triggered by the system.
As an example lets assume you have hibernated the PC and then you turn 
the PC on. When you turn the PC back on in that case _dwc2_hcd_resume() 
function is called to resume from suspended state (Hibernation/partial 
power down)
> 
> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-04-30  7:10 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-30  7:10 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/29/2019 21:35, Doug Anderson wrote:
> Hi,
> 
> On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/27/2019 00:45, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> - In dwc2_port_suspend() function added waiting for the
>>>>     HPRT0.PrtSusp register field to be set.
>>>>
>>>> - In _dwc2_hcd_suspend() function added checking of
>>>>     "hsotg->flags.b.port_connect_status" port connection
>>>>     status if port connection status is 0 then skipping
>>>>     power saving (entering partial power down mode).
>>>>     Because if there is no device connected there would
>>>>     be no need to enter partial power down mode.
>>>>
>>>> - Added "hsotg->bus_suspended = true" beceuse after
>>>
>>> s/beceuse/because
>>>
>>>>     entering partial power down in host mode the
>>>>     bus_suspended flag must be set.
>>>
>>> The above statement sounds to me like trying to win an argument by
>>> saying "I'm right because I'm right."  Can you give more details about
>>> why "bus_suspended" must be set?  See below also.
>>>
>> There is no intention of winning any argument.
> 
> I was trying to say that your statement does not convey any
> information about the "why".  It just says: "I now set this variable
> because it needs to be set".  This tells me nothing useful because
> presumably if it did't need to be set then you wouldn't have set it.
> I want to know more information about how the code was broken before
> you did this.  What specifically requires this variable to be set?
Specifically that variable is set when core enters to hibernation or 
partial power down.
> 
> 
>> Are you familiar with "bus_suspended" flag ? have you looked at what is
>> it used for ?
>>
>>    * @bus_suspended:     True if bus is suspended
>>
>> So when entering to hibernation is performed bus is suspended. To
>> indicate that "hsotg->bus_suspended" is assigned to true.
> 
> Perhaps you can help me understand what the difference is between
> "port suspend" and "bus suspend" on dwc2.  I think this is where my
> confusion lies since there are functions for both and they do subtly
> different things.  ...but both functions set bus_suspended.
dwc2_port_suspend() is a function which is called when set port feature
"USB_PORT_FEAT_SUSPEND" is asserted. Yet, bus_suspended is a variable. 
That variable should be set any time that host enters to hibernation or 
partial power down.

> 
> 
>>>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>>>                   goto skip_power_saving;
>>>>           }
>>>>
>>>> +       hsotg->bus_suspended = true;
>>>> +
>>>
>>> I'm a bit unsure about this.  Specifically I note that
>>> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
>>> Does that now become dead code?
>> No it doesn't became a dead code.
> 
> Can you explain when it gets triggered, then?
_dwc2_hcd_resume() is triggered by the system.
As an example lets assume you have hibernated the PC and then you turn 
the PC on. When you turn the PC back on in that case _dwc2_hcd_resume() 
function is called to resume from suspended state (Hibernation/partial 
power down)
> 
> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-30 12:45 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-30 12:45 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/29/2019 21:41, Doug Anderson wrote:
> Hi,
> 
> On Mon, Apr 29, 2019 at 4:30 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/27/2019 00:46, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> - Added a default param "power_saving" to enable or
>>>>     disable hibernation or partial power down features.
>>>>
>>>> - Printed hibernation param in hw_params_show and
>>>>     power_saving param in params_show.
>>>>
>>>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>>>> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
>>>> ---
>>>>    drivers/usb/dwc2/core.h    |  3 +++
>>>>    drivers/usb/dwc2/debugfs.c |  2 ++
>>>>    drivers/usb/dwc2/params.c  | 19 +++++++++++++------
>>>>    3 files changed, 18 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
>>>> index 30bab8463c96..9221933ab64e 100644
>>>> --- a/drivers/usb/dwc2/core.h
>>>> +++ b/drivers/usb/dwc2/core.h
>>>> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
>>>>     *                      case.
>>>>     *                      0 - No (default)
>>>>     *                      1 - Yes
>>>> + * @power_saving:      Specifies if power saving is enabled or not. If it is
>>>> + *                     enabled power_down functionality will be enabled.
>>>>     * @power_down:         Specifies whether the controller support power_down.
>>>>     *                     If power_down is enabled, the controller will enter
>>>>     *                     power_down in both peripheral and host mode when
>>>
>>> Why are you adding a new parameter?  power_saving should be exactly
>>> the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
>>> anywhere you need it.
>> Customers should have a parameter using which they will disable entire
>> power saving hibernation and Partial Power Down support.
>>
>> power_down is used to see which power saving mode we got
>> (hibernation/partial power down).
>>
>>>
>>> Having two parameters like you're doing is just asking for them to get
>>> out of sync.  ...and, in fact, I think they will get out of sync.  On
>>> rk3288, for instance:
>>>
>>> -> dwc2_set_default_params()
>>> ---> power_saving = true
>>> ---> dwc2_set_param_power_down()
>>> -----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
>>> -> set_params(), which is actually dwc2_set_rk_params()
>>> ---> power_down = 0
>> Setting power_down = 0  is a wrong and old option of disabling power
>> saving feature because if we set power_down = 0 then it shows that there
>> is no support for any power saving mode. That is why this patch is
>> introduced to provide an easier way of disabling power saving modes.
> 
> If setting "power_down = 0" is wrong then please update your patch to
> remove all the mainline code that sets power_down to 0.  Presumably
> this means you'd want to convert that code over to using "power_saving
> = False".  Perhaps then I can see your vision of how this works more
> clearly.
Yes this is a good idea.
> 
> NOTE: I'm curious how you envision what someone would do if they had a
> core that supported hibernation but they only wanted to enable partial
> power down.  I guess then they'd have to set "power_saving = True" and
> then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
> vision of the world is:
I have implemented everything based on programming guide and data book.
Core can only support hibernation or partial power down based on the 
configuration parameters. There cannot be two modes simultaneously of 
power saving only one of them.

The power_down flag is set to DWC2_POWER_DOWN_PARAM_PARTIAL , 
DWC2_POWER_DOWN_PARAM_HIBERNATION or DWC2_POWER_DOWN_PARAM_NONE while 
checking the hw parameters. So it just indicates which power down mode 
is supporting the core.

> 
> 
> // Example 1: Core supports power savings but we want disabled
> // (no code since this is the default)
> 
> // Example 2: Pick the best power saving available
> params->power_saving = True
> 
> // Example 3: Supports hibernation, but we only want partial:
> params->power_saving = True
> params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
> 
> 
> My vision of the world is:
> 
> // Example 1: Core supports power savings but we want disabled
> params->power_down = DWC2_POWER_DOWN_PARAM_NONE
If we do so it will show that core doesn't support both hibernation and 
partial power down but the core actually supports one of them.

> 
> // Example 2: Pick the best power saving available
> // (no code since this is the default)
> 
> // Example 3: Supports hibernation, but we only want partial:
> params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
There is only one mode available at one core hibernation or partial 
power down.
> 
> 
> I like that in my vision of the world "pick the best" is the default
> (though I suppose we need to fix the driver so it actually works) and
> that there's only one variable so you don't have extra confusion.
Confusion will be when let's say core supports hibernation but you set 
power_down to DWC2_POWER_DOWN_PARAM_NONE. This will mean that core 
doesn't support no power saving option. But in reality it does and it is 
hibernation for instance.
> 
> 
>>> ...so at the end of dwc2_init_params() you will have power_saving =
>>> true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
>>> bad.  ...and, in fact:
>>>
>>> # grep '^power' /sys/kernel/debug/*.usb/params
>>> /sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
>>> /sys/kernel/debug/ff540000.usb/params:power_down                    : 0
>>> /sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
>>> /sys/kernel/debug/ff580000.usb/params:power_down                    : 0
>>>
>>>
>>> ...so while you could fix all of the various set_params() functions,
>>> it seems better to just drop this patch since I don't think it buys
>>> anything.
>> I don't think we should drop this patch. Because, it is introducing the
>> correct way of disabling power saving (hibernation/partial power down
>> modes). Explanation is listed above.
> 
> I personally see no benefit still.  It's just as clear to me for
> someone to set "power_down = DWC2_POWER_DOWN_PARAM_NONE" as it is to
> set "power_savings = False".
Your vision of the world to set "power_down = 
DWC2_POWER_DOWN_PARAM_NONE" will indicate that there is no power saving 
mode available on the core.
> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-30 12:45 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-30 12:45 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On 4/29/2019 21:41, Doug Anderson wrote:
> Hi,
> 
> On Mon, Apr 29, 2019 at 4:30 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/27/2019 00:46, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Fri, Apr 19, 2019 at 11:53 AM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> - Added a default param "power_saving" to enable or
>>>>     disable hibernation or partial power down features.
>>>>
>>>> - Printed hibernation param in hw_params_show and
>>>>     power_saving param in params_show.
>>>>
>>>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>>>> Signed-off-by: Minas Harutyunyan <hminas@synopsys.com>
>>>> ---
>>>>    drivers/usb/dwc2/core.h    |  3 +++
>>>>    drivers/usb/dwc2/debugfs.c |  2 ++
>>>>    drivers/usb/dwc2/params.c  | 19 +++++++++++++------
>>>>    3 files changed, 18 insertions(+), 6 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
>>>> index 30bab8463c96..9221933ab64e 100644
>>>> --- a/drivers/usb/dwc2/core.h
>>>> +++ b/drivers/usb/dwc2/core.h
>>>> @@ -373,6 +373,8 @@ enum dwc2_ep0_state {
>>>>     *                      case.
>>>>     *                      0 - No (default)
>>>>     *                      1 - Yes
>>>> + * @power_saving:      Specifies if power saving is enabled or not. If it is
>>>> + *                     enabled power_down functionality will be enabled.
>>>>     * @power_down:         Specifies whether the controller support power_down.
>>>>     *                     If power_down is enabled, the controller will enter
>>>>     *                     power_down in both peripheral and host mode when
>>>
>>> Why are you adding a new parameter?  power_saving should be exactly
>>> the same as "power_down != DWC2_POWER_DOWN_PARAM_NONE".  Just use that
>>> anywhere you need it.
>> Customers should have a parameter using which they will disable entire
>> power saving hibernation and Partial Power Down support.
>>
>> power_down is used to see which power saving mode we got
>> (hibernation/partial power down).
>>
>>>
>>> Having two parameters like you're doing is just asking for them to get
>>> out of sync.  ...and, in fact, I think they will get out of sync.  On
>>> rk3288, for instance:
>>>
>>> -> dwc2_set_default_params()
>>> ---> power_saving = true
>>> ---> dwc2_set_param_power_down()
>>> -----> power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
>>> -> set_params(), which is actually dwc2_set_rk_params()
>>> ---> power_down = 0
>> Setting power_down = 0  is a wrong and old option of disabling power
>> saving feature because if we set power_down = 0 then it shows that there
>> is no support for any power saving mode. That is why this patch is
>> introduced to provide an easier way of disabling power saving modes.
> 
> If setting "power_down = 0" is wrong then please update your patch to
> remove all the mainline code that sets power_down to 0.  Presumably
> this means you'd want to convert that code over to using "power_saving
> = False".  Perhaps then I can see your vision of how this works more
> clearly.
Yes this is a good idea.
> 
> NOTE: I'm curious how you envision what someone would do if they had a
> core that supported hibernation but they only wanted to enable partial
> power down.  I guess then they'd have to set "power_saving = True" and
> then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
> vision of the world is:
I have implemented everything based on programming guide and data book.
Core can only support hibernation or partial power down based on the 
configuration parameters. There cannot be two modes simultaneously of 
power saving only one of them.

The power_down flag is set to DWC2_POWER_DOWN_PARAM_PARTIAL , 
DWC2_POWER_DOWN_PARAM_HIBERNATION or DWC2_POWER_DOWN_PARAM_NONE while 
checking the hw parameters. So it just indicates which power down mode 
is supporting the core.

> 
> 
> // Example 1: Core supports power savings but we want disabled
> // (no code since this is the default)
> 
> // Example 2: Pick the best power saving available
> params->power_saving = True
> 
> // Example 3: Supports hibernation, but we only want partial:
> params->power_saving = True
> params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
> 
> 
> My vision of the world is:
> 
> // Example 1: Core supports power savings but we want disabled
> params->power_down = DWC2_POWER_DOWN_PARAM_NONE
If we do so it will show that core doesn't support both hibernation and 
partial power down but the core actually supports one of them.

> 
> // Example 2: Pick the best power saving available
> // (no code since this is the default)
> 
> // Example 3: Supports hibernation, but we only want partial:
> params->power_down = DWC2_POWER_DOWN_PARAM_PARTIAL
There is only one mode available at one core hibernation or partial 
power down.
> 
> 
> I like that in my vision of the world "pick the best" is the default
> (though I suppose we need to fix the driver so it actually works) and
> that there's only one variable so you don't have extra confusion.
Confusion will be when let's say core supports hibernation but you set 
power_down to DWC2_POWER_DOWN_PARAM_NONE. This will mean that core 
doesn't support no power saving option. But in reality it does and it is 
hibernation for instance.
> 
> 
>>> ...so at the end of dwc2_init_params() you will have power_saving =
>>> true but power_down set to DWC2_POWER_DOWN_PARAM_NONE.  That seems
>>> bad.  ...and, in fact:
>>>
>>> # grep '^power' /sys/kernel/debug/*.usb/params
>>> /sys/kernel/debug/ff540000.usb/params:power_saving                  : 1
>>> /sys/kernel/debug/ff540000.usb/params:power_down                    : 0
>>> /sys/kernel/debug/ff580000.usb/params:power_saving                  : 1
>>> /sys/kernel/debug/ff580000.usb/params:power_down                    : 0
>>>
>>>
>>> ...so while you could fix all of the various set_params() functions,
>>> it seems better to just drop this patch since I don't think it buys
>>> anything.
>> I don't think we should drop this patch. Because, it is introducing the
>> correct way of disabling power saving (hibernation/partial power down
>> modes). Explanation is listed above.
> 
> I personally see no benefit still.  It's just as clear to me for
> someone to set "power_down = DWC2_POWER_DOWN_PARAM_NONE" as it is to
> set "power_savings = False".
Your vision of the world to set "power_down = 
DWC2_POWER_DOWN_PARAM_NONE" will indicate that there is no power saving 
mode available on the core.
> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-30 13:06 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-30 13:06 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 4/29/2019 21:43, Doug Anderson wrote:
> Hi,
> 
> On Mon, Apr 29, 2019 at 5:01 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/27/2019 01:01, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> Added a new flow of entering and exiting hibernation when PC is
>>>> hibernated or suspended.
>>>>
>>>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>>>> ---
>>>>    drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
>>>>    1 file changed, 81 insertions(+), 47 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
>>>> index 45d4a3e1ebd2..f1e92a287cb1 100644
>>>> --- a/drivers/usb/dwc2/hcd.c
>>>> +++ b/drivers/usb/dwc2/hcd.c
>>>> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>>>           if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>>>>                   goto unlock;
>>>>
>>>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>>>> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>>>>               hsotg->flags.b.port_connect_status == 0)
>>>>                   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(hsotg, hprt0, HPRT0);
>>>> -               spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> -               dwc2_vbus_supply_exit(hsotg);
>>>> -               spin_lock_irqsave(&hsotg->lock, flags);
>>>> -       }
>>>> +       switch (hsotg->params.power_down) {
>>>> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>>>> +               /*
>>>> +                * 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(hsotg, hprt0, HPRT0);
>>>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> +                       dwc2_vbus_supply_exit(hsotg);
>>>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>>>> +               }
>>>>
>>>> -       /* Enter partial_power_down */
>>>> -       ret = dwc2_enter_partial_power_down(hsotg);
>>>> -       if (ret) {
>>>> -               if (ret != -ENOTSUPP)
>>>> -                       dev_err(hsotg->dev,
>>>> -                               "enter partial_power_down failed\n");
>>>> +               /* Enter partial_power_down */
>>>> +               ret = dwc2_enter_partial_power_down(hsotg);
>>>> +               if (ret) {
>>>> +                       if (ret != -ENOTSUPP)
>>>> +                               dev_err(hsotg->dev,
>>>> +                                       "enter partial_power_down failed\n");
>>>> +                       goto skip_power_saving;
>>>> +               }
>>>> +               hsotg->bus_suspended = true;
>>>> +               break;
>>>> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
>>>> +               if (!hsotg->bus_suspended) {
>>>
>>> Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
>>> call dwc2_enter_partial_power_down() even if bus_suspended is true,
>>> but for hibernate you don't call dwc2_enter_hibernation()?
>> For Hibernation I do call dwc2_enter_hibernation().
> 
> Maybe you didn't understand the question.  I'll be clearer.
> 
> Imagine _dwc2_hcd_suspend() is called but "bus_suspended" is already
> true at the start of the function.
> 
> If we're in DWC2_POWER_DOWN_PARAM_PARTIAL, _dwc2_hcd_suspend() _will_
> call dwc2_enter_partial_power_down()
> 
> If we're in DWC2_POWER_DOWN_PARAM_HIBERNATION, _dwc2_hcd_suspend()
> _will NOT_ call dwc2_enter_partial_power_down()
So what? why should dwc2_enter_partial_power_down() be called when we 
have power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION ?

So what the switch statement basically does is that it checks if core 
supports partial power down then it calls dwc2_enter_partial_power_down()
if core supports hibernation it calls
dwc2_enter_hibernation();

> 
> 
> This is all part of the whole asymmetry between PARTIAL and
> HIBERNATION that makes it hard to understand.
See partial power down and hibernation are actually two separate 
implementations.
1. When core supports partial power down we enter to partial power down.
2. When core supports Hibernation we enter to Hibernation
3. If core doesn't support none of them we just skip the power saving.

So the switch statement checks the availability of one of the power 
saving modes and then calls either dwc2_enter_hibernation() or 
dwc2_enter_partial_power_down().

> 
> 
>>>> +                       /* Enter hibernation */
>>>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> +                       ret = dwc2_enter_hibernation(hsotg, 1);
>>>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>>>> +                       if (ret && ret != -ENOTSUPP)
>>>> +                               dev_err(hsotg->dev,
>>>> +                                       "%s: enter hibernation failed\n",
>>>> +                                       __func__);
>>>
>>> nit: no __func__ in dev_xxx() error messages.  The device plus the
>>> message should be enough.  Only resort to __func__ if you're forced to
>>> do an error message without a "struct device *".
>> This code comes form previous implementations I have not touched it not
>> to back anything.
> 
> Please fix.  Even if you had internal code that did this it still
> needs to be fixed when going upstream.  It is highly unlikely you'll
> break something when removing something like this.
> 
> 
> 
>>> nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP
>>>
>>> Also, presumably you want to match the error handling in
>>> DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
>>> you see an error?
>> When there is an error power_saving should be skipped.
> 
> OK, so you agree?
Agree that if there is an error en entering to hibernation then power 
saving should be skipped.
> 
> 
>>>> +               } else {
>>>> +                       goto skip_power_saving;
>>>> +               }
>>>> +               break;
>>>> +       default:
>>>>                   goto skip_power_saving;
>>>>           }
>>>>
>>>> -       hsotg->bus_suspended = true;
>>>> -
>>>
>>> It's a bit weird to remove this, but I guess it just got moved to the
>>> partial power down case?  ...and in the hibernate case you're relying
>>> on the hibernate function to set this?  Yet another frustratingly
>>> asymmetric code structure...
>> Enter hibernation implements setting bus_suspend so I don't touch this.
>> Actually this patch set fixes issues it doesn't clean up everything
>> related to hibernation or partial power down.
> 
> Yet more asymmetry.
> 
> 
>>>>           /* Ask phy to be suspended */
>>>>           if (!IS_ERR_OR_NULL(hsotg->uphy)) {
>>>>                   spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>>>>           int ret = 0;
>>>>           u32 hprt0;
>>>>
>>>> -       hprt0 = dwc2_read_hprt0(hsotg);
>>>> -
>>>>           spin_lock_irqsave(&hsotg->lock, flags);
>>>>
>>>> -       if (dwc2_is_device_mode(hsotg))
>>>> +       if (!hsotg->bus_suspended)
>>>
>>> As per my comments above I don't have a good grasp on what
>>> "bus_suspended" is for.  ...that being said, if your change here is
>>> actually correct then you probably (?) want to remove the "if
>>> (hsotg->bus_suspended)" check later in this same function.
>>>
>>> Said another way, you've now got code that looks like:
>>>
>>> if (!hsotg->bus_suspended)
>>>     goto exit;
>>>
>>> /* code that I think doesn't touch bus_suspended */
>>>
>>> if (hsotg->bus_suspended) {
>>>     /* do something */
>>> } else {
>>>     /* do something else */
>>> }
>>>
>>> Presumably the "do something" is now dead code?
>>>
>> That part is not dad because if hsotg->bus_suspended is true
>> resuming/exiting from suspend/partial power down/hibernation should be
>> performed.
>> On the other hand if hsotg->bus_suspended is false there is no need to
>> resume.
>>
>> So of course if core is not suspended the code responsible for resuming
>> should not be called. In that sense the code can be called dead.
> 
> I think I didn't explain it well.  Does this patch help you?
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2B_4e84efdbeb74bcb8b24e2b1fea24153981acc185-255E-2521_&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=nZWkYoZKaqSi_evQfEH0uCUKIXb5UZydmgRSXsVwSOs&s=h-ZqBu_CidHWrCH6sAbTi1ddgSfHkYjwSfCOGjpHbRM&e=
No it doesn't.

This is diff from your suggestion.

hsotg->lx_state = DWC2_L0;

+		hsotg->flags.b.port_suspend_change = 1;
Why are you setting this ?

  		spin_unlock_irqrestore(&hsotg->lock, flags);
-
-		if (hsotg->bus_suspended) {
-			spin_lock_irqsave(&hsotg->lock, flags);
-			hsotg->flags.b.port_suspend_change = 1;
-			spin_unlock_irqrestore(&hsotg->lock, flags);
-			dwc2_port_resume(hsotg);
You have removed this but it should be called when we exit from partial 
power down.
Have you performed testes on this? I am not sure that this is a working 
code.

-		} else {
-			dwc2_vbus_supply_init(hsotg);
-
-			/* Wait for controller to correctly update D+/D- level */
-			usleep_range(3000, 5000);
-
-			/*
-			 * Clear Port Enable and Port Status changes.
-			 * Enable Port Power.
-			 */
-			dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
-				HPRT0_ENACHG, HPRT0);
-			/* Wait for controller to detect Port Connect */
-			usleep_range(5000, 7000);
-		}
+		dwc2_port_resume(hsotg);
  		break;



> 
> 
>>>> +       spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> +
>>>
>>> I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
>>> applying your patch series.  As far as I can tell your switch
>>> statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
>>> spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
>>> twice.  Is that really legit?
>> I have tested the patches on HAPS-DX and Linaro HiKey 960 boards.
> 
> How is it possible that you don't end up spin unlocking more than
> once?  This seems like a pretty serious problem.
> 
> My guess is that whatever tests you ran didn't actually exercise this
> function.  Personally I could only get it to exercise by doing
> suspend/resume.
> 
> ...and when I did, sure enough I saw:
> 
> BUG: spinlock already unlocked on CPU#2, kworker/u8:32/5812
I will debug it once more.
> 
> 
>>> ...with that a quick test seems to show that partial power down is
>>> sorta working on rk3288 now.  I _think_ I saw one case where hotplug
>>> failed but I've seen several where it works.  ...unfortunately it
>>> seems to break when I do hotplug on the port where I have
>>> "snps,reset-phy-on-wake" set.
>> You can provide debug logs for that scenario I will try to help you fix
>> issues with that.
> 
> All you need to do is make sure you run the function
> _dwc2_hcd_suspend() with power down mode set to
> "DWC2_POWER_DOWN_PARAM_PARTIAL".  ...or walk through the code and see
> that spin_unlock_irqrestore() will certainly be called twice.
I hibernate the PC it enters to partial power down then I turn PC on 
everything works fine. But I will check this one more time.
> 
> 
> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume
@ 2019-04-30 13:06 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-04-30 13:06 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 4/29/2019 21:43, Doug Anderson wrote:
> Hi,
> 
> On Mon, Apr 29, 2019 at 5:01 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/27/2019 01:01, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> Added a new flow of entering and exiting hibernation when PC is
>>>> hibernated or suspended.
>>>>
>>>> Signed-off-by: Artur Petrosyan <arturp@synopsys.com>
>>>> ---
>>>>    drivers/usb/dwc2/hcd.c | 128 +++++++++++++++++++++++++++++++------------------
>>>>    1 file changed, 81 insertions(+), 47 deletions(-)
>>>>
>>>> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
>>>> index 45d4a3e1ebd2..f1e92a287cb1 100644
>>>> --- a/drivers/usb/dwc2/hcd.c
>>>> +++ b/drivers/usb/dwc2/hcd.c
>>>> @@ -4510,35 +4510,54 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>>>           if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
>>>>                   goto unlock;
>>>>
>>>> -       if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL ||
>>>> +       if (hsotg->params.power_down == DWC2_POWER_DOWN_PARAM_NONE ||
>>>>               hsotg->flags.b.port_connect_status == 0)
>>>>                   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(hsotg, hprt0, HPRT0);
>>>> -               spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> -               dwc2_vbus_supply_exit(hsotg);
>>>> -               spin_lock_irqsave(&hsotg->lock, flags);
>>>> -       }
>>>> +       switch (hsotg->params.power_down) {
>>>> +       case DWC2_POWER_DOWN_PARAM_PARTIAL:
>>>> +               /*
>>>> +                * 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(hsotg, hprt0, HPRT0);
>>>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> +                       dwc2_vbus_supply_exit(hsotg);
>>>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>>>> +               }
>>>>
>>>> -       /* Enter partial_power_down */
>>>> -       ret = dwc2_enter_partial_power_down(hsotg);
>>>> -       if (ret) {
>>>> -               if (ret != -ENOTSUPP)
>>>> -                       dev_err(hsotg->dev,
>>>> -                               "enter partial_power_down failed\n");
>>>> +               /* Enter partial_power_down */
>>>> +               ret = dwc2_enter_partial_power_down(hsotg);
>>>> +               if (ret) {
>>>> +                       if (ret != -ENOTSUPP)
>>>> +                               dev_err(hsotg->dev,
>>>> +                                       "enter partial_power_down failed\n");
>>>> +                       goto skip_power_saving;
>>>> +               }
>>>> +               hsotg->bus_suspended = true;
>>>> +               break;
>>>> +       case DWC2_POWER_DOWN_PARAM_HIBERNATION:
>>>> +               if (!hsotg->bus_suspended) {
>>>
>>> Do you have any idea why for DWC2_POWER_DOWN_PARAM_PARTIAL we still
>>> call dwc2_enter_partial_power_down() even if bus_suspended is true,
>>> but for hibernate you don't call dwc2_enter_hibernation()?
>> For Hibernation I do call dwc2_enter_hibernation().
> 
> Maybe you didn't understand the question.  I'll be clearer.
> 
> Imagine _dwc2_hcd_suspend() is called but "bus_suspended" is already
> true at the start of the function.
> 
> If we're in DWC2_POWER_DOWN_PARAM_PARTIAL, _dwc2_hcd_suspend() _will_
> call dwc2_enter_partial_power_down()
> 
> If we're in DWC2_POWER_DOWN_PARAM_HIBERNATION, _dwc2_hcd_suspend()
> _will NOT_ call dwc2_enter_partial_power_down()
So what? why should dwc2_enter_partial_power_down() be called when we 
have power_down == DWC2_POWER_DOWN_PARAM_HIBERNATION ?

So what the switch statement basically does is that it checks if core 
supports partial power down then it calls dwc2_enter_partial_power_down()
if core supports hibernation it calls
dwc2_enter_hibernation();

> 
> 
> This is all part of the whole asymmetry between PARTIAL and
> HIBERNATION that makes it hard to understand.
See partial power down and hibernation are actually two separate 
implementations.
1. When core supports partial power down we enter to partial power down.
2. When core supports Hibernation we enter to Hibernation
3. If core doesn't support none of them we just skip the power saving.

So the switch statement checks the availability of one of the power 
saving modes and then calls either dwc2_enter_hibernation() or 
dwc2_enter_partial_power_down().

> 
> 
>>>> +                       /* Enter hibernation */
>>>> +                       spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> +                       ret = dwc2_enter_hibernation(hsotg, 1);
>>>> +                       spin_lock_irqsave(&hsotg->lock, flags);
>>>> +                       if (ret && ret != -ENOTSUPP)
>>>> +                               dev_err(hsotg->dev,
>>>> +                                       "%s: enter hibernation failed\n",
>>>> +                                       __func__);
>>>
>>> nit: no __func__ in dev_xxx() error messages.  The device plus the
>>> message should be enough.  Only resort to __func__ if you're forced to
>>> do an error message without a "struct device *".
>> This code comes form previous implementations I have not touched it not
>> to back anything.
> 
> Please fix.  Even if you had internal code that did this it still
> needs to be fixed when going upstream.  It is highly unlikely you'll
> break something when removing something like this.
> 
> 
> 
>>> nit: as per my comments in an earlier patch, remove special case for -ENOTSUPP
>>>
>>> Also, presumably you want to match the error handling in
>>> DWC2_POWER_DOWN_PARAM_PARTIAL and do a "goto skip_power_saving" when
>>> you see an error?
>> When there is an error power_saving should be skipped.
> 
> OK, so you agree?
Agree that if there is an error en entering to hibernation then power 
saving should be skipped.
> 
> 
>>>> +               } else {
>>>> +                       goto skip_power_saving;
>>>> +               }
>>>> +               break;
>>>> +       default:
>>>>                   goto skip_power_saving;
>>>>           }
>>>>
>>>> -       hsotg->bus_suspended = true;
>>>> -
>>>
>>> It's a bit weird to remove this, but I guess it just got moved to the
>>> partial power down case?  ...and in the hibernate case you're relying
>>> on the hibernate function to set this?  Yet another frustratingly
>>> asymmetric code structure...
>> Enter hibernation implements setting bus_suspend so I don't touch this.
>> Actually this patch set fixes issues it doesn't clean up everything
>> related to hibernation or partial power down.
> 
> Yet more asymmetry.
> 
> 
>>>>           /* Ask phy to be suspended */
>>>>           if (!IS_ERR_OR_NULL(hsotg->uphy)) {
>>>>                   spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> @@ -4564,17 +4583,17 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
>>>>           int ret = 0;
>>>>           u32 hprt0;
>>>>
>>>> -       hprt0 = dwc2_read_hprt0(hsotg);
>>>> -
>>>>           spin_lock_irqsave(&hsotg->lock, flags);
>>>>
>>>> -       if (dwc2_is_device_mode(hsotg))
>>>> +       if (!hsotg->bus_suspended)
>>>
>>> As per my comments above I don't have a good grasp on what
>>> "bus_suspended" is for.  ...that being said, if your change here is
>>> actually correct then you probably (?) want to remove the "if
>>> (hsotg->bus_suspended)" check later in this same function.
>>>
>>> Said another way, you've now got code that looks like:
>>>
>>> if (!hsotg->bus_suspended)
>>>     goto exit;
>>>
>>> /* code that I think doesn't touch bus_suspended */
>>>
>>> if (hsotg->bus_suspended) {
>>>     /* do something */
>>> } else {
>>>     /* do something else */
>>> }
>>>
>>> Presumably the "do something" is now dead code?
>>>
>> That part is not dad because if hsotg->bus_suspended is true
>> resuming/exiting from suspend/partial power down/hibernation should be
>> performed.
>> On the other hand if hsotg->bus_suspended is false there is no need to
>> resume.
>>
>> So of course if core is not suspended the code responsible for resuming
>> should not be called. In that sense the code can be called dead.
> 
> I think I didn't explain it well.  Does this patch help you?
> 
> https://urldefense.proofpoint.com/v2/url?u=https-3A__chromium.googlesource.com_chromiumos_third-5Fparty_kernel_-2B_4e84efdbeb74bcb8b24e2b1fea24153981acc185-255E-2521_&d=DwIBaQ&c=DPL6_X_6JkXFx7AXWqB0tg&r=9hPBFKCJ_nBjJhGVrrlYOeOQjP_HlVzYqrC_D7niMJI&m=nZWkYoZKaqSi_evQfEH0uCUKIXb5UZydmgRSXsVwSOs&s=h-ZqBu_CidHWrCH6sAbTi1ddgSfHkYjwSfCOGjpHbRM&e=
No it doesn't.

This is diff from your suggestion.

hsotg->lx_state = DWC2_L0;

+		hsotg->flags.b.port_suspend_change = 1;
Why are you setting this ?

  		spin_unlock_irqrestore(&hsotg->lock, flags);
-
-		if (hsotg->bus_suspended) {
-			spin_lock_irqsave(&hsotg->lock, flags);
-			hsotg->flags.b.port_suspend_change = 1;
-			spin_unlock_irqrestore(&hsotg->lock, flags);
-			dwc2_port_resume(hsotg);
You have removed this but it should be called when we exit from partial 
power down.
Have you performed testes on this? I am not sure that this is a working 
code.

-		} else {
-			dwc2_vbus_supply_init(hsotg);
-
-			/* Wait for controller to correctly update D+/D- level */
-			usleep_range(3000, 5000);
-
-			/*
-			 * Clear Port Enable and Port Status changes.
-			 * Enable Port Power.
-			 */
-			dwc2_writel(hsotg, HPRT0_PWR | HPRT0_CONNDET |
-				HPRT0_ENACHG, HPRT0);
-			/* Wait for controller to detect Port Connect */
-			usleep_range(5000, 7000);
-		}
+		dwc2_port_resume(hsotg);
  		break;



> 
> 
>>>> +       spin_unlock_irqrestore(&hsotg->lock, flags);
>>>> +
>>>
>>> I'm pretty curious if you tested DWC2_POWER_DOWN_PARAM_PARTIAL after
>>> applying your patch series.  As far as I can tell your switch
>>> statement for DWC2_POWER_DOWN_PARAM_PARTIAL will "break" with the
>>> spinlock already unlocked.  ...so you'll run spin_unlock_irqrestore
>>> twice.  Is that really legit?
>> I have tested the patches on HAPS-DX and Linaro HiKey 960 boards.
> 
> How is it possible that you don't end up spin unlocking more than
> once?  This seems like a pretty serious problem.
> 
> My guess is that whatever tests you ran didn't actually exercise this
> function.  Personally I could only get it to exercise by doing
> suspend/resume.
> 
> ...and when I did, sure enough I saw:
> 
> BUG: spinlock already unlocked on CPU#2, kworker/u8:32/5812
I will debug it once more.
> 
> 
>>> ...with that a quick test seems to show that partial power down is
>>> sorta working on rk3288 now.  I _think_ I saw one case where hotplug
>>> failed but I've seen several where it works.  ...unfortunately it
>>> seems to break when I do hotplug on the port where I have
>>> "snps,reset-phy-on-wake" set.
>> You can provide debug logs for that scenario I will try to help you fix
>> issues with that.
> 
> All you need to do is make sure you run the function
> _dwc2_hcd_suspend() with power down mode set to
> "DWC2_POWER_DOWN_PARAM_PARTIAL".  ...or walk through the code and see
> that spin_unlock_irqrestore() will certainly be called twice.
I hibernate the PC it enters to partial power down then I turn PC on 
everything works fine. But I will check this one more time.
> 
> 
> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-30 15:23 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-30 15:23 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Tue, Apr 30, 2019 at 5:45 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> > If setting "power_down = 0" is wrong then please update your patch to
> > remove all the mainline code that sets power_down to 0.  Presumably
> > this means you'd want to convert that code over to using "power_saving
> > = False".  Perhaps then I can see your vision of how this works more
> > clearly.
> Yes this is a good idea.

Actually, I have a feeling it won't work, at least not without more
changes.  ...and that's part of the problem with your patch.

Specifically dwc2 works by first filling in the "default" parameters.
Then the per-platform config function runs and overrides the defaults.
If the per-platform config function overrides the "power_saving"
parameter then it will be too late.


> > NOTE: I'm curious how you envision what someone would do if they had a
> > core that supported hibernation but they only wanted to enable partial
> > power down.  I guess then they'd have to set "power_saving = True" and
> > then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
> > vision of the world is:
> I have implemented everything based on programming guide and data book.
> Core can only support hibernation or partial power down based on the
> configuration parameters. There cannot be two modes simultaneously of
> power saving only one of them.

Ah, this is new information to me.  I assumed they were supersets of
each other, so if you supported hibernation you also supported partial
power down.  Thanks for clearing that up!


> The power_down flag is set to DWC2_POWER_DOWN_PARAM_PARTIAL ,
> DWC2_POWER_DOWN_PARAM_HIBERNATION or DWC2_POWER_DOWN_PARAM_NONE while
> checking the hw parameters. So it just indicates which power down mode
> is supporting the core.

I don't think this is what the params are about.  The params are about
the currently configured parameters, not about what the core supports.
This is why all the other code checks the actual value of the params
to decide whether to do power savings.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-04-30 15:23 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-04-30 15:23 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Tue, Apr 30, 2019 at 5:45 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> > If setting "power_down = 0" is wrong then please update your patch to
> > remove all the mainline code that sets power_down to 0.  Presumably
> > this means you'd want to convert that code over to using "power_saving
> > = False".  Perhaps then I can see your vision of how this works more
> > clearly.
> Yes this is a good idea.

Actually, I have a feeling it won't work, at least not without more
changes.  ...and that's part of the problem with your patch.

Specifically dwc2 works by first filling in the "default" parameters.
Then the per-platform config function runs and overrides the defaults.
If the per-platform config function overrides the "power_saving"
parameter then it will be too late.


> > NOTE: I'm curious how you envision what someone would do if they had a
> > core that supported hibernation but they only wanted to enable partial
> > power down.  I guess then they'd have to set "power_saving = True" and
> > then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
> > vision of the world is:
> I have implemented everything based on programming guide and data book.
> Core can only support hibernation or partial power down based on the
> configuration parameters. There cannot be two modes simultaneously of
> power saving only one of them.

Ah, this is new information to me.  I assumed they were supersets of
each other, so if you supported hibernation you also supported partial
power down.  Thanks for clearing that up!


> The power_down flag is set to DWC2_POWER_DOWN_PARAM_PARTIAL ,
> DWC2_POWER_DOWN_PARAM_HIBERNATION or DWC2_POWER_DOWN_PARAM_NONE while
> checking the hw parameters. So it just indicates which power down mode
> is supporting the core.

I don't think this is what the params are about.  The params are about
the currently configured parameters, not about what the core supports.
This is why all the other code checks the actual value of the params
to decide whether to do power savings.

-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-05-01  1:54 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-05-01  1:54 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Tue, Apr 30, 2019 at 12:11 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/29/2019 21:35, Doug Anderson wrote:
> > Hi,
> >
> > On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> Hi,
> >>
> >> On 4/27/2019 00:45, Doug Anderson wrote:
> >>> Hi,
> >>>
> >>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> >>> <Arthur.Petrosyan@synopsys.com> wrote:
> >>>>
> >>>> - In dwc2_port_suspend() function added waiting for the
> >>>>     HPRT0.PrtSusp register field to be set.
> >>>>
> >>>> - In _dwc2_hcd_suspend() function added checking of
> >>>>     "hsotg->flags.b.port_connect_status" port connection
> >>>>     status if port connection status is 0 then skipping
> >>>>     power saving (entering partial power down mode).
> >>>>     Because if there is no device connected there would
> >>>>     be no need to enter partial power down mode.
> >>>>
> >>>> - Added "hsotg->bus_suspended = true" beceuse after
> >>>
> >>> s/beceuse/because
> >>>
> >>>>     entering partial power down in host mode the
> >>>>     bus_suspended flag must be set.
> >>>
> >>> The above statement sounds to me like trying to win an argument by
> >>> saying "I'm right because I'm right."  Can you give more details about
> >>> why "bus_suspended" must be set?  See below also.
> >>>
> >> There is no intention of winning any argument.
> >
> > I was trying to say that your statement does not convey any
> > information about the "why".  It just says: "I now set this variable
> > because it needs to be set".  This tells me nothing useful because
> > presumably if it did't need to be set then you wouldn't have set it.
> > I want to know more information about how the code was broken before
> > you did this.  What specifically requires this variable to be set?
> Specifically that variable is set when core enters to hibernation or
> partial power down.
> >
> >
> >> Are you familiar with "bus_suspended" flag ? have you looked at what is
> >> it used for ?
> >>
> >>    * @bus_suspended:     True if bus is suspended
> >>
> >> So when entering to hibernation is performed bus is suspended. To
> >> indicate that "hsotg->bus_suspended" is assigned to true.
> >
> > Perhaps you can help me understand what the difference is between
> > "port suspend" and "bus suspend" on dwc2.  I think this is where my
> > confusion lies since there are functions for both and they do subtly
> > different things.  ...but both functions set bus_suspended.
> dwc2_port_suspend() is a function which is called when set port feature
> "USB_PORT_FEAT_SUSPEND" is asserted. Yet, bus_suspended is a variable.
> That variable should be set any time that host enters to hibernation or
> partial power down.
>
> >
> >
> >>>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
> >>>>                   goto skip_power_saving;
> >>>>           }
> >>>>
> >>>> +       hsotg->bus_suspended = true;
> >>>> +
> >>>
> >>> I'm a bit unsure about this.  Specifically I note that
> >>> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
> >>> Does that now become dead code?
> >> No it doesn't became a dead code.
> >
> > Can you explain when it gets triggered, then?
> _dwc2_hcd_resume() is triggered by the system.
> As an example lets assume you have hibernated the PC and then you turn
> the PC on. When you turn the PC back on in that case _dwc2_hcd_resume()
> function is called to resume from suspended state (Hibernation/partial
> power down)

I think you are still not understanding my question here.  Please
re-read it again.


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-05-01  1:54 ` Doug Anderson
  0 siblings, 0 replies; 84+ messages in thread
From: Doug Anderson @ 2019-05-01  1:54 UTC (permalink / raw)
  To: Artur Petrosyan
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

Hi,

On Tue, Apr 30, 2019 at 12:11 AM Artur Petrosyan
<Arthur.Petrosyan@synopsys.com> wrote:
>
> Hi,
>
> On 4/29/2019 21:35, Doug Anderson wrote:
> > Hi,
> >
> > On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
> > <Arthur.Petrosyan@synopsys.com> wrote:
> >>
> >> Hi,
> >>
> >> On 4/27/2019 00:45, Doug Anderson wrote:
> >>> Hi,
> >>>
> >>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
> >>> <Arthur.Petrosyan@synopsys.com> wrote:
> >>>>
> >>>> - In dwc2_port_suspend() function added waiting for the
> >>>>     HPRT0.PrtSusp register field to be set.
> >>>>
> >>>> - In _dwc2_hcd_suspend() function added checking of
> >>>>     "hsotg->flags.b.port_connect_status" port connection
> >>>>     status if port connection status is 0 then skipping
> >>>>     power saving (entering partial power down mode).
> >>>>     Because if there is no device connected there would
> >>>>     be no need to enter partial power down mode.
> >>>>
> >>>> - Added "hsotg->bus_suspended = true" beceuse after
> >>>
> >>> s/beceuse/because
> >>>
> >>>>     entering partial power down in host mode the
> >>>>     bus_suspended flag must be set.
> >>>
> >>> The above statement sounds to me like trying to win an argument by
> >>> saying "I'm right because I'm right."  Can you give more details about
> >>> why "bus_suspended" must be set?  See below also.
> >>>
> >> There is no intention of winning any argument.
> >
> > I was trying to say that your statement does not convey any
> > information about the "why".  It just says: "I now set this variable
> > because it needs to be set".  This tells me nothing useful because
> > presumably if it did't need to be set then you wouldn't have set it.
> > I want to know more information about how the code was broken before
> > you did this.  What specifically requires this variable to be set?
> Specifically that variable is set when core enters to hibernation or
> partial power down.
> >
> >
> >> Are you familiar with "bus_suspended" flag ? have you looked at what is
> >> it used for ?
> >>
> >>    * @bus_suspended:     True if bus is suspended
> >>
> >> So when entering to hibernation is performed bus is suspended. To
> >> indicate that "hsotg->bus_suspended" is assigned to true.
> >
> > Perhaps you can help me understand what the difference is between
> > "port suspend" and "bus suspend" on dwc2.  I think this is where my
> > confusion lies since there are functions for both and they do subtly
> > different things.  ...but both functions set bus_suspended.
> dwc2_port_suspend() is a function which is called when set port feature
> "USB_PORT_FEAT_SUSPEND" is asserted. Yet, bus_suspended is a variable.
> That variable should be set any time that host enters to hibernation or
> partial power down.
>
> >
> >
> >>>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
> >>>>                   goto skip_power_saving;
> >>>>           }
> >>>>
> >>>> +       hsotg->bus_suspended = true;
> >>>> +
> >>>
> >>> I'm a bit unsure about this.  Specifically I note that
> >>> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
> >>> Does that now become dead code?
> >> No it doesn't became a dead code.
> >
> > Can you explain when it gets triggered, then?
> _dwc2_hcd_resume() is triggered by the system.
> As an example lets assume you have hibernated the PC and then you turn
> the PC on. When you turn the PC back on in that case _dwc2_hcd_resume()
> function is called to resume from suspended state (Hibernation/partial
> power down)

I think you are still not understanding my question here.  Please
re-read it again.


-Doug

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-05-03  7:58 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-05-03  7:58 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 4/30/2019 19:23, Doug Anderson wrote:
> Hi,
> 
> On Tue, Apr 30, 2019 at 5:45 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>>> If setting "power_down = 0" is wrong then please update your patch to
>>> remove all the mainline code that sets power_down to 0.  Presumably
>>> this means you'd want to convert that code over to using "power_saving
>>> = False".  Perhaps then I can see your vision of how this works more
>>> clearly.
>> Yes this is a good idea.
> 
> Actually, I have a feeling it won't work, at least not without more
> changes.  ...and that's part of the problem with your patch.
I have lot of testes which prove that the patch is working. If there is 
any case that the patch is not working please mention. If possible 
provide the logs of the failure.
> 
> Specifically dwc2 works by first filling in the "default" parameters.
> Then the per-platform config function runs and overrides the defaults.
> If the per-platform config function overrides the "power_saving"
> parameter then it will be too late.
> 
> 
>>> NOTE: I'm curious how you envision what someone would do if they had a
>>> core that supported hibernation but they only wanted to enable partial
>>> power down.  I guess then they'd have to set "power_saving = True" and
>>> then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
>>> vision of the world is:
>> I have implemented everything based on programming guide and data book.
>> Core can only support hibernation or partial power down based on the
>> configuration parameters. There cannot be two modes simultaneously of
>> power saving only one of them.
> 
> Ah, this is new information to me.  I assumed they were supersets of
> each other, so if you supported hibernation you also supported partial
> power down.  Thanks for clearing that up!
Welcome. All of that information is listed in the data book.
> 
> 
>> The power_down flag is set to DWC2_POWER_DOWN_PARAM_PARTIAL ,
>> DWC2_POWER_DOWN_PARAM_HIBERNATION or DWC2_POWER_DOWN_PARAM_NONE while
>> checking the hw parameters. So it just indicates which power down mode
>> is supporting the core.
> 
> I don't think this is what the params are about.  The params are about
> the currently configured parameters, not about what the core supports.
> This is why all the other code checks the actual value of the params
> to decide whether to do power savings.
So for the power saving which should be currently configured parameter I 
have added power_saving flag.

> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 08/14] usb: dwc2: Add default param to control power optimization.
@ 2019-05-03  7:58 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-05-03  7:58 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 4/30/2019 19:23, Doug Anderson wrote:
> Hi,
> 
> On Tue, Apr 30, 2019 at 5:45 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>>> If setting "power_down = 0" is wrong then please update your patch to
>>> remove all the mainline code that sets power_down to 0.  Presumably
>>> this means you'd want to convert that code over to using "power_saving
>>> = False".  Perhaps then I can see your vision of how this works more
>>> clearly.
>> Yes this is a good idea.
> 
> Actually, I have a feeling it won't work, at least not without more
> changes.  ...and that's part of the problem with your patch.
I have lot of testes which prove that the patch is working. If there is 
any case that the patch is not working please mention. If possible 
provide the logs of the failure.
> 
> Specifically dwc2 works by first filling in the "default" parameters.
> Then the per-platform config function runs and overrides the defaults.
> If the per-platform config function overrides the "power_saving"
> parameter then it will be too late.
> 
> 
>>> NOTE: I'm curious how you envision what someone would do if they had a
>>> core that supported hibernation but they only wanted to enable partial
>>> power down.  I guess then they'd have to set "power_saving = True" and
>>> then "power_down = DWC2_POWER_DOWN_PARAM_PARTIAL"?  I guess your
>>> vision of the world is:
>> I have implemented everything based on programming guide and data book.
>> Core can only support hibernation or partial power down based on the
>> configuration parameters. There cannot be two modes simultaneously of
>> power saving only one of them.
> 
> Ah, this is new information to me.  I assumed they were supersets of
> each other, so if you supported hibernation you also supported partial
> power down.  Thanks for clearing that up!
Welcome. All of that information is listed in the data book.
> 
> 
>> The power_down flag is set to DWC2_POWER_DOWN_PARAM_PARTIAL ,
>> DWC2_POWER_DOWN_PARAM_HIBERNATION or DWC2_POWER_DOWN_PARAM_NONE while
>> checking the hw parameters. So it just indicates which power down mode
>> is supporting the core.
> 
> I don't think this is what the params are about.  The params are about
> the currently configured parameters, not about what the core supports.
> This is why all the other code checks the actual value of the params
> to decide whether to do power savings.
So for the power saving which should be currently configured parameter I 
have added power_saving flag.

> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

* [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-05-03  8:13 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-05-03  8:13 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 5/1/2019 05:55, Doug Anderson wrote:
> Hi,
> 
> On Tue, Apr 30, 2019 at 12:11 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/29/2019 21:35, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> On 4/27/2019 00:45, Doug Anderson wrote:
>>>>> Hi,
>>>>>
>>>>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
>>>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>>>
>>>>>> - In dwc2_port_suspend() function added waiting for the
>>>>>>      HPRT0.PrtSusp register field to be set.
>>>>>>
>>>>>> - In _dwc2_hcd_suspend() function added checking of
>>>>>>      "hsotg->flags.b.port_connect_status" port connection
>>>>>>      status if port connection status is 0 then skipping
>>>>>>      power saving (entering partial power down mode).
>>>>>>      Because if there is no device connected there would
>>>>>>      be no need to enter partial power down mode.
>>>>>>
>>>>>> - Added "hsotg->bus_suspended = true" beceuse after
>>>>>
>>>>> s/beceuse/because
>>>>>
>>>>>>      entering partial power down in host mode the
>>>>>>      bus_suspended flag must be set.
>>>>>
>>>>> The above statement sounds to me like trying to win an argument by
>>>>> saying "I'm right because I'm right."  Can you give more details about
>>>>> why "bus_suspended" must be set?  See below also.
>>>>>
>>>> There is no intention of winning any argument.
>>>
>>> I was trying to say that your statement does not convey any
>>> information about the "why".  It just says: "I now set this variable
>>> because it needs to be set".  This tells me nothing useful because
>>> presumably if it did't need to be set then you wouldn't have set it.
>>> I want to know more information about how the code was broken before
>>> you did this.  What specifically requires this variable to be set?
>> Specifically that variable is set when core enters to hibernation or
>> partial power down.
>>>
>>>
>>>> Are you familiar with "bus_suspended" flag ? have you looked at what is
>>>> it used for ?
>>>>
>>>>     * @bus_suspended:     True if bus is suspended
>>>>
>>>> So when entering to hibernation is performed bus is suspended. To
>>>> indicate that "hsotg->bus_suspended" is assigned to true.
>>>
>>> Perhaps you can help me understand what the difference is between
>>> "port suspend" and "bus suspend" on dwc2.  I think this is where my
>>> confusion lies since there are functions for both and they do subtly
>>> different things.  ...but both functions set bus_suspended.
>> dwc2_port_suspend() is a function which is called when set port feature
>> "USB_PORT_FEAT_SUSPEND" is asserted. Yet, bus_suspended is a variable.
>> That variable should be set any time that host enters to hibernation or
>> partial power down.
>>
>>>
>>>
>>>>>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>>>>>                    goto skip_power_saving;
>>>>>>            }
>>>>>>
>>>>>> +       hsotg->bus_suspended = true;
>>>>>> +
>>>>>
>>>>> I'm a bit unsure about this.  Specifically I note that
>>>>> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
>>>>> Does that now become dead code?
>>>> No it doesn't became a dead code.
>>>
>>> Can you explain when it gets triggered, then?
>> _dwc2_hcd_resume() is triggered by the system.
>> As an example lets assume you have hibernated the PC and then you turn
>> the PC on. When you turn the PC back on in that case _dwc2_hcd_resume()
>> function is called to resume from suspended state (Hibernation/partial
>> power down)
> 
> I think you are still not understanding my question here.  Please
> re-read it again.
Your question is "Can you explain when it gets triggered, then?" so I 
have explained one case when it is triggered.
> 
> 
> -Doug
>

^ permalink raw reply	[flat|nested] 84+ messages in thread

* Re: [PATCH v1 04/14] usb: dwc2: Fix suspend state in host mode for partial power down.
@ 2019-05-03  8:13 ` Artur Petrosyan
  0 siblings, 0 replies; 84+ messages in thread
From: Artur Petrosyan @ 2019-05-03  8:13 UTC (permalink / raw)
  To: Doug Anderson
  Cc: Felipe Balbi, Greg Kroah-Hartman, Minas Harutyunyan, linux-usb,
	John Youn

On 5/1/2019 05:55, Doug Anderson wrote:
> Hi,
> 
> On Tue, Apr 30, 2019 at 12:11 AM Artur Petrosyan
> <Arthur.Petrosyan@synopsys.com> wrote:
>>
>> Hi,
>>
>> On 4/29/2019 21:35, Doug Anderson wrote:
>>> Hi,
>>>
>>> On Mon, Apr 29, 2019 at 4:03 AM Artur Petrosyan
>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>
>>>> Hi,
>>>>
>>>> On 4/27/2019 00:45, Doug Anderson wrote:
>>>>> Hi,
>>>>>
>>>>> On Fri, Apr 19, 2019 at 1:05 PM Artur Petrosyan
>>>>> <Arthur.Petrosyan@synopsys.com> wrote:
>>>>>>
>>>>>> - In dwc2_port_suspend() function added waiting for the
>>>>>>      HPRT0.PrtSusp register field to be set.
>>>>>>
>>>>>> - In _dwc2_hcd_suspend() function added checking of
>>>>>>      "hsotg->flags.b.port_connect_status" port connection
>>>>>>      status if port connection status is 0 then skipping
>>>>>>      power saving (entering partial power down mode).
>>>>>>      Because if there is no device connected there would
>>>>>>      be no need to enter partial power down mode.
>>>>>>
>>>>>> - Added "hsotg->bus_suspended = true" beceuse after
>>>>>
>>>>> s/beceuse/because
>>>>>
>>>>>>      entering partial power down in host mode the
>>>>>>      bus_suspended flag must be set.
>>>>>
>>>>> The above statement sounds to me like trying to win an argument by
>>>>> saying "I'm right because I'm right."  Can you give more details about
>>>>> why "bus_suspended" must be set?  See below also.
>>>>>
>>>> There is no intention of winning any argument.
>>>
>>> I was trying to say that your statement does not convey any
>>> information about the "why".  It just says: "I now set this variable
>>> because it needs to be set".  This tells me nothing useful because
>>> presumably if it did't need to be set then you wouldn't have set it.
>>> I want to know more information about how the code was broken before
>>> you did this.  What specifically requires this variable to be set?
>> Specifically that variable is set when core enters to hibernation or
>> partial power down.
>>>
>>>
>>>> Are you familiar with "bus_suspended" flag ? have you looked at what is
>>>> it used for ?
>>>>
>>>>     * @bus_suspended:     True if bus is suspended
>>>>
>>>> So when entering to hibernation is performed bus is suspended. To
>>>> indicate that "hsotg->bus_suspended" is assigned to true.
>>>
>>> Perhaps you can help me understand what the difference is between
>>> "port suspend" and "bus suspend" on dwc2.  I think this is where my
>>> confusion lies since there are functions for both and they do subtly
>>> different things.  ...but both functions set bus_suspended.
>> dwc2_port_suspend() is a function which is called when set port feature
>> "USB_PORT_FEAT_SUSPEND" is asserted. Yet, bus_suspended is a variable.
>> That variable should be set any time that host enters to hibernation or
>> partial power down.
>>
>>>
>>>
>>>>>> @@ -4514,6 +4519,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
>>>>>>                    goto skip_power_saving;
>>>>>>            }
>>>>>>
>>>>>> +       hsotg->bus_suspended = true;
>>>>>> +
>>>>>
>>>>> I'm a bit unsure about this.  Specifically I note that
>>>>> _dwc2_hcd_resume() has a special case "if (hsotg->bus_suspended)".
>>>>> Does that now become dead code?
>>>> No it doesn't became a dead code.
>>>
>>> Can you explain when it gets triggered, then?
>> _dwc2_hcd_resume() is triggered by the system.
>> As an example lets assume you have hibernated the PC and then you turn
>> the PC on. When you turn the PC back on in that case _dwc2_hcd_resume()
>> function is called to resume from suspended state (Hibernation/partial
>> power down)
> 
> I think you are still not understanding my question here.  Please
> re-read it again.
Your question is "Can you explain when it gets triggered, then?" so I 
have explained one case when it is triggered.
> 
> 
> -Doug
> 


-- 
Regards,
Artur

^ permalink raw reply	[flat|nested] 84+ messages in thread

end of thread, other threads:[~2019-05-03  8:13 UTC | newest]

Thread overview: 84+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-04-19 11:24 [v1,09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function Artur Petrosyan
2019-04-19 11:24 ` [PATCH v1 09/14] " Artur Petrosyan
  -- strict thread matches above, loose matches on Subject: below --
2019-05-03  8:13 [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down Artur Petrosyan
2019-05-03  8:13 ` [PATCH v1 04/14] " Artur Petrosyan
2019-05-03  7:58 [v1,08/14] usb: dwc2: Add default param to control power optimization Artur Petrosyan
2019-05-03  7:58 ` [PATCH v1 08/14] " Artur Petrosyan
2019-05-01  1:54 [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down Doug Anderson
2019-05-01  1:54 ` [PATCH v1 04/14] " Doug Anderson
2019-04-30 15:23 [v1,08/14] usb: dwc2: Add default param to control power optimization Doug Anderson
2019-04-30 15:23 ` [PATCH v1 08/14] " Doug Anderson
2019-04-30 13:06 [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume Artur Petrosyan
2019-04-30 13:06 ` [PATCH v1 14/14] " Artur Petrosyan
2019-04-30 12:45 [v1,08/14] usb: dwc2: Add default param to control power optimization Artur Petrosyan
2019-04-30 12:45 ` [PATCH v1 08/14] " Artur Petrosyan
2019-04-30  7:10 [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down Artur Petrosyan
2019-04-30  7:10 ` [PATCH v1 04/14] " Artur Petrosyan
2019-04-29 17:42 [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume Doug Anderson
2019-04-29 17:42 ` [PATCH v1 14/14] " Doug Anderson
2019-04-29 17:40 [v1,08/14] usb: dwc2: Add default param to control power optimization Doug Anderson
2019-04-29 17:40 ` [PATCH v1 08/14] " Doug Anderson
2019-04-29 17:35 [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down Doug Anderson
2019-04-29 17:35 ` [PATCH v1 04/14] " Doug Anderson
2019-04-29 12:01 [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume Artur Petrosyan
2019-04-29 12:01 ` [PATCH v1 14/14] " Artur Petrosyan
2019-04-29 11:35 [v1,09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function Artur Petrosyan
2019-04-29 11:35 ` [PATCH v1 09/14] " Artur Petrosyan
2019-04-29 11:29 [v1,08/14] usb: dwc2: Add default param to control power optimization Artur Petrosyan
2019-04-29 11:29 ` [PATCH v1 08/14] " Artur Petrosyan
2019-04-29 11:03 [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down Artur Petrosyan
2019-04-29 11:03 ` [PATCH v1 04/14] " Artur Petrosyan
2019-04-29 10:54 [v1,03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers Artur Petrosyan
2019-04-29 10:54 ` [PATCH v1 03/14] " Artur Petrosyan
2019-04-26 21:00 [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume Doug Anderson
2019-04-26 21:00 ` [PATCH v1 14/14] " Doug Anderson
2019-04-26 20:51 [v1,12/14] usb: dwc2: Clear fifo_map when resetting core Doug Anderson
2019-04-26 20:51 ` [PATCH v1 12/14] " Doug Anderson
2019-04-26 20:51 [v1,09/14] usb: dwc2: Update dwc2_handle_usb_suspend_intr function Doug Anderson
2019-04-26 20:51 ` [PATCH v1 09/14] " Doug Anderson
2019-04-26 20:46 [v1,08/14] usb: dwc2: Add default param to control power optimization Doug Anderson
2019-04-26 20:46 ` [PATCH v1 08/14] " Doug Anderson
2019-04-26 20:45 [v1,06/14] usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change() Doug Anderson
2019-04-26 20:45 ` [PATCH v1 06/14] " Doug Anderson
2019-04-26 20:45 [v1,05/14] usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function Doug Anderson
2019-04-26 20:45 ` [PATCH v1 05/14] " Doug Anderson
2019-04-26 20:44 [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down Doug Anderson
2019-04-26 20:44 ` [PATCH v1 04/14] " Doug Anderson
2019-04-26 20:44 [v1,03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers Doug Anderson
2019-04-26 20:44 ` [PATCH v1 03/14] " Doug Anderson
2019-04-19 11:25 [v1,14/14] usb: dwc2: Add enter/exit hibernation from system issued suspend/resume Artur Petrosyan
2019-04-19 11:25 ` [PATCH v1 14/14] " Artur Petrosyan
2019-04-19 11:25 [v1,13/14] usb: dwc2: Clear GINTSTS_RESTOREDONE bit after restore is generated Artur Petrosyan
2019-04-19 11:25 ` [PATCH v1 13/14] " Artur Petrosyan
2019-04-19 11:25 [v1,12/14] usb: dwc2: Clear fifo_map when resetting core Artur Petrosyan
2019-04-19 11:25 ` [PATCH v1 12/14] " Artur Petrosyan
2019-04-19 11:25 [v1,11/14] usb: dwc2: Allow exiting hibernation from gpwrdn rst detect Artur Petrosyan
2019-04-19 11:25 ` [PATCH v1 11/14] " Artur Petrosyan
2019-04-19 11:25 [v1,10/14] usb: dwc2: Fix hibernation between host and device modes Artur Petrosyan
2019-04-19 11:25 ` [PATCH v1 10/14] " Artur Petrosyan
2019-04-19 11:24 [v1,08/14] usb: dwc2: Add default param to control power optimization Artur Petrosyan
2019-04-19 11:24 ` [PATCH v1 08/14] " Artur Petrosyan
2019-04-19 11:24 [v1,07/14] usb: dwc2: Reset DEVADDR after exiting gadget hibernation Artur Petrosyan
2019-04-19 11:24 ` [PATCH v1 07/14] " Artur Petrosyan
2019-04-19 11:24 [v1,06/14] usb: dwc2: Add part. power down exit from dwc2_conn_id_status_change() Artur Petrosyan
2019-04-19 11:24 ` [PATCH v1 06/14] " Artur Petrosyan
2019-04-19 11:24 [v1,05/14] usb: dwc2: Add port conn. sts. checking in _dwc2_hcd_resume() function Artur Petrosyan
2019-04-19 11:24 ` [PATCH v1 05/14] " Artur Petrosyan
2019-04-19 11:24 [v1,04/14] usb: dwc2: Fix suspend state in host mode for partial power down Artur Petrosyan
2019-04-19 11:24 ` [PATCH v1 04/14] " Artur Petrosyan
2019-04-19 11:23 [v1,03/14] usb: dwc2: Fix wakeup detected and session request interrupt handlers Artur Petrosyan
2019-04-19 11:23 ` [PATCH v1 03/14] " Artur Petrosyan
2019-04-19 11:23 [v1,02/14] usb: dwc2: Add descriptive debug messages for Partial Power Down mode Artur Petrosyan
2019-04-19 11:23 ` [PATCH v1 02/14] " Artur Petrosyan
2019-04-19 11:23 [v1,01/14] usb: dwc2: Fix dwc2_restore_device_registers() function Artur Petrosyan
2019-04-19 11:23 ` [PATCH v1 01/14] " Artur Petrosyan
2019-04-19 11:23 [PATCH v1 00/14] usb: dwc2: Fix and improve power saving modes Artur Petrosyan
2019-04-25 12:43 ` Felipe Balbi
2019-04-25 14:00   ` Artur Petrosyan
2019-04-25 20:12     ` Doug Anderson
2019-04-26  7:10       ` Artur Petrosyan
2019-04-26 16:01         ` Doug Anderson
2019-04-26 21:06           ` Doug Anderson
2019-04-29 12:05             ` Artur Petrosyan
2019-04-29 17:43               ` Doug Anderson
2019-04-29  8:44           ` Artur Petrosyan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.