RE: USB Type C ptn5110

2018-11-04 Thread Jun Li
Hi Angus

> -Original Message-
> From: Angus Ainslie 
> Sent: 2018年11月1日 21:53
> To: Jun Li 
> Subject: USB Type C ptn5110
> 
> Hi Li,
> 
> We have a custom PCB that has a PTN5110 on it. The board can power from the
> USB C no problem but we are starting to look into the data modes and roles
> switching.
> 
> When I plug it into a host PC the host doesn't not recognize any device 
> attached. I
> don't have anything setup on the target as far as the gadgetfs so I assume 
> that is
> the issue there.
> 
> Also we would like the port to work in host mode. When we plug and unplug
> devices ( Type C hub and Type C HDMI connector ) I was expecting activity and 
> a
> role switch on the port but we only get VBUS on/off events. There's a log 
> below
> and I'll attach the page from our schematic, I can send additional pages if 
> needed.
> 

What usb driver are you using? Is there a sync mechanism between typec driver
and your usb driver?

What kernel version you are using, why SNK_ATTACH_WAIT can come to
PORT_RESET state?

This is tcpm code I see:

case SNK_ATTACH_WAIT:
if ((port->cc1 == TYPEC_CC_OPEN &&
 port->cc2 != TYPEC_CC_OPEN) ||
(port->cc1 != TYPEC_CC_OPEN &&
 port->cc2 == TYPEC_CC_OPEN))
tcpm_set_state(port, SNK_DEBOUNCED,
   PD_T_CC_DEBOUNCE);
else if (tcpm_port_is_disconnected(port))
tcpm_set_state(port, SNK_UNATTACHED,
   PD_T_PD_DEBOUNCE);
break;

You can cc to linux-usb mail list for more help.

Li Jun

> Any help would be appreciated.
> 
> Thanks
> 
> Angus
> 
> [    9.995334] Setting voltage/current limit 0 mV 0 mA [    9.995339] 
> polarity 0
> [    9.999888] Requesting mux mode 0, usb-role 0, orientation 0 [   10.001072]
> state change INVALID_STATE -> SNK_UNATTACHED [   10.001688] CC1: 0 -> 3,
> CC2: 0 -> 0 [state SNK_UNATTACHED, polarity 0, connected] [   10.001693] state
> change SNK_UNATTACHED -> SNK_ATTACH_WAIT [   10.001699] state change
> SNK_ATTACH_WAIT -> PORT_RESET [   10.001709] 0-0052:
> registered
> 
> 
> [   10.015559] Setting voltage/current limit 0 mV 0 mA [   10.015564] 
> polarity 0
> [   10.018415] Requesting mux mode 0, usb-role 0, orientation 0 [   10.018915]
> cc:=0 [   10.020105] pending state change PORT_RESET ->
> PORT_RESET_WAIT_OFF @
> 100 ms
> [   10.021369] CC1: 3 -> 0, CC2: 0 -> 0 [state PORT_RESET, polarity 0,
> disconnected] [   10.021374] state change PORT_RESET -> SNK_UNATTACHED
> [   10.021384] Start DRP toggling [   10.026761] CC1: 0 -> 0, CC2: 0 -> 0 
> [state
> DRP_TOGGLING, polarity 0, disconnected]
> 
> [  102.839786] VBUS off
> [  102.843610] VBUS off
> [  107.269437] VBUS on
> [  107.270646] VBUS on
> [  107.273120] VBUS on
> [  265.490589] VBUS off



[PATCH 1/8] usb: dwc3: gadget: fix ISOC TRB type on unaligned transfers

2018-11-04 Thread Felipe Balbi
When chaining ISOC TRBs together, only the first ISOC TRB should be of
type ISOC_FIRST, all others should be of type ISOC. This patch fixes
that.

Fixes: c6267a51639b ("usb: dwc3: gadget: align transfers to wMaxPacketSize")
Cc:  # v4.11+
Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/gadget.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index f973e7909f5b..2de1a3971a26 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1072,7 +1072,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
/* Now prepare one extra TRB to align transfer size */
trb = &dep->trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr,
-   maxp - rem, false, 0,
+   maxp - rem, false, 1,
req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
@@ -1116,7 +1116,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
/* Now prepare one extra TRB to align transfer size */
trb = &dep->trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem,
-   false, 0, req->request.stream_id,
+   false, 1, req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
} else if (req->request.zero && req->request.length &&
@@ -1132,7 +1132,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
/* Now prepare one extra TRB to handle ZLP */
trb = &dep->trb_pool[dep->trb_enqueue];
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
-   false, 0, req->request.stream_id,
+   false, 1, req->request.stream_id,
req->request.short_not_ok,
req->request.no_interrupt);
} else {
-- 
2.19.1



[PATCH 3/8] usb: dwc3: gadget: track number of TRBs per request

2018-11-04 Thread Felipe Balbi
This will help us remove the wait_event() from our ->dequeue().

Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/core.h   | 3 +++
 drivers/usb/dwc3/gadget.c | 6 ++
 2 files changed, 9 insertions(+)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 4872cba8699b..0de78cb29f2c 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -847,6 +847,7 @@ struct dwc3_hwparams {
  * @epnum: endpoint number to which this request refers
  * @trb: pointer to struct dwc3_trb
  * @trb_dma: DMA address of @trb
+ * @num_trbs: number of TRBs used by this request
  * @needs_extra_trb: true when request needs one extra TRB (either due to ZLP
  * or unaligned OUT)
  * @direction: IN or OUT direction flag
@@ -867,6 +868,8 @@ struct dwc3_request {
struct dwc3_trb *trb;
dma_addr_t  trb_dma;
 
+   unsignednum_trbs;
+
unsignedneeds_extra_trb:1;
unsigneddirection:1;
unsignedmapped:1;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 502a85707e65..c7fe2b8ba335 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1037,6 +1037,8 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep,
req->trb_dma = dwc3_trb_dma_offset(dep, trb);
}
 
+   req->num_trbs++;
+
__dwc3_prepare_one_trb(dep, trb, dma, length, chain, node,
stream_id, short_not_ok, no_interrupt);
 }
@@ -1071,6 +1073,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
 
/* Now prepare one extra TRB to align transfer size */
trb = &dep->trb_pool[dep->trb_enqueue];
+   req->num_trbs++;
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr,
maxp - rem, false, 1,
req->request.stream_id,
@@ -1115,6 +1118,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
 
/* Now prepare one extra TRB to align transfer size */
trb = &dep->trb_pool[dep->trb_enqueue];
+   req->num_trbs++;
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, maxp - rem,
false, 1, req->request.stream_id,
req->request.short_not_ok,
@@ -1131,6 +1135,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
 
/* Now prepare one extra TRB to handle ZLP */
trb = &dep->trb_pool[dep->trb_enqueue];
+   req->num_trbs++;
__dwc3_prepare_one_trb(dep, trb, dwc->bounce_addr, 0,
false, 1, req->request.stream_id,
req->request.short_not_ok,
@@ -2231,6 +2236,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct 
dwc3_ep *dep,
dwc3_ep_inc_deq(dep);
 
trace_dwc3_complete_trb(dep, trb);
+   req->num_trbs--;
 
/*
 * If we're in the middle of series of chained TRBs and we
-- 
2.19.1



[PATCH 2/8] usb: dwc3: gadget: combine unaligned and zero flags

2018-11-04 Thread Felipe Balbi
Both flags are used for the same purpose in dwc3: appending an extra
TRB at the end to deal with controller requirements. By combining both
flags into one, we make it clear that the situation is the same and
that they should be treated equally.

Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/core.h   |  7 +++
 drivers/usb/dwc3/gadget.c | 17 -
 2 files changed, 11 insertions(+), 13 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 5bfb62533e0f..4872cba8699b 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -847,11 +847,11 @@ struct dwc3_hwparams {
  * @epnum: endpoint number to which this request refers
  * @trb: pointer to struct dwc3_trb
  * @trb_dma: DMA address of @trb
- * @unaligned: true for OUT endpoints with length not divisible by maxp
+ * @needs_extra_trb: true when request needs one extra TRB (either due to ZLP
+ * or unaligned OUT)
  * @direction: IN or OUT direction flag
  * @mapped: true when request has been dma-mapped
  * @started: request is started
- * @zero: wants a ZLP
  */
 struct dwc3_request {
struct usb_request  request;
@@ -867,11 +867,10 @@ struct dwc3_request {
struct dwc3_trb *trb;
dma_addr_t  trb_dma;
 
-   unsignedunaligned:1;
+   unsignedneeds_extra_trb:1;
unsigneddirection:1;
unsignedmapped:1;
unsignedstarted:1;
-   unsignedzero:1;
 };
 
 /*
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 2de1a3971a26..502a85707e65 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1064,7 +1064,7 @@ static void dwc3_prepare_one_trb_sg(struct dwc3_ep *dep,
struct dwc3 *dwc = dep->dwc;
struct dwc3_trb *trb;
 
-   req->unaligned = true;
+   req->needs_extra_trb = true;
 
/* prepare normal TRB */
dwc3_prepare_one_trb(dep, req, true, i);
@@ -1108,7 +1108,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
struct dwc3 *dwc = dep->dwc;
struct dwc3_trb *trb;
 
-   req->unaligned = true;
+   req->needs_extra_trb = true;
 
/* prepare normal TRB */
dwc3_prepare_one_trb(dep, req, true, 0);
@@ -1124,7 +1124,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep 
*dep,
struct dwc3 *dwc = dep->dwc;
struct dwc3_trb *trb;
 
-   req->zero = true;
+   req->needs_extra_trb = true;
 
/* prepare normal TRB */
dwc3_prepare_one_trb(dep, req, true, 0);
@@ -1406,7 +1406,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
dwc3_ep_inc_deq(dep);
}
 
-   if (r->unaligned || r->zero) {
+   if (r->needs_extra_trb) {
trb = r->trb + r->num_pending_sgs + 1;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
@@ -1417,7 +1417,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
 
-   if (r->unaligned || r->zero) {
+   if (r->needs_extra_trb) {
trb = r->trb + 1;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
@@ -2250,7 +2250,7 @@ static int dwc3_gadget_ep_reclaim_completed_trb(struct 
dwc3_ep *dep,
 * with one TRB pending in the ring. We need to manually clear HWO bit
 * from that TRB.
 */
-   if ((req->zero || req->unaligned) && !(trb->ctrl & DWC3_TRB_CTRL_CHN)) {
+   if (req->needs_extra_trb && !(trb->ctrl & DWC3_TRB_CTRL_CNH)) {
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
return 1;
}
@@ -2327,11 +2327,10 @@ static int 
dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
status);
 
-   if (req->unaligned || req->zero) {
+   if (req->needs_extra_trb) {
ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
status);
-   req->unaligned = false;
-   req->zero = false;
+   req->needs_extra_trb = false;
}
 
req->request.actual = req->request.length - req->remaining;
-- 
2.19.1



[PATCH 4/8] usb: dwc3: gadget: use num_trbs when skipping TRBs on ->dequeue()

2018-11-04 Thread Felipe Balbi
Now that we track how many TRBs a request uses, it's easier to skip
over them in case of a call to usb_ep_dequeue(). Let's do so and
simplify the code a bit.

Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/gadget.c | 28 
 1 file changed, 4 insertions(+), 24 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index c7fe2b8ba335..fa3bbdce8ff7 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1364,6 +1364,8 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
break;
}
if (r == req) {
+   int i;
+
/* wait until it is processed */
dwc3_stop_active_transfer(dep, true);
 
@@ -1401,32 +1403,12 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
if (!r->trb)
goto out0;
 
-   if (r->num_pending_sgs) {
+   for (i = 0; i < r->num_trbs; i++) {
struct dwc3_trb *trb;
-   int i = 0;
-
-   for (i = 0; i < r->num_pending_sgs; i++) {
-   trb = r->trb + i;
-   trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
-   dwc3_ep_inc_deq(dep);
-   }
-
-   if (r->needs_extra_trb) {
-   trb = r->trb + r->num_pending_sgs + 1;
-   trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
-   dwc3_ep_inc_deq(dep);
-   }
-   } else {
-   struct dwc3_trb *trb = r->trb;
 
+   trb = r->trb + i;
trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
dwc3_ep_inc_deq(dep);
-
-   if (r->needs_extra_trb) {
-   trb = r->trb + 1;
-   trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
-   dwc3_ep_inc_deq(dep);
-   }
}
goto out1;
}
@@ -1437,8 +1419,6 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
}
 
 out1:
-   /* giveback the request */
-
dwc3_gadget_giveback(dep, req, -ECONNRESET);
 
 out0:
-- 
2.19.1



[PATCH 6/8] usb: dwc3: gadget: introduce cancelled_list

2018-11-04 Thread Felipe Balbi
This list will host cancelled requests who still have TRBs being
processed.

Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/core.h   |  2 ++
 drivers/usb/dwc3/gadget.c |  1 +
 drivers/usb/dwc3/gadget.h | 15 +++
 3 files changed, 18 insertions(+)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 0de78cb29f2c..24f0b108b7f6 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -636,6 +636,7 @@ struct dwc3_event_buffer {
 /**
  * struct dwc3_ep - device side endpoint representation
  * @endpoint: usb endpoint
+ * @cancelled_list: list of cancelled requests for this endpoint
  * @pending_list: list of pending requests for this endpoint
  * @started_list: list of started requests on this endpoint
  * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
@@ -659,6 +660,7 @@ struct dwc3_event_buffer {
  */
 struct dwc3_ep {
struct usb_ep   endpoint;
+   struct list_headcancelled_list;
struct list_headpending_list;
struct list_headstarted_list;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 03d0ff233dab..4cc0509d74ff 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -2144,6 +2144,7 @@ static int dwc3_gadget_init_endpoint(struct dwc3 *dwc, u8 
epnum)
 
INIT_LIST_HEAD(&dep->pending_list);
INIT_LIST_HEAD(&dep->started_list);
+   INIT_LIST_HEAD(&dep->cancelled_list);
 
return 0;
 }
diff --git a/drivers/usb/dwc3/gadget.h b/drivers/usb/dwc3/gadget.h
index 2aacd1afd9ff..023a473648eb 100644
--- a/drivers/usb/dwc3/gadget.h
+++ b/drivers/usb/dwc3/gadget.h
@@ -79,6 +79,21 @@ static inline void dwc3_gadget_move_started_request(struct 
dwc3_request *req)
list_move_tail(&req->list, &dep->started_list);
 }
 
+/**
+ * dwc3_gadget_move_cancelled_request - move @req to the cancelled_list
+ * @req: the request to be moved
+ *
+ * Caller should take care of locking. This function will move @req from its
+ * current list to the endpoint's cancelled_list.
+ */
+static inline void dwc3_gadget_move_cancelled_request(struct dwc3_request *req)
+{
+   struct dwc3_ep  *dep = req->dep;
+
+   req->started = false;
+   list_move_tail(&req->list, &dep->cancelled_list);
+}
+
 void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
int status);
 
-- 
2.19.1



[PATCH 5/8] usb: dwc3: gadget: extract dwc3_gadget_ep_skip_trbs()

2018-11-04 Thread Felipe Balbi
Extract the logic for skipping over TRBs to its own function. This
makes the code slightly more readable and makes it easier to move this
call to its final resting place as a following patch.

Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/gadget.c | 61 +++
 1 file changed, 24 insertions(+), 37 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index fa3bbdce8ff7..03d0ff233dab 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1337,6 +1337,29 @@ static int dwc3_gadget_ep_queue(struct usb_ep *ep, 
struct usb_request *request,
return ret;
 }
 
+static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep *dep, struct dwc3_request 
*req)
+{
+   int i;
+
+   /*
+* If request was already started, this means we had to
+* stop the transfer. With that we also need to ignore
+* all TRBs used by the request, however TRBs can only
+* be modified after completion of END_TRANSFER
+* command. So what we do here is that we wait for
+* END_TRANSFER completion and only after that, we jump
+* over TRBs by clearing HWO and incrementing dequeue
+* pointer.
+*/
+   for (i = 0; i < req->num_trbs; i++) {
+   struct dwc3_trb *trb;
+
+   trb = req->trb + i;
+   trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
+   dwc3_ep_inc_deq(dep);
+   }
+}
+
 static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
struct usb_request *request)
 {
@@ -1364,38 +1387,8 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
break;
}
if (r == req) {
-   int i;
-
/* wait until it is processed */
dwc3_stop_active_transfer(dep, true);
-
-   /*
-* If request was already started, this means we had to
-* stop the transfer. With that we also need to ignore
-* all TRBs used by the request, however TRBs can only
-* be modified after completion of END_TRANSFER
-* command. So what we do here is that we wait for
-* END_TRANSFER completion and only after that, we jump
-* over TRBs by clearing HWO and incrementing dequeue
-* pointer.
-*
-* Note that we have 2 possible types of transfers here:
-*
-* i) Linear buffer request
-* ii) SG-list based request
-*
-* SG-list based requests will have r->num_pending_sgs
-* set to a valid number (> 0). Linear requests,
-* normally use a single TRB.
-*
-* For each of these two cases, if r->unaligned flag is
-* set, one extra TRB has been used to align transfer
-* size to wMaxPacketSize.
-*
-* All of these cases need to be taken into
-* consideration so we don't mess up our TRB ring
-* pointers.
-*/
wait_event_lock_irq(dep->wait_end_transfer,
!(dep->flags & 
DWC3_EP_END_TRANSFER_PENDING),
dwc->lock);
@@ -1403,13 +1396,7 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
if (!r->trb)
goto out0;
 
-   for (i = 0; i < r->num_trbs; i++) {
-   struct dwc3_trb *trb;
-
-   trb = r->trb + i;
-   trb->ctrl &= ~DWC3_TRB_CTRL_HWO;
-   dwc3_ep_inc_deq(dep);
-   }
+   dwc3_gadget_ep_skip_trbs(dep, r);
goto out1;
}
dev_err(dwc->dev, "request %pK was not queued to %s\n",
-- 
2.19.1



[PATCH 7/8] usb: dwc3: gadget: move requests to cancelled_list

2018-11-04 Thread Felipe Balbi
Whenever we have a request in flight, we can move it to the cancelled
list and later simply iterate over that list and skip over any TRBs we
find.

Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/gadget.c | 17 ++---
 1 file changed, 14 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4cc0509d74ff..cfe99009210f 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1360,6 +1360,17 @@ static void dwc3_gadget_ep_skip_trbs(struct dwc3_ep 
*dep, struct dwc3_request *r
}
 }
 
+static void dwc3_gadget_ep_cleanup_cancelled_requests(struct dwc3_ep *dep)
+{
+   struct dwc3_request *req;
+   struct dwc3_request *tmp;
+
+   list_for_each_entry_safe(req, tmp, &dep->cancelled_list, list) {
+   dwc3_gadget_ep_skip_trbs(dep, req);
+   dwc3_gadget_giveback(dep, req, -ECONNRESET);
+   }
+}
+
 static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
struct usb_request *request)
 {
@@ -1396,8 +1407,9 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
if (!r->trb)
goto out0;
 
-   dwc3_gadget_ep_skip_trbs(dep, r);
-   goto out1;
+   dwc3_gadget_move_cancelled_request(req);
+   dwc3_gadget_ep_cleanup_cancelled_requests(dep);
+   goto out0;
}
dev_err(dwc->dev, "request %pK was not queued to %s\n",
request, ep->name);
@@ -1405,7 +1417,6 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
goto out0;
}
 
-out1:
dwc3_gadget_giveback(dep, req, -ECONNRESET);
 
 out0:
-- 
2.19.1



[PATCH 8/8] usb: dwc3: gadget: remove wait_end_transfer

2018-11-04 Thread Felipe Balbi
Now that we have a list of cancelled requests, we can skip over TRBs
when END_TRANSFER command completes.

Signed-off-by: Felipe Balbi 
---
 drivers/usb/dwc3/core.h   |  3 ---
 drivers/usb/dwc3/gadget.c | 40 +--
 2 files changed, 1 insertion(+), 42 deletions(-)

diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 24f0b108b7f6..131028501752 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -639,7 +639,6 @@ struct dwc3_event_buffer {
  * @cancelled_list: list of cancelled requests for this endpoint
  * @pending_list: list of pending requests for this endpoint
  * @started_list: list of started requests on this endpoint
- * @wait_end_transfer: wait_queue_head_t for waiting on End Transfer complete
  * @lock: spinlock for endpoint request queue traversal
  * @regs: pointer to first endpoint register
  * @trb_pool: array of transaction buffers
@@ -664,8 +663,6 @@ struct dwc3_ep {
struct list_headpending_list;
struct list_headstarted_list;
 
-   wait_queue_head_t   wait_end_transfer;
-
spinlock_t  lock;
void __iomem*regs;
 
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index cfe99009210f..9794b8bc2e22 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -638,8 +638,6 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep, 
unsigned int action)
reg |= DWC3_DALEPENA_EP(dep->number);
dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
 
-   init_waitqueue_head(&dep->wait_end_transfer);
-
if (usb_endpoint_xfer_control(desc))
goto out;
 
@@ -1400,15 +1398,11 @@ static int dwc3_gadget_ep_dequeue(struct usb_ep *ep,
if (r == req) {
/* wait until it is processed */
dwc3_stop_active_transfer(dep, true);
-   wait_event_lock_irq(dep->wait_end_transfer,
-   !(dep->flags & 
DWC3_EP_END_TRANSFER_PENDING),
-   dwc->lock);
 
if (!r->trb)
goto out0;
 
dwc3_gadget_move_cancelled_request(req);
-   dwc3_gadget_ep_cleanup_cancelled_requests(dep);
goto out0;
}
dev_err(dwc->dev, "request %pK was not queued to %s\n",
@@ -1913,8 +1907,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
 {
struct dwc3 *dwc = gadget_to_dwc(g);
unsigned long   flags;
-   int epnum;
-   u32 tmo_eps = 0;
 
spin_lock_irqsave(&dwc->lock, flags);
 
@@ -1923,36 +1915,6 @@ static int dwc3_gadget_stop(struct usb_gadget *g)
 
__dwc3_gadget_stop(dwc);
 
-   for (epnum = 2; epnum < DWC3_ENDPOINTS_NUM; epnum++) {
-   struct dwc3_ep  *dep = dwc->eps[epnum];
-   int ret;
-
-   if (!dep)
-   continue;
-
-   if (!(dep->flags & DWC3_EP_END_TRANSFER_PENDING))
-   continue;
-
-   ret = 
wait_event_interruptible_lock_irq_timeout(dep->wait_end_transfer,
-   !(dep->flags & DWC3_EP_END_TRANSFER_PENDING),
-   dwc->lock, msecs_to_jiffies(5));
-
-   if (ret <= 0) {
-   /* Timed out or interrupted! There's nothing much
-* we can do so we just log here and print which
-* endpoints timed out at the end.
-*/
-   tmo_eps |= 1 << epnum;
-   dep->flags &= DWC3_EP_END_TRANSFER_PENDING;
-   }
-   }
-
-   if (tmo_eps) {
-   dev_err(dwc->dev,
-   "end transfer timed out on endpoints 0x%x [bitmap]\n",
-   tmo_eps);
-   }
-
 out:
dwc->gadget_driver  = NULL;
spin_unlock_irqrestore(&dwc->lock, flags);
@@ -2448,7 +2410,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc,
 
if (cmd == DWC3_DEPCMD_ENDTRANSFER) {
dep->flags &= ~DWC3_EP_END_TRANSFER_PENDING;
-   wake_up(&dep->wait_end_transfer);
+   dwc3_gadget_ep_cleanup_cancelled_requests(dep);
}
break;
case DWC3_DEPEVT_STREAMEVT:
-- 
2.19.1



[PATCH] usb: dwc2: Fix ep disable spinlock flow.

2018-11-04 Thread Minas Harutyunyan
Changed spinlock flow to fix smatch warnings.

Fixes: dccf1bad4be7 ("usb: dwc2: Disable all EP's on disconnect")
Signed-off-by: Minas Harutyunyan 
---
 drivers/usb/dwc2/gadget.c | 6 ++
 1 file changed, 2 insertions(+), 4 deletions(-)

diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 2d6d2c8244de..8eb25e3597b0 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -4088,9 +4088,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
 
epctrl_reg = dir_in ? DIEPCTL(index) : DOEPCTL(index);
 
-   locked = spin_is_locked(&hsotg->lock);
-   if (!locked)
-   spin_lock_irqsave(&hsotg->lock, flags);
+   locked = spin_trylock_irqsave(&hsotg->lock, flags);
 
ctrl = dwc2_readl(hsotg, epctrl_reg);
 
@@ -4114,7 +4112,7 @@ static int dwc2_hsotg_ep_disable(struct usb_ep *ep)
hs_ep->fifo_index = 0;
hs_ep->fifo_size = 0;
 
-   if (!locked)
+   if (locked)
spin_unlock_irqrestore(&hsotg->lock, flags);
 
return 0;
-- 
2.11.0



RE: [RFC PATCH v1 13/14] usb:cdns3: Adds debugging function.

2018-11-04 Thread Pawel Laszczak
>> Patch implements some function used for debugging driver.
>[]
>> +static inline char *cdns3_decode_ep_irq(u32 ep_sts, const char *ep_name)
>> +{
>> +static char str[256];
>> +int ret;
>> +
>> +ret = sprintf(str, "IRQ for %s: %08x ", ep_name, ep_sts);
>> +
>> +if (ep_sts & EP_STS_SETUP)
>> +ret += sprintf(str + ret, "SETUP ");
>> +if (ep_sts & EP_STS_IOC)
>> +ret += sprintf(str + ret, "IOC ");
>> +if (ep_sts & EP_STS_ISP)
>> +ret += sprintf(str + ret, "ISP ");
>> +if (ep_sts & EP_STS_DESCMIS)
>> +ret += sprintf(str + ret, "DESCMIS ");
>> +if (ep_sts & EP_STS_STREAMR)
>> +ret += sprintf(str + ret, "STREAMR ");
>> +if (ep_sts & EP_STS_MD_EXIT)
>> +ret += sprintf(str + ret, "MD_EXIT ");
>> +if (ep_sts & EP_STS_TRBERR)
>> +ret += sprintf(str + ret, "TRBERR ");
>> +if (ep_sts & EP_STS_NRDY)
>> +ret += sprintf(str + ret, "NRDY ");
>> +if (ep_sts & EP_STS_PRIME)
>> +ret += sprintf(str + ret, "PRIME ");
>> +if (ep_sts & EP_STS_SIDERR)
>> +ret += sprintf(str + ret, "SIDERRT ");
>> +if (ep_sts & EP_STS_OUTSMM)
>> +ret += sprintf(str + ret, "OUTSMM ");
>> +if (ep_sts & EP_STS_ISOERR)
>> +ret += sprintf(str + ret, "ISOERR ");
>> +if (ep_sts & EP_STS_IOT)
>> +ret += sprintf(str + ret, "IOT ");
>> +
>> +return str;
>> +}
>
>This bit is pretty unsightly.
>Especially the static in each inline

Hi Joe.

I understood that you mean line 
static char str[256];
This array will be defined several times. 

I will remove inline form function definition. 
It's not necessary. 

>> +
>> +char *cdns3_decode_epx_irq(struct cdns3_endpoint *priv_ep)
>> +{
>> +struct cdns3_device *priv_dev = priv_ep->cdns3_dev;
>> +
>> +return cdns3_decode_ep_irq(readl(&priv_dev->regs->ep_sts),
>> +   priv_ep->name);
>> +}
>> +
>> +char *cdns3_decode_ep0_irq(struct cdns3_device *priv_dev, int dir)
>> +{
>> +if (dir)
>> +return cdns3_decode_ep_irq(readl(&priv_dev->regs->ep_sts),
>> +   "ep0IN");
>> +else
>> +return cdns3_decode_ep_irq(readl(&priv_dev->regs->ep_sts),
>> +   "ep0OUT");
>> +}
>> +
>[]
>> diff --git a/drivers/usb/cdns3/ep0.c b/drivers/usb/cdns3/ep0.c
>[]
>> @@ -604,12 +604,15 @@ void cdns3_check_ep0_interrupt_proceed(struct 
>> cdns3_device *priv_dev, int dir)
>>  cdns3_select_ep(priv_dev, 0 | (dir ? USB_DIR_IN : USB_DIR_OUT));
>>  ep_sts_reg = readl(®s->ep_sts);
>>
>> +dev_dbg(&priv_dev->dev, "%s\n", cdns3_decode_ep0_irq(priv_dev, dir));
>[]
>> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c
>[]
>> @@ -537,6 +547,8 @@ static int cdns3_check_ep_interrupt_proceed(struct 
>> cdns3_endpoint *priv_ep)
>>  cdns3_select_ep(priv_dev, priv_ep->endpoint.address);
>>  ep_sts_reg = readl(®s->ep_sts);
>>
>> +dev_dbg(&priv_dev->dev, "%s\n", cdns3_decode_epx_irq(priv_ep));
>>

Thank you for comment.
Cheers Pawel