Skip to content

Commit

Permalink
usb: cdns3: allocate TX FIFO size according to composite EP number
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Frank Li authored and Greg Kroah-Hartman committed May 19, 2022
1 parent 9d778f0 commit dce4944
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 7 deletions.
47 changes: 43 additions & 4 deletions drivers/usb/cdns3/cdns3-gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -2038,7 +2038,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);

Expand All @@ -2057,7 +2057,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;
}

Expand All @@ -2073,14 +2073,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:
Expand All @@ -2095,6 +2095,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,
Expand Down Expand Up @@ -2961,6 +2965,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,
Expand All @@ -2969,6 +3007,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)
Expand Down
9 changes: 6 additions & 3 deletions drivers/usb/cdns3/cdns3-gadget.h
Original file line number Diff line number Diff line change
Expand Up @@ -562,15 +562,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. */
Expand Down Expand Up @@ -1094,9 +1097,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
Expand Down Expand Up @@ -1333,6 +1333,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);
Expand Down

0 comments on commit dce4944

Please sign in to comment.