diff mbox series

[1/1] usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM

Message ID 20230518154946.3666662-1-Frank.Li@nxp.com (mailing list archive)
State Accepted
Commit dbe678f6192f27879ac9ff6bc7a1036aad85aae9
Headers show
Series [1/1] usb: cdns3: fix NCM gadget RX speed 20x slow than expection at iMX8QM | expand

Commit Message

Frank Li May 18, 2023, 3:49 p.m. UTC
At iMX8QM platform, enable NCM gadget and run 'iperf3 -s'.
At host, run 'iperf3 -V -c fe80::6863:98ff:feef:3e0%enxc6e147509498'

[  5]   0.00-1.00   sec  1.55 MBytes  13.0 Mbits/sec   90   4.18 KBytes
[  5]   1.00-2.00   sec  1.44 MBytes  12.0 Mbits/sec   75   4.18 KBytes
[  5]   2.00-3.00   sec  1.48 MBytes  12.4 Mbits/sec   75   4.18 KBytes

Expected speed should be bigger than 300Mbits/sec.

The root cause of this performance drop was found to be data corruption
happening at 4K borders in some Ethernet packets, leading to TCP
checksum errors. This corruption occurs from the position
(4K - (address & 0x7F)) to 4K. The u_ether function's allocation of
skb_buff reserves 64B, meaning all RX addresses resemble 0xXXXX0040.

Force trb_burst_size to 16 can fix this problem.

Cc: stable@vger.kernel.org
Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
Signed-off-by: Frank Li <Frank.Li@nxp.com>
---
 drivers/usb/cdns3/cdns3-gadget.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

Comments

Peter Chen June 4, 2023, 10:56 p.m. UTC | #1
On 23-05-18 11:49:45, Frank Li wrote:
> At iMX8QM platform, enable NCM gadget and run 'iperf3 -s'.
> At host, run 'iperf3 -V -c fe80::6863:98ff:feef:3e0%enxc6e147509498'
> 
> [  5]   0.00-1.00   sec  1.55 MBytes  13.0 Mbits/sec   90   4.18 KBytes
> [  5]   1.00-2.00   sec  1.44 MBytes  12.0 Mbits/sec   75   4.18 KBytes
> [  5]   2.00-3.00   sec  1.48 MBytes  12.4 Mbits/sec   75   4.18 KBytes
> 
> Expected speed should be bigger than 300Mbits/sec.
> 
> The root cause of this performance drop was found to be data corruption
> happening at 4K borders in some Ethernet packets, leading to TCP
> checksum errors. This corruption occurs from the position
> (4K - (address & 0x7F)) to 4K. The u_ether function's allocation of
> skb_buff reserves 64B, meaning all RX addresses resemble 0xXXXX0040.
> 
> Force trb_burst_size to 16 can fix this problem.
> 
> Cc: stable@vger.kernel.org
> Fixes: 7733f6c32e36 ("usb: cdns3: Add Cadence USB3 DRD Driver")
> Signed-off-by: Frank Li <Frank.Li@nxp.com>
> ---
>  drivers/usb/cdns3/cdns3-gadget.c | 13 +++++++++++++
>  1 file changed, 13 insertions(+)
> 
> diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
> index ccfaebca6faa..1dcadef933e3 100644
> --- a/drivers/usb/cdns3/cdns3-gadget.c
> +++ b/drivers/usb/cdns3/cdns3-gadget.c
> @@ -2097,6 +2097,19 @@ int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
>  	else
>  		priv_ep->trb_burst_size = 16;
>  
> +	/*
> +	 * In versions preceding DEV_VER_V2, for example, iMX8QM, there exit the bugs
> +	 * in the DMA. These bugs occur when the trb_burst_size exceeds 16 and the
> +	 * address is not aligned to 128 Bytes (which is a product of the 64-bit AXI
> +	 * and AXI maximum burst length of 16 or 0xF+1, dma_axi_ctrl0[3:0]). This
> +	 * results in data corruption when it crosses the 4K border. The corruption
> +	 * specifically occurs from the position (4K - (address & 0x7F)) to 4K.
> +	 *
> +	 * So force trb_burst_size to 16 at such platform.
> +	 */
> +	if (priv_dev->dev_ver < DEV_VER_V2)
> +		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);
> -- 
> 2.34.1
> 

Acked-by: Peter Chen <peter.chen@kernel.org>
diff mbox series

Patch

diff --git a/drivers/usb/cdns3/cdns3-gadget.c b/drivers/usb/cdns3/cdns3-gadget.c
index ccfaebca6faa..1dcadef933e3 100644
--- a/drivers/usb/cdns3/cdns3-gadget.c
+++ b/drivers/usb/cdns3/cdns3-gadget.c
@@ -2097,6 +2097,19 @@  int cdns3_ep_config(struct cdns3_endpoint *priv_ep, bool enable)
 	else
 		priv_ep->trb_burst_size = 16;
 
+	/*
+	 * In versions preceding DEV_VER_V2, for example, iMX8QM, there exit the bugs
+	 * in the DMA. These bugs occur when the trb_burst_size exceeds 16 and the
+	 * address is not aligned to 128 Bytes (which is a product of the 64-bit AXI
+	 * and AXI maximum burst length of 16 or 0xF+1, dma_axi_ctrl0[3:0]). This
+	 * results in data corruption when it crosses the 4K border. The corruption
+	 * specifically occurs from the position (4K - (address & 0x7F)) to 4K.
+	 *
+	 * So force trb_burst_size to 16 at such platform.
+	 */
+	if (priv_dev->dev_ver < DEV_VER_V2)
+		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);