From: Felipe Balbi <felipe.balbi@linux.intel.com>
Date: Mon, 30 May 2016 10:37:02 +0000 (+0300)
Subject: UPSTREAM: usb: dwc3: gadget: halt and stop based HWO bit
X-Git-Tag: firefly_0821_release~1787
X-Git-Url: http://demsky.eecs.uci.edu/git/?a=commitdiff_plain;h=d5c84f6771e889e45b192fda4fee4886c06f0c55;p=firefly-linux-kernel-4.4.55.git

UPSTREAM: usb: dwc3: gadget: halt and stop based HWO bit

Instead of relying on empty list of queued requests,
let's rely on the fact that we have a TRB being
processed right now.

Change-Id: I06075d3aaf695f74946ebd269746a240be7e51c0
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
Signed-off-by: Wu Liang feng <wulf@rock-chips.com>
(cherry picked from commit 69450c4dc164d9ecbc0b54cb47a2ec80cde45da4)
---

diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 54d2d104d78a..2d3a6c8c4e51 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -600,8 +600,16 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum, bool force);
 static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
 {
 	struct dwc3_request		*req;
+	struct dwc3_trb			*current_trb;
+	unsigned			transfer_in_flight;
 
-	if (!list_empty(&dep->started_list)) {
+	if (dep->number > 1)
+		current_trb = &dep->trb_pool[dep->trb_enqueue];
+	else
+		current_trb = &dwc->ep0_trb[dep->trb_enqueue];
+	transfer_in_flight = current_trb->ctrl & DWC3_TRB_CTRL_HWO;
+
+	if (transfer_in_flight && !list_empty(&dep->started_list)) {
 		dwc3_stop_active_transfer(dwc, dep->number, true);
 
 		/* - giveback all requests to gadget driver */
@@ -1313,9 +1321,21 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol)
 	memset(&params, 0x00, sizeof(params));
 
 	if (value) {
-		if (!protocol && ((dep->direction && dep->flags & DWC3_EP_BUSY) ||
-				(!list_empty(&dep->started_list) ||
-				 !list_empty(&dep->pending_list)))) {
+		struct dwc3_trb *trb;
+
+		unsigned transfer_in_flight;
+		unsigned started;
+
+		if (dep->number > 1)
+			trb = dwc3_ep_prev_trb(dep, dep->trb_enqueue);
+		else
+			trb = &dwc->ep0_trb[dep->trb_enqueue];
+
+		transfer_in_flight = trb->ctrl & DWC3_TRB_CTRL_HWO;
+		started = !list_empty(&dep->started_list);
+
+		if (!protocol && ((dep->direction && transfer_in_flight) ||
+				(!dep->direction && started))) {
 			dwc3_trace(trace_dwc3_gadget,
 					"%s: pending request, cannot halt",
 					dep->name);