From: Daniel Golle Date: Tue, 23 Apr 2024 12:11:52 +0000 (+0100) Subject: generic: 6.1, 6.6: mt7530: import accepted patches X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=ac8bfe316b816e9b40e58da55e44197f5b395dd2;p=openwrt%2Fstaging%2Fnbd.git generic: 6.1, 6.6: mt7530: import accepted patches Import patches for the MT7530 DSA driver from net-next tree: cae425cb43fe net: dsa: allow DSA switch drivers to provide their own phylink mac ops dd0c9855b413 net: dsa: introduce dsa_phylink_to_port() 7c5e37d7ee78 net: dsa: mt7530: simplify core operations 868ff5f4944a net: dsa: mt7530-mdio: read PHY address of switch from device tree 2c606d138518 net: dsa: mt7530: fix port mirroring for MT7988 SoC switch d59cf049c837 net: dsa: mt7530: fix mirroring frames received on local port 62d6d91db98a net: dsa: mt7530: provide own phylink MAC operations Signed-off-by: Daniel Golle --- diff --git a/target/linux/generic/backport-6.1/765-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch b/target/linux/generic/backport-6.1/765-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch new file mode 100644 index 0000000000..4cef7194eb --- /dev/null +++ b/target/linux/generic/backport-6.1/765-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch @@ -0,0 +1,99 @@ +From f13b2b33c7674fa0988dfaa9adb95d7d912b489f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 10 Apr 2024 20:42:38 +0100 +Subject: [PATCH 1/2] net: dsa: introduce dsa_phylink_to_port() + +We convert from a phylink_config struct to a dsa_port struct in many +places, let's provide a helper for this. + +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/E1rudqA-006K9B-85@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 6 ++++++ + net/dsa/port.c | 12 ++++++------ + 2 files changed, 12 insertions(+), 6 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -337,6 +337,12 @@ struct dsa_port { + struct list_head vlans; + }; + ++static inline struct dsa_port * ++dsa_phylink_to_port(struct phylink_config *config) ++{ ++ return container_of(config, struct dsa_port, pl_config); ++} ++ + /* TODO: ideally DSA ports would have a single dp->link_dp member, + * and no dst->rtable nor this struct dsa_link would be needed, + * but this would require some more complex tree walking, +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1552,7 +1552,7 @@ static void dsa_port_phylink_validate(st + unsigned long *supported, + struct phylink_link_state *state) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_validate) { +@@ -1567,7 +1567,7 @@ static void dsa_port_phylink_validate(st + static void dsa_port_phylink_mac_pcs_get_state(struct phylink_config *config, + struct phylink_link_state *state) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + int err; + +@@ -1589,7 +1589,7 @@ static struct phylink_pcs * + dsa_port_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct phylink_pcs *pcs = ERR_PTR(-EOPNOTSUPP); + struct dsa_switch *ds = dp->ds; + +@@ -1603,7 +1603,7 @@ static void dsa_port_phylink_mac_config( + unsigned int mode, + const struct phylink_link_state *state) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_config) +@@ -1614,7 +1614,7 @@ static void dsa_port_phylink_mac_config( + + static void dsa_port_phylink_mac_an_restart(struct phylink_config *config) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_an_restart) +@@ -1627,7 +1627,7 @@ static void dsa_port_phylink_mac_link_do + unsigned int mode, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct phy_device *phydev = NULL; + struct dsa_switch *ds = dp->ds; + +@@ -1650,7 +1650,7 @@ static void dsa_port_phylink_mac_link_up + int speed, int duplex, + bool tx_pause, bool rx_pause) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_link_up) { diff --git a/target/linux/generic/backport-6.1/766-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch b/target/linux/generic/backport-6.1/766-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch new file mode 100644 index 0000000000..51250ac97a --- /dev/null +++ b/target/linux/generic/backport-6.1/766-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch @@ -0,0 +1,117 @@ +From c22d8240fcd73a1c3ec8dcb055bd583fb970c375 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 10 Apr 2024 20:42:43 +0100 +Subject: [PATCH 2/2] net: dsa: allow DSA switch drivers to provide their own + phylink mac ops + +Rather than having a shim for each and every phylink MAC operation, +allow DSA switch drivers to provide their own ops structure. When a +DSA driver provides the phylink MAC operations, the shimmed ops must +not be provided, so fail an attempt to register a switch with both +the phylink_mac_ops in struct dsa_switch and the phylink_mac_* +operations populated in dsa_switch_ops populated. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/E1rudqF-006K9H-Cc@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 5 +++++ + net/dsa/dsa.c | 11 +++++++++++ + net/dsa/port.c | 26 ++++++++++++++++++++------ + 3 files changed, 36 insertions(+), 6 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -468,6 +468,11 @@ struct dsa_switch { + const struct dsa_switch_ops *ops; + + /* ++ * Allow a DSA switch driver to override the phylink MAC ops ++ */ ++ const struct phylink_mac_ops *phylink_mac_ops; ++ ++ /* + * Slave mii_bus and devices for the individual ports. + */ + u32 phys_mii_mask; +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1675,6 +1675,7 @@ static const struct phylink_mac_ops dsa_ + + int dsa_port_phylink_create(struct dsa_port *dp) + { ++ const struct phylink_mac_ops *mac_ops; + struct dsa_switch *ds = dp->ds; + phy_interface_t mode; + struct phylink *pl; +@@ -1694,8 +1695,12 @@ int dsa_port_phylink_create(struct dsa_p + if (ds->ops->phylink_get_caps) + ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config); + +- pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), +- mode, &dsa_port_phylink_mac_ops); ++ mac_ops = &dsa_port_phylink_mac_ops; ++ if (ds->phylink_mac_ops) ++ mac_ops = ds->phylink_mac_ops; ++ ++ pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), mode, ++ mac_ops); + if (IS_ERR(pl)) { + pr_err("error creating PHYLINK: %ld\n", PTR_ERR(pl)); + return PTR_ERR(pl); +@@ -1961,12 +1966,23 @@ static void dsa_shared_port_validate_of( + dn, dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index); + } + ++static void dsa_shared_port_link_down(struct dsa_port *dp) ++{ ++ struct dsa_switch *ds = dp->ds; ++ ++ if (ds->phylink_mac_ops && ds->phylink_mac_ops->mac_link_down) ++ ds->phylink_mac_ops->mac_link_down(&dp->pl_config, MLO_AN_FIXED, ++ PHY_INTERFACE_MODE_NA); ++ else if (ds->ops->phylink_mac_link_down) ++ ds->ops->phylink_mac_link_down(ds, dp->index, MLO_AN_FIXED, ++ PHY_INTERFACE_MODE_NA); ++} ++ + int dsa_shared_port_link_register_of(struct dsa_port *dp) + { + struct dsa_switch *ds = dp->ds; + bool missing_link_description; + bool missing_phy_mode; +- int port = dp->index; + + dsa_shared_port_validate_of(dp, &missing_phy_mode, + &missing_link_description); +@@ -1982,9 +1998,7 @@ int dsa_shared_port_link_register_of(str + "Skipping phylink registration for %s port %d\n", + dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index); + } else { +- if (ds->ops->phylink_mac_link_down) +- ds->ops->phylink_mac_link_down(ds, port, +- MLO_AN_FIXED, PHY_INTERFACE_MODE_NA); ++ dsa_shared_port_link_down(dp); + + return dsa_shared_port_phylink_register(dp); + } +--- a/net/dsa/dsa2.c ++++ b/net/dsa/dsa2.c +@@ -1736,6 +1736,15 @@ static int dsa_switch_probe(struct dsa_s + if (!ds->num_ports) + return -EINVAL; + ++ if (ds->phylink_mac_ops) { ++ if (ds->ops->phylink_mac_select_pcs || ++ ds->ops->phylink_mac_config || ++ ds->ops->phylink_mac_link_down || ++ ds->ops->phylink_mac_link_up || ++ ds->ops->adjust_link) ++ return -EINVAL; ++ } ++ + if (np) { + err = dsa_switch_parse_of(ds, np); + if (err) diff --git a/target/linux/generic/backport-6.1/790-49-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patc b/target/linux/generic/backport-6.1/790-49-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patc new file mode 100644 index 0000000000..ca2657d57d --- /dev/null +++ b/target/linux/generic/backport-6.1/790-49-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patc @@ -0,0 +1,135 @@ +From 5754b3bdcd872aa229881b8f07f84a8404c7d72a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 12 Apr 2024 16:15:34 +0100 +Subject: [PATCH 1/5] net: dsa: mt7530: provide own phylink MAC operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert mt753x to provide its own phylink MAC operations, thus avoiding +the shim layer in DSA's port.c + +Signed-off-by: Russell King (Oracle) +Tested-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/E1rvIco-006bQu-Fq@rmk-PC.armlinux.org.uk +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 46 +++++++++++++++++++++++++--------------- + 1 file changed, 29 insertions(+), 17 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2841,28 +2841,34 @@ mt7531_mac_config(struct dsa_switch *ds, + } + + static struct phylink_pcs * +-mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port, ++mt753x_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + + switch (interface) { + case PHY_INTERFACE_MODE_TRGMII: +- return &priv->pcs[port].pcs; ++ return &priv->pcs[dp->index].pcs; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- return priv->ports[port].sgmii_pcs; ++ return priv->ports[dp->index].sgmii_pcs; + default: + return NULL; + } + } + + static void +-mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++mt753x_phylink_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct dsa_switch *ds = dp->ds; ++ struct mt7530_priv *priv; ++ int port = dp->index; ++ ++ priv = ds->priv; + + if ((port == 5 || port == 6) && priv->info->mac_port_config) + priv->info->mac_port_config(ds, port, mode, state->interface); +@@ -2872,23 +2878,25 @@ mt753x_phylink_mac_config(struct dsa_swi + mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY); + } + +-static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, ++static void mt753x_phylink_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + +- mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); ++ mt7530_clear(priv, MT7530_PMCR_P(dp->index), PMCR_LINK_SETTINGS_MASK); + } + +-static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, ++static void mt753x_phylink_mac_link_up(struct phylink_config *config, ++ struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev, + int speed, int duplex, + bool tx_pause, bool rx_pause) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + u32 mcr; + + mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; +@@ -2923,7 +2931,7 @@ static void mt753x_phylink_mac_link_up(s + } + } + +- mt7530_set(priv, MT7530_PMCR_P(port), mcr); ++ mt7530_set(priv, MT7530_PMCR_P(dp->index), mcr); + } + + static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, +@@ -3148,16 +3156,19 @@ const struct dsa_switch_ops mt7530_switc + .port_mirror_add = mt753x_port_mirror_add, + .port_mirror_del = mt753x_port_mirror_del, + .phylink_get_caps = mt753x_phylink_get_caps, +- .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs, +- .phylink_mac_config = mt753x_phylink_mac_config, +- .phylink_mac_link_down = mt753x_phylink_mac_link_down, +- .phylink_mac_link_up = mt753x_phylink_mac_link_up, + .get_mac_eee = mt753x_get_mac_eee, + .set_mac_eee = mt753x_set_mac_eee, + .master_state_change = mt753x_conduit_state_change, + }; + EXPORT_SYMBOL_GPL(mt7530_switch_ops); + ++static const struct phylink_mac_ops mt753x_phylink_mac_ops = { ++ .mac_select_pcs = mt753x_phylink_mac_select_pcs, ++ .mac_config = mt753x_phylink_mac_config, ++ .mac_link_down = mt753x_phylink_mac_link_down, ++ .mac_link_up = mt753x_phylink_mac_link_up, ++}; ++ + const struct mt753x_info mt753x_table[] = { + [ID_MT7621] = { + .id = ID_MT7621, +@@ -3227,6 +3238,7 @@ mt7530_probe_common(struct mt7530_priv * + priv->dev = dev; + priv->ds->priv = priv; + priv->ds->ops = &mt7530_switch_ops; ++ priv->ds->phylink_mac_ops = &mt753x_phylink_mac_ops; + mutex_init(&priv->reg_mutex); + dev_set_drvdata(dev, priv); + diff --git a/target/linux/generic/backport-6.1/790-50-v6.10-net-dsa-mt7530-fix-mirroring-frames-received-on-loca.patch b/target/linux/generic/backport-6.1/790-50-v6.10-net-dsa-mt7530-fix-mirroring-frames-received-on-loca.patch new file mode 100644 index 0000000000..7640a9cb41 --- /dev/null +++ b/target/linux/generic/backport-6.1/790-50-v6.10-net-dsa-mt7530-fix-mirroring-frames-received-on-loca.patch @@ -0,0 +1,70 @@ +From d4097ddef078a113643a6dcde01e99741f852adb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sat, 13 Apr 2024 16:01:39 +0300 +Subject: [PATCH 2/5] net: dsa: mt7530: fix mirroring frames received on local + port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This switch intellectual property provides a bit on the ARL global control +register which controls allowing mirroring frames which are received on the +local port (monitor port). This bit is unset after reset. + +This ability must be enabled to fully support the port mirroring feature on +this switch intellectual property. + +Therefore, this patch fixes the traffic not being reflected on a port, +which would be configured like below: + + tc qdisc add dev swp0 clsact + + tc filter add dev swp0 ingress matchall skip_sw \ + action mirred egress mirror dev swp0 + +As a side note, this configuration provides the hairpinning feature for a +single port. + +Fixes: 37feab6076aa ("net: dsa: mt7530: add support for port mirroring") +Signed-off-by: Arınç ÜNAL +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 6 ++++++ + drivers/net/dsa/mt7530.h | 4 ++++ + 2 files changed, 10 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2471,6 +2471,9 @@ mt7530_setup(struct dsa_switch *ds) + PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); + } + ++ /* Allow mirroring frames received on the local port (monitor port). */ ++ mt7530_set(priv, MT753X_AGC, LOCAL_EN); ++ + /* Setup VLAN ID 0 for VLAN-unaware bridges */ + ret = mt7530_setup_vlan0(priv); + if (ret) +@@ -2582,6 +2585,9 @@ mt7531_setup_common(struct dsa_switch *d + PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); + } + ++ /* Allow mirroring frames received on the local port (monitor port). */ ++ mt7530_set(priv, MT753X_AGC, LOCAL_EN); ++ + /* Flush the FDB table */ + ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); + if (ret < 0) +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -32,6 +32,10 @@ enum mt753x_id { + #define SYSC_REG_RSTCTRL 0x34 + #define RESET_MCM BIT(2) + ++/* Register for ARL global control */ ++#define MT753X_AGC 0xc ++#define LOCAL_EN BIT(7) ++ + /* Registers to mac forward control for unknown frames */ + #define MT7530_MFC 0x10 + #define BC_FFP(x) (((x) & 0xff) << 24) diff --git a/target/linux/generic/backport-6.1/790-51-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch b/target/linux/generic/backport-6.1/790-51-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch new file mode 100644 index 0000000000..304ea21adc --- /dev/null +++ b/target/linux/generic/backport-6.1/790-51-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch @@ -0,0 +1,49 @@ +From 019a17a5e76940ea86114838d1d638d4dc8d3750 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sat, 13 Apr 2024 16:01:40 +0300 +Subject: [PATCH 3/5] net: dsa: mt7530: fix port mirroring for MT7988 SoC + switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open Version) +v0.1" document shows bits 16 to 18 as the MIRROR_PORT field of the CPU +forward control register. Currently, the MT7530 DSA subdriver configures +bits 0 to 2 of the CPU forward control register which breaks the port +mirroring feature for the MT7988 SoC switch. + +Fix this by using the MT7531_MIRROR_PORT_GET() and MT7531_MIRROR_PORT_SET() +macros which utilise the correct bits. + +Fixes: 110c18bfed41 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch") +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1876,14 +1876,16 @@ mt7530_port_vlan_del(struct dsa_switch * + + static int mt753x_mirror_port_get(unsigned int id, u32 val) + { +- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) : +- MIRROR_PORT(val); ++ return (id == ID_MT7531 || id == ID_MT7988) ? ++ MT7531_MIRROR_PORT_GET(val) : ++ MIRROR_PORT(val); + } + + static int mt753x_mirror_port_set(unsigned int id, u32 val) + { +- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) : +- MIRROR_PORT(val); ++ return (id == ID_MT7531 || id == ID_MT7988) ? ++ MT7531_MIRROR_PORT_SET(val) : ++ MIRROR_PORT(val); + } + + static int mt753x_port_mirror_add(struct dsa_switch *ds, int port, diff --git a/target/linux/generic/backport-6.1/790-52-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch b/target/linux/generic/backport-6.1/790-52-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch new file mode 100644 index 0000000000..6b6a255e26 --- /dev/null +++ b/target/linux/generic/backport-6.1/790-52-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch @@ -0,0 +1,238 @@ +From 5053a6cf1d50d785078562470d2a63695a9f3bf2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Thu, 18 Apr 2024 08:35:30 +0300 +Subject: [PATCH 4/5] net: dsa: mt7530-mdio: read PHY address of switch from + device tree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Read the PHY address the switch listens on from the reg property of the +switch node on the device tree. This change brings support for MT7530 +switches on boards with such bootstrapping configuration where the switch +listens on a different PHY address than the hardcoded PHY address on the +driver, 31. + +As described on the "MT7621 Programming Guide v0.4" document, the MT7530 +switch and its PHYs can be configured to listen on the range of 7-12, +15-20, 23-28, and 31 and 0-4 PHY addresses. + +There are operations where the switch PHY registers are used. For the PHY +address of the control PHY, transform the MT753X_CTRL_PHY_ADDR constant +into a macro and use it. The PHY address for the control PHY is 0 when the +switch listens on 31. In any other case, it is one greater than the PHY +address the switch listens on. + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Reviewed-by: Florian Fainelli +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530-mdio.c | 28 +++++++++++++------------- + drivers/net/dsa/mt7530.c | 37 +++++++++++++++++++++++------------ + drivers/net/dsa/mt7530.h | 4 +++- + 3 files changed, 41 insertions(+), 28 deletions(-) + +--- a/drivers/net/dsa/mt7530-mdio.c ++++ b/drivers/net/dsa/mt7530-mdio.c +@@ -18,7 +18,8 @@ + static int + mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) + { +- struct mii_bus *bus = context; ++ struct mt7530_priv *priv = context; ++ struct mii_bus *bus = priv->bus; + u16 page, r, lo, hi; + int ret; + +@@ -27,36 +28,35 @@ mt7530_regmap_write(void *context, unsig + lo = val & 0xffff; + hi = val >> 16; + +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); + if (ret < 0) + return ret; + +- ret = bus->write(bus, 0x1f, r, lo); ++ ret = bus->write(bus, priv->mdiodev->addr, r, lo); + if (ret < 0) + return ret; + +- ret = bus->write(bus, 0x1f, 0x10, hi); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x10, hi); + return ret; + } + + static int + mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) + { +- struct mii_bus *bus = context; ++ struct mt7530_priv *priv = context; ++ struct mii_bus *bus = priv->bus; + u16 page, r, lo, hi; + int ret; + + page = (reg >> 6) & 0x3ff; + r = (reg >> 2) & 0xf; + +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); + if (ret < 0) + return ret; + +- lo = bus->read(bus, 0x1f, r); +- hi = bus->read(bus, 0x1f, 0x10); ++ lo = bus->read(bus, priv->mdiodev->addr, r); ++ hi = bus->read(bus, priv->mdiodev->addr, 0x10); + + *val = (hi << 16) | (lo & 0xffff); + +@@ -107,8 +107,7 @@ mt7531_create_sgmii(struct mt7530_priv * + mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; + mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; + +- regmap = devm_regmap_init(priv->dev, +- &mt7530_regmap_bus, priv->bus, ++ regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv, + mt7531_pcs_config[i]); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); +@@ -153,6 +152,7 @@ mt7530_probe(struct mdio_device *mdiodev + + priv->bus = mdiodev->bus; + priv->dev = &mdiodev->dev; ++ priv->mdiodev = mdiodev; + + ret = mt7530_probe_common(priv); + if (ret) +@@ -203,8 +203,8 @@ mt7530_probe(struct mdio_device *mdiodev + regmap_config->reg_stride = 4; + regmap_config->max_register = MT7530_CREV; + regmap_config->disable_locking = true; +- priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, +- priv->bus, regmap_config); ++ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv, ++ regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -86,22 +86,26 @@ core_read_mmd_indirect(struct mt7530_pri + int value, ret; + + /* Write the desired MMD Devad */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, devad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ +- ret = bus->write(bus, 0, MII_MMD_DATA, prtad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, prtad); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + + /* Read the content of the MMD's selected register */ +- value = bus->read(bus, 0, MII_MMD_DATA); ++ value = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA); + + return value; + err: +@@ -118,22 +122,26 @@ core_write_mmd_indirect(struct mt7530_pr + int ret; + + /* Write the desired MMD Devad */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, devad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ +- ret = bus->write(bus, 0, MII_MMD_DATA, prtad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, prtad); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + + /* Write the data into MMD's selected register */ +- ret = bus->write(bus, 0, MII_MMD_DATA, data); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, data); + err: + if (ret < 0) + dev_err(&bus->dev, +@@ -2670,16 +2678,19 @@ mt7531_setup(struct dsa_switch *ds) + * phy_[read,write]_mmd_indirect is called, we provide our own + * mt7531_ind_mmd_phy_[read,write] to complete this function. + */ +- val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR, ++ val = mt7531_ind_c45_phy_read(priv, ++ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), + MDIO_MMD_VEND2, CORE_PLL_GROUP4); + val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE; + val &= ~MT7531_PHY_PLL_OFF; +- mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, +- CORE_PLL_GROUP4, val); ++ mt7531_ind_c45_phy_write(priv, ++ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MDIO_MMD_VEND2, CORE_PLL_GROUP4, val); + + /* Disable EEE advertisement on the switch PHYs. */ +- for (i = MT753X_CTRL_PHY_ADDR; +- i < MT753X_CTRL_PHY_ADDR + MT7530_NUM_PHYS; i++) { ++ for (i = MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr); ++ i < MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr) + MT7530_NUM_PHYS; ++ i++) { + mt7531_ind_c45_phy_write(priv, i, MDIO_MMD_AN, MDIO_AN_EEE_ADV, + 0); + } +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -629,7 +629,7 @@ enum mt7531_clk_skew { + #define MT7531_PHY_PLL_OFF BIT(5) + #define MT7531_PHY_PLL_BYPASS_MODE BIT(4) + +-#define MT753X_CTRL_PHY_ADDR 0 ++#define MT753X_CTRL_PHY_ADDR(addr) ((addr + 1) & 0x1f) + + #define CORE_PLL_GROUP5 0x404 + #define RG_LCDDS_PCW_NCPO1(x) ((x) & 0xffff) +@@ -771,6 +771,7 @@ struct mt753x_info { + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN + * @create_sgmii: Pointer to function creating SGMII PCS instance(s) + * @active_cpu_ports: Holding the active CPU ports ++ * @mdiodev: The pointer to the MDIO device structure + */ + struct mt7530_priv { + struct device *dev; +@@ -797,6 +798,7 @@ struct mt7530_priv { + u32 irq_enable; + int (*create_sgmii)(struct mt7530_priv *priv); + u8 active_cpu_ports; ++ struct mdio_device *mdiodev; + }; + + struct mt7530_hw_vlan_entry { diff --git a/target/linux/generic/backport-6.1/790-53-v6.10-net-dsa-mt7530-simplify-core-operations.patch b/target/linux/generic/backport-6.1/790-53-v6.10-net-dsa-mt7530-simplify-core-operations.patch new file mode 100644 index 0000000000..d9d70f1d4d --- /dev/null +++ b/target/linux/generic/backport-6.1/790-53-v6.10-net-dsa-mt7530-simplify-core-operations.patch @@ -0,0 +1,186 @@ +From 9764a08b3d260f4e7799d34bbfe64463db940d74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Thu, 18 Apr 2024 08:35:31 +0300 +Subject: [PATCH 5/5] net: dsa: mt7530: simplify core operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The core_rmw() function calls core_read_mmd_indirect() to read the +requested register, and then calls core_write_mmd_indirect() to write the +requested value to the register. Because Clause 22 is used to access Clause +45 registers, some operations on core_write_mmd_indirect() are +unnecessarily run. Get rid of core_read_mmd_indirect() and +core_write_mmd_indirect(), and run only the necessary operations on +core_write() and core_rmw(). + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 108 ++++++++++++++++----------------------- + 1 file changed, 43 insertions(+), 65 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -74,116 +74,94 @@ static const struct mt7530_mib_desc mt75 + MIB_DESC(1, 0xb8, "RxArlDrop"), + }; + +-/* Since phy_device has not yet been created and +- * phy_{read,write}_mmd_indirect is not available, we provide our own +- * core_{read,write}_mmd_indirect with core_{clear,write,set} wrappers +- * to complete this function. +- */ +-static int +-core_read_mmd_indirect(struct mt7530_priv *priv, int prtad, int devad) ++static void ++mt7530_mutex_lock(struct mt7530_priv *priv) ++{ ++ if (priv->bus) ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++} ++ ++static void ++mt7530_mutex_unlock(struct mt7530_priv *priv) ++{ ++ if (priv->bus) ++ mutex_unlock(&priv->bus->mdio_lock); ++} ++ ++static void ++core_write(struct mt7530_priv *priv, u32 reg, u32 val) + { + struct mii_bus *bus = priv->bus; +- int value, ret; ++ int ret; ++ ++ mt7530_mutex_lock(priv); + + /* Write the desired MMD Devad */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad); ++ MII_MMD_CTRL, MDIO_MMD_VEND2); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, prtad); ++ MII_MMD_DATA, reg); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); ++ MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + +- /* Read the content of the MMD's selected register */ +- value = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA); +- +- return value; ++ /* Write the data into MMD's selected register */ ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, val); + err: +- dev_err(&bus->dev, "failed to read mmd register\n"); ++ if (ret < 0) ++ dev_err(&bus->dev, "failed to write mmd register\n"); + +- return ret; ++ mt7530_mutex_unlock(priv); + } + +-static int +-core_write_mmd_indirect(struct mt7530_priv *priv, int prtad, +- int devad, u32 data) ++static void ++core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) + { + struct mii_bus *bus = priv->bus; ++ u32 val; + int ret; + ++ mt7530_mutex_lock(priv); ++ + /* Write the desired MMD Devad */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad); ++ MII_MMD_CTRL, MDIO_MMD_VEND2); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, prtad); ++ MII_MMD_DATA, reg); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); ++ MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + ++ /* Read the content of the MMD's selected register */ ++ val = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA); ++ val &= ~mask; ++ val |= set; + /* Write the data into MMD's selected register */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, data); ++ MII_MMD_DATA, val); + err: + if (ret < 0) +- dev_err(&bus->dev, +- "failed to write mmd register\n"); +- return ret; +-} +- +-static void +-mt7530_mutex_lock(struct mt7530_priv *priv) +-{ +- if (priv->bus) +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); +-} +- +-static void +-mt7530_mutex_unlock(struct mt7530_priv *priv) +-{ +- if (priv->bus) +- mutex_unlock(&priv->bus->mdio_lock); +-} +- +-static void +-core_write(struct mt7530_priv *priv, u32 reg, u32 val) +-{ +- mt7530_mutex_lock(priv); +- +- core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); +- +- mt7530_mutex_unlock(priv); +-} +- +-static void +-core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) +-{ +- u32 val; +- +- mt7530_mutex_lock(priv); +- +- val = core_read_mmd_indirect(priv, reg, MDIO_MMD_VEND2); +- val &= ~mask; +- val |= set; +- core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); ++ dev_err(&bus->dev, "failed to write mmd register\n"); + + mt7530_mutex_unlock(priv); + } diff --git a/target/linux/generic/backport-6.6/763-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch b/target/linux/generic/backport-6.6/763-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch new file mode 100644 index 0000000000..0e7ace9d1a --- /dev/null +++ b/target/linux/generic/backport-6.6/763-v6.10-net-dsa-introduce-dsa_phylink_to_port.patch @@ -0,0 +1,90 @@ +From f13b2b33c7674fa0988dfaa9adb95d7d912b489f Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 10 Apr 2024 20:42:38 +0100 +Subject: [PATCH 1/2] net: dsa: introduce dsa_phylink_to_port() + +We convert from a phylink_config struct to a dsa_port struct in many +places, let's provide a helper for this. + +Reviewed-by: Andrew Lunn +Reviewed-by: Florian Fainelli +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Link: https://lore.kernel.org/r/E1rudqA-006K9B-85@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 6 ++++++ + net/dsa/port.c | 12 ++++++------ + 2 files changed, 12 insertions(+), 6 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -327,6 +327,12 @@ struct dsa_port { + }; + }; + ++static inline struct dsa_port * ++dsa_phylink_to_port(struct phylink_config *config) ++{ ++ return container_of(config, struct dsa_port, pl_config); ++} ++ + /* TODO: ideally DSA ports would have a single dp->link_dp member, + * and no dst->rtable nor this struct dsa_link would be needed, + * but this would require some more complex tree walking, +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1572,7 +1572,7 @@ static struct phylink_pcs * + dsa_port_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct phylink_pcs *pcs = ERR_PTR(-EOPNOTSUPP); + struct dsa_switch *ds = dp->ds; + +@@ -1586,7 +1586,7 @@ static int dsa_port_phylink_mac_prepare( + unsigned int mode, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + int err = 0; + +@@ -1601,7 +1601,7 @@ static void dsa_port_phylink_mac_config( + unsigned int mode, + const struct phylink_link_state *state) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_config) +@@ -1614,7 +1614,7 @@ static int dsa_port_phylink_mac_finish(s + unsigned int mode, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + int err = 0; + +@@ -1629,7 +1629,7 @@ static void dsa_port_phylink_mac_link_do + unsigned int mode, + phy_interface_t interface) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct phy_device *phydev = NULL; + struct dsa_switch *ds = dp->ds; + +@@ -1652,7 +1652,7 @@ static void dsa_port_phylink_mac_link_up + int speed, int duplex, + bool tx_pause, bool rx_pause) + { +- struct dsa_port *dp = container_of(config, struct dsa_port, pl_config); ++ struct dsa_port *dp = dsa_phylink_to_port(config); + struct dsa_switch *ds = dp->ds; + + if (!ds->ops->phylink_mac_link_up) { diff --git a/target/linux/generic/backport-6.6/764-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch b/target/linux/generic/backport-6.6/764-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch new file mode 100644 index 0000000000..7c9ab16d4a --- /dev/null +++ b/target/linux/generic/backport-6.6/764-v6.10-net-dsa-allow-DSA-switch-drivers-to-provide-their-ow.patch @@ -0,0 +1,119 @@ +From c22d8240fcd73a1c3ec8dcb055bd583fb970c375 Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Wed, 10 Apr 2024 20:42:43 +0100 +Subject: [PATCH 2/2] net: dsa: allow DSA switch drivers to provide their own + phylink mac ops + +Rather than having a shim for each and every phylink MAC operation, +allow DSA switch drivers to provide their own ops structure. When a +DSA driver provides the phylink MAC operations, the shimmed ops must +not be provided, so fail an attempt to register a switch with both +the phylink_mac_ops in struct dsa_switch and the phylink_mac_* +operations populated in dsa_switch_ops populated. + +Signed-off-by: Russell King (Oracle) +Reviewed-by: Vladimir Oltean +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/E1rudqF-006K9H-Cc@rmk-PC.armlinux.org.uk +Signed-off-by: Jakub Kicinski +--- + include/net/dsa.h | 5 +++++ + net/dsa/dsa.c | 11 +++++++++++ + net/dsa/port.c | 26 ++++++++++++++++++++------ + 3 files changed, 36 insertions(+), 6 deletions(-) + +--- a/include/net/dsa.h ++++ b/include/net/dsa.h +@@ -458,6 +458,11 @@ struct dsa_switch { + const struct dsa_switch_ops *ops; + + /* ++ * Allow a DSA switch driver to override the phylink MAC ops ++ */ ++ const struct phylink_mac_ops *phylink_mac_ops; ++ ++ /* + * Slave mii_bus and devices for the individual ports. + */ + u32 phys_mii_mask; +--- a/net/dsa/dsa.c ++++ b/net/dsa/dsa.c +@@ -1510,6 +1510,17 @@ static int dsa_switch_probe(struct dsa_s + if (!ds->num_ports) + return -EINVAL; + ++ if (ds->phylink_mac_ops) { ++ if (ds->ops->phylink_mac_select_pcs || ++ ds->ops->phylink_mac_prepare || ++ ds->ops->phylink_mac_config || ++ ds->ops->phylink_mac_finish || ++ ds->ops->phylink_mac_link_down || ++ ds->ops->phylink_mac_link_up || ++ ds->ops->adjust_link) ++ return -EINVAL; ++ } ++ + if (np) { + err = dsa_switch_parse_of(ds, np); + if (err) +--- a/net/dsa/port.c ++++ b/net/dsa/port.c +@@ -1677,6 +1677,7 @@ static const struct phylink_mac_ops dsa_ + + int dsa_port_phylink_create(struct dsa_port *dp) + { ++ const struct phylink_mac_ops *mac_ops; + struct dsa_switch *ds = dp->ds; + phy_interface_t mode; + struct phylink *pl; +@@ -1700,8 +1701,12 @@ int dsa_port_phylink_create(struct dsa_p + } + } + +- pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), +- mode, &dsa_port_phylink_mac_ops); ++ mac_ops = &dsa_port_phylink_mac_ops; ++ if (ds->phylink_mac_ops) ++ mac_ops = ds->phylink_mac_ops; ++ ++ pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn), mode, ++ mac_ops); + if (IS_ERR(pl)) { + pr_err("error creating PHYLINK: %ld\n", PTR_ERR(pl)); + return PTR_ERR(pl); +@@ -1967,12 +1972,23 @@ static void dsa_shared_port_validate_of( + dn, dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index); + } + ++static void dsa_shared_port_link_down(struct dsa_port *dp) ++{ ++ struct dsa_switch *ds = dp->ds; ++ ++ if (ds->phylink_mac_ops && ds->phylink_mac_ops->mac_link_down) ++ ds->phylink_mac_ops->mac_link_down(&dp->pl_config, MLO_AN_FIXED, ++ PHY_INTERFACE_MODE_NA); ++ else if (ds->ops->phylink_mac_link_down) ++ ds->ops->phylink_mac_link_down(ds, dp->index, MLO_AN_FIXED, ++ PHY_INTERFACE_MODE_NA); ++} ++ + int dsa_shared_port_link_register_of(struct dsa_port *dp) + { + struct dsa_switch *ds = dp->ds; + bool missing_link_description; + bool missing_phy_mode; +- int port = dp->index; + + dsa_shared_port_validate_of(dp, &missing_phy_mode, + &missing_link_description); +@@ -1988,9 +2004,7 @@ int dsa_shared_port_link_register_of(str + "Skipping phylink registration for %s port %d\n", + dsa_port_is_cpu(dp) ? "CPU" : "DSA", dp->index); + } else { +- if (ds->ops->phylink_mac_link_down) +- ds->ops->phylink_mac_link_down(ds, port, +- MLO_AN_FIXED, PHY_INTERFACE_MODE_NA); ++ dsa_shared_port_link_down(dp); + + return dsa_shared_port_phylink_register(dp); + } diff --git a/target/linux/generic/backport-6.6/790-33-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patch b/target/linux/generic/backport-6.6/790-33-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patch new file mode 100644 index 0000000000..7cbdc9e50d --- /dev/null +++ b/target/linux/generic/backport-6.6/790-33-v6.10-net-dsa-mt7530-provide-own-phylink-MAC-operations.patch @@ -0,0 +1,135 @@ +From 5754b3bdcd872aa229881b8f07f84a8404c7d72a Mon Sep 17 00:00:00 2001 +From: "Russell King (Oracle)" +Date: Fri, 12 Apr 2024 16:15:34 +0100 +Subject: [PATCH 1/5] net: dsa: mt7530: provide own phylink MAC operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Convert mt753x to provide its own phylink MAC operations, thus avoiding +the shim layer in DSA's port.c + +Signed-off-by: Russell King (Oracle) +Tested-by: Arınç ÜNAL +Link: https://lore.kernel.org/r/E1rvIco-006bQu-Fq@rmk-PC.armlinux.org.uk +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 46 +++++++++++++++++++++++++--------------- + 1 file changed, 29 insertions(+), 17 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2850,28 +2850,34 @@ mt7531_mac_config(struct dsa_switch *ds, + } + + static struct phylink_pcs * +-mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port, ++mt753x_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + + switch (interface) { + case PHY_INTERFACE_MODE_TRGMII: +- return &priv->pcs[port].pcs; ++ return &priv->pcs[dp->index].pcs; + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: +- return priv->ports[port].sgmii_pcs; ++ return priv->ports[dp->index].sgmii_pcs; + default: + return NULL; + } + } + + static void +-mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, ++mt753x_phylink_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct dsa_switch *ds = dp->ds; ++ struct mt7530_priv *priv; ++ int port = dp->index; ++ ++ priv = ds->priv; + + if ((port == 5 || port == 6) && priv->info->mac_port_config) + priv->info->mac_port_config(ds, port, mode, state->interface); +@@ -2881,23 +2887,25 @@ mt753x_phylink_mac_config(struct dsa_swi + mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY); + } + +-static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port, ++static void mt753x_phylink_mac_link_down(struct phylink_config *config, + unsigned int mode, + phy_interface_t interface) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + +- mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK); ++ mt7530_clear(priv, MT7530_PMCR_P(dp->index), PMCR_LINK_SETTINGS_MASK); + } + +-static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port, ++static void mt753x_phylink_mac_link_up(struct phylink_config *config, ++ struct phy_device *phydev, + unsigned int mode, + phy_interface_t interface, +- struct phy_device *phydev, + int speed, int duplex, + bool tx_pause, bool rx_pause) + { +- struct mt7530_priv *priv = ds->priv; ++ struct dsa_port *dp = dsa_phylink_to_port(config); ++ struct mt7530_priv *priv = dp->ds->priv; + u32 mcr; + + mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK; +@@ -2932,7 +2940,7 @@ static void mt753x_phylink_mac_link_up(s + } + } + +- mt7530_set(priv, MT7530_PMCR_P(port), mcr); ++ mt7530_set(priv, MT7530_PMCR_P(dp->index), mcr); + } + + static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port, +@@ -3152,16 +3160,19 @@ const struct dsa_switch_ops mt7530_switc + .port_mirror_add = mt753x_port_mirror_add, + .port_mirror_del = mt753x_port_mirror_del, + .phylink_get_caps = mt753x_phylink_get_caps, +- .phylink_mac_select_pcs = mt753x_phylink_mac_select_pcs, +- .phylink_mac_config = mt753x_phylink_mac_config, +- .phylink_mac_link_down = mt753x_phylink_mac_link_down, +- .phylink_mac_link_up = mt753x_phylink_mac_link_up, + .get_mac_eee = mt753x_get_mac_eee, + .set_mac_eee = mt753x_set_mac_eee, + .master_state_change = mt753x_conduit_state_change, + }; + EXPORT_SYMBOL_GPL(mt7530_switch_ops); + ++static const struct phylink_mac_ops mt753x_phylink_mac_ops = { ++ .mac_select_pcs = mt753x_phylink_mac_select_pcs, ++ .mac_config = mt753x_phylink_mac_config, ++ .mac_link_down = mt753x_phylink_mac_link_down, ++ .mac_link_up = mt753x_phylink_mac_link_up, ++}; ++ + const struct mt753x_info mt753x_table[] = { + [ID_MT7621] = { + .id = ID_MT7621, +@@ -3239,6 +3250,7 @@ mt7530_probe_common(struct mt7530_priv * + priv->dev = dev; + priv->ds->priv = priv; + priv->ds->ops = &mt7530_switch_ops; ++ priv->ds->phylink_mac_ops = &mt753x_phylink_mac_ops; + mutex_init(&priv->reg_mutex); + dev_set_drvdata(dev, priv); + diff --git a/target/linux/generic/backport-6.6/790-34-v6.10-net-dsa-mt7530-fix-mirroring-frames-received-on-loca.patch b/target/linux/generic/backport-6.6/790-34-v6.10-net-dsa-mt7530-fix-mirroring-frames-received-on-loca.patch new file mode 100644 index 0000000000..11f9a68cee --- /dev/null +++ b/target/linux/generic/backport-6.6/790-34-v6.10-net-dsa-mt7530-fix-mirroring-frames-received-on-loca.patch @@ -0,0 +1,70 @@ +From d4097ddef078a113643a6dcde01e99741f852adb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sat, 13 Apr 2024 16:01:39 +0300 +Subject: [PATCH 2/5] net: dsa: mt7530: fix mirroring frames received on local + port +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This switch intellectual property provides a bit on the ARL global control +register which controls allowing mirroring frames which are received on the +local port (monitor port). This bit is unset after reset. + +This ability must be enabled to fully support the port mirroring feature on +this switch intellectual property. + +Therefore, this patch fixes the traffic not being reflected on a port, +which would be configured like below: + + tc qdisc add dev swp0 clsact + + tc filter add dev swp0 ingress matchall skip_sw \ + action mirred egress mirror dev swp0 + +As a side note, this configuration provides the hairpinning feature for a +single port. + +Fixes: 37feab6076aa ("net: dsa: mt7530: add support for port mirroring") +Signed-off-by: Arınç ÜNAL +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 6 ++++++ + drivers/net/dsa/mt7530.h | 4 ++++ + 2 files changed, 10 insertions(+) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -2480,6 +2480,9 @@ mt7530_setup(struct dsa_switch *ds) + PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); + } + ++ /* Allow mirroring frames received on the local port (monitor port). */ ++ mt7530_set(priv, MT753X_AGC, LOCAL_EN); ++ + /* Setup VLAN ID 0 for VLAN-unaware bridges */ + ret = mt7530_setup_vlan0(priv); + if (ret) +@@ -2591,6 +2594,9 @@ mt7531_setup_common(struct dsa_switch *d + PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT)); + } + ++ /* Allow mirroring frames received on the local port (monitor port). */ ++ mt7530_set(priv, MT753X_AGC, LOCAL_EN); ++ + /* Flush the FDB table */ + ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL); + if (ret < 0) +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -32,6 +32,10 @@ enum mt753x_id { + #define SYSC_REG_RSTCTRL 0x34 + #define RESET_MCM BIT(2) + ++/* Register for ARL global control */ ++#define MT753X_AGC 0xc ++#define LOCAL_EN BIT(7) ++ + /* Registers to mac forward control for unknown frames */ + #define MT7530_MFC 0x10 + #define BC_FFP(x) (((x) & 0xff) << 24) diff --git a/target/linux/generic/backport-6.6/790-35-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch b/target/linux/generic/backport-6.6/790-35-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch new file mode 100644 index 0000000000..d5ba8ef1c4 --- /dev/null +++ b/target/linux/generic/backport-6.6/790-35-v6.10-net-dsa-mt7530-fix-port-mirroring-for-MT7988-SoC-swi.patch @@ -0,0 +1,49 @@ +From 019a17a5e76940ea86114838d1d638d4dc8d3750 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Sat, 13 Apr 2024 16:01:40 +0300 +Subject: [PATCH 3/5] net: dsa: mt7530: fix port mirroring for MT7988 SoC + switch +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open Version) +v0.1" document shows bits 16 to 18 as the MIRROR_PORT field of the CPU +forward control register. Currently, the MT7530 DSA subdriver configures +bits 0 to 2 of the CPU forward control register which breaks the port +mirroring feature for the MT7988 SoC switch. + +Fix this by using the MT7531_MIRROR_PORT_GET() and MT7531_MIRROR_PORT_SET() +macros which utilise the correct bits. + +Fixes: 110c18bfed41 ("net: dsa: mt7530: introduce driver for MT7988 built-in switch") +Signed-off-by: Arınç ÜNAL +Acked-by: Daniel Golle +Signed-off-by: David S. Miller +--- + drivers/net/dsa/mt7530.c | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -1883,14 +1883,16 @@ mt7530_port_vlan_del(struct dsa_switch * + + static int mt753x_mirror_port_get(unsigned int id, u32 val) + { +- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_GET(val) : +- MIRROR_PORT(val); ++ return (id == ID_MT7531 || id == ID_MT7988) ? ++ MT7531_MIRROR_PORT_GET(val) : ++ MIRROR_PORT(val); + } + + static int mt753x_mirror_port_set(unsigned int id, u32 val) + { +- return (id == ID_MT7531) ? MT7531_MIRROR_PORT_SET(val) : +- MIRROR_PORT(val); ++ return (id == ID_MT7531 || id == ID_MT7988) ? ++ MT7531_MIRROR_PORT_SET(val) : ++ MIRROR_PORT(val); + } + + static int mt753x_port_mirror_add(struct dsa_switch *ds, int port, diff --git a/target/linux/generic/backport-6.6/790-36-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch b/target/linux/generic/backport-6.6/790-36-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch new file mode 100644 index 0000000000..a6cbb0fc6b --- /dev/null +++ b/target/linux/generic/backport-6.6/790-36-v6.10-net-dsa-mt7530-mdio-read-PHY-address-of-switch-from-.patch @@ -0,0 +1,238 @@ +From 5053a6cf1d50d785078562470d2a63695a9f3bf2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Thu, 18 Apr 2024 08:35:30 +0300 +Subject: [PATCH 4/5] net: dsa: mt7530-mdio: read PHY address of switch from + device tree +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Read the PHY address the switch listens on from the reg property of the +switch node on the device tree. This change brings support for MT7530 +switches on boards with such bootstrapping configuration where the switch +listens on a different PHY address than the hardcoded PHY address on the +driver, 31. + +As described on the "MT7621 Programming Guide v0.4" document, the MT7530 +switch and its PHYs can be configured to listen on the range of 7-12, +15-20, 23-28, and 31 and 0-4 PHY addresses. + +There are operations where the switch PHY registers are used. For the PHY +address of the control PHY, transform the MT753X_CTRL_PHY_ADDR constant +into a macro and use it. The PHY address for the control PHY is 0 when the +switch listens on 31. In any other case, it is one greater than the PHY +address the switch listens on. + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Reviewed-by: Florian Fainelli +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530-mdio.c | 28 +++++++++++++------------- + drivers/net/dsa/mt7530.c | 37 +++++++++++++++++++++++------------ + drivers/net/dsa/mt7530.h | 4 +++- + 3 files changed, 41 insertions(+), 28 deletions(-) + +--- a/drivers/net/dsa/mt7530-mdio.c ++++ b/drivers/net/dsa/mt7530-mdio.c +@@ -18,7 +18,8 @@ + static int + mt7530_regmap_write(void *context, unsigned int reg, unsigned int val) + { +- struct mii_bus *bus = context; ++ struct mt7530_priv *priv = context; ++ struct mii_bus *bus = priv->bus; + u16 page, r, lo, hi; + int ret; + +@@ -27,36 +28,35 @@ mt7530_regmap_write(void *context, unsig + lo = val & 0xffff; + hi = val >> 16; + +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); + if (ret < 0) + return ret; + +- ret = bus->write(bus, 0x1f, r, lo); ++ ret = bus->write(bus, priv->mdiodev->addr, r, lo); + if (ret < 0) + return ret; + +- ret = bus->write(bus, 0x1f, 0x10, hi); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x10, hi); + return ret; + } + + static int + mt7530_regmap_read(void *context, unsigned int reg, unsigned int *val) + { +- struct mii_bus *bus = context; ++ struct mt7530_priv *priv = context; ++ struct mii_bus *bus = priv->bus; + u16 page, r, lo, hi; + int ret; + + page = (reg >> 6) & 0x3ff; + r = (reg >> 2) & 0xf; + +- /* MT7530 uses 31 as the pseudo port */ +- ret = bus->write(bus, 0x1f, 0x1f, page); ++ ret = bus->write(bus, priv->mdiodev->addr, 0x1f, page); + if (ret < 0) + return ret; + +- lo = bus->read(bus, 0x1f, r); +- hi = bus->read(bus, 0x1f, 0x10); ++ lo = bus->read(bus, priv->mdiodev->addr, r); ++ hi = bus->read(bus, priv->mdiodev->addr, 0x10); + + *val = (hi << 16) | (lo & 0xffff); + +@@ -107,8 +107,7 @@ mt7531_create_sgmii(struct mt7530_priv * + mt7531_pcs_config[i]->unlock = mt7530_mdio_regmap_unlock; + mt7531_pcs_config[i]->lock_arg = &priv->bus->mdio_lock; + +- regmap = devm_regmap_init(priv->dev, +- &mt7530_regmap_bus, priv->bus, ++ regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv, + mt7531_pcs_config[i]); + if (IS_ERR(regmap)) { + ret = PTR_ERR(regmap); +@@ -153,6 +152,7 @@ mt7530_probe(struct mdio_device *mdiodev + + priv->bus = mdiodev->bus; + priv->dev = &mdiodev->dev; ++ priv->mdiodev = mdiodev; + + ret = mt7530_probe_common(priv); + if (ret) +@@ -203,8 +203,8 @@ mt7530_probe(struct mdio_device *mdiodev + regmap_config->reg_stride = 4; + regmap_config->max_register = MT7530_CREV; + regmap_config->disable_locking = true; +- priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, +- priv->bus, regmap_config); ++ priv->regmap = devm_regmap_init(priv->dev, &mt7530_regmap_bus, priv, ++ regmap_config); + if (IS_ERR(priv->regmap)) + return PTR_ERR(priv->regmap); + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -86,22 +86,26 @@ core_read_mmd_indirect(struct mt7530_pri + int value, ret; + + /* Write the desired MMD Devad */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, devad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ +- ret = bus->write(bus, 0, MII_MMD_DATA, prtad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, prtad); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + + /* Read the content of the MMD's selected register */ +- value = bus->read(bus, 0, MII_MMD_DATA); ++ value = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA); + + return value; + err: +@@ -118,22 +122,26 @@ core_write_mmd_indirect(struct mt7530_pr + int ret; + + /* Write the desired MMD Devad */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, devad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ +- ret = bus->write(bus, 0, MII_MMD_DATA, prtad); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, prtad); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ +- ret = bus->write(bus, 0, MII_MMD_CTRL, (devad | MII_MMD_CTRL_NOINCR)); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + + /* Write the data into MMD's selected register */ +- ret = bus->write(bus, 0, MII_MMD_DATA, data); ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, data); + err: + if (ret < 0) + dev_err(&bus->dev, +@@ -2679,16 +2687,19 @@ mt7531_setup(struct dsa_switch *ds) + * phy_[read,write]_mmd_indirect is called, we provide our own + * mt7531_ind_mmd_phy_[read,write] to complete this function. + */ +- val = mt7531_ind_c45_phy_read(priv, MT753X_CTRL_PHY_ADDR, ++ val = mt7531_ind_c45_phy_read(priv, ++ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), + MDIO_MMD_VEND2, CORE_PLL_GROUP4); + val |= MT7531_RG_SYSPLL_DMY2 | MT7531_PHY_PLL_BYPASS_MODE; + val &= ~MT7531_PHY_PLL_OFF; +- mt7531_ind_c45_phy_write(priv, MT753X_CTRL_PHY_ADDR, MDIO_MMD_VEND2, +- CORE_PLL_GROUP4, val); ++ mt7531_ind_c45_phy_write(priv, ++ MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MDIO_MMD_VEND2, CORE_PLL_GROUP4, val); + + /* Disable EEE advertisement on the switch PHYs. */ +- for (i = MT753X_CTRL_PHY_ADDR; +- i < MT753X_CTRL_PHY_ADDR + MT7530_NUM_PHYS; i++) { ++ for (i = MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr); ++ i < MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr) + MT7530_NUM_PHYS; ++ i++) { + mt7531_ind_c45_phy_write(priv, i, MDIO_MMD_AN, MDIO_AN_EEE_ADV, + 0); + } +--- a/drivers/net/dsa/mt7530.h ++++ b/drivers/net/dsa/mt7530.h +@@ -629,7 +629,7 @@ enum mt7531_clk_skew { + #define MT7531_PHY_PLL_OFF BIT(5) + #define MT7531_PHY_PLL_BYPASS_MODE BIT(4) + +-#define MT753X_CTRL_PHY_ADDR 0 ++#define MT753X_CTRL_PHY_ADDR(addr) ((addr + 1) & 0x1f) + + #define CORE_PLL_GROUP5 0x404 + #define RG_LCDDS_PCW_NCPO1(x) ((x) & 0xffff) +@@ -778,6 +778,7 @@ struct mt753x_info { + * @irq_enable: IRQ enable bits, synced to SYS_INT_EN + * @create_sgmii: Pointer to function creating SGMII PCS instance(s) + * @active_cpu_ports: Holding the active CPU ports ++ * @mdiodev: The pointer to the MDIO device structure + */ + struct mt7530_priv { + struct device *dev; +@@ -804,6 +805,7 @@ struct mt7530_priv { + u32 irq_enable; + int (*create_sgmii)(struct mt7530_priv *priv); + u8 active_cpu_ports; ++ struct mdio_device *mdiodev; + }; + + struct mt7530_hw_vlan_entry { diff --git a/target/linux/generic/backport-6.6/790-37-v6.10-net-dsa-mt7530-simplify-core-operations.patch b/target/linux/generic/backport-6.6/790-37-v6.10-net-dsa-mt7530-simplify-core-operations.patch new file mode 100644 index 0000000000..d9d70f1d4d --- /dev/null +++ b/target/linux/generic/backport-6.6/790-37-v6.10-net-dsa-mt7530-simplify-core-operations.patch @@ -0,0 +1,186 @@ +From 9764a08b3d260f4e7799d34bbfe64463db940d74 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= +Date: Thu, 18 Apr 2024 08:35:31 +0300 +Subject: [PATCH 5/5] net: dsa: mt7530: simplify core operations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The core_rmw() function calls core_read_mmd_indirect() to read the +requested register, and then calls core_write_mmd_indirect() to write the +requested value to the register. Because Clause 22 is used to access Clause +45 registers, some operations on core_write_mmd_indirect() are +unnecessarily run. Get rid of core_read_mmd_indirect() and +core_write_mmd_indirect(), and run only the necessary operations on +core_write() and core_rmw(). + +Reviewed-by: Daniel Golle +Tested-by: Daniel Golle +Signed-off-by: Arınç ÜNAL +Signed-off-by: Paolo Abeni +--- + drivers/net/dsa/mt7530.c | 108 ++++++++++++++++----------------------- + 1 file changed, 43 insertions(+), 65 deletions(-) + +--- a/drivers/net/dsa/mt7530.c ++++ b/drivers/net/dsa/mt7530.c +@@ -74,116 +74,94 @@ static const struct mt7530_mib_desc mt75 + MIB_DESC(1, 0xb8, "RxArlDrop"), + }; + +-/* Since phy_device has not yet been created and +- * phy_{read,write}_mmd_indirect is not available, we provide our own +- * core_{read,write}_mmd_indirect with core_{clear,write,set} wrappers +- * to complete this function. +- */ +-static int +-core_read_mmd_indirect(struct mt7530_priv *priv, int prtad, int devad) ++static void ++mt7530_mutex_lock(struct mt7530_priv *priv) ++{ ++ if (priv->bus) ++ mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); ++} ++ ++static void ++mt7530_mutex_unlock(struct mt7530_priv *priv) ++{ ++ if (priv->bus) ++ mutex_unlock(&priv->bus->mdio_lock); ++} ++ ++static void ++core_write(struct mt7530_priv *priv, u32 reg, u32 val) + { + struct mii_bus *bus = priv->bus; +- int value, ret; ++ int ret; ++ ++ mt7530_mutex_lock(priv); + + /* Write the desired MMD Devad */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad); ++ MII_MMD_CTRL, MDIO_MMD_VEND2); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, prtad); ++ MII_MMD_DATA, reg); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); ++ MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + +- /* Read the content of the MMD's selected register */ +- value = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA); +- +- return value; ++ /* Write the data into MMD's selected register */ ++ ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA, val); + err: +- dev_err(&bus->dev, "failed to read mmd register\n"); ++ if (ret < 0) ++ dev_err(&bus->dev, "failed to write mmd register\n"); + +- return ret; ++ mt7530_mutex_unlock(priv); + } + +-static int +-core_write_mmd_indirect(struct mt7530_priv *priv, int prtad, +- int devad, u32 data) ++static void ++core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) + { + struct mii_bus *bus = priv->bus; ++ u32 val; + int ret; + ++ mt7530_mutex_lock(priv); ++ + /* Write the desired MMD Devad */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad); ++ MII_MMD_CTRL, MDIO_MMD_VEND2); + if (ret < 0) + goto err; + + /* Write the desired MMD register address */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, prtad); ++ MII_MMD_DATA, reg); + if (ret < 0) + goto err; + + /* Select the Function : DATA with no post increment */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_CTRL, devad | MII_MMD_CTRL_NOINCR); ++ MII_MMD_CTRL, MDIO_MMD_VEND2 | MII_MMD_CTRL_NOINCR); + if (ret < 0) + goto err; + ++ /* Read the content of the MMD's selected register */ ++ val = bus->read(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), ++ MII_MMD_DATA); ++ val &= ~mask; ++ val |= set; + /* Write the data into MMD's selected register */ + ret = bus->write(bus, MT753X_CTRL_PHY_ADDR(priv->mdiodev->addr), +- MII_MMD_DATA, data); ++ MII_MMD_DATA, val); + err: + if (ret < 0) +- dev_err(&bus->dev, +- "failed to write mmd register\n"); +- return ret; +-} +- +-static void +-mt7530_mutex_lock(struct mt7530_priv *priv) +-{ +- if (priv->bus) +- mutex_lock_nested(&priv->bus->mdio_lock, MDIO_MUTEX_NESTED); +-} +- +-static void +-mt7530_mutex_unlock(struct mt7530_priv *priv) +-{ +- if (priv->bus) +- mutex_unlock(&priv->bus->mdio_lock); +-} +- +-static void +-core_write(struct mt7530_priv *priv, u32 reg, u32 val) +-{ +- mt7530_mutex_lock(priv); +- +- core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); +- +- mt7530_mutex_unlock(priv); +-} +- +-static void +-core_rmw(struct mt7530_priv *priv, u32 reg, u32 mask, u32 set) +-{ +- u32 val; +- +- mt7530_mutex_lock(priv); +- +- val = core_read_mmd_indirect(priv, reg, MDIO_MMD_VEND2); +- val &= ~mask; +- val |= set; +- core_write_mmd_indirect(priv, reg, MDIO_MMD_VEND2, val); ++ dev_err(&bus->dev, "failed to write mmd register\n"); + + mt7530_mutex_unlock(priv); + }