diff --git a/include/bpf.mk b/include/bpf.mk index 8a0121aabe..b9c8034c68 100644 --- a/include/bpf.mk +++ b/include/bpf.mk @@ -1,30 +1,40 @@ BPF_DEPENDS := @HAS_BPF_TOOLCHAIN +@NEED_BPF_TOOLCHAIN -LLVM_VER:= CLANG_MIN_VER:=12 ifneq ($(CONFIG_USE_LLVM_HOST),) + find-llvm-tool=$(firstword $(shell PATH='$(BPF_PATH)' command -v $(1) || echo '$(firstword $(1))-not-found')) + BPF_TOOLCHAIN_HOST_PATH:=$(call qstrip,$(CONFIG_BPF_TOOLCHAIN_HOST_PATH)) ifneq ($(BPF_TOOLCHAIN_HOST_PATH),) BPF_PATH:=$(BPF_TOOLCHAIN_HOST_PATH)/bin:$(PATH) else BPF_PATH:=$(PATH) endif - CLANG:=$(firstword $(shell PATH='$(BPF_PATH)' command -v clang clang-13 clang-12 clang-11)) + CLANG:=$(call find-llvm-tool,clang clang-13 clang-12) LLVM_VER:=$(subst clang,,$(notdir $(CLANG))) -endif -ifneq ($(CONFIG_USE_LLVM_PREBUILT),) - CLANG:=$(TOPDIR)/llvm-bpf/bin/clang -endif -ifneq ($(CONFIG_USE_LLVM_BUILD),) - CLANG:=$(STAGING_DIR_HOST)/llvm-bpf/bin/clang -endif -LLVM_PATH:=$(dir $(CLANG)) -LLVM_LLC:=$(LLVM_PATH)/llc$(LLVM_VER) -LLVM_DIS:=$(LLVM_PATH)/llvm-dis$(LLVM_VER) -LLVM_OPT:=$(LLVM_PATH)/opt$(LLVM_VER) -LLVM_STRIP:=$(LLVM_PATH)/llvm-strip$(LLVM_VER) + BPF_PATH:=$(dir $(CLANG)):$(BPF_PATH) + LLVM_LLC:=$(call find-llvm-tool,llc$(LLVM_VER)) + LLVM_DIS:=$(call find-llvm-tool,llvm-dis$(LLVM_VER)) + LLVM_OPT:=$(call find-llvm-tool,opt$(LLVM_VER)) + LLVM_STRIP:=$(call find-llvm-tool,llvm-strip$(LLVM_VER)) +else + LLVM_PATH:=/invalid + + ifneq ($(CONFIG_USE_LLVM_PREBUILT),) + LLVM_PATH:=$(TOPDIR)/llvm-bpf/bin + endif + ifneq ($(CONFIG_USE_LLVM_BUILD),) + LLVM_PATH:=$(STAGING_DIR_HOST)/llvm-bpf/bin + endif + + CLANG:=$(LLVM_PATH)/clang + LLVM_LLC:=$(LLVM_PATH)/llc + LLVM_DIS:=$(LLVM_PATH)/llvm-dis + LLVM_OPT:=$(LLVM_PATH)/opt + LLVM_STRIP:=$(LLVM_PATH)/llvm-strip +endif BPF_KARCH:=mips BPF_ARCH:=mips$(if $(CONFIG_ARCH_64BIT),64)$(if $(CONFIG_BIG_ENDIAN),,el) diff --git a/target/linux/generic/backport-6.6/793-01-v6.11-net-dsa-qca8k-do-not-write-port-mask-twice-in-bridge.patch b/target/linux/generic/backport-6.6/793-01-v6.11-net-dsa-qca8k-do-not-write-port-mask-twice-in-bridge.patch new file mode 100644 index 0000000000..22b544c433 --- /dev/null +++ b/target/linux/generic/backport-6.6/793-01-v6.11-net-dsa-qca8k-do-not-write-port-mask-twice-in-bridge.patch @@ -0,0 +1,58 @@ +From e85d3e6fea05c8ae21a40809a3c6b7adc97411c7 Mon Sep 17 00:00:00 2001 +Message-ID: +From: Matthias Schiffer +Date: Thu, 20 Jun 2024 19:25:48 +0200 +Subject: [PATCH] net: dsa: qca8k: do not write port mask twice in bridge + join/leave + +qca8k_port_bridge_join() set QCA8K_PORT_LOOKUP_CTRL() for i == port twice, +once in the loop handling all other port's masks, and finally at the end +with the accumulated port_mask. + +The first time it would incorrectly set the port's own bit in the mask, +only to correct the mistake a moment later. qca8k_port_bridge_leave() had +the same issue, but here the regmap_clear_bits() was a no-op rather than +setting an unintended value. + +Remove the duplicate assignment by skipping the whole loop iteration for +i == port. The unintended bit setting doesn't seem to have any negative +effects (even when not reverted right away), so the change is submitted +as a simple cleanup rather than a fix. + +Signed-off-by: Matthias Schiffer +Reviewed-by: Wojciech Drewek +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-common.c | 7 +++++-- + 1 file changed, 5 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -654,6 +654,8 @@ int qca8k_port_bridge_join(struct dsa_sw + port_mask = BIT(cpu_port); + + for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (i == port) ++ continue; + if (dsa_is_cpu_port(ds, i)) + continue; + if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) +@@ -666,8 +668,7 @@ int qca8k_port_bridge_join(struct dsa_sw + BIT(port)); + if (ret) + return ret; +- if (i != port) +- port_mask |= BIT(i); ++ port_mask |= BIT(i); + } + + /* Add all other ports to this ports portvlan mask */ +@@ -686,6 +687,8 @@ void qca8k_port_bridge_leave(struct dsa_ + cpu_port = dsa_to_port(ds, port)->cpu_dp->index; + + for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (i == port) ++ continue; + if (dsa_is_cpu_port(ds, i)) + continue; + if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) diff --git a/target/linux/generic/backport-6.6/793-02-v6.11-net-dsa-qca8k-factor-out-bridge-join-leave-logic.patch b/target/linux/generic/backport-6.6/793-02-v6.11-net-dsa-qca8k-factor-out-bridge-join-leave-logic.patch new file mode 100644 index 0000000000..fdb7e7b8b6 --- /dev/null +++ b/target/linux/generic/backport-6.6/793-02-v6.11-net-dsa-qca8k-factor-out-bridge-join-leave-logic.patch @@ -0,0 +1,153 @@ +From 412e1775f413c944b8c51bdadb675be957d83dc8 Mon Sep 17 00:00:00 2001 +Message-ID: <412e1775f413c944b8c51bdadb675be957d83dc8.1728674648.git.mschiffer@universe-factory.net> +In-Reply-To: +References: +From: Matthias Schiffer +Date: Thu, 20 Jun 2024 19:25:49 +0200 +Subject: [PATCH] net: dsa: qca8k: factor out bridge join/leave logic + +Most of the logic in qca8k_port_bridge_join() and qca8k_port_bridge_leave() +is the same. Refactor to reduce duplication and prepare for reusing the +code for implementing bridge port isolation. + +dsa_port_offloads_bridge_dev() is used instead of +dsa_port_offloads_bridge(), passing the bridge in as a struct netdevice *, +as we won't have a struct dsa_bridge in qca8k_port_bridge_flags(). + +The error handling is changed slightly in the bridge leave case, +returning early and emitting an error message when a regmap access fails. +This shouldn't matter in practice, as there isn't much we can do if +communication with the switch breaks down in the middle of reconfiguration. + +Signed-off-by: Matthias Schiffer +Reviewed-by: Wojciech Drewek +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-common.c | 101 ++++++++++++++--------------- + 1 file changed, 50 insertions(+), 51 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -615,6 +615,49 @@ void qca8k_port_stp_state_set(struct dsa + qca8k_port_configure_learning(ds, port, learning); + } + ++static int qca8k_update_port_member(struct qca8k_priv *priv, int port, ++ const struct net_device *bridge_dev, ++ bool join) ++{ ++ struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp; ++ u32 port_mask = BIT(dp->cpu_dp->index); ++ int i, ret; ++ ++ for (i = 0; i < QCA8K_NUM_PORTS; i++) { ++ if (i == port) ++ continue; ++ if (dsa_is_cpu_port(priv->ds, i)) ++ continue; ++ ++ other_dp = dsa_to_port(priv->ds, i); ++ if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev)) ++ continue; ++ ++ /* Add/remove this port to/from the portvlan mask of the other ++ * ports in the bridge ++ */ ++ if (join) { ++ port_mask |= BIT(i); ++ ret = regmap_set_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(i), ++ BIT(port)); ++ } else { ++ ret = regmap_clear_bits(priv->regmap, ++ QCA8K_PORT_LOOKUP_CTRL(i), ++ BIT(port)); ++ } ++ ++ if (ret) ++ return ret; ++ } ++ ++ /* Add/remove all other ports to/from this port's portvlan mask */ ++ ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), ++ QCA8K_PORT_LOOKUP_MEMBER, port_mask); ++ ++ return ret; ++} ++ + int qca8k_port_pre_bridge_flags(struct dsa_switch *ds, int port, + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) +@@ -647,65 +690,21 @@ int qca8k_port_bridge_join(struct dsa_sw + struct netlink_ext_ack *extack) + { + struct qca8k_priv *priv = ds->priv; +- int port_mask, cpu_port; +- int i, ret; +- +- cpu_port = dsa_to_port(ds, port)->cpu_dp->index; +- port_mask = BIT(cpu_port); + +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- if (i == port) +- continue; +- if (dsa_is_cpu_port(ds, i)) +- continue; +- if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) +- continue; +- /* Add this port to the portvlan mask of the other ports +- * in the bridge +- */ +- ret = regmap_set_bits(priv->regmap, +- QCA8K_PORT_LOOKUP_CTRL(i), +- BIT(port)); +- if (ret) +- return ret; +- port_mask |= BIT(i); +- } +- +- /* Add all other ports to this ports portvlan mask */ +- ret = qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_MEMBER, port_mask); +- +- return ret; ++ return qca8k_update_port_member(priv, port, bridge.dev, true); + } + + void qca8k_port_bridge_leave(struct dsa_switch *ds, int port, + struct dsa_bridge bridge) + { + struct qca8k_priv *priv = ds->priv; +- int cpu_port, i; +- +- cpu_port = dsa_to_port(ds, port)->cpu_dp->index; +- +- for (i = 0; i < QCA8K_NUM_PORTS; i++) { +- if (i == port) +- continue; +- if (dsa_is_cpu_port(ds, i)) +- continue; +- if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) +- continue; +- /* Remove this port to the portvlan mask of the other ports +- * in the bridge +- */ +- regmap_clear_bits(priv->regmap, +- QCA8K_PORT_LOOKUP_CTRL(i), +- BIT(port)); +- } ++ int err; + +- /* Set the cpu port to be the only one in the portvlan mask of +- * this port +- */ +- qca8k_rmw(priv, QCA8K_PORT_LOOKUP_CTRL(port), +- QCA8K_PORT_LOOKUP_MEMBER, BIT(cpu_port)); ++ err = qca8k_update_port_member(priv, port, bridge.dev, false); ++ if (err) ++ dev_err(priv->dev, ++ "Failed to update switch config for bridge leave: %d\n", ++ err); + } + + void qca8k_port_fast_age(struct dsa_switch *ds, int port) diff --git a/target/linux/generic/backport-6.6/793-03-v6.11-net-dsa-qca8k-add-support-for-bridge-port-isolation.patch b/target/linux/generic/backport-6.6/793-03-v6.11-net-dsa-qca8k-add-support-for-bridge-port-isolation.patch new file mode 100644 index 0000000000..263fe10d4b --- /dev/null +++ b/target/linux/generic/backport-6.6/793-03-v6.11-net-dsa-qca8k-add-support-for-bridge-port-isolation.patch @@ -0,0 +1,91 @@ +From 422b64025ec10981c48f9367311846bf4bd38042 Mon Sep 17 00:00:00 2001 +Message-ID: <422b64025ec10981c48f9367311846bf4bd38042.1728674648.git.mschiffer@universe-factory.net> +In-Reply-To: +References: +From: Matthias Schiffer +Date: Thu, 20 Jun 2024 19:25:50 +0200 +Subject: [PATCH] net: dsa: qca8k: add support for bridge port isolation + +Remove a pair of ports from the port matrix when both ports have the +isolated flag set. + +Signed-off-by: Matthias Schiffer +Reviewed-by: Wojciech Drewek +Signed-off-by: David S. Miller +--- + drivers/net/dsa/qca/qca8k-common.c | 22 ++++++++++++++++++++-- + drivers/net/dsa/qca/qca8k.h | 1 + + 2 files changed, 21 insertions(+), 2 deletions(-) + +--- a/drivers/net/dsa/qca/qca8k-common.c ++++ b/drivers/net/dsa/qca/qca8k-common.c +@@ -619,6 +619,7 @@ static int qca8k_update_port_member(stru + const struct net_device *bridge_dev, + bool join) + { ++ bool isolated = !!(priv->port_isolated_map & BIT(port)), other_isolated; + struct dsa_port *dp = dsa_to_port(priv->ds, port), *other_dp; + u32 port_mask = BIT(dp->cpu_dp->index); + int i, ret; +@@ -633,10 +634,12 @@ static int qca8k_update_port_member(stru + if (!dsa_port_offloads_bridge_dev(other_dp, bridge_dev)) + continue; + ++ other_isolated = !!(priv->port_isolated_map & BIT(i)); ++ + /* Add/remove this port to/from the portvlan mask of the other + * ports in the bridge + */ +- if (join) { ++ if (join && !(isolated && other_isolated)) { + port_mask |= BIT(i); + ret = regmap_set_bits(priv->regmap, + QCA8K_PORT_LOOKUP_CTRL(i), +@@ -662,7 +665,7 @@ int qca8k_port_pre_bridge_flags(struct d + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) + { +- if (flags.mask & ~BR_LEARNING) ++ if (flags.mask & ~(BR_LEARNING | BR_ISOLATED)) + return -EINVAL; + + return 0; +@@ -672,6 +675,7 @@ int qca8k_port_bridge_flags(struct dsa_s + struct switchdev_brport_flags flags, + struct netlink_ext_ack *extack) + { ++ struct qca8k_priv *priv = ds->priv; + int ret; + + if (flags.mask & BR_LEARNING) { +@@ -680,6 +684,20 @@ int qca8k_port_bridge_flags(struct dsa_s + if (ret) + return ret; + } ++ ++ if (flags.mask & BR_ISOLATED) { ++ struct dsa_port *dp = dsa_to_port(ds, port); ++ struct net_device *bridge_dev = dsa_port_bridge_dev_get(dp); ++ ++ if (flags.val & BR_ISOLATED) ++ priv->port_isolated_map |= BIT(port); ++ else ++ priv->port_isolated_map &= ~BIT(port); ++ ++ ret = qca8k_update_port_member(priv, port, bridge_dev, true); ++ if (ret) ++ return ret; ++ } + + return 0; + } +--- a/drivers/net/dsa/qca/qca8k.h ++++ b/drivers/net/dsa/qca/qca8k.h +@@ -451,6 +451,7 @@ struct qca8k_priv { + * Bit 1: port enabled. Bit 0: port disabled. + */ + u8 port_enabled_map; ++ u8 port_isolated_map; + struct qca8k_ports_config ports_config; + struct regmap *regmap; + struct mii_bus *bus; diff --git a/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch b/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch index 3197aea091..8d815dd2f2 100644 --- a/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch +++ b/target/linux/generic/pending-6.6/711-01-net-dsa-qca8k-implement-lag_fdb_add-del-ops.patch @@ -27,7 +27,7 @@ Signed-off-by: Christian Marangi .port_mirror_add = qca8k_port_mirror_add, --- a/drivers/net/dsa/qca/qca8k-common.c +++ b/drivers/net/dsa/qca/qca8k-common.c -@@ -1215,6 +1215,42 @@ int qca8k_port_lag_leave(struct dsa_swit +@@ -1235,6 +1235,42 @@ int qca8k_port_lag_leave(struct dsa_swit return qca8k_lag_refresh_portmap(ds, port, lag, true); } @@ -72,7 +72,7 @@ Signed-off-by: Christian Marangi u32 val; --- a/drivers/net/dsa/qca/qca8k.h +++ b/drivers/net/dsa/qca/qca8k.h -@@ -590,5 +590,11 @@ int qca8k_port_lag_join(struct dsa_switc +@@ -591,5 +591,11 @@ int qca8k_port_lag_join(struct dsa_switc struct netlink_ext_ack *extack); int qca8k_port_lag_leave(struct dsa_switch *ds, int port, struct dsa_lag lag); diff --git a/target/linux/ipq40xx/patches-6.6/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch b/target/linux/ipq40xx/patches-6.6/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch index 9bd5ca515e..73e99f2bdc 100644 --- a/target/linux/ipq40xx/patches-6.6/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch +++ b/target/linux/ipq40xx/patches-6.6/706-net-dsa-qca8k-add-IPQ4019-built-in-switch-support.patch @@ -67,27 +67,18 @@ Signed-off-by: Robert Marko mask = QCA8K_VTU_FUNC0_EG_MODE_PORT_NOT(i); if ((reg & mask) != mask) { -@@ -653,7 +653,7 @@ int qca8k_port_bridge_join(struct dsa_sw - cpu_port = dsa_to_port(ds, port)->cpu_dp->index; - port_mask = BIT(cpu_port); +@@ -624,7 +624,7 @@ static int qca8k_update_port_member(stru + u32 port_mask = BIT(dp->cpu_dp->index); + int i, ret; - for (i = 0; i < QCA8K_NUM_PORTS; i++) { -+ for (i = 0; i < ds->num_ports; i++) { - if (dsa_is_cpu_port(ds, i)) ++ for (i = 0; i < priv->ds->num_ports; i++) { + if (i == port) continue; - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) -@@ -685,7 +685,7 @@ void qca8k_port_bridge_leave(struct dsa_ - - cpu_port = dsa_to_port(ds, port)->cpu_dp->index; - -- for (i = 0; i < QCA8K_NUM_PORTS; i++) { -+ for (i = 0; i < ds->num_ports; i++) { - if (dsa_is_cpu_port(ds, i)) - continue; - if (!dsa_port_offloads_bridge(dsa_to_port(ds, i), &bridge)) + if (dsa_is_cpu_port(priv->ds, i)) --- /dev/null +++ b/drivers/net/dsa/qca/qca8k-ipq4019.c -@@ -0,0 +1,948 @@ +@@ -0,0 +1,950 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) 2009 Felix Fietkau @@ -879,6 +870,8 @@ Signed-off-by: Robert Marko + .port_change_mtu = qca8k_port_change_mtu, + .port_max_mtu = qca8k_port_max_mtu, + .port_stp_state_set = qca8k_port_stp_state_set, ++ .port_pre_bridge_flags = qca8k_port_pre_bridge_flags, ++ .port_bridge_flags = qca8k_port_bridge_flags, + .port_bridge_join = qca8k_port_bridge_join, + .port_bridge_leave = qca8k_port_bridge_leave, + .port_fast_age = qca8k_port_fast_age, @@ -1119,7 +1112,7 @@ Signed-off-by: Robert Marko enum { QCA8K_PORT_SPEED_10M = 0, QCA8K_PORT_SPEED_100M = 1, -@@ -466,6 +518,10 @@ struct qca8k_priv { +@@ -467,6 +519,10 @@ struct qca8k_priv { struct qca8k_pcs pcs_port_6; const struct qca8k_match_data *info; struct qca8k_led ports_led[QCA8K_LED_COUNT]; diff --git a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c index f9d37fb3bd..b47a2f075e 100644 --- a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c +++ b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/dsa.c @@ -797,10 +797,6 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port, { struct rtl838x_switch_priv *priv = ds->priv; int sds_num; - u32 reg; - - pr_info("%s port %d, mode %x, phy-mode: %s, speed %d, link %d\n", __func__, - port, mode, phy_modes(state->interface), state->speed, state->link); /* Nothing to be done for the CPU-port */ if (port == priv->cpu_port) @@ -815,48 +811,6 @@ static void rtl93xx_phylink_mac_config(struct dsa_switch *ds, int port, (state->interface == PHY_INTERFACE_MODE_1000BASEX || state->interface == PHY_INTERFACE_MODE_10GBASER)) rtl9300_serdes_setup(port, sds_num, state->interface); - - reg = sw_r32(priv->r->mac_force_mode_ctrl(port)); - reg &= ~(0xf << 3); - - switch (state->speed) { - case SPEED_10000: - reg |= 4 << 3; - break; - case SPEED_5000: - reg |= 6 << 3; - break; - case SPEED_2500: - reg |= 5 << 3; - break; - case SPEED_1000: - reg |= 2 << 3; - break; - case SPEED_100: - reg |= 1 << 3; - break; - default: - /* Also covers 10M */ - break; - } - - if (state->link) - reg |= RTL930X_FORCE_LINK_EN; - - if (priv->lagmembers & BIT_ULL(port)) - reg |= RTL930X_DUPLEX_MODE | RTL930X_FORCE_LINK_EN; - - if (state->duplex == DUPLEX_FULL) - reg |= RTL930X_DUPLEX_MODE; - else - reg &= ~RTL930X_DUPLEX_MODE; /* Clear duplex bit otherwise */ - - if (priv->ports[port].phy_is_integrated) - reg &= ~RTL930X_FORCE_EN; /* Clear MAC_FORCE_EN to allow SDS-MAC link */ - else - reg |= RTL930X_FORCE_EN; - - sw_w32(reg, priv->r->mac_force_mode_ctrl(port)); } static void rtl83xx_phylink_mac_link_down(struct dsa_switch *ds, int port, @@ -962,11 +916,49 @@ static void rtl93xx_phylink_mac_link_up(struct dsa_switch *ds, int port, int speed, int duplex, bool tx_pause, bool rx_pause) { + struct dsa_port *dp = dsa_to_port(ds, port); struct rtl838x_switch_priv *priv = ds->priv; + u32 mcr, spdsel; + + if (speed == SPEED_10000) + spdsel = RTL_SPEED_10000; + else if (speed == SPEED_5000) + spdsel = RTL_SPEED_5000; + else if (speed == SPEED_2500) + spdsel = RTL_SPEED_2500; + else if (speed == SPEED_1000) + spdsel = RTL_SPEED_1000; + else if (speed == SPEED_100) + spdsel = RTL_SPEED_100; + else + spdsel = RTL_SPEED_10; + + mcr = sw_r32(priv->r->mac_force_mode_ctrl(port)); + + if (priv->family_id == RTL9300_FAMILY_ID) { + mcr &= ~RTL930X_RX_PAUSE_EN; + mcr &= ~RTL930X_TX_PAUSE_EN; + mcr &= ~RTL930X_DUPLEX_MODE; + mcr &= ~RTL930X_SPEED_MASK; + mcr |= RTL930X_FORCE_LINK_EN; + mcr |= spdsel << RTL930X_SPEED_SHIFT; + + if (tx_pause) + mcr |= RTL930X_TX_PAUSE_EN; + if (rx_pause) + mcr |= RTL930X_RX_PAUSE_EN; + if (duplex == DUPLEX_FULL || priv->lagmembers & BIT_ULL(port)) + mcr |= RTL930X_DUPLEX_MODE; + if (dsa_port_is_cpu(dp) || !priv->ports[port].phy_is_integrated) + mcr |= RTL930X_FORCE_EN; + } + + pr_debug("%s port %d, mode %x, speed %d, duplex %d, txpause %d, rxpause %d: set mcr=%08x\n", + __func__, port, mode, speed, duplex, tx_pause, rx_pause, mcr); + sw_w32(mcr, priv->r->mac_force_mode_ctrl(port)); /* Restart TX/RX to port */ sw_w32_mask(0, 0x3, priv->r->mac_port_ctrl(port)); - /* TODO: Set speed/duplex/pauses */ } static void rtl83xx_get_strings(struct dsa_switch *ds, diff --git a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h index 13a0bb5ffa..16c6098378 100644 --- a/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h +++ b/target/linux/realtek/files-6.6/drivers/net/dsa/rtl83xx/rtl838x.h @@ -147,6 +147,9 @@ #define RTL_SPEED_10 0 #define RTL_SPEED_100 1 #define RTL_SPEED_1000 2 +#define RTL_SPEED_2500 5 +#define RTL_SPEED_5000 6 +#define RTL_SPEED_10000 4 #define RTL83XX_FORCE_EN (1 << 0) #define RTL83XX_FORCE_LINK_EN (1 << 1) @@ -169,6 +172,8 @@ #define RTL930X_FORCE_EN (1 << 0) #define RTL930X_FORCE_LINK_EN (1 << 1) #define RTL930X_DUPLEX_MODE (1 << 2) +#define RTL930X_SPEED_SHIFT (3) +#define RTL930X_SPEED_MASK (15 << RTL930X_SPEED_SHIFT) #define RTL930X_TX_PAUSE_EN (1 << 7) #define RTL930X_RX_PAUSE_EN (1 << 8) #define RTL930X_MAC_FORCE_FC_EN (1 << 9)