aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/dwc3
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2011-08-29 07:56:37 -0400
committerFelipe Balbi <balbi@ti.com>2011-09-09 06:02:10 -0400
commit624407f96f134bcd3063eb0d404fc6d41323bef8 (patch)
treea51495355d6bda9a0289e5a3ea14448fd1f44386 /drivers/usb/dwc3
parent7650bd74d3441907867276dc381b2ee0dc355c65 (diff)
usb: dwc3: gadget: rework the dequeue on RESET & DISCONNECT
- since a while we are disabling an endpoint and purging every requests on RESET and DISCONNECT which leads to a warning since the endpoint was disabled twice (once by the UDC, and second time by the gadget). I think UDC should nuke all requests because all those requests become invalid. It's gadget driver's responsability, though, to disable its used endpoints. This is done by merging dwc3_stop_active_transfer() and dwc3_gadget_nuke_reqs() into dwc3_remove_requests(). - dwc3_stop_active_transfer() is now no longer called unconditionaly. This has the advantage that it is always called to disable an active transfer which means if res_trans_idx 0 than something went wrong and it is an error condition because we can't clean up the requests. - Remove the DWC3_EP_WILL_SHUTDOWN which was introduced while introducing the command complete part for dequeue. All requests on req_queued list should be removed during the dwc3_cleanup_done_reqs() callback so there is no reason to go through the list again. We consider it an error condition if requests are still on this list since we never queue TRB without LST=1 (the last requests has always LST=1, there are no requests with LST=0 behind it). [ balbi@ti.com : reworked commit log a bit, made patch apply ] Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3')
-rw-r--r--drivers/usb/dwc3/core.h1
-rw-r--r--drivers/usb/dwc3/gadget.c31
2 files changed, 12 insertions, 20 deletions
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index 01892b12396a..6c1ff7a58fcb 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -348,7 +348,6 @@ struct dwc3_ep {
348#define DWC3_EP_WEDGE (1 << 2) 348#define DWC3_EP_WEDGE (1 << 2)
349#define DWC3_EP_BUSY (1 << 4) 349#define DWC3_EP_BUSY (1 << 4)
350#define DWC3_EP_PENDING_REQUEST (1 << 5) 350#define DWC3_EP_PENDING_REQUEST (1 << 5)
351#define DWC3_EP_WILL_SHUTDOWN (1 << 6)
352 351
353 /* This last one is specific to EP0 */ 352 /* This last one is specific to EP0 */
354#define DWC3_EP0_DIR_IN (1 << 31) 353#define DWC3_EP0_DIR_IN (1 << 31)
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index b4f1aefb4289..7c014e9c1277 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -359,34 +359,36 @@ static int __dwc3_gadget_ep_enable(struct dwc3_ep *dep,
359 return 0; 359 return 0;
360} 360}
361 361
362static void dwc3_gadget_nuke_reqs(struct dwc3_ep *dep, const int status) 362static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum);
363static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep)
363{ 364{
364 struct dwc3_request *req; 365 struct dwc3_request *req;
365 366
367 if (!list_empty(&dep->req_queued))
368 dwc3_stop_active_transfer(dwc, dep->number);
369
366 while (!list_empty(&dep->request_list)) { 370 while (!list_empty(&dep->request_list)) {
367 req = next_request(&dep->request_list); 371 req = next_request(&dep->request_list);
368 372
369 dwc3_gadget_giveback(dep, req, status); 373 dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
370 } 374 }
371 /* nuke queued TRBs as well on command complete */
372 dep->flags |= DWC3_EP_WILL_SHUTDOWN;
373} 375}
374 376
375/** 377/**
376 * __dwc3_gadget_ep_disable - Disables a HW endpoint 378 * __dwc3_gadget_ep_disable - Disables a HW endpoint
377 * @dep: the endpoint to disable 379 * @dep: the endpoint to disable
378 * 380 *
379 * Caller should take care of locking 381 * This function also removes requests which are currently processed ny the
382 * hardware and those which are not yet scheduled.
383 * Caller should take care of locking.
380 */ 384 */
381static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum);
382static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) 385static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep)
383{ 386{
384 struct dwc3 *dwc = dep->dwc; 387 struct dwc3 *dwc = dep->dwc;
385 u32 reg; 388 u32 reg;
386 389
387 dep->flags &= ~DWC3_EP_ENABLED; 390 dep->flags &= ~DWC3_EP_ENABLED;
388 dwc3_stop_active_transfer(dwc, dep->number); 391 dwc3_remove_requests(dwc, dep);
389 dwc3_gadget_nuke_reqs(dep, -ESHUTDOWN);
390 392
391 reg = dwc3_readl(dwc->regs, DWC3_DALEPENA); 393 reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
392 reg &= ~DWC3_DALEPENA_EP(dep->number); 394 reg &= ~DWC3_DALEPENA_EP(dep->number);
@@ -1416,16 +1418,6 @@ static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep,
1416 dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN); 1418 dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN);
1417 dep->flags &= ~DWC3_EP_BUSY; 1419 dep->flags &= ~DWC3_EP_BUSY;
1418 /* pending requets are ignored and are queued on XferNotReady */ 1420 /* pending requets are ignored and are queued on XferNotReady */
1419
1420 if (dep->flags & DWC3_EP_WILL_SHUTDOWN) {
1421 while (!list_empty(&dep->req_queued)) {
1422 struct dwc3_request *req;
1423
1424 req = next_request(&dep->req_queued);
1425 dwc3_gadget_giveback(dep, req, -ESHUTDOWN);
1426 }
1427 dep->flags &= ~DWC3_EP_WILL_SHUTDOWN;
1428 }
1429} 1421}
1430 1422
1431static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, 1423static void dwc3_ep_cmd_compl(struct dwc3_ep *dep,
@@ -1533,6 +1525,7 @@ static void dwc3_stop_active_transfer(struct dwc3 *dwc, u32 epnum)
1533 1525
1534 dep = dwc->eps[epnum]; 1526 dep = dwc->eps[epnum];
1535 1527
1528 WARN_ON(!dep->res_trans_idx);
1536 if (dep->res_trans_idx) { 1529 if (dep->res_trans_idx) {
1537 cmd = DWC3_DEPCMD_ENDTRANSFER; 1530 cmd = DWC3_DEPCMD_ENDTRANSFER;
1538 cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC; 1531 cmd |= DWC3_DEPCMD_HIPRI_FORCERM | DWC3_DEPCMD_CMDIOC;
@@ -1555,7 +1548,7 @@ static void dwc3_stop_active_transfers(struct dwc3 *dwc)
1555 if (!(dep->flags & DWC3_EP_ENABLED)) 1548 if (!(dep->flags & DWC3_EP_ENABLED))
1556 continue; 1549 continue;
1557 1550
1558 __dwc3_gadget_ep_disable(dep); 1551 dwc3_remove_requests(dwc, dep);
1559 } 1552 }
1560} 1553}
1561 1554