Hi Frank, > >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 >ecnds3_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. > >Signed-off-by: Frank Li <Frank.Li@xxxxxxx> >--- > drivers/usb/cdns3/cdns3-gadget.c | 46 +++++++++++++++++++++++++++++--- > drivers/usb/cdns3/cdns3-gadget.h | 6 ++--- > 2 files changed, 45 insertions(+), 7 deletions(-) > >diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c >index 1f3b4a1422126..62ea1bd773386 100644 >--- a/drivers/usb/cdns3/cdns3-gadget.c >+++ b/drivers/usb/cdns3/cdns3-gadget.c >@@ -2050,7 +2050,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); > >@@ -2069,7 +2069,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; > } > >@@ -2085,14 +2085,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: >@@ -2970,6 +2970,43 @@ 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++; >+ } >+ >+ priv_dev->ep_buf_size = 1; >+ priv_dev->ep_iso_burst = 1; >+ >+ /* 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); >+ I think you should put here or in cdns3_ep_config some Limitation for ep_buf_size and ep_iso_burst. What in case e.g. UVC (1 OUT + 1 IN) when onchip_buffers is 52 ? As I remember you have 18KB onchip memory, so in your case it will work fine. Description of EP_CFG. BUFFERING: Max number of buffered packets The maximum number of packets the device can buffer in the on-chip memory for specified endpoint. Valid values are from 0 to 15 .... Thanks and Regards Pawel >+ return 0; >+} >+ > static const struct usb_gadget_ops cdns3_gadget_ops = { > .get_frame = cdns3_gadget_get_frame, > .wakeup = cdns3_gadget_wakeup, >@@ -2978,6 +3015,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/cdns3-gadget.h b/drivers/usb/cdns3/cdns3-gadget.h >index c5660f2c4293f..f333c34b93ffb 100644 >--- a/drivers/usb/cdns3/cdns3-gadget.h >+++ b/drivers/usb/cdns3/cdns3-gadget.h >@@ -1094,9 +1094,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 >@@ -1333,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); >-- >2.35.1