[openwrt/openwrt] lantiq: improve ethernet performance

LEDE Commits lede-commits at lists.infradead.org
Mon Nov 15 14:17:45 PST 2021


mkresin pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/0e561a2aea8dddbb446f710f1037ec305c23af9e

commit 0e561a2aea8dddbb446f710f1037ec305c23af9e
Author: Aleksander Jan Bajkowski <olek2 at wp.pl>
AuthorDate: Sat May 22 20:07:56 2021 +0200

    lantiq: improve ethernet performance
    
    This commit contains a series of fixes for DMA. The burst length
    patch significantly improves Ethernet performance. Patches were
    tested on the xRX200 and xRX330.
    
    Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
---
 .../files/arch/mips/boot/dts/lantiq/amazonse.dtsi  |   2 +
 .../files/arch/mips/boot/dts/lantiq/ar9.dtsi       |   2 +
 .../files/arch/mips/boot/dts/lantiq/danube.dtsi    |   2 +
 .../files/arch/mips/boot/dts/lantiq/vr9.dtsi       |   2 +
 ...PS-lantiq-dma-add-small-delay-after-reset.patch |  32 ++++++
 ...antiq-dma-reset-correct-number-of-channel.patch |  68 +++++++++++
 ...-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch |  41 +++++++
 ...-dma-make-a-burst-length-configurable-in-.patch |  84 ++++++++++++++
 ...antiq-configure-burst-length-for-ethernet.patch | 124 +++++++++++++++++++++
 ...PS-lantiq-dma-add-small-delay-after-reset.patch |  32 ++++++
 ...antiq-dma-reset-correct-number-of-channel.patch |  68 +++++++++++
 ...-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch |  41 +++++++
 ...-dma-make-a-burst-length-configurable-in-.patch |  84 ++++++++++++++
 ...antiq-configure-burst-length-for-ethernet.patch | 124 +++++++++++++++++++++
 14 files changed, 706 insertions(+)

diff --git a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/amazonse.dtsi b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/amazonse.dtsi
index c477473a06..5c608dab63 100644
--- a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/amazonse.dtsi
+++ b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/amazonse.dtsi
@@ -236,6 +236,8 @@
 			interrupts = <105 109>;
 			pinctrl-0 = <&mdio_pins>;
 			pinctrl-names = "default";
+			lantiq,tx-burst-length = <4>;
+			lantiq,rx-burst-length = <4>;
 		};
 	};
 
diff --git a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/ar9.dtsi b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/ar9.dtsi
index 819dcfb5a8..61283f5621 100644
--- a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/ar9.dtsi
+++ b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/ar9.dtsi
@@ -387,6 +387,8 @@
 			interrupts = <73 72>;
 			pinctrl-0 = <&mdio_pins>;
 			pinctrl-names = "default";
+			lantiq,tx-burst-length = <8>;
+			lantiq,rx-burst-length = <8>;
 		};
 
 		ppe at e234000 {
diff --git a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/danube.dtsi b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/danube.dtsi
index e531fe45e8..a18183a2de 100644
--- a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/danube.dtsi
+++ b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/danube.dtsi
@@ -299,6 +299,8 @@
 			reg = <0xe180000 0x40000>;
 			interrupt-parent = <&icu0>;
 			interrupts = <73 78>;
+			lantiq,tx-burst-length = <4>;
+			lantiq,rx-burst-length = <4>;
 		};
 
 		ppe at e234000 {
diff --git a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9.dtsi b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9.dtsi
index 27858be28f..e379b07b53 100644
--- a/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9.dtsi
+++ b/target/linux/lantiq/files/arch/mips/boot/dts/lantiq/vr9.dtsi
@@ -488,6 +488,8 @@
 			interrupt-names = "tx", "rx";
 			resets = <&reset0 21 16>, <&reset0 8 8>, <&reset0 3 3>;
 			reset-names = "switch", "ppe", "ppe_dsp";
+			lantiq,tx-burst-length = <8>;
+			lantiq,rx-burst-length = <8>;
 			#address-cells = <1>;
 			#size-cells = <0>;
 
diff --git a/target/linux/lantiq/patches-5.10/0110-MIPS-lantiq-dma-add-small-delay-after-reset.patch b/target/linux/lantiq/patches-5.10/0110-MIPS-lantiq-dma-add-small-delay-after-reset.patch
new file mode 100644
index 0000000000..05227c8f89
--- /dev/null
+++ b/target/linux/lantiq/patches-5.10/0110-MIPS-lantiq-dma-add-small-delay-after-reset.patch
@@ -0,0 +1,32 @@
+From 497acc03cd3918baabe25d46e30c5c62b998e24d Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Sat, 19 Jun 2021 13:38:12 +0200
+Subject: [PATCH 1/5] MIPS: lantiq: dma: add small delay after reset
+
+Reading the DMA registers immediately after the reset causes
+Data Bus Error. Adding a small delay fixes this problem.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ arch/mips/lantiq/xway/dma.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -11,6 +11,7 @@
+ #include <linux/export.h>
+ #include <linux/spinlock.h>
+ #include <linux/clk.h>
++#include <linux/delay.h>
+ #include <linux/err.h>
+ 
+ #include <lantiq_soc.h>
+@@ -221,6 +222,8 @@ ltq_dma_init(struct platform_device *pde
+ 	clk_enable(clk);
+ 	ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
+ 
++	usleep_range(1, 10);
++
+ 	/* disable all interrupts */
+ 	ltq_dma_w32(0, LTQ_DMA_IRNEN);
+ 
diff --git a/target/linux/lantiq/patches-5.10/0111-MIPS-lantiq-dma-reset-correct-number-of-channel.patch b/target/linux/lantiq/patches-5.10/0111-MIPS-lantiq-dma-reset-correct-number-of-channel.patch
new file mode 100644
index 0000000000..5d1862d576
--- /dev/null
+++ b/target/linux/lantiq/patches-5.10/0111-MIPS-lantiq-dma-reset-correct-number-of-channel.patch
@@ -0,0 +1,68 @@
+From d31260c2f6a5cdddb052ab7cb09560eb23ce6597 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Thu, 15 Apr 2021 21:28:24 +0200
+Subject: [PATCH 2/5] MIPS: lantiq: dma: reset correct number of channel
+
+Different SoCs have a different number of channels, e.g .:
+* amazon-se has 10 channels,
+* danube+ar9 have 20 channels,
+* vr9 has 28 channels,
+* ar10 has 24 channels.
+
+We can read the ID register and, depending on the reported
+number of channels, reset the appropriate number of channels.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ arch/mips/lantiq/xway/dma.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -30,6 +30,7 @@
+ #define LTQ_DMA_PCTRL		0x44
+ #define LTQ_DMA_IRNEN		0xf4
+ 
++#define DMA_ID_CHNR		GENMASK(26, 20)	/* channel number */
+ #define DMA_DESCPT		BIT(3)		/* descriptor complete irq */
+ #define DMA_TX			BIT(8)		/* TX channel direction */
+ #define DMA_CHAN_ON		BIT(0)		/* channel on / off bit */
+@@ -40,7 +41,6 @@
+ #define DMA_POLL		BIT(31)		/* turn on channel polling */
+ #define DMA_CLK_DIV4		BIT(6)		/* polling clock divider */
+ #define DMA_2W_BURST		BIT(1)		/* 2 word burst length */
+-#define DMA_MAX_CHANNEL		20		/* the soc has 20 channels */
+ #define DMA_ETOP_ENDIANNESS	(0xf << 8) /* endianness swap etop channels */
+ #define DMA_WEIGHT	(BIT(17) | BIT(16))	/* default channel wheight */
+ 
+@@ -206,7 +206,7 @@ ltq_dma_init(struct platform_device *pde
+ {
+ 	struct clk *clk;
+ 	struct resource *res;
+-	unsigned id;
++	unsigned int id, nchannels;
+ 	int i;
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -228,17 +228,18 @@ ltq_dma_init(struct platform_device *pde
+ 	ltq_dma_w32(0, LTQ_DMA_IRNEN);
+ 
+ 	/* reset/configure each channel */
+-	for (i = 0; i < DMA_MAX_CHANNEL; i++) {
++	id = ltq_dma_r32(LTQ_DMA_ID);
++	nchannels = ((id & DMA_ID_CHNR) >> 20);
++	for (i = 0; i < nchannels; i++) {
+ 		ltq_dma_w32(i, LTQ_DMA_CS);
+ 		ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
+ 		ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
+ 		ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+ 	}
+ 
+-	id = ltq_dma_r32(LTQ_DMA_ID);
+ 	dev_info(&pdev->dev,
+ 		"Init done - hw rev: %X, ports: %d, channels: %d\n",
+-		id & 0x1f, (id >> 16) & 0xf, id >> 20);
++		id & 0x1f, (id >> 16) & 0xf, nchannels);
+ 
+ 	return 0;
+ }
diff --git a/target/linux/lantiq/patches-5.10/0112-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch b/target/linux/lantiq/patches-5.10/0112-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch
new file mode 100644
index 0000000000..67423d2e97
--- /dev/null
+++ b/target/linux/lantiq/patches-5.10/0112-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch
@@ -0,0 +1,41 @@
+From 7d9ea9052d6680d2910b8b005c397d95b3a8b012 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Wed, 7 Apr 2021 21:04:39 +0200
+Subject: [PATCH 3/5] MIPS: lantiq: dma: fix burst length for DEU
+
+The current definition of 2W burst length is invalid.
+This patch fixes it. Current downstream DEU driver doesn't
+use DMA. An incorrect burst length value doesn't cause any
+errors. This patch also adds other burst length values.
+
+Fixes: dfec1a827d2b ("MIPS: Lantiq: Add DMA support")
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ arch/mips/lantiq/xway/dma.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -40,7 +40,11 @@
+ #define DMA_IRQ_ACK		0x7e		/* IRQ status register */
+ #define DMA_POLL		BIT(31)		/* turn on channel polling */
+ #define DMA_CLK_DIV4		BIT(6)		/* polling clock divider */
+-#define DMA_2W_BURST		BIT(1)		/* 2 word burst length */
++#define DMA_PCTRL_2W_BURST	0x1		/* 2 word burst length */
++#define DMA_PCTRL_4W_BURST	0x2		/* 4 word burst length */
++#define DMA_PCTRL_8W_BURST	0x3		/* 8 word burst length */
++#define DMA_TX_BURST_SHIFT	4		/* tx burst shift */
++#define DMA_RX_BURST_SHIFT	2		/* rx burst shift */
+ #define DMA_ETOP_ENDIANNESS	(0xf << 8) /* endianness swap etop channels */
+ #define DMA_WEIGHT	(BIT(17) | BIT(16))	/* default channel wheight */
+ 
+@@ -191,7 +195,8 @@ ltq_dma_init_port(int p)
+ 		break;
+ 
+ 	case DMA_PORT_DEU:
+-		ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2),
++		ltq_dma_w32((DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT) |
++			(DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT),
+ 			LTQ_DMA_PCTRL);
+ 		break;
+ 
diff --git a/target/linux/lantiq/patches-5.10/0113-MIPS-lantiq-dma-make-a-burst-length-configurable-in-.patch b/target/linux/lantiq/patches-5.10/0113-MIPS-lantiq-dma-make-a-burst-length-configurable-in-.patch
new file mode 100644
index 0000000000..fab2440453
--- /dev/null
+++ b/target/linux/lantiq/patches-5.10/0113-MIPS-lantiq-dma-make-a-burst-length-configurable-in-.patch
@@ -0,0 +1,84 @@
+From 6615eeb39f7a110a196f20acbfb3a017da4d75d2 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Fri, 14 May 2021 21:25:08 +0200
+Subject: [PATCH 4/5] MIPS: lantiq: dma: make a burst length configurable in
+ drivers
+
+Make a burst length configurable in drivers.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ .../include/asm/mach-lantiq/xway/xway_dma.h   |  2 +-
+ arch/mips/lantiq/xway/dma.c                   | 38 ++++++++++++++++---
+ 2 files changed, 34 insertions(+), 6 deletions(-)
+
+--- a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
+@@ -45,6 +45,6 @@ extern void ltq_dma_close(struct ltq_dma
+ extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch);
+ extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch);
+ extern void ltq_dma_free(struct ltq_dma_channel *ch);
+-extern void ltq_dma_init_port(int p);
++extern void ltq_dma_init_port(int p, int tx_burst, int rx_burst);
+ 
+ #endif
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -181,7 +181,7 @@ ltq_dma_free(struct ltq_dma_channel *ch)
+ EXPORT_SYMBOL_GPL(ltq_dma_free);
+ 
+ void
+-ltq_dma_init_port(int p)
++ltq_dma_init_port(int p, int tx_burst, int rx_burst)
+ {
+ 	ltq_dma_w32(p, LTQ_DMA_PS);
+ 	switch (p) {
+@@ -190,16 +190,44 @@ ltq_dma_init_port(int p)
+ 		 * Tell the DMA engine to swap the endianness of data frames and
+ 		 * drop packets if the channel arbitration fails.
+ 		 */
+-		ltq_dma_w32_mask(0, DMA_ETOP_ENDIANNESS | DMA_PDEN,
++		ltq_dma_w32_mask(0, (DMA_ETOP_ENDIANNESS | DMA_PDEN),
+ 			LTQ_DMA_PCTRL);
+ 		break;
+ 
+-	case DMA_PORT_DEU:
+-		ltq_dma_w32((DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT) |
+-			(DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT),
++	default:
++		break;
++	}
++
++	switch (rx_burst) {
++	case 8:
++		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_8W_BURST << DMA_RX_BURST_SHIFT),
+ 			LTQ_DMA_PCTRL);
+ 		break;
++	case 4:
++		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_4W_BURST << DMA_RX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	case 2:
++		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	default:
++		break;
++	}
+ 
++	switch (tx_burst) {
++	case 8:
++		ltq_dma_w32_mask(0x30, (DMA_PCTRL_8W_BURST << DMA_TX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	case 4:
++		ltq_dma_w32_mask(0x30, (DMA_PCTRL_4W_BURST << DMA_TX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	case 2:
++		ltq_dma_w32_mask(0x30, (DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
+ 	default:
+ 		break;
+ 	}
diff --git a/target/linux/lantiq/patches-5.10/0710-net-lantiq-configure-burst-length-for-ethernet.patch b/target/linux/lantiq/patches-5.10/0710-net-lantiq-configure-burst-length-for-ethernet.patch
new file mode 100644
index 0000000000..0a2996813a
--- /dev/null
+++ b/target/linux/lantiq/patches-5.10/0710-net-lantiq-configure-burst-length-for-ethernet.patch
@@ -0,0 +1,124 @@
+From ec1a17a11aced3cd756e59d91ad6f50b7a2fabfb Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Sun, 16 May 2021 15:52:06 +0200
+Subject: [PATCH 5/5] net: lantiq: configure burst length for ethernet
+
+Configure the burst length for Ethernet. This improves Ethernet
+performance by 58%. According to the vendor BSP, 8W burst length
+is supported by ar9 and newer SoCs.
+
+The NAT benchmark results on xRX200 (Down/Up):
+* 2W: 330 Mb/s
+* 4W: 432 Mb/s    372 Mb/s
+* 8W: 520 Mb/s    389 Mb/s
+
+Tested on xRX200 and xRX330.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ drivers/net/ethernet/lantiq_etop.c   | 21 ++++++++++++++++++---
+ drivers/net/ethernet/lantiq_xrx200.c | 21 ++++++++++++++++++---
+ 2 files changed, 36 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -148,6 +148,9 @@ struct ltq_etop_priv {
+ 	struct ltq_etop_chan txch;
+ 	struct ltq_etop_chan rxch;
+ 
++	int tx_burst_len;
++	int rx_burst_len;
++
+ 	int tx_irq;
+ 	int rx_irq;
+ 
+@@ -399,7 +402,7 @@ ltq_etop_dma_init(struct net_device *dev
+ 	int rx = priv->rx_irq - LTQ_DMA_ETOP;
+ 	int err;
+ 
+-	ltq_dma_init_port(DMA_PORT_ETOP);
++	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, priv->rx_burst_len);
+ 
+ 	priv->txch.dma.nr = tx;
+ 	priv->txch.dma.dev = &priv->pdev->dev;
+@@ -676,8 +679,8 @@ ltq_etop_tx(struct sk_buff *skb, struct
+ 		return NETDEV_TX_BUSY;
+ 	}
+ 
+-	/* dma needs to start on a 16 byte aligned address */
+-	byte_offset = CPHYSADDR(skb->data) % 16;
++	/* dma needs to start on a burst length value aligned address */
++	byte_offset = CPHYSADDR(skb->data) % (priv->tx_burst_len * 4);
+ 	priv->txch.skb[priv->txch.dma.desc] = skb;
+ 
+ 	netif_trans_update(dev);
+@@ -925,6 +928,18 @@ static int ltq_etop_probe(struct platfor
+ 	spin_lock_init(&priv->lock);
+ 	SET_NETDEV_DEV(dev, &pdev->dev);
+ 
++	err = device_property_read_u32(&pdev->dev, "lantiq,tx-burst-length", &priv->tx_burst_len);
++	if (err < 0) {
++		dev_err(&pdev->dev, "unable to read tx-burst-length property\n");
++		return err;
++	}
++
++	err = device_property_read_u32(&pdev->dev, "lantiq,rx-burst-length", &priv->rx_burst_len);
++	if (err < 0) {
++		dev_err(&pdev->dev, "unable to read rx-burst-length property\n");
++		return err;
++	}
++
+ 	netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8);
+ 	netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32);
+ 	priv->txch.netdev = dev;
+--- a/drivers/net/ethernet/lantiq_xrx200.c
++++ b/drivers/net/ethernet/lantiq_xrx200.c
+@@ -71,6 +71,9 @@ struct xrx200_priv {
+ 	struct net_device *net_dev;
+ 	struct device *dev;
+ 
++	int tx_burst_len;
++	int rx_burst_len;
++
+ 	__iomem void *pmac_reg;
+ };
+ 
+@@ -316,8 +319,8 @@ static netdev_tx_t xrx200_start_xmit(str
+ 	if (unlikely(dma_mapping_error(priv->dev, mapping)))
+ 		goto err_drop;
+ 
+-	/* dma needs to start on a 16 byte aligned address */
+-	byte_offset = mapping % 16;
++	/* dma needs to start on a burst length value aligned address */
++	byte_offset = mapping % (priv->tx_burst_len * 4);
+ 
+ 	desc->addr = mapping - byte_offset;
+ 	/* Make sure the address is written before we give it to HW */
+@@ -369,7 +372,7 @@ static int xrx200_dma_init(struct xrx200
+ 	int ret = 0;
+ 	int i;
+ 
+-	ltq_dma_init_port(DMA_PORT_ETOP);
++	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, priv->rx_burst_len);
+ 
+ 	ch_rx->dma.nr = XRX200_DMA_RX;
+ 	ch_rx->dma.dev = priv->dev;
+@@ -487,6 +490,18 @@ static int xrx200_probe(struct platform_
+ 	if (err)
+ 		eth_hw_addr_random(net_dev);
+ 
++	err = device_property_read_u32(dev, "lantiq,tx-burst-length", &priv->tx_burst_len);
++	if (err < 0) {
++		dev_err(dev, "unable to read tx-burst-length property\n");
++		return err;
++	}
++
++	err = device_property_read_u32(dev, "lantiq,rx-burst-length", &priv->rx_burst_len);
++	if (err < 0) {
++		dev_err(dev, "unable to read rx-burst-length property\n");
++		return err;
++	}
++
+ 	/* bring up the dma engine and IP core */
+ 	err = xrx200_dma_init(priv);
+ 	if (err)
diff --git a/target/linux/lantiq/patches-5.4/0110-MIPS-lantiq-dma-add-small-delay-after-reset.patch b/target/linux/lantiq/patches-5.4/0110-MIPS-lantiq-dma-add-small-delay-after-reset.patch
new file mode 100644
index 0000000000..05227c8f89
--- /dev/null
+++ b/target/linux/lantiq/patches-5.4/0110-MIPS-lantiq-dma-add-small-delay-after-reset.patch
@@ -0,0 +1,32 @@
+From 497acc03cd3918baabe25d46e30c5c62b998e24d Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Sat, 19 Jun 2021 13:38:12 +0200
+Subject: [PATCH 1/5] MIPS: lantiq: dma: add small delay after reset
+
+Reading the DMA registers immediately after the reset causes
+Data Bus Error. Adding a small delay fixes this problem.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ arch/mips/lantiq/xway/dma.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -11,6 +11,7 @@
+ #include <linux/export.h>
+ #include <linux/spinlock.h>
+ #include <linux/clk.h>
++#include <linux/delay.h>
+ #include <linux/err.h>
+ 
+ #include <lantiq_soc.h>
+@@ -221,6 +222,8 @@ ltq_dma_init(struct platform_device *pde
+ 	clk_enable(clk);
+ 	ltq_dma_w32_mask(0, DMA_RESET, LTQ_DMA_CTRL);
+ 
++	usleep_range(1, 10);
++
+ 	/* disable all interrupts */
+ 	ltq_dma_w32(0, LTQ_DMA_IRNEN);
+ 
diff --git a/target/linux/lantiq/patches-5.4/0111-MIPS-lantiq-dma-reset-correct-number-of-channel.patch b/target/linux/lantiq/patches-5.4/0111-MIPS-lantiq-dma-reset-correct-number-of-channel.patch
new file mode 100644
index 0000000000..5d1862d576
--- /dev/null
+++ b/target/linux/lantiq/patches-5.4/0111-MIPS-lantiq-dma-reset-correct-number-of-channel.patch
@@ -0,0 +1,68 @@
+From d31260c2f6a5cdddb052ab7cb09560eb23ce6597 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Thu, 15 Apr 2021 21:28:24 +0200
+Subject: [PATCH 2/5] MIPS: lantiq: dma: reset correct number of channel
+
+Different SoCs have a different number of channels, e.g .:
+* amazon-se has 10 channels,
+* danube+ar9 have 20 channels,
+* vr9 has 28 channels,
+* ar10 has 24 channels.
+
+We can read the ID register and, depending on the reported
+number of channels, reset the appropriate number of channels.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ arch/mips/lantiq/xway/dma.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -30,6 +30,7 @@
+ #define LTQ_DMA_PCTRL		0x44
+ #define LTQ_DMA_IRNEN		0xf4
+ 
++#define DMA_ID_CHNR		GENMASK(26, 20)	/* channel number */
+ #define DMA_DESCPT		BIT(3)		/* descriptor complete irq */
+ #define DMA_TX			BIT(8)		/* TX channel direction */
+ #define DMA_CHAN_ON		BIT(0)		/* channel on / off bit */
+@@ -40,7 +41,6 @@
+ #define DMA_POLL		BIT(31)		/* turn on channel polling */
+ #define DMA_CLK_DIV4		BIT(6)		/* polling clock divider */
+ #define DMA_2W_BURST		BIT(1)		/* 2 word burst length */
+-#define DMA_MAX_CHANNEL		20		/* the soc has 20 channels */
+ #define DMA_ETOP_ENDIANNESS	(0xf << 8) /* endianness swap etop channels */
+ #define DMA_WEIGHT	(BIT(17) | BIT(16))	/* default channel wheight */
+ 
+@@ -206,7 +206,7 @@ ltq_dma_init(struct platform_device *pde
+ {
+ 	struct clk *clk;
+ 	struct resource *res;
+-	unsigned id;
++	unsigned int id, nchannels;
+ 	int i;
+ 
+ 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+@@ -228,17 +228,18 @@ ltq_dma_init(struct platform_device *pde
+ 	ltq_dma_w32(0, LTQ_DMA_IRNEN);
+ 
+ 	/* reset/configure each channel */
+-	for (i = 0; i < DMA_MAX_CHANNEL; i++) {
++	id = ltq_dma_r32(LTQ_DMA_ID);
++	nchannels = ((id & DMA_ID_CHNR) >> 20);
++	for (i = 0; i < nchannels; i++) {
+ 		ltq_dma_w32(i, LTQ_DMA_CS);
+ 		ltq_dma_w32(DMA_CHAN_RST, LTQ_DMA_CCTRL);
+ 		ltq_dma_w32(DMA_POLL | DMA_CLK_DIV4, LTQ_DMA_CPOLL);
+ 		ltq_dma_w32_mask(DMA_CHAN_ON, 0, LTQ_DMA_CCTRL);
+ 	}
+ 
+-	id = ltq_dma_r32(LTQ_DMA_ID);
+ 	dev_info(&pdev->dev,
+ 		"Init done - hw rev: %X, ports: %d, channels: %d\n",
+-		id & 0x1f, (id >> 16) & 0xf, id >> 20);
++		id & 0x1f, (id >> 16) & 0xf, nchannels);
+ 
+ 	return 0;
+ }
diff --git a/target/linux/lantiq/patches-5.4/0112-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch b/target/linux/lantiq/patches-5.4/0112-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch
new file mode 100644
index 0000000000..67423d2e97
--- /dev/null
+++ b/target/linux/lantiq/patches-5.4/0112-MIPS-lantiq-dma-fix-burst-length-for-DEU.patch
@@ -0,0 +1,41 @@
+From 7d9ea9052d6680d2910b8b005c397d95b3a8b012 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Wed, 7 Apr 2021 21:04:39 +0200
+Subject: [PATCH 3/5] MIPS: lantiq: dma: fix burst length for DEU
+
+The current definition of 2W burst length is invalid.
+This patch fixes it. Current downstream DEU driver doesn't
+use DMA. An incorrect burst length value doesn't cause any
+errors. This patch also adds other burst length values.
+
+Fixes: dfec1a827d2b ("MIPS: Lantiq: Add DMA support")
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ arch/mips/lantiq/xway/dma.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -40,7 +40,11 @@
+ #define DMA_IRQ_ACK		0x7e		/* IRQ status register */
+ #define DMA_POLL		BIT(31)		/* turn on channel polling */
+ #define DMA_CLK_DIV4		BIT(6)		/* polling clock divider */
+-#define DMA_2W_BURST		BIT(1)		/* 2 word burst length */
++#define DMA_PCTRL_2W_BURST	0x1		/* 2 word burst length */
++#define DMA_PCTRL_4W_BURST	0x2		/* 4 word burst length */
++#define DMA_PCTRL_8W_BURST	0x3		/* 8 word burst length */
++#define DMA_TX_BURST_SHIFT	4		/* tx burst shift */
++#define DMA_RX_BURST_SHIFT	2		/* rx burst shift */
+ #define DMA_ETOP_ENDIANNESS	(0xf << 8) /* endianness swap etop channels */
+ #define DMA_WEIGHT	(BIT(17) | BIT(16))	/* default channel wheight */
+ 
+@@ -191,7 +195,8 @@ ltq_dma_init_port(int p)
+ 		break;
+ 
+ 	case DMA_PORT_DEU:
+-		ltq_dma_w32((DMA_2W_BURST << 4) | (DMA_2W_BURST << 2),
++		ltq_dma_w32((DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT) |
++			(DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT),
+ 			LTQ_DMA_PCTRL);
+ 		break;
+ 
diff --git a/target/linux/lantiq/patches-5.4/0113-MIPS-lantiq-dma-make-a-burst-length-configurable-in-.patch b/target/linux/lantiq/patches-5.4/0113-MIPS-lantiq-dma-make-a-burst-length-configurable-in-.patch
new file mode 100644
index 0000000000..fab2440453
--- /dev/null
+++ b/target/linux/lantiq/patches-5.4/0113-MIPS-lantiq-dma-make-a-burst-length-configurable-in-.patch
@@ -0,0 +1,84 @@
+From 6615eeb39f7a110a196f20acbfb3a017da4d75d2 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Fri, 14 May 2021 21:25:08 +0200
+Subject: [PATCH 4/5] MIPS: lantiq: dma: make a burst length configurable in
+ drivers
+
+Make a burst length configurable in drivers.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ .../include/asm/mach-lantiq/xway/xway_dma.h   |  2 +-
+ arch/mips/lantiq/xway/dma.c                   | 38 ++++++++++++++++---
+ 2 files changed, 34 insertions(+), 6 deletions(-)
+
+--- a/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
++++ b/arch/mips/include/asm/mach-lantiq/xway/xway_dma.h
+@@ -45,6 +45,6 @@ extern void ltq_dma_close(struct ltq_dma
+ extern void ltq_dma_alloc_tx(struct ltq_dma_channel *ch);
+ extern void ltq_dma_alloc_rx(struct ltq_dma_channel *ch);
+ extern void ltq_dma_free(struct ltq_dma_channel *ch);
+-extern void ltq_dma_init_port(int p);
++extern void ltq_dma_init_port(int p, int tx_burst, int rx_burst);
+ 
+ #endif
+--- a/arch/mips/lantiq/xway/dma.c
++++ b/arch/mips/lantiq/xway/dma.c
+@@ -181,7 +181,7 @@ ltq_dma_free(struct ltq_dma_channel *ch)
+ EXPORT_SYMBOL_GPL(ltq_dma_free);
+ 
+ void
+-ltq_dma_init_port(int p)
++ltq_dma_init_port(int p, int tx_burst, int rx_burst)
+ {
+ 	ltq_dma_w32(p, LTQ_DMA_PS);
+ 	switch (p) {
+@@ -190,16 +190,44 @@ ltq_dma_init_port(int p)
+ 		 * Tell the DMA engine to swap the endianness of data frames and
+ 		 * drop packets if the channel arbitration fails.
+ 		 */
+-		ltq_dma_w32_mask(0, DMA_ETOP_ENDIANNESS | DMA_PDEN,
++		ltq_dma_w32_mask(0, (DMA_ETOP_ENDIANNESS | DMA_PDEN),
+ 			LTQ_DMA_PCTRL);
+ 		break;
+ 
+-	case DMA_PORT_DEU:
+-		ltq_dma_w32((DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT) |
+-			(DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT),
++	default:
++		break;
++	}
++
++	switch (rx_burst) {
++	case 8:
++		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_8W_BURST << DMA_RX_BURST_SHIFT),
+ 			LTQ_DMA_PCTRL);
+ 		break;
++	case 4:
++		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_4W_BURST << DMA_RX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	case 2:
++		ltq_dma_w32_mask(0x0c, (DMA_PCTRL_2W_BURST << DMA_RX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	default:
++		break;
++	}
+ 
++	switch (tx_burst) {
++	case 8:
++		ltq_dma_w32_mask(0x30, (DMA_PCTRL_8W_BURST << DMA_TX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	case 4:
++		ltq_dma_w32_mask(0x30, (DMA_PCTRL_4W_BURST << DMA_TX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
++	case 2:
++		ltq_dma_w32_mask(0x30, (DMA_PCTRL_2W_BURST << DMA_TX_BURST_SHIFT),
++			LTQ_DMA_PCTRL);
++		break;
+ 	default:
+ 		break;
+ 	}
diff --git a/target/linux/lantiq/patches-5.4/0710-net-lantiq-configure-burst-length-for-ethernet.patch b/target/linux/lantiq/patches-5.4/0710-net-lantiq-configure-burst-length-for-ethernet.patch
new file mode 100644
index 0000000000..746a09c453
--- /dev/null
+++ b/target/linux/lantiq/patches-5.4/0710-net-lantiq-configure-burst-length-for-ethernet.patch
@@ -0,0 +1,124 @@
+From ec1a17a11aced3cd756e59d91ad6f50b7a2fabfb Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2 at wp.pl>
+Date: Sun, 16 May 2021 15:52:06 +0200
+Subject: [PATCH 5/5] net: lantiq: configure burst length for ethernet
+
+Configure the burst length for Ethernet. This improves Ethernet
+performance by 58%. According to the vendor BSP, 8W burst length
+is supported by ar9 and newer SoCs.
+
+The NAT benchmark results on xRX200 (Down/Up):
+* 2W: 330 Mb/s
+* 4W: 432 Mb/s    372 Mb/s
+* 8W: 520 Mb/s    389 Mb/s
+
+Tested on xRX200 and xRX330.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2 at wp.pl>
+---
+ drivers/net/ethernet/lantiq_etop.c   | 21 ++++++++++++++++++---
+ drivers/net/ethernet/lantiq_xrx200.c | 21 ++++++++++++++++++---
+ 2 files changed, 36 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/lantiq_etop.c
++++ b/drivers/net/ethernet/lantiq_etop.c
+@@ -148,6 +148,9 @@ struct ltq_etop_priv {
+ 	struct ltq_etop_chan txch;
+ 	struct ltq_etop_chan rxch;
+ 
++	int tx_burst_len;
++	int rx_burst_len;
++
+ 	int tx_irq;
+ 	int rx_irq;
+ 
+@@ -399,7 +402,7 @@ ltq_etop_dma_init(struct net_device *dev
+ 	int rx = priv->rx_irq - LTQ_DMA_ETOP;
+ 	int err;
+ 
+-	ltq_dma_init_port(DMA_PORT_ETOP);
++	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, priv->rx_burst_len);
+ 
+ 	priv->txch.dma.nr = tx;
+ 	priv->txch.dma.dev = &priv->pdev->dev;
+@@ -676,8 +679,8 @@ ltq_etop_tx(struct sk_buff *skb, struct
+ 		return NETDEV_TX_BUSY;
+ 	}
+ 
+-	/* dma needs to start on a 16 byte aligned address */
+-	byte_offset = CPHYSADDR(skb->data) % 16;
++	/* dma needs to start on a burst length value aligned address */
++	byte_offset = CPHYSADDR(skb->data) % (priv->tx_burst_len * 4);
+ 	priv->txch.skb[priv->txch.dma.desc] = skb;
+ 
+ 	netif_trans_update(dev);
+@@ -930,6 +933,18 @@ static int ltq_etop_probe(struct platfor
+ 	spin_lock_init(&priv->lock);
+ 	SET_NETDEV_DEV(dev, &pdev->dev);
+ 
++	err = device_property_read_u32(&pdev->dev, "lantiq,tx-burst-length", &priv->tx_burst_len);
++	if (err < 0) {
++		dev_err(&pdev->dev, "unable to read tx-burst-length property\n");
++		return err;
++	}
++
++	err = device_property_read_u32(&pdev->dev, "lantiq,rx-burst-length", &priv->rx_burst_len);
++	if (err < 0) {
++		dev_err(&pdev->dev, "unable to read rx-burst-length property\n");
++		return err;
++	}
++
+ 	netif_napi_add(dev, &priv->txch.napi, ltq_etop_poll_tx, 8);
+ 	netif_napi_add(dev, &priv->rxch.napi, ltq_etop_poll_rx, 32);
+ 	priv->txch.netdev = dev;
+--- a/drivers/net/ethernet/lantiq_xrx200.c
++++ b/drivers/net/ethernet/lantiq_xrx200.c
+@@ -71,6 +71,9 @@ struct xrx200_priv {
+ 	struct net_device *net_dev;
+ 	struct device *dev;
+ 
++	int tx_burst_len;
++	int rx_burst_len;
++
+ 	__iomem void *pmac_reg;
+ };
+ 
+@@ -315,8 +318,8 @@ static int xrx200_start_xmit(struct sk_b
+ 	if (unlikely(dma_mapping_error(priv->dev, mapping)))
+ 		goto err_drop;
+ 
+-	/* dma needs to start on a 16 byte aligned address */
+-	byte_offset = mapping % 16;
++	/* dma needs to start on a burst length value aligned address */
++	byte_offset = mapping % (priv->tx_burst_len * 4);
+ 
+ 	desc->addr = mapping - byte_offset;
+ 	/* Make sure the address is written before we give it to HW */
+@@ -368,7 +371,7 @@ static int xrx200_dma_init(struct xrx200
+ 	int ret = 0;
+ 	int i;
+ 
+-	ltq_dma_init_port(DMA_PORT_ETOP);
++	ltq_dma_init_port(DMA_PORT_ETOP, priv->tx_burst_len, priv->rx_burst_len);
+ 
+ 	ch_rx->dma.nr = XRX200_DMA_RX;
+ 	ch_rx->dma.dev = priv->dev;
+@@ -486,6 +489,18 @@ static int xrx200_probe(struct platform_
+ 	if (err)
+ 		eth_hw_addr_random(net_dev);
+ 
++	err = device_property_read_u32(dev, "lantiq,tx-burst-length", &priv->tx_burst_len);
++	if (err < 0) {
++		dev_err(dev, "unable to read tx-burst-length property\n");
++		return err;
++	}
++
++	err = device_property_read_u32(dev, "lantiq,rx-burst-length", &priv->rx_burst_len);
++	if (err < 0) {
++		dev_err(dev, "unable to read rx-burst-length property\n");
++		return err;
++	}
++
+ 	/* bring up the dma engine and IP core */
+ 	err = xrx200_dma_init(priv);
+ 	if (err)



More information about the lede-commits mailing list