diff options
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 55 |
1 files changed, 33 insertions, 22 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 8f8c2157910e..1f5597ef945d 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -829,7 +829,7 @@ static void dwc3_prepare_one_trb(struct dwc3_ep *dep, | |||
829 | if (!req->request.no_interrupt && !chain) | 829 | if (!req->request.no_interrupt && !chain) |
830 | trb->ctrl |= DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI; | 830 | trb->ctrl |= DWC3_TRB_CTRL_IOC | DWC3_TRB_CTRL_ISP_IMI; |
831 | 831 | ||
832 | if (last) | 832 | if (last && !usb_endpoint_xfer_isoc(dep->endpoint.desc)) |
833 | trb->ctrl |= DWC3_TRB_CTRL_LST; | 833 | trb->ctrl |= DWC3_TRB_CTRL_LST; |
834 | 834 | ||
835 | if (chain) | 835 | if (chain) |
@@ -1955,7 +1955,8 @@ static void dwc3_gadget_free_endpoints(struct dwc3 *dwc) | |||
1955 | 1955 | ||
1956 | static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, | 1956 | static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, |
1957 | struct dwc3_request *req, struct dwc3_trb *trb, | 1957 | struct dwc3_request *req, struct dwc3_trb *trb, |
1958 | const struct dwc3_event_depevt *event, int status) | 1958 | const struct dwc3_event_depevt *event, int status, |
1959 | int chain) | ||
1959 | { | 1960 | { |
1960 | unsigned int count; | 1961 | unsigned int count; |
1961 | unsigned int s_pkt = 0; | 1962 | unsigned int s_pkt = 0; |
@@ -1964,17 +1965,22 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
1964 | dep->queued_requests--; | 1965 | dep->queued_requests--; |
1965 | trace_dwc3_complete_trb(dep, trb); | 1966 | trace_dwc3_complete_trb(dep, trb); |
1966 | 1967 | ||
1968 | /* | ||
1969 | * If we're in the middle of series of chained TRBs and we | ||
1970 | * receive a short transfer along the way, DWC3 will skip | ||
1971 | * through all TRBs including the last TRB in the chain (the | ||
1972 | * where CHN bit is zero. DWC3 will also avoid clearing HWO | ||
1973 | * bit and SW has to do it manually. | ||
1974 | * | ||
1975 | * We're going to do that here to avoid problems of HW trying | ||
1976 | * to use bogus TRBs for transfers. | ||
1977 | */ | ||
1978 | if (chain && (trb->ctrl & DWC3_TRB_CTRL_HWO)) | ||
1979 | trb->ctrl &= ~DWC3_TRB_CTRL_HWO; | ||
1980 | |||
1967 | if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) | 1981 | if ((trb->ctrl & DWC3_TRB_CTRL_HWO) && status != -ESHUTDOWN) |
1968 | /* | 1982 | return 1; |
1969 | * We continue despite the error. There is not much we | 1983 | |
1970 | * can do. If we don't clean it up we loop forever. If | ||
1971 | * we skip the TRB then it gets overwritten after a | ||
1972 | * while since we use them in a ring buffer. A BUG() | ||
1973 | * would help. Lets hope that if this occurs, someone | ||
1974 | * fixes the root cause instead of looking away :) | ||
1975 | */ | ||
1976 | dev_err(dwc->dev, "%s's TRB (%p) still owned by HW\n", | ||
1977 | dep->name, trb); | ||
1978 | count = trb->size & DWC3_TRB_SIZE_MASK; | 1984 | count = trb->size & DWC3_TRB_SIZE_MASK; |
1979 | 1985 | ||
1980 | if (dep->direction) { | 1986 | if (dep->direction) { |
@@ -2013,15 +2019,7 @@ static int __dwc3_cleanup_done_trbs(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
2013 | s_pkt = 1; | 2019 | s_pkt = 1; |
2014 | } | 2020 | } |
2015 | 2021 | ||
2016 | /* | 2022 | if (s_pkt && !chain) |
2017 | * We assume here we will always receive the entire data block | ||
2018 | * which we should receive. Meaning, if we program RX to | ||
2019 | * receive 4K but we receive only 2K, we assume that's all we | ||
2020 | * should receive and we simply bounce the request back to the | ||
2021 | * gadget driver for further processing. | ||
2022 | */ | ||
2023 | req->request.actual += req->request.length - count; | ||
2024 | if (s_pkt) | ||
2025 | return 1; | 2023 | return 1; |
2026 | if ((event->status & DEPEVT_STATUS_LST) && | 2024 | if ((event->status & DEPEVT_STATUS_LST) && |
2027 | (trb->ctrl & (DWC3_TRB_CTRL_LST | | 2025 | (trb->ctrl & (DWC3_TRB_CTRL_LST | |
@@ -2040,13 +2038,17 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
2040 | struct dwc3_trb *trb; | 2038 | struct dwc3_trb *trb; |
2041 | unsigned int slot; | 2039 | unsigned int slot; |
2042 | unsigned int i; | 2040 | unsigned int i; |
2041 | int count = 0; | ||
2043 | int ret; | 2042 | int ret; |
2044 | 2043 | ||
2045 | do { | 2044 | do { |
2045 | int chain; | ||
2046 | |||
2046 | req = next_request(&dep->started_list); | 2047 | req = next_request(&dep->started_list); |
2047 | if (WARN_ON_ONCE(!req)) | 2048 | if (WARN_ON_ONCE(!req)) |
2048 | return 1; | 2049 | return 1; |
2049 | 2050 | ||
2051 | chain = req->request.num_mapped_sgs > 0; | ||
2050 | i = 0; | 2052 | i = 0; |
2051 | do { | 2053 | do { |
2052 | slot = req->first_trb_index + i; | 2054 | slot = req->first_trb_index + i; |
@@ -2054,13 +2056,22 @@ static int dwc3_cleanup_done_reqs(struct dwc3 *dwc, struct dwc3_ep *dep, | |||
2054 | slot++; | 2056 | slot++; |
2055 | slot %= DWC3_TRB_NUM; | 2057 | slot %= DWC3_TRB_NUM; |
2056 | trb = &dep->trb_pool[slot]; | 2058 | trb = &dep->trb_pool[slot]; |
2059 | count += trb->size & DWC3_TRB_SIZE_MASK; | ||
2057 | 2060 | ||
2058 | ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, | 2061 | ret = __dwc3_cleanup_done_trbs(dwc, dep, req, trb, |
2059 | event, status); | 2062 | event, status, chain); |
2060 | if (ret) | 2063 | if (ret) |
2061 | break; | 2064 | break; |
2062 | } while (++i < req->request.num_mapped_sgs); | 2065 | } while (++i < req->request.num_mapped_sgs); |
2063 | 2066 | ||
2067 | /* | ||
2068 | * We assume here we will always receive the entire data block | ||
2069 | * which we should receive. Meaning, if we program RX to | ||
2070 | * receive 4K but we receive only 2K, we assume that's all we | ||
2071 | * should receive and we simply bounce the request back to the | ||
2072 | * gadget driver for further processing. | ||
2073 | */ | ||
2074 | req->request.actual += req->request.length - count; | ||
2064 | dwc3_gadget_giveback(dep, req, status); | 2075 | dwc3_gadget_giveback(dep, req, status); |
2065 | 2076 | ||
2066 | if (ret) | 2077 | if (ret) |