Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Thinh Nguyen and committed by
Greg Kroah-Hartman
666f3de7 c45479ec

+30 -5
+9
drivers/usb/dwc3/core.h
··· 153 153 #define DWC3_DGCMDPAR 0xc710 154 154 #define DWC3_DGCMD 0xc714 155 155 #define DWC3_DALEPENA 0xc720 156 + #define DWC3_DCFG1 0xc740 /* DWC_usb32 only */ 156 157 157 158 #define DWC3_DEP_BASE(n) (0xc800 + ((n) * 0x10)) 158 159 #define DWC3_DEPCMDPAR2 0x00 ··· 383 382 384 383 /* Global HWPARAMS9 Register */ 385 384 #define DWC3_GHWPARAMS9_DEV_TXF_FLUSH_BYPASS BIT(0) 385 + #define DWC3_GHWPARAMS9_DEV_MST BIT(1) 386 386 387 387 /* Global Frame Length Adjustment Register */ 388 388 #define DWC3_GFLADJ_30MHZ_SDBND_SEL BIT(7) ··· 559 557 560 558 /* The EP number goes 0..31 so ep0 is always out and ep1 is always in */ 561 559 #define DWC3_DALEPENA_EP(n) BIT(n) 560 + 561 + /* DWC_usb32 DCFG1 config */ 562 + #define DWC3_DCFG1_DIS_MST_ENH BIT(1) 562 563 563 564 #define DWC3_DEPCMD_TYPE_CONTROL 0 564 565 #define DWC3_DEPCMD_TYPE_ISOC 1 ··· 892 887 893 888 /* HWPARAMS7 */ 894 889 #define DWC3_RAM1_DEPTH(n) ((n) & 0xffff) 890 + 891 + /* HWPARAMS9 */ 892 + #define DWC3_MST_CAPABLE(p) (!!((p)->hwparams9 & \ 893 + DWC3_GHWPARAMS9_DEV_MST)) 895 894 896 895 /** 897 896 * struct dwc3_request - representation of a transfer request
+21 -5
drivers/usb/dwc3/gadget.c
··· 1275 1275 trb->ctrl |= DWC3_TRB_CTRL_ISP_IMI; 1276 1276 } 1277 1277 1278 + /* All TRBs setup for MST must set CSP=1 when LST=0 */ 1279 + if (dep->stream_capable && DWC3_MST_CAPABLE(&dwc->hwparams)) 1280 + trb->ctrl |= DWC3_TRB_CTRL_CSP; 1281 + 1278 1282 if ((!no_interrupt && !chain) || must_interrupt) 1279 1283 trb->ctrl |= DWC3_TRB_CTRL_IOC; 1280 1284 1281 1285 if (chain) 1282 1286 trb->ctrl |= DWC3_TRB_CTRL_CHN; 1283 - else if (dep->stream_capable && is_last) 1287 + else if (dep->stream_capable && is_last && 1288 + !DWC3_MST_CAPABLE(&dwc->hwparams)) 1284 1289 trb->ctrl |= DWC3_TRB_CTRL_LST; 1285 1290 1286 1291 if (usb_endpoint_xfer_bulk(dep->endpoint.desc) && dep->stream_capable) ··· 1533 1528 * burst capability may try to read and use TRBs beyond the 1534 1529 * active transfer instead of stopping. 1535 1530 */ 1536 - if (dep->stream_capable && req->request.is_last) 1531 + if (dep->stream_capable && req->request.is_last && 1532 + !DWC3_MST_CAPABLE(&dep->dwc->hwparams)) 1537 1533 return ret; 1538 1534 } 1539 1535 ··· 1567 1561 * burst capability may try to read and use TRBs beyond the 1568 1562 * active transfer instead of stopping. 1569 1563 */ 1570 - if (dep->stream_capable && req->request.is_last) 1564 + if (dep->stream_capable && req->request.is_last && 1565 + !DWC3_MST_CAPABLE(&dwc->hwparams)) 1571 1566 return ret; 1572 1567 } 1573 1568 ··· 1645 1638 return ret; 1646 1639 } 1647 1640 1648 - if (dep->stream_capable && req->request.is_last) 1641 + if (dep->stream_capable && req->request.is_last && 1642 + !DWC3_MST_CAPABLE(&dep->dwc->hwparams)) 1649 1643 dep->flags |= DWC3_EP_WAIT_TRANSFER_COMPLETE; 1650 1644 1651 1645 return 0; ··· 2661 2653 reg |= DWC3_DCFG_IGNSTRMPP; 2662 2654 dwc3_writel(dwc->regs, DWC3_DCFG, reg); 2663 2655 2656 + /* Enable MST by default if the device is capable of MST */ 2657 + if (DWC3_MST_CAPABLE(&dwc->hwparams)) { 2658 + reg = dwc3_readl(dwc->regs, DWC3_DCFG1); 2659 + reg &= ~DWC3_DCFG1_DIS_MST_ENH; 2660 + dwc3_writel(dwc->regs, DWC3_DCFG1, reg); 2661 + } 2662 + 2664 2663 /* Start with SuperSpeed Default */ 2665 2664 dwc3_gadget_ep0_desc.wMaxPacketSize = cpu_to_le16(512); 2666 2665 ··· 3467 3452 case DEPEVT_STREAM_NOSTREAM: 3468 3453 if ((dep->flags & DWC3_EP_IGNORE_NEXT_NOSTREAM) || 3469 3454 !(dep->flags & DWC3_EP_FORCE_RESTART_STREAM) || 3470 - !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE)) 3455 + (!DWC3_MST_CAPABLE(&dwc->hwparams) && 3456 + !(dep->flags & DWC3_EP_WAIT_TRANSFER_COMPLETE))) 3471 3457 break; 3472 3458 3473 3459 /*