diff options
author | Felipe Balbi <balbi@ti.com> | 2012-02-17 05:10:04 -0500 |
---|---|---|
committer | Felipe Balbi <balbi@ti.com> | 2012-06-06 04:22:24 -0400 |
commit | ea53b8828c50b7a5138a8931c41b2671682c86b5 (patch) | |
tree | 1e2e7c519313478a30342ed757641bbef7c21294 /drivers/usb/dwc3/gadget.c | |
parent | 6dbc10c61d5841f64945fd94977fa8fa1c0192da (diff) |
usb: dwc3: gadget: don't wait for ep cmd IRQ
That IRQ is causing way too much trouble. We have
a different handling which was agreed with IP
provider and has been tested with FPGA and OMAP5.
Tested-by: Pratyush Anand <pratyush.anand@st.com>
Signed-off-by: Felipe Balbi <balbi@ti.com>
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 66 |
1 files changed, 27 insertions, 39 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 056ace8ab97d..0f19978d4840 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -555,9 +555,34 @@ static void dwc3_remove_requests(struct dwc3 *dwc, struct dwc3_ep *dep) | |||
555 | { | 555 | { |
556 | struct dwc3_request *req; | 556 | struct dwc3_request *req; |
557 | 557 | ||
558 | if (!list_empty(&dep->req_queued)) | 558 | if (!list_empty(&dep->req_queued)) { |
559 | dwc3_stop_active_transfer(dwc, dep->number); | 559 | dwc3_stop_active_transfer(dwc, dep->number); |
560 | 560 | ||
561 | /* | ||
562 | * NOTICE: We are violating what the Databook says about the | ||
563 | * EndTransfer command. Ideally we would _always_ wait for the | ||
564 | * EndTransfer Command Completion IRQ, but that's causing too | ||
565 | * much trouble synchronizing between us and gadget driver. | ||
566 | * | ||
567 | * We have discussed this with the IP Provider and it was | ||
568 | * suggested to giveback all requests here, but give HW some | ||
569 | * extra time to synchronize with the interconnect. We're using | ||
570 | * an arbitraty 100us delay for that. | ||
571 | * | ||
572 | * Note also that a similar handling was tested by Synopsys | ||
573 | * (thanks a lot Paul) and nothing bad has come out of it. | ||
574 | * In short, what we're doing is: | ||
575 | * | ||
576 | * - Issue EndTransfer WITH CMDIOC bit set | ||
577 | * - Wait 100us | ||
578 | * - giveback all requests to gadget driver | ||
579 | */ | ||
580 | udelay(100); | ||
581 | |||
582 | req = next_request(&dep->req_queued); | ||
583 | dwc3_gadget_giveback(dep, req, -ESHUTDOWN); | ||
584 | } | ||
585 | |||
561 | while (!list_empty(&dep->request_list)) { | 586 | while (!list_empty(&dep->request_list)) { |
562 | req = next_request(&dep->request_list); | 587 | req = next_request(&dep->request_list); |
563 | 588 | ||
@@ -1735,43 +1760,6 @@ static void dwc3_endpoint_transfer_complete(struct dwc3 *dwc, | |||
1735 | } | 1760 | } |
1736 | } | 1761 | } |
1737 | 1762 | ||
1738 | static void dwc3_process_ep_cmd_complete(struct dwc3_ep *dep, | ||
1739 | const struct dwc3_event_depevt *event) | ||
1740 | { | ||
1741 | struct dwc3 *dwc = dep->dwc; | ||
1742 | struct dwc3_event_depevt mod_ev = *event; | ||
1743 | |||
1744 | /* | ||
1745 | * We were asked to remove one request. It is possible that this | ||
1746 | * request and a few others were started together and have the same | ||
1747 | * transfer index. Since we stopped the complete endpoint we don't | ||
1748 | * know how many requests were already completed (and not yet) | ||
1749 | * reported and how could be done (later). We purge them all until | ||
1750 | * the end of the list. | ||
1751 | */ | ||
1752 | mod_ev.status = DEPEVT_STATUS_LST; | ||
1753 | dwc3_cleanup_done_reqs(dwc, dep, &mod_ev, -ESHUTDOWN); | ||
1754 | dep->flags &= ~DWC3_EP_BUSY; | ||
1755 | /* pending requests are ignored and are queued on XferNotReady */ | ||
1756 | } | ||
1757 | |||
1758 | static void dwc3_ep_cmd_compl(struct dwc3_ep *dep, | ||
1759 | const struct dwc3_event_depevt *event) | ||
1760 | { | ||
1761 | u32 param = event->parameters; | ||
1762 | u32 cmd_type = (param >> 8) & ((1 << 5) - 1); | ||
1763 | |||
1764 | switch (cmd_type) { | ||
1765 | case DWC3_DEPCMD_ENDTRANSFER: | ||
1766 | dwc3_process_ep_cmd_complete(dep, event); | ||
1767 | break; | ||
1768 | default: | ||
1769 | printk(KERN_ERR "%s() unknown /unexpected type: %d\n", | ||
1770 | __func__, cmd_type); | ||
1771 | break; | ||
1772 | }; | ||
1773 | } | ||
1774 | |||
1775 | static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | 1763 | static void dwc3_endpoint_interrupt(struct dwc3 *dwc, |
1776 | const struct dwc3_event_depevt *event) | 1764 | const struct dwc3_event_depevt *event) |
1777 | { | 1765 | { |
@@ -1853,7 +1841,7 @@ static void dwc3_endpoint_interrupt(struct dwc3 *dwc, | |||
1853 | dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); | 1841 | dev_dbg(dwc->dev, "%s FIFO Overrun\n", dep->name); |
1854 | break; | 1842 | break; |
1855 | case DWC3_DEPEVT_EPCMDCMPLT: | 1843 | case DWC3_DEPEVT_EPCMDCMPLT: |
1856 | dwc3_ep_cmd_compl(dep, event); | 1844 | dev_vdbg(dwc->dev, "Endpoint Command Complete\n"); |
1857 | break; | 1845 | break; |
1858 | } | 1846 | } |
1859 | } | 1847 | } |