diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-07-24 12:51:10 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2016-07-24 12:51:10 -0400 |
commit | dc05973b288a5226bb7e56afd6c2fa07560a907c (patch) | |
tree | 2e1eade8b6010ff4c844341fdeec9ee966d75ac7 /drivers/usb/dwc3/gadget.c | |
parent | 297fae4d0bee5d683533f3324baf1b363e7b48bf (diff) | |
parent | e7bdea7750eb2a64aea4a08fa5c0a31719c8155d (diff) |
Merge commit 'e7bdea7750eb'
Needed in order to work on top of pNFS changes in Linus' upstream kernel.
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, return ret; } +static int dwc3_send_clear_stall_ep_cmd(struct dwc3_ep *dep) +{ + struct dwc3 *dwc = dep->dwc; + struct dwc3_gadget_ep_cmd_params params; + u32 cmd = DWC3_DEPCMD_CLEARSTALL; + + /* + * As of core revision 2.60a the recommended programming model + * is to set the ClearPendIN bit when issuing a Clear Stall EP + * command for IN endpoints. This is to prevent an issue where + * some (non-compliant) hosts may not send ACK TPs for pending + * IN transfers due to a mishandled error condition. Synopsys + * STAR 9000614252. + */ + if (dep->direction && (dwc->revision >= DWC3_REVISION_260A)) + cmd |= DWC3_DEPCMD_CLEARPENDIN; + + memset(¶ms, 0, sizeof(params)); + + return dwc3_send_gadget_ep_cmd(dwc, dep->number, cmd, ¶ms); +} + static dma_addr_t dwc3_trb_dma_offset(struct dwc3_ep *dep, struct dwc3_trb *trb) { @@ -1314,8 +1336,7 @@ int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) else dep->flags |= DWC3_EP_STALL; } else { - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_CLEARSTALL, ¶ms); + ret = dwc3_send_clear_stall_ep_cmd(dep); if (ret) dev_err(dwc->dev, "failed to clear STALL on %s\n", dep->name); @@ -2247,7 +2268,6 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) for (epnum = 1; epnum < DWC3_ENDPOINTS_NUM; epnum++) { struct dwc3_ep *dep; - struct dwc3_gadget_ep_cmd_params params; int ret; dep = dwc->eps[epnum]; @@ -2259,9 +2279,7 @@ static void dwc3_clear_stall_all_ep(struct dwc3 *dwc) dep->flags &= ~DWC3_EP_STALL; - memset(¶ms, 0, sizeof(params)); - ret = dwc3_send_gadget_ep_cmd(dwc, dep->number, - DWC3_DEPCMD_CLEARSTALL, ¶ms); + ret = dwc3_send_clear_stall_ep_cmd(dep); WARN_ON_ONCE(ret); } } |