diff options
author | Thinh Nguyen <Thinh.Nguyen@synopsys.com> | 2021-11-30 06:21:28 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2021-12-13 16:56:37 +0300 |
commit | 666f3de741f7ce66119b375145d471e89fac21ff (patch) | |
tree | 617844bc3a9cfc6cbb642b70fdb64ffa57ebc5ec /drivers/usb/dwc3/gadget.c | |
parent | c45479ecd0c21705ab078ceaba097bbb730a0541 (diff) | |
download | linux-666f3de741f7ce66119b375145d471e89fac21ff.tar.xz |
usb: dwc3: gadget: Support Multi-Stream Transfer
Synopsys introduced a new enhancement to DWC_usb32 called Multi-Stream
Transfer (MST) to improve bulk streams performance for SuperSpeed and
SuperSpeed Plus. This enhancement allows the controller to look ahead
and process multiple bulk streams.
Previously, to initiate a bulk stream transfer, the driver has to issue
Start Transfer command and wait for the stream to complete before
initiating a new stream. As a result, the controller does not process
TRBs beyond a single stream. With the enhancement, as long as there are
new requests, the dwc3 driver can keep preparing new TRBs and the
controller can keep caching and processing them without waiting for the
transfer completion.
The programming flow is similar to regular bulk endpoint with a few
additional rules:
1) Chained TRBs of the same stream must have a matching stream ID
2) The last TRB of a stream must have CHN=0
3) All the TRBs with LST=0 must have CSP=1
Depends on the application and usage, internal tests show significant
performance improvement in UASP transfers with this enhancement.
Signed-off-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
Link: https://lore.kernel.org/r/cd9c7a8bf11f790983ac546222dd114893f16b3a.1638242424.git.Thinh.Nguyen@synopsys.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/usb/dwc3/gadget.c')
-rw-r--r-- | drivers/usb/dwc3/gadget.c | 26 |
1 files changed, 21 insertions, 5 deletions
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index c0c89374716b..520031ba38aa 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -1275,12 +1275,17 @@ static void __dwc3_prepare_one_trb(struct dwc3_ep *dep, struct dwc3_trb *trb, trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; } + /* All TRBs setup for MST must set CSP=1 when LST=0 */ + if (dep->stream_capable && DWC3_MST_CAPABLE(&dwc->hwparams)) + trb->ctrl |= DWC3_TRB_CTRL_CSP; + if ((!no_interrupt && !chain) || must_interrupt) trb->ctrl |= DWC3_TRB_CTRL_IOC; if (chain) trb->ctrl |= DWC3_TRB_CTRL_CHN; - else if (dep->stream_capable && is_last) + else if (dep->stream_capable && is_last && + !DWC3_MST_CAPABLE(&dwc->hwparams)) trb->ctrl |= DWC3_TRB_CTRL_LST; if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) @@ -1528,7 +1533,8 @@ static int dwc3_prepare_trbs(struct dwc3_ep *dep) * burst capability may try to read and use TRBs beyond the * active transfer instead of stopping. */ - if (dep->stream_capable && req->request.is_last) + if (dep->stream_capable && req->request.is_last && + !DWC3_MST_CAPABLE(&dep->dwc->hwparams)) return ret; } @@ -1561,7 +1567,8 @@ static int dwc3_prepare_trbs(struct dwc3_ep *dep) * burst capability may try to read and use TRBs beyond the * active transfer instead of stopping. */ - if (dep->stream_capable && req->request.is_last) + if (dep->stream_capable && req->request.is_last && + !DWC3_MST_CAPABLE(&dwc->hwparams)) return ret; } @@ -1638,7 +1645,8 @@ static int __dwc3_gadget_kick_transfer(struct dwc3_ep *dep) return ret; } - if (dep->stream_capable && req->request.is_last) + if (dep->stream_capable && req->request.is_last && + !DWC3_MST_CAPABLE(&dep->dwc->hwparams)) dep->flags |= DWC3_EP_WAIT_TRANSFER_COMPLETE; return 0; @@ -2653,6 +2661,13 @@ static int __dwc3_gadget_start(struct dwc3 *dwc) reg |= DWC3_DCFG_IGNSTRMPP; dwc3_writel(dwc->regs, DWC3_DCFG, reg); + /* Enable MST by default if the device is capable of MST */ + if (DWC3_MST_CAPABLE(&dwc->hwparams)) { + reg = dwc3_readl(dwc->regs, DWC3_DCFG1); + reg &= ~DWC3_DCFG1_DIS_MST_ENH; + dwc3_writel(dwc->regs, DWC3_DCFG1, reg); + } + /* Start with SuperSpeed Default */ dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); @@ -3452,7 +3467,8 @@ static void dwc3_gadget_endpoint_stream_event(struct dwc3_ep *dep, case DEPEVT_STREAM_NOSTREAM: if ((dep->flags & DWC3_EP_IGNORE_NEXT_NOSTREAM) || !(dep->flags & DWC3_EP_FORCE_RESTART_STREAM) || - !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE)) + (!DWC3_MST_CAPABLE(&dwc->hwparams) && + !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE))) break; /* |