diff --git a/target/linux/microchipsw/patches-6.12/126-net-lan969x-correct-RGMII-port-mapping-index.patch b/target/linux/microchipsw/patches-6.12/126-net-lan969x-correct-RGMII-port-mapping-index.patch new file mode 100644 index 0000000000..b8aef7e51a --- /dev/null +++ b/target/linux/microchipsw/patches-6.12/126-net-lan969x-correct-RGMII-port-mapping-index.patch @@ -0,0 +1,37 @@ +From 44ed546c4231fbf9d0c92738c2c48c49f8249f48 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 24 Mar 2026 12:02:05 +0100 +Subject: [PATCH 126/130] net: lan969x: correct RGMII port mapping index + +Currently, the lan969x_port_dev_mapping does not check for RGMII ports +and just returns the physical port index. + +However, this does not work for RGMII ports as they have dedicated DEVRGMII +register space with an dedicated instance per RGMII port. + +So, check if requested port index is an RGMII port and return the correct +DEVRGMII index. + +Signed-off-by: Robert Marko +--- + drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c ++++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c +@@ -142,6 +142,15 @@ static u32 lan969x_get_dev_mode_bit(stru + + static u32 lan969x_port_dev_mapping(struct sparx5 *sparx5, int port) + { ++ if (lan969x_port_is_rgmii(port)) { ++ switch (port) { ++ case 28: ++ return 0; ++ case 29: ++ return 1; ++ } ++ } ++ + if (lan969x_port_is_5g(port)) { + switch (port) { + case 9: diff --git a/target/linux/microchipsw/patches-6.12/127-net-sparx5-add-MTU-change-framework.patch b/target/linux/microchipsw/patches-6.12/127-net-sparx5-add-MTU-change-framework.patch new file mode 100644 index 0000000000..874ac560b3 --- /dev/null +++ b/target/linux/microchipsw/patches-6.12/127-net-sparx5-add-MTU-change-framework.patch @@ -0,0 +1,264 @@ +From 372e0295a1dbf0ea4333183ac82b8620bef9c0dc Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 24 Mar 2026 12:19:03 +0100 +Subject: [PATCH 127/130] net: sparx5: add MTU change framework + +Port the MTU change framework from Microchip BSP kernel. +This only wires the generic SparX-5 and LAN969x code. + +SparX-5 and LAN969x specific code to actually change the MTU will follow. + +Signed-off-by: Robert Marko +--- + .../net/ethernet/microchip/sparx5/Makefile | 2 +- + .../ethernet/microchip/sparx5/sparx5_fdma.c | 20 +++ + .../ethernet/microchip/sparx5/sparx5_main.h | 8 ++ + .../microchip/sparx5/sparx5_main_regs.h | 11 ++ + .../ethernet/microchip/sparx5/sparx5_mtu.c | 130 ++++++++++++++++++ + 5 files changed, 170 insertions(+), 1 deletion(-) + create mode 100644 drivers/net/ethernet/microchip/sparx5/sparx5_mtu.c + +--- a/drivers/net/ethernet/microchip/sparx5/Makefile ++++ b/drivers/net/ethernet/microchip/sparx5/Makefile +@@ -11,7 +11,7 @@ sparx5-switch-y := sparx5_main.o sparx5 + sparx5_ptp.o sparx5_pgid.o sparx5_tc.o sparx5_qos.o \ + sparx5_vcap_impl.o sparx5_vcap_ag_api.o sparx5_tc_flower.o \ + sparx5_tc_matchall.o sparx5_pool.o sparx5_sdlb.o sparx5_police.o \ +- sparx5_psfp.o sparx5_mirror.o sparx5_regs.o ++ sparx5_psfp.o sparx5_mirror.o sparx5_regs.o sparx5_mtu.o + + sparx5-switch-$(CONFIG_SPARX5_DCB) += sparx5_dcb.o + sparx5-switch-$(CONFIG_DEBUG_FS) += sparx5_vcap_debugfs.o +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c +@@ -462,6 +462,15 @@ int sparx5_fdma_start(struct sparx5 *spa + sparx5_fdma_rx_activate(sparx5, rx); + sparx5_fdma_tx_activate(sparx5, tx); + ++ for (int i = 0; i < sparx5->data->consts->n_ports; i++) { ++ struct sparx5_port *port = sparx5->ports[i]; ++ ++ if (!port) ++ continue; ++ if (netif_queue_stopped(port->ndev)) ++ netif_wake_queue(port->ndev); ++ } ++ + return 0; + } + +@@ -471,6 +480,7 @@ int sparx5_fdma_stop(struct sparx5 *spar + struct sparx5_tx *tx = &sparx5->tx; + u32 val; + ++ napi_synchronize(&sparx5->rx.napi); + napi_disable(&rx->napi); + + /* Stop the fdma and channel interrupts */ +@@ -482,5 +492,15 @@ int sparx5_fdma_stop(struct sparx5 *spar + FDMA_PORT_CTRL_XTR_BUF_IS_EMPTY_GET(val) == 0, + 500, 10000, 0, sparx5); + ++ for (int i = 0; i < sparx5->data->consts->n_ports; i++) { ++ struct sparx5_port *port = sparx5->ports[i]; ++ ++ if (!port) ++ continue; ++ netif_stop_queue(port->ndev); ++ } ++ ++ netif_napi_del(&sparx5->rx.napi); ++ + return 0; + } +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +@@ -102,6 +102,7 @@ enum sparx5_feature { + #define PGID_TABLE_SIZE 3290 + + #define IFH_LEN 9 /* 36 bytes */ ++#define IFH_LEN_BYTES (IFH_LEN * sizeof(u32)) + #define NULL_VID 0 + #define SPX5_MACT_PULL_DELAY (2 * HZ) + #define SPX5_STATS_CHECK_DELAY (1 * HZ) +@@ -188,6 +189,7 @@ struct sparx5_tx { + struct sparx5_tx_buf *dbs; + u64 packets; + u64 dropped; ++ u16 max_mtu; + }; + + struct sparx5_port_config { +@@ -348,6 +350,8 @@ struct sparx5_ops { + int (*fdma_poll)(struct napi_struct *napi, int weight); + int (*fdma_xmit)(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb, + struct net_device *dev); ++ int (*fdma_resize)(struct sparx5 *sparx5); ++ u32 (*get_mtu)(struct sparx5 *sparx5); + }; + + struct sparx5_main_io_resource { +@@ -712,6 +716,10 @@ void sparx5_mirror_del(struct sparx5_mal + void sparx5_mirror_stats(struct sparx5_mall_entry *entry, + struct flow_stats *fstats); + ++/* sparx5_mtu.c */ ++int sparx5_mtu_change(struct net_device *dev, int new_mtu); ++u32 sparx5_mtu_max(struct sparx5 *sparx5); ++ + /* Clock period in picoseconds */ + static inline u32 sparx5_clk_period(enum sparx5_core_clockfreq cclock) + { +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h +@@ -8204,6 +8204,17 @@ extern const struct sparx5_regs *regs; + FIELD_GET(DEVRGMII_MAC_ENA_CFG_TX_ENA, x) + + /* LAN969X ONLY */ ++/* DEV1G:MAC_CFG_STATUS:MAC_MAXLEN_CFG */ ++#define DEVRGMII_MAC_MAXLEN_CFG(t) \ ++ __REG(TARGET_DEVRGMII, t, 2, 36, 0, 1, 36, 8, 0, 1, 4) ++ ++#define DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN GENMASK(15, 0) ++#define DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN_SET(x)\ ++ FIELD_PREP(DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN, x) ++#define DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN_GET(x)\ ++ FIELD_GET(DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN, x) ++ ++/* LAN969X ONLY */ + /* DEV1G:MAC_CFG_STATUS:MAC_TAGS_CFG */ + #define DEVRGMII_MAC_TAGS_CFG(t) \ + __REG(TARGET_DEVRGMII, t, 2, 36, 0, 1, 36, 12, 0, 1, 4) +--- /dev/null ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_mtu.c +@@ -0,0 +1,130 @@ ++// SPDX-License-Identifier: GPL-2.0+ ++/* Microchip Sparx5 Switch driver ++ * ++ * Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries. ++ */ ++ ++#include "sparx5_main.h" ++ ++#define SPX5_HW_MTU(mtu) ((mtu) + ETH_ALEN + IFH_LEN * 4 + ETH_FCS_LEN) ++ ++/* Get the MTU for this port */ ++static u32 sparx5_mtu_get(struct sparx5_port *port) ++{ ++ struct sparx5 *sparx5 = port->sparx5; ++ const struct sparx5_ops *ops = sparx5->data->ops; ++ u32 val; ++ ++ /* We always set 2G5 or RGMII MTU, so there is no point in trying to ++ * read high-speed MAC MTU here ++ */ ++ if (ops->is_port_rgmii(port->portno)) { ++ u32 idx = ops->get_port_dev_index(sparx5, port->portno); ++ val = spx5_rd(sparx5, DEVRGMII_MAC_MAXLEN_CFG(idx)); ++ return DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN_GET(val); ++ } else { ++ val = spx5_rd(sparx5, DEV2G5_MAC_MAXLEN_CFG(port->portno)); ++ return DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_GET(val); ++ } ++} ++ ++/* Set the MTU for this port. */ ++static void sparx5_mtu_set(struct sparx5_port *port, u32 new_mtu) ++{ ++ struct sparx5 *sparx5 = port->sparx5; ++ const struct sparx5_ops *ops; ++ u32 idx, hw_mtu; ++ ++ ops = sparx5->data->ops; ++ idx = ops->get_port_dev_index(sparx5, port->portno); ++ hw_mtu = SPX5_HW_MTU(new_mtu); ++ ++ pr_debug("Setting MTU to: %u for portno (idx: %u): %u\n", new_mtu, ++ port->portno, idx); ++ ++ /* All port modules have a 2g5 shadow device (and DEV2G5 is indexed ++ * by port number). Except the RGMII ports ++ */ ++ if (!ops->is_port_rgmii(port->portno)) ++ spx5_rmw(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(hw_mtu), ++ DEV2G5_MAC_MAXLEN_CFG_MAX_LEN, sparx5, ++ DEV2G5_MAC_MAXLEN_CFG(port->portno)); ++ ++ if (ops->is_port_rgmii(port->portno)) ++ spx5_rmw(DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN_SET(hw_mtu), ++ DEVRGMII_MAC_MAXLEN_CFG_MAX_LEN, sparx5, ++ DEVRGMII_MAC_MAXLEN_CFG(idx)); ++ else if (ops->is_port_2g5(port->portno)) ++ return; /* Already configured. */ ++ else if (ops->is_port_5g(port->portno)) ++ spx5_rmw(DEV5G_MAC_MAXLEN_CFG_MAX_LEN_SET(hw_mtu), ++ DEV5G_MAC_MAXLEN_CFG_MAX_LEN, sparx5, ++ DEV5G_MAC_MAXLEN_CFG(idx)); ++ else if (ops->is_port_10g(port->portno)) ++ spx5_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(hw_mtu), ++ DEV10G_MAC_MAXLEN_CFG_MAX_LEN, sparx5, ++ DEV10G_MAC_MAXLEN_CFG(idx)); ++ else ++ spx5_rmw(DEV25G_MAC_MAXLEN_CFG_MAX_LEN_SET(hw_mtu), ++ DEV25G_MAC_MAXLEN_CFG_MAX_LEN, sparx5, ++ DEV25G_MAC_MAXLEN_CFG(idx)); ++} ++ ++u32 sparx5_mtu_max(struct sparx5 *sparx5) ++{ ++ u32 mtu_max = 0; ++ ++ for (int i = 0; i < sparx5->data->consts->n_ports; i++) { ++ struct sparx5_port *port = sparx5->ports[i]; ++ u32 mtu; ++ ++ if (!port) ++ continue; ++ ++ mtu = sparx5_mtu_get(port) + IFH_LEN_BYTES + ++ SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) + ++ VLAN_HLEN * 2 + XDP_PACKET_HEADROOM; ++ ++ if (mtu > mtu_max) ++ mtu_max = mtu; ++ } ++ ++ return mtu_max; ++} ++ ++static int sparx5_mtu_fdma_set(struct sparx5 *sparx5) ++{ ++ const struct sparx5_ops *ops = sparx5->data->ops; ++ u32 mtu_max = sparx5_mtu_max(sparx5); ++ ++ /* We might not be using FDMA */ ++ if (sparx5->fdma_irq <= 0) ++ return 0; ++ ++ /* No need to restart FDMA if the MTU reflects the buffer size */ ++ if (mtu_max == sparx5->tx.max_mtu) ++ return 0; ++ ++ return ops->fdma_resize(sparx5); ++} ++ ++int sparx5_mtu_change(struct net_device *dev, int new_mtu) ++{ ++ struct sparx5_port *port = netdev_priv(dev); ++ struct sparx5 *sparx5 = port->sparx5; ++ int err, orig_mtu = dev->mtu; ++ ++ /* Write MTU to hardware */ ++ sparx5_mtu_set(port, new_mtu); ++ ++ err = sparx5_mtu_fdma_set(sparx5); ++ if (err) { ++ sparx5_mtu_set(port, orig_mtu); ++ return err; ++ } ++ ++ /* Let the stack know */ ++ WRITE_ONCE(dev->mtu, new_mtu); ++ ++ return 0; ++} diff --git a/target/linux/microchipsw/patches-6.12/128-net-sparx5-add-MTU-change.patch b/target/linux/microchipsw/patches-6.12/128-net-sparx5-add-MTU-change.patch new file mode 100644 index 0000000000..d628ac8914 --- /dev/null +++ b/target/linux/microchipsw/patches-6.12/128-net-sparx5-add-MTU-change.patch @@ -0,0 +1,107 @@ +From 466d22c9d3bdb2feda284c582d4f183879fc57ad Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 24 Mar 2026 12:26:51 +0100 +Subject: [PATCH 128/130] net: sparx5: add MTU change + +Add the required SparX-5 specific code to change the MTU. + +Signed-off-by: Robert Marko +--- + .../ethernet/microchip/sparx5/sparx5_fdma.c | 52 +++++++++++++++++++ + .../ethernet/microchip/sparx5/sparx5_main.c | 2 + + .../ethernet/microchip/sparx5/sparx5_main.h | 1 + + 3 files changed, 55 insertions(+) + +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_fdma.c +@@ -278,6 +278,8 @@ static void sparx5_fdma_rx_init(struct s + struct fdma *fdma = &rx->fdma; + int idx; + ++ sparx5->rx.page_order = ++ round_up(sparx5->tx.max_mtu, PAGE_SIZE) / PAGE_SIZE - 1; + fdma->channel_id = channel; + fdma->n_dcbs = FDMA_DCB_MAX; + fdma->n_dbs = FDMA_RX_DCB_MAX_DBS; +@@ -403,6 +405,8 @@ int sparx5_fdma_init(struct sparx5 *spar + { + int err; + ++ sparx5->tx.max_mtu = sparx5->data->ops->get_mtu(sparx5); ++ + /* Reset FDMA state */ + spx5_wr(FDMA_CTRL_NRESET_SET(0), sparx5, FDMA_CTRL); + spx5_wr(FDMA_CTRL_NRESET_SET(1), sparx5, FDMA_CTRL); +@@ -504,3 +508,51 @@ int sparx5_fdma_stop(struct sparx5 *spar + + return 0; + } ++ ++int sparx5_fdma_resize(struct sparx5 *sparx5) ++{ ++ u32 old_mtu = sparx5->tx.max_mtu; ++ struct fdma tx_fdma_old = {0}; ++ struct fdma rx_fdma_old = {0}; ++ int err; ++ ++ memcpy(&tx_fdma_old, &sparx5->tx.fdma, sizeof(struct fdma)); ++ memcpy(&rx_fdma_old, &sparx5->rx.fdma, sizeof(struct fdma)); ++ ++ sparx5_fdma_stop(sparx5); ++ ++ err = sparx5_fdma_init(sparx5); ++ if (err) ++ goto restore; ++ ++ fdma_free_phys(&rx_fdma_old); ++ fdma_free_phys(&tx_fdma_old); ++ ++ goto start; ++ ++restore: ++ ++ /* At this point, the FDMA engine is stopped and the stack is not ++ * calling us for xmit. Restore the old MTU and rx,tx buffers and ++ * restart the engine. ++ */ ++ ++ sparx5->tx.max_mtu = old_mtu; ++ memcpy(&sparx5->tx.fdma, &tx_fdma_old, sizeof(struct fdma)); ++ memcpy(&sparx5->rx.fdma, &rx_fdma_old, sizeof(struct fdma)); ++ ++ /* Old buffers have to be re-initialized. */ ++ ++ fdma_dcbs_init(&sparx5->rx.fdma, ++ FDMA_DCB_INFO_DATAL(sparx5->rx.fdma.db_size), ++ FDMA_DCB_STATUS_INTR); ++ ++ fdma_dcbs_init(&sparx5->tx.fdma, ++ FDMA_DCB_INFO_DATAL(sparx5->tx.fdma.db_size), ++ FDMA_DCB_STATUS_DONE); ++ ++start: ++ sparx5_fdma_start(sparx5); ++ ++ return err; ++} +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c +@@ -1108,6 +1108,8 @@ static const struct sparx5_ops sparx5_op + .fdma_deinit = &sparx5_fdma_deinit, + .fdma_poll = &sparx5_fdma_napi_callback, + .fdma_xmit = &sparx5_fdma_xmit, ++ .fdma_resize = &sparx5_fdma_resize, ++ .get_mtu = &sparx5_mtu_max, + }; + + static const struct sparx5_match_data sparx5_desc = { +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +@@ -472,6 +472,7 @@ int sparx5_fdma_xmit(struct sparx5 *spar + irqreturn_t sparx5_fdma_handler(int irq, void *args); + void sparx5_fdma_reload(struct sparx5 *sparx5, struct fdma *fdma); + void sparx5_fdma_injection_mode(struct sparx5 *sparx5); ++int sparx5_fdma_resize(struct sparx5 *sparx5); + + /* sparx5_mactable.c */ + void sparx5_mact_pull_work(struct work_struct *work); diff --git a/target/linux/microchipsw/patches-6.12/129-net-lan969x-add-MTU-change.patch b/target/linux/microchipsw/patches-6.12/129-net-lan969x-add-MTU-change.patch new file mode 100644 index 0000000000..ef89cacd04 --- /dev/null +++ b/target/linux/microchipsw/patches-6.12/129-net-lan969x-add-MTU-change.patch @@ -0,0 +1,126 @@ +From b73c8d9fe87d3e35dc09faca85d5a5f9ee8e3f6c Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 24 Mar 2026 12:30:45 +0100 +Subject: [PATCH 129/130] net: lan969x: add MTU change + +Add the LAN969x specific code for MTU change. + +Signed-off-by: Robert Marko +--- + .../microchip/sparx5/lan969x/lan969x.c | 2 + + .../microchip/sparx5/lan969x/lan969x.h | 1 + + .../microchip/sparx5/lan969x/lan969x_fdma.c | 60 ++++++++++++++++++- + 3 files changed, 61 insertions(+), 2 deletions(-) + +--- a/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c ++++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c +@@ -354,6 +354,8 @@ static const struct sparx5_ops lan969x_o + .fdma_deinit = &lan969x_fdma_deinit, + .fdma_poll = &lan969x_fdma_napi_poll, + .fdma_xmit = &lan969x_fdma_xmit, ++ .fdma_resize = lan969x_fdma_resize, ++ .get_mtu = &sparx5_mtu_max, + }; + + const struct sparx5_match_data lan969x_desc = { +--- a/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.h ++++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.h +@@ -78,5 +78,6 @@ int lan969x_fdma_deinit(struct sparx5 *s + int lan969x_fdma_napi_poll(struct napi_struct *napi, int weight); + int lan969x_fdma_xmit(struct sparx5 *sparx5, u32 *ifh, struct sk_buff *skb, + struct net_device *dev); ++int lan969x_fdma_resize(struct sparx5 *sparx5); + + #endif +--- a/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_fdma.c ++++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_fdma.c +@@ -154,7 +154,7 @@ static int lan969x_fdma_rx_alloc(struct + int err; + + struct page_pool_params pp_params = { +- .order = 0, ++ .order = rx->page_order, + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, + .pool_size = fdma->n_dcbs * fdma->n_dbs, + .nid = NUMA_NO_NODE, +@@ -209,12 +209,14 @@ static void lan969x_fdma_rx_init(struct + { + struct fdma *fdma = &sparx5->rx.fdma; + ++ sparx5->rx.page_order = ++ round_up(sparx5->tx.max_mtu, PAGE_SIZE) / PAGE_SIZE - 1; + fdma->channel_id = FDMA_XTR_CHANNEL; + fdma->n_dcbs = FDMA_DCB_MAX; + fdma->n_dbs = 1; + fdma->priv = sparx5; + fdma->size = fdma_get_size(fdma); +- fdma->db_size = PAGE_SIZE; ++ fdma->db_size = PAGE_SIZE << sparx5->rx.page_order; + fdma->ops.dataptr_cb = &lan969x_fdma_rx_dataptr_cb; + fdma->ops.nextptr_cb = &fdma_nextptr_cb; + +@@ -359,6 +361,8 @@ int lan969x_fdma_init(struct sparx5 *spa + struct sparx5_rx *rx = &sparx5->rx; + int err; + ++ sparx5->tx.max_mtu = sparx5->data->ops->get_mtu(sparx5); ++ + lan969x_fdma_rx_init(sparx5); + lan969x_fdma_tx_init(sparx5); + sparx5_fdma_injection_mode(sparx5); +@@ -404,3 +408,55 @@ int lan969x_fdma_deinit(struct sparx5 *s + + return 0; + } ++ ++int lan969x_fdma_resize(struct sparx5 *sparx5) ++{ ++ struct page_pool *page_pool_old = sparx5->rx.page_pool; ++ u32 old_mtu = sparx5->tx.max_mtu; ++ struct fdma tx_fdma_old = {0}; ++ struct fdma rx_fdma_old = {0}; ++ int err; ++ ++ memcpy(&tx_fdma_old, &sparx5->tx.fdma, sizeof(struct fdma)); ++ memcpy(&rx_fdma_old, &sparx5->rx.fdma, sizeof(struct fdma)); ++ ++ sparx5_fdma_stop(sparx5); ++ lan969x_fdma_free_pages(&sparx5->rx); ++ ++ err = lan969x_fdma_init(sparx5); ++ if (err) ++ goto restore; ++ ++ fdma_free_coherent(sparx5->dev, &rx_fdma_old); ++ fdma_free_coherent(sparx5->dev, &tx_fdma_old); ++ page_pool_destroy(page_pool_old); ++ ++ goto start; ++ ++restore: ++ ++ /* At this point, the FDMA engine is stopped and the stack is not ++ * calling us for xmit. Restore the old MTU and rx,tx buffers and ++ * restart the engine. ++ */ ++ ++ sparx5->tx.max_mtu = old_mtu; ++ sparx5->rx.page_pool = page_pool_old; ++ memcpy(&sparx5->tx.fdma, &tx_fdma_old, sizeof(struct fdma)); ++ memcpy(&sparx5->rx.fdma, &rx_fdma_old, sizeof(struct fdma)); ++ ++ /* Old buffers have to be re-initialized. */ ++ ++ fdma_dcbs_init(&sparx5->rx.fdma, ++ FDMA_DCB_INFO_DATAL(sparx5->rx.fdma.db_size), ++ FDMA_DCB_STATUS_INTR); ++ ++ fdma_dcbs_init(&sparx5->tx.fdma, ++ FDMA_DCB_INFO_DATAL(sparx5->tx.fdma.db_size), ++ FDMA_DCB_STATUS_DONE); ++ ++start: ++ sparx5_fdma_start(sparx5); ++ ++ return err; ++} diff --git a/target/linux/microchipsw/patches-6.12/130-net-sparx5-wire-in-MTU-change.patch b/target/linux/microchipsw/patches-6.12/130-net-sparx5-wire-in-MTU-change.patch new file mode 100644 index 0000000000..678b601342 --- /dev/null +++ b/target/linux/microchipsw/patches-6.12/130-net-sparx5-wire-in-MTU-change.patch @@ -0,0 +1,33 @@ +From aa92b8a004be460d68aa671c3f8e98373496b199 Mon Sep 17 00:00:00 2001 +From: Robert Marko +Date: Tue, 24 Mar 2026 12:32:39 +0100 +Subject: [PATCH 130/130] net: sparx5: wire in MTU change + +Now that both generic and chip specific MTU code is in place, add the +required netdev OP to trigger the MTU change. + +Signed-off-by: Robert Marko +--- + drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c ++++ b/drivers/net/ethernet/microchip/sparx5/sparx5_netdev.c +@@ -259,6 +259,7 @@ static const struct net_device_ops sparx + .ndo_setup_tc = sparx5_port_setup_tc, + .ndo_hwtstamp_get = sparx5_port_hwtstamp_get, + .ndo_hwtstamp_set = sparx5_port_hwtstamp_set, ++ .ndo_change_mtu = sparx5_mtu_change, + }; + + bool sparx5_netdevice_check(const struct net_device *dev) +@@ -279,6 +280,9 @@ struct net_device *sparx5_create_netdev( + ndev->hw_features |= NETIF_F_HW_TC; + ndev->features |= NETIF_F_HW_TC; + ++ /* The MAC supports frame lengths of up to 14,000 bytes */ ++ ndev->max_mtu = 14000; ++ + SET_NETDEV_DEV(ndev, sparx5->dev); + spx5_port = netdev_priv(ndev); + spx5_port->ndev = ndev;