linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC][PATCH 0/5] Fixes and workarounds for dwc2 on HiKey board
@ 2016-12-13  7:09 John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 1/5] usb: dwc2: Avoid sleeping while holding hsotg->lock John Stultz
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: John Stultz @ 2016-12-13  7:09 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring,
	John Youn, Douglas Anderson, Chen Yu, Kishon Vijay Abraham I,
	Felipe Balbi, Greg Kroah-Hartman, linux-usb

I just wanted to send out my current queue of patches for dwc2
controller on the HiKey board.

This does exclude my patchset[1] to add extcon support to dwc2,
which John Youn suspects a pending rework of the dwc2 fifo init
logic might make unnecssary.

So in the meantime, I wanted to send out the other patches I
have to use, so that they can get feedback and be consdiered
for the next (4.11) merge window.

Feedback would be greatly appreciated!

thanks
-john

[1] https://lkml.org/lkml/2016/12/6/69

Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Guodong Xu <guodong.xu@linaro.org>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: John Youn <johnyoun@synopsys.com>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Chen Yu <chenyu56@huawei.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org

Chen Yu (2):
  usb: dwc2: Force port resume on switching to device mode
  usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220

John Stultz (3):
  usb: dwc2: Avoid sleeping while holding hsotg->lock
  usb: dwc2: Workaround case where GOTGCTL state is wrong
  usb: dwc2: Avoid suspending if we're in gadget mode

 drivers/usb/dwc2/core.c     |  6 ++--
 drivers/usb/dwc2/core.h     |  8 ++++-
 drivers/usb/dwc2/gadget.c   |  2 +-
 drivers/usb/dwc2/hcd.c      | 75 ++++++++++++++++++++++++++++++++++++++++++++-
 drivers/usb/dwc2/platform.c |  1 +
 5 files changed, 86 insertions(+), 6 deletions(-)

-- 
2.7.4

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

* [RFC][PATCH 1/5] usb: dwc2: Avoid sleeping while holding hsotg->lock
  2016-12-13  7:09 [RFC][PATCH 0/5] Fixes and workarounds for dwc2 on HiKey board John Stultz
@ 2016-12-13  7:09 ` John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong John Stultz
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: John Stultz @ 2016-12-13  7:09 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring,
	John Youn, Douglas Anderson, Chen Yu, Kishon Vijay Abraham I,
	Felipe Balbi, Greg Kroah-Hartman, linux-usb

Basically when plugging in various cables in different orders, I'm
occasionally seeing the following BUG splat:

[   86.215403] BUG: scheduling while atomic: kworker/u16:2/53/0x00000002
[   86.219164] usb 1-1: USB disconnect, device number 9
[   86.226845] Preemption disabled at:[   86.230218]
[<ffffff8008673558>] dwc2_conn_id_status_change+0x120/0x250
[   86.236894] CPU: 0 PID: 53 Comm: kworker/u16:2 Tainted: G        W
     4.9.0-rc8-00051-gd5a7979-dirty #1702
[   86.246836] Hardware name: HiKey Development Board (DT)
[   86.252100] Workqueue: dwc2 dwc2_conn_id_status_change
[   86.257279] Call trace:
[   86.259771] [<ffffff8008087c28>] dump_backtrace+0x0/0x1a0
[   86.265210] [<ffffff8008087ddc>] show_stack+0x14/0x20
[   86.270308] [<ffffff80084343f0>] dump_stack+0x90/0xb0
[   86.275401] [<ffffff80080d8d94>] __schedule_bug+0x6c/0xb8
[   86.280841] [<ffffff8008a07220>] __schedule+0x4f8/0x5b0
[   86.286099] [<ffffff8008a073e8>] schedule+0x38/0xa0
[   86.291017] [<ffffff8008a0a6cc>] schedule_hrtimeout_range_clock+0x8c/0xf0
[   86.297846] [<ffffff8008a0a740>] schedule_hrtimeout_range+0x10/0x18
[   86.304150] [<ffffff8008a0a4a0>] usleep_range+0x50/0x58
[   86.309418] [<ffffff800866d8dc>] dwc2_wait_for_mode.isra.4+0x54/0xd0
[   86.315815] [<ffffff800866f058>] dwc2_core_reset+0xe0/0x168
[   86.321431] [<ffffff800867e364>] dwc2_hsotg_core_init_disconnected+0x2c/0x310
[   86.328602] [<ffffff8008673568>] dwc2_conn_id_status_change+0x130/0x250
[   86.335254] [<ffffff80080ccd48>] process_one_work+0x118/0x370
[   86.341035] [<ffffff80080ccfe8>] worker_thread+0x48/0x498
[   86.346473] [<ffffff80080d2eb0>] kthread+0xd0/0xe8
[   86.351299] [<ffffff8008082e80>] ret_from_fork+0x10/0x50

This seems to be caused by the dwc2_wait_for_mode() calling
usleep_range() while the hstog->lock spinlock is held, since
we take that before calling dwc2_hsotg_core_init_disconnected().

This patch avoids the issue by adding an extra argument to
dwc2_core_reset(), as suggested by John Youn, which allows us to
skip the waiting, which should be unnecessary when calling from
dwc2_hsotg_core_init_disconnected().

Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Guodong Xu <guodong.xu@linaro.org>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: John Youn <johnyoun@synopsys.com>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Chen Yu <chenyu56@huawei.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/usb/dwc2/core.c   | 6 +++---
 drivers/usb/dwc2/core.h   | 2 +-
 drivers/usb/dwc2/gadget.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 4c0fa0b..2e83545 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -313,7 +313,7 @@ static bool dwc2_iddig_filter_enabled(struct dwc2_hsotg *hsotg)
  * Do core a soft reset of the core.  Be careful with this because it
  * resets all the internal state machines of the core.
  */
-int dwc2_core_reset(struct dwc2_hsotg *hsotg)
+int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait)
 {
 	u32 greset;
 	int count = 0;
@@ -369,7 +369,7 @@ int dwc2_core_reset(struct dwc2_hsotg *hsotg)
 		}
 	} while (!(greset & GRSTCTL_AHBIDLE));
 
-	if (wait_for_host_mode)
+	if (wait_for_host_mode && !skip_wait)
 		dwc2_wait_for_mode(hsotg, true);
 
 	return 0;
@@ -500,7 +500,7 @@ int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg)
 {
 	int retval;
 
-	retval = dwc2_core_reset(hsotg);
+	retval = dwc2_core_reset(hsotg, false);
 	if (retval)
 		return retval;
 
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 2a21a04..963ea1b 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -1020,7 +1020,7 @@ enum dwc2_halt_status {
  * The following functions support initialization of the core driver component
  * and the DWC_otg controller
  */
-extern int dwc2_core_reset(struct dwc2_hsotg *hsotg);
+extern int dwc2_core_reset(struct dwc2_hsotg *hsotg, bool skip_wait);
 extern int dwc2_core_reset_and_force_dr_mode(struct dwc2_hsotg *hsotg);
 extern int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg);
 extern int dwc2_exit_hibernation(struct dwc2_hsotg *hsotg, bool restore);
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 24fbebc..0bda799 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2521,7 +2521,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
 	kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
 
 	if (!is_usb_reset)
-		if (dwc2_core_reset(hsotg))
+		if (dwc2_core_reset(hsotg, true))
 			return;
 
 	/*
-- 
2.7.4

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

* [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong
  2016-12-13  7:09 [RFC][PATCH 0/5] Fixes and workarounds for dwc2 on HiKey board John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 1/5] usb: dwc2: Avoid sleeping while holding hsotg->lock John Stultz
@ 2016-12-13  7:09 ` John Stultz
  2016-12-13 12:28   ` Vardan Mikayelyan
  2016-12-13  7:09 ` [RFC][PATCH 3/5] usb: dwc2: Force port resume on switching to device mode John Stultz
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: John Stultz @ 2016-12-13  7:09 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring,
	John Youn, Douglas Anderson, Chen Yu, Kishon Vijay Abraham I,
	Felipe Balbi, Greg Kroah-Hartman, linux-usb

When removing a USB-A to USB-otg adapter cable, we get a change
status irq, and then in dwc2_conn_id_status_change, we
erroniously see the GOTGCTL_CONID_B flag set. This causes us to
get  stuck in the "while (!dwc2_is_device_mode(hsotg))" loop,
spitting out "Waiting for Peripheral Mode, Mode=Host" warnings
until it fails out many seconds later.

This patch works around the issue by re-reading the GOTGCTL
state to check if the GOTGCTL_CONID_B is still set and if not
restarting the change status logic.

I suspect this isn't the best solution, but it seems to work
well for me.

Feedback would be greatly appreciated!

Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Guodong Xu <guodong.xu@linaro.org>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: John Youn <johnyoun@synopsys.com>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Chen Yu <chenyu56@huawei.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Acked-by: John Youn <johnyoun@synopsys.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/usb/dwc2/hcd.c | 5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index df5a065..a3f34dd 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3199,7 +3199,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 	dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
 	dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
 		!!(gotgctl & GOTGCTL_CONID_B));
-
+again:
 	/* B-Device connector (Device Mode) */
 	if (gotgctl & GOTGCTL_CONID_B) {
 		/* Wait for switch to device mode */
@@ -3210,6 +3210,9 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 				 dwc2_is_host_mode(hsotg) ? "Host" :
 				 "Peripheral");
 			usleep_range(20000, 40000);
+			gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+			if (!(gotgctl & GOTGCTL_CONID_B))
+				goto again;
 			if (++count > 250)
 				break;
 		}
-- 
2.7.4

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

* [RFC][PATCH 3/5] usb: dwc2: Force port resume on switching to device mode
  2016-12-13  7:09 [RFC][PATCH 0/5] Fixes and workarounds for dwc2 on HiKey board John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 1/5] usb: dwc2: Avoid sleeping while holding hsotg->lock John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong John Stultz
@ 2016-12-13  7:09 ` John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 4/5] usb: dwc2: Avoid suspending if we're in gadget mode John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 5/5] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220 John Stultz
  4 siblings, 0 replies; 10+ messages in thread
From: John Stultz @ 2016-12-13  7:09 UTC (permalink / raw)
  To: lkml
  Cc: Chen Yu, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring, John Youn,
	Douglas Anderson, Felipe Balbi, Greg Kroah-Hartman, linux-usb,
	John Stultz

From: Chen Yu <chenyu56@huawei.com>

We've seen failures when switching between host and gadget mode,
which was diagnosed as being caused due to the bus being
auto-suspended when we switched.

So this patch forces a port resume when switching to device
mode if the bus is suspended.

Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Guodong Xu <guodong.xu@linaro.org>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: John Youn <johnyoun@synopsys.com>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Chen Yu <chenyu56@huawei.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Signed-off-by: Chen Yu <chenyu56@huawei.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/usb/dwc2/hcd.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index a3f34dd..24db997 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -54,6 +54,8 @@
 #include "core.h"
 #include "hcd.h"
 
+static void dwc2_port_resume(struct dwc2_hsotg *hsotg);
+
 /*
  * =========================================================================
  *  Host Core Layer Functions
@@ -3204,6 +3206,11 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
 	if (gotgctl & GOTGCTL_CONID_B) {
 		/* Wait for switch to device mode */
 		dev_dbg(hsotg->dev, "connId B\n");
+		if (hsotg->bus_suspended) {
+			dev_info(hsotg->dev,
+				 "Do port resume before switching to device mode\n");
+			dwc2_port_resume(hsotg);
+		}
 		while (!dwc2_is_device_mode(hsotg)) {
 			dev_info(hsotg->dev,
 				 "Waiting for Peripheral Mode, Mode=%s\n",
-- 
2.7.4

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

* [RFC][PATCH 4/5] usb: dwc2: Avoid suspending if we're in gadget mode
  2016-12-13  7:09 [RFC][PATCH 0/5] Fixes and workarounds for dwc2 on HiKey board John Stultz
                   ` (2 preceding siblings ...)
  2016-12-13  7:09 ` [RFC][PATCH 3/5] usb: dwc2: Force port resume on switching to device mode John Stultz
@ 2016-12-13  7:09 ` John Stultz
  2016-12-13  7:09 ` [RFC][PATCH 5/5] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220 John Stultz
  4 siblings, 0 replies; 10+ messages in thread
From: John Stultz @ 2016-12-13  7:09 UTC (permalink / raw)
  To: lkml
  Cc: John Stultz, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring,
	John Youn, Douglas Anderson, Chen Yu, Kishon Vijay Abraham I,
	Felipe Balbi, Greg Kroah-Hartman, linux-usb

I've found when booting HiKey with the usb gadget cable attached
if I then try to connect via adb, I get an infinite spew of:

dwc2 f72c0000.usb: dwc2_hsotg_ep_sethalt(ep ffffffc0790ecb18 ep1out, 0)
dwc2 f72c0000.usb: dwc2_hsotg_ep_sethalt(ep ffffffc0790eca18 ep1in, 0)

It seems that the usb autosuspend is suspending the bus shortly
after bootup when the gadget cable is attached. So when adbd
then tries to use the device, it doesn't work and it then tries
to restart it over and over via the ep_sethalt calls (via
FUNCTIONFS_CLEAR_HALT ioctl).

Chen Yu suggested this patch to avoid suspending if we're
in device mode, and it avoids the problem.

This doesn't remove the need for the previous patch, to resume
the port when we switch to gadget mode from host mode. But it
does seem to resolve the issue.

Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Guodong Xu <guodong.xu@linaro.org>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: John Youn <johnyoun@synopsys.com>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Chen Yu <chenyu56@huawei.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Suggested-by: Chen Yu <chenyu56@huawei.com>
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
 drivers/usb/dwc2/hcd.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 24db997..008f5bc 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4375,6 +4375,9 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 	if (!HCD_HW_ACCESSIBLE(hcd))
 		goto unlock;
 
+	if (hsotg->op_state == OTG_STATE_B_PERIPHERAL)
+		goto unlock;
+
 	if (!hsotg->core_params->hibernation)
 		goto skip_power_saving;
 
-- 
2.7.4

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

* [RFC][PATCH 5/5] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220
  2016-12-13  7:09 [RFC][PATCH 0/5] Fixes and workarounds for dwc2 on HiKey board John Stultz
                   ` (3 preceding siblings ...)
  2016-12-13  7:09 ` [RFC][PATCH 4/5] usb: dwc2: Avoid suspending if we're in gadget mode John Stultz
@ 2016-12-13  7:09 ` John Stultz
  2016-12-13 13:24   ` Alan Stern
  4 siblings, 1 reply; 10+ messages in thread
From: John Stultz @ 2016-12-13  7:09 UTC (permalink / raw)
  To: lkml
  Cc: Chen Yu, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring, John Youn,
	Douglas Anderson, Kishon Vijay Abraham I, Felipe Balbi,
	Greg Kroah-Hartman, linux-usb, John Stultz

From: Chen Yu <chenyu56@huawei.com>

The Hi6220's usb controller is limited in that it does not
support "Split Transactions", so it does not support communicating
with low-speed and full-speed devices behind a high-speed hub.

Thus it requires a quirk so that we can manually drop the usb
speed when low/full-speed are attached, and bump back to high
speed when they are removed.

Cc: Wei Xu <xuwei5@hisilicon.com>
Cc: Guodong Xu <guodong.xu@linaro.org>
Cc: Amit Pundir <amit.pundir@linaro.org>
Cc: Rob Herring <robh+dt@kernel.org>
Cc: John Youn <johnyoun@synopsys.com>
Cc: Douglas Anderson <dianders@chromium.org>
Cc: Chen Yu <chenyu56@huawei.com>
Cc: Kishon Vijay Abraham I <kishon@ti.com>
Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org
Signed-off-by: Chen Yu <chenyu56@huawei.com>
[jstultz: Reworked to simplify the patch, and made
 commit log to be more specific about the issue]
Signed-off-by: John Stultz <john.stultz@linaro.org>
---
v2:
* Fix build issue reported by kbuildbot
* Rework to avoid using new dts entry suggested by RobH
* Further tweaks from Chen Yu to try to address comments from
  John Youn
* Further simplified logic
---
 drivers/usb/dwc2/core.h     |  6 +++++
 drivers/usb/dwc2/hcd.c      | 60 +++++++++++++++++++++++++++++++++++++++++++++
 drivers/usb/dwc2/platform.c |  1 +
 3 files changed, 67 insertions(+)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 963ea1b..de1fa0c 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -417,6 +417,11 @@ enum dwc2_ep0_state {
  *			needed.
  *			0 - No (default)
  *			1 - Yes
+ * @change_speed_quirk: Change speed configuration to DWC2_SPEED_PARAM_FULL
+ *                      while full&low speed device connect. And change speed
+ *                      back to DWC2_SPEED_PARAM_HIGH while device is gone.
+ *			0 - No (default)
+ *			1 - Yes
  *
  * The following parameters may be specified when starting the module. These
  * parameters define how the DWC_otg controller should be configured. A
@@ -457,6 +462,7 @@ struct dwc2_core_params {
 	int uframe_sched;
 	int external_id_pin_ctl;
 	int hibernation;
+	int change_speed_quirk;
 };
 
 /**
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 008f5bc..7cf8d8e 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -4873,6 +4873,61 @@ static void _dwc2_hcd_clear_tt_buffer_complete(struct usb_hcd *hcd,
 	spin_unlock_irqrestore(&hsotg->lock, flags);
 }
 
+/*
+ * HPRT0_SPD_HIGH_SPEED: high speed
+ * HPRT0_SPD_FULL_SPEED: full speed
+ */
+static void dwc2_change_bus_speed(struct usb_hcd *hcd, int speed)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+
+	if (hsotg->core_params->speed == speed)
+		return;
+
+	hsotg->core_params->speed = speed;
+	queue_work(hsotg->wq_otg, &hsotg->wf_otg);
+}
+
+static void dwc2_free_dev(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+
+	if (!hsotg->core_params->change_speed_quirk)
+		return;
+
+	/*
+	 * On removal, set speed to default high-speed.
+	 */
+	if (udev->parent && udev->parent->speed > USB_SPEED_UNKNOWN &&
+	    udev->parent->speed < USB_SPEED_HIGH) {
+		dev_info(hsotg->dev, "Set speed to default high-speed\n");
+		dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED);
+	}
+}
+
+static int dwc2_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
+{
+	struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+
+	if (!hsotg->core_params->change_speed_quirk)
+		return 0;
+
+	if (udev->speed == USB_SPEED_HIGH) {
+		dev_info(hsotg->dev, "Set speed to high-speed\n");
+		dwc2_change_bus_speed(hcd, HPRT0_SPD_HIGH_SPEED);
+	} else if ((udev->speed == USB_SPEED_FULL ||
+				udev->speed == USB_SPEED_LOW)) {
+		/*
+		 * Change speed setting to full-speed if there's
+		 * a full-speed or low-speed device plugged in.
+		 */
+		dev_info(hsotg->dev, "Set speed to full-speed\n");
+		dwc2_change_bus_speed(hcd, HPRT0_SPD_FULL_SPEED);
+	}
+
+	return 0;
+}
+
 static struct hc_driver dwc2_hc_driver = {
 	.description = "dwc2_hsotg",
 	.product_desc = "DWC OTG Controller",
@@ -5028,6 +5083,11 @@ int dwc2_hcd_init(struct dwc2_hsotg *hsotg, int irq)
 			dev_warn(hsotg->dev, "can't set coherent DMA mask\n");
 	}
 
+	if (hsotg->core_params->change_speed_quirk) {
+		dwc2_hc_driver.free_dev = dwc2_free_dev;
+		dwc2_hc_driver.reset_device = dwc2_reset_device;
+	}
+
 	hcd = usb_create_hcd(&dwc2_hc_driver, hsotg->dev, dev_name(hsotg->dev));
 	if (!hcd)
 		goto error1;
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 8e1728b..17eb5fd 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -85,6 +85,7 @@ static const struct dwc2_core_params params_hi6220 = {
 	.uframe_sched			= 0,
 	.external_id_pin_ctl		= -1,
 	.hibernation			= -1,
+	.change_speed_quirk		= 1,
 };
 
 static const struct dwc2_core_params params_bcm2835 = {
-- 
2.7.4

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

* Re: [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong
  2016-12-13  7:09 ` [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong John Stultz
@ 2016-12-13 12:28   ` Vardan Mikayelyan
  2016-12-13 20:40     ` John Stultz
  0 siblings, 1 reply; 10+ messages in thread
From: Vardan Mikayelyan @ 2016-12-13 12:28 UTC (permalink / raw)
  To: John Stultz, lkml
  Cc: Wei Xu, Guodong Xu, Amit Pundir, Rob Herring, John Youn,
	Douglas Anderson, Chen Yu, Kishon Vijay Abraham I, Felipe Balbi,
	Greg Kroah-Hartman, linux-usb

On 12/13/2016 11:12 AM, John Stultz wrote:
> When removing a USB-A to USB-otg adapter cable, we get a change
> status irq, and then in dwc2_conn_id_status_change, we
> erroniously see the GOTGCTL_CONID_B flag set. This causes us to
> get  stuck in the "while (!dwc2_is_device_mode(hsotg))" loop,
> spitting out "Waiting for Peripheral Mode, Mode=Host" warnings
> until it fails out many seconds later.
>
> This patch works around the issue by re-reading the GOTGCTL
> state to check if the GOTGCTL_CONID_B is still set and if not
> restarting the change status logic.
>
> I suspect this isn't the best solution, but it seems to work
> well for me.
>
> Feedback would be greatly appreciated!
>
> Cc: Wei Xu <xuwei5@hisilicon.com>
> Cc: Guodong Xu <guodong.xu@linaro.org>
> Cc: Amit Pundir <amit.pundir@linaro.org>
> Cc: Rob Herring <robh+dt@kernel.org>
> Cc: John Youn <johnyoun@synopsys.com>
> Cc: Douglas Anderson <dianders@chromium.org>
> Cc: Chen Yu <chenyu56@huawei.com>
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
> Cc: linux-usb@vger.kernel.org
> Acked-by: John Youn <johnyoun@synopsys.com>
> Signed-off-by: John Stultz <john.stultz@linaro.org>
> ---
>  drivers/usb/dwc2/hcd.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
> index df5a065..a3f34dd 100644
> --- a/drivers/usb/dwc2/hcd.c
> +++ b/drivers/usb/dwc2/hcd.c
> @@ -3199,7 +3199,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>  	dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
>  	dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
>  		!!(gotgctl & GOTGCTL_CONID_B));
> -
> +again:
>  	/* B-Device connector (Device Mode) */
>  	if (gotgctl & GOTGCTL_CONID_B) {
>  		/* Wait for switch to device mode */
> @@ -3210,6 +3210,9 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>  				 dwc2_is_host_mode(hsotg) ? "Host" :
>  				 "Peripheral");
>  			usleep_range(20000, 40000);
> +			gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
> +			if (!(gotgctl & GOTGCTL_CONID_B))
> +				goto again;
>  			if (++count > 250)
>  				break;
>  		}
>
Hi John Stultz,

When it goes to ":again", it will go to else anyways. I'll suggest 
alternative way to do this. Please see below.

Also you can add "Reviewed-by: Vardan Mikayelyan <mvardan@synopsys.com>"

Thanks,
Vardan.

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index b7311a6..128311b 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3242,6 +3242,9 @@ static void dwc2_conn_id_status_change(struct 
work_struct *work)
                                  dwc2_is_host_mode(hsotg) ? "Host" :
                                  "Peripheral");
                         usleep_range(20000, 40000);
+                       gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
+                       if (!(gotgctl & GOTGCTL_CONID_B))
+                               goto host;
                         if (++count > 250)
                                 break;
                 }
@@ -3256,6 +3259,7 @@ static void dwc2_conn_id_status_change(struct 
work_struct *work)
                 spin_unlock_irqrestore(&hsotg->lock, flags);
                 dwc2_hsotg_core_connect(hsotg);
         } else {
+host:
                 /* A-Device connector (Host Mode) */
                 dev_dbg(hsotg->dev, "connId A\n");
                 while (!dwc2_is_host_mode(hsotg)) {

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

* Re: [RFC][PATCH 5/5] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220
  2016-12-13  7:09 ` [RFC][PATCH 5/5] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220 John Stultz
@ 2016-12-13 13:24   ` Alan Stern
  2016-12-13 19:23     ` John Stultz
  0 siblings, 1 reply; 10+ messages in thread
From: Alan Stern @ 2016-12-13 13:24 UTC (permalink / raw)
  To: John Stultz
  Cc: lkml, Chen Yu, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring,
	John Youn, Douglas Anderson, Kishon Vijay Abraham I,
	Felipe Balbi, Greg Kroah-Hartman, linux-usb

On Mon, 12 Dec 2016, John Stultz wrote:

> From: Chen Yu <chenyu56@huawei.com>
> 
> The Hi6220's usb controller is limited in that it does not
> support "Split Transactions", so it does not support communicating
> with low-speed and full-speed devices behind a high-speed hub.
> 
> Thus it requires a quirk so that we can manually drop the usb
> speed when low/full-speed are attached, and bump back to high
> speed when they are removed.

Just out of curiosity (I know nothing about this hardware), what 
happens if there is a high-speed hub plugged into the host controller 
and both a high-speed and a full-speed device plugged into the hub?  

Do you end up forcing the high-speed device to run at full speed?

Alan Stern

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

* Re: [RFC][PATCH 5/5] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220
  2016-12-13 13:24   ` Alan Stern
@ 2016-12-13 19:23     ` John Stultz
  0 siblings, 0 replies; 10+ messages in thread
From: John Stultz @ 2016-12-13 19:23 UTC (permalink / raw)
  To: Alan Stern
  Cc: lkml, Chen Yu, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring,
	John Youn, Douglas Anderson, Kishon Vijay Abraham I,
	Felipe Balbi, Greg Kroah-Hartman, Linux USB List

On Tue, Dec 13, 2016 at 5:24 AM, Alan Stern <stern@rowland.harvard.edu> wrote:
> On Mon, 12 Dec 2016, John Stultz wrote:
>
>> From: Chen Yu <chenyu56@huawei.com>
>>
>> The Hi6220's usb controller is limited in that it does not
>> support "Split Transactions", so it does not support communicating
>> with low-speed and full-speed devices behind a high-speed hub.
>>
>> Thus it requires a quirk so that we can manually drop the usb
>> speed when low/full-speed are attached, and bump back to high
>> speed when they are removed.
>
> Just out of curiosity (I know nothing about this hardware), what

If your interested in details, page 12 of the pdf here has some details:
https://github.com/96boards/documentation/blob/master/ConsumerEdition/HiKey/AdditionalDocs/HiKey_Hardware_User_Manual_Rev0.2.pdf

There's also schematics for the board available (if you are interested
in that sort of stuff). You can find the USB bits on Page 4 here:
https://github.com/96boards/documentation/blob/master/ConsumerEdition/HiKey/HardwareDocs/HiKey_schematics_LeMaker_version_Rev_A1.pdf


> happens if there is a high-speed hub plugged into the host controller
> and both a high-speed and a full-speed device plugged into the hub?
>
> Do you end up forcing the high-speed device to run at full speed?

Yes. It drops back to full-speed.

thanks
-john

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

* Re: [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong
  2016-12-13 12:28   ` Vardan Mikayelyan
@ 2016-12-13 20:40     ` John Stultz
  0 siblings, 0 replies; 10+ messages in thread
From: John Stultz @ 2016-12-13 20:40 UTC (permalink / raw)
  To: Vardan Mikayelyan
  Cc: lkml, Wei Xu, Guodong Xu, Amit Pundir, Rob Herring, John Youn,
	Douglas Anderson, Chen Yu, Kishon Vijay Abraham I, Felipe Balbi,
	Greg Kroah-Hartman, linux-usb

On Tue, Dec 13, 2016 at 4:28 AM, Vardan Mikayelyan
<Vardan.Mikayelyan@synopsys.com> wrote:
> On 12/13/2016 11:12 AM, John Stultz wrote:
>> When removing a USB-A to USB-otg adapter cable, we get a change
>> status irq, and then in dwc2_conn_id_status_change, we
>> erroniously see the GOTGCTL_CONID_B flag set. This causes us to
>> get  stuck in the "while (!dwc2_is_device_mode(hsotg))" loop,
>> spitting out "Waiting for Peripheral Mode, Mode=Host" warnings
>> until it fails out many seconds later.
>>
>> This patch works around the issue by re-reading the GOTGCTL
>> state to check if the GOTGCTL_CONID_B is still set and if not
>> restarting the change status logic.
>>
>> I suspect this isn't the best solution, but it seems to work
>> well for me.
>>
>> Feedback would be greatly appreciated!
>>
>> Cc: Wei Xu <xuwei5@hisilicon.com>
>> Cc: Guodong Xu <guodong.xu@linaro.org>
>> Cc: Amit Pundir <amit.pundir@linaro.org>
>> Cc: Rob Herring <robh+dt@kernel.org>
>> Cc: John Youn <johnyoun@synopsys.com>
>> Cc: Douglas Anderson <dianders@chromium.org>
>> Cc: Chen Yu <chenyu56@huawei.com>
>> Cc: Kishon Vijay Abraham I <kishon@ti.com>
>> Cc: Felipe Balbi <felipe.balbi@linux.intel.com>
>> Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
>> Cc: linux-usb@vger.kernel.org
>> Acked-by: John Youn <johnyoun@synopsys.com>
>> Signed-off-by: John Stultz <john.stultz@linaro.org>
>> ---
>>  drivers/usb/dwc2/hcd.c | 5 ++++-
>>  1 file changed, 4 insertions(+), 1 deletion(-)
>>
>> diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
>> index df5a065..a3f34dd 100644
>> --- a/drivers/usb/dwc2/hcd.c
>> +++ b/drivers/usb/dwc2/hcd.c
>> @@ -3199,7 +3199,7 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>>       dev_dbg(hsotg->dev, "gotgctl=%0x\n", gotgctl);
>>       dev_dbg(hsotg->dev, "gotgctl.b.conidsts=%d\n",
>>               !!(gotgctl & GOTGCTL_CONID_B));
>> -
>> +again:
>>       /* B-Device connector (Device Mode) */
>>       if (gotgctl & GOTGCTL_CONID_B) {
>>               /* Wait for switch to device mode */
>> @@ -3210,6 +3210,9 @@ static void dwc2_conn_id_status_change(struct work_struct *work)
>>                                dwc2_is_host_mode(hsotg) ? "Host" :
>>                                "Peripheral");
>>                       usleep_range(20000, 40000);
>> +                     gotgctl = dwc2_readl(hsotg->regs + GOTGCTL);
>> +                     if (!(gotgctl & GOTGCTL_CONID_B))
>> +                             goto again;
>>                       if (++count > 250)
>>                               break;
>>               }
>>
> Hi John Stultz,
>
> When it goes to ":again", it will go to else anyways. I'll suggest
> alternative way to do this. Please see below.

Sounds good. I've made the change.

> Also you can add "Reviewed-by: Vardan Mikayelyan <mvardan@synopsys.com>"

Thanks so much for your review!
-john

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

end of thread, other threads:[~2016-12-13 21:15 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-12-13  7:09 [RFC][PATCH 0/5] Fixes and workarounds for dwc2 on HiKey board John Stultz
2016-12-13  7:09 ` [RFC][PATCH 1/5] usb: dwc2: Avoid sleeping while holding hsotg->lock John Stultz
2016-12-13  7:09 ` [RFC][PATCH 2/5] usb: dwc2: Workaround case where GOTGCTL state is wrong John Stultz
2016-12-13 12:28   ` Vardan Mikayelyan
2016-12-13 20:40     ` John Stultz
2016-12-13  7:09 ` [RFC][PATCH 3/5] usb: dwc2: Force port resume on switching to device mode John Stultz
2016-12-13  7:09 ` [RFC][PATCH 4/5] usb: dwc2: Avoid suspending if we're in gadget mode John Stultz
2016-12-13  7:09 ` [RFC][PATCH 5/5] usb: dwc2: Add a quirk to allow speed negotiation for Hisilicon Hi6220 John Stultz
2016-12-13 13:24   ` Alan Stern
2016-12-13 19:23     ` John Stultz

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).