+++ /dev/null
-From 24a43ae2ac0ea06c474b1c80dc75651294d49321 Mon Sep 17 00:00:00 2001
-From: Thomas Nixon <tom@tomn.co.uk>
-Date: Sat, 2 Oct 2021 00:48:05 +0100
-Subject: [PATCH 2/2] net: lantiq: enable jumbo frames on GSWIP
-
-This enables non-standard MTUs on a per-port basis, with the overall
-frame size set based on the CPU port.
-
-When the MTU is not changed, this should have no effect.
-
-Long packets crash the switch with MTUs of greater than 2526, so the
-maximum is limited for now.
-
-Signed-off-by: Thomas Nixon <tom@tomn.co.uk>
----
- drivers/net/dsa/lantiq_gswip.c | 46 +++++++++++++++++++++++++++++++---
- 1 file changed, 42 insertions(+), 4 deletions(-)
-
---- a/drivers/net/dsa/lantiq_gswip.c
-+++ b/drivers/net/dsa/lantiq_gswip.c
-@@ -238,6 +238,11 @@
-
- #define XRX200_GPHY_FW_ALIGN (16 * 1024)
-
-+/* maximum packet size supported by the switch; in theory this should be 9600,
-+ * but long packets currently cause lock-ups with an MTU of over 2526
-+ */
-+#define GSWIP_MAX_PACKET_LENGTH 2556
-+
- struct gswip_hw_info {
- int max_ports;
- int cpu_port;
-@@ -856,10 +861,6 @@ static int gswip_setup(struct dsa_switch
- gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS,
- GSWIP_PCE_PCTRL_0p(cpu_port));
-
-- gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
-- GSWIP_MAC_CTRL_2p(cpu_port));
-- gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8 + ETH_FCS_LEN,
-- GSWIP_MAC_FLEN);
- gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD,
- GSWIP_BM_QUEUE_GCTRL);
-
-@@ -876,6 +877,8 @@ static int gswip_setup(struct dsa_switch
- return err;
- }
-
-+ ds->mtu_enforcement_ingress = true;
-+
- gswip_port_enable(ds, cpu_port, NULL);
- return 0;
- }
-@@ -1438,6 +1441,39 @@ static int gswip_port_fdb_dump(struct ds
- return 0;
- }
-
-+static int gswip_port_max_mtu(struct dsa_switch *ds, int port)
-+{
-+ /* includes 8 bytes for special header */
-+ return GSWIP_MAX_PACKET_LENGTH - VLAN_ETH_HLEN - ETH_FCS_LEN;
-+}
-+
-+static int gswip_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
-+{
-+ struct gswip_priv *priv = ds->priv;
-+ int cpu_port = priv->hw_info->cpu_port;
-+
-+ /* cpu port always has maximum mtu of user ports, so use it to set
-+ * switch frame size, including 8 byte special header
-+ */
-+ if (port == cpu_port) {
-+ new_mtu += 8;
-+ gswip_switch_w(priv, VLAN_ETH_HLEN + new_mtu + ETH_FCS_LEN,
-+ GSWIP_MAC_FLEN);
-+ }
-+
-+ /* enable MLEN for ports with non-standard MTUs, including the special
-+ * header on the CPU port added above
-+ */
-+ if (new_mtu != ETH_DATA_LEN)
-+ gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
-+ GSWIP_MAC_CTRL_2p(port));
-+ else
-+ gswip_switch_mask(priv, GSWIP_MAC_CTRL_2_MLEN, 0,
-+ GSWIP_MAC_CTRL_2p(port));
-+
-+ return 0;
-+}
-+
- static void gswip_phylink_validate(struct dsa_switch *ds, int port,
- unsigned long *supported,
- struct phylink_link_state *state)
-@@ -1781,6 +1817,8 @@ static const struct dsa_switch_ops gswip
- .port_fdb_add = gswip_port_fdb_add,
- .port_fdb_del = gswip_port_fdb_del,
- .port_fdb_dump = gswip_port_fdb_dump,
-+ .port_change_mtu = gswip_port_change_mtu,
-+ .port_max_mtu = gswip_port_max_mtu,
- .phylink_validate = gswip_phylink_validate,
- .phylink_mac_config = gswip_phylink_mac_config,
- .phylink_mac_link_down = gswip_phylink_mac_link_down,
--- /dev/null
+From 1488fc204568f707fe2a42a913788c00a95af30e Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2@wp.pl>
+Date: Fri, 17 Dec 2021 01:07:40 +0100
+Subject: [PATCH] net: lantiq_xrx200: increase buffer reservation
+
+If the user sets a lower mtu on the CPU port than on the switch,
+then DMA inserts a few more bytes into the buffer than expected.
+In the worst case, it may exceed the size of the buffer. The
+experiments showed that the buffer should be a multiple of the
+burst length value. This patch rounds the length of the rx buffer
+upwards and fixes this bug. The reservation of FCS space in the
+buffer has been removed as PMAC strips the FCS.
+
+Fixes: 998ac358019e ("net: lantiq: add support for jumbo frames")
+Reported-by: Thomas Nixon <tom@tomn.co.uk>
+Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/lantiq_xrx200.c | 34 ++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ethernet/lantiq_xrx200.c
++++ b/drivers/net/ethernet/lantiq_xrx200.c
+@@ -70,6 +70,8 @@ struct xrx200_priv {
+ struct xrx200_chan chan_tx;
+ struct xrx200_chan chan_rx;
+
++ u16 rx_buf_size;
++
+ struct net_device *net_dev;
+ struct device *dev;
+
+@@ -96,6 +98,16 @@ static void xrx200_pmac_mask(struct xrx2
+ xrx200_pmac_w32(priv, val, offset);
+ }
+
++static int xrx200_max_frame_len(int mtu)
++{
++ return VLAN_ETH_HLEN + mtu;
++}
++
++static int xrx200_buffer_size(int mtu)
++{
++ return round_up(xrx200_max_frame_len(mtu), 4 * XRX200_DMA_BURST_LEN);
++}
++
+ /* drop all the packets from the DMA ring */
+ static void xrx200_flush_dma(struct xrx200_chan *ch)
+ {
+@@ -108,8 +120,7 @@ static void xrx200_flush_dma(struct xrx2
+ break;
+
+ desc->ctl = LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
+- (ch->priv->net_dev->mtu + VLAN_ETH_HLEN +
+- ETH_FCS_LEN);
++ ch->priv->rx_buf_size;
+ ch->dma.desc++;
+ ch->dma.desc %= LTQ_DESC_NUM;
+ }
+@@ -157,21 +168,21 @@ static int xrx200_close(struct net_devic
+
+ static int xrx200_alloc_skb(struct xrx200_chan *ch)
+ {
+- int len = ch->priv->net_dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
+ struct sk_buff *skb = ch->skb[ch->dma.desc];
++ struct xrx200_priv *priv = ch->priv;
+ dma_addr_t mapping;
+ int ret = 0;
+
+- ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev,
+- len);
++ ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(priv->net_dev,
++ priv->rx_buf_size);
+ if (!ch->skb[ch->dma.desc]) {
+ ret = -ENOMEM;
+ goto skip;
+ }
+
+- mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data,
+- len, DMA_FROM_DEVICE);
+- if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) {
++ mapping = dma_map_single(priv->dev, ch->skb[ch->dma.desc]->data,
++ priv->rx_buf_size, DMA_FROM_DEVICE);
++ if (unlikely(dma_mapping_error(priv->dev, mapping))) {
+ dev_kfree_skb_any(ch->skb[ch->dma.desc]);
+ ch->skb[ch->dma.desc] = skb;
+ ret = -ENOMEM;
+@@ -183,7 +194,7 @@ static int xrx200_alloc_skb(struct xrx20
+ wmb();
+ skip:
+ ch->dma.desc_base[ch->dma.desc].ctl =
+- LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | len;
++ LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | priv->rx_buf_size;
+
+ return ret;
+ }
+@@ -355,6 +366,7 @@ xrx200_change_mtu(struct net_device *net
+ int ret = 0;
+
+ net_dev->mtu = new_mtu;
++ priv->rx_buf_size = xrx200_buffer_size(new_mtu);
+
+ if (new_mtu <= old_mtu)
+ return ret;
+@@ -374,6 +386,7 @@ xrx200_change_mtu(struct net_device *net
+ ret = xrx200_alloc_skb(ch_rx);
+ if (ret) {
+ net_dev->mtu = old_mtu;
++ priv->rx_buf_size = xrx200_buffer_size(old_mtu);
+ break;
+ }
+ dev_kfree_skb_any(skb);
+@@ -504,7 +517,8 @@ static int xrx200_probe(struct platform_
+ net_dev->netdev_ops = &xrx200_netdev_ops;
+ SET_NETDEV_DEV(net_dev, dev);
+ net_dev->min_mtu = ETH_ZLEN;
+- net_dev->max_mtu = XRX200_DMA_DATA_LEN - VLAN_ETH_HLEN - ETH_FCS_LEN;
++ net_dev->max_mtu = XRX200_DMA_DATA_LEN - xrx200_max_frame_len(0);
++ priv->rx_buf_size = xrx200_buffer_size(ETH_DATA_LEN);
+
+ /* load the memory ranges */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+++ /dev/null
-From 1488fc204568f707fe2a42a913788c00a95af30e Mon Sep 17 00:00:00 2001
-From: Aleksander Jan Bajkowski <olek2@wp.pl>
-Date: Fri, 17 Dec 2021 01:07:40 +0100
-Subject: [PATCH] net: lantiq_xrx200: increase buffer reservation
-
-If the user sets a lower mtu on the CPU port than on the switch,
-then DMA inserts a few more bytes into the buffer than expected.
-In the worst case, it may exceed the size of the buffer. The
-experiments showed that the buffer should be a multiple of the
-burst length value. This patch rounds the length of the rx buffer
-upwards and fixes this bug. The reservation of FCS space in the
-buffer has been removed as PMAC strips the FCS.
-
-Fixes: 998ac358019e ("net: lantiq: add support for jumbo frames")
-Reported-by: Thomas Nixon <tom@tomn.co.uk>
-Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
-Signed-off-by: Jakub Kicinski <kuba@kernel.org>
----
- drivers/net/ethernet/lantiq_xrx200.c | 34 ++++++++++++++++++++--------
- 1 file changed, 24 insertions(+), 10 deletions(-)
-
---- a/drivers/net/ethernet/lantiq_xrx200.c
-+++ b/drivers/net/ethernet/lantiq_xrx200.c
-@@ -70,6 +70,8 @@ struct xrx200_priv {
- struct xrx200_chan chan_tx;
- struct xrx200_chan chan_rx;
-
-+ u16 rx_buf_size;
-+
- struct net_device *net_dev;
- struct device *dev;
-
-@@ -96,6 +98,16 @@ static void xrx200_pmac_mask(struct xrx2
- xrx200_pmac_w32(priv, val, offset);
- }
-
-+static int xrx200_max_frame_len(int mtu)
-+{
-+ return VLAN_ETH_HLEN + mtu;
-+}
-+
-+static int xrx200_buffer_size(int mtu)
-+{
-+ return round_up(xrx200_max_frame_len(mtu), 4 * XRX200_DMA_BURST_LEN);
-+}
-+
- /* drop all the packets from the DMA ring */
- static void xrx200_flush_dma(struct xrx200_chan *ch)
- {
-@@ -108,8 +120,7 @@ static void xrx200_flush_dma(struct xrx2
- break;
-
- desc->ctl = LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) |
-- (ch->priv->net_dev->mtu + VLAN_ETH_HLEN +
-- ETH_FCS_LEN);
-+ ch->priv->rx_buf_size;
- ch->dma.desc++;
- ch->dma.desc %= LTQ_DESC_NUM;
- }
-@@ -157,21 +168,21 @@ static int xrx200_close(struct net_devic
-
- static int xrx200_alloc_skb(struct xrx200_chan *ch)
- {
-- int len = ch->priv->net_dev->mtu + VLAN_ETH_HLEN + ETH_FCS_LEN;
- struct sk_buff *skb = ch->skb[ch->dma.desc];
-+ struct xrx200_priv *priv = ch->priv;
- dma_addr_t mapping;
- int ret = 0;
-
-- ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(ch->priv->net_dev,
-- len);
-+ ch->skb[ch->dma.desc] = netdev_alloc_skb_ip_align(priv->net_dev,
-+ priv->rx_buf_size);
- if (!ch->skb[ch->dma.desc]) {
- ret = -ENOMEM;
- goto skip;
- }
-
-- mapping = dma_map_single(ch->priv->dev, ch->skb[ch->dma.desc]->data,
-- len, DMA_FROM_DEVICE);
-- if (unlikely(dma_mapping_error(ch->priv->dev, mapping))) {
-+ mapping = dma_map_single(priv->dev, ch->skb[ch->dma.desc]->data,
-+ priv->rx_buf_size, DMA_FROM_DEVICE);
-+ if (unlikely(dma_mapping_error(priv->dev, mapping))) {
- dev_kfree_skb_any(ch->skb[ch->dma.desc]);
- ch->skb[ch->dma.desc] = skb;
- ret = -ENOMEM;
-@@ -183,7 +194,7 @@ static int xrx200_alloc_skb(struct xrx20
- wmb();
- skip:
- ch->dma.desc_base[ch->dma.desc].ctl =
-- LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | len;
-+ LTQ_DMA_OWN | LTQ_DMA_RX_OFFSET(NET_IP_ALIGN) | priv->rx_buf_size;
-
- return ret;
- }
-@@ -355,6 +366,7 @@ xrx200_change_mtu(struct net_device *net
- int ret = 0;
-
- net_dev->mtu = new_mtu;
-+ priv->rx_buf_size = xrx200_buffer_size(new_mtu);
-
- if (new_mtu <= old_mtu)
- return ret;
-@@ -374,6 +386,7 @@ xrx200_change_mtu(struct net_device *net
- ret = xrx200_alloc_skb(ch_rx);
- if (ret) {
- net_dev->mtu = old_mtu;
-+ priv->rx_buf_size = xrx200_buffer_size(old_mtu);
- break;
- }
- dev_kfree_skb_any(skb);
-@@ -504,7 +517,8 @@ static int xrx200_probe(struct platform_
- net_dev->netdev_ops = &xrx200_netdev_ops;
- SET_NETDEV_DEV(net_dev, dev);
- net_dev->min_mtu = ETH_ZLEN;
-- net_dev->max_mtu = XRX200_DMA_DATA_LEN - VLAN_ETH_HLEN - ETH_FCS_LEN;
-+ net_dev->max_mtu = XRX200_DMA_DATA_LEN - xrx200_max_frame_len(0);
-+ priv->rx_buf_size = xrx200_buffer_size(ETH_DATA_LEN);
-
- /* load the memory ranges */
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
--- /dev/null
+From c3e6b2c35b34214c58c1e90d65dab5f5393608e7 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2@wp.pl>
+Date: Mon, 3 Jan 2022 20:43:16 +0100
+Subject: [PATCH] net: lantiq_xrx200: add ingress SG DMA support
+
+This patch adds support for scatter gather DMA. DMA in PMAC splits
+the packet into several buffers when the MTU on the CPU port is
+less than the MTU of the switch. The first buffer starts at an
+offset of NET_IP_ALIGN. In subsequent buffers, dma ignores the
+offset. Thanks to this patch, the user can still connect to the
+device in such a situation. For normal configurations, the patch
+has no effect on performance.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/ethernet/lantiq_xrx200.c | 47 +++++++++++++++++++++++-----
+ 1 file changed, 40 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/ethernet/lantiq_xrx200.c
++++ b/drivers/net/ethernet/lantiq_xrx200.c
+@@ -26,6 +26,9 @@
+ #define XRX200_DMA_RX 0
+ #define XRX200_DMA_TX 1
+
++#define XRX200_DMA_PACKET_COMPLETE 0
++#define XRX200_DMA_PACKET_IN_PROGRESS 1
++
+ /* cpu port mac */
+ #define PMAC_RX_IPG 0x0024
+ #define PMAC_RX_IPG_MASK 0xf
+@@ -61,6 +64,9 @@ struct xrx200_chan {
+ struct ltq_dma_channel dma;
+ struct sk_buff *skb[LTQ_DESC_NUM];
+
++ struct sk_buff *skb_head;
++ struct sk_buff *skb_tail;
++
+ struct xrx200_priv *priv;
+ };
+
+@@ -204,7 +210,8 @@ static int xrx200_hw_receive(struct xrx2
+ struct xrx200_priv *priv = ch->priv;
+ struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
+ struct sk_buff *skb = ch->skb[ch->dma.desc];
+- int len = (desc->ctl & LTQ_DMA_SIZE_MASK);
++ u32 ctl = desc->ctl;
++ int len = (ctl & LTQ_DMA_SIZE_MASK);
+ struct net_device *net_dev = priv->net_dev;
+ int ret;
+
+@@ -220,12 +227,36 @@ static int xrx200_hw_receive(struct xrx2
+ }
+
+ skb_put(skb, len);
+- skb->protocol = eth_type_trans(skb, net_dev);
+- netif_receive_skb(skb);
+- net_dev->stats.rx_packets++;
+- net_dev->stats.rx_bytes += len;
+
+- return 0;
++ /* add buffers to skb via skb->frag_list */
++ if (ctl & LTQ_DMA_SOP) {
++ ch->skb_head = skb;
++ ch->skb_tail = skb;
++ } else if (ch->skb_head) {
++ if (ch->skb_head == ch->skb_tail)
++ skb_shinfo(ch->skb_tail)->frag_list = skb;
++ else
++ ch->skb_tail->next = skb;
++ ch->skb_tail = skb;
++ skb_reserve(ch->skb_tail, -NET_IP_ALIGN);
++ ch->skb_head->len += skb->len;
++ ch->skb_head->data_len += skb->len;
++ ch->skb_head->truesize += skb->truesize;
++ }
++
++ if (ctl & LTQ_DMA_EOP) {
++ ch->skb_head->protocol = eth_type_trans(ch->skb_head, net_dev);
++ netif_receive_skb(ch->skb_head);
++ net_dev->stats.rx_packets++;
++ net_dev->stats.rx_bytes += ch->skb_head->len;
++ ch->skb_head = NULL;
++ ch->skb_tail = NULL;
++ ret = XRX200_DMA_PACKET_COMPLETE;
++ } else {
++ ret = XRX200_DMA_PACKET_IN_PROGRESS;
++ }
++
++ return ret;
+ }
+
+ static int xrx200_poll_rx(struct napi_struct *napi, int budget)
+@@ -240,7 +271,9 @@ static int xrx200_poll_rx(struct napi_st
+
+ if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
+ ret = xrx200_hw_receive(ch);
+- if (ret)
++ if (ret == XRX200_DMA_PACKET_IN_PROGRESS)
++ continue;
++ if (ret != XRX200_DMA_PACKET_COMPLETE)
+ return ret;
+ rx++;
+ } else {
--- /dev/null
+From a09d042b086202735c4ed64573cdd79933020001 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2@wp.pl>
+Date: Mon, 22 Mar 2021 21:37:15 +0100
+Subject: [PATCH] net: dsa: lantiq: allow to use all GPHYs on xRX300 and xRX330
+
+This patch allows to use all PHYs on GRX300 and GRX330. The ARX300
+has 3 and the GRX330 has 4 integrated PHYs connected to different
+ports compared to VRX200. Each integrated PHY can work as single
+Gigabit Ethernet PHY (GMII) or as double Fast Ethernet PHY (MII).
+
+Allowed port configurations:
+
+xRX200:
+GMAC0: RGMII, MII, REVMII or RMII port
+GMAC1: RGMII, MII, REVMII or RMII port
+GMAC2: GPHY0 (GMII)
+GMAC3: GPHY0 (MII)
+GMAC4: GPHY1 (GMII)
+GMAC5: GPHY1 (MII) or RGMII port
+
+xRX300:
+GMAC0: RGMII port
+GMAC1: GPHY2 (GMII)
+GMAC2: GPHY0 (GMII)
+GMAC3: GPHY0 (MII)
+GMAC4: GPHY1 (GMII)
+GMAC5: GPHY1 (MII) or RGMII port
+
+xRX330:
+GMAC0: RGMII, GMII or RMII port
+GMAC1: GPHY2 (GMII)
+GMAC2: GPHY0 (GMII)
+GMAC3: GPHY0 (MII) or GPHY3 (GMII)
+GMAC4: GPHY1 (GMII)
+GMAC5: GPHY1 (MII), RGMII or RMII port
+
+Tested on D-Link DWR966 (xRX330) with OpenWRT.
+
+Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
+Acked-by: Hauke Mehrtens <hauke@hauke-m.de>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/dsa/lantiq_gswip.c | 142 ++++++++++++++++++++++++++-------
+ 1 file changed, 113 insertions(+), 29 deletions(-)
+
+--- a/drivers/net/dsa/lantiq_gswip.c
++++ b/drivers/net/dsa/lantiq_gswip.c
+@@ -1,6 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /*
+- * Lantiq / Intel GSWIP switch driver for VRX200 SoCs
++ * Lantiq / Intel GSWIP switch driver for VRX200, xRX300 and xRX330 SoCs
+ *
+ * Copyright (C) 2010 Lantiq Deutschland
+ * Copyright (C) 2012 John Crispin <john@phrozen.org>
+@@ -104,6 +104,7 @@
+ #define GSWIP_MII_CFG_MODE_RMIIP 0x2
+ #define GSWIP_MII_CFG_MODE_RMIIM 0x3
+ #define GSWIP_MII_CFG_MODE_RGMII 0x4
++#define GSWIP_MII_CFG_MODE_GMII 0x9
+ #define GSWIP_MII_CFG_MODE_MASK 0xf
+ #define GSWIP_MII_CFG_RATE_M2P5 0x00
+ #define GSWIP_MII_CFG_RATE_M25 0x10
+@@ -241,6 +242,7 @@
+ struct gswip_hw_info {
+ int max_ports;
+ int cpu_port;
++ const struct dsa_switch_ops *ops;
+ };
+
+ struct xway_gphy_match_data {
+@@ -1438,12 +1440,42 @@ static int gswip_port_fdb_dump(struct ds
+ return 0;
+ }
+
+-static void gswip_phylink_validate(struct dsa_switch *ds, int port,
+- unsigned long *supported,
+- struct phylink_link_state *state)
++static void gswip_phylink_set_capab(unsigned long *supported,
++ struct phylink_link_state *state)
+ {
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+
++ /* Allow all the expected bits */
++ phylink_set(mask, Autoneg);
++ phylink_set_port_modes(mask);
++ phylink_set(mask, Pause);
++ phylink_set(mask, Asym_Pause);
++
++ /* With the exclusion of MII, Reverse MII and Reduced MII, we
++ * support Gigabit, including Half duplex
++ */
++ if (state->interface != PHY_INTERFACE_MODE_MII &&
++ state->interface != PHY_INTERFACE_MODE_REVMII &&
++ state->interface != PHY_INTERFACE_MODE_RMII) {
++ phylink_set(mask, 1000baseT_Full);
++ phylink_set(mask, 1000baseT_Half);
++ }
++
++ phylink_set(mask, 10baseT_Half);
++ phylink_set(mask, 10baseT_Full);
++ phylink_set(mask, 100baseT_Half);
++ phylink_set(mask, 100baseT_Full);
++
++ bitmap_and(supported, supported, mask,
++ __ETHTOOL_LINK_MODE_MASK_NBITS);
++ bitmap_and(state->advertising, state->advertising, mask,
++ __ETHTOOL_LINK_MODE_MASK_NBITS);
++}
++
++static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port,
++ unsigned long *supported,
++ struct phylink_link_state *state)
++{
+ switch (port) {
+ case 0:
+ case 1:
+@@ -1470,38 +1502,54 @@ static void gswip_phylink_validate(struc
+ return;
+ }
+
+- /* Allow all the expected bits */
+- phylink_set(mask, Autoneg);
+- phylink_set_port_modes(mask);
+- phylink_set(mask, Pause);
+- phylink_set(mask, Asym_Pause);
++ gswip_phylink_set_capab(supported, state);
+
+- /* With the exclusion of MII, Reverse MII and Reduced MII, we
+- * support Gigabit, including Half duplex
+- */
+- if (state->interface != PHY_INTERFACE_MODE_MII &&
+- state->interface != PHY_INTERFACE_MODE_REVMII &&
+- state->interface != PHY_INTERFACE_MODE_RMII) {
+- phylink_set(mask, 1000baseT_Full);
+- phylink_set(mask, 1000baseT_Half);
++ return;
++
++unsupported:
++ bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
++ dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
++ phy_modes(state->interface), port);
++}
++
++static void gswip_xrx300_phylink_validate(struct dsa_switch *ds, int port,
++ unsigned long *supported,
++ struct phylink_link_state *state)
++{
++ switch (port) {
++ case 0:
++ if (!phy_interface_mode_is_rgmii(state->interface) &&
++ state->interface != PHY_INTERFACE_MODE_GMII &&
++ state->interface != PHY_INTERFACE_MODE_RMII)
++ goto unsupported;
++ break;
++ case 1:
++ case 2:
++ case 3:
++ case 4:
++ if (state->interface != PHY_INTERFACE_MODE_INTERNAL)
++ goto unsupported;
++ break;
++ case 5:
++ if (!phy_interface_mode_is_rgmii(state->interface) &&
++ state->interface != PHY_INTERFACE_MODE_INTERNAL &&
++ state->interface != PHY_INTERFACE_MODE_RMII)
++ goto unsupported;
++ break;
++ default:
++ bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
++ dev_err(ds->dev, "Unsupported port: %i\n", port);
++ return;
+ }
+
+- phylink_set(mask, 10baseT_Half);
+- phylink_set(mask, 10baseT_Full);
+- phylink_set(mask, 100baseT_Half);
+- phylink_set(mask, 100baseT_Full);
++ gswip_phylink_set_capab(supported, state);
+
+- bitmap_and(supported, supported, mask,
+- __ETHTOOL_LINK_MODE_MASK_NBITS);
+- bitmap_and(state->advertising, state->advertising, mask,
+- __ETHTOOL_LINK_MODE_MASK_NBITS);
+ return;
+
+ unsupported:
+ bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
+ dev_err(ds->dev, "Unsupported interface '%s' for port %d\n",
+ phy_modes(state->interface), port);
+- return;
+ }
+
+ static void gswip_port_set_link(struct gswip_priv *priv, int port, bool link)
+@@ -1639,6 +1687,9 @@ static void gswip_phylink_mac_config(str
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ miicfg |= GSWIP_MII_CFG_MODE_RGMII;
+ break;
++ case PHY_INTERFACE_MODE_GMII:
++ miicfg |= GSWIP_MII_CFG_MODE_GMII;
++ break;
+ default:
+ dev_err(ds->dev,
+ "Unsupported interface: %d\n", state->interface);
+@@ -1765,7 +1816,7 @@ static int gswip_get_sset_count(struct d
+ return ARRAY_SIZE(gswip_rmon_cnt);
+ }
+
+-static const struct dsa_switch_ops gswip_switch_ops = {
++static const struct dsa_switch_ops gswip_xrx200_switch_ops = {
+ .get_tag_protocol = gswip_get_tag_protocol,
+ .setup = gswip_setup,
+ .port_enable = gswip_port_enable,
+@@ -1781,7 +1832,31 @@ static const struct dsa_switch_ops gswip
+ .port_fdb_add = gswip_port_fdb_add,
+ .port_fdb_del = gswip_port_fdb_del,
+ .port_fdb_dump = gswip_port_fdb_dump,
+- .phylink_validate = gswip_phylink_validate,
++ .phylink_validate = gswip_xrx200_phylink_validate,
++ .phylink_mac_config = gswip_phylink_mac_config,
++ .phylink_mac_link_down = gswip_phylink_mac_link_down,
++ .phylink_mac_link_up = gswip_phylink_mac_link_up,
++ .get_strings = gswip_get_strings,
++ .get_ethtool_stats = gswip_get_ethtool_stats,
++ .get_sset_count = gswip_get_sset_count,
++};
++
++static const struct dsa_switch_ops gswip_xrx300_switch_ops = {
++ .get_tag_protocol = gswip_get_tag_protocol,
++ .setup = gswip_setup,
++ .port_enable = gswip_port_enable,
++ .port_disable = gswip_port_disable,
++ .port_bridge_join = gswip_port_bridge_join,
++ .port_bridge_leave = gswip_port_bridge_leave,
++ .port_fast_age = gswip_port_fast_age,
++ .port_vlan_filtering = gswip_port_vlan_filtering,
++ .port_vlan_add = gswip_port_vlan_add,
++ .port_vlan_del = gswip_port_vlan_del,
++ .port_stp_state_set = gswip_port_stp_state_set,
++ .port_fdb_add = gswip_port_fdb_add,
++ .port_fdb_del = gswip_port_fdb_del,
++ .port_fdb_dump = gswip_port_fdb_dump,
++ .phylink_validate = gswip_xrx300_phylink_validate,
+ .phylink_mac_config = gswip_phylink_mac_config,
+ .phylink_mac_link_down = gswip_phylink_mac_link_down,
+ .phylink_mac_link_up = gswip_phylink_mac_link_up,
+@@ -2043,7 +2118,7 @@ static int gswip_probe(struct platform_d
+ priv->ds->dev = dev;
+ priv->ds->num_ports = priv->hw_info->max_ports;
+ priv->ds->priv = priv;
+- priv->ds->ops = &gswip_switch_ops;
++ priv->ds->ops = priv->hw_info->ops;
+ priv->dev = dev;
+ version = gswip_switch_r(priv, GSWIP_VERSION);
+
+@@ -2127,10 +2202,19 @@ static int gswip_remove(struct platform_
+ static const struct gswip_hw_info gswip_xrx200 = {
+ .max_ports = 7,
+ .cpu_port = 6,
++ .ops = &gswip_xrx200_switch_ops,
++};
++
++static const struct gswip_hw_info gswip_xrx300 = {
++ .max_ports = 7,
++ .cpu_port = 6,
++ .ops = &gswip_xrx300_switch_ops,
+ };
+
+ static const struct of_device_id gswip_of_match[] = {
+ { .compatible = "lantiq,xrx200-gswip", .data = &gswip_xrx200 },
++ { .compatible = "lantiq,xrx300-gswip", .data = &gswip_xrx300 },
++ { .compatible = "lantiq,xrx330-gswip", .data = &gswip_xrx300 },
+ {},
+ };
+ MODULE_DEVICE_TABLE(of, gswip_of_match);
+++ /dev/null
-From c3e6b2c35b34214c58c1e90d65dab5f5393608e7 Mon Sep 17 00:00:00 2001
-From: Aleksander Jan Bajkowski <olek2@wp.pl>
-Date: Mon, 3 Jan 2022 20:43:16 +0100
-Subject: [PATCH] net: lantiq_xrx200: add ingress SG DMA support
-
-This patch adds support for scatter gather DMA. DMA in PMAC splits
-the packet into several buffers when the MTU on the CPU port is
-less than the MTU of the switch. The first buffer starts at an
-offset of NET_IP_ALIGN. In subsequent buffers, dma ignores the
-offset. Thanks to this patch, the user can still connect to the
-device in such a situation. For normal configurations, the patch
-has no effect on performance.
-
-Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
-Signed-off-by: David S. Miller <davem@davemloft.net>
----
- drivers/net/ethernet/lantiq_xrx200.c | 47 +++++++++++++++++++++++-----
- 1 file changed, 40 insertions(+), 7 deletions(-)
-
---- a/drivers/net/ethernet/lantiq_xrx200.c
-+++ b/drivers/net/ethernet/lantiq_xrx200.c
-@@ -26,6 +26,9 @@
- #define XRX200_DMA_RX 0
- #define XRX200_DMA_TX 1
-
-+#define XRX200_DMA_PACKET_COMPLETE 0
-+#define XRX200_DMA_PACKET_IN_PROGRESS 1
-+
- /* cpu port mac */
- #define PMAC_RX_IPG 0x0024
- #define PMAC_RX_IPG_MASK 0xf
-@@ -61,6 +64,9 @@ struct xrx200_chan {
- struct ltq_dma_channel dma;
- struct sk_buff *skb[LTQ_DESC_NUM];
-
-+ struct sk_buff *skb_head;
-+ struct sk_buff *skb_tail;
-+
- struct xrx200_priv *priv;
- };
-
-@@ -204,7 +210,8 @@ static int xrx200_hw_receive(struct xrx2
- struct xrx200_priv *priv = ch->priv;
- struct ltq_dma_desc *desc = &ch->dma.desc_base[ch->dma.desc];
- struct sk_buff *skb = ch->skb[ch->dma.desc];
-- int len = (desc->ctl & LTQ_DMA_SIZE_MASK);
-+ u32 ctl = desc->ctl;
-+ int len = (ctl & LTQ_DMA_SIZE_MASK);
- struct net_device *net_dev = priv->net_dev;
- int ret;
-
-@@ -220,12 +227,36 @@ static int xrx200_hw_receive(struct xrx2
- }
-
- skb_put(skb, len);
-- skb->protocol = eth_type_trans(skb, net_dev);
-- netif_receive_skb(skb);
-- net_dev->stats.rx_packets++;
-- net_dev->stats.rx_bytes += len;
-
-- return 0;
-+ /* add buffers to skb via skb->frag_list */
-+ if (ctl & LTQ_DMA_SOP) {
-+ ch->skb_head = skb;
-+ ch->skb_tail = skb;
-+ } else if (ch->skb_head) {
-+ if (ch->skb_head == ch->skb_tail)
-+ skb_shinfo(ch->skb_tail)->frag_list = skb;
-+ else
-+ ch->skb_tail->next = skb;
-+ ch->skb_tail = skb;
-+ skb_reserve(ch->skb_tail, -NET_IP_ALIGN);
-+ ch->skb_head->len += skb->len;
-+ ch->skb_head->data_len += skb->len;
-+ ch->skb_head->truesize += skb->truesize;
-+ }
-+
-+ if (ctl & LTQ_DMA_EOP) {
-+ ch->skb_head->protocol = eth_type_trans(ch->skb_head, net_dev);
-+ netif_receive_skb(ch->skb_head);
-+ net_dev->stats.rx_packets++;
-+ net_dev->stats.rx_bytes += ch->skb_head->len;
-+ ch->skb_head = NULL;
-+ ch->skb_tail = NULL;
-+ ret = XRX200_DMA_PACKET_COMPLETE;
-+ } else {
-+ ret = XRX200_DMA_PACKET_IN_PROGRESS;
-+ }
-+
-+ return ret;
- }
-
- static int xrx200_poll_rx(struct napi_struct *napi, int budget)
-@@ -240,7 +271,9 @@ static int xrx200_poll_rx(struct napi_st
-
- if ((desc->ctl & (LTQ_DMA_OWN | LTQ_DMA_C)) == LTQ_DMA_C) {
- ret = xrx200_hw_receive(ch);
-- if (ret)
-+ if (ret == XRX200_DMA_PACKET_IN_PROGRESS)
-+ continue;
-+ if (ret != XRX200_DMA_PACKET_COMPLETE)
- return ret;
- rx++;
- } else {
--- /dev/null
+From c40bb4fedcd6b8b6a714da5dd466eb88ed2652d1 Mon Sep 17 00:00:00 2001
+From: Aleksander Jan Bajkowski <olek2@wp.pl>
+Date: Wed, 9 Mar 2022 00:04:57 +0100
+Subject: net: dsa: lantiq_gswip: enable jumbo frames on GSWIP
+
+This enables non-standard MTUs on a per-port basis, with the overall
+frame size set based on the CPU port.
+
+When the MTU is not changed, this should have no effect.
+
+Long packets crash the switch with MTUs of greater than 2526, so the
+maximum is limited for now. Medium packets are sometimes dropped (e.g.
+TCP over 2477, UDP over 2516-2519, ICMP over 2526), Hence an MTU value
+of 2400 seems safe.
+
+Signed-off-by: Thomas Nixon <tom@tomn.co.uk>
+Signed-off-by: Aleksander Jan Bajkowski <olek2@wp.pl>
+Link: https://lore.kernel.org/r/20220308230457.1599237-1-olek2@wp.pl
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/lantiq_gswip.c | 53 ++++++++++++++++++++++++++++++++++++++----
+ 1 file changed, 49 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/dsa/lantiq_gswip.c
++++ b/drivers/net/dsa/lantiq_gswip.c
+@@ -213,6 +213,7 @@
+ #define GSWIP_MAC_CTRL_0_GMII_MII 0x0001
+ #define GSWIP_MAC_CTRL_0_GMII_RGMII 0x0002
+ #define GSWIP_MAC_CTRL_2p(p) (0x905 + ((p) * 0xC))
++#define GSWIP_MAC_CTRL_2_LCHKL BIT(2) /* Frame Length Check Long Enable */
+ #define GSWIP_MAC_CTRL_2_MLEN BIT(3) /* Maximum Untagged Frame Lnegth */
+
+ /* Ethernet Switch Fetch DMA Port Control Register */
+@@ -239,6 +240,15 @@
+
+ #define XRX200_GPHY_FW_ALIGN (16 * 1024)
+
++/* Maximum packet size supported by the switch. In theory this should be 10240,
++ * but long packets currently cause lock-ups with an MTU of over 2526. Medium
++ * packets are sometimes dropped (e.g. TCP over 2477, UDP over 2516-2519, ICMP
++ * over 2526), hence an MTU value of 2400 seems safe. This issue only affects
++ * packet reception. This is probably caused by the PPA engine, which is on the
++ * RX part of the device. Packet transmission works properly up to 10240.
++ */
++#define GSWIP_MAX_PACKET_LENGTH 2400
++
+ struct gswip_hw_info {
+ int max_ports;
+ int cpu_port;
+@@ -858,10 +868,6 @@ static int gswip_setup(struct dsa_switch
+ gswip_switch_mask(priv, 0, GSWIP_PCE_PCTRL_0_INGRESS,
+ GSWIP_PCE_PCTRL_0p(cpu_port));
+
+- gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
+- GSWIP_MAC_CTRL_2p(cpu_port));
+- gswip_switch_w(priv, VLAN_ETH_FRAME_LEN + 8 + ETH_FCS_LEN,
+- GSWIP_MAC_FLEN);
+ gswip_switch_mask(priv, 0, GSWIP_BM_QUEUE_GCTRL_GL_MOD,
+ GSWIP_BM_QUEUE_GCTRL);
+
+@@ -878,6 +884,8 @@ static int gswip_setup(struct dsa_switch
+ return err;
+ }
+
++ ds->mtu_enforcement_ingress = true;
++
+ gswip_port_enable(ds, cpu_port, NULL);
+ return 0;
+ }
+@@ -1472,6 +1480,39 @@ static void gswip_phylink_set_capab(unsi
+ __ETHTOOL_LINK_MODE_MASK_NBITS);
+ }
+
++static int gswip_port_max_mtu(struct dsa_switch *ds, int port)
++{
++ /* Includes 8 bytes for special header. */
++ return GSWIP_MAX_PACKET_LENGTH - VLAN_ETH_HLEN - ETH_FCS_LEN;
++}
++
++static int gswip_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
++{
++ struct gswip_priv *priv = ds->priv;
++ int cpu_port = priv->hw_info->cpu_port;
++
++ /* CPU port always has maximum mtu of user ports, so use it to set
++ * switch frame size, including 8 byte special header.
++ */
++ if (port == cpu_port) {
++ new_mtu += 8;
++ gswip_switch_w(priv, VLAN_ETH_HLEN + new_mtu + ETH_FCS_LEN,
++ GSWIP_MAC_FLEN);
++ }
++
++ /* Enable MLEN for ports with non-standard MTUs, including the special
++ * header on the CPU port added above.
++ */
++ if (new_mtu != ETH_DATA_LEN)
++ gswip_switch_mask(priv, 0, GSWIP_MAC_CTRL_2_MLEN,
++ GSWIP_MAC_CTRL_2p(port));
++ else
++ gswip_switch_mask(priv, GSWIP_MAC_CTRL_2_MLEN, 0,
++ GSWIP_MAC_CTRL_2p(port));
++
++ return 0;
++}
++
+ static void gswip_xrx200_phylink_validate(struct dsa_switch *ds, int port,
+ unsigned long *supported,
+ struct phylink_link_state *state)
+@@ -1832,6 +1873,8 @@ static const struct dsa_switch_ops gswip
+ .port_fdb_add = gswip_port_fdb_add,
+ .port_fdb_del = gswip_port_fdb_del,
+ .port_fdb_dump = gswip_port_fdb_dump,
++ .port_change_mtu = gswip_port_change_mtu,
++ .port_max_mtu = gswip_port_max_mtu,
+ .phylink_validate = gswip_xrx200_phylink_validate,
+ .phylink_mac_config = gswip_phylink_mac_config,
+ .phylink_mac_link_down = gswip_phylink_mac_link_down,
+@@ -1856,6 +1899,8 @@ static const struct dsa_switch_ops gswip
+ .port_fdb_add = gswip_port_fdb_add,
+ .port_fdb_del = gswip_port_fdb_del,
+ .port_fdb_dump = gswip_port_fdb_dump,
++ .port_change_mtu = gswip_port_change_mtu,
++ .port_max_mtu = gswip_port_max_mtu,
+ .phylink_validate = gswip_xrx300_phylink_validate,
+ .phylink_mac_config = gswip_phylink_mac_config,
+ .phylink_mac_link_down = gswip_phylink_mac_link_down,