• Frank Li's avatar
    usb: cdns3: fix uvc failure work since sg support enabled · 1b8be5ec
    Frank Li authored
    When IP version >= DEV_VER_V2, gadget:sg_supported is true. So uvc gadget
    function driver will use sg to equeue data, first is 8bytes header, the
    second is 1016bytes data.
    
        cdns3_prepare_trb: ep2in: trb 0000000000ac755f, dma buf: 0xbf455000, size: 8, burst: 128 ctrl: 0x00000415 (C=1, T=0, ISP, CHAIN, Normal)
        cdns3_prepare_trb: ep2in: trb 00000000a574e693, dma buf: 0xc0200fe0, size: 1016, burst: 128 ctrl: 0x00000405 (C=1, T=0, ISP, Normal)
    
    But cdns3_ep_run_transfer() can't correctly handle this case, which only
    support one TRB for ISO transfer.
    
    The controller requires duplicate the TD for each SOF if priv_ep->interval
    is not 1. DMA will read data from DDR to internal FIFO when get SOF. Send
    data to bus when receive IN token. DMA always refill FIFO when get SOF
    regardless host send IN token or not. If host send IN token later, some
    frames data will be lost.
    
    Fixed it by below major steps:
    
    1. Calculate numembers of TRB base on sg_nums and priv_ep->interval.
    2. Remove CHAIN flags for each end TRB of TD when duplicate TD.
    3. The controller requires LINK TRB must be first TRB of TD. When check
    there are not enough TRBs lefts, just fill LINK TRB for left TRBs.
    
    .... CHAIN_TRB DATA_TRB, CHAIN_TRB DATA_TRB,  LINK_TRB ... LINK_TRB
                                                               ^End of TRB List
    
    Cc:  <stable@vger.kernel.org>
    Fixes: 7733f6c3 ("usb: cdns3: Add Cadence USB3 DRD Driver")
    Signed-off-by: default avatarFrank Li <Frank.Li@nxp.com>
    Link: https://lore.kernel.org/r/20231224153816.1664687-2-Frank.Li@nxp.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    1b8be5ec
cdns3-gadget.c 91.7 KB