This is a note to let you know that I've just added the patch titled usb: cdns3: allocate TX FIFO size according to composite EP number to the 5.10-stable tree which can be found at: http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary The filename of the patch is: usb-cdns3-allocate-tx-fifo-size-according-to-composi.patch and it can be found in the queue-5.10 subdirectory. If you, or anyone else, feels it should not be added to the stable tree, please let <stable@xxxxxxxxxxxxxxx> know about it. commit dac5893ffa1be6b839081af4c8facc9412ecf5eb Author: Frank Li <Frank.Li@xxxxxxx> Date: Mon May 9 11:40:55 2022 -0500 usb: cdns3: allocate TX FIFO size according to composite EP number [ Upstream commit dce49449e04ff150838a31386ee65917beb9ebb5 ] 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@xxxxxxxxxx> Signed-off-by: Frank Li <Frank.Li@xxxxxxx> Link: https://lore.kernel.org/r/20220509164055.1815081-1-Frank.Li@xxxxxxx Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx> Stable-dep-of: dbe678f6192f ("usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM") Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx> diff --git a/drivers/usb/cdns3/gadget.c b/drivers/usb/cdns3/gadget.c index e3a8b6c71aa1d..24dab7006b823 100644 --- a/drivers/usb/cdns3/gadget.c +++ b/drivers/usb/cdns3/gadget.c @@ -2041,7 +2041,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) u8 mult = 0; int ret; - buffering = CDNS3_EP_BUF_SIZE - 1; + buffering = priv_dev->ep_buf_size - 1; cdns3_configure_dmult(priv_dev, priv_ep); @@ -2060,7 +2060,7 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) break; default: ep_cfg = EP_CFG_EPTYPE(USB_ENDPOINT_XFER_ISOC); - mult = CDNS3_EP_ISO_HS_MULT - 1; + mult = priv_dev->ep_iso_burst - 1; buffering = mult + 1; } @@ -2076,14 +2076,14 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) mult = 0; max_packet_size = 1024; if (priv_ep->type == USB_ENDPOINT_XFER_ISOC) { - maxburst = CDNS3_EP_ISO_SS_BURST - 1; + maxburst = priv_dev->ep_iso_burst - 1; buffering = (mult + 1) * (maxburst + 1); if (priv_ep->interval > 1) buffering++; } else { - maxburst = CDNS3_EP_BUF_SIZE - 1; + maxburst = priv_dev->ep_buf_size - 1; } break; default: @@ -2098,6 +2098,10 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable) else priv_ep->trb_burst_size = 16; + mult = min_t(u8, mult, EP_CFG_MULT_MAX); + buffering = min_t(u8, buffering, EP_CFG_BUFFERING_MAX); + maxburst = min_t(u8, maxburst, EP_CFG_MAXBURST_MAX); + /* onchip buffer is only allocated before configuration */ if (!priv_dev->hw_configured_flag) { ret = cdns3_ep_onchip_buffer_reserve(priv_dev, buffering + 1, @@ -2971,6 +2975,40 @@ static int cdns3_gadget_udc_stop(struct usb_gadget *gadget) return 0; } +/** + * cdns3_gadget_check_config - ensure cdns3 can support the USB configuration + * @gadget: pointer to the USB gadget + * + * Used to record the maximum number of endpoints being used in a USB composite + * device. (across all configurations) This is to be used in the calculation + * of the TXFIFO sizes when resizing internal memory for individual endpoints. + * It will help ensured that the resizing logic reserves enough space for at + * least one max packet. + */ +static int cdns3_gadget_check_config(struct usb_gadget *gadget) +{ + struct cdns3_device *priv_dev = gadget_to_cdns3_device(gadget); + struct usb_ep *ep; + int n_in = 0; + int total; + + list_for_each_entry(ep, &gadget->ep_list, ep_list) { + if (ep->claimed && (ep->address & USB_DIR_IN)) + n_in++; + } + + /* 2KB are reserved for EP0, 1KB for out*/ + total = 2 + n_in + 1; + + if (total > priv_dev->onchip_buffers) + return -ENOMEM; + + priv_dev->ep_buf_size = priv_dev->ep_iso_burst = + (priv_dev->onchip_buffers - 2) / (n_in + 1); + + return 0; +} + static const struct usb_gadget_ops cdns3_gadget_ops = { .get_frame = cdns3_gadget_get_frame, .wakeup = cdns3_gadget_wakeup, @@ -2979,6 +3017,7 @@ static const struct usb_gadget_ops cdns3_gadget_ops = { .udc_start = cdns3_gadget_udc_start, .udc_stop = cdns3_gadget_udc_stop, .match_ep = cdns3_gadget_match_ep, + .check_config = cdns3_gadget_check_config, }; static void cdns3_free_all_eps(struct cdns3_device *priv_dev) diff --git a/drivers/usb/cdns3/gadget.h b/drivers/usb/cdns3/gadget.h index 21fa461c518ec..32825477edd3e 100644 --- a/drivers/usb/cdns3/gadget.h +++ b/drivers/usb/cdns3/gadget.h @@ -561,15 +561,18 @@ struct cdns3_usb_regs { /* Max burst size (used only in SS mode). */ #define EP_CFG_MAXBURST_MASK GENMASK(11, 8) #define EP_CFG_MAXBURST(p) (((p) << 8) & EP_CFG_MAXBURST_MASK) +#define EP_CFG_MAXBURST_MAX 15 /* ISO max burst. */ #define EP_CFG_MULT_MASK GENMASK(15, 14) #define EP_CFG_MULT(p) (((p) << 14) & EP_CFG_MULT_MASK) +#define EP_CFG_MULT_MAX 2 /* ISO max burst. */ #define EP_CFG_MAXPKTSIZE_MASK GENMASK(26, 16) #define EP_CFG_MAXPKTSIZE(p) (((p) << 16) & EP_CFG_MAXPKTSIZE_MASK) /* Max number of buffered packets. */ #define EP_CFG_BUFFERING_MASK GENMASK(31, 27) #define EP_CFG_BUFFERING(p) (((p) << 27) & EP_CFG_BUFFERING_MASK) +#define EP_CFG_BUFFERING_MAX 15 /* EP_CMD - bitmasks */ /* Endpoint reset. */ @@ -1093,9 +1096,6 @@ struct cdns3_trb { #define CDNS3_ENDPOINTS_MAX_COUNT 32 #define CDNS3_EP_ZLP_BUF_SIZE 1024 -#define CDNS3_EP_BUF_SIZE 4 /* KB */ -#define CDNS3_EP_ISO_HS_MULT 3 -#define CDNS3_EP_ISO_SS_BURST 3 #define CDNS3_MAX_NUM_DESCMISS_BUF 32 #define CDNS3_DESCMIS_BUF_SIZE 2048 /* Bytes */ #define CDNS3_WA2_NUM_BUFFERS 128 @@ -1330,6 +1330,9 @@ struct cdns3_device { /*in KB */ u16 onchip_buffers; u16 onchip_used_size; + + u16 ep_buf_size; + u16 ep_iso_burst; }; void cdns3_set_register_bit(void __iomem *ptr, u32 mask);