[openwrt/openwrt] generic: 6.1, 6.6: mt7530: import accepted patches

LEDE Commits lede-commits at lists.infradead.org
Wed Apr 24 13:06:33 PDT 2024


dangole pushed a commit to openwrt/openwrt.git, branch main:
https://git.openwrt.org/ac8bfe316b816e9b40e58da55e44197f5b395dd2

commit ac8bfe316b816e9b40e58da55e44197f5b395dd2
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Tue Apr 23 13:11:52 2024 +0100

    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 <daniel at makrotopia.org>
---
 ....10-net-dsa-introduce-dsa_phylink_to_port.patch |  99 +++++++++
 ...ow-DSA-switch-drivers-to-provide-their-ow.patch | 117 ++++++++++
 ...-mt7530-provide-own-phylink-MAC-operations.patc | 135 ++++++++++++
 ...530-fix-mirroring-frames-received-on-loca.patch |  70 ++++++
 ...530-fix-port-mirroring-for-MT7988-SoC-swi.patch |  49 +++++
 ...530-mdio-read-PHY-address-of-switch-from-.patch | 238 +++++++++++++++++++++
 ...0-net-dsa-mt7530-simplify-core-operations.patch | 186 ++++++++++++++++
 ....10-net-dsa-introduce-dsa_phylink_to_port.patch |  90 ++++++++
 ...ow-DSA-switch-drivers-to-provide-their-ow.patch | 119 +++++++++++
 ...mt7530-provide-own-phylink-MAC-operations.patch | 135 ++++++++++++
 ...530-fix-mirroring-frames-received-on-loca.patch |  70 ++++++
 ...530-fix-port-mirroring-for-MT7988-SoC-swi.patch |  49 +++++
 ...530-mdio-read-PHY-address-of-switch-from-.patch | 238 +++++++++++++++++++++
 ...0-net-dsa-mt7530-simplify-core-operations.patch | 186 ++++++++++++++++
 14 files changed, 1781 insertions(+)

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)" <rmk+kernel at armlinux.org.uk>
+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 <andrew at lunn.ch>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Link: https://lore.kernel.org/r/E1rudqA-006K9B-85@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ 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)" <rmk+kernel at armlinux.org.uk>
+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) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://lore.kernel.org/r/E1rudqF-006K9H-Cc@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ 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)" <rmk+kernel at armlinux.org.uk>
+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) <rmk+kernel at armlinux.org.uk>
+Tested-by: Arınç ÜNAL <arinc.unal at arinc9.com>
+Link: https://lore.kernel.org/r/E1rvIco-006bQu-Fq@rmk-PC.armlinux.org.uk
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <arinc.unal at arinc9.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <arinc.unal at arinc9.com>
+Acked-by: Daniel Golle <daniel at makrotopia.org>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <daniel at makrotopia.org>
+Tested-by: Daniel Golle <daniel at makrotopia.org>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Signed-off-by: Arınç ÜNAL <arinc.unal at arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <daniel at makrotopia.org>
+Tested-by: Daniel Golle <daniel at makrotopia.org>
+Signed-off-by: Arınç ÜNAL <arinc.unal at arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ 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)" <rmk+kernel at armlinux.org.uk>
+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 <andrew at lunn.ch>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Link: https://lore.kernel.org/r/E1rudqA-006K9B-85@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ 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)" <rmk+kernel at armlinux.org.uk>
+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) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Link: https://lore.kernel.org/r/E1rudqF-006K9H-Cc@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ 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)" <rmk+kernel at armlinux.org.uk>
+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) <rmk+kernel at armlinux.org.uk>
+Tested-by: Arınç ÜNAL <arinc.unal at arinc9.com>
+Link: https://lore.kernel.org/r/E1rvIco-006bQu-Fq@rmk-PC.armlinux.org.uk
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <arinc.unal at arinc9.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <arinc.unal at arinc9.com>
+Acked-by: Daniel Golle <daniel at makrotopia.org>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <daniel at makrotopia.org>
+Tested-by: Daniel Golle <daniel at makrotopia.org>
+Reviewed-by: Florian Fainelli <florian.fainelli at broadcom.com>
+Signed-off-by: Arınç ÜNAL <arinc.unal at arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ 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?= <arinc.unal at arinc9.com>
+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 <daniel at makrotopia.org>
+Tested-by: Daniel Golle <daniel at makrotopia.org>
+Signed-off-by: Arınç ÜNAL <arinc.unal at arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ 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);
+ }




More information about the lede-commits mailing list