diff options
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 30 |
1 files changed, 24 insertions, 6 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 9a7d0bd15dc3..07248ff1be5c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c | |||
@@ -347,6 +347,28 @@ int dwc3_send_gadget_ep_cmd(struct dwc3 *dwc, unsigned ep, | |||
347 | return ret; | 347 | return ret; |
348 | } | 348 | } |
349 | 349 | ||
350 | static int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep) | ||
351 | { | ||
352 | struct dwc3 *dwc = dep->dwc; | ||
353 | struct dwc3_gadget_ep_cmd_params params; | ||
354 | u32 cmd = DWC3_DEPCMD_CLEARSTALL; | ||
355 | |||
356 | /* | ||
357 | * As of core revision 2.60a the recommended programming model | ||
358 | * is to set the ClearPendIN bit when issuing a Clear Stall EP | ||
359 | * command for IN endpoints. This is to prevent an issue where | ||
360 | * some (non-compliant) hosts may not send ACK TPs for pending | ||
361 | * IN transfers due to a mishandled error condition. Synopsys | ||
362 | * STAR 9000614252. | ||
363 | */ | ||
364 | if (dep->direction && (dwc->revision >= DWC3_REVISION_260A)) | ||
365 | cmd |= DWC3_DEPCMD_CLEARPENDIN; | ||
366 | |||
367 | memset(¶ms, 0, sizeof(params)); | ||
368 | |||
369 | return dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); | ||
370 | } | ||
371 | |||
350 | static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, | 372 | static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, |
351 | struct dwc3_trb *trb) | 373 | struct dwc3_trb *trb) |
352 | { | 374 | { |
@@ -1314,8 +1336,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) | |||
1314 | else | 1336 | else |
1315 | dep->flags |= DWC3_EP_STALL; | 1337 | dep->flags |= DWC3_EP_STALL; |
1316 | } else { | 1338 | } else { |
1317 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, | 1339 | ret = dwc3_send_clear_stall_ep_cmd(dep); |
1318 | DWC3_DEPCMD_CLEARSTALL, ¶ms); | ||
1319 | if (ret) | 1340 | if (ret) |
1320 | dev_err(dwc->dev, "failed to clear STALL on %s\n", | 1341 | dev_err(dwc->dev, "failed to clear STALL on %s\n", |
1321 | dep->name); | 1342 | dep->name); |
@@ -2247,7 +2268,6 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) | |||
2247 | 2268 | ||
2248 | for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) { | 2269 | for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) { |
2249 | struct dwc3_ep *dep; | 2270 | struct dwc3_ep *dep; |
2250 | struct dwc3_gadget_ep_cmd_params params; | ||
2251 | int ret; | 2271 | int ret; |
2252 | 2272 | ||
2253 | dep = dwc->eps[epnum]; | 2273 | dep = dwc->eps[epnum]; |
@@ -2259,9 +2279,7 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) | |||
2259 | 2279 | ||
2260 | dep->flags &= ~DWC3_EP_STALL; | 2280 | dep->flags &= ~DWC3_EP_STALL; |
2261 | 2281 | ||
2262 | memset(¶ms, 0, sizeof(params)); | 2282 | ret = dwc3_send_clear_stall_ep_cmd(dep); |
2263 | ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, | ||
2264 | DWC3_DEPCMD_CLEARSTALL, ¶ms); | ||
2265 | WARN_ON_ONCE(ret); | 2283 | WARN_ON_ONCE(ret); |
2266 | } | 2284 | } |
2267 | } | 2285 | } |