mirror of
https://git.openwrt.org/openwrt/openwrt.git
synced 2026-05-05 09:56:12 +02:00
microchipsw: add MTU change support
Add the MTU change support ported from Microchip BSP kernel. It will be sent upstream as well. Signed-off-by: Robert Marko <robert.marko@sartura.hr>
This commit is contained in:
parent
c5455f60ab
commit
0a82d6054c
@ -0,0 +1,37 @@
|
||||
From 44ed546c4231fbf9d0c92738c2c48c49f8249f48 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
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 <robert.marko@sartura.hr>
|
||||
---
|
||||
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:
|
||||
@ -0,0 +1,264 @@
|
||||
From 372e0295a1dbf0ea4333183ac82b8620bef9c0dc Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
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 <robert.marko@sartura.hr>
|
||||
---
|
||||
.../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;
|
||||
+}
|
||||
@ -0,0 +1,107 @@
|
||||
From 466d22c9d3bdb2feda284c582d4f183879fc57ad Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
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 <robert.marko@sartura.hr>
|
||||
---
|
||||
.../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);
|
||||
@ -0,0 +1,126 @@
|
||||
From b73c8d9fe87d3e35dc09faca85d5a5f9ee8e3f6c Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
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 <robert.marko@sartura.hr>
|
||||
---
|
||||
.../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;
|
||||
+}
|
||||
@ -0,0 +1,33 @@
|
||||
From aa92b8a004be460d68aa671c3f8e98373496b199 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Marko <robert.marko@sartura.hr>
|
||||
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 <robert.marko@sartura.hr>
|
||||
---
|
||||
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;
|
||||
Loading…
x
Reference in New Issue
Block a user