| From 4616acb0710e778737476c8c63747da8ba3a0464 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 31 Jan 2020 16:59:27 -0800 |
| Subject: usb: dwc3: gadget: Properly set maxpacket limit |
| |
| From: Thinh Nguyen <Thinh.Nguyen@synopsys.com> |
| |
| [ Upstream commit d94ea5319813658ad5861d161ae16a194c2abf88 ] |
| |
| 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 <thinhn@synopsys.com> |
| Signed-off-by: Felipe Balbi <balbi@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/usb/dwc3/core.h | 4 +++ |
| drivers/usb/dwc3/gadget.c | 52 ++++++++++++++++++++++++++++++--------- |
| 2 files changed, 45 insertions(+), 11 deletions(-) |
| |
| diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h |
| index e34308d64619e..d6968b90ee6bb 100644 |
| --- a/drivers/usb/dwc3/core.h |
| +++ b/drivers/usb/dwc3/core.h |
| @@ -300,6 +300,10 @@ |
| #define DWC3_GTXFIFOSIZ_TXFDEF(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) |
| diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c |
| index 1a6c973da4879..99f6a5aa01095 100644 |
| --- a/drivers/usb/dwc3/gadget.c |
| +++ b/drivers/usb/dwc3/gadget.c |
| @@ -2032,7 +2032,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); |
| @@ -2048,17 +2047,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); |
| |
| @@ -2076,8 +2075,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, |
| -- |
| 2.20.1 |
| |