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

usb: cdns3: allocate TX FIFO size according to composite EP number

Some devices have USB compositions which may require multiple endpoints.
To get better performance, need bigger CDNS3_EP_BUF_SIZE.

But bigger CDNS3_EP_BUF_SIZE may exceed total hardware FIFO size when
multiple endpoints.

By introducing the check_config() callback, calculate CDNS3_EP_BUF_SIZE.

Move CDNS3_EP_BUF_SIZE into cnds3_device: ep_buf_size
Combine CDNS3_EP_ISO_SS_BURST and CDNS3_EP_ISO_HS_MULT into
cnds3_device:ep_iso_burst

Using a simple algorithm to calculate ep_buf_size.
ep_buf_size = ep_iso_burst = (onchip_buffers - 2k) / (number of IN EP +
1).

Test at 8qxp:

Gadget ep_buf_size

RNDIS: 5
RNDIS+ACM: 3
Mass Storage + NCM + ACM 2

Previous CDNS3_EP_BUF_SIZE is 4, RNDIS + ACM will be failure because
exceed FIFO memory.

Acked-by: Peter Chen <peter.chen@kernel.org>
Signed-off-by: Frank Li <Frank.Li@nxp.com>
Link: https://lore.kernel.org/r/20220509164055.1815081-1-Frank.Li@nxp.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Frank Li and committed by
Greg Kroah-Hartman
dce49449 9d778f0c

+49 -7
+43 -4
drivers/usb/cdns3/cdns3-gadget.c
··· 2038 2038 u8 mult = 0; 2039 2039 int ret; 2040 2040 2041 - buffering = CDNS3_EP_BUF_SIZE - 1; 2041 + buffering = priv_dev->ep_buf_size - 1; 2042 2042 2043 2043 cdns3_configure_dmult(priv_dev, priv_ep); 2044 2044 ··· 2057 2057 break; 2058 2058 default: 2059 2059 ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); 2060 - mult = CDNS3_EP_ISO_HS_MULT - 1; 2060 + mult = priv_dev->ep_iso_burst - 1; 2061 2061 buffering = mult + 1; 2062 2062 } 2063 2063 ··· 2073 2073 mult = 0; 2074 2074 max_packet_size = 1024; 2075 2075 if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) { 2076 - maxburst = CDNS3_EP_ISO_SS_BURST - 1; 2076 + maxburst = priv_dev->ep_iso_burst - 1; 2077 2077 buffering = (mult + 1) * 2078 2078 (maxburst + 1); 2079 2079 2080 2080 if (priv_ep->interval > 1) 2081 2081 buffering++; 2082 2082 } else { 2083 - maxburst = CDNS3_EP_BUF_SIZE - 1; 2083 + maxburst = priv_dev->ep_buf_size - 1; 2084 2084 } 2085 2085 break; 2086 2086 default: ··· 2094 2094 priv_ep->trb_burst_size = 64; 2095 2095 else 2096 2096 priv_ep->trb_burst_size = 16; 2097 + 2098 + mult = min_t(u8, mult, EP_CFG_MULT_MAX); 2099 + buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX); 2100 + maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX); 2097 2101 2098 2102 /* onchip buffer is only allocated before configuration */ 2099 2103 if (!priv_dev->hw_configured_flag) { ··· 2965 2961 return 0; 2966 2962 } 2967 2963 2964 + /** 2965 + * cdns3_gadget_check_config - ensure cdns3 can support the USB configuration 2966 + * @gadget: pointer to the USB gadget 2967 + * 2968 + * Used to record the maximum number of endpoints being used in a USB composite 2969 + * device. (across all configurations) This is to be used in the calculation 2970 + * of the TXFIFO sizes when resizing internal memory for individual endpoints. 2971 + * It will help ensured that the resizing logic reserves enough space for at 2972 + * least one max packet. 2973 + */ 2974 + static int cdns3_gadget_check_config(struct usb_gadget *gadget) 2975 + { 2976 + struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); 2977 + struct usb_ep *ep; 2978 + int n_in = 0; 2979 + int total; 2980 + 2981 + list_for_each_entry(ep, &gadget->ep_list, ep_list) { 2982 + if (ep->claimed && (ep->address & USB_DIR_IN)) 2983 + n_in++; 2984 + } 2985 + 2986 + /* 2KB are reserved for EP0, 1KB for out*/ 2987 + total = 2 + n_in + 1; 2988 + 2989 + if (total > priv_dev->onchip_buffers) 2990 + return -ENOMEM; 2991 + 2992 + priv_dev->ep_buf_size = priv_dev->ep_iso_burst = 2993 + (priv_dev->onchip_buffers - 2) / (n_in + 1); 2994 + 2995 + return 0; 2996 + } 2997 + 2968 2998 static const struct usb_gadget_ops cdns3_gadget_ops = { 2969 2999 .get_frame = cdns3_gadget_get_frame, 2970 3000 .wakeup = cdns3_gadget_wakeup, ··· 3007 2969 .udc_start = cdns3_gadget_udc_start, 3008 2970 .udc_stop = cdns3_gadget_udc_stop, 3009 2971 .match_ep = cdns3_gadget_match_ep, 2972 + .check_config = cdns3_gadget_check_config, 3010 2973 }; 3011 2974 3012 2975 static void cdns3_free_all_eps(struct cdns3_device *priv_dev)
+6 -3
drivers/usb/cdns3/cdns3-gadget.h
··· 562 562 /* Max burst size (used only in SS mode). */ 563 563 #define EP_CFG_MAXBURST_MASK GENMASK(11, 8) 564 564 #define EP_CFG_MAXBURST(p) (((p) << 8) & EP_CFG_MAXBURST_MASK) 565 + #define EP_CFG_MAXBURST_MAX 15 565 566 /* ISO max burst. */ 566 567 #define EP_CFG_MULT_MASK GENMASK(15, 14) 567 568 #define EP_CFG_MULT(p) (((p) << 14) & EP_CFG_MULT_MASK) 569 + #define EP_CFG_MULT_MAX 2 568 570 /* ISO max burst. */ 569 571 #define EP_CFG_MAXPKTSIZE_MASK GENMASK(26, 16) 570 572 #define EP_CFG_MAXPKTSIZE(p) (((p) << 16) & EP_CFG_MAXPKTSIZE_MASK) 571 573 /* Max number of buffered packets. */ 572 574 #define EP_CFG_BUFFERING_MASK GENMASK(31, 27) 573 575 #define EP_CFG_BUFFERING(p) (((p) << 27) & EP_CFG_BUFFERING_MASK) 576 + #define EP_CFG_BUFFERING_MAX 15 574 577 575 578 /* EP_CMD - bitmasks */ 576 579 /* Endpoint reset. */ ··· 1097 1094 #define CDNS3_ENDPOINTS_MAX_COUNT 32 1098 1095 #define CDNS3_EP_ZLP_BUF_SIZE 1024 1099 1096 1100 - #define CDNS3_EP_BUF_SIZE 4 /* KB */ 1101 - #define CDNS3_EP_ISO_HS_MULT 3 1102 - #define CDNS3_EP_ISO_SS_BURST 3 1103 1097 #define CDNS3_MAX_NUM_DESCMISS_BUF 32 1104 1098 #define CDNS3_DESCMIS_BUF_SIZE 2048 /* Bytes */ 1105 1099 #define CDNS3_WA2_NUM_BUFFERS 128 ··· 1333 1333 /*in KB */ 1334 1334 u16 onchip_buffers; 1335 1335 u16 onchip_used_size; 1336 + 1337 + u16 ep_buf_size; 1338 + u16 ep_iso_burst; 1336 1339 }; 1337 1340 1338 1341 void cdns3_set_register_bit(void __iomem *ptr, u32 mask);