[PATCH] usb: gadget: uvc: fix permissions of configfs attributes

2015-11-28 Thread Mian Yousaf Kaukab
76e0da3 "usb-gadget/uvc: use per-attribute show and store methods"
removed write permission for writeable attributes. Correct attribute
permissions.

Fixes: 76e0da3 "usb-gadget/uvc: use per-attribute show and store methods"
Signed-off-by: Mian Yousaf Kaukab 
---
 drivers/usb/gadget/function/uvc_configfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/function/uvc_configfs.c 
b/drivers/usb/gadget/function/uvc_configfs.c
index 289ebca..ad8c9b0 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -20,7 +20,7 @@
 #define UVC_ATTR(prefix, cname, aname) \
 static struct configfs_attribute prefix##attr_##cname = { \
.ca_name= __stringify(aname),   \
-   .ca_mode= S_IRUGO,  \
+   .ca_mode= S_IRUGO | S_IWUGO,\
.ca_owner   = THIS_MODULE,  \
.show   = prefix##cname##_show, \
.store  = prefix##cname##_store,\
-- 
1.9.1

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


[PATCH] usb: gadget: net2280: restore ep_cfg after defect7374 workaround

2015-10-19 Thread Mian Yousaf Kaukab
Defect 7374 workaround enables all GPEP as endpoint 0. Restore
endpoint number when defect 7374 workaround is disabled. Otherwise,
check to match USB endpoint number to hardware endpoint number in
net2280_enable() fails.

Cc:  # 4.2
Reported-by: Paul Jones 
Signed-off-by: Mian Yousaf Kaukab 
---
Hi Felipe,
Is it possible to queue this for v4.3-rc?

BR,
Yousaf

 drivers/usb/gadget/udc/net2280.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
index cf0ed42..6706aef 100644
--- a/drivers/usb/gadget/udc/net2280.c
+++ b/drivers/usb/gadget/udc/net2280.c
@@ -1913,7 +1913,7 @@ static void defect7374_disable_data_eps(struct net2280 
*dev)
 
for (i = 1; i < 5; i++) {
ep = &dev->ep[i];
-   writel(0, &ep->cfg->ep_cfg);
+   writel(i, &ep->cfg->ep_cfg);
}
 
/* CSROUT, CSRIN, PCIOUT, PCIIN, STATIN, RCIN */
-- 
2.3.3

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


[PATCH] usb: dwc2: fix duplicate argument warning

2015-10-12 Thread Mian Yousaf Kaukab
Fix a duplicate argument warning reported by 0-DAY kernel test
infrastructure in the following patch:
77dbf71 usb: dwc2: host: add disconnect interrupt to host only interrupts

Signed-off-by: Mian Yousaf Kaukab 
---
 drivers/usb/dwc2/core.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index bf5e951..ef73e49 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -863,8 +863,7 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
 
/* Enable host mode interrupts without disturbing common interrupts */
intmsk = dwc2_readl(hsotg->regs + GINTMSK);
-   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT |
-   GINTSTS_DISCONNINT;
+   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT;
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
-- 
2.3.3

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


[PATCH v4 32/32] usb: dwc2: exit hibernation on session request

2015-09-30 Thread Mian Yousaf Kaukab
Controller enters hibernation through suspend interrupt on
disconnection. On connection, session request interrupt is generated.
dwc2 must exit hibernation and restore state from this interrupt
before continuing.

In host mode, exit from hibernation is handled by bus_resume function.

Signed-off-by: Mian Yousaf Kaukab 
Signed-off-by: Gregory Herrero 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core_intr.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index d8a5400..27daa42 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -313,16 +313,28 @@ static void dwc2_handle_conn_id_status_change_intr(struct 
dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 {
-   dev_dbg(hsotg->dev, "++Session Request Interrupt++\n");
+   int ret;
+
+   dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
+   hsotg->lx_state);
 
/* Clear interrupt */
dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
 
-   /*
-* Report disconnect if there is any previous session established
-*/
-   if (dwc2_is_device_mode(hsotg))
+   if (dwc2_is_device_mode(hsotg)) {
+   if (hsotg->lx_state == DWC2_L2) {
+   ret = dwc2_exit_hibernation(hsotg, true);
+   if (ret && (ret != -ENOTSUPP))
+   dev_err(hsotg->dev,
+   "exit hibernation failed\n");
+   }
+
+   /*
+* Report disconnect if there is any previous session
+* established
+*/
dwc2_hsotg_disconnect(hsotg);
+   }
 }
 
 /*
-- 
2.3.3

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


[PATCH v4 22/32] usb: dwc2: gadget: set op_state in vbus_session call

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Some device may have external id pin control enabled, so op_state
will not be set on id pin interrupt change.
Thus, ensure op_state is set to peripheral during vbus detection.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index c9a839e..fd080b8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3153,6 +3153,7 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
spin_lock_irqsave(&hsotg->lock, flags);
 
if (is_active) {
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
/*
 * If controller is hibernated, it must exit from hibernation
 * before being initialized
-- 
2.3.3

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


[PATCH v4 31/32] usb: dwc2: gadget: handle reset interrupt before endpoint interrupts

2015-09-30 Thread Mian Yousaf Kaukab
If system is loaded, reset, enum-done and setup interrupts can occur
at the same time. Current interrupt handling sequence will handle
setup packet's interrupt before handling reset interrupt. Which will
break the enumeration process. Correct sequence is to handle reset,
enum-done and then any other endpoint interrupts.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 60 +++
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 50d86d2..d9bcea0 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2456,6 +2456,36 @@ irq_retry:
 
gintsts &= gintmsk;
 
+   if (gintsts & GINTSTS_RESETDET) {
+   dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
+
+   dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
+
+   /* This event must be used only if controller is suspended */
+   if (hsotg->lx_state == DWC2_L2) {
+   dwc2_exit_hibernation(hsotg, true);
+   hsotg->lx_state = DWC2_L0;
+   }
+   }
+
+   if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
+
+   u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+   u32 connected = hsotg->connected;
+
+   dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
+   dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
+   dwc2_readl(hsotg->regs + GNPTXSTS));
+
+   dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
+
+   /* Report disconnection if it is not already done. */
+   dwc2_hsotg_disconnect(hsotg);
+
+   if (usb_status & GOTGCTL_BSESVLD && connected)
+   dwc2_hsotg_core_init_disconnected(hsotg, true);
+   }
+
if (gintsts & GINTSTS_ENUMDONE) {
dwc2_writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
 
@@ -2487,36 +2517,6 @@ irq_retry:
}
}
 
-   if (gintsts & GINTSTS_RESETDET) {
-   dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
-
-   dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
-
-   /* This event must be used only if controller is suspended */
-   if (hsotg->lx_state == DWC2_L2) {
-   dwc2_exit_hibernation(hsotg, true);
-   hsotg->lx_state = DWC2_L0;
-   }
-   }
-
-   if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
-
-   u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
-   u32 connected = hsotg->connected;
-
-   dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
-   dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
-   dwc2_readl(hsotg->regs + GNPTXSTS));
-
-   dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
-
-   /* Report disconnection if it is not already done. */
-   dwc2_hsotg_disconnect(hsotg);
-
-   if (usb_status & GOTGCTL_BSESVLD && connected)
-   dwc2_hsotg_core_init_disconnected(hsotg, true);
-   }
-
/* check both FIFOs */
 
if (gintsts & GINTSTS_NPTXFEMP) {
-- 
2.3.3

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


[PATCH v4 29/32] usb: dwc2: gadget: unmask idstschng interrupt only if controller supports it

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

idstschng interrupt should not be used when id pin control is
external. This is already handled on dwc2 host part. Fix it on gadget
part as well.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 25ef200..3363fa5 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2281,6 +2281,7 @@ static int dwc2_hsotg_corereset(struct dwc2_hsotg *hsotg)
 void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
bool is_usb_reset)
 {
+   u32 intmsk;
u32 val;
 
/* Kill any ep0 requests as controller will be reinitialized */
@@ -2312,14 +2313,16 @@ void dwc2_hsotg_core_init_disconnected(struct 
dwc2_hsotg *hsotg,
 
/* Clear any pending interrupts */
dwc2_writel(0x, hsotg->regs + GINTSTS);
-
-   dwc2_writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
+   intmsk = GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF |
-   GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST |
-   GINTSTS_RESETDET | GINTSTS_ENUMDONE |
-   GINTSTS_OTGINT | GINTSTS_USBSUSP |
-   GINTSTS_WKUPINT,
-   hsotg->regs + GINTMSK);
+   GINTSTS_USBRST | GINTSTS_RESETDET |
+   GINTSTS_ENUMDONE | GINTSTS_OTGINT |
+   GINTSTS_USBSUSP | GINTSTS_WKUPINT;
+
+   if (hsotg->core_params->external_id_pin_ctl <= 0)
+   intmsk |= GINTSTS_CONIDSTSCHNG;
+
+   dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 
if (using_dma(hsotg))
dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
-- 
2.3.3

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


[PATCH v4 27/32] usb: dwc2: gadget: kill ep0 requests before reinitializing core

2015-09-30 Thread Mian Yousaf Kaukab
Make sure there are no requests pending on ep0 before reinitializing
core. Otherwise, dwc2_hsotg_enqueue_setup will fail afterwards.

Also, take hsotg->lock before calling
dwc2_hsotg_core_init_disconnected() from dwc2_conn_id_status_change()
as dwc2_hsotg_complete_request() expect lock to be held.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 8 +++-
 drivers/usb/dwc2/hcd.c| 3 +++
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 2d0bba7..eee2b43 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2283,6 +2283,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
 {
u32 val;
 
+   /* Kill any ep0 requests as controller will be reinitialized */
+   kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
+
if (!is_usb_reset)
if (dwc2_hsotg_corereset(hsotg))
return;
@@ -2511,9 +2514,6 @@ irq_retry:
if (time_after(jiffies, hsotg->last_rst +
   msecs_to_jiffies(200))) {
 
-   kill_all_requests(hsotg, hsotg->eps_out[0],
- -ECONNRESET);
-
dwc2_hsotg_core_init_disconnected(hsotg, true);
}
}
@@ -3240,8 +3240,6 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
if (hsotg->lx_state == DWC2_L2)
dwc2_exit_hibernation(hsotg, false);
 
-   /* Kill any ep0 requests as controller will be reinitialized */
-   kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
dwc2_hsotg_core_connect(hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index f97e9e9..95aefe5 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1355,6 +1355,7 @@ static void dwc2_conn_id_status_change(struct work_struct 
*work)
wf_otg);
u32 count = 0;
u32 gotgctl;
+   unsigned long flags;
 
dev_dbg(hsotg->dev, "%s()\n", __func__);
 
@@ -1382,7 +1383,9 @@ static void dwc2_conn_id_status_change(struct work_struct 
*work)
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
dwc2_core_init(hsotg, false, -1);
dwc2_enable_global_interrupts(hsotg);
+   spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hsotg_core_init_disconnected(hsotg, false);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_hsotg_core_connect(hsotg);
} else {
/* A-Device connector (Host Mode) */
-- 
2.3.3

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


[PATCH v4 28/32] usb: dwc2: gadget: only reset core after addressed state

2015-09-30 Thread Mian Yousaf Kaukab
There is a 200ms guard period to avoid unnecessary resets of the dwc2
ip. This delay sometimes prove to be too large when usbcv is run with
an ehci host. dwc2 only needs to be reset after addressed state.
Change the logic to reset ip after addressed state.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.h   |  2 --
 drivers/usb/dwc2/gadget.c | 11 +++
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 27e6fbf..8c56054 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -688,7 +688,6 @@ struct dwc2_hregs_backup {
  * @ctrl_req:   Request for EP0 control packets.
  * @ep0_state:  EP0 control transfers state
  * @test_mode:  USB test mode requested by the host
- * @last_rst:   Time of last reset
  * @eps:The endpoints being supplied to the gadget framework
  * @g_using_dma:  Indicate if dma usage is enabled
  * @g_rx_fifo_sz: Contains rx fifo size value
@@ -832,7 +831,6 @@ struct dwc2_hsotg {
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
-   unsigned long last_rst;
struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
u32 g_using_dma;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index eee2b43..25ef200 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2416,7 +2416,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
/* must be at-least 3ms to allow bus to see disconnect */
mdelay(3);
 
-   hsotg->last_rst = jiffies;
hsotg->lx_state = DWC2_L0;
 }
 
@@ -2500,6 +2499,7 @@ irq_retry:
if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
 
u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+   u32 connected = hsotg->connected;
 
dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
@@ -2510,13 +2510,8 @@ irq_retry:
/* Report disconnection if it is not already done. */
dwc2_hsotg_disconnect(hsotg);
 
-   if (usb_status & GOTGCTL_BSESVLD) {
-   if (time_after(jiffies, hsotg->last_rst +
-  msecs_to_jiffies(200))) {
-
-   dwc2_hsotg_core_init_disconnected(hsotg, true);
-   }
-   }
+   if (usb_status & GOTGCTL_BSESVLD && connected)
+   dwc2_hsotg_core_init_disconnected(hsotg, true);
}
 
/* check both FIFOs */
-- 
2.3.3

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


[PATCH v4 24/32] usb: dwc2: gadget: ignore stall check for ep0

2015-09-30 Thread Mian Yousaf Kaukab
dwc2_hsotg_start_req starts a request only if endpoint is not stalled.
Ignore this check for ep0 as core will clear DOEPCTL0.Stall after
sending stall handshake. Prepare instead for receiving next setup
packet.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index ac1beb5..56b7424 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -552,7 +552,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
/* If endpoint is stalled, we will restart request later */
ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
 
-   if (ctrl & DXEPCTL_STALL) {
+   if (index && ctrl & DXEPCTL_STALL) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
return;
}
-- 
2.3.3

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


[PATCH v4 25/32] usb: dwc2: gadget: print complete setup packet

2015-09-30 Thread Mian Yousaf Kaukab
wIndex field was missing. Also print in natural order instead of
Req first, so that its easier to compare for example against
bus analyzer logs.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 56b7424..6cd6bf9 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1202,9 +1202,10 @@ static void dwc2_hsotg_process_control(struct dwc2_hsotg 
*hsotg,
int ret = 0;
u32 dcfg;
 
-   dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n",
-ctrl->bRequest, ctrl->bRequestType,
-ctrl->wValue, ctrl->wLength);
+   dev_dbg(hsotg->dev,
+   "ctrl Type=%02x, Req=%02x, V=%04x, I=%04x, L=%04x\n",
+   ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+   ctrl->wIndex, ctrl->wLength);
 
if (ctrl->wLength == 0) {
ep0->dir_in = 1;
-- 
2.3.3

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


[PATCH v4 26/32] usb: dwc2: gadget: stop current transfer on dequeue

2015-09-30 Thread Mian Yousaf Kaukab
If the request being dequeued is already started, disable endpoint
to stop the transfer and then call dwc2_hsotg_complete_request().
Endpoint will be re-enabled on next call to dwc2_hsotg_start_req().

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 77 +++
 1 file changed, 77 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 6cd6bf9..2d0bba7 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2822,6 +2822,79 @@ static bool on_list(struct dwc2_hsotg_ep *ep, struct 
dwc2_hsotg_req *test)
return false;
 }
 
+static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
+   u32 bit, u32 timeout)
+{
+   u32 i;
+
+   for (i = 0; i < timeout; i++) {
+   if (dwc2_readl(hs_otg->regs + reg) & bit)
+   return 0;
+   udelay(1);
+   }
+
+   return -ETIMEDOUT;
+}
+
+static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
+   struct dwc2_hsotg_ep *hs_ep)
+{
+   u32 epctrl_reg;
+   u32 epint_reg;
+
+   epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) :
+   DOEPCTL(hs_ep->index);
+   epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) :
+   DOEPINT(hs_ep->index);
+
+   dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__,
+   hs_ep->name);
+   if (hs_ep->dir_in) {
+   __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
+   /* Wait for Nak effect */
+   if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
+   DXEPINT_INEPNAKEFF, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout DIEPINT.NAKEFF\n", __func__);
+   } else {
+   /* Clear any pending nak effect interrupt */
+   dwc2_writel(GINTSTS_GINNAKEFF, hsotg->regs + GINTSTS);
+
+   __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+
+   /* Wait for global nak to take effect */
+   if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+   GINTSTS_GINNAKEFF, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout GINTSTS.GINNAKEFF\n", __func__);
+   }
+
+   /* Disable ep */
+   __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
+
+   /* Wait for ep to be disabled */
+   if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout DOEPCTL.EPDisable\n", __func__);
+
+   if (hs_ep->dir_in) {
+   if (hsotg->dedicated_fifos) {
+   dwc2_writel(GRSTCTL_TXFNUM(hs_ep->fifo_index) |
+   GRSTCTL_TXFFLSH, hsotg->regs + GRSTCTL);
+   /* Wait for fifo flush */
+   if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL,
+   GRSTCTL_TXFFLSH, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout flushing fifos\n",
+   __func__);
+   }
+   /* TODO: Flush shared tx fifo */
+   } else {
+   /* Remove global NAKs */
+   __bic32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+   }
+}
+
 /**
  * dwc2_hsotg_ep_dequeue - dequeue given endpoint
  * @ep: The endpoint to dequeue.
@@ -2843,6 +2916,10 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, 
struct usb_request *req)
return -EINVAL;
}
 
+   /* Dequeue already started request */
+   if (req == &hs_ep->req->req)
+   dwc2_hsotg_ep_stop_xfr(hs, hs_ep);
+
dwc2_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
spin_unlock_irqrestore(&hs->lock, flags);
 
-- 
2.3.3

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


[PATCH v4 30/32] usb: dwc2: gadget: exit hibernation before power down

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

When disconnecting cable, controller will detect a suspend condition
and enter partial power down. If vbus_session is called by the phy
driver during hibernation, make sure controller exit hibernation
before it is accessed.

Signed-off-by: Jianqiang Tang 
Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3363fa5..50d86d2 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3229,14 +3229,15 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
dev_dbg(hsotg->dev, "%s: is_active: %d\n", __func__, is_active);
spin_lock_irqsave(&hsotg->lock, flags);
 
+   /*
+* If controller is hibernated, it must exit from hibernation
+* before being initialized / de-initialized
+*/
+   if (hsotg->lx_state == DWC2_L2)
+   dwc2_exit_hibernation(hsotg, false);
+
if (is_active) {
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
-   /*
-* If controller is hibernated, it must exit from hibernation
-* before being initialized
-*/
-   if (hsotg->lx_state == DWC2_L2)
-   dwc2_exit_hibernation(hsotg, false);
 
dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
-- 
2.3.3

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


[PATCH v4 23/32] usb: dwc2: gadget: abort core init if core_reset fails

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

No point of continue with initialization if core is not in a sane
state.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index fd080b8..ac1beb5 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2283,7 +2283,8 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
u32 val;
 
if (!is_usb_reset)
-   dwc2_hsotg_corereset(hsotg);
+   if (dwc2_hsotg_corereset(hsotg))
+   return;
 
/*
 * we must now enable ep0 ready for host detection and then
-- 
2.3.3

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


[PATCH v4 19/32] usb: dwc2: gadget: initialize op_state for peripheral only configuration

2015-09-30 Thread Mian Yousaf Kaukab
ID status change interrupt will not be handled in peripheral only
configuration. So initialize op_state during gadget init.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index e4a4b18..df8d599 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3447,6 +3447,8 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
hsotg->gadget.name = dev_name(dev);
if (hsotg->dr_mode == USB_DR_MODE_OTG)
hsotg->gadget.is_otg = 1;
+   else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 
/*
 * Force Device mode before initialization.
-- 
2.3.3

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


[PATCH v4 20/32] usb: dwc2: force dr_mode in case of configuration mismatch

2015-09-30 Thread Mian Yousaf Kaukab
If dual role configuration is not selected, check and force dr_mode
based on the selected configuration.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/platform.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index ed7a78e..a62514f 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -368,6 +368,17 @@ static int dwc2_driver_probe(struct platform_device *dev)
(unsigned long)res->start, hsotg->regs);
 
hsotg->dr_mode = usb_get_dr_mode(&dev->dev);
+   if (IS_ENABLED(CONFIG_USB_DWC2_HOST) &&
+   hsotg->dr_mode != USB_DR_MODE_HOST) {
+   hsotg->dr_mode = USB_DR_MODE_HOST;
+   dev_warn(hsotg->dev,
+   "Configuration mismatch. Forcing host mode\n");
+   } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) &&
+   hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
+   hsotg->dr_mode = USB_DR_MODE_PERIPHERAL;
+   dev_warn(hsotg->dev,
+   "Configuration mismatch. Forcing peripheral mode\n");
+   }
 
retval = dwc2_lowlevel_hw_init(hsotg);
if (retval)
-- 
2.3.3

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


[PATCH v4 17/32] usb: dwc2: host: kill remaining urbs using -ECONNRESET status

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

On a disconnect, dwc2 will kill all remaining urbs from qh list.
urbs are given back to hcd with -ETIMEDOUT status.
Some usb device driver, like mass storage, will unlink all urbs
using usb_hcd_unlink_urb when receiving a negative status different
from -ECONNRESET.
The following flow will then happen:
dwc2_hcd_disconnect()
-> dwc2_kill_all_urbs() try to kill first pending urb.
-> dwc2_host_complete(-ETIMEDOUT)
-> usb_hcd_giveback_urb(-ETIMEDOUT)
-> sg_complete()
-> usb_unlink_urb()
-> usb_put_dev(urb->dev)
-> dwc2_kill_all_urbs() try to kill next pending urb.
-> dwc2_host_complete(-ETIMEDOUT)
-> usb_hcd_giveback_urb(-ETIMEDOUT)
-> NULL pointer dereferencing because urb->dev has been freed for all
urbs of this device.

The root cause of this NULL pointer is to call call usb_unlink_urb()
while we are killing all urbs. To avoid this return urb with
-ECONNRESET status

This issue usually happens while removing mass storage device during
transfer.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 882be25..f97e9e9 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -134,7 +134,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg 
*hsotg,
list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
 qtd_list_entry) {
-   dwc2_host_complete(hsotg, qtd, -ETIMEDOUT);
+   dwc2_host_complete(hsotg, qtd, -ECONNRESET);
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
}
}
-- 
2.3.3

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


[PATCH v4 21/32] usb: dwc2: gadget: don't modify pullup state in host mode

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Modifying the pullup state during host mode trig a new enumeration
of attached device. Thus, avoid modifying pullup in host mode.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index df8d599..c9a839e 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3116,7 +3116,14 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, 
int is_on)
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags = 0;
 
-   dev_dbg(hsotg->dev, "%s: is_on: %d\n", __func__, is_on);
+   dev_dbg(hsotg->dev, "%s: is_on: %d, op_state: %d\n", __func__, is_on,
+   hsotg->op_state);
+
+   /* Don't modify pullup state while in host mode */
+   if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
+   hsotg->enabled = is_on;
+   return 0;
+   }
 
mutex_lock(&hsotg->init_mutex);
spin_lock_irqsave(&hsotg->lock, flags);
-- 
2.3.3

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


[PATCH v4 16/32] usb: dwc2: host: use correct frame number during qh init

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

On first qh initialization, hsotg->frame_number is not corresponding
to reality. So read it from host controller to get correct value.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd_queue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 294fe28..d9b3a6f 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -106,6 +106,9 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct 
dwc2_qh *qh,
USB_SPEED_HIGH : dev_speed, qh->ep_is_in,
qh->ep_type == USB_ENDPOINT_XFER_ISOC,
bytecount));
+
+   /* Ensure frame_number corresponds to the reality */
+   hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
/* Start in a slightly future (micro)frame */
qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
 SCHEDULE_SLOP);
-- 
2.3.3

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


[PATCH v4 18/32] usb: dwc2: gadget: ensure lx_state corresponds to current state

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Correctly update lx_state on gadget connection and disconnection.
When usb cable is disconnected, lx_state must be updated to L3 as
controller could be in power off state.
When usb cable is connected, lx_state must be updated to L0 as
controller is powered.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 12ac879..e4a4b18 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2185,6 +2185,7 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
}
 
call_gadget(hsotg, disconnect);
+   hsotg->lx_state = DWC2_L3;
 }
 
 /**
@@ -2411,6 +2412,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
mdelay(3);
 
hsotg->last_rst = jiffies;
+   hsotg->lx_state = DWC2_L0;
 }
 
 static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
@@ -2510,7 +2512,6 @@ irq_retry:
kill_all_requests(hsotg, hsotg->eps_out[0],
  -ECONNRESET);
 
-   hsotg->lx_state = DWC2_L0;
dwc2_hsotg_core_init_disconnected(hsotg, true);
}
}
@@ -3149,10 +3150,9 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
 * If controller is hibernated, it must exit from hibernation
 * before being initialized
 */
-   if (hsotg->lx_state == DWC2_L2) {
+   if (hsotg->lx_state == DWC2_L2)
dwc2_exit_hibernation(hsotg, false);
-   hsotg->lx_state = DWC2_L0;
-   }
+
/* Kill any ep0 requests as controller will be reinitialized */
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
dwc2_hsotg_core_init_disconnected(hsotg, false);
-- 
2.3.3

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


[PATCH v4 12/32] usb: dwc2: host: disable interrupt during stop

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Disable host interrupts before synchronising dwc2 irq.
So that interrupts are not generated once controller is stopped.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 5acdeaf..844bf83 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2350,6 +2350,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
unsigned long flags;
 
+   /* Turn off all host-specific interrupts */
+   dwc2_disable_host_interrupts(hsotg);
+
/* Wait for interrupt processing to finish */
synchronize_irq(hcd->irq);
 
-- 
2.3.3

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


[PATCH v4 15/32] usb: dwc2: host: correctly dump urb isochronous descriptors

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Print urb->iso_frame_desc.status after it has been updated using
dwc2_hcd_urb_get_iso_desc_status().

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 30dc21d..882be25 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2227,11 +2227,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct 
dwc2_qtd *qtd,
 usb_pipein(urb->pipe) ? "IN" : "OUT", status,
 urb->actual_length);
 
-   if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
-   for (i = 0; i < urb->number_of_packets; i++)
-   dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
-i, urb->iso_frame_desc[i].status);
-   }
 
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
@@ -2244,6 +2239,12 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct 
dwc2_qtd *qtd,
}
}
 
+   if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
+   for (i = 0; i < urb->number_of_packets; i++)
+   dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
+i, urb->iso_frame_desc[i].status);
+   }
+
urb->status = status;
if (!status) {
if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
-- 
2.3.3

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


[PATCH v4 14/32] usb: dwc2: host: wait 3ms for controller stabilization

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Some high speed mass storage devices fail to enumerate with following
error:

Cannot enable port %i.  Maybe the USB cable is bad?

This happens only when the device is plugged while the controller
is in hibernation state. After exiting hibernation, the controller
detects the device as a low speed device and fail to enumerate it.

Problem occurs only if HPRT0.PWR bit is programmed in a too short
delay after exiting hibernation. Dumping hprt register in
_dwc2_hcd_resume() directly after dwc2_exit_hibernation() shows that
HPRT0.LNSTS (D+/D- level) becomes valid approximately 2ms after
exiting hibernation.

Since dwc2_exit_hibernation() is called from atomic context, keep the
delay out of this function.

Delay value is experimental and not mentioned in Synopsys
documentation. To be on the safe side 3ms delay is used.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 844bf83..30dc21d 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2472,6 +2472,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_port_resume(hsotg);
} else {
+   /* Wait for controller to correctly update D+/D- level */
+   usleep_range(3000, 5000);
+
/*
 * Clear Port Enable and Port Status changes.
 * Enable Port Power.
@@ -2479,7 +2482,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
dwc2_writel(HPRT0_PWR | HPRT0_CONNDET |
HPRT0_ENACHG, hsotg->regs + HPRT0);
/* Wait for controller to detect Port Connect */
-   mdelay(5);
+   usleep_range(5000, 7000);
}
 
return ret;
-- 
2.3.3

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


[PATCH v4 13/32] usb: dwc2: host: clear pending interrupts prior hibernation

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

If an interrupt rises during hibernation process, dwc2 will assert
interrupt line to interrupt controller. If interrupt is level
sensitive, interrupt handler will be called in a loop because dwc2
will not be able to clear it while controller is hibernated.
Thus, clear all controller interrupts before hibernation entry.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 c5e0a45..bf5e951 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -398,6 +398,12 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
}
}
 
+   /*
+* Clear any pending interrupts since dwc2 will not be able to
+* clear them after entering hibernation.
+*/
+   dwc2_writel(0x, hsotg->regs + GINTSTS);
+
/* Put the controller in low power state */
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
-- 
2.3.3

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


[PATCH v4 09/32] usb: dwc2: host: reset frame number after suspend

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Frame number is reset in hardware after exiting hibernation.
Thus, reset frame_number and ensure qh are queued with correct
sched_frame.

Otherwise, qh->sched_frame may be too high compared to
current frame number (which is 0). This can delay addition of qh in
the list of transfers until frame number reaches qh->sched_frame.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.c  | 1 +
 drivers/usb/dwc2/hcd_queue.c | 7 +++
 2 files changed, 8 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 0bfc987..f5c3120 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -116,6 +116,7 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg 
*hsotg)
 
dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);
dwc2_writel(hr->hfir, hsotg->regs + HFIR);
+   hsotg->frame_number = 0;
 
return 0;
 }
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 712977f..294fe28 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -583,6 +583,13 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct 
dwc2_qh *qh)
/* QH already in a schedule */
return 0;
 
+   if (!dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number) &&
+   !hsotg->frame_number) {
+   dev_dbg(hsotg->dev, "reset frame number counter\n");
+   qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
+   SCHEDULE_SLOP);
+   }
+
/* Add the new QH to the appropriate schedule */
if (dwc2_qh_is_non_per(qh)) {
/* Always start in inactive schedule */
-- 
2.3.3

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


[PATCH v4 11/32] usb: dwc2: host: add disconnect interrupt to host only interrupts

2015-09-30 Thread Mian Yousaf Kaukab
GINTSTS.DisconnInt is host only interrupt and should be disable after
dwc2_disable_host_interrupts is called.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index f5c3120..c5e0a45 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -857,7 +857,8 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
 
/* Enable host mode interrupts without disturbing common interrupts */
intmsk = dwc2_readl(hsotg->regs + GINTMSK);
-   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT;
+   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT |
+   GINTSTS_DISCONNINT;
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
@@ -872,7 +873,7 @@ void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
 
/* Disable host mode interrupts without disturbing common interrupts */
intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT |
-   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP);
+   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | GINTSTS_DISCONNINT);
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
-- 
2.3.3

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


[PATCH v4 08/32] usb: dwc2: host: resume only if bus is suspended

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Port can be resumed in bus_resume callback.
In this case, there is no need to drive resume a second time
when hcd ask for it.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index f5fc13b..76692b5 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1571,7 +1571,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, 
u16 typereq,
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
 
-   dwc2_port_resume(hsotg);
+   if (hsotg->bus_suspended)
+   dwc2_port_resume(hsotg);
break;
 
case USB_PORT_FEAT_POWER:
-- 
2.3.3

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


[PATCH v4 10/32] usb: dwc2: host: disconnect hcd prior stopping it

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

In case controller is asked to stop while devices are connected,
disconnect all devices and clean up before stopping.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 76692b5..5acdeaf 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2350,7 +2350,12 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
unsigned long flags;
 
+   /* Wait for interrupt processing to finish */
+   synchronize_irq(hcd->irq);
+
spin_lock_irqsave(&hsotg->lock, flags);
+   /* Ensure hcd is disconnected */
+   dwc2_hcd_disconnect(hsotg);
dwc2_hcd_stop(hsotg);
hsotg->lx_state = DWC2_L3;
hcd->state = HC_STATE_HALT;
-- 
2.3.3

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


[PATCH v4 03/32] usb: dwc2: host: add flag to reflect bus state

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

lx_state must be used to reflect controller power state only and not
bus state. Thus add a flag to track state during bus suspend.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.h | 1 +
 drivers/usb/dwc2/hcd.c  | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a130e38..27e6fbf 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -765,6 +765,7 @@ struct dwc2_hsotg {
u16 frame_usecs[8];
u16 frame_number;
u16 periodic_qh_count;
+   bool bus_suspended;
 
 #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
 #define FRAME_NUM_ARRAY_SIZE 1000
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index b929087..6dfa143 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1425,6 +1425,7 @@ static void dwc2_wakeup_detected(unsigned long data)
dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
dwc2_readl(hsotg->regs + HPRT0));
 
+   hsotg->bus_suspended = false;
dwc2_hcd_rem_wakeup(hsotg);
 
/* Change to L0 state */
@@ -1461,8 +1462,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
hprt0 |= HPRT0_SUSP;
dwc2_writel(hprt0, hsotg->regs + HPRT0);
 
-   /* Update lx_state */
-   hsotg->lx_state = DWC2_L2;
+   hsotg->bus_suspended = true;
 
/* Suspend the Phy Clock */
pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
@@ -1510,6 +1510,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   hsotg->bus_suspended = false;
spin_unlock_irqrestore(&hsotg->lock, flags);
 }
 
-- 
2.3.3

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


[PATCH v4 01/32] usb: dwc2: host: don't clear hprt0 status bits when exiting hibernation

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

When entering hibernation hprt0 must be read using dwc2_read_hprt0().
Otherwise, any set hprt0 status bits will be cleared when restoring
hprt0 on exit from hibernation.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fc0521a..0bfc987 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -78,7 +78,7 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg 
*hsotg)
for (i = 0; i < hsotg->core_params->host_channels; ++i)
hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i));
 
-   hr->hprt0 = dwc2_readl(hsotg->regs + HPRT0);
+   hr->hprt0 = dwc2_read_hprt0(hsotg);
hr->hfir = dwc2_readl(hsotg->regs + HFIR);
hr->valid = true;
 
-- 
2.3.3

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


[PATCH v4 00/32] usb: dwc2: various bug fixes

2015-09-30 Thread Mian Yousaf Kaukab
Hi,
This series consists of various bug fixes for both host and gadget
sides. All patches are verified on dwc2 v3.0a with dedicated fifos.
It would be good to get some Tested-bys for other platforms.

It is based on testing/next branch in Felipe's git.

Hi Felipe,
I see that you have already applied some of the patches from this series.
Can you please take the whole series again? as patches have been modified
after comments from Sergei Shtylyov.

Thank you,

Best regards,
Yousaf

History:
v4:
 - Fix comments from Sergei Shtylyov
 
v3:
 - Fix comment from Sergei Shtylyov
 - Rebase to latest testing/next
 
v2:
 - Rebase to latest testing/next
 - Fix lock issue found by John Youn when calling
   dwc2_hsotg_core_init_disconnected() from dwc2_conn_id_status_change()
 - Fix comments from John Youn
 - Fix comments from Doug Anderson

v1:
 - Fix following comments from David Cohen (received on an internal
   list):
- Fix build when "usb: dwc2: host: create a function to handle-
  port_resume" is applied.
- Take spin locks within if statements in "usb: dwc2: host: enter-
  hibernation during bus suspend"
- Remove extra 100us delay in "usb: dwc2: host: enter-
  hibernation during bus suspend"
- Fix spelling mistakes in "usb: dwc2: host: update hcd and-
  lx_state during start/stop callbacks"
- Change dev_warn to dev_dbg in "usb: dwc2: host: reset frame-
   number after suspend"
- Change mdelay to usleep_range in "usb: dwc2: host: wait 3ms for-
  controller stabilization"
 - Fix comments from Sergei Shtylyov

Gregory Herrero (22):
  usb: dwc2: host: don't clear hprt0 status bits when exiting
hibernation
  usb: dwc2: host: create a function to handle port_resume
  usb: dwc2: host: add flag to reflect bus state
  usb: dwc2: host: enter hibernation during bus suspend
  usb: dwc2: host: update hcd and lx_state during start/stop callbacks
  usb: dwc2: host: avoid resetting lx_state to L3 during disconnect
  usb: dwc2: host: ignore wakeup interrupt if hibernation supported
  usb: dwc2: host: resume only if bus is suspended
  usb: dwc2: host: reset frame number after suspend
  usb: dwc2: host: disconnect hcd prior stopping it
  usb: dwc2: host: disable interrupt during stop
  usb: dwc2: host: clear pending interrupts prior hibernation
  usb: dwc2: host: wait 3ms for controller stabilization
  usb: dwc2: host: correctly dump urb isochronous descriptors
  usb: dwc2: host: use correct frame number during qh init
  usb: dwc2: host: kill remaining urbs using -ECONNRESET status
  usb: dwc2: gadget: ensure lx_state corresponds to current state
  usb: dwc2: gadget: don't modify pullup state in host mode
  usb: dwc2: gadget: set op_state in vbus_session call
  usb: dwc2: gadget: abort core init if core_reset fails
  usb: dwc2: gadget: unmask idstschng interrupt only if controller
    supports it
  usb: dwc2: gadget: exit hibernation before power down

Mian Yousaf Kaukab (10):
  usb: dwc2: host: add disconnect interrupt to host only interrupts
  usb: dwc2: gadget: initialize op_state for peripheral only
configuration
  usb: dwc2: force dr_mode in case of configuration mismatch
  usb: dwc2: gadget: ignore stall check for ep0
  usb: dwc2: gadget: print complete setup packet
  usb: dwc2: gadget: stop current transfer on dequeue
  usb: dwc2: gadget: kill ep0 requests before reinitializing core
  usb: dwc2: gadget: only reset core after addressed state
  usb: dwc2: gadget: handle reset interrupt before endpoint interrupts
  usb: dwc2: exit hibernation on session request

 drivers/usb/dwc2/core.c  |  14 ++-
 drivers/usb/dwc2/core.h  |   3 +-
 drivers/usb/dwc2/core_intr.c |  29 --
 drivers/usb/dwc2/gadget.c| 210 ++-
 drivers/usb/dwc2/hcd.c   | 209 --
 drivers/usb/dwc2/hcd_queue.c |  10 +++
 drivers/usb/dwc2/platform.c  |  11 +++
 7 files changed, 385 insertions(+), 101 deletions(-)

-- 
2.3.3

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


[PATCH v4 02/32] usb: dwc2: host: create a function to handle port_resume

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

port resume sequence may be used in different places. Create a
function to handle it. Make hprt0 read-modify-write atomic and
clear HPRT0_SUSP for both writes as it is a "read, write-set,
and self-clear (R_WS_SC)" bit. Since the lock is released
between the writes, read hprt0 again.

Since the phy clock is stopped in dwc2_port_suspend(), enable it
here and remove the PCGCTL write from dwc2_hcd_hub_control()

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 40 ++--
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 1595d70..b929087 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1484,6 +1484,35 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
}
 }
 
+/* Must NOT be called with interrupt disabled or spinlock held */
+static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
+{
+   unsigned long flags;
+   u32 hprt0;
+   u32 pcgctl;
+
+   /* Resume the Phy Clock */
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl &= ~PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   usleep_range(2, 4);
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 |= HPRT0_RES;
+   hprt0 &= ~HPRT0_SUSP;
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+
+   msleep(USB_RESUME_TIMEOUT);
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
 /* Handles hub class-specific requests */
 static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
u16 wvalue, u16 windex, char *buf, u16 wlength)
@@ -1529,17 +1558,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg 
*hsotg, u16 typereq,
case USB_PORT_FEAT_SUSPEND:
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
-   dwc2_writel(0, hsotg->regs + PCGCTL);
-   usleep_range(2, 4);
 
-   hprt0 = dwc2_read_hprt0(hsotg);
-   hprt0 |= HPRT0_RES;
-   dwc2_writel(hprt0, hsotg->regs + HPRT0);
-   hprt0 &= ~HPRT0_SUSP;
-   msleep(USB_RESUME_TIMEOUT);
-
-   hprt0 &= ~HPRT0_RES;
-   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   dwc2_port_resume(hsotg);
break;
 
case USB_PORT_FEAT_POWER:
-- 
2.3.3

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


[PATCH v4 04/32] usb: dwc2: host: enter hibernation during bus suspend

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Disable controller power and enter hibernation when usb bus is
suspended. A phy driver is required to disable the power of the
controller and detect remote-wakeup or disconnection since the
controller will not be able to detect these in this state.

Once the phy driver detects bus activity, it must call
usb_hcd_resume_root_hub.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 140 -
 1 file changed, 128 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 6dfa143..15adc7d 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1464,11 +1464,17 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
 
hsotg->bus_suspended = true;
 
-   /* Suspend the Phy Clock */
-   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
-   pcgctl |= PCGCTL_STOPPCLK;
-   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
-   udelay(10);
+   /*
+* If hibernation is supported, Phy clock will be suspended
+* after registers are backuped.
+*/
+   if (!hsotg->core_params->hibernation) {
+   /* Suspend the Phy Clock */
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl |= PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   udelay(10);
+   }
 
/* For HNP the bus must be suspended for at least 200ms */
if (dwc2_host_is_b_hnp_enabled(hsotg)) {
@@ -1491,11 +1497,16 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
u32 hprt0;
u32 pcgctl;
 
-   /* Resume the Phy Clock */
-   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
-   pcgctl &= ~PCGCTL_STOPPCLK;
-   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
-   usleep_range(2, 4);
+   /*
+* If hibernation is supported, Phy clock is already resumed
+* after registers restore.
+*/
+   if (!hsotg->core_params->hibernation) {
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl &= ~PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   usleep_range(2, 4);
+   }
 
spin_lock_irqsave(&hsotg->lock, flags);
hprt0 = dwc2_read_hprt0(hsotg);
@@ -2347,17 +2358,122 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 {
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+   unsigned long flags;
+   int ret = 0;
+   u32 hprt0;
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+
+   if (hsotg->lx_state != DWC2_L0)
+   goto unlock;
+
+   if (!HCD_HW_ACCESSIBLE(hcd))
+   goto unlock;
+
+   if (!hsotg->core_params->hibernation)
+   goto skip_power_saving;
+
+   /*
+* Drive USB suspend and disable port Power
+* if usb bus is not suspended.
+*/
+   if (!hsotg->bus_suspended) {
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 |= HPRT0_SUSP;
+   hprt0 &= ~HPRT0_PWR;
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   }
+
+   /* Enter hibernation */
+   ret = dwc2_enter_hibernation(hsotg);
+   if (ret) {
+   if (ret != -ENOTSUPP)
+   dev_err(hsotg->dev,
+   "enter hibernation failed\n");
+   goto skip_power_saving;
+   }
+
+   /* Ask phy to be suspended */
+   if (!IS_ERR_OR_NULL(hsotg->uphy)) {
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+   usb_phy_set_suspend(hsotg->uphy, true);
+   spin_lock_irqsave(&hsotg->lock, flags);
+   }
+
+   /* After entering hibernation, hardware is no more accessible */
+   clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
+skip_power_saving:
hsotg->lx_state = DWC2_L2;
-   return 0;
+unlock:
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+
+   return ret;
 }
 
 static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 {
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+   unsigned long flags;
+   int ret = 0;
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+
+   if (hsotg->lx_state != DWC2_L2)
+   goto unlock;
+
+   if (!hsotg->core_params->hibernation) {
+   hsotg->lx_state = DWC2_L0;
+   goto unlock;
+   }
+
+   /*
+* Set HW accessible bit before powering on the controller
+* since an interrupt may rise.
+*/
+   set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+   /*
+

[PATCH v4 06/32] usb: dwc2: host: avoid resetting lx_state to L3 during disconnect

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

When a device is disconnected, lx_state must not be changed since the
device may be disconnected whereas controller is still powered.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core_intr.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index a6b1613..3275310 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -387,9 +387,6 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg 
*hsotg)
if (hsotg->op_state == OTG_STATE_A_HOST)
dwc2_hcd_disconnect(hsotg);
 
-   /* Change to L3 (OFF) state */
-   hsotg->lx_state = DWC2_L3;
-
dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
 }
 
-- 
2.3.3

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


[PATCH v4 07/32] usb: dwc2: host: ignore wakeup interrupt if hibernation supported

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

If hibernation is supported, resume of devices will be handled in
bus_resume callback.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core_intr.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 3275310..d8a5400 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -356,6 +356,10 @@ static void dwc2_handle_wakeup_detected_intr(struct 
dwc2_hsotg *hsotg)
/* Change to L0 state */
hsotg->lx_state = DWC2_L0;
} else {
+   if (hsotg->core_params->hibernation) {
+   dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+   return;
+   }
if (hsotg->lx_state != DWC2_L1) {
u32 pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
-- 
2.3.3

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


[PATCH v4 05/32] usb: dwc2: host: update hcd and lx_state during start/stop callbacks

2015-09-30 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

During hcd initialization, hardware accessible flag and lx_state must
be reset to the working state since controller is powered at this stage.

Same logic applied for stop callback.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 15adc7d..f5fc13b 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2318,8 +2318,9 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
 
spin_lock_irqsave(&hsotg->lock, flags);
-
+   hsotg->lx_state = DWC2_L0;
hcd->state = HC_STATE_RUNNING;
+   set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
if (dwc2_is_device_mode(hsotg)) {
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -2350,6 +2351,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 
spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hcd_stop(hsotg);
+   hsotg->lx_state = DWC2_L3;
+   hcd->state = HC_STATE_HALT;
+   clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irqrestore(&hsotg->lock, flags);
 
usleep_range(1000, 3000);
-- 
2.3.3

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


[PATCH v1 Resend] usb: dwc2: gadget: fix a memory use-after-free bug

2015-09-29 Thread Mian Yousaf Kaukab
From: Yunzhi Li 

When dwc2_hsotg_handle_unaligned_buf_complete() hs_req->req.buf
already destroyed, in dwc2_hsotg_unmap_dma(), it touches
hs_req->req.dma again, so dwc2_hsotg_unmap_dma() should be called
before dwc2_hsotg_handle_unaligned_buf_complete(). Otherwise, it
will cause a bad_page BUG, when allocate this memory page next
time.

This bug led to the following crash:

BUG: Bad page state in process swapper/0  pfn:2bdbc
[   26.820440] page:eed76780 count:0 mapcount:0 mapping:  (null) index:0x0
[   26.854710] page flags: 0x200(arch_1)
[   26.885836] page dumped because: PAGE_FLAGS_CHECK_AT_PREP flag set
[   26.919179] bad because of flags:
[   26.948917] page flags: 0x200(arch_1)
[   26.979100] Modules linked in:
[   27.008401] CPU: 0 PID: 0 Comm: swapper/0 Tainted: G W3.14.0 #17
[   27.041816] [] (unwind_backtrace) from [] 
(show_stack+0x20/0x24)
[   27.076108] [] (show_stack) from [] 
(dump_stack+0x70/0x8c)
[   27.110246] [] (dump_stack) from [] (bad_page+0xfc/0x12c)
[   27.143958] [] (bad_page) from [] 
(get_page_from_freelist+0x3e4/0x50c)
[   27.179298] [] (get_page_from_freelist) from [] 
(__alloc_pages_nodemask)
[   27.216296] [] (__alloc_pages_nodemask) from [] 
(__get_free_pages+0x20/)
[   27.252326] [] (__get_free_pages) from [] 
(kmalloc_order_trace+0x34/0xa)
[   27.288295] [] (kmalloc_order_trace) from [] 
(__kmalloc+0x40/0x1ac)
[   27.323751] [] (__kmalloc) from [] 
(dwc2_hsotg_ep_queue.isra.12+0x7c/0x1)
[   27.359937] [] (dwc2_hsotg_ep_queue.isra.12) from [] 
(dwc2_hsotg_ep_queue)
[   27.397478] [] (dwc2_hsotg_ep_queue_lock) from [] 
(rx_submit+0xfc/0x164)
[   27.433619] [] (rx_submit) from [] 
(rx_complete+0x22c/0x230)
[   27.468872] [] (rx_complete) from [] 
(dwc2_hsotg_complete_request+0xfc/0)
[   27.506240] [] (dwc2_hsotg_complete_request) from [] 
(dwc2_hsotg_handle_o)
[   27.545401] [] (dwc2_hsotg_handle_outdone) from [] 
(dwc2_hsotg_epint+0x2c)
[   27.583689] [] (dwc2_hsotg_epint) from [] 
(dwc2_hsotg_irq+0x1dc/0x4ac)
[   27.621041] [] (dwc2_hsotg_irq) from [] 
(handle_irq_event_percpu+0x70/0x)
[   27.659066] [] (handle_irq_event_percpu) from [] 
(handle_irq_event+0x4c)
[   27.697322] [] (handle_irq_event) from [] 
(handle_fasteoi_irq+0xc8/0x11)
[   27.735451] [] (handle_fasteoi_irq) from [] 
(generic_handle_irq+0x30/0x)
[   27.773918] [] (generic_handle_irq) from [] 
(__handle_domain_irq+0x84/0)
[   27.812018] [] (__handle_domain_irq) from [] 
(gic_handle_irq+0x48/0x6c)
[   27.849695] [] (gic_handle_irq) from [] 
(__irq_svc+0x40/0x50)
[   27.886907] Exception stack(0xc0d01ee0 to 0xc0d01f28)

Acked-by: John Youn 
Tested-by: Heiko Stuebner 
Tested-by: Jeffy Chen 
Signed-off-by: Yunzhi Li 
---
Resending on Yunzhi's behalf since he is travelling.

 drivers/usb/dwc2/gadget.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 12ac879..5755e65 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1390,14 +1390,14 @@ static void dwc2_hsotg_complete_request(struct 
dwc2_hsotg *hsotg,
if (hs_req->req.status == -EINPROGRESS)
hs_req->req.status = result;
 
+   if (using_dma(hsotg))
+   dwc2_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
+
dwc2_hsotg_handle_unaligned_buf_complete(hsotg, hs_ep, hs_req);
 
hs_ep->req = NULL;
list_del_init(&hs_req->queue);
 
-   if (using_dma(hsotg))
-   dwc2_hsotg_unmap_dma(hsotg, hs_ep, hs_req);
-
/*
 * call the complete request with the locks off, just in case the
 * request tries to queue more work for this endpoint.
-- 
2.3.3

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


[PATCH v3 32/32] usb: dwc2: exit hibernation on session request

2015-09-29 Thread Mian Yousaf Kaukab
Controller enters hibernation through suspend interrupt on
disconnection. On connection, session request interrupt is generated.
dwc2 must exit hibernation and restore state from this interrupt
before continuing.

In host mode, exit from hibernation is handled by bus_resume function.

Signed-off-by: Mian Yousaf Kaukab 
Signed-off-by: Gregory Herrero 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core_intr.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index d8a5400..27daa42 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -313,16 +313,28 @@ static void dwc2_handle_conn_id_status_change_intr(struct 
dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 {
-   dev_dbg(hsotg->dev, "++Session Request Interrupt++\n");
+   int ret;
+
+   dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
+   hsotg->lx_state);
 
/* Clear interrupt */
dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
 
-   /*
-* Report disconnect if there is any previous session established
-*/
-   if (dwc2_is_device_mode(hsotg))
+   if (dwc2_is_device_mode(hsotg)) {
+   if (hsotg->lx_state == DWC2_L2) {
+   ret = dwc2_exit_hibernation(hsotg, true);
+   if (ret && (ret != -ENOTSUPP))
+   dev_err(hsotg->dev,
+   "exit hibernation failed\n");
+   }
+
+   /*
+* Report disconnect if there is any previous session
+* established
+*/
dwc2_hsotg_disconnect(hsotg);
+   }
 }
 
 /*
-- 
2.3.3

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


[PATCH v3 21/32] usb: dwc2: gadget: don't modify pullup state in host mode

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Modifying the pullup state during host mode trig a new enumeration
of attached device. Thus, avoid modifying pullup in host mode.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index df8d599..6260ad4 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3116,7 +3116,14 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, 
int is_on)
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags = 0;
 
-   dev_dbg(hsotg->dev, "%s: is_on: %d\n", __func__, is_on);
+   dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on,
+   hsotg->op_state);
+
+   /* Don't modify pullup state while in host mode */
+   if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
+   hsotg->enabled = is_on;
+   return 0;
+   }
 
mutex_lock(&hsotg->init_mutex);
spin_lock_irqsave(&hsotg->lock, flags);
-- 
2.3.3

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


[PATCH v3 19/32] usb: dwc2: gadget: initialize op_state for peripheral only configuration

2015-09-29 Thread Mian Yousaf Kaukab
ID status change interrupt will not be handled in peripheral only
configuration. So initialize op_state during gadget init.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index e4a4b18..df8d599 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3447,6 +3447,8 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
hsotg->gadget.name = dev_name(dev);
if (hsotg->dr_mode == USB_DR_MODE_OTG)
hsotg->gadget.is_otg = 1;
+   else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 
/*
 * Force Device mode before initialization.
-- 
2.3.3

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


[PATCH v3 23/32] usb: dwc2: gadget: abort core init if core_reset fails

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

No point of continue with initialization if core is not in a sane
state.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 48a26cb..01858b8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2283,7 +2283,8 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
u32 val;
 
if (!is_usb_reset)
-   dwc2_hsotg_corereset(hsotg);
+   if (dwc2_hsotg_corereset(hsotg))
+   return;
 
/*
 * we must now enable ep0 ready for host detection and then
-- 
2.3.3

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


[PATCH v3 22/32] usb: dwc2: gadget: set op_state in vbus_session call

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Some device may have external id pin control enabled, so op_state
will not be set on id pin interrupt change.
Thus, ensure op_state is set to peripheral during vbus detection.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 6260ad4..48a26cb 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3153,6 +3153,7 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
spin_lock_irqsave(&hsotg->lock, flags);
 
if (is_active) {
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
/*
 * If controller is hibernated, it must exit from hibernation
 * before being initialized
-- 
2.3.3

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


[PATCH v3 31/32] usb: dwc2: gadget: handle reset interrupt before endpoint interrupts

2015-09-29 Thread Mian Yousaf Kaukab
If system is loaded, reset, enum-done and setup interrupts can occur
at the same time. Current interrupt handling sequence will handle
setup packet's interrupt before handling reset interrupt. Which will
break the enumeration process. Correct sequence is to handle reset,
enum-done and then any other endpoint interrupts.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 60 +++
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index f853bd1..8cfc0fa 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2456,6 +2456,36 @@ irq_retry:
 
gintsts &= gintmsk;
 
+   if (gintsts & GINTSTS_RESETDET) {
+   dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
+
+   dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
+
+   /* This event must be used only if controller is suspended */
+   if (hsotg->lx_state == DWC2_L2) {
+   dwc2_exit_hibernation(hsotg, true);
+   hsotg->lx_state = DWC2_L0;
+   }
+   }
+
+   if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
+
+   u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+   u32 connected = hsotg->connected;
+
+   dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
+   dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
+   dwc2_readl(hsotg->regs + GNPTXSTS));
+
+   dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
+
+   /* Report disconnection if it is not already done. */
+   dwc2_hsotg_disconnect(hsotg);
+
+   if (usb_status & GOTGCTL_BSESVLD && connected)
+   dwc2_hsotg_core_init_disconnected(hsotg, true);
+   }
+
if (gintsts & GINTSTS_ENUMDONE) {
dwc2_writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
 
@@ -2487,36 +2517,6 @@ irq_retry:
}
}
 
-   if (gintsts & GINTSTS_RESETDET) {
-   dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
-
-   dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
-
-   /* This event must be used only if controller is suspended */
-   if (hsotg->lx_state == DWC2_L2) {
-   dwc2_exit_hibernation(hsotg, true);
-   hsotg->lx_state = DWC2_L0;
-   }
-   }
-
-   if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
-
-   u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
-   u32 connected = hsotg->connected;
-
-   dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
-   dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
-   dwc2_readl(hsotg->regs + GNPTXSTS));
-
-   dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
-
-   /* Report disconnection if it is not already done. */
-   dwc2_hsotg_disconnect(hsotg);
-
-   if (usb_status & GOTGCTL_BSESVLD && connected)
-   dwc2_hsotg_core_init_disconnected(hsotg, true);
-   }
-
/* check both FIFOs */
 
if (gintsts & GINTSTS_NPTXFEMP) {
-- 
2.3.3

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


[PATCH v3 28/32] usb: dwc2: gadget: only reset core after addressed state

2015-09-29 Thread Mian Yousaf Kaukab
There is a 200ms guard period to avoid unnecessary resets of the dwc2
ip. This delay sometimes prove to be too large when usbcv is run with
an ehci host. dwc2 only needs to be reset after addressed state.
Change the logic to reset ip after addressed state.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.h   |  2 --
 drivers/usb/dwc2/gadget.c | 11 +++
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 27e6fbf..8c56054 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -688,7 +688,6 @@ struct dwc2_hregs_backup {
  * @ctrl_req:   Request for EP0 control packets.
  * @ep0_state:  EP0 control transfers state
  * @test_mode:  USB test mode requested by the host
- * @last_rst:   Time of last reset
  * @eps:The endpoints being supplied to the gadget framework
  * @g_using_dma:  Indicate if dma usage is enabled
  * @g_rx_fifo_sz: Contains rx fifo size value
@@ -832,7 +831,6 @@ struct dwc2_hsotg {
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
-   unsigned long last_rst;
struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
u32 g_using_dma;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index ba55f09..146bc99 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2416,7 +2416,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
/* must be at-least 3ms to allow bus to see disconnect */
mdelay(3);
 
-   hsotg->last_rst = jiffies;
hsotg->lx_state = DWC2_L0;
 }
 
@@ -2500,6 +2499,7 @@ irq_retry:
if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
 
u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+   u32 connected = hsotg->connected;
 
dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
@@ -2510,13 +2510,8 @@ irq_retry:
/* Report disconnection if it is not already done. */
dwc2_hsotg_disconnect(hsotg);
 
-   if (usb_status & GOTGCTL_BSESVLD) {
-   if (time_after(jiffies, hsotg->last_rst +
-  msecs_to_jiffies(200))) {
-
-   dwc2_hsotg_core_init_disconnected(hsotg, true);
-   }
-   }
+   if (usb_status & GOTGCTL_BSESVLD && connected)
+   dwc2_hsotg_core_init_disconnected(hsotg, true);
}
 
/* check both FIFOs */
-- 
2.3.3

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


[PATCH v3 25/32] usb: dwc2: gadget: print complete setup packet

2015-09-29 Thread Mian Yousaf Kaukab
wIndex field was missing. Also print in natural order instead of
Req first, so that its easier to compare for example against
bus analyzer logs.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 92b6d25..0c97ca8 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1202,9 +1202,10 @@ static void dwc2_hsotg_process_control(struct dwc2_hsotg 
*hsotg,
int ret = 0;
u32 dcfg;
 
-   dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n",
-ctrl->bRequest, ctrl->bRequestType,
-ctrl->wValue, ctrl->wLength);
+   dev_dbg(hsotg->dev,
+   "ctrl Type=%02x, Req=%02x, V=%04x, I=%04x, L=%04x\n",
+   ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+   ctrl->wIndex, ctrl->wLength);
 
if (ctrl->wLength == 0) {
ep0->dir_in = 1;
-- 
2.3.3

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


[PATCH v3 26/32] usb: dwc2: gadget: stop current transfer on dequeue

2015-09-29 Thread Mian Yousaf Kaukab
If the request being dequeued is already started, disable endpoint
to stop the transfer and then call dwc2_hsotg_complete_request().
Endpoint will be re-enabled on next call to dwc2_hsotg_start_req().

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 77 +++
 1 file changed, 77 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 0c97ca8..3556685 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2822,6 +2822,79 @@ static bool on_list(struct dwc2_hsotg_ep *ep, struct 
dwc2_hsotg_req *test)
return false;
 }
 
+static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
+   u32 bit, u32 timeout)
+{
+   u32 i;
+
+   for (i = 0; i < timeout; i++) {
+   if (dwc2_readl(hs_otg->regs + reg) & bit)
+   return 0;
+   udelay(1);
+   }
+
+   return -ETIMEDOUT;
+}
+
+static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
+   struct dwc2_hsotg_ep *hs_ep)
+{
+   u32 epctrl_reg;
+   u32 epint_reg;
+
+   epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) :
+  DOEPCTL(hs_ep->index);
+   epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) :
+   DOEPINT(hs_ep->index);
+
+   dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__,
+   hs_ep->name);
+   if (hs_ep->dir_in) {
+   __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
+   /* Wait for Nak effect */
+   if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
+   DXEPINT_INEPNAKEFF, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout DIEPINT.NAKEFF\n", __func__);
+   } else {
+   /* Clear any pending nak effect interrupt */
+   dwc2_writel(GINTSTS_GINNAKEFF, hsotg->regs + GINTSTS);
+
+   __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+
+   /* Wait for global nak to take effect */
+   if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+   GINTSTS_GINNAKEFF, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout GINTSTS.GINNAKEFF\n", __func__);
+   }
+
+   /* Disable ep */
+   __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
+
+   /* Wait for ep to be disabled */
+   if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout DOEPCTL.EPDisable\n", __func__);
+
+   if (hs_ep->dir_in) {
+   if (hsotg->dedicated_fifos) {
+   dwc2_writel(GRSTCTL_TXFNUM(hs_ep->fifo_index) |
+   GRSTCTL_TXFFLSH, hsotg->regs + GRSTCTL);
+   /* Wait for fifo flush */
+   if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL,
+   GRSTCTL_TXFFLSH, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout flushing fifos\n",
+   __func__);
+   }
+   /* TODO: Flush shared tx fifo */
+   } else {
+   /* Remove global NAKs */
+   __bic32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+   }
+}
+
 /**
  * dwc2_hsotg_ep_dequeue - dequeue given endpoint
  * @ep: The endpoint to dequeue.
@@ -2843,6 +2916,10 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, 
struct usb_request *req)
return -EINVAL;
}
 
+   /* Dequeue already started request */
+   if (req == &hs_ep->req->req)
+   dwc2_hsotg_ep_stop_xfr(hs, hs_ep);
+
dwc2_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
spin_unlock_irqrestore(&hs->lock, flags);
 
-- 
2.3.3

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


[PATCH v3 24/32] usb: dwc2: gadget: ignore stall check for ep0

2015-09-29 Thread Mian Yousaf Kaukab
dwc2_hsotg_start_req starts a request only if endpoint is not stalled.
Ignore this check for ep0 as core will clear DOEPCTL0.Stall after
sending stall handshake. Prepare instead for receiving next setup
packet.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 01858b8..92b6d25 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -552,7 +552,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
/* If endpoint is stalled, we will restart request later */
ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
 
-   if (ctrl & DXEPCTL_STALL) {
+   if (index && ctrl & DXEPCTL_STALL) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
return;
}
-- 
2.3.3

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


[PATCH v3 20/32] usb: dwc2: force dr_mode in case of configuration mismatch

2015-09-29 Thread Mian Yousaf Kaukab
If dual role configuration is not selected, check and force dr_mode
based on the selected configuration.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/platform.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index ed7a78e..0945e21 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -368,6 +368,17 @@ static int dwc2_driver_probe(struct platform_device *dev)
(unsigned long)res->start, hsotg->regs);
 
hsotg->dr_mode = usb_get_dr_mode(&dev->dev);
+   if (IS_ENABLED(CONFIG_USB_DWC2_HOST) &&
+   hsotg->dr_mode != USB_DR_MODE_HOST) {
+   hsotg->dr_mode = USB_DR_MODE_HOST;
+   dev_warn(hsotg->dev,
+   "Configuration mismatch. Forcing host mode\n");
+   } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) &&
+   hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
+   hsotg->dr_mode = USB_DR_MODE_PERIPHERAL;
+   dev_warn(hsotg->dev,
+   "Configuration mismatch. Forcing peripheral mode\n");
+   }
 
retval = dwc2_lowlevel_hw_init(hsotg);
if (retval)
-- 
2.3.3

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


[PATCH v3 30/32] usb: dwc2: gadget: exit hibernation before power down

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

When disconnecting cable, controller will detect a suspend condition
and enter partial power down. If vbus_session is called by the phy
driver during hibernation, make sure controller exit hibernation
before it is accessed.

Signed-off-by: Jianqiang Tang 
Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 8414f1d..f853bd1 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3229,14 +3229,15 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
dev_dbg(hsotg->dev, "%s: is_active: %d\n", __func__, is_active);
spin_lock_irqsave(&hsotg->lock, flags);
 
+   /*
+* If controller is hibernated, it must exit from hibernation
+* before being initialized / de-initialized
+*/
+   if (hsotg->lx_state == DWC2_L2)
+   dwc2_exit_hibernation(hsotg, false);
+
if (is_active) {
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
-   /*
-* If controller is hibernated, it must exit from hibernation
-* before being initialized
-*/
-   if (hsotg->lx_state == DWC2_L2)
-   dwc2_exit_hibernation(hsotg, false);
 
dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
-- 
2.3.3

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


[PATCH v3 29/32] usb: dwc2: gadget: unmask idstschng interrupt only if controller supports it

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

idstschng interrupt should not be used when id pin control is
external. This is already handled on dwc2 host part. Fix it on gadget
part as well.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 146bc99..8414f1d 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2281,6 +2281,7 @@ static int dwc2_hsotg_corereset(struct dwc2_hsotg *hsotg)
 void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
bool is_usb_reset)
 {
+   u32 intmsk;
u32 val;
 
/* Kill any ep0 requests as controller will be reinitialized */
@@ -2312,14 +2313,16 @@ void dwc2_hsotg_core_init_disconnected(struct 
dwc2_hsotg *hsotg,
 
/* Clear any pending interrupts */
dwc2_writel(0x, hsotg->regs + GINTSTS);
-
-   dwc2_writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
+   intmsk = GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF |
-   GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST |
-   GINTSTS_RESETDET | GINTSTS_ENUMDONE |
-   GINTSTS_OTGINT | GINTSTS_USBSUSP |
-   GINTSTS_WKUPINT,
-   hsotg->regs + GINTMSK);
+   GINTSTS_USBRST | GINTSTS_RESETDET |
+   GINTSTS_ENUMDONE | GINTSTS_OTGINT |
+   GINTSTS_USBSUSP | GINTSTS_WKUPINT;
+
+   if (hsotg->core_params->external_id_pin_ctl <= 0)
+   intmsk |= GINTSTS_CONIDSTSCHNG;
+
+   dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 
if (using_dma(hsotg))
dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
-- 
2.3.3

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


[PATCH v3 27/32] usb: dwc2: gadget: kill ep0 requests before reinitializing core

2015-09-29 Thread Mian Yousaf Kaukab
Make sure there are no requests pending on ep0 before reinitializing
core. Otherwise, dwc2_hsotg_enqueue_setup will fail afterwards.

Also, take hsotg->lock before calling
dwc2_hsotg_core_init_disconnected() from dwc2_conn_id_status_change()
as dwc2_hsotg_complete_request() expect lock to be held.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 8 +++-
 drivers/usb/dwc2/hcd.c| 3 +++
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 3556685..ba55f09 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2283,6 +2283,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
 {
u32 val;
 
+   /* Kill any ep0 requests as controller will be reinitialized */
+   kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
+
if (!is_usb_reset)
if (dwc2_hsotg_corereset(hsotg))
return;
@@ -2511,9 +2514,6 @@ irq_retry:
if (time_after(jiffies, hsotg->last_rst +
   msecs_to_jiffies(200))) {
 
-   kill_all_requests(hsotg, hsotg->eps_out[0],
- -ECONNRESET);
-
dwc2_hsotg_core_init_disconnected(hsotg, true);
}
}
@@ -3240,8 +3240,6 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
if (hsotg->lx_state == DWC2_L2)
dwc2_exit_hibernation(hsotg, false);
 
-   /* Kill any ep0 requests as controller will be reinitialized */
-   kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
dwc2_hsotg_core_connect(hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 15a1e62..af4e4a2 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1355,6 +1355,7 @@ static void dwc2_conn_id_status_change(struct work_struct 
*work)
wf_otg);
u32 count = 0;
u32 gotgctl;
+   unsigned long flags;
 
dev_dbg(hsotg->dev, "%s()\n", __func__);
 
@@ -1382,7 +1383,9 @@ static void dwc2_conn_id_status_change(struct work_struct 
*work)
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
dwc2_core_init(hsotg, false, -1);
dwc2_enable_global_interrupts(hsotg);
+   spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hsotg_core_init_disconnected(hsotg, false);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_hsotg_core_connect(hsotg);
} else {
/* A-Device connector (Host Mode) */
-- 
2.3.3

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


[PATCH v3 15/32] usb: dwc2: host: correctly dump urb isochronous descriptors

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Print urb->iso_frame_desc.status after it has been updated using
dwc2_hcd_urb_get_iso_desc_status().

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 65044da..397bb7d 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2227,11 +2227,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct 
dwc2_qtd *qtd,
 usb_pipein(urb->pipe) ? "IN" : "OUT", status,
 urb->actual_length);
 
-   if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
-   for (i = 0; i < urb->number_of_packets; i++)
-   dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
-i, urb->iso_frame_desc[i].status);
-   }
 
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
@@ -2244,6 +2239,12 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct 
dwc2_qtd *qtd,
}
}
 
+   if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
+   for (i = 0; i < urb->number_of_packets; i++)
+   dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
+i, urb->iso_frame_desc[i].status);
+   }
+
urb->status = status;
if (!status) {
if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
-- 
2.3.3

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


[PATCH v3 13/32] usb: dwc2: host: clear pending interrupts prior hibernation

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

If an interrupt rises during hibernation process, dwc2 will assert
interrupt line to interrupt controller. If interrupt is level
sensitive, interrupt handler will be called in a loop because dwc2
will not be able to clear it while controller is hibernated.
Thus, clear all controller interrupts before hibernation entry.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 c5e0a45..bf5e951 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -398,6 +398,12 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
}
}
 
+   /*
+* Clear any pending interrupts since dwc2 will not be able to
+* clear them after entering hibernation.
+*/
+   dwc2_writel(0x, hsotg->regs + GINTSTS);
+
/* Put the controller in low power state */
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
-- 
2.3.3

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


[PATCH v3 14/32] usb: dwc2: host: wait 3ms for controller stabilization

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Some high speed mass storage devices fail to enumerate with following
error:

Cannot enable port %i.  Maybe the USB cable is bad?

This happens only when the device is plugged while the controller
is in hibernation state. After exiting hibernation, the controller
detects the device as a low speed device and fail to enumerate it.

Problem occurs only if HPRT0.PWR bit is programmed in a too short
delay after exiting hibernation. Dumping hprt register in
_dwc2_hcd_resume() directly after dwc2_exit_hibernation() shows that
HPRT0.LNSTS (D+/D- level) becomes valid approximately 2ms after
exiting hibernation.

Since dwc2_exit_hibernation() is called from atomic context, keep the
delay out of this function.

Delay value is experimental and not mentioned in Synopsys
documentation. To be on the safe side 3ms delay is used.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 de9d2e2..65044da 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2472,6 +2472,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_port_resume(hsotg);
} else {
+   /* Wait for controller to correctly update D+/D- level */
+   usleep_range(3000, 5000);
+
/*
 * Clear Port Enable and Port Status changes.
 * Enable Port Power.
@@ -2479,7 +2482,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
dwc2_writel(HPRT0_PWR | HPRT0_CONNDET |
HPRT0_ENACHG, hsotg->regs + HPRT0);
/* Wait for controller to detect Port Connect */
-   mdelay(5);
+   usleep_range(5000, 7000);
}
 
return ret;
-- 
2.3.3

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


[PATCH v3 10/32] usb: dwc2: host: disconnect hcd prior stopping it

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

In case controller is asked to stop while devices are connected,
disconnect all devices and clean up before stopping.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 856e21c..257f957 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2350,7 +2350,12 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
unsigned long flags;
 
+   /* Wait for interrupt processing to finish */
+   synchronize_irq(hcd->irq);
+
spin_lock_irqsave(&hsotg->lock, flags);
+   /* Ensure hcd is disconnected */
+   dwc2_hcd_disconnect(hsotg);
dwc2_hcd_stop(hsotg);
hsotg->lx_state = DWC2_L3;
hcd->state = HC_STATE_HALT;
-- 
2.3.3

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


[PATCH v3 08/32] usb: dwc2: host: resume only if bus is suspended

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Port can be resumed in bus_resume callback.
In this case, there is no need to drive resume a second time
when hcd ask for it.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 65ae0a39..856e21c 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1571,7 +1571,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, 
u16 typereq,
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
 
-   dwc2_port_resume(hsotg);
+   if (hsotg->bus_suspended)
+   dwc2_port_resume(hsotg);
break;
 
case USB_PORT_FEAT_POWER:
-- 
2.3.3

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


[PATCH v3 18/32] usb: dwc2: gadget: ensure lx_state corresponds to current state

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Correctly update lx_state on gadget connection and disconnection.
When usb cable is disconnected, lx_state must be updated to L3 as
controller could be in power off state.
When usb cable is connected, lx_state must be updated to L0 as
controller is powered.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/gadget.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 12ac879..e4a4b18 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2185,6 +2185,7 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
}
 
call_gadget(hsotg, disconnect);
+   hsotg->lx_state = DWC2_L3;
 }
 
 /**
@@ -2411,6 +2412,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
mdelay(3);
 
hsotg->last_rst = jiffies;
+   hsotg->lx_state = DWC2_L0;
 }
 
 static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
@@ -2510,7 +2512,6 @@ irq_retry:
kill_all_requests(hsotg, hsotg->eps_out[0],
  -ECONNRESET);
 
-   hsotg->lx_state = DWC2_L0;
dwc2_hsotg_core_init_disconnected(hsotg, true);
}
}
@@ -3149,10 +3150,9 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
 * If controller is hibernated, it must exit from hibernation
 * before being initialized
 */
-   if (hsotg->lx_state == DWC2_L2) {
+   if (hsotg->lx_state == DWC2_L2)
dwc2_exit_hibernation(hsotg, false);
-   hsotg->lx_state = DWC2_L0;
-   }
+
/* Kill any ep0 requests as controller will be reinitialized */
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
dwc2_hsotg_core_init_disconnected(hsotg, false);
-- 
2.3.3

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


[PATCH v3 09/32] usb: dwc2: host: reset frame number after suspend

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Frame number is reset in hardware after exiting hibernation.
Thus, reset frame_number and ensure qh are queued with correct
sched_frame.

Otherwise, qh->sched_frame may be too high compared to
current frame number (which is 0). This can delay addition of qh in
the list of transfers until frame number reaches qh->sched_frame.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.c  | 1 +
 drivers/usb/dwc2/hcd_queue.c | 8 
 2 files changed, 9 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 0bfc987..f5c3120 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -116,6 +116,7 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg 
*hsotg)
 
dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);
dwc2_writel(hr->hfir, hsotg->regs + HFIR);
+   hsotg->frame_number = 0;
 
return 0;
 }
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 712977f..801bd9d 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -583,6 +583,14 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct 
dwc2_qh *qh)
/* QH already in a schedule */
return 0;
 
+   if (!dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number) &&
+   !hsotg->frame_number) {
+   dev_dbg(hsotg->dev,
+   "reset frame number counter\n");
+   qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
+   SCHEDULE_SLOP);
+   }
+
/* Add the new QH to the appropriate schedule */
if (dwc2_qh_is_non_per(qh)) {
/* Always start in inactive schedule */
-- 
2.3.3

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


[PATCH v3 16/32] usb: dwc2: host: use correct frame number during qh init

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

On first qh initialization, hsotg->frame_number is not corresponding
to reality. So read it from host controller to get correct value.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd_queue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 801bd9d..7d8d06c 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -106,6 +106,9 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct 
dwc2_qh *qh,
USB_SPEED_HIGH : dev_speed, qh->ep_is_in,
qh->ep_type == USB_ENDPOINT_XFER_ISOC,
bytecount));
+
+   /* Ensure frame_number corresponds to the reality */
+   hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
/* Start in a slightly future (micro)frame */
qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
 SCHEDULE_SLOP);
-- 
2.3.3

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


[PATCH v3 12/32] usb: dwc2: host: disable interrupt during stop

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Disable host interrupts before synchronising dwc2 irq.
So that interrupts are not generated once controller is stopped.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 257f957..de9d2e2 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2350,6 +2350,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
unsigned long flags;
 
+   /* Turn off all host-specific interrupts */
+   dwc2_disable_host_interrupts(hsotg);
+
/* Wait for interrupt processing to finish */
synchronize_irq(hcd->irq);
 
-- 
2.3.3

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


[PATCH v3 17/32] usb: dwc2: host: kill remaining urbs using -ECONNRESET status

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

On a disconnect, dwc2 will kill all remaining urbs from qh list.
urbs are given back to hcd with -ETIMEDOUT status.
Some usb device driver, like mass storage, will unlink all urbs
using usb_hcd_unlink_urb when receiving a negative status different
from -ECONNRESET.
The following flow will then happen:
dwc2_hcd_disconnect()
-> dwc2_kill_all_urbs() try to kill first pending urb.
-> dwc2_host_complete(-ETIMEDOUT)
-> usb_hcd_giveback_urb(-ETIMEDOUT)
-> sg_complete()
-> usb_unlink_urb()
-> usb_put_dev(urb->dev)
-> dwc2_kill_all_urbs() try to kill next pending urb.
-> dwc2_host_complete(-ETIMEDOUT)
-> usb_hcd_giveback_urb(-ETIMEDOUT)
-> NULL pointer dereferencing because urb->dev has been freed for all
urbs of this device.

The root cause of this NULL pointer is to call call usb_unlink_urb()
while we are killing all urbs. To avoid this return urb with
-ECONNRESET status

This issue usually happens while removing mass storage device during
transfer.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 397bb7d..15a1e62 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -134,7 +134,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg 
*hsotg,
list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
 qtd_list_entry) {
-   dwc2_host_complete(hsotg, qtd, -ETIMEDOUT);
+   dwc2_host_complete(hsotg, qtd, -ECONNRESET);
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
}
}
-- 
2.3.3

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


[PATCH v3 11/32] usb: dwc2: host: add disconnect interrupt to host only interrupts

2015-09-29 Thread Mian Yousaf Kaukab
GINTSTS.DisconnInt is host only interrupt and should be disable after
dwc2_disable_host_interrupts is called.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index f5c3120..c5e0a45 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -857,7 +857,8 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
 
/* Enable host mode interrupts without disturbing common interrupts */
intmsk = dwc2_readl(hsotg->regs + GINTMSK);
-   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT;
+   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT |
+   GINTSTS_DISCONNINT;
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
@@ -872,7 +873,7 @@ void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
 
/* Disable host mode interrupts without disturbing common interrupts */
intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT |
-   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP);
+   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | GINTSTS_DISCONNINT);
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
-- 
2.3.3

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


[PATCH v3 07/32] usb: dwc2: host: ignore wakeup interrupt if hibernation supported

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

If hibernation is supported, resume of devices will be handled in
bus_resume callback.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core_intr.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index 3275310..d8a5400 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -356,6 +356,10 @@ static void dwc2_handle_wakeup_detected_intr(struct 
dwc2_hsotg *hsotg)
/* Change to L0 state */
hsotg->lx_state = DWC2_L0;
} else {
+   if (hsotg->core_params->hibernation) {
+   dwc2_writel(GINTSTS_WKUPINT, hsotg->regs + GINTSTS);
+   return;
+   }
if (hsotg->lx_state != DWC2_L1) {
u32 pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
-- 
2.3.3

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


[PATCH v3 01/32] usb: dwc2: host: don't clear hprt0 status bits when exiting hibernation

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

When entering hibernation hprt0 must be read using dwc2_read_hprt0().
Otherwise, any set hprt0 status bits will be cleared when restoring
hprt0 on exit from hibernation.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index fc0521a..0bfc987 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -78,7 +78,7 @@ static int dwc2_backup_host_registers(struct dwc2_hsotg 
*hsotg)
for (i = 0; i < hsotg->core_params->host_channels; ++i)
hr->hcintmsk[i] = dwc2_readl(hsotg->regs + HCINTMSK(i));
 
-   hr->hprt0 = dwc2_readl(hsotg->regs + HPRT0);
+   hr->hprt0 = dwc2_read_hprt0(hsotg);
hr->hfir = dwc2_readl(hsotg->regs + HFIR);
hr->valid = true;
 
-- 
2.3.3

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


[PATCH v3 05/32] usb: dwc2: host: update hcd and lx_state during start/stop callbacks

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

During hcd initialization, hardware accessible flag and lx_state must
be reset to the working state since controller is powered at this stage.

Same logic applied for stop callback.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 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 459b441..65ae0a39 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2318,8 +2318,9 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
 
spin_lock_irqsave(&hsotg->lock, flags);
-
+   hsotg->lx_state = DWC2_L0;
hcd->state = HC_STATE_RUNNING;
+   set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
if (dwc2_is_device_mode(hsotg)) {
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -2350,6 +2351,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 
spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hcd_stop(hsotg);
+   hsotg->lx_state = DWC2_L3;
+   hcd->state = HC_STATE_HALT;
+   clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irqrestore(&hsotg->lock, flags);
 
usleep_range(1000, 3000);
-- 
2.3.3

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


[PATCH v3 06/32] usb: dwc2: host: avoid resetting lx_state to L3 during disconnect

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

When a device is disconnected, lx_state must not be changed since the
device may be disconnected whereas controller is still powered.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core_intr.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index a6b1613..3275310 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -387,9 +387,6 @@ static void dwc2_handle_disconnect_intr(struct dwc2_hsotg 
*hsotg)
if (hsotg->op_state == OTG_STATE_A_HOST)
dwc2_hcd_disconnect(hsotg);
 
-   /* Change to L3 (OFF) state */
-   hsotg->lx_state = DWC2_L3;
-
dwc2_writel(GINTSTS_DISCONNINT, hsotg->regs + GINTSTS);
 }
 
-- 
2.3.3

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


[PATCH v3 04/32] usb: dwc2: host: enter hibernation during bus suspend

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Disable controller power and enter hibernation when usb bus is
suspended. A phy driver is required to disable the power of the
controller and detect remote-wakeup or disconnection since the
controller will not be able to detect these in this state.

Once the phy driver detects bus activity, it must call
usb_hcd_resume_root_hub.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 140 -
 1 file changed, 128 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 490ecb7..459b441 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1464,11 +1464,17 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
 
hsotg->bus_suspended = 1;
 
-   /* Suspend the Phy Clock */
-   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
-   pcgctl |= PCGCTL_STOPPCLK;
-   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
-   udelay(10);
+   /*
+* If hibernation is supported, Phy clock will be suspended
+* after registers are backuped.
+*/
+   if (!hsotg->core_params->hibernation) {
+   /* Suspend the Phy Clock */
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl |= PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   udelay(10);
+   }
 
/* For HNP the bus must be suspended for at least 200ms */
if (dwc2_host_is_b_hnp_enabled(hsotg)) {
@@ -1491,11 +1497,16 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
u32 hprt0;
u32 pcgctl;
 
-   /* Resume the Phy Clock */
-   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
-   pcgctl &= ~PCGCTL_STOPPCLK;
-   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
-   usleep_range(2, 4);
+   /*
+* If hibernation is supported, Phy clock is already resumed
+* after registers restore.
+*/
+   if (!hsotg->core_params->hibernation) {
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl &= ~PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   usleep_range(2, 4);
+   }
 
spin_lock_irqsave(&hsotg->lock, flags);
hprt0 = dwc2_read_hprt0(hsotg);
@@ -2347,17 +2358,122 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 {
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+   unsigned long flags;
+   int ret = 0;
+   u32 hprt0;
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+
+   if (hsotg->lx_state != DWC2_L0)
+   goto unlock;
+
+   if (!HCD_HW_ACCESSIBLE(hcd))
+   goto unlock;
+
+   if (!hsotg->core_params->hibernation)
+   goto skip_power_saving;
+
+   /*
+* Drive USB suspend and disable port Power
+* if usb bus is not suspended.
+*/
+   if (!hsotg->bus_suspended) {
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 |= HPRT0_SUSP;
+   hprt0 &= ~HPRT0_PWR;
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   }
+
+   /* Enter hibernation */
+   ret = dwc2_enter_hibernation(hsotg);
+   if (ret) {
+   if (ret != -ENOTSUPP)
+   dev_err(hsotg->dev,
+   "enter hibernation failed\n");
+   goto skip_power_saving;
+   }
+
+   /* Ask phy to be suspended */
+   if (!IS_ERR_OR_NULL(hsotg->uphy)) {
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+   usb_phy_set_suspend(hsotg->uphy, true);
+   spin_lock_irqsave(&hsotg->lock, flags);
+   }
+
+   /* After entering hibernation, hardware is no more accessible */
+   clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
+skip_power_saving:
hsotg->lx_state = DWC2_L2;
-   return 0;
+unlock:
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+
+   return ret;
 }
 
 static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 {
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+   unsigned long flags;
+   int ret = 0;
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+
+   if (hsotg->lx_state != DWC2_L2)
+   goto unlock;
+
+   if (!hsotg->core_params->hibernation) {
+   hsotg->lx_state = DWC2_L0;
+   goto unlock;
+   }
+
+   /*
+* Set HW accessible bit before powering on the controller
+* since an interrupt may rise.
+*/
+   set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+   /*
+* Enable 

[PATCH v3 00/32] usb: dwc2: various bug fixes

2015-09-29 Thread Mian Yousaf Kaukab
Hi,
This series consists of various bug fixes for both host and gadget
sides. All patches are verified on dwc2 v3.0a with dedicated fifos.
It would be good to get some Tested-bys for other platforms.

It is based on testing/next branch in Felipe's git.

Thank you,

Best regards,
Yousaf

History:
v3:
 - Fix comment from Sergei Shtylyov
 - Rebase to latest testing/next
 
v2:
 - Rebase to latest testing/next
 - Fix lock issue found by John Youn when calling
   dwc2_hsotg_core_init_disconnected() from dwc2_conn_id_status_change()
 - Fix comments from John Youn
 - Fix comments from Doug Anderson

v1:
 - Fix following comments from David Cohen (received on an internal
   list):
- Fix build when "usb: dwc2: host: create a function to handle-
  port_resume" is applied.
- Take spin locks within if statements in "usb: dwc2: host: enter-
  hibernation during bus suspend"
- Remove extra 100us delay in "usb: dwc2: host: enter-
  hibernation during bus suspend"
- Fix spelling mistakes in "usb: dwc2: host: update hcd and-
  lx_state during start/stop callbacks"
- Change dev_warn to dev_dbg in "usb: dwc2: host: reset frame-
   number after suspend"
- Change mdelay to usleep_range in "usb: dwc2: host: wait 3ms for-
  controller stabilization"
 - Fix comments from Sergei Shtylyov

Gregory Herrero (22):
  usb: dwc2: host: don't clear hprt0 status bits when exiting
hibernation
  usb: dwc2: host: create a function to handle port_resume
  usb: dwc2: host: add flag to reflect bus state
  usb: dwc2: host: enter hibernation during bus suspend
  usb: dwc2: host: update hcd and lx_state during start/stop callbacks
  usb: dwc2: host: avoid resetting lx_state to L3 during disconnect
  usb: dwc2: host: ignore wakeup interrupt if hibernation supported
  usb: dwc2: host: resume only if bus is suspended
  usb: dwc2: host: reset frame number after suspend
  usb: dwc2: host: disconnect hcd prior stopping it
  usb: dwc2: host: disable interrupt during stop
  usb: dwc2: host: clear pending interrupts prior hibernation
  usb: dwc2: host: wait 3ms for controller stabilization
  usb: dwc2: host: correctly dump urb isochronous descriptors
  usb: dwc2: host: use correct frame number during qh init
  usb: dwc2: host: kill remaining urbs using -ECONNRESET status
  usb: dwc2: gadget: ensure lx_state corresponds to current state
  usb: dwc2: gadget: don't modify pullup state in host mode
  usb: dwc2: gadget: set op_state in vbus_session call
  usb: dwc2: gadget: abort core init if core_reset fails
  usb: dwc2: gadget: unmask idstschng interrupt only if controller
    supports it
  usb: dwc2: gadget: exit hibernation before power down

Mian Yousaf Kaukab (10):
  usb: dwc2: host: add disconnect interrupt to host only interrupts
  usb: dwc2: gadget: initialize op_state for peripheral only
configuration
  usb: dwc2: force dr_mode in case of configuration mismatch
  usb: dwc2: gadget: ignore stall check for ep0
  usb: dwc2: gadget: print complete setup packet
  usb: dwc2: gadget: stop current transfer on dequeue
  usb: dwc2: gadget: kill ep0 requests before reinitializing core
  usb: dwc2: gadget: only reset core after addressed state
  usb: dwc2: gadget: handle reset interrupt before endpoint interrupts
  usb: dwc2: exit hibernation on session request

 drivers/usb/dwc2/core.c  |  14 ++-
 drivers/usb/dwc2/core.h  |   3 +-
 drivers/usb/dwc2/core_intr.c |  29 --
 drivers/usb/dwc2/gadget.c| 210 ++-
 drivers/usb/dwc2/hcd.c   | 209 --
 drivers/usb/dwc2/hcd_queue.c |  11 +++
 drivers/usb/dwc2/platform.c  |  11 +++
 7 files changed, 386 insertions(+), 101 deletions(-)

-- 
2.3.3

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


[PATCH v3 03/32] usb: dwc2: host: add flag to reflect bus state

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

lx_state must be used to reflect controller power state only and not
bus state. Thus add a flag to track state during bus suspend.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/core.h | 1 +
 drivers/usb/dwc2/hcd.c  | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a130e38..27e6fbf 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -765,6 +765,7 @@ struct dwc2_hsotg {
u16 frame_usecs[8];
u16 frame_number;
u16 periodic_qh_count;
+   bool bus_suspended;
 
 #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
 #define FRAME_NUM_ARRAY_SIZE 1000
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index b929087..490ecb7 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1425,6 +1425,7 @@ static void dwc2_wakeup_detected(unsigned long data)
dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
dwc2_readl(hsotg->regs + HPRT0));
 
+   hsotg->bus_suspended = 0;
dwc2_hcd_rem_wakeup(hsotg);
 
/* Change to L0 state */
@@ -1461,8 +1462,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
hprt0 |= HPRT0_SUSP;
dwc2_writel(hprt0, hsotg->regs + HPRT0);
 
-   /* Update lx_state */
-   hsotg->lx_state = DWC2_L2;
+   hsotg->bus_suspended = 1;
 
/* Suspend the Phy Clock */
pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
@@ -1510,6 +1510,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   hsotg->bus_suspended = 0;
spin_unlock_irqrestore(&hsotg->lock, flags);
 }
 
-- 
2.3.3

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


[PATCH v3 02/32] usb: dwc2: host: create a function to handle port_resume

2015-09-29 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

port resume sequence may be used in different places. Create a
function to handle it. Make hprt0 read-modify-write atomic and
clear HPRT0_SUSP for both writes as it is a "read, write-set,
and self-clear (R_WS_SC)" bit. Since the lock is released
between the writes, read hprt0 again.

Since the phy clock is stopped in dwc2_port_suspend(), enable it
here and remove the PCGCTL write from dwc2_hcd_hub_control()

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
Tested-by: Dinh Nguyen 
Tested-by: John Youn 
Acked-by: John Youn 
---
 drivers/usb/dwc2/hcd.c | 40 ++--
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 1595d70..b929087 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1484,6 +1484,35 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
}
 }
 
+/* Must NOT be called with interrupt disabled or spinlock held */
+static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
+{
+   unsigned long flags;
+   u32 hprt0;
+   u32 pcgctl;
+
+   /* Resume the Phy Clock */
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl &= ~PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   usleep_range(2, 4);
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 |= HPRT0_RES;
+   hprt0 &= ~HPRT0_SUSP;
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+
+   msleep(USB_RESUME_TIMEOUT);
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
 /* Handles hub class-specific requests */
 static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
u16 wvalue, u16 windex, char *buf, u16 wlength)
@@ -1529,17 +1558,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg 
*hsotg, u16 typereq,
case USB_PORT_FEAT_SUSPEND:
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
-   dwc2_writel(0, hsotg->regs + PCGCTL);
-   usleep_range(2, 4);
 
-   hprt0 = dwc2_read_hprt0(hsotg);
-   hprt0 |= HPRT0_RES;
-   dwc2_writel(hprt0, hsotg->regs + HPRT0);
-   hprt0 &= ~HPRT0_SUSP;
-   msleep(USB_RESUME_TIMEOUT);
-
-   hprt0 &= ~HPRT0_RES;
-   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   dwc2_port_resume(hsotg);
break;
 
case USB_PORT_FEAT_POWER:
-- 
2.3.3

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


[PATCH v2] media: uvcvideo: handle urb completion in a tasklet

2015-09-23 Thread Mian Yousaf Kaukab
urb completion callback is executed in either host controllers
interrupt context or a tasklet (if hcd has set HCD_BH flag).

If hcd is calling urb->complete from interrupt context, to keep
preempt disable time short, add urbs to a list on completion and
schedule a tasklet to process the list.

Moreover, save timestamp and sof number in the urb completion callback
to avoid any delays.

Signed-off-by: Mian Yousaf Kaukab 
---
[Rename from media: uvcvideo: handle urb completion in a work queue]

History:
v2:
 - Change to use tasklet instead of workqueue
 - Don't use local tasklet if hcd is aleady using tasklet for
   completion callback
v1:
 - Use global work queue instead of creating ordered queue.
 - Add completed urbs to a list and process all on the list when work
   is scheduled
 - Save timestamp and sof number in urb completion callback and use
   in uvc_video_clock_decode() and uvc_video_decode_start()
 - Fix race between usb_submit_urb() from uvc_video_complete() and
   usb_kill_urb() from uvc_uninit_video()

 drivers/media/usb/uvc/uvc_driver.c |   8 +++
 drivers/media/usb/uvc/uvc_isight.c |   3 +-
 drivers/media/usb/uvc/uvc_video.c  | 144 -
 drivers/media/usb/uvc/uvcvideo.h   |  18 -
 4 files changed, 134 insertions(+), 39 deletions(-)

diff --git a/drivers/media/usb/uvc/uvc_driver.c 
b/drivers/media/usb/uvc/uvc_driver.c
index 4b5b3e8..218d4f5 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include 
@@ -1945,6 +1946,13 @@ static int uvc_probe(struct usb_interface *intf,
"supported.\n", ret);
}
 
+   /*
+* This shouldn't be here. But since not all hcd are using tasklet for
+* urb completion callback, Check this from hcd and only use tasklet
+* for handling urb completion if hcd is not already using it.
+*/
+   dev->hcd_uses_bh = hcd_giveback_urb_in_bh(bus_to_hcd(udev->bus));
+
uvc_trace(UVC_TRACE_PROBE, "UVC device initialized.\n");
usb_enable_autosuspend(udev);
return 0;
diff --git a/drivers/media/usb/uvc/uvc_isight.c 
b/drivers/media/usb/uvc/uvc_isight.c
index 8510e725..7f93d09 100644
--- a/drivers/media/usb/uvc/uvc_isight.c
+++ b/drivers/media/usb/uvc/uvc_isight.c
@@ -99,9 +99,10 @@ static int isight_decode(struct uvc_video_queue *queue, 
struct uvc_buffer *buf,
return 0;
 }
 
-void uvc_video_decode_isight(struct urb *urb, struct uvc_streaming *stream,
+void uvc_video_decode_isight(struct uvc_urb *uu, struct uvc_streaming *stream,
struct uvc_buffer *buf)
 {
+   struct urb *urb = uu->urb;
int ret, i;
 
for (i = 0; i < urb->number_of_packets; ++i) {
diff --git a/drivers/media/usb/uvc/uvc_video.c 
b/drivers/media/usb/uvc/uvc_video.c
index f839654..2dfb233 100644
--- a/drivers/media/usb/uvc/uvc_video.c
+++ b/drivers/media/usb/uvc/uvc_video.c
@@ -379,15 +379,14 @@ static inline void uvc_video_get_ts(struct timespec *ts)
 
 static void
 uvc_video_clock_decode(struct uvc_streaming *stream, struct uvc_buffer *buf,
-  const __u8 *data, int len)
+  const __u8 *data, int len, u16 host_sof,
+  struct timespec *ts)
 {
struct uvc_clock_sample *sample;
unsigned int header_size;
bool has_pts = false;
bool has_scr = false;
unsigned long flags;
-   struct timespec ts;
-   u16 host_sof;
u16 dev_sof;
 
switch (data[1] & (UVC_STREAM_PTS | UVC_STREAM_SCR)) {
@@ -435,9 +434,6 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct 
uvc_buffer *buf,
 
stream->clock.last_sof = dev_sof;
 
-   host_sof = usb_get_current_frame_number(stream->dev->udev);
-   uvc_video_get_ts(&ts);
-
/* The UVC specification allows device implementations that can't obtain
 * the USB frame number to keep their own frame counters as long as they
 * match the size and frequency of the frame number associated with USB
@@ -473,7 +469,7 @@ uvc_video_clock_decode(struct uvc_streaming *stream, struct 
uvc_buffer *buf,
sample->dev_stc = get_unaligned_le32(&data[header_size - 6]);
sample->dev_sof = dev_sof;
sample->host_sof = host_sof;
-   sample->host_ts = ts;
+   sample->host_ts = *ts;
 
/* Update the sliding window head and count. */
stream->clock.head = (stream->clock.head + 1) % stream->clock.size;
@@ -964,7 +960,8 @@ static void uvc_video_stats_stop(struct uvc_streaming 
*stream)
  * uvc_video_decode_end will never be called with a NULL buffer.
  */
 static int uvc_video_decode_start(struct uvc_streaming *stream,
-   struct uvc_buffer *buf, const __u8 *data, int len)
+   struct uvc_buffer *buf, const __u8 *data, i

[PATCH v2 32/32] usb: dwc2: exit hibernation on session request

2015-09-22 Thread Mian Yousaf Kaukab
Controller enters hibernation through suspend interrupt on
disconnection. On connection, session request interrupt is generated.
dwc2 must exit hibernation and restore state from this interrupt
before continuing.

In host mode, exit from hibernation is handled by bus_resume function.

Signed-off-by: Mian Yousaf Kaukab 
Signed-off-by: Gregory Herrero 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/core_intr.c | 22 +-
 1 file changed, 17 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/core_intr.c b/drivers/usb/dwc2/core_intr.c
index d8a5400..27daa42 100644
--- a/drivers/usb/dwc2/core_intr.c
+++ b/drivers/usb/dwc2/core_intr.c
@@ -313,16 +313,28 @@ static void dwc2_handle_conn_id_status_change_intr(struct 
dwc2_hsotg *hsotg)
  */
 static void dwc2_handle_session_req_intr(struct dwc2_hsotg *hsotg)
 {
-   dev_dbg(hsotg->dev, "++Session Request Interrupt++\n");
+   int ret;
+
+   dev_dbg(hsotg->dev, "Session request interrupt - lx_state=%d\n",
+   hsotg->lx_state);
 
/* Clear interrupt */
dwc2_writel(GINTSTS_SESSREQINT, hsotg->regs + GINTSTS);
 
-   /*
-* Report disconnect if there is any previous session established
-*/
-   if (dwc2_is_device_mode(hsotg))
+   if (dwc2_is_device_mode(hsotg)) {
+   if (hsotg->lx_state == DWC2_L2) {
+   ret = dwc2_exit_hibernation(hsotg, true);
+   if (ret && (ret != -ENOTSUPP))
+   dev_err(hsotg->dev,
+   "exit hibernation failed\n");
+   }
+
+   /*
+* Report disconnect if there is any previous session
+* established
+*/
dwc2_hsotg_disconnect(hsotg);
+   }
 }
 
 /*
-- 
2.3.3

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


[PATCH v2 31/32] usb: dwc2: gadget: handle reset interrupt before endpoint interrupts

2015-09-22 Thread Mian Yousaf Kaukab
If system is loaded, reset, enum-done and setup interrupts can occur
at the same time. Current interrupt handling sequence will handle
setup packet's interrupt before handling reset interrupt. Which will
break the enumeration process. Correct sequence is to handle reset,
enum-done and then any other endpoint interrupts.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 60 +++
 1 file changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index a62224a..7037997 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2460,6 +2460,36 @@ irq_retry:
 
gintsts &= gintmsk;
 
+   if (gintsts & GINTSTS_RESETDET) {
+   dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
+
+   dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
+
+   /* This event must be used only if controller is suspended */
+   if (hsotg->lx_state == DWC2_L2) {
+   dwc2_exit_hibernation(hsotg, true);
+   hsotg->lx_state = DWC2_L0;
+   }
+   }
+
+   if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
+
+   u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+   u32 connected = hsotg->connected;
+
+   dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
+   dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
+   dwc2_readl(hsotg->regs + GNPTXSTS));
+
+   dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
+
+   /* Report disconnection if it is not already done. */
+   dwc2_hsotg_disconnect(hsotg);
+
+   if (usb_status & GOTGCTL_BSESVLD && connected)
+   dwc2_hsotg_core_init_disconnected(hsotg, true);
+   }
+
if (gintsts & GINTSTS_ENUMDONE) {
dwc2_writel(GINTSTS_ENUMDONE, hsotg->regs + GINTSTS);
 
@@ -2491,36 +2521,6 @@ irq_retry:
}
}
 
-   if (gintsts & GINTSTS_RESETDET) {
-   dev_dbg(hsotg->dev, "%s: USBRstDet\n", __func__);
-
-   dwc2_writel(GINTSTS_RESETDET, hsotg->regs + GINTSTS);
-
-   /* This event must be used only if controller is suspended */
-   if (hsotg->lx_state == DWC2_L2) {
-   dwc2_exit_hibernation(hsotg, true);
-   hsotg->lx_state = DWC2_L0;
-   }
-   }
-
-   if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
-
-   u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
-   u32 connected = hsotg->connected;
-
-   dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
-   dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
-   dwc2_readl(hsotg->regs + GNPTXSTS));
-
-   dwc2_writel(GINTSTS_USBRST, hsotg->regs + GINTSTS);
-
-   /* Report disconnection if it is not already done. */
-   dwc2_hsotg_disconnect(hsotg);
-
-   if (usb_status & GOTGCTL_BSESVLD && connected)
-   dwc2_hsotg_core_init_disconnected(hsotg, true);
-   }
-
/* check both FIFOs */
 
if (gintsts & GINTSTS_NPTXFEMP) {
-- 
2.3.3

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


[PATCH v2 17/32] usb: dwc2: host: kill remaining urbs using -ECONNRESET status

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

On a disconnect, dwc2 will kill all remaining urbs from qh list.
urbs are given back to hcd with -ETIMEDOUT status.
Some usb device driver, like mass storage, will unlink all urbs
using usb_hcd_unlink_urb when receiving a negative status different
from -ECONNRESET.
The following flow will then happen:
dwc2_hcd_disconnect()
-> dwc2_kill_all_urbs() try to kill first pending urb.
-> dwc2_host_complete(-ETIMEDOUT)
-> usb_hcd_giveback_urb(-ETIMEDOUT)
-> sg_complete()
-> usb_unlink_urb()
-> usb_put_dev(urb->dev)
-> dwc2_kill_all_urbs() try to kill next pending urb.
-> dwc2_host_complete(-ETIMEDOUT)
-> usb_hcd_giveback_urb(-ETIMEDOUT)
-> NULL pointer dereferencing because urb->dev has been freed for all
urbs of this device.

The root cause of this NULL pointer is to call call usb_unlink_urb()
while we are killing all urbs. To avoid this return urb with
-ECONNRESET status

This issue usually happens while removing mass storage device during
transfer.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/hcd.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 397bb7d..15a1e62 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -134,7 +134,7 @@ static void dwc2_kill_urbs_in_qh_list(struct dwc2_hsotg 
*hsotg,
list_for_each_entry_safe(qh, qh_tmp, qh_list, qh_list_entry) {
list_for_each_entry_safe(qtd, qtd_tmp, &qh->qtd_list,
 qtd_list_entry) {
-   dwc2_host_complete(hsotg, qtd, -ETIMEDOUT);
+   dwc2_host_complete(hsotg, qtd, -ECONNRESET);
dwc2_hcd_qtd_unlink_and_free(hsotg, qtd, qh);
}
}
-- 
2.3.3

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


[PATCH v2 23/32] usb: dwc2: gadget: abort core init if core_reset fails

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

No point of continue with initialization if core is not in a sane
state.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index efbad12..742765e 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2287,7 +2287,8 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
u32 val;
 
if (!is_usb_reset)
-   dwc2_hsotg_corereset(hsotg);
+   if (dwc2_hsotg_corereset(hsotg))
+   return;
 
/*
 * we must now enable ep0 ready for host detection and then
-- 
2.3.3

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


[PATCH v2 27/32] usb: dwc2: gadget: kill ep0 requests before reinitializing core

2015-09-22 Thread Mian Yousaf Kaukab
Make sure there are no requests pending on ep0 before reinitializing
core. Otherwise, dwc2_hsotg_enqueue_setup will fail afterwards.

Also, take hsotg->lock before calling
dwc2_hsotg_core_init_disconnected() from dwc2_conn_id_status_change()
as dwc2_hsotg_complete_request() expect lock to be held.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 8 +++-
 drivers/usb/dwc2/hcd.c| 3 +++
 2 files changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 97bf696..1697eec 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2287,6 +2287,9 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
 {
u32 val;
 
+   /* Kill any ep0 requests as controller will be reinitialized */
+   kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
+
if (!is_usb_reset)
if (dwc2_hsotg_corereset(hsotg))
return;
@@ -2515,9 +2518,6 @@ irq_retry:
if (time_after(jiffies, hsotg->last_rst +
   msecs_to_jiffies(200))) {
 
-   kill_all_requests(hsotg, hsotg->eps_out[0],
- -ECONNRESET);
-
dwc2_hsotg_core_init_disconnected(hsotg, true);
}
}
@@ -3296,8 +3296,6 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
if (hsotg->lx_state == DWC2_L2)
dwc2_exit_hibernation(hsotg, false);
 
-   /* Kill any ep0 requests as controller will be reinitialized */
-   kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
dwc2_hsotg_core_connect(hsotg);
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 15a1e62..af4e4a2 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1355,6 +1355,7 @@ static void dwc2_conn_id_status_change(struct work_struct 
*work)
wf_otg);
u32 count = 0;
u32 gotgctl;
+   unsigned long flags;
 
dev_dbg(hsotg->dev, "%s()\n", __func__);
 
@@ -1382,7 +1383,9 @@ static void dwc2_conn_id_status_change(struct work_struct 
*work)
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
dwc2_core_init(hsotg, false, -1);
dwc2_enable_global_interrupts(hsotg);
+   spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hsotg_core_init_disconnected(hsotg, false);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_hsotg_core_connect(hsotg);
} else {
/* A-Device connector (Host Mode) */
-- 
2.3.3

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


[PATCH v2 29/32] usb: dwc2: gadget: unmask idstschng interrupt only if controller supports it

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

idstschng interrupt should not be used when id pin control is
external. This is already handled on dwc2 host part. Fix it on gadget
part as well.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 17 ++---
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 9c82d61..229dccd 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2285,6 +2285,7 @@ static int dwc2_hsotg_corereset(struct dwc2_hsotg *hsotg)
 void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg *hsotg,
bool is_usb_reset)
 {
+   u32 intmsk;
u32 val;
 
/* Kill any ep0 requests as controller will be reinitialized */
@@ -2316,14 +2317,16 @@ void dwc2_hsotg_core_init_disconnected(struct 
dwc2_hsotg *hsotg,
 
/* Clear any pending interrupts */
dwc2_writel(0x, hsotg->regs + GINTSTS);
-
-   dwc2_writel(GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
+   intmsk = GINTSTS_ERLYSUSP | GINTSTS_SESSREQINT |
GINTSTS_GOUTNAKEFF | GINTSTS_GINNAKEFF |
-   GINTSTS_CONIDSTSCHNG | GINTSTS_USBRST |
-   GINTSTS_RESETDET | GINTSTS_ENUMDONE |
-   GINTSTS_OTGINT | GINTSTS_USBSUSP |
-   GINTSTS_WKUPINT,
-   hsotg->regs + GINTMSK);
+   GINTSTS_USBRST | GINTSTS_RESETDET |
+   GINTSTS_ENUMDONE | GINTSTS_OTGINT |
+   GINTSTS_USBSUSP | GINTSTS_WKUPINT;
+
+   if (hsotg->core_params->external_id_pin_ctl <= 0)
+   intmsk |= GINTSTS_CONIDSTSCHNG;
+
+   dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 
if (using_dma(hsotg))
dwc2_writel(GAHBCFG_GLBL_INTR_EN | GAHBCFG_DMA_EN |
-- 
2.3.3

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


[PATCH v2 26/32] usb: dwc2: gadget: stop current transfer on dequeue

2015-09-22 Thread Mian Yousaf Kaukab
If the request being dequeued is already started, disable endpoint
to stop the transfer and then call dwc2_hsotg_complete_request().
Endpoint will be re-enabled on next call to dwc2_hsotg_start_req().

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 77 +++
 1 file changed, 77 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 6c00c0d..97bf696 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2826,6 +2826,79 @@ static bool on_list(struct dwc2_hsotg_ep *ep, struct 
dwc2_hsotg_req *test)
return false;
 }
 
+static int dwc2_hsotg_wait_bit_set(struct dwc2_hsotg *hs_otg, u32 reg,
+   u32 bit, u32 timeout)
+{
+   u32 i;
+
+   for (i = 0; i < timeout; i++) {
+   if (dwc2_readl(hs_otg->regs + reg) & bit)
+   return 0;
+   udelay(1);
+   }
+
+   return -ETIMEDOUT;
+}
+
+static void dwc2_hsotg_ep_stop_xfr(struct dwc2_hsotg *hsotg,
+   struct dwc2_hsotg_ep *hs_ep)
+{
+   u32 epctrl_reg;
+   u32 epint_reg;
+
+   epctrl_reg = hs_ep->dir_in ? DIEPCTL(hs_ep->index) :
+  DOEPCTL(hs_ep->index);
+   epint_reg = hs_ep->dir_in ? DIEPINT(hs_ep->index) :
+   DOEPINT(hs_ep->index);
+
+   dev_dbg(hsotg->dev, "%s: stopping transfer on %s\n", __func__,
+   hs_ep->name);
+   if (hs_ep->dir_in) {
+   __orr32(hsotg->regs + epctrl_reg, DXEPCTL_SNAK);
+   /* Wait for Nak effect */
+   if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg,
+   DXEPINT_INEPNAKEFF, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout DIEPINT.NAKEFF\n", __func__);
+   } else {
+   /* Clear any pending nak effect interrupt */
+   dwc2_writel(GINTSTS_GINNAKEFF, hsotg->regs + GINTSTS);
+
+   __orr32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+
+   /* Wait for global nak to take effect */
+   if (dwc2_hsotg_wait_bit_set(hsotg, GINTSTS,
+   GINTSTS_GINNAKEFF, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout GINTSTS.GINNAKEFF\n", __func__);
+   }
+
+   /* Disable ep */
+   __orr32(hsotg->regs + epctrl_reg, DXEPCTL_EPDIS | DXEPCTL_SNAK);
+
+   /* Wait for ep to be disabled */
+   if (dwc2_hsotg_wait_bit_set(hsotg, epint_reg, DXEPINT_EPDISBLD, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout DOEPCTL.EPDisable\n", __func__);
+
+   if (hs_ep->dir_in) {
+   if (hsotg->dedicated_fifos) {
+   dwc2_writel(GRSTCTL_TXFNUM(hs_ep->fifo_index) |
+   GRSTCTL_TXFFLSH, hsotg->regs + GRSTCTL);
+   /* Wait for fifo flush */
+   if (dwc2_hsotg_wait_bit_set(hsotg, GRSTCTL,
+   GRSTCTL_TXFFLSH, 100))
+   dev_warn(hsotg->dev,
+   "%s: timeout flushing fifos\n",
+   __func__);
+   }
+   /* TODO: Flush shared tx fifo */
+   } else {
+   /* Remove global NAKs */
+   __bic32(hsotg->regs + DCTL, DCTL_SGNPINNAK);
+   }
+}
+
 /**
  * dwc2_hsotg_ep_dequeue - dequeue given endpoint
  * @ep: The endpoint to dequeue.
@@ -2847,6 +2920,10 @@ static int dwc2_hsotg_ep_dequeue(struct usb_ep *ep, 
struct usb_request *req)
return -EINVAL;
}
 
+   /* Dequeue already started request */
+   if (req == &hs_ep->req->req)
+   dwc2_hsotg_ep_stop_xfr(hs, hs_ep);
+
dwc2_hsotg_complete_request(hs, hs_ep, hs_req, -ECONNRESET);
spin_unlock_irqrestore(&hs->lock, flags);
 
-- 
2.3.3

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


[PATCH v2 30/32] usb: dwc2: gadget: exit hibernation before power down

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

When disconnecting cable, controller will detect a suspend condition
and enter partial power down. If vbus_session is called by the phy
driver during hibernation, make sure controller exit hibernation
before it is accessed.

Signed-off-by: Jianqiang Tang 
Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 13 +++--
 1 file changed, 7 insertions(+), 6 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 229dccd..a62224a 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3285,14 +3285,15 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
dev_dbg(hsotg->dev, "%s: is_active: %d\n", __func__, is_active);
spin_lock_irqsave(&hsotg->lock, flags);
 
+   /*
+* If controller is hibernated, it must exit from hibernation
+* before being initialized / de-initialized
+*/
+   if (hsotg->lx_state == DWC2_L2)
+   dwc2_exit_hibernation(hsotg, false);
+
if (is_active) {
hsotg->op_state = OTG_STATE_B_PERIPHERAL;
-   /*
-* If controller is hibernated, it must exit from hibernation
-* before being initialized
-*/
-   if (hsotg->lx_state == DWC2_L2)
-   dwc2_exit_hibernation(hsotg, false);
 
dwc2_hsotg_core_init_disconnected(hsotg, false);
if (hsotg->enabled)
-- 
2.3.3

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


[PATCH v2 25/32] usb: dwc2: gadget: print complete setup packet

2015-09-22 Thread Mian Yousaf Kaukab
wIndex field was missing. Also print in natural order instead of
Req first, so that its easier to compare for example against
bus analyzer logs.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 99da1db..6c00c0d 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -1206,9 +1206,10 @@ static void dwc2_hsotg_process_control(struct dwc2_hsotg 
*hsotg,
int ret = 0;
u32 dcfg;
 
-   dev_dbg(hsotg->dev, "ctrl Req=%02x, Type=%02x, V=%04x, L=%04x\n",
-ctrl->bRequest, ctrl->bRequestType,
-ctrl->wValue, ctrl->wLength);
+   dev_dbg(hsotg->dev,
+   "ctrl Type=%02x, Req=%02x, V=%04x, I=%04x, L=%04x\n",
+   ctrl->bRequestType, ctrl->bRequest, ctrl->wValue,
+   ctrl->wIndex, ctrl->wLength);
 
if (ctrl->wLength == 0) {
ep0->dir_in = 1;
-- 
2.3.3

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


[PATCH v2 18/32] usb: dwc2: gadget: ensure lx_state corresponds to current state

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Correctly update lx_state on gadget connection and disconnection.
When usb cable is disconnected, lx_state must be updated to L3 as
controller could be in power off state.
When usb cable is connected, lx_state must be updated to L0 as
controller is powered.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 8 
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index ddd14a7..ddb5427 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2189,6 +2189,7 @@ void dwc2_hsotg_disconnect(struct dwc2_hsotg *hsotg)
}
 
call_gadget(hsotg, disconnect);
+   hsotg->lx_state = DWC2_L3;
 }
 
 /**
@@ -2415,6 +2416,7 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
mdelay(3);
 
hsotg->last_rst = jiffies;
+   hsotg->lx_state = DWC2_L0;
 }
 
 static void dwc2_hsotg_core_disconnect(struct dwc2_hsotg *hsotg)
@@ -2514,7 +2516,6 @@ irq_retry:
kill_all_requests(hsotg, hsotg->eps_out[0],
  -ECONNRESET);
 
-   hsotg->lx_state = DWC2_L0;
dwc2_hsotg_core_init_disconnected(hsotg, true);
}
}
@@ -3205,10 +3206,9 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
 * If controller is hibernated, it must exit from hibernation
 * before being initialized
 */
-   if (hsotg->lx_state == DWC2_L2) {
+   if (hsotg->lx_state == DWC2_L2)
dwc2_exit_hibernation(hsotg, false);
-   hsotg->lx_state = DWC2_L0;
-   }
+
/* Kill any ep0 requests as controller will be reinitialized */
kill_all_requests(hsotg, hsotg->eps_out[0], -ECONNRESET);
dwc2_hsotg_core_init_disconnected(hsotg, false);
-- 
2.3.3

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


[PATCH v2 19/32] usb: dwc2: gadget: initialize op_state for peripheral only configuration

2015-09-22 Thread Mian Yousaf Kaukab
ID status change interrupt will not be handled in peripheral only
configuration. So initialize op_state during gadget init.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index ddb5427..36345ab 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3535,6 +3535,8 @@ int dwc2_gadget_init(struct dwc2_hsotg *hsotg, int irq)
hsotg->gadget.name = dev_name(dev);
if (hsotg->dr_mode == USB_DR_MODE_OTG)
hsotg->gadget.is_otg = 1;
+   else if (hsotg->dr_mode == USB_DR_MODE_PERIPHERAL)
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
 
/* reset the system */
 
-- 
2.3.3

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


[PATCH v2 24/32] usb: dwc2: gadget: ignore stall check for ep0

2015-09-22 Thread Mian Yousaf Kaukab
dwc2_hsotg_start_req starts a request only if endpoint is not stalled.
Ignore this check for ep0 as core will clear DOEPCTL0.Stall after
sending stall handshake. Prepare instead for receiving next setup
packet.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 742765e..99da1db 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -556,7 +556,7 @@ static void dwc2_hsotg_start_req(struct dwc2_hsotg *hsotg,
/* If endpoint is stalled, we will restart request later */
ctrl = dwc2_readl(hsotg->regs + epctrl_reg);
 
-   if (ctrl & DXEPCTL_STALL) {
+   if (index && ctrl & DXEPCTL_STALL) {
dev_warn(hsotg->dev, "%s: ep%d is stalled\n", __func__, index);
return;
}
-- 
2.3.3

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


[PATCH v2 15/32] usb: dwc2: host: correctly dump urb isochronous descriptors

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Print urb->iso_frame_desc.status after it has been updated using
dwc2_hcd_urb_get_iso_desc_status().

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/hcd.c | 11 ++-
 1 file changed, 6 insertions(+), 5 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 65044da..397bb7d 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2227,11 +2227,6 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct 
dwc2_qtd *qtd,
 usb_pipein(urb->pipe) ? "IN" : "OUT", status,
 urb->actual_length);
 
-   if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
-   for (i = 0; i < urb->number_of_packets; i++)
-   dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
-i, urb->iso_frame_desc[i].status);
-   }
 
if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS) {
urb->error_count = dwc2_hcd_urb_get_error_count(qtd->urb);
@@ -2244,6 +2239,12 @@ void dwc2_host_complete(struct dwc2_hsotg *hsotg, struct 
dwc2_qtd *qtd,
}
}
 
+   if (usb_pipetype(urb->pipe) == PIPE_ISOCHRONOUS && dbg_perio()) {
+   for (i = 0; i < urb->number_of_packets; i++)
+   dev_vdbg(hsotg->dev, " ISO Desc %d status %d\n",
+i, urb->iso_frame_desc[i].status);
+   }
+
urb->status = status;
if (!status) {
if ((urb->transfer_flags & URB_SHORT_NOT_OK) &&
-- 
2.3.3

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


[PATCH v2 28/32] usb: dwc2: gadget: only reset core after addressed state

2015-09-22 Thread Mian Yousaf Kaukab
There is a 200ms guard period to avoid unnecessary resets of the dwc2
ip. This delay sometimes prove to be too large when usbcv is run with
an ehci host. dwc2 only needs to be reset after addressed state.
Change the logic to reset ip after addressed state.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/core.h   |  2 --
 drivers/usb/dwc2/gadget.c | 11 +++
 2 files changed, 3 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index d2115d2..3056981 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -688,7 +688,6 @@ struct dwc2_hregs_backup {
  * @ctrl_req:   Request for EP0 control packets.
  * @ep0_state:  EP0 control transfers state
  * @test_mode:  USB test mode requested by the host
- * @last_rst:   Time of last reset
  * @eps:The endpoints being supplied to the gadget framework
  * @g_using_dma:  Indicate if dma usage is enabled
  * @g_rx_fifo_sz: Contains rx fifo size value
@@ -831,7 +830,6 @@ struct dwc2_hsotg {
struct usb_gadget gadget;
unsigned int enabled:1;
unsigned int connected:1;
-   unsigned long last_rst;
struct dwc2_hsotg_ep *eps_in[MAX_EPS_CHANNELS];
struct dwc2_hsotg_ep *eps_out[MAX_EPS_CHANNELS];
u32 g_using_dma;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 1697eec..9c82d61 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -2420,7 +2420,6 @@ void dwc2_hsotg_core_init_disconnected(struct dwc2_hsotg 
*hsotg,
/* must be at-least 3ms to allow bus to see disconnect */
mdelay(3);
 
-   hsotg->last_rst = jiffies;
hsotg->lx_state = DWC2_L0;
 }
 
@@ -2504,6 +2503,7 @@ irq_retry:
if (gintsts & (GINTSTS_USBRST | GINTSTS_RESETDET)) {
 
u32 usb_status = dwc2_readl(hsotg->regs + GOTGCTL);
+   u32 connected = hsotg->connected;
 
dev_dbg(hsotg->dev, "%s: USBRst\n", __func__);
dev_dbg(hsotg->dev, "GNPTXSTS=%08x\n",
@@ -2514,13 +2514,8 @@ irq_retry:
/* Report disconnection if it is not already done. */
dwc2_hsotg_disconnect(hsotg);
 
-   if (usb_status & GOTGCTL_BSESVLD) {
-   if (time_after(jiffies, hsotg->last_rst +
-  msecs_to_jiffies(200))) {
-
-   dwc2_hsotg_core_init_disconnected(hsotg, true);
-   }
-   }
+   if (usb_status & GOTGCTL_BSESVLD && connected)
+   dwc2_hsotg_core_init_disconnected(hsotg, true);
}
 
/* check both FIFOs */
-- 
2.3.3

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


[PATCH v2 14/32] usb: dwc2: host: wait 3ms for controller stabilization

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Some high speed mass storage devices fail to enumerate with following
error:

Cannot enable port %i.  Maybe the USB cable is bad?

This happens only when the device is plugged while the controller
is in hibernation state. After exiting hibernation, the controller
detects the device as a low speed device and fail to enumerate it.

Problem occurs only if HPRT0.PWR bit is programmed in a too short
delay after exiting hibernation. Dumping hprt register in
_dwc2_hcd_resume() directly after dwc2_exit_hibernation() shows that
HPRT0.LNSTS (D+/D- level) becomes valid approximately 2ms after
exiting hibernation.

Since dwc2_exit_hibernation() is called from atomic context, move the
delay out of this function.

Delay value is experimental and not mentioned in Synopsys
documentation. To be on the safe side 3ms delay is used.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 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 de9d2e2..65044da 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2472,6 +2472,9 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
spin_unlock_irqrestore(&hsotg->lock, flags);
dwc2_port_resume(hsotg);
} else {
+   /* Wait for controller to correctly update D+/D- level */
+   usleep_range(3000, 5000);
+
/*
 * Clear Port Enable and Port Status changes.
 * Enable Port Power.
@@ -2479,7 +2482,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
dwc2_writel(HPRT0_PWR | HPRT0_CONNDET |
HPRT0_ENACHG, hsotg->regs + HPRT0);
/* Wait for controller to detect Port Connect */
-   mdelay(5);
+   usleep_range(5000, 7000);
}
 
return ret;
-- 
2.3.3

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


[PATCH v2 22/32] usb: dwc2: gadget: set op_state in vbus_session call

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Some device may have external id pin control enabled, so op_state
will not be set on id pin interrupt change.
Thus, ensure op_state is set to peripheral during vbus detection.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 68ae8eb..efbad12 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3209,6 +3209,7 @@ static int dwc2_hsotg_vbus_session(struct usb_gadget 
*gadget, int is_active)
spin_lock_irqsave(&hsotg->lock, flags);
 
if (is_active) {
+   hsotg->op_state = OTG_STATE_B_PERIPHERAL;
/*
 * If controller is hibernated, it must exit from hibernation
 * before being initialized
-- 
2.3.3

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


[PATCH v2 11/32] usb: dwc2: host: add disconnect interrupt to host only interrupts

2015-09-22 Thread Mian Yousaf Kaukab
GINTSTS.DisconnInt is host only interrupt and should be disable after
dwc2_disable_host_interrupts is called.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/core.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index f5c3120..c5e0a45 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -857,7 +857,8 @@ void dwc2_enable_host_interrupts(struct dwc2_hsotg *hsotg)
 
/* Enable host mode interrupts without disturbing common interrupts */
intmsk = dwc2_readl(hsotg->regs + GINTMSK);
-   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT;
+   intmsk |= GINTSTS_DISCONNINT | GINTSTS_PRTINT | GINTSTS_HCHINT |
+   GINTSTS_DISCONNINT;
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
@@ -872,7 +873,7 @@ void dwc2_disable_host_interrupts(struct dwc2_hsotg *hsotg)
 
/* Disable host mode interrupts without disturbing common interrupts */
intmsk &= ~(GINTSTS_SOF | GINTSTS_PRTINT | GINTSTS_HCHINT |
-   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP);
+   GINTSTS_PTXFEMP | GINTSTS_NPTXFEMP | GINTSTS_DISCONNINT);
dwc2_writel(intmsk, hsotg->regs + GINTMSK);
 }
 
-- 
2.3.3

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


[PATCH v2 09/32] usb: dwc2: host: reset frame number after suspend

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Frame number is reset in hardware after exiting hibernation.
Thus, reset frame_number and ensure qh are queued with correct
sched_frame.

Otherwise, qh->sched_frame may be too high compared to
current frame number (which is 0). This can delay addition of qh in
the list of transfers until frame number reaches qh->sched_frame.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/core.c  | 1 +
 drivers/usb/dwc2/hcd_queue.c | 8 
 2 files changed, 9 insertions(+)

diff --git a/drivers/usb/dwc2/core.c b/drivers/usb/dwc2/core.c
index 0bfc987..f5c3120 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -116,6 +116,7 @@ static int dwc2_restore_host_registers(struct dwc2_hsotg 
*hsotg)
 
dwc2_writel(hr->hprt0, hsotg->regs + HPRT0);
dwc2_writel(hr->hfir, hsotg->regs + HFIR);
+   hsotg->frame_number = 0;
 
return 0;
 }
diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 712977f..801bd9d 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -583,6 +583,14 @@ int dwc2_hcd_qh_add(struct dwc2_hsotg *hsotg, struct 
dwc2_qh *qh)
/* QH already in a schedule */
return 0;
 
+   if (!dwc2_frame_num_le(qh->sched_frame, hsotg->frame_number) &&
+   !hsotg->frame_number) {
+   dev_dbg(hsotg->dev,
+   "reset frame number counter\n");
+   qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
+   SCHEDULE_SLOP);
+   }
+
/* Add the new QH to the appropriate schedule */
if (dwc2_qh_is_non_per(qh)) {
/* Always start in inactive schedule */
-- 
2.3.3

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


[PATCH v2 10/32] usb: dwc2: host: disconnect hcd prior stopping it

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

In case controller is asked to stop while devices are connected,
disconnect all devices and clean up before stopping.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/hcd.c | 5 +
 1 file changed, 5 insertions(+)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 856e21c..257f957 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2350,7 +2350,12 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
unsigned long flags;
 
+   /* Wait for interrupt processing to finish */
+   synchronize_irq(hcd->irq);
+
spin_lock_irqsave(&hsotg->lock, flags);
+   /* Ensure hcd is disconnected */
+   dwc2_hcd_disconnect(hsotg);
dwc2_hcd_stop(hsotg);
hsotg->lx_state = DWC2_L3;
hcd->state = HC_STATE_HALT;
-- 
2.3.3

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


[PATCH v2 20/32] usb: dwc2: force dr_mode in case of configuration mismatch

2015-09-22 Thread Mian Yousaf Kaukab
If dual role configuration is not selected, check and force dr_mode
based on the selected configuration.

Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/platform.c | 11 +++
 1 file changed, 11 insertions(+)

diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index 3d1f82d..50a0e70 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -221,6 +221,17 @@ static int dwc2_driver_probe(struct platform_device *dev)
(unsigned long)res->start, hsotg->regs);
 
hsotg->dr_mode = of_usb_get_dr_mode(dev->dev.of_node);
+   if (IS_ENABLED(CONFIG_USB_DWC2_HOST) &&
+   hsotg->dr_mode != USB_DR_MODE_HOST) {
+   hsotg->dr_mode = USB_DR_MODE_HOST;
+   dev_warn(hsotg->dev,
+   "Configuration mismatch. Forcing host mode\n");
+   } else if (IS_ENABLED(CONFIG_USB_DWC2_PERIPHERAL) &&
+   hsotg->dr_mode != USB_DR_MODE_PERIPHERAL) {
+   hsotg->dr_mode = USB_DR_MODE_PERIPHERAL;
+   dev_warn(hsotg->dev,
+   "Configuration mismatch. Forcing peripheral mode\n");
+   }
 
/*
 * Attempt to find a generic PHY, then look for an old style
-- 
2.3.3

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


[PATCH v2 21/32] usb: dwc2: gadget: don't modify pullup state in host mode

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Modifying the pullup state during host mode trig a new enumeration
of attached device. Thus, avoid modifying pullup in host mode.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/gadget.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 36345ab..68ae8eb 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -3170,7 +3170,14 @@ static int dwc2_hsotg_pullup(struct usb_gadget *gadget, 
int is_on)
struct dwc2_hsotg *hsotg = to_hsotg(gadget);
unsigned long flags = 0;
 
-   dev_dbg(hsotg->dev, "%s: is_on: %d\n", __func__, is_on);
+   dev_dbg(hsotg->dev, "%s: is_on: %d op_state: %d\n", __func__, is_on,
+   hsotg->op_state);
+
+   /* Don't modify pullup state while in host mode */
+   if (hsotg->op_state != OTG_STATE_B_PERIPHERAL) {
+   hsotg->enabled = is_on;
+   return 0;
+   }
 
mutex_lock(&hsotg->init_mutex);
spin_lock_irqsave(&hsotg->lock, flags);
-- 
2.3.3

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


[PATCH v2 16/32] usb: dwc2: host: use correct frame number during qh init

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

On first qh initialization, hsotg->frame_number is not corresponding
to reality. So read it from host controller to get correct value.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/hcd_queue.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/usb/dwc2/hcd_queue.c b/drivers/usb/dwc2/hcd_queue.c
index 801bd9d..7d8d06c 100644
--- a/drivers/usb/dwc2/hcd_queue.c
+++ b/drivers/usb/dwc2/hcd_queue.c
@@ -106,6 +106,9 @@ static void dwc2_qh_init(struct dwc2_hsotg *hsotg, struct 
dwc2_qh *qh,
USB_SPEED_HIGH : dev_speed, qh->ep_is_in,
qh->ep_type == USB_ENDPOINT_XFER_ISOC,
bytecount));
+
+   /* Ensure frame_number corresponds to the reality */
+   hsotg->frame_number = dwc2_hcd_get_frame_number(hsotg);
/* Start in a slightly future (micro)frame */
qh->sched_frame = dwc2_frame_num_inc(hsotg->frame_number,
 SCHEDULE_SLOP);
-- 
2.3.3

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


[PATCH v2 12/32] usb: dwc2: host: disable interrupt during stop

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Disable host interrupts before synchronising dwc2 irq.
So that interrupts are not generated once controller is stopped.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 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 257f957..de9d2e2 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2350,6 +2350,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
unsigned long flags;
 
+   /* Turn off all host-specific interrupts */
+   dwc2_disable_host_interrupts(hsotg);
+
/* Wait for interrupt processing to finish */
synchronize_irq(hcd->irq);
 
-- 
2.3.3

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


[PATCH v2 13/32] usb: dwc2: host: clear pending interrupts prior hibernation

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

If an interrupt rises during hibernation process, dwc2 will assert
interrupt line to interrupt controller. If interrupt is level
sensitive, interrupt handler will be called in a loop because dwc2
will not be able to clear it while controller is hibernated.
Thus, clear all controller interrupts before hibernation entry.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 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 c5e0a45..bf5e951 100644
--- a/drivers/usb/dwc2/core.c
+++ b/drivers/usb/dwc2/core.c
@@ -398,6 +398,12 @@ int dwc2_enter_hibernation(struct dwc2_hsotg *hsotg)
}
}
 
+   /*
+* Clear any pending interrupts since dwc2 will not be able to
+* clear them after entering hibernation.
+*/
+   dwc2_writel(0x, hsotg->regs + GINTSTS);
+
/* Put the controller in low power state */
pcgcctl = dwc2_readl(hsotg->regs + PCGCTL);
 
-- 
2.3.3

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


[PATCH v2 04/32] usb: dwc2: host: enter hibernation during bus suspend

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Disable controller power and enter hibernation when usb bus is
suspended. A phy driver is required to disable the power of the
controller and detect remote-wakeup or disconnection since the
controller will not be able to detect these in this state.

Once the phy driver detects bus activity, it must call
usb_hcd_resume_root_hub.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/hcd.c | 140 -
 1 file changed, 128 insertions(+), 12 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 490ecb7..459b441 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1464,11 +1464,17 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
 
hsotg->bus_suspended = 1;
 
-   /* Suspend the Phy Clock */
-   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
-   pcgctl |= PCGCTL_STOPPCLK;
-   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
-   udelay(10);
+   /*
+* If hibernation is supported, Phy clock will be suspended
+* after registers are backuped.
+*/
+   if (!hsotg->core_params->hibernation) {
+   /* Suspend the Phy Clock */
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl |= PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   udelay(10);
+   }
 
/* For HNP the bus must be suspended for at least 200ms */
if (dwc2_host_is_b_hnp_enabled(hsotg)) {
@@ -1491,11 +1497,16 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
u32 hprt0;
u32 pcgctl;
 
-   /* Resume the Phy Clock */
-   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
-   pcgctl &= ~PCGCTL_STOPPCLK;
-   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
-   usleep_range(2, 4);
+   /*
+* If hibernation is supported, Phy clock is already resumed
+* after registers restore.
+*/
+   if (!hsotg->core_params->hibernation) {
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl &= ~PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   usleep_range(2, 4);
+   }
 
spin_lock_irqsave(&hsotg->lock, flags);
hprt0 = dwc2_read_hprt0(hsotg);
@@ -2347,17 +2358,122 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
 {
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+   unsigned long flags;
+   int ret = 0;
+   u32 hprt0;
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+
+   if (hsotg->lx_state != DWC2_L0)
+   goto unlock;
+
+   if (!HCD_HW_ACCESSIBLE(hcd))
+   goto unlock;
+
+   if (!hsotg->core_params->hibernation)
+   goto skip_power_saving;
+
+   /*
+* Drive USB suspend and disable port Power
+* if usb bus is not suspended.
+*/
+   if (!hsotg->bus_suspended) {
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 |= HPRT0_SUSP;
+   hprt0 &= ~HPRT0_PWR;
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   }
+
+   /* Enter hibernation */
+   ret = dwc2_enter_hibernation(hsotg);
+   if (ret) {
+   if (ret != -ENOTSUPP)
+   dev_err(hsotg->dev,
+   "enter hibernation failed\n");
+   goto skip_power_saving;
+   }
+
+   /* Ask phy to be suspended */
+   if (!IS_ERR_OR_NULL(hsotg->uphy)) {
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+   usb_phy_set_suspend(hsotg->uphy, true);
+   spin_lock_irqsave(&hsotg->lock, flags);
+   }
+
+   /* After entering hibernation, hardware is no more accessible */
+   clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
+skip_power_saving:
hsotg->lx_state = DWC2_L2;
-   return 0;
+unlock:
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+
+   return ret;
 }
 
 static int _dwc2_hcd_resume(struct usb_hcd *hcd)
 {
struct dwc2_hsotg *hsotg = dwc2_hcd_to_hsotg(hcd);
+   unsigned long flags;
+   int ret = 0;
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+
+   if (hsotg->lx_state != DWC2_L2)
+   goto unlock;
+
+   if (!hsotg->core_params->hibernation) {
+   hsotg->lx_state = DWC2_L0;
+   goto unlock;
+   }
+
+   /*
+* Set HW accessible bit before powering on the controller
+* since an interrupt may rise.
+*/
+   set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
+
+   /*
+* Enable power if not already done.
+* This must not be spinlocked si

[PATCH v2 03/32] usb: dwc2: host: add flag to reflect bus state

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

lx_state must be used to reflect controller power state only and not
bus state. Thus add a flag to track state during bus suspend.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/core.h | 1 +
 drivers/usb/dwc2/hcd.c  | 5 +++--
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 1a7982d..d2115d2 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -764,6 +764,7 @@ struct dwc2_hsotg {
u16 frame_usecs[8];
u16 frame_number;
u16 periodic_qh_count;
+   bool bus_suspended;
 
 #ifdef CONFIG_USB_DWC2_TRACK_MISSED_SOFS
 #define FRAME_NUM_ARRAY_SIZE 1000
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index b929087..490ecb7 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1425,6 +1425,7 @@ static void dwc2_wakeup_detected(unsigned long data)
dev_dbg(hsotg->dev, "Clear Resume: HPRT0=%0x\n",
dwc2_readl(hsotg->regs + HPRT0));
 
+   hsotg->bus_suspended = 0;
dwc2_hcd_rem_wakeup(hsotg);
 
/* Change to L0 state */
@@ -1461,8 +1462,7 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
hprt0 |= HPRT0_SUSP;
dwc2_writel(hprt0, hsotg->regs + HPRT0);
 
-   /* Update lx_state */
-   hsotg->lx_state = DWC2_L2;
+   hsotg->bus_suspended = 1;
 
/* Suspend the Phy Clock */
pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
@@ -1510,6 +1510,7 @@ static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
hprt0 = dwc2_read_hprt0(hsotg);
hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   hsotg->bus_suspended = 0;
spin_unlock_irqrestore(&hsotg->lock, flags);
 }
 
-- 
2.3.3

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


[PATCH v2 08/32] usb: dwc2: host: resume only if bus is suspended

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

Port can be resumed in bus_resume callback.
In this case, there is no need to drive resume a second time
when hcd ask for it.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/hcd.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 65ae0a39..856e21c 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1571,7 +1571,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, 
u16 typereq,
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
 
-   dwc2_port_resume(hsotg);
+   if (hsotg->bus_suspended)
+   dwc2_port_resume(hsotg);
break;
 
case USB_PORT_FEAT_POWER:
-- 
2.3.3

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


[PATCH v2 05/32] usb: dwc2: host: update hcd and lx_state during start/stop callbacks

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

During hcd initialization, hardware accessible flag and lx_state must
be reset to the working state since controller is powered at this stage.

Same logic applied for stop callback.

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 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 459b441..65ae0a39 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -2318,8 +2318,9 @@ static int _dwc2_hcd_start(struct usb_hcd *hcd)
dev_dbg(hsotg->dev, "DWC OTG HCD START\n");
 
spin_lock_irqsave(&hsotg->lock, flags);
-
+   hsotg->lx_state = DWC2_L0;
hcd->state = HC_STATE_RUNNING;
+   set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 
if (dwc2_is_device_mode(hsotg)) {
spin_unlock_irqrestore(&hsotg->lock, flags);
@@ -2350,6 +2351,9 @@ static void _dwc2_hcd_stop(struct usb_hcd *hcd)
 
spin_lock_irqsave(&hsotg->lock, flags);
dwc2_hcd_stop(hsotg);
+   hsotg->lx_state = DWC2_L3;
+   hcd->state = HC_STATE_HALT;
+   clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
spin_unlock_irqrestore(&hsotg->lock, flags);
 
usleep_range(1000, 3000);
-- 
2.3.3

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


[PATCH v2 02/32] usb: dwc2: host: create a function to handle port_resume

2015-09-22 Thread Mian Yousaf Kaukab
From: Gregory Herrero 

port resume sequence may be used in different places. Create a
function to handle it. Make hprt0 read-modify-write atomic and
clear HPRT0_SUSP for both writes as it is a "read, write-set,
and self-clear (R_WS_SC)" bit. Since the lock is released
between the writes, read hprt0 again.

Since the phy clock is stopped in dwc2_port_suspend(), enable it
here and remove the PCGCTL write from dwc2_hcd_hub_control()

Signed-off-by: Gregory Herrero 
Signed-off-by: Mian Yousaf Kaukab 
Tested-by: Robert Baldyga 
---
 drivers/usb/dwc2/hcd.c | 40 ++--
 1 file changed, 30 insertions(+), 10 deletions(-)

diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index 1595d70..b929087 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -1484,6 +1484,35 @@ static void dwc2_port_suspend(struct dwc2_hsotg *hsotg, 
u16 windex)
}
 }
 
+/* Must NOT be called with interrupt disabled or spinlock held */
+static void dwc2_port_resume(struct dwc2_hsotg *hsotg)
+{
+   unsigned long flags;
+   u32 hprt0;
+   u32 pcgctl;
+
+   /* Resume the Phy Clock */
+   pcgctl = dwc2_readl(hsotg->regs + PCGCTL);
+   pcgctl &= ~PCGCTL_STOPPCLK;
+   dwc2_writel(pcgctl, hsotg->regs + PCGCTL);
+   usleep_range(2, 4);
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 |= HPRT0_RES;
+   hprt0 &= ~HPRT0_SUSP;
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+
+   msleep(USB_RESUME_TIMEOUT);
+
+   spin_lock_irqsave(&hsotg->lock, flags);
+   hprt0 = dwc2_read_hprt0(hsotg);
+   hprt0 &= ~(HPRT0_RES | HPRT0_SUSP);
+   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   spin_unlock_irqrestore(&hsotg->lock, flags);
+}
+
 /* Handles hub class-specific requests */
 static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
u16 wvalue, u16 windex, char *buf, u16 wlength)
@@ -1529,17 +1558,8 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg 
*hsotg, u16 typereq,
case USB_PORT_FEAT_SUSPEND:
dev_dbg(hsotg->dev,
"ClearPortFeature USB_PORT_FEAT_SUSPEND\n");
-   dwc2_writel(0, hsotg->regs + PCGCTL);
-   usleep_range(2, 4);
 
-   hprt0 = dwc2_read_hprt0(hsotg);
-   hprt0 |= HPRT0_RES;
-   dwc2_writel(hprt0, hsotg->regs + HPRT0);
-   hprt0 &= ~HPRT0_SUSP;
-   msleep(USB_RESUME_TIMEOUT);
-
-   hprt0 &= ~HPRT0_RES;
-   dwc2_writel(hprt0, hsotg->regs + HPRT0);
+   dwc2_port_resume(hsotg);
break;
 
case USB_PORT_FEAT_POWER:
-- 
2.3.3

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


  1   2   3   4   5   >