Skip to content

Commit

Permalink
usb: dwc3: gadget: Properly set maxpacket limit
Browse files Browse the repository at this point in the history
Currently the calculation of max packet size limit for IN endpoints is
too restrictive. This prevents a matching of a capable hardware endpoint
during configuration. Below is the minimum recommended HW configuration
to support a particular endpoint setup from the databook:

For OUT endpoints, the databook recommended the minimum RxFIFO size to
be at least 3x MaxPacketSize + 3x setup packets size (8 bytes each) +
clock crossing margin (16 bytes).

For IN endpoints, the databook recommended the minimum TxFIFO size to be
at least 3x MaxPacketSize for endpoints that support burst. If the
endpoint doesn't support burst or when the device is operating in USB
2.0 mode, a minimum TxFIFO size of 2x MaxPacketSize is recommended.

Base on these recommendations, we can calculate the MaxPacketSize limit
of each endpoint. This patch revises the IN endpoint MaxPacketSize limit
and also sets the MaxPacketSize limit for OUT endpoints.

Reference: Databook 3.30a section 3.2.2 and 3.2.3

Signed-off-by: Thinh Nguyen <[email protected]>
Signed-off-by: Felipe Balbi <[email protected]>
  • Loading branch information
Thinh Nguyen authored and felipebalbi committed Apr 16, 2020
1 parent 586f433 commit d94ea53
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 11 deletions.
4 changes: 4 additions & 0 deletions drivers/usb/dwc3/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,10 @@
#define DWC3_GTXFIFOSIZ_TXFDEP(n) ((n) & 0xffff)
#define DWC3_GTXFIFOSIZ_TXFSTADDR(n) ((n) & 0xffff0000)

/* Global RX Fifo Size Register */
#define DWC31_GRXFIFOSIZ_RXFDEP(n) ((n) & 0x7fff) /* DWC_usb31 only */
#define DWC3_GRXFIFOSIZ_RXFDEP(n) ((n) & 0xffff)

/* Global Event Size Registers */
#define DWC3_GEVNTSIZ_INTMASK BIT(31)
#define DWC3_GEVNTSIZ_SIZE(n) ((n) & 0xffff)
Expand Down
52 changes: 41 additions & 11 deletions drivers/usb/dwc3/gadget.c
Original file line number Diff line number Diff line change
Expand Up @@ -2227,7 +2227,6 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
{
struct dwc3 *dwc = dep->dwc;
int mdwidth;
int kbytes;
int size;

mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);
Expand All @@ -2243,17 +2242,17 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
/* FIFO Depth is in MDWDITH bytes. Multiply */
size *= mdwidth;

kbytes = size / 1024;
if (kbytes == 0)
kbytes = 1;

/*
* FIFO sizes account an extra MDWIDTH * (kbytes + 1) bytes for
* internal overhead. We don't really know how these are used,
* but documentation say it exists.
* To meet performance requirement, a minimum TxFIFO size of 3x
* MaxPacketSize is recommended for endpoints that support burst and a
* minimum TxFIFO size of 2x MaxPacketSize for endpoints that don't
* support burst. Use those numbers and we can calculate the max packet
* limit as below.
*/
size -= mdwidth * (kbytes + 1);
size /= kbytes;
if (dwc->maximum_speed >= USB_SPEED_SUPER)
size /= 3;
else
size /= 2;

usb_ep_set_maxpacket_limit(&dep->endpoint, size);

Expand All @@ -2271,8 +2270,39 @@ static int dwc3_gadget_init_in_endpoint(struct dwc3_ep *dep)
static int dwc3_gadget_init_out_endpoint(struct dwc3_ep *dep)
{
struct dwc3 *dwc = dep->dwc;
int mdwidth;
int size;

mdwidth = DWC3_MDWIDTH(dwc->hwparams.hwparams0);

/* MDWIDTH is represented in bits, convert to bytes */
mdwidth /= 8;

usb_ep_set_maxpacket_limit(&dep->endpoint, 1024);
/* All OUT endpoints share a single RxFIFO space */
size = dwc3_readl(dwc->regs, DWC3_GRXFIFOSIZ(0));
if (dwc3_is_usb31(dwc))
size = DWC31_GRXFIFOSIZ_RXFDEP(size);
else
size = DWC3_GRXFIFOSIZ_RXFDEP(size);

/* FIFO depth is in MDWDITH bytes */
size *= mdwidth;

/*
* To meet performance requirement, a minimum recommended RxFIFO size
* is defined as follow:
* RxFIFO size >= (3 x MaxPacketSize) +
* (3 x 8 bytes setup packets size) + (16 bytes clock crossing margin)
*
* Then calculate the max packet limit as below.
*/
size -= (3 * 8) + 16;
if (size < 0)
size = 0;
else
size /= 3;

usb_ep_set_maxpacket_limit(&dep->endpoint, size);
dep->endpoint.max_streams = 15;
dep->endpoint.ops = &dwc3_gadget_ep_ops;
list_add_tail(&dep->endpoint.ep_list,
Expand Down

0 comments on commit d94ea53

Please sign in to comment.