bcm4908: backport Ethernet driver fixes from the 5.12
authorRafał Miłecki <rafal@milecki.pl>
Mon, 1 Mar 2021 07:14:49 +0000 (08:14 +0100)
committerRafał Miłecki <rafal@milecki.pl>
Mon, 1 Mar 2021 07:15:48 +0000 (08:15 +0100)
The most noticeable one is fix for RX stopping on high traffic.

Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
target/linux/bcm4908/patches-5.4/073-v5.12-0009-net-broadcom-bcm4908_enet-set-MTU-on-open-on-request.patch [new file with mode: 0644]
target/linux/bcm4908/patches-5.4/073-v5.12-0010-net-broadcom-bcm4908_enet-fix-RX-path-possible-mem-l.patch [new file with mode: 0644]
target/linux/bcm4908/patches-5.4/073-v5.12-0011-net-broadcom-bcm4908_enet-fix-NAPI-poll-returned-val.patch [new file with mode: 0644]
target/linux/bcm4908/patches-5.4/073-v5.12-0012-net-broadcom-bcm4908_enet-enable-RX-after-processing.patch [new file with mode: 0644]
target/linux/bcm4908/patches-5.4/170-net-broadcom-bcm4908_enet-set-MTU-on-open-on-request.patch [deleted file]

diff --git a/target/linux/bcm4908/patches-5.4/073-v5.12-0009-net-broadcom-bcm4908_enet-set-MTU-on-open-on-request.patch b/target/linux/bcm4908/patches-5.4/073-v5.12-0009-net-broadcom-bcm4908_enet-set-MTU-on-open-on-request.patch
new file mode 100644 (file)
index 0000000..0201bfe
--- /dev/null
@@ -0,0 +1,119 @@
+From 14b3b46a67f78ade99eafcbf320105615e948569 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 12 Feb 2021 16:21:35 +0100
+Subject: [PATCH] net: broadcom: bcm4908_enet: set MTU on open & on request
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Hardware comes up with default max frame size set to 1518. When using it
+with switch it results in actual Ethernet MTU 1492:
+1518 - 14 (Ethernet header) - 4 (Broadcom's tag) - 4 (802.1q) - 4 (FCS)
+
+Above means hardware in its default state can't handle standard Ethernet
+traffic (MTU 1500).
+
+Define maximum possible Ethernet overhead and always set MAC max frame
+length accordingly. This change fixes handling Ethernet frames of length
+1506 - 1514.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/broadcom/bcm4908_enet.c | 31 ++++++++++++++++----
+ 1 file changed, 25 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
+@@ -5,6 +5,7 @@
+ #include <linux/delay.h>
+ #include <linux/etherdevice.h>
++#include <linux/if_vlan.h>
+ #include <linux/interrupt.h>
+ #include <linux/module.h>
+ #include <linux/of.h>
+@@ -29,9 +30,10 @@
+                                                ENET_DMA_CH_CFG_INT_BUFF_DONE)
+ #define ENET_DMA_MAX_BURST_LEN                        8 /* in 64 bit words */
+-#define ENET_MTU_MIN                          60
+-#define ENET_MTU_MAX                          1500 /* Is it possible to support 2044? */
+-#define ENET_MTU_MAX_EXTRA_SIZE                       32 /* L2 */
++#define ENET_MTU_MAX                          ETH_DATA_LEN /* Is it possible to support 2044? */
++#define BRCM_MAX_TAG_LEN                      6
++#define ENET_MAX_ETH_OVERHEAD                 (ETH_HLEN + BRCM_MAX_TAG_LEN + VLAN_HLEN + \
++                                               ETH_FCS_LEN + 4) /* 32 */
+ struct bcm4908_enet_dma_ring_bd {
+       __le32 ctl;
+@@ -135,6 +137,11 @@ static void bcm4908_enet_intrs_ack(struc
+       enet_write(enet, ENET_DMA_CH_RX_CFG + ENET_DMA_CH_CFG_INT_STAT, ENET_DMA_INT_DEFAULTS);
+ }
++static void bcm4908_enet_set_mtu(struct bcm4908_enet *enet, int mtu)
++{
++      enet_umac_write(enet, UMAC_MAX_FRAME_LEN, mtu + ENET_MAX_ETH_OVERHEAD);
++}
++
+ /***
+  * DMA
+  */
+@@ -246,7 +253,7 @@ static int bcm4908_enet_dma_alloc_rx_buf
+       u32 tmp;
+       int err;
+-      slot->len = ENET_MTU_MAX + ENET_MTU_MAX_EXTRA_SIZE;
++      slot->len = ENET_MTU_MAX + ENET_MAX_ETH_OVERHEAD;
+       slot->skb = netdev_alloc_skb(enet->netdev, slot->len);
+       if (!slot->skb)
+@@ -374,6 +381,8 @@ static void bcm4908_enet_gmac_init(struc
+ {
+       u32 cmd;
++      bcm4908_enet_set_mtu(enet, enet->netdev->mtu);
++
+       cmd = enet_umac_read(enet, UMAC_CMD);
+       enet_umac_write(enet, UMAC_CMD, cmd | CMD_SW_RESET);
+       enet_umac_write(enet, UMAC_CMD, cmd & ~CMD_SW_RESET);
+@@ -559,7 +568,7 @@ static int bcm4908_enet_poll(struct napi
+               len = (ctl & DMA_CTL_LEN_DESC_BUFLENGTH) >> DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT;
+-              if (len < ENET_MTU_MIN ||
++              if (len < ETH_ZLEN ||
+                   (ctl & (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) != (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) {
+                       enet->netdev->stats.rx_dropped++;
+                       break;
+@@ -583,11 +592,21 @@ static int bcm4908_enet_poll(struct napi
+       return handled;
+ }
++static int bcm4908_enet_change_mtu(struct net_device *netdev, int new_mtu)
++{
++      struct bcm4908_enet *enet = netdev_priv(netdev);
++
++      bcm4908_enet_set_mtu(enet, new_mtu);
++
++      return 0;
++}
++
+ static const struct net_device_ops bcm4908_enet_netdev_ops = {
+       .ndo_open = bcm4908_enet_open,
+       .ndo_stop = bcm4908_enet_stop,
+       .ndo_start_xmit = bcm4908_enet_start_xmit,
+       .ndo_set_mac_address = eth_mac_addr,
++      .ndo_change_mtu = bcm4908_enet_change_mtu,
+ };
+ static int bcm4908_enet_probe(struct platform_device *pdev)
+@@ -625,7 +644,7 @@ static int bcm4908_enet_probe(struct pla
+       eth_hw_addr_random(netdev);
+       netdev->netdev_ops = &bcm4908_enet_netdev_ops;
+       netdev->min_mtu = ETH_ZLEN;
+-      netdev->mtu = ENET_MTU_MAX;
++      netdev->mtu = ETH_DATA_LEN;
+       netdev->max_mtu = ENET_MTU_MAX;
+       netif_napi_add(netdev, &enet->napi, bcm4908_enet_poll, 64);
diff --git a/target/linux/bcm4908/patches-5.4/073-v5.12-0010-net-broadcom-bcm4908_enet-fix-RX-path-possible-mem-l.patch b/target/linux/bcm4908/patches-5.4/073-v5.12-0010-net-broadcom-bcm4908_enet-fix-RX-path-possible-mem-l.patch
new file mode 100644 (file)
index 0000000..8a24324
--- /dev/null
@@ -0,0 +1,30 @@
+From 4dc7f09b8becfa35a55430a49d95acf19f996e6b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Wed, 24 Feb 2021 16:18:41 +0100
+Subject: [PATCH] net: broadcom: bcm4908_enet: fix RX path possible mem leak
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+After filling RX ring slot with new skb it's required to free old skb.
+Immediately on error or later in the net subsystem.
+
+Fixes: 4feffeadbcb2 ("net: broadcom: bcm4908enet: add BCM4908 controller driver")
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Link: https://lore.kernel.org/r/20210224151842.2419-1-zajec5@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bcm4908_enet.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
+@@ -570,6 +570,7 @@ static int bcm4908_enet_poll(struct napi
+               if (len < ETH_ZLEN ||
+                   (ctl & (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) != (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) {
++                      kfree_skb(slot.skb);
+                       enet->netdev->stats.rx_dropped++;
+                       break;
+               }
diff --git a/target/linux/bcm4908/patches-5.4/073-v5.12-0011-net-broadcom-bcm4908_enet-fix-NAPI-poll-returned-val.patch b/target/linux/bcm4908/patches-5.4/073-v5.12-0011-net-broadcom-bcm4908_enet-fix-NAPI-poll-returned-val.patch
new file mode 100644 (file)
index 0000000..d4cf84e
--- /dev/null
@@ -0,0 +1,31 @@
+From 4d9274cee40b6a20dd6148c6c81c6733c2678cbc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Wed, 24 Feb 2021 16:18:42 +0100
+Subject: [PATCH] net: broadcom: bcm4908_enet: fix NAPI poll returned value
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Missing increment was resulting in poll function always returning 0
+instead of amount of processed packets.
+
+Fixes: 4feffeadbcb2 ("net: broadcom: bcm4908enet: add BCM4908 controller driver")
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Link: https://lore.kernel.org/r/20210224151842.2419-2-zajec5@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bcm4908_enet.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
+@@ -583,6 +583,8 @@ static int bcm4908_enet_poll(struct napi
+               enet->netdev->stats.rx_packets++;
+               enet->netdev->stats.rx_bytes += len;
++
++              handled++;
+       }
+       if (handled < weight) {
diff --git a/target/linux/bcm4908/patches-5.4/073-v5.12-0012-net-broadcom-bcm4908_enet-enable-RX-after-processing.patch b/target/linux/bcm4908/patches-5.4/073-v5.12-0012-net-broadcom-bcm4908_enet-enable-RX-after-processing.patch
new file mode 100644 (file)
index 0000000..ad1bebf
--- /dev/null
@@ -0,0 +1,34 @@
+From d313d16bbaea0f11a2e98f04a6c678b43c208915 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Fri, 26 Feb 2021 14:20:38 +0100
+Subject: [PATCH] net: broadcom: bcm4908_enet: enable RX after processing
+ packets
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When receiving a lot of packets hardware may run out of free
+descriptiors and stop RX ring. Enable it every time after handling
+received packets.
+
+Fixes: 4feffeadbcb2 ("net: broadcom: bcm4908enet: add BCM4908 controller driver")
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Acked-by: Florian Fainelli <f.fainelli@gmail.com>
+Link: https://lore.kernel.org/r/20210226132038.29849-1-zajec5@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/broadcom/bcm4908_enet.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
++++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
+@@ -592,6 +592,9 @@ static int bcm4908_enet_poll(struct napi
+               bcm4908_enet_intrs_on(enet);
+       }
++      /* Hardware could disable ring if it run out of descriptors */
++      bcm4908_enet_dma_rx_ring_enable(enet, &enet->rx_ring);
++
+       return handled;
+ }
diff --git a/target/linux/bcm4908/patches-5.4/170-net-broadcom-bcm4908_enet-set-MTU-on-open-on-request.patch b/target/linux/bcm4908/patches-5.4/170-net-broadcom-bcm4908_enet-set-MTU-on-open-on-request.patch
deleted file mode 100644 (file)
index 87cb851..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-From d7dfbcba0437955ccbe4c6db736526d528f27720 Mon Sep 17 00:00:00 2001
-From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
-Date: Fri, 12 Feb 2021 16:06:00 +0100
-Subject: [PATCH] net: broadcom: bcm4908_enet: set MTU on open & on request
-
-Hardware comes up with default max frame size set to 1518. When using it
-with switch it results in actual Ethernet MTU 1492:
-1518 - 14 (Ethernet header) - 4 (Broadcom's tag) - 4 (802.1q) - 4 (FCS)
-
-Above means hardware in its default state can't handle standard Ethernet
-traffic (MTU 1500).
-
-Define maximum possible Ethernet overhead and always set MAC max frame
-length accordingly. This change fixes handling Ethernet frames of length
-1506 - 1514.
----
- drivers/net/ethernet/broadcom/bcm4908_enet.c | 31 ++++++++++++++++----
- 1 file changed, 25 insertions(+), 6 deletions(-)
-
---- a/drivers/net/ethernet/broadcom/bcm4908_enet.c
-+++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c
-@@ -5,6 +5,7 @@
- #include <linux/delay.h>
- #include <linux/etherdevice.h>
-+#include <linux/if_vlan.h>
- #include <linux/interrupt.h>
- #include <linux/module.h>
- #include <linux/of.h>
-@@ -29,9 +30,10 @@
-                                                ENET_DMA_CH_CFG_INT_BUFF_DONE)
- #define ENET_DMA_MAX_BURST_LEN                        8 /* in 64 bit words */
--#define ENET_MTU_MIN                          60
--#define ENET_MTU_MAX                          1500 /* Is it possible to support 2044? */
--#define ENET_MTU_MAX_EXTRA_SIZE                       32 /* L2 */
-+#define ENET_MTU_MAX                          ETH_DATA_LEN /* Is it possible to support 2044? */
-+#define BRCM_MAX_TAG_LEN                      6
-+#define ENET_MAX_ETH_OVERHEAD                 (ETH_HLEN + BRCM_MAX_TAG_LEN + VLAN_HLEN + \
-+                                               ETH_FCS_LEN + 4) /* 32 */
- struct bcm4908_enet_dma_ring_bd {
-       __le32 ctl;
-@@ -135,6 +137,11 @@ static void bcm4908_enet_intrs_ack(struc
-       enet_write(enet, ENET_DMA_CH_RX_CFG + ENET_DMA_CH_CFG_INT_STAT, ENET_DMA_INT_DEFAULTS);
- }
-+static void bcm4908_enet_set_mtu(struct bcm4908_enet *enet, int mtu)
-+{
-+      enet_umac_write(enet, UMAC_MAX_FRAME_LEN, mtu + ENET_MAX_ETH_OVERHEAD);
-+}
-+
- /***
-  * DMA
-  */
-@@ -246,7 +253,7 @@ static int bcm4908_enet_dma_alloc_rx_buf
-       u32 tmp;
-       int err;
--      slot->len = ENET_MTU_MAX + ENET_MTU_MAX_EXTRA_SIZE;
-+      slot->len = ENET_MTU_MAX + ENET_MAX_ETH_OVERHEAD;
-       slot->skb = netdev_alloc_skb(enet->netdev, slot->len);
-       if (!slot->skb)
-@@ -374,6 +381,8 @@ static void bcm4908_enet_gmac_init(struc
- {
-       u32 cmd;
-+      bcm4908_enet_set_mtu(enet, enet->netdev->mtu);
-+
-       cmd = enet_umac_read(enet, UMAC_CMD);
-       enet_umac_write(enet, UMAC_CMD, cmd | CMD_SW_RESET);
-       enet_umac_write(enet, UMAC_CMD, cmd & ~CMD_SW_RESET);
-@@ -559,7 +568,7 @@ static int bcm4908_enet_poll(struct napi
-               len = (ctl & DMA_CTL_LEN_DESC_BUFLENGTH) >> DMA_CTL_LEN_DESC_BUFLENGTH_SHIFT;
--              if (len < ENET_MTU_MIN ||
-+              if (len < ETH_ZLEN ||
-                   (ctl & (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) != (DMA_CTL_STATUS_SOP | DMA_CTL_STATUS_EOP)) {
-                       enet->netdev->stats.rx_dropped++;
-                       break;
-@@ -583,11 +592,21 @@ static int bcm4908_enet_poll(struct napi
-       return handled;
- }
-+static int bcm4908_enet_change_mtu(struct net_device *netdev, int new_mtu)
-+{
-+      struct bcm4908_enet *enet = netdev_priv(netdev);
-+
-+      bcm4908_enet_set_mtu(enet, new_mtu);
-+
-+      return 0;
-+}
-+
- static const struct net_device_ops bcm4908_enet_netdev_ops = {
-       .ndo_open = bcm4908_enet_open,
-       .ndo_stop = bcm4908_enet_stop,
-       .ndo_start_xmit = bcm4908_enet_start_xmit,
-       .ndo_set_mac_address = eth_mac_addr,
-+      .ndo_change_mtu = bcm4908_enet_change_mtu,
- };
- static int bcm4908_enet_probe(struct platform_device *pdev)
-@@ -625,7 +644,7 @@ static int bcm4908_enet_probe(struct pla
-       eth_hw_addr_random(netdev);
-       netdev->netdev_ops = &bcm4908_enet_netdev_ops;
-       netdev->min_mtu = ETH_ZLEN;
--      netdev->mtu = ENET_MTU_MAX;
-+      netdev->mtu = ETH_DATA_LEN;
-       netdev->max_mtu = ENET_MTU_MAX;
-       netif_napi_add(netdev, &enet->napi, bcm4908_enet_poll, 64);