[openwrt/openwrt] kernel: backport generic phylink validate

LEDE Commits lede-commits at lists.infradead.org
Tue Aug 30 12:48:22 PDT 2022


dangole pushed a commit to openwrt/openwrt.git, branch master:
https://git.openwrt.org/aab466f422500842adb62ddb7b1357e2e123ebb2

commit aab466f422500842adb62ddb7b1357e2e123ebb2
Author: Daniel Golle <daniel at makrotopia.org>
AuthorDate: Mon Jul 25 02:31:20 2022 +0200

    kernel: backport generic phylink validate
    
    Backport generic phylink validate series and make use of it for
    mtk_eth_soc Ethernet driver as well as mt7530 DSA driver.
    
    Signed-off-by: Daniel Golle <daniel at makrotopia.org>
---
 ...et-phylink-add-MAC-phy_interface_t-bitmap.patch |  24 ++
 ...-use-supported_interfaces-for-phylink-val.patch |  98 ++++++
 ...-dsa-populate-supported_interfaces-member.patch |  63 ++++
 ...5.17-net-dsa-consolidate-phylink-creation.patch | 149 ++++++++
 ...lace-phylink_get_interfaces-with-phylink_.patch |  51 +++
 ...sa-add-support-for-phylink-mac_select_pcs.patch |  59 ++++
 ...et-phy-add-phy_interface_t-bitmap-support.patch |  61 ++++
 ...-add-mac_select_pcs-method-to-phylink_mac.patch | 197 +++++++++++
 ...ylink-add-generic-validate-implementation.patch | 341 ++++++++++++++++++
 ...roduce-helpers-for-iterating-through-port.patch |  68 ++++
 ...v5.17-net-phylink-add-pcs_validate-method.patch | 106 ++++++
 ...hylink-add-legacy_pre_march2020-indicator.patch |  43 +++
 ...-mark-DSA-phylink-as-legacy_pre_march2020.patch |  36 ++
 ...5.17-net-phylink-use-legacy_pre_march2020.patch | 115 ++++++
 ..._soc-populate-supported_interfaces-member.patch |  43 +++
 ..._soc-remove-interface-checks-in-mtk_valid.patch |  75 ++++
 ..._soc-drop-use-of-phylink_helper_basex_spe.patch |  42 +++
 ...-mtk_eth_soc-use-phylink_generic_validate.patch |  84 +++++
 ..._soc-mark-as-a-legacy_pre_march2020-drive.patch |  29 ++
 ..._soc-remove-a-copy-of-the-NAPI_POLL_WEIGH.patch |  40 +++
 ...-v5.19-mtk_eth_soc-remove-unused-mac-mode.patch |  35 ++
 ...net-mtk_eth_soc-remove-unused-sgmii-flags.patch |  40 +++
 ..._soc-add-mask-and-update-PCS-speed-defini.patch |  40 +++
 ...-mtk_eth_soc-correct-802.3z-speed-setting.patch |  60 ++++
 ...mtk_eth_soc-correct-802.3z-duplex-setting.patch | 101 ++++++
 ..._soc-stop-passing-phylink-state-to-sgmii-.patch |  60 ++++
 ...-net-mtk_eth_soc-provide-mtk_sgmii_config.patch |  89 +++++
 ..._soc-add-fixme-comment-for-state-speed-us.patch |  38 ++
 ...th_soc-move-MAC_MCR-setting-to-mac_finish.patch |  79 +++++
 ..._soc-move-restoration-of-SYSCFG0-to-mac_f.patch |  57 +++
 ..._soc-convert-code-structure-to-suit-split.patch | 254 ++++++++++++++
 ..._eth_soc-partially-convert-to-phylink_pcs.patch | 262 ++++++++++++++
 ...530-iterate-using-dsa_switch_for_each_use.patch | 106 ++++++
 ...530-populate-supported_interfaces-and-mac.patch | 166 +++++++++
 ...19-net-dsa-mt7530-remove-interface-checks.patch | 172 +++++++++
 ...530-drop-use-of-phylink_helper_basex_spee.patch |  34 ++
 ...530-only-indicate-linkmodes-that-can-be-s.patch |  86 +++++
 ...t7530-switch-to-use-phylink_get_linkmodes.patch | 131 +++++++
 ...a-mt7530-partially-convert-to-phylink_pcs.patch | 385 +++++++++++++++++++++
 ...530-move-autoneg-handling-to-PCS-validati.patch |  80 +++++
 ...9-v5.19-net-dsa-mt7530-mark-as-non-legacy.patch |  34 ++
 ...-dsa-mt753x-fix-pcs-conversion-regression.patch | 116 +++++++
 ...dsa-mt7530-rework-mt7530_hw_vlan_-add-del.patch |  87 +++++
 ...6.0-net-dsa-mt7530-rework-mt753-01-_setup.patch |  75 ++++
 ...530-get-cpu-port-via-dp-cpu_dp-instead-of.patch | 117 +++++++
 ...rder-PHY-initialization-with-MTU-setup-in.patch |   4 +-
 ...ge-rtnl_lock-sections-in-dsa_slave_create.patch |   2 +-
 ...vide-switch-operations-for-tracking-the-m.patch |   6 +-
 ...ethernet-mtk_eth_soc-enable-threaded-NAPI.patch |   8 +-
 ...-add-detach-callback-to-struct-phy_driver.patch |   2 +-
 ...-net-mediatek-add-flow-offload-for-mt7623.patch |   2 +-
 ...t-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch |   2 +-
 ...t-ethernet-mtk_eth_soc-announce-2500baseT.patch |  10 -
 ...-net-ethernet-mediatek-support-net-labels.patch |   4 +-
 ...et-phy-simplify-phy_link_change-arguments.patch |   4 +-
 .../721-NET-no-auto-carrier-off-support.patch      |   2 +-
 56 files changed, 4446 insertions(+), 28 deletions(-)

diff --git a/target/linux/generic/backport-5.15/703-01-v5.16-net-phylink-add-MAC-phy_interface_t-bitmap.patch b/target/linux/generic/backport-5.15/703-01-v5.16-net-phylink-add-MAC-phy_interface_t-bitmap.patch
new file mode 100644
index 0000000000..b72faec8d9
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-01-v5.16-net-phylink-add-MAC-phy_interface_t-bitmap.patch
@@ -0,0 +1,24 @@
+From 38c310eb46f5f80213a92093af11af270c209a76 Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel at armlinux.org.uk>
+Date: Tue, 26 Oct 2021 11:06:06 +0100
+Subject: [PATCH] net: phylink: add MAC phy_interface_t bitmap
+
+Add a phy_interface_t bitmap so the MAC driver can specifiy which PHY
+interface modes it supports.
+
+Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ include/linux/phylink.h | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -76,6 +76,7 @@ struct phylink_config {
+ 	bool ovr_an_inband;
+ 	void (*get_fixed_state)(struct phylink_config *config,
+ 				struct phylink_link_state *state);
++	DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
+ };
+ 
+ /**
diff --git a/target/linux/generic/backport-5.15/703-02-v5.16-net-phylink-use-supported_interfaces-for-phylink-val.patch b/target/linux/generic/backport-5.15/703-02-v5.16-net-phylink-use-supported_interfaces-for-phylink-val.patch
new file mode 100644
index 0000000000..8996fc8d45
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-02-v5.16-net-phylink-use-supported_interfaces-for-phylink-val.patch
@@ -0,0 +1,98 @@
+From d25f3a74f30aace819163dfa54f2a4b8ca1dc932 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 26 Oct 2021 11:06:11 +0100
+Subject: [PATCH] net: phylink: use supported_interfaces for phylink
+ validation
+
+If the network device supplies a supported interface bitmap, we can use
+that during phylink's validation to simplify MAC drivers in two ways by
+using the supported_interfaces bitmap to:
+
+1. reject unsupported interfaces before calling into the MAC driver.
+2. generate the set of all supported link modes across all supported
+   interfaces (used mainly for SFP, but also some 10G PHYs.)
+
+Suggested-by: Sean Anderson <sean.anderson at seco.com>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/phy/phylink.c | 36 ++++++++++++++++++++++++++++++++++++
+ include/linux/phylink.h   | 12 ++++++++++--
+ 2 files changed, 46 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -155,9 +155,45 @@ static const char *phylink_an_mode_str(u
+ 	return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
+ }
+ 
++static int phylink_validate_any(struct phylink *pl, unsigned long *supported,
++				struct phylink_link_state *state)
++{
++	__ETHTOOL_DECLARE_LINK_MODE_MASK(all_adv) = { 0, };
++	__ETHTOOL_DECLARE_LINK_MODE_MASK(all_s) = { 0, };
++	__ETHTOOL_DECLARE_LINK_MODE_MASK(s);
++	struct phylink_link_state t;
++	int intf;
++
++	for (intf = 0; intf < PHY_INTERFACE_MODE_MAX; intf++) {
++		if (test_bit(intf, pl->config->supported_interfaces)) {
++			linkmode_copy(s, supported);
++
++			t = *state;
++			t.interface = intf;
++			pl->mac_ops->validate(pl->config, s, &t);
++			linkmode_or(all_s, all_s, s);
++			linkmode_or(all_adv, all_adv, t.advertising);
++		}
++	}
++
++	linkmode_copy(supported, all_s);
++	linkmode_copy(state->advertising, all_adv);
++
++	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
++}
++
+ static int phylink_validate(struct phylink *pl, unsigned long *supported,
+ 			    struct phylink_link_state *state)
+ {
++	if (!phy_interface_empty(pl->config->supported_interfaces)) {
++		if (state->interface == PHY_INTERFACE_MODE_NA)
++			return phylink_validate_any(pl, supported, state);
++
++		if (!test_bit(state->interface,
++			      pl->config->supported_interfaces))
++			return -EINVAL;
++	}
++
+ 	pl->mac_ops->validate(pl->config, supported, state);
+ 
+ 	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -67,6 +67,8 @@ enum phylink_op_type {
+  * @ovr_an_inband: if true, override PCS to MLO_AN_INBAND
+  * @get_fixed_state: callback to execute to determine the fixed link state,
+  *		     if MAC link is at %MLO_AN_FIXED mode.
++ * @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx
++ *                        are supported by the MAC/PCS.
+  */
+ struct phylink_config {
+ 	struct device *dev;
+@@ -134,8 +136,14 @@ struct phylink_mac_ops {
+  * based on @state->advertising and/or @state->speed and update
+  * @state->interface accordingly. See phylink_helper_basex_speed().
+  *
+- * When @state->interface is %PHY_INTERFACE_MODE_NA, phylink expects the
+- * MAC driver to return all supported link modes.
++ * When @config->supported_interfaces has been set, phylink will iterate
++ * over the supported interfaces to determine the full capability of the
++ * MAC. The validation function must not print errors if @state->interface
++ * is set to an unexpected value.
++ *
++ * When @config->supported_interfaces is empty, phylink will call this
++ * function with @state->interface set to %PHY_INTERFACE_MODE_NA, and
++ * expects the MAC driver to return all supported link modes.
+  *
+  * If the @state->interface mode is not supported, then the @supported
+  * mask must be cleared.
diff --git a/target/linux/generic/backport-5.15/703-03-v5.16-net-dsa-populate-supported_interfaces-member.patch b/target/linux/generic/backport-5.15/703-03-v5.16-net-dsa-populate-supported_interfaces-member.patch
new file mode 100644
index 0000000000..83d1f7ee7c
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-03-v5.16-net-dsa-populate-supported_interfaces-member.patch
@@ -0,0 +1,63 @@
+From c07c6e8eb4b38bae921f9e2f108d1e7f8e14226e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Marek=20Beh=C3=BAn?= <kabel at kernel.org>
+Date: Thu, 28 Oct 2021 18:00:14 +0100
+Subject: [PATCH] net: dsa: populate supported_interfaces member
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Add a new DSA switch operation, phylink_get_interfaces, which should
+fill in which PHY_INTERFACE_MODE_* are supported by given port.
+
+Use this before phylink_create() to fill phylinks supported_interfaces
+member, allowing phylink to determine which PHY_INTERFACE_MODEs are
+supported.
+
+Signed-off-by: Marek Behún <kabel at kernel.org>
+[tweaked patch and description to add more complete support -- rmk]
+Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ include/net/dsa.h | 2 ++
+ net/dsa/port.c    | 4 ++++
+ net/dsa/slave.c   | 4 ++++
+ 3 files changed, 10 insertions(+)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -626,6 +626,8 @@ struct dsa_switch_ops {
+ 	/*
+ 	 * PHYLINK integration
+ 	 */
++	void	(*phylink_get_interfaces)(struct dsa_switch *ds, int port,
++					  unsigned long *supported_interfaces);
+ 	void	(*phylink_validate)(struct dsa_switch *ds, int port,
+ 				    unsigned long *supported,
+ 				    struct phylink_link_state *state);
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -1172,6 +1172,10 @@ static int dsa_port_phylink_register(str
+ 	dp->pl_config.type = PHYLINK_DEV;
+ 	dp->pl_config.pcs_poll = ds->pcs_poll;
+ 
++	if (ds->ops->phylink_get_interfaces)
++		ds->ops->phylink_get_interfaces(ds, dp->index,
++					dp->pl_config.supported_interfaces);
++
+ 	dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn),
+ 				mode, &dsa_port_phylink_mac_ops);
+ 	if (IS_ERR(dp->pl)) {
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -1837,6 +1837,10 @@ static int dsa_slave_phy_setup(struct ne
+ 		dp->pl_config.poll_fixed_state = true;
+ 	}
+ 
++	if (ds->ops->phylink_get_interfaces)
++		ds->ops->phylink_get_interfaces(ds, dp->index,
++					dp->pl_config.supported_interfaces);
++
+ 	dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode,
+ 				&dsa_port_phylink_mac_ops);
+ 	if (IS_ERR(dp->pl)) {
diff --git a/target/linux/generic/backport-5.15/703-04-v5.17-net-dsa-consolidate-phylink-creation.patch b/target/linux/generic/backport-5.15/703-04-v5.17-net-dsa-consolidate-phylink-creation.patch
new file mode 100644
index 0000000000..8b58c83312
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-04-v5.17-net-dsa-consolidate-phylink-creation.patch
@@ -0,0 +1,149 @@
+From 21bd64bd717dedac96f53b668144cbe37d3c12d4 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 30 Nov 2021 13:09:55 +0000
+Subject: [PATCH] net: dsa: consolidate phylink creation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The code in port.c and slave.c creating the phylink instance is very
+similar - let's consolidate this into a single function.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Marek Behún <kabel at kernel.org>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ net/dsa/dsa_priv.h |  2 +-
+ net/dsa/port.c     | 44 ++++++++++++++++++++++++++++----------------
+ net/dsa/slave.c    | 19 +++----------------
+ 3 files changed, 32 insertions(+), 33 deletions(-)
+
+--- a/net/dsa/dsa_priv.h
++++ b/net/dsa/dsa_priv.h
+@@ -260,13 +260,13 @@ int dsa_port_mrp_add_ring_role(const str
+ 			       const struct switchdev_obj_ring_role_mrp *mrp);
+ int dsa_port_mrp_del_ring_role(const struct dsa_port *dp,
+ 			       const struct switchdev_obj_ring_role_mrp *mrp);
++int dsa_port_phylink_create(struct dsa_port *dp);
+ int dsa_port_link_register_of(struct dsa_port *dp);
+ void dsa_port_link_unregister_of(struct dsa_port *dp);
+ int dsa_port_hsr_join(struct dsa_port *dp, struct net_device *hsr);
+ void dsa_port_hsr_leave(struct dsa_port *dp, struct net_device *hsr);
+ int dsa_port_tag_8021q_vlan_add(struct dsa_port *dp, u16 vid, bool broadcast);
+ void dsa_port_tag_8021q_vlan_del(struct dsa_port *dp, u16 vid, bool broadcast);
+-extern const struct phylink_mac_ops dsa_port_phylink_mac_ops;
+ 
+ static inline bool dsa_port_offloads_bridge_port(struct dsa_port *dp,
+ 						 const struct net_device *dev)
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -1076,7 +1076,7 @@ static void dsa_port_phylink_mac_link_up
+ 				     speed, duplex, tx_pause, rx_pause);
+ }
+ 
+-const struct phylink_mac_ops dsa_port_phylink_mac_ops = {
++static const struct phylink_mac_ops dsa_port_phylink_mac_ops = {
+ 	.validate = dsa_port_phylink_validate,
+ 	.mac_pcs_get_state = dsa_port_phylink_mac_pcs_get_state,
+ 	.mac_config = dsa_port_phylink_mac_config,
+@@ -1085,6 +1085,30 @@ const struct phylink_mac_ops dsa_port_ph
+ 	.mac_link_up = dsa_port_phylink_mac_link_up,
+ };
+ 
++int dsa_port_phylink_create(struct dsa_port *dp)
++{
++	struct dsa_switch *ds = dp->ds;
++	phy_interface_t mode;
++	int err;
++
++	err = of_get_phy_mode(dp->dn, &mode);
++	if (err)
++		mode = PHY_INTERFACE_MODE_NA;
++
++	if (ds->ops->phylink_get_interfaces)
++		ds->ops->phylink_get_interfaces(ds, dp->index,
++					dp->pl_config.supported_interfaces);
++
++	dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn),
++				mode, &dsa_port_phylink_mac_ops);
++	if (IS_ERR(dp->pl)) {
++		pr_err("error creating PHYLINK: %ld\n", PTR_ERR(dp->pl));
++		return PTR_ERR(dp->pl);
++	}
++
++	return 0;
++}
++
+ static int dsa_port_setup_phy_of(struct dsa_port *dp, bool enable)
+ {
+ 	struct dsa_switch *ds = dp->ds;
+@@ -1161,27 +1185,15 @@ static int dsa_port_phylink_register(str
+ {
+ 	struct dsa_switch *ds = dp->ds;
+ 	struct device_node *port_dn = dp->dn;
+-	phy_interface_t mode;
+ 	int err;
+ 
+-	err = of_get_phy_mode(port_dn, &mode);
+-	if (err)
+-		mode = PHY_INTERFACE_MODE_NA;
+-
+ 	dp->pl_config.dev = ds->dev;
+ 	dp->pl_config.type = PHYLINK_DEV;
+ 	dp->pl_config.pcs_poll = ds->pcs_poll;
+ 
+-	if (ds->ops->phylink_get_interfaces)
+-		ds->ops->phylink_get_interfaces(ds, dp->index,
+-					dp->pl_config.supported_interfaces);
+-
+-	dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn),
+-				mode, &dsa_port_phylink_mac_ops);
+-	if (IS_ERR(dp->pl)) {
+-		pr_err("error creating PHYLINK: %ld\n", PTR_ERR(dp->pl));
+-		return PTR_ERR(dp->pl);
+-	}
++	err = dsa_port_phylink_create(dp);
++	if (err)
++		return err;
+ 
+ 	err = phylink_of_phy_connect(dp->pl, port_dn, 0);
+ 	if (err && err != -ENODEV) {
+--- a/net/dsa/slave.c
++++ b/net/dsa/slave.c
+@@ -1817,14 +1817,9 @@ static int dsa_slave_phy_setup(struct ne
+ 	struct dsa_port *dp = dsa_slave_to_port(slave_dev);
+ 	struct device_node *port_dn = dp->dn;
+ 	struct dsa_switch *ds = dp->ds;
+-	phy_interface_t mode;
+ 	u32 phy_flags = 0;
+ 	int ret;
+ 
+-	ret = of_get_phy_mode(port_dn, &mode);
+-	if (ret)
+-		mode = PHY_INTERFACE_MODE_NA;
+-
+ 	dp->pl_config.dev = &slave_dev->dev;
+ 	dp->pl_config.type = PHYLINK_NETDEV;
+ 
+@@ -1837,17 +1832,9 @@ static int dsa_slave_phy_setup(struct ne
+ 		dp->pl_config.poll_fixed_state = true;
+ 	}
+ 
+-	if (ds->ops->phylink_get_interfaces)
+-		ds->ops->phylink_get_interfaces(ds, dp->index,
+-					dp->pl_config.supported_interfaces);
+-
+-	dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(port_dn), mode,
+-				&dsa_port_phylink_mac_ops);
+-	if (IS_ERR(dp->pl)) {
+-		netdev_err(slave_dev,
+-			   "error creating PHYLINK: %ld\n", PTR_ERR(dp->pl));
+-		return PTR_ERR(dp->pl);
+-	}
++	ret = dsa_port_phylink_create(dp);
++	if (ret)
++		return ret;
+ 
+ 	if (ds->ops->get_phy_flags)
+ 		phy_flags = ds->ops->get_phy_flags(ds, dp->index);
diff --git a/target/linux/generic/backport-5.15/703-05-v5.17-net-dsa-replace-phylink_get_interfaces-with-phylink_.patch b/target/linux/generic/backport-5.15/703-05-v5.17-net-dsa-replace-phylink_get_interfaces-with-phylink_.patch
new file mode 100644
index 0000000000..4cea5994da
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-05-v5.17-net-dsa-replace-phylink_get_interfaces-with-phylink_.patch
@@ -0,0 +1,51 @@
+From 072eea6c22b2af680c3949e64f9adde278c71e68 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 30 Nov 2021 13:10:01 +0000
+Subject: [PATCH] net: dsa: replace phylink_get_interfaces() with
+ phylink_get_caps()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Phylink needs slightly more information than phylink_get_interfaces()
+allows us to get from the DSA drivers - we need the MAC capabilities.
+Replace the phylink_get_interfaces() method with phylink_get_caps() to
+allow DSA drivers to fill in the phylink_config MAC capabilities field
+as well.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Marek Behún <kabel at kernel.org>
+Reviewed-by: Andrew Lunn <andrew at lunn.ch>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ include/net/dsa.h | 4 ++--
+ net/dsa/port.c    | 5 ++---
+ 2 files changed, 4 insertions(+), 5 deletions(-)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -626,8 +626,8 @@ struct dsa_switch_ops {
+ 	/*
+ 	 * PHYLINK integration
+ 	 */
+-	void	(*phylink_get_interfaces)(struct dsa_switch *ds, int port,
+-					  unsigned long *supported_interfaces);
++	void	(*phylink_get_caps)(struct dsa_switch *ds, int port,
++				    struct phylink_config *config);
+ 	void	(*phylink_validate)(struct dsa_switch *ds, int port,
+ 				    unsigned long *supported,
+ 				    struct phylink_link_state *state);
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -1095,9 +1095,8 @@ int dsa_port_phylink_create(struct dsa_p
+ 	if (err)
+ 		mode = PHY_INTERFACE_MODE_NA;
+ 
+-	if (ds->ops->phylink_get_interfaces)
+-		ds->ops->phylink_get_interfaces(ds, dp->index,
+-					dp->pl_config.supported_interfaces);
++	if (ds->ops->phylink_get_caps)
++		ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config);
+ 
+ 	dp->pl = phylink_create(&dp->pl_config, of_fwnode_handle(dp->dn),
+ 				mode, &dsa_port_phylink_mac_ops);
diff --git a/target/linux/generic/backport-5.15/703-06-v5.18-net-dsa-add-support-for-phylink-mac_select_pcs.patch b/target/linux/generic/backport-5.15/703-06-v5.18-net-dsa-add-support-for-phylink-mac_select_pcs.patch
new file mode 100644
index 0000000000..a28d14d27a
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-06-v5.18-net-dsa-add-support-for-phylink-mac_select_pcs.patch
@@ -0,0 +1,59 @@
+From bde018222c6b084ac32933a9f933581dd83da18e Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Thu, 17 Feb 2022 18:30:35 +0000
+Subject: [PATCH] net: dsa: add support for phylink mac_select_pcs()
+
+Add DSA support for the phylink mac_select_pcs() method so DSA drivers
+can return provide phylink with the appropriate PCS for the PHY
+interface mode.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ include/net/dsa.h |  3 +++
+ net/dsa/port.c    | 15 +++++++++++++++
+ 2 files changed, 18 insertions(+)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -631,6 +631,9 @@ struct dsa_switch_ops {
+ 	void	(*phylink_validate)(struct dsa_switch *ds, int port,
+ 				    unsigned long *supported,
+ 				    struct phylink_link_state *state);
++	struct phylink_pcs *(*phylink_mac_select_pcs)(struct dsa_switch *ds,
++						      int port,
++						      phy_interface_t iface);
+ 	int	(*phylink_mac_link_state)(struct dsa_switch *ds, int port,
+ 					  struct phylink_link_state *state);
+ 	void	(*phylink_mac_config)(struct dsa_switch *ds, int port,
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -1012,6 +1012,20 @@ static void dsa_port_phylink_mac_pcs_get
+ 	}
+ }
+ 
++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_switch *ds = dp->ds;
++	struct phylink_pcs *pcs = NULL;
++
++	if (ds->ops->phylink_mac_select_pcs)
++		pcs = ds->ops->phylink_mac_select_pcs(ds, dp->index, interface);
++
++	return pcs;
++}
++
+ static void dsa_port_phylink_mac_config(struct phylink_config *config,
+ 					unsigned int mode,
+ 					const struct phylink_link_state *state)
+@@ -1078,6 +1092,7 @@ static void dsa_port_phylink_mac_link_up
+ 
+ static const struct phylink_mac_ops dsa_port_phylink_mac_ops = {
+ 	.validate = dsa_port_phylink_validate,
++	.mac_select_pcs = dsa_port_phylink_mac_select_pcs,
+ 	.mac_pcs_get_state = dsa_port_phylink_mac_pcs_get_state,
+ 	.mac_config = dsa_port_phylink_mac_config,
+ 	.mac_an_restart = dsa_port_phylink_mac_an_restart,
diff --git a/target/linux/generic/backport-5.15/703-07-v5.16-net-phy-add-phy_interface_t-bitmap-support.patch b/target/linux/generic/backport-5.15/703-07-v5.16-net-phy-add-phy_interface_t-bitmap-support.patch
new file mode 100644
index 0000000000..1a7817b0f9
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-07-v5.16-net-phy-add-phy_interface_t-bitmap-support.patch
@@ -0,0 +1,61 @@
+From 8e20f591f204f8db7f1182918f8e2285d3f589e0 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 26 Oct 2021 11:06:01 +0100
+Subject: [PATCH] net: phy: add phy_interface_t bitmap support
+
+Add support for a bitmap for phy interface modes, which includes:
+- a macro to declare the interface bitmap
+- an inline helper to zero the interface bitmap
+- an inline helper to detect an empty interface bitmap
+- inline helpers to do a bitwise AND and OR operations on two interface
+  bitmaps
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ include/linux/phy.h | 34 ++++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+
+--- a/include/linux/phy.h
++++ b/include/linux/phy.h
+@@ -155,6 +155,40 @@ typedef enum {
+ 	PHY_INTERFACE_MODE_MAX,
+ } phy_interface_t;
+ 
++/* PHY interface mode bitmap handling */
++#define DECLARE_PHY_INTERFACE_MASK(name) \
++	DECLARE_BITMAP(name, PHY_INTERFACE_MODE_MAX)
++
++static inline void phy_interface_zero(unsigned long *intf)
++{
++	bitmap_zero(intf, PHY_INTERFACE_MODE_MAX);
++}
++
++static inline bool phy_interface_empty(const unsigned long *intf)
++{
++	return bitmap_empty(intf, PHY_INTERFACE_MODE_MAX);
++}
++
++static inline void phy_interface_and(unsigned long *dst, const unsigned long *a,
++				     const unsigned long *b)
++{
++	bitmap_and(dst, a, b, PHY_INTERFACE_MODE_MAX);
++}
++
++static inline void phy_interface_or(unsigned long *dst, const unsigned long *a,
++				    const unsigned long *b)
++{
++	bitmap_or(dst, a, b, PHY_INTERFACE_MODE_MAX);
++}
++
++static inline void phy_interface_set_rgmii(unsigned long *intf)
++{
++	__set_bit(PHY_INTERFACE_MODE_RGMII, intf);
++	__set_bit(PHY_INTERFACE_MODE_RGMII_ID, intf);
++	__set_bit(PHY_INTERFACE_MODE_RGMII_RXID, intf);
++	__set_bit(PHY_INTERFACE_MODE_RGMII_TXID, intf);
++}
++
+ /*
+  * phy_supported_speeds - return all speeds currently supported by a PHY device
+  */
diff --git a/target/linux/generic/backport-5.15/703-08-v5.17-net-phylink-add-mac_select_pcs-method-to-phylink_mac.patch b/target/linux/generic/backport-5.15/703-08-v5.17-net-phylink-add-mac_select_pcs-method-to-phylink_mac.patch
new file mode 100644
index 0000000000..e1cfc3f439
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-08-v5.17-net-phylink-add-mac_select_pcs-method-to-phylink_mac.patch
@@ -0,0 +1,197 @@
+From d1e86325af377129adb7fc6f34eb044ca6068b47 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 15 Dec 2021 15:34:15 +0000
+Subject: [PATCH] net: phylink: add mac_select_pcs() method to phylink_mac_ops
+
+mac_select_pcs() allows us to have an explicit point to query which
+PCS the MAC wishes to use for a particular PHY interface mode, thereby
+allowing us to add support to validate the link settings with the PCS.
+
+Phylink will also use this to select the PCS to be used during a major
+configuration event without the MAC driver needing to call
+phylink_set_pcs().
+
+Note that if mac_select_pcs() is present, the supported_interfaces
+bitmap must be filled in; this avoids mac_select_pcs() being called
+with PHY_INTERFACE_MODE_NA when we want to get support for all
+interface types. Phylink will return an error in phylink_create()
+unless this condition is satisfied.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/phy/phylink.c | 68 +++++++++++++++++++++++++++++++++------
+ include/linux/phylink.h   | 18 +++++++++++
+ 2 files changed, 77 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -155,6 +155,23 @@ static const char *phylink_an_mode_str(u
+ 	return mode < ARRAY_SIZE(modestr) ? modestr[mode] : "unknown";
+ }
+ 
++static int phylink_validate_mac_and_pcs(struct phylink *pl,
++					unsigned long *supported,
++					struct phylink_link_state *state)
++{
++	struct phylink_pcs *pcs;
++
++	if (pl->mac_ops->mac_select_pcs) {
++		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
++		if (IS_ERR(pcs))
++			return PTR_ERR(pcs);
++	}
++
++	pl->mac_ops->validate(pl->config, supported, state);
++
++	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
++}
++
+ static int phylink_validate_any(struct phylink *pl, unsigned long *supported,
+ 				struct phylink_link_state *state)
+ {
+@@ -170,9 +187,10 @@ static int phylink_validate_any(struct p
+ 
+ 			t = *state;
+ 			t.interface = intf;
+-			pl->mac_ops->validate(pl->config, s, &t);
+-			linkmode_or(all_s, all_s, s);
+-			linkmode_or(all_adv, all_adv, t.advertising);
++			if (!phylink_validate_mac_and_pcs(pl, s, &t)) {
++				linkmode_or(all_s, all_s, s);
++				linkmode_or(all_adv, all_adv, t.advertising);
++			}
+ 		}
+ 	}
+ 
+@@ -194,9 +212,7 @@ static int phylink_validate(struct phyli
+ 			return -EINVAL;
+ 	}
+ 
+-	pl->mac_ops->validate(pl->config, supported, state);
+-
+-	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
++	return phylink_validate_mac_and_pcs(pl, supported, state);
+ }
+ 
+ static int phylink_parse_fixedlink(struct phylink *pl,
+@@ -486,10 +502,21 @@ static void phylink_mac_pcs_an_restart(s
+ static void phylink_major_config(struct phylink *pl, bool restart,
+ 				  const struct phylink_link_state *state)
+ {
++	struct phylink_pcs *pcs = NULL;
+ 	int err;
+ 
+ 	phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
+ 
++	if (pl->mac_ops->mac_select_pcs) {
++		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
++		if (IS_ERR(pcs)) {
++			phylink_err(pl,
++				    "mac_select_pcs unexpectedly failed: %pe\n",
++				    pcs);
++			return;
++		}
++	}
++
+ 	if (pl->mac_ops->mac_prepare) {
+ 		err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
+ 					       state->interface);
+@@ -500,6 +527,12 @@ static void phylink_major_config(struct
+ 		}
+ 	}
+ 
++	/* If we have a new PCS, switch to the new PCS after preparing the MAC
++	 * for the change.
++	 */
++	if (pcs)
++		phylink_set_pcs(pl, pcs);
++
+ 	phylink_mac_config(pl, state);
+ 
+ 	if (pl->pcs_ops) {
+@@ -879,6 +912,14 @@ struct phylink *phylink_create(struct ph
+ 	struct phylink *pl;
+ 	int ret;
+ 
++	/* Validate the supplied configuration */
++	if (mac_ops->mac_select_pcs &&
++	    phy_interface_empty(config->supported_interfaces)) {
++		dev_err(config->dev,
++			"phylink: error: empty supported_interfaces but mac_select_pcs() method present\n");
++		return ERR_PTR(-EINVAL);
++	}
++
+ 	pl = kzalloc(sizeof(*pl), GFP_KERNEL);
+ 	if (!pl)
+ 		return ERR_PTR(-ENOMEM);
+@@ -946,9 +987,10 @@ EXPORT_SYMBOL_GPL(phylink_create);
+  * @pl: a pointer to a &struct phylink returned from phylink_create()
+  * @pcs: a pointer to the &struct phylink_pcs
+  *
+- * Bind the MAC PCS to phylink.  This may be called after phylink_create(),
+- * in mac_prepare() or mac_config() methods if it is desired to dynamically
+- * change the PCS.
++ * Bind the MAC PCS to phylink.  This may be called after phylink_create().
++ * If it is desired to dynamically change the PCS, then the preferred method
++ * is to use mac_select_pcs(), but it may also be called in mac_prepare()
++ * or mac_config().
+  *
+  * Please note that there are behavioural changes with the mac_config()
+  * callback if a PCS is present (denoting a newer setup) so removing a PCS
+@@ -959,6 +1001,14 @@ void phylink_set_pcs(struct phylink *pl,
+ {
+ 	pl->pcs = pcs;
+ 	pl->pcs_ops = pcs->ops;
++
++	if (!pl->phylink_disable_state &&
++	    pl->cfg_link_an_mode == MLO_AN_INBAND) {
++		if (pl->config->pcs_poll || pcs->poll)
++			mod_timer(&pl->link_poll, jiffies + HZ);
++		else
++			del_timer(&pl->link_poll);
++	}
+ }
+ EXPORT_SYMBOL_GPL(phylink_set_pcs);
+ 
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -84,6 +84,7 @@ struct phylink_config {
+ /**
+  * struct phylink_mac_ops - MAC operations structure.
+  * @validate: Validate and update the link configuration.
++ * @mac_select_pcs: Select a PCS for the interface mode.
+  * @mac_pcs_get_state: Read the current link state from the hardware.
+  * @mac_prepare: prepare for a major reconfiguration of the interface.
+  * @mac_config: configure the MAC for the selected mode and state.
+@@ -98,6 +99,8 @@ struct phylink_mac_ops {
+ 	void (*validate)(struct phylink_config *config,
+ 			 unsigned long *supported,
+ 			 struct phylink_link_state *state);
++	struct phylink_pcs *(*mac_select_pcs)(struct phylink_config *config,
++					      phy_interface_t interface);
+ 	void (*mac_pcs_get_state)(struct phylink_config *config,
+ 				  struct phylink_link_state *state);
+ 	int (*mac_prepare)(struct phylink_config *config, unsigned int mode,
+@@ -150,6 +153,21 @@ struct phylink_mac_ops {
+  */
+ void validate(struct phylink_config *config, unsigned long *supported,
+ 	      struct phylink_link_state *state);
++/**
++ * mac_select_pcs: Select a PCS for the interface mode.
++ * @config: a pointer to a &struct phylink_config.
++ * @interface: PHY interface mode for PCS
++ *
++ * Return the &struct phylink_pcs for the specified interface mode, or
++ * NULL if none is required, or an error pointer on error.
++ *
++ * This must not modify any state. It is used to query which PCS should
++ * be used. Phylink will use this during validation to ensure that the
++ * configuration is valid, and when setting a configuration to internally
++ * set the PCS that will be used.
++ */
++struct phylink_pcs *mac_select_pcs(struct phylink_config *config,
++				   phy_interface_t interface);
+ 
+ /**
+  * mac_pcs_get_state() - Read the current inband link state from the hardware
diff --git a/target/linux/generic/backport-5.15/703-09-v5.17-net-phylink-add-generic-validate-implementation.patch b/target/linux/generic/backport-5.15/703-09-v5.17-net-phylink-add-generic-validate-implementation.patch
new file mode 100644
index 0000000000..73c8b414da
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-09-v5.17-net-phylink-add-generic-validate-implementation.patch
@@ -0,0 +1,341 @@
+From 34ae2c09d46a2d0abd907e139b466f798e4095a8 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 15 Nov 2021 10:00:27 +0000
+Subject: [PATCH] net: phylink: add generic validate implementation
+
+Add a generic validate() implementation using the supported_interfaces
+and a bitmask of MAC pause/speed/duplex capabilities. This allows us
+to entirely eliminate many driver private validate() implementations.
+
+We expose the underlying phylink_get_linkmodes() function so that
+drivers which have special needs can still benefit from conversion.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/phy/phylink.c | 252 ++++++++++++++++++++++++++++++++++++++
+ include/linux/phylink.h   |  31 +++++
+ 2 files changed, 283 insertions(+)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -172,6 +172,258 @@ static int phylink_validate_mac_and_pcs(
+ 	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
+ }
+ 
++static void phylink_caps_to_linkmodes(unsigned long *linkmodes,
++				      unsigned long caps)
++{
++	if (caps & MAC_SYM_PAUSE)
++		__set_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes);
++
++	if (caps & MAC_ASYM_PAUSE)
++		__set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes);
++
++	if (caps & MAC_10HD)
++		__set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, linkmodes);
++
++	if (caps & MAC_10FD)
++		__set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, linkmodes);
++
++	if (caps & MAC_100HD) {
++		__set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT, linkmodes);
++	}
++
++	if (caps & MAC_100FD) {
++		__set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_1000HD)
++		__set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, linkmodes);
++
++	if (caps & MAC_1000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_2500FD) {
++		__set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_5000FD)
++		__set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, linkmodes);
++
++	if (caps & MAC_10000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_25000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_40000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_50000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_56000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_100000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_100000baseDR_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_200000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, linkmodes);
++	}
++
++	if (caps & MAC_400000FD) {
++		__set_bit(ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT,
++			  linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT, linkmodes);
++		__set_bit(ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT, linkmodes);
++	}
++}
++
++/**
++ * phylink_get_linkmodes() - get acceptable link modes
++ * @linkmodes: ethtool linkmode mask (must be already initialised)
++ * @interface: phy interface mode defined by &typedef phy_interface_t
++ * @mac_capabilities: bitmask of MAC capabilities
++ *
++ * Set all possible pause, speed and duplex linkmodes in @linkmodes that
++ * are supported by the @interface mode and @mac_capabilities. @linkmodes
++ * must have been initialised previously.
++ */
++void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface,
++			   unsigned long mac_capabilities)
++{
++	unsigned long caps = MAC_SYM_PAUSE | MAC_ASYM_PAUSE;
++
++	switch (interface) {
++	case PHY_INTERFACE_MODE_USXGMII:
++		caps |= MAC_10000FD | MAC_5000FD | MAC_2500FD;
++		fallthrough;
++
++	case PHY_INTERFACE_MODE_RGMII_TXID:
++	case PHY_INTERFACE_MODE_RGMII_RXID:
++	case PHY_INTERFACE_MODE_RGMII_ID:
++	case PHY_INTERFACE_MODE_RGMII:
++	case PHY_INTERFACE_MODE_QSGMII:
++	case PHY_INTERFACE_MODE_SGMII:
++	case PHY_INTERFACE_MODE_GMII:
++		caps |= MAC_1000HD | MAC_1000FD;
++		fallthrough;
++
++	case PHY_INTERFACE_MODE_REVRMII:
++	case PHY_INTERFACE_MODE_RMII:
++	case PHY_INTERFACE_MODE_REVMII:
++	case PHY_INTERFACE_MODE_MII:
++		caps |= MAC_10HD | MAC_10FD;
++		fallthrough;
++
++	case PHY_INTERFACE_MODE_100BASEX:
++		caps |= MAC_100HD | MAC_100FD;
++		break;
++
++	case PHY_INTERFACE_MODE_TBI:
++	case PHY_INTERFACE_MODE_MOCA:
++	case PHY_INTERFACE_MODE_RTBI:
++	case PHY_INTERFACE_MODE_1000BASEX:
++		caps |= MAC_1000HD;
++		fallthrough;
++	case PHY_INTERFACE_MODE_TRGMII:
++		caps |= MAC_1000FD;
++		break;
++
++	case PHY_INTERFACE_MODE_2500BASEX:
++		caps |= MAC_2500FD;
++		break;
++
++	case PHY_INTERFACE_MODE_5GBASER:
++		caps |= MAC_5000FD;
++		break;
++
++	case PHY_INTERFACE_MODE_XGMII:
++	case PHY_INTERFACE_MODE_RXAUI:
++	case PHY_INTERFACE_MODE_XAUI:
++	case PHY_INTERFACE_MODE_10GBASER:
++	case PHY_INTERFACE_MODE_10GKR:
++		caps |= MAC_10000FD;
++		break;
++
++	case PHY_INTERFACE_MODE_25GBASER:
++		caps |= MAC_25000FD;
++		break;
++
++	case PHY_INTERFACE_MODE_XLGMII:
++		caps |= MAC_40000FD;
++		break;
++
++	case PHY_INTERFACE_MODE_INTERNAL:
++		caps |= ~0;
++		break;
++
++	case PHY_INTERFACE_MODE_NA:
++	case PHY_INTERFACE_MODE_MAX:
++	case PHY_INTERFACE_MODE_SMII:
++		break;
++	}
++
++	phylink_caps_to_linkmodes(linkmodes, caps & mac_capabilities);
++}
++EXPORT_SYMBOL_GPL(phylink_get_linkmodes);
++
++/**
++ * phylink_generic_validate() - generic validate() callback implementation
++ * @config: a pointer to a &struct phylink_config.
++ * @supported: ethtool bitmask for supported link modes.
++ * @state: a pointer to a &struct phylink_link_state.
++ *
++ * Generic implementation of the validate() callback that MAC drivers can
++ * use when they pass the range of supported interfaces and MAC capabilities.
++ * This makes use of phylink_get_linkmodes().
++ */
++void phylink_generic_validate(struct phylink_config *config,
++			      unsigned long *supported,
++			      struct phylink_link_state *state)
++{
++	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
++
++	phylink_set_port_modes(mask);
++	phylink_set(mask, Autoneg);
++	phylink_get_linkmodes(mask, state->interface, config->mac_capabilities);
++
++	linkmode_and(supported, supported, mask);
++	linkmode_and(state->advertising, state->advertising, mask);
++}
++EXPORT_SYMBOL_GPL(phylink_generic_validate);
++
+ static int phylink_validate_any(struct phylink *pl, unsigned long *supported,
+ 				struct phylink_link_state *state)
+ {
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -20,6 +20,29 @@ enum {
+ 	MLO_AN_PHY = 0,	/* Conventional PHY */
+ 	MLO_AN_FIXED,	/* Fixed-link mode */
+ 	MLO_AN_INBAND,	/* In-band protocol */
++
++	MAC_SYM_PAUSE	= BIT(0),
++	MAC_ASYM_PAUSE	= BIT(1),
++	MAC_10HD	= BIT(2),
++	MAC_10FD	= BIT(3),
++	MAC_10		= MAC_10HD | MAC_10FD,
++	MAC_100HD	= BIT(4),
++	MAC_100FD	= BIT(5),
++	MAC_100		= MAC_100HD | MAC_100FD,
++	MAC_1000HD	= BIT(6),
++	MAC_1000FD	= BIT(7),
++	MAC_1000	= MAC_1000HD | MAC_1000FD,
++	MAC_2500FD	= BIT(8),
++	MAC_5000FD	= BIT(9),
++	MAC_10000FD	= BIT(10),
++	MAC_20000FD	= BIT(11),
++	MAC_25000FD	= BIT(12),
++	MAC_40000FD	= BIT(13),
++	MAC_50000FD	= BIT(14),
++	MAC_56000FD	= BIT(15),
++	MAC_100000FD	= BIT(16),
++	MAC_200000FD	= BIT(17),
++	MAC_400000FD	= BIT(18),
+ };
+ 
+ static inline bool phylink_autoneg_inband(unsigned int mode)
+@@ -69,6 +92,7 @@ enum phylink_op_type {
+  *		     if MAC link is at %MLO_AN_FIXED mode.
+  * @supported_interfaces: bitmap describing which PHY_INTERFACE_MODE_xxx
+  *                        are supported by the MAC/PCS.
++ * @mac_capabilities: MAC pause/speed/duplex capabilities.
+  */
+ struct phylink_config {
+ 	struct device *dev;
+@@ -79,6 +103,7 @@ struct phylink_config {
+ 	void (*get_fixed_state)(struct phylink_config *config,
+ 				struct phylink_link_state *state);
+ 	DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
++	unsigned long mac_capabilities;
+ };
+ 
+ /**
+@@ -460,6 +485,12 @@ void pcs_link_up(struct phylink_pcs *pcs
+ 		 phy_interface_t interface, int speed, int duplex);
+ #endif
+ 
++void phylink_get_linkmodes(unsigned long *linkmodes, phy_interface_t interface,
++			   unsigned long mac_capabilities);
++void phylink_generic_validate(struct phylink_config *config,
++			      unsigned long *supported,
++			      struct phylink_link_state *state);
++
+ struct phylink *phylink_create(struct phylink_config *, struct fwnode_handle *,
+ 			       phy_interface_t iface,
+ 			       const struct phylink_mac_ops *mac_ops);
diff --git a/target/linux/generic/backport-5.15/703-10-v5.16-net-dsa-introduce-helpers-for-iterating-through-port.patch b/target/linux/generic/backport-5.15/703-10-v5.16-net-dsa-introduce-helpers-for-iterating-through-port.patch
new file mode 100644
index 0000000000..a55623519c
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-10-v5.16-net-dsa-introduce-helpers-for-iterating-through-port.patch
@@ -0,0 +1,68 @@
+From 82b318983c515f29b8b3a0dad9f6a5fe8a68a7f4 Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <vladimir.oltean at nxp.com>
+Date: Wed, 20 Oct 2021 20:49:49 +0300
+Subject: [PATCH] net: dsa: introduce helpers for iterating through ports using
+ dp
+
+Since the DSA conversion from the ds->ports array into the dst->ports
+list, the DSA API has encouraged driver writers, as well as the core
+itself, to write inefficient code.
+
+Currently, code that wants to filter by a specific type of port when
+iterating, like {!unused, user, cpu, dsa}, uses the dsa_is_*_port helper.
+Under the hood, this uses dsa_to_port which iterates again through
+dst->ports. But the driver iterates through the port list already, so
+the complexity is quadratic for the typical case of a single-switch
+tree.
+
+This patch introduces some iteration helpers where the iterator is
+already a struct dsa_port *dp, so that the other variant of the
+filtering functions, dsa_port_is_{unused,user,cpu_dsa}, can be used
+directly on the iterator. This eliminates the second lookup.
+
+These functions can be used both by the core and by drivers.
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ include/net/dsa.h | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+--- a/include/net/dsa.h
++++ b/include/net/dsa.h
+@@ -476,6 +476,34 @@ static inline bool dsa_is_user_port(stru
+ 	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_USER;
+ }
+ 
++#define dsa_tree_for_each_user_port(_dp, _dst) \
++	list_for_each_entry((_dp), &(_dst)->ports, list) \
++		if (dsa_port_is_user((_dp)))
++
++#define dsa_switch_for_each_port(_dp, _ds) \
++	list_for_each_entry((_dp), &(_ds)->dst->ports, list) \
++		if ((_dp)->ds == (_ds))
++
++#define dsa_switch_for_each_port_safe(_dp, _next, _ds) \
++	list_for_each_entry_safe((_dp), (_next), &(_ds)->dst->ports, list) \
++		if ((_dp)->ds == (_ds))
++
++#define dsa_switch_for_each_port_continue_reverse(_dp, _ds) \
++	list_for_each_entry_continue_reverse((_dp), &(_ds)->dst->ports, list) \
++		if ((_dp)->ds == (_ds))
++
++#define dsa_switch_for_each_available_port(_dp, _ds) \
++	dsa_switch_for_each_port((_dp), (_ds)) \
++		if (!dsa_port_is_unused((_dp)))
++
++#define dsa_switch_for_each_user_port(_dp, _ds) \
++	dsa_switch_for_each_port((_dp), (_ds)) \
++		if (dsa_port_is_user((_dp)))
++
++#define dsa_switch_for_each_cpu_port(_dp, _ds) \
++	dsa_switch_for_each_port((_dp), (_ds)) \
++		if (dsa_port_is_cpu((_dp)))
++
+ static inline u32 dsa_user_ports(struct dsa_switch *ds)
+ {
+ 	u32 mask = 0;
diff --git a/target/linux/generic/backport-5.15/703-11-v5.17-net-phylink-add-pcs_validate-method.patch b/target/linux/generic/backport-5.15/703-11-v5.17-net-phylink-add-pcs_validate-method.patch
new file mode 100644
index 0000000000..add2e6e352
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-11-v5.17-net-phylink-add-pcs_validate-method.patch
@@ -0,0 +1,106 @@
+From 0d22d4b626a4eaa3196019092eb6c1919e9f8caa Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 15 Dec 2021 15:34:20 +0000
+Subject: [PATCH] net: phylink: add pcs_validate() method
+
+Add a hook for PCS to validate the link parameters. This avoids MAC
+drivers having to have knowledge of their PCS in their validate()
+method, thereby allowing several MAC drivers to be simplfied.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/phy/phylink.c | 31 +++++++++++++++++++++++++++++++
+ include/linux/phylink.h   | 20 ++++++++++++++++++++
+ 2 files changed, 51 insertions(+)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -160,13 +160,44 @@ static int phylink_validate_mac_and_pcs(
+ 					struct phylink_link_state *state)
+ {
+ 	struct phylink_pcs *pcs;
++	int ret;
+ 
++	/* Get the PCS for this interface mode */
+ 	if (pl->mac_ops->mac_select_pcs) {
+ 		pcs = pl->mac_ops->mac_select_pcs(pl->config, state->interface);
+ 		if (IS_ERR(pcs))
+ 			return PTR_ERR(pcs);
++	} else {
++		pcs = pl->pcs;
+ 	}
+ 
++	if (pcs) {
++		/* The PCS, if present, must be setup before phylink_create()
++		 * has been called. If the ops is not initialised, print an
++		 * error and backtrace rather than oopsing the kernel.
++		 */
++		if (!pcs->ops) {
++			phylink_err(pl, "interface %s: uninitialised PCS\n",
++				    phy_modes(state->interface));
++			dump_stack();
++			return -EINVAL;
++		}
++
++		/* Validate the link parameters with the PCS */
++		if (pcs->ops->pcs_validate) {
++			ret = pcs->ops->pcs_validate(pcs, supported, state);
++			if (ret < 0 || phylink_is_empty_linkmode(supported))
++				return -EINVAL;
++
++			/* Ensure the advertising mask is a subset of the
++			 * supported mask.
++			 */
++			linkmode_and(state->advertising, state->advertising,
++				     supported);
++		}
++	}
++
++	/* Then validate the link parameters with the MAC */
+ 	pl->mac_ops->validate(pl->config, supported, state);
+ 
+ 	return phylink_is_empty_linkmode(supported) ? -EINVAL : 0;
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -396,6 +396,7 @@ struct phylink_pcs {
+ 
+ /**
+  * struct phylink_pcs_ops - MAC PCS operations structure.
++ * @pcs_validate: validate the link configuration.
+  * @pcs_get_state: read the current MAC PCS link state from the hardware.
+  * @pcs_config: configure the MAC PCS for the selected mode and state.
+  * @pcs_an_restart: restart 802.3z BaseX autonegotiation.
+@@ -403,6 +404,8 @@ struct phylink_pcs {
+  *               (where necessary).
+  */
+ struct phylink_pcs_ops {
++	int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
++			    const struct phylink_link_state *state);
+ 	void (*pcs_get_state)(struct phylink_pcs *pcs,
+ 			      struct phylink_link_state *state);
+ 	int (*pcs_config)(struct phylink_pcs *pcs, unsigned int mode,
+@@ -416,6 +419,23 @@ struct phylink_pcs_ops {
+ 
+ #if 0 /* For kernel-doc purposes only. */
+ /**
++ * pcs_validate() - validate the link configuration.
++ * @pcs: a pointer to a &struct phylink_pcs.
++ * @supported: ethtool bitmask for supported link modes.
++ * @state: a const pointer to a &struct phylink_link_state.
++ *
++ * Validate the interface mode, and advertising's autoneg bit, removing any
++ * media ethtool link modes that would not be supportable from the supported
++ * mask. Phylink will propagate the changes to the advertising mask. See the
++ * &struct phylink_mac_ops validate() method.
++ *
++ * Returns -EINVAL if the interface mode/autoneg mode is not supported.
++ * Returns non-zero positive if the link state can be supported.
++ */
++int pcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
++		 const struct phylink_link_state *state);
++
++/**
+  * pcs_get_state() - Read the current inband link state from the hardware
+  * @pcs: a pointer to a &struct phylink_pcs.
+  * @state: a pointer to a &struct phylink_link_state.
diff --git a/target/linux/generic/backport-5.15/703-12-v5.17-net-phylink-add-legacy_pre_march2020-indicator.patch b/target/linux/generic/backport-5.15/703-12-v5.17-net-phylink-add-legacy_pre_march2020-indicator.patch
new file mode 100644
index 0000000000..6fbde12507
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-12-v5.17-net-phylink-add-legacy_pre_march2020-indicator.patch
@@ -0,0 +1,43 @@
+From 3e5b1feccea7db576353ffc302f78d522e4116e6 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Thu, 9 Dec 2021 13:11:32 +0000
+Subject: [PATCH] net: phylink: add legacy_pre_march2020 indicator
+
+Add a boolean to phylink_config to indicate whether a driver has not
+been updated for the changes in commit 7cceb599d15d ("net: phylink:
+avoid mac_config calls"), and thus are reliant on the old behaviour.
+
+We were currently keying the phylink behaviour on the presence of a
+PCS, but this is sub-optimal for modern drivers that may not have a
+PCS.
+
+This commit merely introduces the new flag, but does not add any use,
+since we need all legacy drivers to set this flag before it can be
+used. Once these legacy drivers have been updated, we can remove this
+flag.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ include/linux/phylink.h | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -84,6 +84,8 @@ enum phylink_op_type {
+  * struct phylink_config - PHYLINK configuration structure
+  * @dev: a pointer to a struct device associated with the MAC
+  * @type: operation type of PHYLINK instance
++ * @legacy_pre_march2020: driver has not been updated for March 2020 updates
++ *	(See commit 7cceb599d15d ("net: phylink: avoid mac_config calls")
+  * @pcs_poll: MAC PCS cannot provide link change interrupt
+  * @poll_fixed_state: if true, starts link_poll,
+  *		      if MAC link is at %MLO_AN_FIXED mode.
+@@ -97,6 +99,7 @@ enum phylink_op_type {
+ struct phylink_config {
+ 	struct device *dev;
+ 	enum phylink_op_type type;
++	bool legacy_pre_march2020;
+ 	bool pcs_poll;
+ 	bool poll_fixed_state;
+ 	bool ovr_an_inband;
diff --git a/target/linux/generic/backport-5.15/703-13-v5.17-net-dsa-mark-DSA-phylink-as-legacy_pre_march2020.patch b/target/linux/generic/backport-5.15/703-13-v5.17-net-dsa-mark-DSA-phylink-as-legacy_pre_march2020.patch
new file mode 100644
index 0000000000..dff0db5db6
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-13-v5.17-net-dsa-mark-DSA-phylink-as-legacy_pre_march2020.patch
@@ -0,0 +1,36 @@
+From 0a9f0794d9bd67e590a9488afe87fbb0419d9539 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Thu, 9 Dec 2021 13:11:38 +0000
+Subject: [PATCH] net: dsa: mark DSA phylink as legacy_pre_march2020
+
+The majority of DSA drivers do not make use of the PCS support, and
+thus operate in legacy mode. In order to preserve this behaviour in
+future, we need to set the legacy_pre_march2020 flag so phylink knows
+this may require the legacy calls.
+
+There are some DSA drivers that do make use of PCS support, and these
+will continue operating as before - legacy_pre_march2020 will not
+prevent split-PCS support enabling the newer phylink behaviour.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ net/dsa/port.c | 7 +++++++
+ 1 file changed, 7 insertions(+)
+
+--- a/net/dsa/port.c
++++ b/net/dsa/port.c
+@@ -1110,6 +1110,13 @@ int dsa_port_phylink_create(struct dsa_p
+ 	if (err)
+ 		mode = PHY_INTERFACE_MODE_NA;
+ 
++	/* Presence of phylink_mac_link_state or phylink_mac_an_restart is
++	 * an indicator of a legacy phylink driver.
++	 */
++	if (ds->ops->phylink_mac_link_state ||
++	    ds->ops->phylink_mac_an_restart)
++		dp->pl_config.legacy_pre_march2020 = true;
++
+ 	if (ds->ops->phylink_get_caps)
+ 		ds->ops->phylink_get_caps(ds, dp->index, &dp->pl_config);
+ 
diff --git a/target/linux/generic/backport-5.15/703-14-v5.17-net-phylink-use-legacy_pre_march2020.patch b/target/linux/generic/backport-5.15/703-14-v5.17-net-phylink-use-legacy_pre_march2020.patch
new file mode 100644
index 0000000000..361fa10d4d
--- /dev/null
+++ b/target/linux/generic/backport-5.15/703-14-v5.17-net-phylink-use-legacy_pre_march2020.patch
@@ -0,0 +1,115 @@
+From 001f4261fe4d5ae710cf1f445b6cae6d9d3ae26e Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Thu, 9 Dec 2021 13:11:48 +0000
+Subject: [PATCH] net: phylink: use legacy_pre_march2020
+
+Use the legacy flag to indicate whether we should operate in legacy
+mode. This allows us to stop using the presence of a PCS as an
+indicator to the age of the phylink user, and make PCS presence
+optional.
+
+Legacy mode involves:
+1) calling mac_config() whenever the link comes up
+2) calling mac_config() whenever the inband advertisement changes,
+   possibly followed by a call to mac_an_restart()
+3) making use of mac_an_restart()
+4) making use of mac_pcs_get_state()
+
+All the above functionality was moved to a seperate "PCS" block of
+operations in March 2020.
+
+Update the documents to indicate that the differences that this flag
+makes.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/phy/phylink.c | 12 ++++++------
+ include/linux/phylink.h   | 17 +++++++++++++++++
+ 2 files changed, 23 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/phy/phylink.c
++++ b/drivers/net/phy/phylink.c
+@@ -777,7 +777,7 @@ static void phylink_mac_pcs_an_restart(s
+ 	    phylink_autoneg_inband(pl->cur_link_an_mode)) {
+ 		if (pl->pcs_ops)
+ 			pl->pcs_ops->pcs_an_restart(pl->pcs);
+-		else
++		else if (pl->config->legacy_pre_march2020)
+ 			pl->mac_ops->mac_an_restart(pl->config);
+ 	}
+ }
+@@ -855,7 +855,7 @@ static int phylink_change_inband_advert(
+ 	if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
+ 		return 0;
+ 
+-	if (!pl->pcs_ops) {
++	if (!pl->pcs_ops && pl->config->legacy_pre_march2020) {
+ 		/* Legacy method */
+ 		phylink_mac_config(pl, &pl->link_config);
+ 		phylink_mac_pcs_an_restart(pl);
+@@ -900,7 +900,8 @@ static void phylink_mac_pcs_get_state(st
+ 
+ 	if (pl->pcs_ops)
+ 		pl->pcs_ops->pcs_get_state(pl->pcs, state);
+-	else if (pl->mac_ops->mac_pcs_get_state)
++	else if (pl->mac_ops->mac_pcs_get_state &&
++		 pl->config->legacy_pre_march2020)
+ 		pl->mac_ops->mac_pcs_get_state(pl->config, state);
+ 	else
+ 		state->link = 0;
+@@ -1094,12 +1095,11 @@ static void phylink_resolve(struct work_
+ 			}
+ 			phylink_major_config(pl, false, &link_state);
+ 			pl->link_config.interface = link_state.interface;
+-		} else if (!pl->pcs_ops) {
++		} else if (!pl->pcs_ops && pl->config->legacy_pre_march2020) {
+ 			/* The interface remains unchanged, only the speed,
+ 			 * duplex or pause settings have changed. Call the
+ 			 * old mac_config() method to configure the MAC/PCS
+-			 * only if we do not have a PCS installed (an
+-			 * unconverted user.)
++			 * only if we do not have a legacy MAC driver.
+ 			 */
+ 			phylink_mac_config(pl, &link_state);
+ 		}
+--- a/include/linux/phylink.h
++++ b/include/linux/phylink.h
+@@ -208,6 +208,10 @@ struct phylink_pcs *mac_select_pcs(struc
+  * negotiation completion state in @state->an_complete, and link up state
+  * in @state->link. If possible, @state->lp_advertising should also be
+  * populated.
++ *
++ * Note: This is a legacy method. This function will not be called unless
++ * legacy_pre_march2020 is set in &struct phylink_config and there is no
++ * PCS attached.
+  */
+ void mac_pcs_get_state(struct phylink_config *config,
+ 		       struct phylink_link_state *state);
+@@ -248,6 +252,15 @@ int mac_prepare(struct phylink_config *c
+  * guaranteed to be correct, and so any mac_config() implementation must
+  * never reference these fields.
+  *
++ * Note: For legacy March 2020 drivers (drivers with legacy_pre_march2020 set
++ * in their &phylnk_config and which don't have a PCS), this function will be
++ * called on each link up event, and to also change the in-band advert. For
++ * non-legacy drivers, it will only be called to reconfigure the MAC for a
++ * "major" change in e.g. interface mode. It will not be called for changes
++ * in speed, duplex or pause modes or to change the in-band advertisement.
++ * In any case, it is strongly preferred that speed, duplex and pause settings
++ * are handled in the mac_link_up() method and not in this method.
++ *
+  * (this requires a rewrite - please refer to mac_link_up() for situations
+  *  where the PCS and MAC are not tightly integrated.)
+  *
+@@ -332,6 +345,10 @@ int mac_finish(struct phylink_config *co
+ /**
+  * mac_an_restart() - restart 802.3z BaseX autonegotiation
+  * @config: a pointer to a &struct phylink_config.
++ *
++ * Note: This is a legacy method. This function will not be called unless
++ * legacy_pre_march2020 is set in &struct phylink_config and there is no
++ * PCS attached.
+  */
+ void mac_an_restart(struct phylink_config *config);
+ 
diff --git a/target/linux/generic/backport-5.15/704-01-v5.17-net-mtk_eth_soc-populate-supported_interfaces-member.patch b/target/linux/generic/backport-5.15/704-01-v5.17-net-mtk_eth_soc-populate-supported_interfaces-member.patch
new file mode 100644
index 0000000000..43e1f9cc31
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-01-v5.17-net-mtk_eth_soc-populate-supported_interfaces-member.patch
@@ -0,0 +1,43 @@
+From 83800d29f0c578e82554e7d4c6bfdbdf9b6cf428 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 16 Nov 2021 10:06:43 +0000
+Subject: [PATCH] net: mtk_eth_soc: populate supported_interfaces member
+
+Populate the phy interface mode bitmap for the Mediatek driver with
+interfaces modes supported by the MAC.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 20 ++++++++++++++++++++
+ 1 file changed, 20 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -3352,6 +3352,26 @@ static int mtk_add_mac(struct mtk_eth *e
+ 
+ 	mac->phylink_config.dev = &eth->netdev[id]->dev;
+ 	mac->phylink_config.type = PHYLINK_NETDEV;
++	__set_bit(PHY_INTERFACE_MODE_MII,
++		  mac->phylink_config.supported_interfaces);
++	__set_bit(PHY_INTERFACE_MODE_GMII,
++		  mac->phylink_config.supported_interfaces);
++
++	if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII))
++		phy_interface_set_rgmii(mac->phylink_config.supported_interfaces);
++
++	if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) && !mac->id)
++		__set_bit(PHY_INTERFACE_MODE_TRGMII,
++			  mac->phylink_config.supported_interfaces);
++
++	if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) {
++		__set_bit(PHY_INTERFACE_MODE_SGMII,
++			  mac->phylink_config.supported_interfaces);
++		__set_bit(PHY_INTERFACE_MODE_1000BASEX,
++			  mac->phylink_config.supported_interfaces);
++		__set_bit(PHY_INTERFACE_MODE_2500BASEX,
++			  mac->phylink_config.supported_interfaces);
++	}
+ 
+ 	phylink = phylink_create(&mac->phylink_config,
+ 				 of_fwnode_handle(mac->of_node),
diff --git a/target/linux/generic/backport-5.15/704-02-v5.17-net-mtk_eth_soc-remove-interface-checks-in-mtk_valid.patch b/target/linux/generic/backport-5.15/704-02-v5.17-net-mtk_eth_soc-remove-interface-checks-in-mtk_valid.patch
new file mode 100644
index 0000000000..05a84c4f67
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-02-v5.17-net-mtk_eth_soc-remove-interface-checks-in-mtk_valid.patch
@@ -0,0 +1,75 @@
+From db81ca153814475d7e07365d46a4d1134bd122e2 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 16 Nov 2021 10:06:48 +0000
+Subject: [PATCH] net: mtk_eth_soc: remove interface checks in mtk_validate()
+
+As phylink checks the interface mode against the supported_interfaces
+bitmap, we no longer need to validate the interface mode, nor handle
+PHY_INTERFACE_MODE_NA in the validation function. Remove these to
+simplify the implementation.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 34 ---------------------
+ 1 file changed, 34 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -567,24 +567,8 @@ static void mtk_validate(struct phylink_
+ 			 unsigned long *supported,
+ 			 struct phylink_link_state *state)
+ {
+-	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+-					   phylink_config);
+ 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+ 
+-	if (state->interface != PHY_INTERFACE_MODE_NA &&
+-	    state->interface != PHY_INTERFACE_MODE_MII &&
+-	    state->interface != PHY_INTERFACE_MODE_GMII &&
+-	    !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII) &&
+-	      phy_interface_mode_is_rgmii(state->interface)) &&
+-	    !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_TRGMII) &&
+-	      !mac->id && state->interface == PHY_INTERFACE_MODE_TRGMII) &&
+-	    !(MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII) &&
+-	      (state->interface == PHY_INTERFACE_MODE_SGMII ||
+-	       phy_interface_mode_is_8023z(state->interface)))) {
+-		linkmode_zero(supported);
+-		return;
+-	}
+-
+ 	phylink_set_port_modes(mask);
+ 	phylink_set(mask, Autoneg);
+ 
+@@ -611,7 +595,6 @@ static void mtk_validate(struct phylink_
+ 	case PHY_INTERFACE_MODE_MII:
+ 	case PHY_INTERFACE_MODE_RMII:
+ 	case PHY_INTERFACE_MODE_REVMII:
+-	case PHY_INTERFACE_MODE_NA:
+ 	default:
+ 		phylink_set(mask, 10baseT_Half);
+ 		phylink_set(mask, 10baseT_Full);
+@@ -620,23 +603,6 @@ static void mtk_validate(struct phylink_
+ 		break;
+ 	}
+ 
+-	if (state->interface == PHY_INTERFACE_MODE_NA) {
+-		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) {
+-			phylink_set(mask, 1000baseT_Full);
+-			phylink_set(mask, 1000baseX_Full);
+-			phylink_set(mask, 2500baseX_Full);
+-		}
+-		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) {
+-			phylink_set(mask, 1000baseT_Full);
+-			phylink_set(mask, 1000baseT_Half);
+-			phylink_set(mask, 1000baseX_Full);
+-		}
+-		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_GEPHY)) {
+-			phylink_set(mask, 1000baseT_Full);
+-			phylink_set(mask, 1000baseT_Half);
+-		}
+-	}
+-
+ 	phylink_set(mask, Pause);
+ 	phylink_set(mask, Asym_Pause);
+ 
diff --git a/target/linux/generic/backport-5.15/704-03-v5.17-net-mtk_eth_soc-drop-use-of-phylink_helper_basex_spe.patch b/target/linux/generic/backport-5.15/704-03-v5.17-net-mtk_eth_soc-drop-use-of-phylink_helper_basex_spe.patch
new file mode 100644
index 0000000000..a3cfab7f88
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-03-v5.17-net-mtk_eth_soc-drop-use-of-phylink_helper_basex_spe.patch
@@ -0,0 +1,42 @@
+From 71d927494463c4f016d828e1134da26b7e961af5 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 16 Nov 2021 10:06:53 +0000
+Subject: [PATCH] net: mtk_eth_soc: drop use of phylink_helper_basex_speed()
+
+Now that we have a better method to select SFP interface modes, we
+no longer need to use phylink_helper_basex_speed() in a driver's
+validation function, and we can also get rid of our hack to indicate
+both 1000base-X and 2500base-X if the comphy is present to make that
+work. Remove this hack and use of phylink_helper_basex_speed().
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++------
+ 1 file changed, 2 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -577,8 +577,9 @@ static void mtk_validate(struct phylink_
+ 		phylink_set(mask, 1000baseT_Full);
+ 		break;
+ 	case PHY_INTERFACE_MODE_1000BASEX:
+-	case PHY_INTERFACE_MODE_2500BASEX:
+ 		phylink_set(mask, 1000baseX_Full);
++		break;
++	case PHY_INTERFACE_MODE_2500BASEX:
+ 		phylink_set(mask, 2500baseX_Full);
+ 		break;
+ 	case PHY_INTERFACE_MODE_GMII:
+@@ -608,11 +609,6 @@ static void mtk_validate(struct phylink_
+ 
+ 	linkmode_and(supported, supported, mask);
+ 	linkmode_and(state->advertising, state->advertising, mask);
+-
+-	/* We can only operate at 2500BaseX or 1000BaseX. If requested
+-	 * to advertise both, only report advertising at 2500BaseX.
+-	 */
+-	phylink_helper_basex_speed(state);
+ }
+ 
+ static const struct phylink_mac_ops mtk_phylink_ops = {
diff --git a/target/linux/generic/backport-5.15/704-04-v5.17-net-mtk_eth_soc-use-phylink_generic_validate.patch b/target/linux/generic/backport-5.15/704-04-v5.17-net-mtk_eth_soc-use-phylink_generic_validate.patch
new file mode 100644
index 0000000000..7f3734a765
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-04-v5.17-net-mtk_eth_soc-use-phylink_generic_validate.patch
@@ -0,0 +1,84 @@
+From a4238f6ce151afa331375d74a5033b76da637644 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Tue, 16 Nov 2021 10:06:58 +0000
+Subject: [PATCH] net: mtk_eth_soc: use phylink_generic_validate()
+
+mtk_eth_soc has no special behaviour in its validation implementation,
+so can be switched to phylink_generic_validate().
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 53 ++-------------------
+ 1 file changed, 4 insertions(+), 49 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -563,56 +563,8 @@ static void mtk_mac_link_up(struct phyli
+ 	mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
+ }
+ 
+-static void mtk_validate(struct phylink_config *config,
+-			 unsigned long *supported,
+-			 struct phylink_link_state *state)
+-{
+-	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+-
+-	phylink_set_port_modes(mask);
+-	phylink_set(mask, Autoneg);
+-
+-	switch (state->interface) {
+-	case PHY_INTERFACE_MODE_TRGMII:
+-		phylink_set(mask, 1000baseT_Full);
+-		break;
+-	case PHY_INTERFACE_MODE_1000BASEX:
+-		phylink_set(mask, 1000baseX_Full);
+-		break;
+-	case PHY_INTERFACE_MODE_2500BASEX:
+-		phylink_set(mask, 2500baseX_Full);
+-		break;
+-	case PHY_INTERFACE_MODE_GMII:
+-	case PHY_INTERFACE_MODE_RGMII:
+-	case PHY_INTERFACE_MODE_RGMII_ID:
+-	case PHY_INTERFACE_MODE_RGMII_RXID:
+-	case PHY_INTERFACE_MODE_RGMII_TXID:
+-		phylink_set(mask, 1000baseT_Half);
+-		fallthrough;
+-	case PHY_INTERFACE_MODE_SGMII:
+-		phylink_set(mask, 1000baseT_Full);
+-		phylink_set(mask, 1000baseX_Full);
+-		fallthrough;
+-	case PHY_INTERFACE_MODE_MII:
+-	case PHY_INTERFACE_MODE_RMII:
+-	case PHY_INTERFACE_MODE_REVMII:
+-	default:
+-		phylink_set(mask, 10baseT_Half);
+-		phylink_set(mask, 10baseT_Full);
+-		phylink_set(mask, 100baseT_Half);
+-		phylink_set(mask, 100baseT_Full);
+-		break;
+-	}
+-
+-	phylink_set(mask, Pause);
+-	phylink_set(mask, Asym_Pause);
+-
+-	linkmode_and(supported, supported, mask);
+-	linkmode_and(state->advertising, state->advertising, mask);
+-}
+-
+ static const struct phylink_mac_ops mtk_phylink_ops = {
+-	.validate = mtk_validate,
++	.validate = phylink_generic_validate,
+ 	.mac_pcs_get_state = mtk_mac_pcs_get_state,
+ 	.mac_an_restart = mtk_mac_an_restart,
+ 	.mac_config = mtk_mac_config,
+@@ -3314,6 +3266,9 @@ static int mtk_add_mac(struct mtk_eth *e
+ 
+ 	mac->phylink_config.dev = &eth->netdev[id]->dev;
+ 	mac->phylink_config.type = PHYLINK_NETDEV;
++	mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++		MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
++
+ 	__set_bit(PHY_INTERFACE_MODE_MII,
+ 		  mac->phylink_config.supported_interfaces);
+ 	__set_bit(PHY_INTERFACE_MODE_GMII,
diff --git a/target/linux/generic/backport-5.15/704-05-v5.17-net-mtk_eth_soc-mark-as-a-legacy_pre_march2020-drive.patch b/target/linux/generic/backport-5.15/704-05-v5.17-net-mtk_eth_soc-mark-as-a-legacy_pre_march2020-drive.patch
new file mode 100644
index 0000000000..6aa99acf77
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-05-v5.17-net-mtk_eth_soc-mark-as-a-legacy_pre_march2020-drive.patch
@@ -0,0 +1,29 @@
+From b06515367facfadcf5e70cf6f39db749cf4eb5e3 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Thu, 9 Dec 2021 13:11:43 +0000
+Subject: [PATCH] net: mtk_eth_soc: mark as a legacy_pre_march2020 driver
+
+mtk_eth_soc has not been updated for commit 7cceb599d15d ("net: phylink:
+avoid mac_config calls"), and makes use of state->speed and
+state->duplex in contravention of the phylink documentation. This makes
+reliant on the legacy behaviours, so mark it as a legacy driver.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -3266,6 +3266,10 @@ static int mtk_add_mac(struct mtk_eth *e
+ 
+ 	mac->phylink_config.dev = &eth->netdev[id]->dev;
+ 	mac->phylink_config.type = PHYLINK_NETDEV;
++	/* This driver makes use of state->speed/state->duplex in
++	 * mac_config
++	 */
++	mac->phylink_config.legacy_pre_march2020 = true;
+ 	mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+ 		MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
+ 
diff --git a/target/linux/generic/backport-5.15/704-06-v5.19-eth-mtk_eth_soc-remove-a-copy-of-the-NAPI_POLL_WEIGH.patch b/target/linux/generic/backport-5.15/704-06-v5.19-eth-mtk_eth_soc-remove-a-copy-of-the-NAPI_POLL_WEIGH.patch
new file mode 100644
index 0000000000..e5f70e36f0
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-06-v5.19-eth-mtk_eth_soc-remove-a-copy-of-the-NAPI_POLL_WEIGH.patch
@@ -0,0 +1,40 @@
+From 889e3691b9d6573de133da1f5e78f590e52152cd Mon Sep 17 00:00:00 2001
+From: Jakub Kicinski <kuba at kernel.org>
+Date: Thu, 28 Apr 2022 14:23:13 -0700
+Subject: [PATCH] eth: mtk_eth_soc: remove a copy of the NAPI_POLL_WEIGHT
+ define
+
+Defining local versions of NAPI_POLL_WEIGHT with the same
+values in the drivers just makes refactoring harder.
+
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+Signed-off-by: David S. Miller <davem at davemloft.net>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 4 ++--
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 -
+ 2 files changed, 2 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -3565,9 +3565,9 @@ static int mtk_probe(struct platform_dev
+ 	 */
+ 	init_dummy_netdev(&eth->dummy_dev);
+ 	netif_napi_add(&eth->dummy_dev, &eth->tx_napi, mtk_napi_tx,
+-		       MTK_NAPI_WEIGHT);
++		       NAPI_POLL_WEIGHT);
+ 	netif_napi_add(&eth->dummy_dev, &eth->rx_napi, mtk_napi_rx,
+-		       MTK_NAPI_WEIGHT);
++		       NAPI_POLL_WEIGHT);
+ 
+ 	platform_set_drvdata(pdev, eth);
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -25,7 +25,6 @@
+ #define MTK_TX_DMA_BUF_LEN	0x3fff
+ #define MTK_TX_DMA_BUF_LEN_V2	0xffff
+ #define MTK_DMA_SIZE		512
+-#define MTK_NAPI_WEIGHT		64
+ #define MTK_MAC_COUNT		2
+ #define MTK_RX_ETH_HLEN		(ETH_HLEN + ETH_FCS_LEN)
+ #define MTK_RX_HLEN		(NET_SKB_PAD + MTK_RX_ETH_HLEN + NET_IP_ALIGN)
diff --git a/target/linux/generic/backport-5.15/704-07-v5.19-mtk_eth_soc-remove-unused-mac-mode.patch b/target/linux/generic/backport-5.15/704-07-v5.19-mtk_eth_soc-remove-unused-mac-mode.patch
new file mode 100644
index 0000000000..4d896cdf39
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-07-v5.19-mtk_eth_soc-remove-unused-mac-mode.patch
@@ -0,0 +1,35 @@
+From 0600bdde1fae75fb9bad72033d28edddc72b44b2 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:54:31 +0100
+Subject: [PATCH 01/12] net: mtk_eth_soc: remove unused mac->mode
+
+mac->mode is only ever written to in one location, and is thus
+superflous. Remove it.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 1 -
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 1 -
+ 2 files changed, 2 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -3261,7 +3261,6 @@ static int mtk_add_mac(struct mtk_eth *e
+ 
+ 	/* mac config is not set */
+ 	mac->interface = PHY_INTERFACE_MODE_NA;
+-	mac->mode = MLO_AN_PHY;
+ 	mac->speed = SPEED_UNKNOWN;
+ 
+ 	mac->phylink_config.dev = &eth->netdev[id]->dev;
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1085,7 +1085,6 @@ struct mtk_eth {
+ struct mtk_mac {
+ 	int				id;
+ 	phy_interface_t			interface;
+-	unsigned int			mode;
+ 	int				speed;
+ 	struct device_node		*of_node;
+ 	struct phylink			*phylink;
diff --git a/target/linux/generic/backport-5.15/704-08-v5.19-net-mtk_eth_soc-remove-unused-sgmii-flags.patch b/target/linux/generic/backport-5.15/704-08-v5.19-net-mtk_eth_soc-remove-unused-sgmii-flags.patch
new file mode 100644
index 0000000000..39aa24157e
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-08-v5.19-net-mtk_eth_soc-remove-unused-sgmii-flags.patch
@@ -0,0 +1,40 @@
+From 5a7a2f4b29d7546244da7d8bbc1962fce5b230f2 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:54:36 +0100
+Subject: [PATCH 02/12] net: mtk_eth_soc: remove unused sgmii flags
+
+The "flags" member of struct mtk_sgmii appears to be unused, as are
+the MTK_SGMII_PHYSPEED_* and MTK_HAS_FLAGS() macros. Remove them.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 --------
+ 1 file changed, 8 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -956,23 +956,15 @@ struct mtk_soc_data {
+ /* currently no SoC has more than 2 macs */
+ #define MTK_MAX_DEVS			2
+ 
+-#define MTK_SGMII_PHYSPEED_AN          BIT(31)
+-#define MTK_SGMII_PHYSPEED_MASK        GENMASK(2, 0)
+-#define MTK_SGMII_PHYSPEED_1000        BIT(0)
+-#define MTK_SGMII_PHYSPEED_2500        BIT(1)
+-#define MTK_HAS_FLAGS(flags, _x)       (((flags) & (_x)) == (_x))
+-
+ /* struct mtk_sgmii -  This is the structure holding sgmii regmap and its
+  *                     characteristics
+  * @regmap:            The register map pointing at the range used to setup
+  *                     SGMII modes
+- * @flags:             The enum refers to which mode the sgmii wants to run on
+  * @ana_rgc3:          The offset refers to register ANA_RGC3 related to regmap
+  */
+ 
+ struct mtk_sgmii {
+ 	struct regmap   *regmap[MTK_MAX_DEVS];
+-	u32             flags[MTK_MAX_DEVS];
+ 	u32             ana_rgc3;
+ };
+ 
diff --git a/target/linux/generic/backport-5.15/704-09-v5.19-net-mtk_eth_soc-add-mask-and-update-PCS-speed-defini.patch b/target/linux/generic/backport-5.15/704-09-v5.19-net-mtk_eth_soc-add-mask-and-update-PCS-speed-defini.patch
new file mode 100644
index 0000000000..f2e1f86bac
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-09-v5.19-net-mtk_eth_soc-add-mask-and-update-PCS-speed-defini.patch
@@ -0,0 +1,40 @@
+From bc5e93e0cd22e360eda23859b939280205567580 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:54:42 +0100
+Subject: [PATCH 03/12] net: mtk_eth_soc: add mask and update PCS speed
+ definitions
+
+The PCS speed setting is a two bit field, but it is defined as two
+separate bits. Add a bitfield mask for the speed definitions, an
+ use the FIELD_PREP() macro to define each PCS speed.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -17,6 +17,7 @@
+ #include <linux/phylink.h>
+ #include <linux/rhashtable.h>
+ #include <linux/dim.h>
++#include <linux/bitfield.h>
+ #include "mtk_ppe.h"
+ 
+ #define MTK_QDMA_PAGE_SIZE	2048
+@@ -473,9 +474,10 @@
+ #define SGMSYS_SGMII_MODE		0x20
+ #define SGMII_IF_MODE_BIT0		BIT(0)
+ #define SGMII_SPEED_DUPLEX_AN		BIT(1)
+-#define SGMII_SPEED_10			0x0
+-#define SGMII_SPEED_100			BIT(2)
+-#define SGMII_SPEED_1000		BIT(3)
++#define SGMII_SPEED_MASK		GENMASK(3, 2)
++#define SGMII_SPEED_10			FIELD_PREP(SGMII_SPEED_MASK, 0)
++#define SGMII_SPEED_100			FIELD_PREP(SGMII_SPEED_MASK, 1)
++#define SGMII_SPEED_1000		FIELD_PREP(SGMII_SPEED_MASK, 2)
+ #define SGMII_DUPLEX_FULL		BIT(4)
+ #define SGMII_IF_MODE_BIT5		BIT(5)
+ #define SGMII_REMOTE_FAULT_DIS		BIT(8)
diff --git a/target/linux/generic/backport-5.15/704-10-v5.19-net-mtk_eth_soc-correct-802.3z-speed-setting.patch b/target/linux/generic/backport-5.15/704-10-v5.19-net-mtk_eth_soc-correct-802.3z-speed-setting.patch
new file mode 100644
index 0000000000..fb1ee4e310
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-10-v5.19-net-mtk_eth_soc-correct-802.3z-speed-setting.patch
@@ -0,0 +1,60 @@
+From 7da3f901f8ecb425105fad39a0f5de73306abe52 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:54:47 +0100
+Subject: [PATCH 04/12] net: mtk_eth_soc: correct 802.3z speed setting
+
+Phylink does not guarantee that state->speed will be set correctly in
+the mac_config() call, so it's a bug that the driver makes use of it.
+Moreover, it is making use of it in a function that is only ever called
+for 1000BASE-X and 2500BASE-X which operate at a fixed speed which
+happens to be the same setting irrespective of the interface mode. We
+can simply remove the switch statement and just set the SGMII interface
+speed.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_sgmii.c | 18 +++++-------------
+ 1 file changed, 5 insertions(+), 13 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -34,6 +34,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
+ 	return 0;
+ }
+ 
++/* For SGMII interface mode */
+ int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
+ {
+ 	unsigned int val;
+@@ -60,6 +61,9 @@ int mtk_sgmii_setup_mode_an(struct mtk_s
+ 	return 0;
+ }
+ 
++/* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
++ * fixed speed.
++ */
+ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
+ 			       const struct phylink_link_state *state)
+ {
+@@ -82,19 +86,7 @@ int mtk_sgmii_setup_mode_force(struct mt
+ 	/* SGMII force mode setting */
+ 	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+ 	val &= ~SGMII_IF_MODE_MASK;
+-
+-	switch (state->speed) {
+-	case SPEED_10:
+-		val |= SGMII_SPEED_10;
+-		break;
+-	case SPEED_100:
+-		val |= SGMII_SPEED_100;
+-		break;
+-	case SPEED_2500:
+-	case SPEED_1000:
+-		val |= SGMII_SPEED_1000;
+-		break;
+-	}
++	val |= SGMII_SPEED_1000;
+ 
+ 	if (state->duplex == DUPLEX_FULL)
+ 		val |= SGMII_DUPLEX_FULL;
diff --git a/target/linux/generic/backport-5.15/704-11-v5.19-net-mtk_eth_soc-correct-802.3z-duplex-setting.patch b/target/linux/generic/backport-5.15/704-11-v5.19-net-mtk_eth_soc-correct-802.3z-duplex-setting.patch
new file mode 100644
index 0000000000..140ff3cab5
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-11-v5.19-net-mtk_eth_soc-correct-802.3z-duplex-setting.patch
@@ -0,0 +1,101 @@
+From a459187390bb221827f9c07866c3a5ffbdf9622b Mon Sep 17 00:00:00 2001
+From: Russell King <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:54:52 +0100
+Subject: [PATCH 05/12] net: mtk_eth_soc: correct 802.3z duplex setting
+
+Phylink does not guarantee that state->duplex will be set correctly in
+the mac_config() call, so it's a bug that the driver makes use of it.
+
+Move the 802.3z PCS duplex configuration to mac_link_up().
+
+Signed-off-by: Russell King <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 16 +++++++++++----
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h |  1 +
+ drivers/net/ethernet/mediatek/mtk_sgmii.c   | 22 +++++++++++++++------
+ 3 files changed, 29 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -532,8 +532,18 @@ static void mtk_mac_link_up(struct phyli
+ {
+ 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ 					   phylink_config);
+-	u32 mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
++	u32 mcr;
+ 
++	if (phy_interface_mode_is_8023z(interface)) {
++		struct mtk_eth *eth = mac->hw;
++
++		/* Decide how GMAC and SGMIISYS be mapped */
++		int sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
++			   0 : mac->id;
++		mtk_sgmii_link_up(eth->sgmii, sid, speed, duplex);
++	}
++
++	mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ 	mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
+ 		 MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
+ 		 MAC_MCR_FORCE_RX_FC);
+@@ -3265,9 +3275,7 @@ static int mtk_add_mac(struct mtk_eth *e
+ 
+ 	mac->phylink_config.dev = &eth->netdev[id]->dev;
+ 	mac->phylink_config.type = PHYLINK_NETDEV;
+-	/* This driver makes use of state->speed/state->duplex in
+-	 * mac_config
+-	 */
++	/* This driver makes use of state->speed in mac_config */
+ 	mac->phylink_config.legacy_pre_march2020 = true;
+ 	mac->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+ 		MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD;
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1103,6 +1103,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
+ int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id);
+ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
+ 			       const struct phylink_link_state *state);
++void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex);
+ void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
+ 
+ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -83,14 +83,10 @@ int mtk_sgmii_setup_mode_force(struct mt
+ 	val &= ~SGMII_AN_ENABLE;
+ 	regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
+ 
+-	/* SGMII force mode setting */
++	/* Set the speed etc but leave the duplex unchanged */
+ 	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
+-	val &= ~SGMII_IF_MODE_MASK;
++	val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
+ 	val |= SGMII_SPEED_1000;
+-
+-	if (state->duplex == DUPLEX_FULL)
+-		val |= SGMII_DUPLEX_FULL;
+-
+ 	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
+ 
+ 	/* Release PHYA power down state */
+@@ -101,6 +97,20 @@ int mtk_sgmii_setup_mode_force(struct mt
+ 	return 0;
+ }
+ 
++/* For 1000BASE-X and 2500BASE-X interface modes */
++void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
++{
++	unsigned int val;
++
++	/* SGMII force duplex setting */
++	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
++	val &= ~SGMII_DUPLEX_FULL;
++	if (duplex == DUPLEX_FULL)
++		val |= SGMII_DUPLEX_FULL;
++
++	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
++}
++
+ void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
+ {
+ 	struct mtk_sgmii *ss = eth->sgmii;
diff --git a/target/linux/generic/backport-5.15/704-12-v5.19-net-mtk_eth_soc-stop-passing-phylink-state-to-sgmii-.patch b/target/linux/generic/backport-5.15/704-12-v5.19-net-mtk_eth_soc-stop-passing-phylink-state-to-sgmii-.patch
new file mode 100644
index 0000000000..56b5e43e53
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-12-v5.19-net-mtk_eth_soc-stop-passing-phylink-state-to-sgmii-.patch
@@ -0,0 +1,60 @@
+From 4ce5a0bd3958ed248f0325bfcb95339f7c74feb2 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:54:57 +0100
+Subject: [PATCH 06/12] net: mtk_eth_soc: stop passing phylink state to sgmii
+ setup
+
+Now that mtk_sgmii_setup_mode_force() only uses the interface mode
+from the phylink state, pass just the interface mode into this
+function.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 2 +-
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h | 2 +-
+ drivers/net/ethernet/mediatek/mtk_sgmii.c   | 4 ++--
+ 3 files changed, 4 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -437,7 +437,7 @@ static void mtk_mac_config(struct phylin
+ 		/* Setup SGMIISYS with the determined property */
+ 		if (state->interface != PHY_INTERFACE_MODE_SGMII)
+ 			err = mtk_sgmii_setup_mode_force(eth->sgmii, sid,
+-							 state);
++							 state->interface);
+ 		else if (phylink_autoneg_inband(mode))
+ 			err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1102,7 +1102,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
+ 		   u32 ana_rgc3);
+ int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id);
+ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
+-			       const struct phylink_link_state *state);
++			       phy_interface_t interface);
+ void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex);
+ void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -65,7 +65,7 @@ int mtk_sgmii_setup_mode_an(struct mtk_s
+  * fixed speed.
+  */
+ int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
+-			       const struct phylink_link_state *state)
++			       phy_interface_t interface)
+ {
+ 	unsigned int val;
+ 
+@@ -74,7 +74,7 @@ int mtk_sgmii_setup_mode_force(struct mt
+ 
+ 	regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
+ 	val &= ~RG_PHY_SPEED_MASK;
+-	if (state->interface == PHY_INTERFACE_MODE_2500BASEX)
++	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+ 		val |= RG_PHY_SPEED_3_125G;
+ 	regmap_write(ss->regmap[id], ss->ana_rgc3, val);
+ 
diff --git a/target/linux/generic/backport-5.15/704-13-v5.19-net-mtk_eth_soc-provide-mtk_sgmii_config.patch b/target/linux/generic/backport-5.15/704-13-v5.19-net-mtk_eth_soc-provide-mtk_sgmii_config.patch
new file mode 100644
index 0000000000..4c91cf68f4
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-13-v5.19-net-mtk_eth_soc-provide-mtk_sgmii_config.patch
@@ -0,0 +1,89 @@
+From 1ec619ee4a052fb9ac48b57554ac2722a0bfe73c Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:55:02 +0100
+Subject: [PATCH 07/12] net: mtk_eth_soc: provide mtk_sgmii_config()
+
+Provide mtk_sgmii_config() to wrap up the decisions about which SGMII
+configuration will be called.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c |  7 +------
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h |  5 ++---
+ drivers/net/ethernet/mediatek/mtk_sgmii.c   | 20 +++++++++++++++++---
+ 3 files changed, 20 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -435,12 +435,7 @@ static void mtk_mac_config(struct phylin
+ 		       0 : mac->id;
+ 
+ 		/* Setup SGMIISYS with the determined property */
+-		if (state->interface != PHY_INTERFACE_MODE_SGMII)
+-			err = mtk_sgmii_setup_mode_force(eth->sgmii, sid,
+-							 state->interface);
+-		else if (phylink_autoneg_inband(mode))
+-			err = mtk_sgmii_setup_mode_an(eth->sgmii, sid);
+-
++		err = mtk_sgmii_config(eth->sgmii, sid, mode, state->interface);
+ 		if (err)
+ 			goto init_err;
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1100,9 +1100,8 @@ u32 mtk_r32(struct mtk_eth *eth, unsigne
+ 
+ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
+ 		   u32 ana_rgc3);
+-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id);
+-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
+-			       phy_interface_t interface);
++int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
++		     phy_interface_t interface);
+ void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex);
+ void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
+ 
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -35,7 +35,7 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
+ }
+ 
+ /* For SGMII interface mode */
+-int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
++static int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
+ {
+ 	unsigned int val;
+ 
+@@ -64,8 +64,8 @@ int mtk_sgmii_setup_mode_an(struct mtk_s
+ /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
+  * fixed speed.
+  */
+-int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
+-			       phy_interface_t interface)
++static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
++				      phy_interface_t interface)
+ {
+ 	unsigned int val;
+ 
+@@ -97,6 +97,20 @@ int mtk_sgmii_setup_mode_force(struct mt
+ 	return 0;
+ }
+ 
++int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
++		     phy_interface_t interface)
++{
++	int err = 0;
++
++	/* Setup SGMIISYS with the determined property */
++	if (interface != PHY_INTERFACE_MODE_SGMII)
++		err = mtk_sgmii_setup_mode_force(ss, id, interface);
++	else if (phylink_autoneg_inband(mode))
++		err = mtk_sgmii_setup_mode_an(ss, id);
++
++	return err;
++}
++
+ /* For 1000BASE-X and 2500BASE-X interface modes */
+ void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+ {
diff --git a/target/linux/generic/backport-5.15/704-14-v5.19-net-mtk_eth_soc-add-fixme-comment-for-state-speed-us.patch b/target/linux/generic/backport-5.15/704-14-v5.19-net-mtk_eth_soc-add-fixme-comment-for-state-speed-us.patch
new file mode 100644
index 0000000000..8080a2ca44
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-14-v5.19-net-mtk_eth_soc-add-fixme-comment-for-state-speed-us.patch
@@ -0,0 +1,38 @@
+From 650a49bc65df6b0e0051a8f62d7c22d95a8f350d Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:55:07 +0100
+Subject: [PATCH 08/12] net: mtk_eth_soc: add fixme comment for state->speed
+ use
+
+Add a fixme comment for the last remaining incorrect usage of
+state->speed in the mac_config() method, which is strangely in a code
+path which is only run when the PHY interface mode changes.
+
+This means if we are in RGMII mode, changes in state->speed will not
+cause the INTF_MODE, TRGMII_RCK_CTRL and TRGMII_TCK_CTRL registers to
+be set according to the speed, nor will the TRGPLL clock be set to the
+correct value.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -374,6 +374,14 @@ static void mtk_mac_config(struct phylin
+ 							      state->interface))
+ 					goto err_phy;
+ 			} else {
++				/* FIXME: this is incorrect. Not only does it
++				 * use state->speed (which is not guaranteed
++				 * to be correct) but it also makes use of it
++				 * in a code path that will only be reachable
++				 * when the PHY interface mode changes, not
++				 * when the speed changes. Consequently, RGMII
++				 * is probably broken.
++				 */
+ 				mtk_gmac0_rgmii_adjust(mac->hw,
+ 						       state->interface,
+ 						       state->speed);
diff --git a/target/linux/generic/backport-5.15/704-15-v5.19-net-mtk_eth_soc-move-MAC_MCR-setting-to-mac_finish.patch b/target/linux/generic/backport-5.15/704-15-v5.19-net-mtk_eth_soc-move-MAC_MCR-setting-to-mac_finish.patch
new file mode 100644
index 0000000000..368db4cca2
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-15-v5.19-net-mtk_eth_soc-move-MAC_MCR-setting-to-mac_finish.patch
@@ -0,0 +1,79 @@
+From 0e37ad71b2ff772009595002da2860999e98e14e Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:55:12 +0100
+Subject: [PATCH 09/12] net: mtk_eth_soc: move MAC_MCR setting to mac_finish()
+
+Move the setting of the MTK_MAC_MCR register from the end of mac_config
+into the phylink mac_finish() method, to keep it as the very last write
+that is done during configuration.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 33 ++++++++++++++-------
+ 1 file changed, 22 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -316,8 +316,8 @@ static void mtk_mac_config(struct phylin
+ 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ 					   phylink_config);
+ 	struct mtk_eth *eth = mac->hw;
+-	u32 mcr_cur, mcr_new, sid, i;
+ 	int val, ge_mode, err = 0;
++	u32 sid, i;
+ 
+ 	/* MT76x8 has no hardware settings between for the MAC */
+ 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
+@@ -455,16 +455,6 @@ static void mtk_mac_config(struct phylin
+ 		return;
+ 	}
+ 
+-	/* Setup gmac */
+-	mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+-	mcr_new = mcr_cur;
+-	mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
+-		   MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
+-
+-	/* Only update control register when needed! */
+-	if (mcr_new != mcr_cur)
+-		mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
+-
+ 	return;
+ 
+ err_phy:
+@@ -477,6 +467,26 @@ init_err:
+ 		mac->id, phy_modes(state->interface), err);
+ }
+ 
++static int mtk_mac_finish(struct phylink_config *config, unsigned int mode,
++			  phy_interface_t interface)
++{
++	struct mtk_mac *mac = container_of(config, struct mtk_mac,
++					   phylink_config);
++	u32 mcr_cur, mcr_new;
++
++	/* Setup gmac */
++	mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
++	mcr_new = mcr_cur;
++	mcr_new |= MAC_MCR_IPG_CFG | MAC_MCR_FORCE_MODE |
++		   MAC_MCR_BACKOFF_EN | MAC_MCR_BACKPR_EN | MAC_MCR_FORCE_LINK;
++
++	/* Only update control register when needed! */
++	if (mcr_new != mcr_cur)
++		mtk_w32(mac->hw, mcr_new, MTK_MAC_MCR(mac->id));
++
++	return 0;
++}
++
+ static void mtk_mac_pcs_get_state(struct phylink_config *config,
+ 				  struct phylink_link_state *state)
+ {
+@@ -581,6 +591,7 @@ static const struct phylink_mac_ops mtk_
+ 	.mac_pcs_get_state = mtk_mac_pcs_get_state,
+ 	.mac_an_restart = mtk_mac_an_restart,
+ 	.mac_config = mtk_mac_config,
++	.mac_finish = mtk_mac_finish,
+ 	.mac_link_down = mtk_mac_link_down,
+ 	.mac_link_up = mtk_mac_link_up,
+ };
diff --git a/target/linux/generic/backport-5.15/704-16-v5.19-net-mtk_eth_soc-move-restoration-of-SYSCFG0-to-mac_f.patch b/target/linux/generic/backport-5.15/704-16-v5.19-net-mtk_eth_soc-move-restoration-of-SYSCFG0-to-mac_f.patch
new file mode 100644
index 0000000000..ad6ec60288
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-16-v5.19-net-mtk_eth_soc-move-restoration-of-SYSCFG0-to-mac_f.patch
@@ -0,0 +1,57 @@
+From 21089867278deb2a110b685e3cd33f64f9ce41e2 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:55:17 +0100
+Subject: [PATCH 10/12] net: mtk_eth_soc: move restoration of SYSCFG0 to
+ mac_finish()
+
+The SGMIISYS configuration is performed while ETHSYS_SYSCFG0 is in a
+disabled state. In order to preserve this when we switch to phylink_pcs
+we need to move the restoration of this register to the mac_finish()
+callback.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 11 +++++++++--
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h |  1 +
+ 2 files changed, 10 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -447,8 +447,8 @@ static void mtk_mac_config(struct phylin
+ 		if (err)
+ 			goto init_err;
+ 
+-		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
+-				   SYSCFG0_SGMII_MASK, val);
++		/* Save the syscfg0 value for mac_finish */
++		mac->syscfg0 = val;
+ 	} else if (phylink_autoneg_inband(mode)) {
+ 		dev_err(eth->dev,
+ 			"In-band mode not supported in non SGMII mode!\n");
+@@ -472,8 +472,15 @@ static int mtk_mac_finish(struct phylink
+ {
+ 	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+ 					   phylink_config);
++	struct mtk_eth *eth = mac->hw;
+ 	u32 mcr_cur, mcr_new;
+ 
++	/* Enable SGMII */
++	if (interface == PHY_INTERFACE_MODE_SGMII ||
++	    phy_interface_mode_is_8023z(interface))
++		regmap_update_bits(eth->ethsys, ETHSYS_SYSCFG0,
++				   SYSCFG0_SGMII_MASK, mac->syscfg0);
++
+ 	/* Setup gmac */
+ 	mcr_cur = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ 	mcr_new = mcr_cur;
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -1087,6 +1087,7 @@ struct mtk_mac {
+ 	struct mtk_hw_stats		*hw_stats;
+ 	__be32				hwlro_ip[MTK_MAX_LRO_IP_CNT];
+ 	int				hwlro_ip_cnt;
++	unsigned int			syscfg0;
+ };
+ 
+ /* the struct describing the SoC. these are declared in the soc_xyz.c files */
diff --git a/target/linux/generic/backport-5.15/704-17-v5.19-net-mtk_eth_soc-convert-code-structure-to-suit-split.patch b/target/linux/generic/backport-5.15/704-17-v5.19-net-mtk_eth_soc-convert-code-structure-to-suit-split.patch
new file mode 100644
index 0000000000..623658f459
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-17-v5.19-net-mtk_eth_soc-convert-code-structure-to-suit-split.patch
@@ -0,0 +1,254 @@
+From 901f3fbe13c3e56f0742e02717ccbfabbc95c463 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:55:22 +0100
+Subject: [PATCH 11/12] net: mtk_eth_soc: convert code structure to suit split
+ PCS support
+
+Provide a mtk_pcs structure which encapsulates everything that the PCS
+functions need (the regmap and ana_rgc3 offset), and use this in the
+PCS functions. Provide shim functions to convert from the existing
+"mtk_sgmii_*" interface to the converted PCS functions.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h |  15 ++-
+ drivers/net/ethernet/mediatek/mtk_sgmii.c   | 123 +++++++++++---------
+ 2 files changed, 79 insertions(+), 59 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -958,16 +958,23 @@ struct mtk_soc_data {
+ /* currently no SoC has more than 2 macs */
+ #define MTK_MAX_DEVS			2
+ 
+-/* struct mtk_sgmii -  This is the structure holding sgmii regmap and its
+- *                     characteristics
++/* struct mtk_pcs -    This structure holds each sgmii regmap and associated
++ *                     data
+  * @regmap:            The register map pointing at the range used to setup
+  *                     SGMII modes
+  * @ana_rgc3:          The offset refers to register ANA_RGC3 related to regmap
+  */
++struct mtk_pcs {
++	struct regmap	*regmap;
++	u32             ana_rgc3;
++};
+ 
++/* struct mtk_sgmii -  This is the structure holding sgmii regmap and its
++ *                     characteristics
++ * @pcs                Array of individual PCS structures
++ */
+ struct mtk_sgmii {
+-	struct regmap   *regmap[MTK_MAX_DEVS];
+-	u32             ana_rgc3;
++	struct mtk_pcs	pcs[MTK_MAX_DEVS];
+ };
+ 
+ /* struct mtk_eth -	This is the main datasructure for holding the state
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -9,90 +9,71 @@
+ 
+ #include <linux/mfd/syscon.h>
+ #include <linux/of.h>
++#include <linux/phylink.h>
+ #include <linux/regmap.h>
+ 
+ #include "mtk_eth_soc.h"
+ 
+-int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+-{
+-	struct device_node *np;
+-	int i;
+-
+-	ss->ana_rgc3 = ana_rgc3;
+-
+-	for (i = 0; i < MTK_MAX_DEVS; i++) {
+-		np = of_parse_phandle(r, "mediatek,sgmiisys", i);
+-		if (!np)
+-			break;
+-
+-		ss->regmap[i] = syscon_node_to_regmap(np);
+-		of_node_put(np);
+-		if (IS_ERR(ss->regmap[i]))
+-			return PTR_ERR(ss->regmap[i]);
+-	}
+-
+-	return 0;
+-}
+-
+ /* For SGMII interface mode */
+-static int mtk_sgmii_setup_mode_an(struct mtk_sgmii *ss, int id)
++static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
+ {
+ 	unsigned int val;
+ 
+-	if (!ss->regmap[id])
++	if (!mpcs->regmap)
+ 		return -EINVAL;
+ 
+ 	/* Setup the link timer and QPHY power up inside SGMIISYS */
+-	regmap_write(ss->regmap[id], SGMSYS_PCS_LINK_TIMER,
++	regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
+ 		     SGMII_LINK_TIMER_DEFAULT);
+ 
+-	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
++	regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
+ 	val |= SGMII_REMOTE_FAULT_DIS;
+-	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
++	regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+ 
+-	regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
++	regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+ 	val |= SGMII_AN_RESTART;
+-	regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
++	regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+ 
+-	regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
++	regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ 	val &= ~SGMII_PHYA_PWD;
+-	regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
++	regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ 
+ 	return 0;
++
+ }
+ 
+ /* For 1000BASE-X and 2500BASE-X interface modes, which operate at a
+  * fixed speed.
+  */
+-static int mtk_sgmii_setup_mode_force(struct mtk_sgmii *ss, int id,
+-				      phy_interface_t interface)
++static int mtk_pcs_setup_mode_force(struct mtk_pcs *mpcs,
++				    phy_interface_t interface)
+ {
+ 	unsigned int val;
+ 
+-	if (!ss->regmap[id])
++	if (!mpcs->regmap)
+ 		return -EINVAL;
+ 
+-	regmap_read(ss->regmap[id], ss->ana_rgc3, &val);
++	regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
+ 	val &= ~RG_PHY_SPEED_MASK;
+ 	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+ 		val |= RG_PHY_SPEED_3_125G;
+-	regmap_write(ss->regmap[id], ss->ana_rgc3, val);
++	regmap_write(mpcs->regmap, mpcs->ana_rgc3, val);
+ 
+ 	/* Disable SGMII AN */
+-	regmap_read(ss->regmap[id], SGMSYS_PCS_CONTROL_1, &val);
++	regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+ 	val &= ~SGMII_AN_ENABLE;
+-	regmap_write(ss->regmap[id], SGMSYS_PCS_CONTROL_1, val);
++	regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+ 
+ 	/* Set the speed etc but leave the duplex unchanged */
+-	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
++	regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
+ 	val &= SGMII_DUPLEX_FULL | ~SGMII_IF_MODE_MASK;
+ 	val |= SGMII_SPEED_1000;
+-	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
++	regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+ 
+ 	/* Release PHYA power down state */
+-	regmap_read(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, &val);
++	regmap_read(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, &val);
+ 	val &= ~SGMII_PHYA_PWD;
+-	regmap_write(ss->regmap[id], SGMSYS_QPHY_PWR_STATE_CTRL, val);
++	regmap_write(mpcs->regmap, SGMSYS_QPHY_PWR_STATE_CTRL, val);
+ 
+ 	return 0;
+ }
+@@ -100,44 +81,76 @@ static int mtk_sgmii_setup_mode_force(st
+ int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
+ 		     phy_interface_t interface)
+ {
++	struct mtk_pcs *mpcs = &ss->pcs[id];
+ 	int err = 0;
+ 
+ 	/* Setup SGMIISYS with the determined property */
+ 	if (interface != PHY_INTERFACE_MODE_SGMII)
+-		err = mtk_sgmii_setup_mode_force(ss, id, interface);
++		err = mtk_pcs_setup_mode_force(mpcs, interface);
+ 	else if (phylink_autoneg_inband(mode))
+-		err = mtk_sgmii_setup_mode_an(ss, id);
++		err = mtk_pcs_setup_mode_an(mpcs);
+ 
+ 	return err;
+ }
+ 
+-/* For 1000BASE-X and 2500BASE-X interface modes */
+-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
++static void mtk_pcs_restart_an(struct mtk_pcs *mpcs)
++{
++	unsigned int val;
++
++	if (!mpcs->regmap)
++		return;
++
++	regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
++	val |= SGMII_AN_RESTART;
++	regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
++}
++
++static void mtk_pcs_link_up(struct mtk_pcs *mpcs, int speed, int duplex)
+ {
+ 	unsigned int val;
+ 
+ 	/* SGMII force duplex setting */
+-	regmap_read(ss->regmap[id], SGMSYS_SGMII_MODE, &val);
++	regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
+ 	val &= ~SGMII_DUPLEX_FULL;
+ 	if (duplex == DUPLEX_FULL)
+ 		val |= SGMII_DUPLEX_FULL;
+ 
+-	regmap_write(ss->regmap[id], SGMSYS_SGMII_MODE, val);
++	regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
++}
++
++/* For 1000BASE-X and 2500BASE-X interface modes */
++void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
++{
++	mtk_pcs_link_up(&ss->pcs[id], speed, duplex);
++}
++
++int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
++{
++	struct device_node *np;
++	int i;
++
++	for (i = 0; i < MTK_MAX_DEVS; i++) {
++		np = of_parse_phandle(r, "mediatek,sgmiisys", i);
++		if (!np)
++			break;
++
++		ss->pcs[i].ana_rgc3 = ana_rgc3;
++		ss->pcs[i].regmap = syscon_node_to_regmap(np);
++		of_node_put(np);
++		if (IS_ERR(ss->pcs[i].regmap))
++			return PTR_ERR(ss->pcs[i].regmap);
++	}
++
++	return 0;
+ }
+ 
+ void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
+ {
+-	struct mtk_sgmii *ss = eth->sgmii;
+-	unsigned int val, sid;
++	unsigned int sid;
+ 
+ 	/* Decide how GMAC and SGMIISYS be mapped */
+ 	sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
+ 	       0 : mac_id;
+ 
+-	if (!ss->regmap[sid])
+-		return;
+-
+-	regmap_read(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, &val);
+-	val |= SGMII_AN_RESTART;
+-	regmap_write(ss->regmap[sid], SGMSYS_PCS_CONTROL_1, val);
++	mtk_pcs_restart_an(&eth->sgmii->pcs[sid]);
+ }
diff --git a/target/linux/generic/backport-5.15/704-18-v5.19-net-mtk_eth_soc-partially-convert-to-phylink_pcs.patch b/target/linux/generic/backport-5.15/704-18-v5.19-net-mtk_eth_soc-partially-convert-to-phylink_pcs.patch
new file mode 100644
index 0000000000..df675e2899
--- /dev/null
+++ b/target/linux/generic/backport-5.15/704-18-v5.19-net-mtk_eth_soc-partially-convert-to-phylink_pcs.patch
@@ -0,0 +1,262 @@
+From 14a44ab0330d290fade1403a920e299cc56d7300 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Wed, 18 May 2022 15:55:28 +0100
+Subject: [PATCH 12/12] net: mtk_eth_soc: partially convert to phylink_pcs
+
+Partially convert mtk_eth_soc to phylink_pcs, moving the configuration,
+link up and AN restart over. However, it seems mac_pcs_get_state()
+doesn't actually get the state from the PCS, so we can't convert that
+over without a better understanding of the hardware.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/ethernet/mediatek/mtk_eth_soc.c | 49 ++++++++----------
+ drivers/net/ethernet/mediatek/mtk_eth_soc.h |  7 ++-
+ drivers/net/ethernet/mediatek/mtk_sgmii.c   | 55 +++++++++++----------
+ 3 files changed, 53 insertions(+), 58 deletions(-)
+
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
+@@ -310,6 +310,25 @@ static void mtk_gmac0_rgmii_adjust(struc
+ 	mtk_w32(eth, val, TRGMII_TCK_CTRL);
+ }
+ 
++static struct phylink_pcs *mtk_mac_select_pcs(struct phylink_config *config,
++					      phy_interface_t interface)
++{
++	struct mtk_mac *mac = container_of(config, struct mtk_mac,
++					   phylink_config);
++	struct mtk_eth *eth = mac->hw;
++	unsigned int sid;
++
++	if (interface == PHY_INTERFACE_MODE_SGMII ||
++	    phy_interface_mode_is_8023z(interface)) {
++		sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
++		       0 : mac->id;
++
++		return mtk_sgmii_select_pcs(eth->sgmii, sid);
++	}
++
++	return NULL;
++}
++
+ static void mtk_mac_config(struct phylink_config *config, unsigned int mode,
+ 			   const struct phylink_link_state *state)
+ {
+@@ -317,7 +336,7 @@ static void mtk_mac_config(struct phylin
+ 					   phylink_config);
+ 	struct mtk_eth *eth = mac->hw;
+ 	int val, ge_mode, err = 0;
+-	u32 sid, i;
++	u32 i;
+ 
+ 	/* MT76x8 has no hardware settings between for the MAC */
+ 	if (!MTK_HAS_CAPS(eth->soc->caps, MTK_SOC_MT7628) &&
+@@ -438,15 +457,6 @@ static void mtk_mac_config(struct phylin
+ 				   SYSCFG0_SGMII_MASK,
+ 				   ~(u32)SYSCFG0_SGMII_MASK);
+ 
+-		/* Decide how GMAC and SGMIISYS be mapped */
+-		sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
+-		       0 : mac->id;
+-
+-		/* Setup SGMIISYS with the determined property */
+-		err = mtk_sgmii_config(eth->sgmii, sid, mode, state->interface);
+-		if (err)
+-			goto init_err;
+-
+ 		/* Save the syscfg0 value for mac_finish */
+ 		mac->syscfg0 = val;
+ 	} else if (phylink_autoneg_inband(mode)) {
+@@ -526,14 +536,6 @@ static void mtk_mac_pcs_get_state(struct
+ 		state->pause |= MLO_PAUSE_TX;
+ }
+ 
+-static void mtk_mac_an_restart(struct phylink_config *config)
+-{
+-	struct mtk_mac *mac = container_of(config, struct mtk_mac,
+-					   phylink_config);
+-
+-	mtk_sgmii_restart_an(mac->hw, mac->id);
+-}
+-
+ static void mtk_mac_link_down(struct phylink_config *config, unsigned int mode,
+ 			      phy_interface_t interface)
+ {
+@@ -554,15 +556,6 @@ static void mtk_mac_link_up(struct phyli
+ 					   phylink_config);
+ 	u32 mcr;
+ 
+-	if (phy_interface_mode_is_8023z(interface)) {
+-		struct mtk_eth *eth = mac->hw;
+-
+-		/* Decide how GMAC and SGMIISYS be mapped */
+-		int sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
+-			   0 : mac->id;
+-		mtk_sgmii_link_up(eth->sgmii, sid, speed, duplex);
+-	}
+-
+ 	mcr = mtk_r32(mac->hw, MTK_MAC_MCR(mac->id));
+ 	mcr &= ~(MAC_MCR_SPEED_100 | MAC_MCR_SPEED_1000 |
+ 		 MAC_MCR_FORCE_DPX | MAC_MCR_FORCE_TX_FC |
+@@ -595,8 +588,8 @@ static void mtk_mac_link_up(struct phyli
+ 
+ static const struct phylink_mac_ops mtk_phylink_ops = {
+ 	.validate = phylink_generic_validate,
++	.mac_select_pcs = mtk_mac_select_pcs,
+ 	.mac_pcs_get_state = mtk_mac_pcs_get_state,
+-	.mac_an_restart = mtk_mac_an_restart,
+ 	.mac_config = mtk_mac_config,
+ 	.mac_finish = mtk_mac_finish,
+ 	.mac_link_down = mtk_mac_link_down,
+--- a/drivers/net/ethernet/mediatek/mtk_eth_soc.h
++++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.h
+@@ -963,10 +963,12 @@ struct mtk_soc_data {
+  * @regmap:            The register map pointing at the range used to setup
+  *                     SGMII modes
+  * @ana_rgc3:          The offset refers to register ANA_RGC3 related to regmap
++ * @pcs:               Phylink PCS structure
+  */
+ struct mtk_pcs {
+ 	struct regmap	*regmap;
+ 	u32             ana_rgc3;
++	struct phylink_pcs pcs;
+ };
+ 
+ /* struct mtk_sgmii -  This is the structure holding sgmii regmap and its
+@@ -1106,12 +1108,9 @@ void mtk_stats_update_mac(struct mtk_mac
+ void mtk_w32(struct mtk_eth *eth, u32 val, unsigned reg);
+ u32 mtk_r32(struct mtk_eth *eth, unsigned reg);
+ 
++struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id);
+ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *np,
+ 		   u32 ana_rgc3);
+-int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
+-		     phy_interface_t interface);
+-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex);
+-void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id);
+ 
+ int mtk_gmac_sgmii_path_setup(struct mtk_eth *eth, int mac_id);
+ int mtk_gmac_gephy_path_setup(struct mtk_eth *eth, int mac_id);
+--- a/drivers/net/ethernet/mediatek/mtk_sgmii.c
++++ b/drivers/net/ethernet/mediatek/mtk_sgmii.c
+@@ -14,14 +14,16 @@
+ 
+ #include "mtk_eth_soc.h"
+ 
++static struct mtk_pcs *pcs_to_mtk_pcs(struct phylink_pcs *pcs)
++{
++	return container_of(pcs, struct mtk_pcs, pcs);
++}
++
+ /* For SGMII interface mode */
+ static int mtk_pcs_setup_mode_an(struct mtk_pcs *mpcs)
+ {
+ 	unsigned int val;
+ 
+-	if (!mpcs->regmap)
+-		return -EINVAL;
+-
+ 	/* Setup the link timer and QPHY power up inside SGMIISYS */
+ 	regmap_write(mpcs->regmap, SGMSYS_PCS_LINK_TIMER,
+ 		     SGMII_LINK_TIMER_DEFAULT);
+@@ -50,9 +52,6 @@ static int mtk_pcs_setup_mode_force(stru
+ {
+ 	unsigned int val;
+ 
+-	if (!mpcs->regmap)
+-		return -EINVAL;
+-
+ 	regmap_read(mpcs->regmap, mpcs->ana_rgc3, &val);
+ 	val &= ~RG_PHY_SPEED_MASK;
+ 	if (interface == PHY_INTERFACE_MODE_2500BASEX)
+@@ -78,10 +77,12 @@ static int mtk_pcs_setup_mode_force(stru
+ 	return 0;
+ }
+ 
+-int mtk_sgmii_config(struct mtk_sgmii *ss, int id, unsigned int mode,
+-		     phy_interface_t interface)
++static int mtk_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
++			  phy_interface_t interface,
++			  const unsigned long *advertising,
++			  bool permit_pause_to_mac)
+ {
+-	struct mtk_pcs *mpcs = &ss->pcs[id];
++	struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ 	int err = 0;
+ 
+ 	/* Setup SGMIISYS with the determined property */
+@@ -93,22 +94,25 @@ int mtk_sgmii_config(struct mtk_sgmii *s
+ 	return err;
+ }
+ 
+-static void mtk_pcs_restart_an(struct mtk_pcs *mpcs)
++static void mtk_pcs_restart_an(struct phylink_pcs *pcs)
+ {
++	struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ 	unsigned int val;
+ 
+-	if (!mpcs->regmap)
+-		return;
+-
+ 	regmap_read(mpcs->regmap, SGMSYS_PCS_CONTROL_1, &val);
+ 	val |= SGMII_AN_RESTART;
+ 	regmap_write(mpcs->regmap, SGMSYS_PCS_CONTROL_1, val);
+ }
+ 
+-static void mtk_pcs_link_up(struct mtk_pcs *mpcs, int speed, int duplex)
++static void mtk_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
++			    phy_interface_t interface, int speed, int duplex)
+ {
++	struct mtk_pcs *mpcs = pcs_to_mtk_pcs(pcs);
+ 	unsigned int val;
+ 
++	if (!phy_interface_mode_is_8023z(interface))
++		return;
++
+ 	/* SGMII force duplex setting */
+ 	regmap_read(mpcs->regmap, SGMSYS_SGMII_MODE, &val);
+ 	val &= ~SGMII_DUPLEX_FULL;
+@@ -118,11 +122,11 @@ static void mtk_pcs_link_up(struct mtk_p
+ 	regmap_write(mpcs->regmap, SGMSYS_SGMII_MODE, val);
+ }
+ 
+-/* For 1000BASE-X and 2500BASE-X interface modes */
+-void mtk_sgmii_link_up(struct mtk_sgmii *ss, int id, int speed, int duplex)
+-{
+-	mtk_pcs_link_up(&ss->pcs[id], speed, duplex);
+-}
++static const struct phylink_pcs_ops mtk_pcs_ops = {
++	.pcs_config = mtk_pcs_config,
++	.pcs_an_restart = mtk_pcs_restart_an,
++	.pcs_link_up = mtk_pcs_link_up,
++};
+ 
+ int mtk_sgmii_init(struct mtk_sgmii *ss, struct device_node *r, u32 ana_rgc3)
+ {
+@@ -139,18 +143,17 @@ int mtk_sgmii_init(struct mtk_sgmii *ss,
+ 		of_node_put(np);
+ 		if (IS_ERR(ss->pcs[i].regmap))
+ 			return PTR_ERR(ss->pcs[i].regmap);
++
++		ss->pcs[i].pcs.ops = &mtk_pcs_ops;
+ 	}
+ 
+ 	return 0;
+ }
+ 
+-void mtk_sgmii_restart_an(struct mtk_eth *eth, int mac_id)
++struct phylink_pcs *mtk_sgmii_select_pcs(struct mtk_sgmii *ss, int id)
+ {
+-	unsigned int sid;
+-
+-	/* Decide how GMAC and SGMIISYS be mapped */
+-	sid = (MTK_HAS_CAPS(eth->soc->caps, MTK_SHARED_SGMII)) ?
+-	       0 : mac_id;
++	if (!ss->pcs[id].regmap)
++		return NULL;
+ 
+-	mtk_pcs_restart_an(&eth->sgmii->pcs[sid]);
++	return &ss->pcs[id].pcs;
+ }
diff --git a/target/linux/generic/backport-5.15/705-01-v5.17-net-dsa-mt7530-iterate-using-dsa_switch_for_each_use.patch b/target/linux/generic/backport-5.15/705-01-v5.17-net-dsa-mt7530-iterate-using-dsa_switch_for_each_use.patch
new file mode 100644
index 0000000000..74567109c5
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-01-v5.17-net-dsa-mt7530-iterate-using-dsa_switch_for_each_use.patch
@@ -0,0 +1,106 @@
+From 505560028b6deb9b4385cf6100f05ca6f4aacaf8 Mon Sep 17 00:00:00 2001
+From: Vladimir Oltean <vladimir.oltean at nxp.com>
+Date: Mon, 6 Dec 2021 18:57:49 +0200
+Subject: [PATCH 01/13] net: dsa: mt7530: iterate using
+ dsa_switch_for_each_user_port in bridging ops
+
+Avoid repeated calls to dsa_to_port() (some hidden behind dsa_is_user_port
+and some in plain sight) by keeping two struct dsa_port references: one
+to the port passed as argument, and another to the other ports of the
+switch that we're iterating over.
+
+dsa_to_port(ds, i) gets replaced by other_dp, i gets replaced by
+other_port which is derived from other_dp->index, dsa_is_user_port is
+handled by the DSA iterator.
+
+Signed-off-by: Vladimir Oltean <vladimir.oltean at nxp.com>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 52 +++++++++++++++++++++++-----------------
+ 1 file changed, 30 insertions(+), 22 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1188,27 +1188,31 @@ static int
+ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
+ 			struct net_device *bridge)
+ {
+-	struct mt7530_priv *priv = ds->priv;
++	struct dsa_port *dp = dsa_to_port(ds, port), *other_dp;
+ 	u32 port_bitmap = BIT(MT7530_CPU_PORT);
+-	int i;
++	struct mt7530_priv *priv = ds->priv;
+ 
+ 	mutex_lock(&priv->reg_mutex);
+ 
+-	for (i = 0; i < MT7530_NUM_PORTS; i++) {
++	dsa_switch_for_each_user_port(other_dp, ds) {
++		int other_port = other_dp->index;
++
++		if (dp == other_dp)
++			continue;
++
+ 		/* Add this port to the port matrix of the other ports in the
+ 		 * same bridge. If the port is disabled, port matrix is kept
+ 		 * and not being setup until the port becomes enabled.
+ 		 */
+-		if (dsa_is_user_port(ds, i) && i != port) {
+-			if (dsa_to_port(ds, i)->bridge_dev != bridge)
+-				continue;
+-			if (priv->ports[i].enable)
+-				mt7530_set(priv, MT7530_PCR_P(i),
+-					   PCR_MATRIX(BIT(port)));
+-			priv->ports[i].pm |= PCR_MATRIX(BIT(port));
++		if (other_dp->bridge_dev != bridge)
++			continue;
+ 
+-			port_bitmap |= BIT(i);
+-		}
++		if (priv->ports[other_port].enable)
++			mt7530_set(priv, MT7530_PCR_P(other_port),
++				   PCR_MATRIX(BIT(port)));
++		priv->ports[other_port].pm |= PCR_MATRIX(BIT(port));
++
++		port_bitmap |= BIT(other_port);
+ 	}
+ 
+ 	/* Add the all other ports to this port matrix. */
+@@ -1301,24 +1305,28 @@ static void
+ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
+ 			 struct net_device *bridge)
+ {
++	struct dsa_port *dp = dsa_to_port(ds, port), *other_dp;
+ 	struct mt7530_priv *priv = ds->priv;
+-	int i;
+ 
+ 	mutex_lock(&priv->reg_mutex);
+ 
+-	for (i = 0; i < MT7530_NUM_PORTS; i++) {
++	dsa_switch_for_each_user_port(other_dp, ds) {
++		int other_port = other_dp->index;
++
++		if (dp == other_dp)
++			continue;
++
+ 		/* Remove this port from the port matrix of the other ports
+ 		 * in the same bridge. If the port is disabled, port matrix
+ 		 * is kept and not being setup until the port becomes enabled.
+ 		 */
+-		if (dsa_is_user_port(ds, i) && i != port) {
+-			if (dsa_to_port(ds, i)->bridge_dev != bridge)
+-				continue;
+-			if (priv->ports[i].enable)
+-				mt7530_clear(priv, MT7530_PCR_P(i),
+-					     PCR_MATRIX(BIT(port)));
+-			priv->ports[i].pm &= ~PCR_MATRIX(BIT(port));
+-		}
++		if (other_dp->bridge_dev != bridge)
++			continue;
++
++		if (priv->ports[other_port].enable)
++			mt7530_clear(priv, MT7530_PCR_P(other_port),
++				     PCR_MATRIX(BIT(port)));
++		priv->ports[other_port].pm &= ~PCR_MATRIX(BIT(port));
+ 	}
+ 
+ 	/* Set the cpu port to be the only one in the port matrix of
diff --git a/target/linux/generic/backport-5.15/705-02-v5.19-net-dsa-mt7530-populate-supported_interfaces-and-mac.patch b/target/linux/generic/backport-5.15/705-02-v5.19-net-dsa-mt7530-populate-supported_interfaces-and-mac.patch
new file mode 100644
index 0000000000..690cc78fb5
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-02-v5.19-net-dsa-mt7530-populate-supported_interfaces-and-mac.patch
@@ -0,0 +1,166 @@
+From a1da54bcd664fc27169386db966575675ac3ccb0 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:01 +0100
+Subject: [PATCH 02/13] net: dsa: mt7530: populate supported_interfaces and
+ mac_capabilities
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Populate the supported interfaces and MAC capabilities for mt7530,
+mt7531 and mt7621 DSA switches. Filling this in will enable phylink
+to pre-check the PHY interface mode against the the supported
+interfaces bitmap prior to calling the validate function, and will
+eventually allow us to convert to using the generic validation.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 74 ++++++++++++++++++++++++++++++++++++++++
+ drivers/net/dsa/mt7530.h |  2 ++
+ 2 files changed, 76 insertions(+)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2385,6 +2385,32 @@ mt7531_setup(struct dsa_switch *ds)
+ 	return 0;
+ }
+ 
++static void mt7530_mac_port_get_caps(struct dsa_switch *ds, int port,
++				     struct phylink_config *config)
++{
++	switch (port) {
++	case 0 ... 4: /* Internal phy */
++		__set_bit(PHY_INTERFACE_MODE_GMII,
++			  config->supported_interfaces);
++		break;
++
++	case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
++		phy_interface_set_rgmii(config->supported_interfaces);
++		__set_bit(PHY_INTERFACE_MODE_MII,
++			  config->supported_interfaces);
++		__set_bit(PHY_INTERFACE_MODE_GMII,
++			  config->supported_interfaces);
++		break;
++
++	case 6: /* 1st cpu port */
++		__set_bit(PHY_INTERFACE_MODE_RGMII,
++			  config->supported_interfaces);
++		__set_bit(PHY_INTERFACE_MODE_TRGMII,
++			  config->supported_interfaces);
++		break;
++	}
++}
++
+ static bool
+ mt7530_phy_mode_supported(struct dsa_switch *ds, int port,
+ 			  const struct phylink_link_state *state)
+@@ -2421,6 +2447,37 @@ static bool mt7531_is_rgmii_port(struct
+ 	return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII);
+ }
+ 
++static void mt7531_mac_port_get_caps(struct dsa_switch *ds, int port,
++				     struct phylink_config *config)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	switch (port) {
++	case 0 ... 4: /* Internal phy */
++		__set_bit(PHY_INTERFACE_MODE_GMII,
++			  config->supported_interfaces);
++		break;
++
++	case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */
++		if (mt7531_is_rgmii_port(priv, port)) {
++			phy_interface_set_rgmii(config->supported_interfaces);
++			break;
++		}
++		fallthrough;
++
++	case 6: /* 1st cpu port supports sgmii/8023z only */
++		__set_bit(PHY_INTERFACE_MODE_SGMII,
++			  config->supported_interfaces);
++		__set_bit(PHY_INTERFACE_MODE_1000BASEX,
++			  config->supported_interfaces);
++		__set_bit(PHY_INTERFACE_MODE_2500BASEX,
++			  config->supported_interfaces);
++
++		config->mac_capabilities |= MAC_2500FD;
++		break;
++	}
++}
++
+ static bool
+ mt7531_phy_mode_supported(struct dsa_switch *ds, int port,
+ 			  const struct phylink_link_state *state)
+@@ -2899,6 +2956,18 @@ mt7531_cpu_port_config(struct dsa_switch
+ 	return 0;
+ }
+ 
++static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
++				    struct phylink_config *config)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	/* This switch only supports full-duplex at 1Gbps */
++	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
++				   MAC_10 | MAC_100 | MAC_1000FD;
++
++	priv->info->mac_port_get_caps(ds, port, config);
++}
++
+ static void
+ mt7530_mac_port_validate(struct dsa_switch *ds, int port,
+ 			 unsigned long *supported)
+@@ -3134,6 +3203,7 @@ static const struct dsa_switch_ops mt753
+ 	.port_vlan_del		= mt7530_port_vlan_del,
+ 	.port_mirror_add	= mt753x_port_mirror_add,
+ 	.port_mirror_del	= mt753x_port_mirror_del,
++	.phylink_get_caps	= mt753x_phylink_get_caps,
+ 	.phylink_validate	= mt753x_phylink_validate,
+ 	.phylink_mac_link_state	= mt753x_phylink_mac_link_state,
+ 	.phylink_mac_config	= mt753x_phylink_mac_config,
+@@ -3151,6 +3221,7 @@ static const struct mt753x_info mt753x_t
+ 		.phy_read = mt7530_phy_read,
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
++		.mac_port_get_caps = mt7530_mac_port_get_caps,
+ 		.phy_mode_supported = mt7530_phy_mode_supported,
+ 		.mac_port_validate = mt7530_mac_port_validate,
+ 		.mac_port_get_state = mt7530_phylink_mac_link_state,
+@@ -3162,6 +3233,7 @@ static const struct mt753x_info mt753x_t
+ 		.phy_read = mt7530_phy_read,
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
++		.mac_port_get_caps = mt7530_mac_port_get_caps,
+ 		.phy_mode_supported = mt7530_phy_mode_supported,
+ 		.mac_port_validate = mt7530_mac_port_validate,
+ 		.mac_port_get_state = mt7530_phylink_mac_link_state,
+@@ -3174,6 +3246,7 @@ static const struct mt753x_info mt753x_t
+ 		.phy_write = mt7531_ind_phy_write,
+ 		.pad_setup = mt7531_pad_setup,
+ 		.cpu_port_config = mt7531_cpu_port_config,
++		.mac_port_get_caps = mt7531_mac_port_get_caps,
+ 		.phy_mode_supported = mt7531_phy_mode_supported,
+ 		.mac_port_validate = mt7531_mac_port_validate,
+ 		.mac_port_get_state = mt7531_phylink_mac_link_state,
+@@ -3236,6 +3309,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ 	 */
+ 	if (!priv->info->sw_setup || !priv->info->pad_setup ||
+ 	    !priv->info->phy_read || !priv->info->phy_write ||
++	    !priv->info->mac_port_get_caps ||
+ 	    !priv->info->phy_mode_supported ||
+ 	    !priv->info->mac_port_validate ||
+ 	    !priv->info->mac_port_get_state || !priv->info->mac_port_config)
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -769,6 +769,8 @@ struct mt753x_info {
+ 	int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
+ 	int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
+ 	int (*cpu_port_config)(struct dsa_switch *ds, int port);
++	void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
++				  struct phylink_config *config);
+ 	bool (*phy_mode_supported)(struct dsa_switch *ds, int port,
+ 				   const struct phylink_link_state *state);
+ 	void (*mac_port_validate)(struct dsa_switch *ds, int port,
diff --git a/target/linux/generic/backport-5.15/705-03-v5.19-net-dsa-mt7530-remove-interface-checks.patch b/target/linux/generic/backport-5.15/705-03-v5.19-net-dsa-mt7530-remove-interface-checks.patch
new file mode 100644
index 0000000000..60eee013d1
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-03-v5.19-net-dsa-mt7530-remove-interface-checks.patch
@@ -0,0 +1,172 @@
+From e3f6719e2269868ca129b05da50cd55786848954 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:06 +0100
+Subject: [PATCH 03/13] net: dsa: mt7530: remove interface checks
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+As phylink checks the interface mode against the supported_interfaces
+bitmap, we no longer need to validate the interface mode, nor handle
+PHY_INTERFACE_MODE_NA in the validation function. Remove these to
+simplify the implementation.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 82 ----------------------------------------
+ drivers/net/dsa/mt7530.h |  2 -
+ 2 files changed, 84 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2411,37 +2411,6 @@ static void mt7530_mac_port_get_caps(str
+ 	}
+ }
+ 
+-static bool
+-mt7530_phy_mode_supported(struct dsa_switch *ds, int port,
+-			  const struct phylink_link_state *state)
+-{
+-	struct mt7530_priv *priv = ds->priv;
+-
+-	switch (port) {
+-	case 0 ... 4: /* Internal phy */
+-		if (state->interface != PHY_INTERFACE_MODE_GMII)
+-			return false;
+-		break;
+-	case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
+-		if (!phy_interface_mode_is_rgmii(state->interface) &&
+-		    state->interface != PHY_INTERFACE_MODE_MII &&
+-		    state->interface != PHY_INTERFACE_MODE_GMII)
+-			return false;
+-		break;
+-	case 6: /* 1st cpu port */
+-		if (state->interface != PHY_INTERFACE_MODE_RGMII &&
+-		    state->interface != PHY_INTERFACE_MODE_TRGMII)
+-			return false;
+-		break;
+-	default:
+-		dev_err(priv->dev, "%s: unsupported port: %i\n", __func__,
+-			port);
+-		return false;
+-	}
+-
+-	return true;
+-}
+-
+ static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port)
+ {
+ 	return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII);
+@@ -2478,44 +2447,6 @@ static void mt7531_mac_port_get_caps(str
+ 	}
+ }
+ 
+-static bool
+-mt7531_phy_mode_supported(struct dsa_switch *ds, int port,
+-			  const struct phylink_link_state *state)
+-{
+-	struct mt7530_priv *priv = ds->priv;
+-
+-	switch (port) {
+-	case 0 ... 4: /* Internal phy */
+-		if (state->interface != PHY_INTERFACE_MODE_GMII)
+-			return false;
+-		break;
+-	case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */
+-		if (mt7531_is_rgmii_port(priv, port))
+-			return phy_interface_mode_is_rgmii(state->interface);
+-		fallthrough;
+-	case 6: /* 1st cpu port supports sgmii/8023z only */
+-		if (state->interface != PHY_INTERFACE_MODE_SGMII &&
+-		    !phy_interface_mode_is_8023z(state->interface))
+-			return false;
+-		break;
+-	default:
+-		dev_err(priv->dev, "%s: unsupported port: %i\n", __func__,
+-			port);
+-		return false;
+-	}
+-
+-	return true;
+-}
+-
+-static bool
+-mt753x_phy_mode_supported(struct dsa_switch *ds, int port,
+-			  const struct phylink_link_state *state)
+-{
+-	struct mt7530_priv *priv = ds->priv;
+-
+-	return priv->info->phy_mode_supported(ds, port, state);
+-}
+-
+ static int
+ mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)
+ {
+@@ -2770,9 +2701,6 @@ mt753x_phylink_mac_config(struct dsa_swi
+ 	struct mt7530_priv *priv = ds->priv;
+ 	u32 mcr_cur, mcr_new;
+ 
+-	if (!mt753x_phy_mode_supported(ds, port, state))
+-		goto unsupported;
+-
+ 	switch (port) {
+ 	case 0 ... 4: /* Internal phy */
+ 		if (state->interface != PHY_INTERFACE_MODE_GMII)
+@@ -2990,12 +2918,6 @@ mt753x_phylink_validate(struct dsa_switc
+ 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+ 	struct mt7530_priv *priv = ds->priv;
+ 
+-	if (state->interface != PHY_INTERFACE_MODE_NA &&
+-	    !mt753x_phy_mode_supported(ds, port, state)) {
+-		linkmode_zero(supported);
+-		return;
+-	}
+-
+ 	phylink_set_port_modes(mask);
+ 
+ 	if (state->interface != PHY_INTERFACE_MODE_TRGMII &&
+@@ -3222,7 +3144,6 @@ static const struct mt753x_info mt753x_t
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
+ 		.mac_port_get_caps = mt7530_mac_port_get_caps,
+-		.phy_mode_supported = mt7530_phy_mode_supported,
+ 		.mac_port_validate = mt7530_mac_port_validate,
+ 		.mac_port_get_state = mt7530_phylink_mac_link_state,
+ 		.mac_port_config = mt7530_mac_config,
+@@ -3234,7 +3155,6 @@ static const struct mt753x_info mt753x_t
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
+ 		.mac_port_get_caps = mt7530_mac_port_get_caps,
+-		.phy_mode_supported = mt7530_phy_mode_supported,
+ 		.mac_port_validate = mt7530_mac_port_validate,
+ 		.mac_port_get_state = mt7530_phylink_mac_link_state,
+ 		.mac_port_config = mt7530_mac_config,
+@@ -3247,7 +3167,6 @@ static const struct mt753x_info mt753x_t
+ 		.pad_setup = mt7531_pad_setup,
+ 		.cpu_port_config = mt7531_cpu_port_config,
+ 		.mac_port_get_caps = mt7531_mac_port_get_caps,
+-		.phy_mode_supported = mt7531_phy_mode_supported,
+ 		.mac_port_validate = mt7531_mac_port_validate,
+ 		.mac_port_get_state = mt7531_phylink_mac_link_state,
+ 		.mac_port_config = mt7531_mac_config,
+@@ -3310,7 +3229,6 @@ mt7530_probe(struct mdio_device *mdiodev
+ 	if (!priv->info->sw_setup || !priv->info->pad_setup ||
+ 	    !priv->info->phy_read || !priv->info->phy_write ||
+ 	    !priv->info->mac_port_get_caps ||
+-	    !priv->info->phy_mode_supported ||
+ 	    !priv->info->mac_port_validate ||
+ 	    !priv->info->mac_port_get_state || !priv->info->mac_port_config)
+ 		return -EINVAL;
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -771,8 +771,6 @@ struct mt753x_info {
+ 	int (*cpu_port_config)(struct dsa_switch *ds, int port);
+ 	void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
+ 				  struct phylink_config *config);
+-	bool (*phy_mode_supported)(struct dsa_switch *ds, int port,
+-				   const struct phylink_link_state *state);
+ 	void (*mac_port_validate)(struct dsa_switch *ds, int port,
+ 				  unsigned long *supported);
+ 	int (*mac_port_get_state)(struct dsa_switch *ds, int port,
diff --git a/target/linux/generic/backport-5.15/705-04-v5.19-net-dsa-mt7530-drop-use-of-phylink_helper_basex_spee.patch b/target/linux/generic/backport-5.15/705-04-v5.19-net-dsa-mt7530-drop-use-of-phylink_helper_basex_spee.patch
new file mode 100644
index 0000000000..22bb2068de
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-04-v5.19-net-dsa-mt7530-drop-use-of-phylink_helper_basex_spee.patch
@@ -0,0 +1,34 @@
+From 58344a3b85f1bd5ffddfc2c11f6f2bf688b5f990 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:12 +0100
+Subject: [PATCH 04/13] net: dsa: mt7530: drop use of
+ phylink_helper_basex_speed()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Now that we have a better method to select SFP interface modes, we
+no longer need to use phylink_helper_basex_speed() in a driver's
+validation function.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 5 -----
+ 1 file changed, 5 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2942,11 +2942,6 @@ mt753x_phylink_validate(struct dsa_switc
+ 
+ 	linkmode_and(supported, supported, mask);
+ 	linkmode_and(state->advertising, state->advertising, mask);
+-
+-	/* We can only operate at 2500BaseX or 1000BaseX.  If requested
+-	 * to advertise both, only report advertising at 2500BaseX.
+-	 */
+-	phylink_helper_basex_speed(state);
+ }
+ 
+ static int
diff --git a/target/linux/generic/backport-5.15/705-05-v5.19-net-dsa-mt7530-only-indicate-linkmodes-that-can-be-s.patch b/target/linux/generic/backport-5.15/705-05-v5.19-net-dsa-mt7530-only-indicate-linkmodes-that-can-be-s.patch
new file mode 100644
index 0000000000..d5d7c54974
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-05-v5.19-net-dsa-mt7530-only-indicate-linkmodes-that-can-be-s.patch
@@ -0,0 +1,86 @@
+From 3c1d788a62dc648d1846049b66119ebb69dedd52 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:17 +0100
+Subject: [PATCH 05/13] net: dsa: mt7530: only indicate linkmodes that can be
+ supported
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Now that mt7530 is not using the basex helper, it becomes unnecessary to
+indicate support for both 1000baseX and 2500baseX when one of the 803.3z
+PHY interface modes is being selected. Ensure that the driver indicates
+only those linkmodes that can actually be supported by the PHY interface
+mode.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 12 ++++++++----
+ drivers/net/dsa/mt7530.h |  1 +
+ 2 files changed, 9 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2518,12 +2518,13 @@ static int mt7531_rgmii_setup(struct mt7
+ }
+ 
+ static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port,
++				  phy_interface_t interface,
+ 				  unsigned long *supported)
+ {
+ 	/* Port5 supports ethier RGMII or SGMII.
+ 	 * Port6 supports SGMII only.
+ 	 */
+-	if (port == 6) {
++	if (port == 6 && interface == PHY_INTERFACE_MODE_2500BASEX) {
+ 		phylink_set(supported, 2500baseX_Full);
+ 		phylink_set(supported, 2500baseT_Full);
+ 	}
+@@ -2898,16 +2899,18 @@ static void mt753x_phylink_get_caps(stru
+ 
+ static void
+ mt7530_mac_port_validate(struct dsa_switch *ds, int port,
++			 phy_interface_t interface,
+ 			 unsigned long *supported)
+ {
+ }
+ 
+ static void mt7531_mac_port_validate(struct dsa_switch *ds, int port,
++				     phy_interface_t interface,
+ 				     unsigned long *supported)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+ 
+-	mt7531_sgmii_validate(priv, port, supported);
++	mt7531_sgmii_validate(priv, port, interface, supported);
+ }
+ 
+ static void
+@@ -2930,12 +2933,13 @@ mt753x_phylink_validate(struct dsa_switc
+ 	}
+ 
+ 	/* This switch only supports 1G full-duplex. */
+-	if (state->interface != PHY_INTERFACE_MODE_MII) {
++	if (state->interface != PHY_INTERFACE_MODE_MII &&
++	    state->interface != PHY_INTERFACE_MODE_2500BASEX) {
+ 		phylink_set(mask, 1000baseT_Full);
+ 		phylink_set(mask, 1000baseX_Full);
+ 	}
+ 
+-	priv->info->mac_port_validate(ds, port, mask);
++	priv->info->mac_port_validate(ds, port, state->interface, mask);
+ 
+ 	phylink_set(mask, Pause);
+ 	phylink_set(mask, Asym_Pause);
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -772,6 +772,7 @@ struct mt753x_info {
+ 	void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
+ 				  struct phylink_config *config);
+ 	void (*mac_port_validate)(struct dsa_switch *ds, int port,
++				  phy_interface_t interface,
+ 				  unsigned long *supported);
+ 	int (*mac_port_get_state)(struct dsa_switch *ds, int port,
+ 				  struct phylink_link_state *state);
diff --git a/target/linux/generic/backport-5.15/705-06-v5.19-net-dsa-mt7530-switch-to-use-phylink_get_linkmodes.patch b/target/linux/generic/backport-5.15/705-06-v5.19-net-dsa-mt7530-switch-to-use-phylink_get_linkmodes.patch
new file mode 100644
index 0000000000..4a2c2f151d
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-06-v5.19-net-dsa-mt7530-switch-to-use-phylink_get_linkmodes.patch
@@ -0,0 +1,131 @@
+From 1c2211cb15dd3957fb26c0e1615eceb5db851ad6 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:22 +0100
+Subject: [PATCH 06/13] net: dsa: mt7530: switch to use phylink_get_linkmodes()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Switch mt7530 to use phylink_get_linkmodes() to generate the ethtool
+linkmodes that can be supported. We are unable to use the generic
+helper for this as pause modes are dependent on the interface as
+the Autoneg bit depends on the interface mode.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 57 ++++------------------------------------
+ 1 file changed, 5 insertions(+), 52 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2517,19 +2517,6 @@ static int mt7531_rgmii_setup(struct mt7
+ 	return 0;
+ }
+ 
+-static void mt7531_sgmii_validate(struct mt7530_priv *priv, int port,
+-				  phy_interface_t interface,
+-				  unsigned long *supported)
+-{
+-	/* Port5 supports ethier RGMII or SGMII.
+-	 * Port6 supports SGMII only.
+-	 */
+-	if (port == 6 && interface == PHY_INTERFACE_MODE_2500BASEX) {
+-		phylink_set(supported, 2500baseX_Full);
+-		phylink_set(supported, 2500baseT_Full);
+-	}
+-}
+-
+ static void
+ mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port,
+ 			   unsigned int mode, phy_interface_t interface,
+@@ -2898,51 +2885,21 @@ static void mt753x_phylink_get_caps(stru
+ }
+ 
+ static void
+-mt7530_mac_port_validate(struct dsa_switch *ds, int port,
+-			 phy_interface_t interface,
+-			 unsigned long *supported)
+-{
+-}
+-
+-static void mt7531_mac_port_validate(struct dsa_switch *ds, int port,
+-				     phy_interface_t interface,
+-				     unsigned long *supported)
+-{
+-	struct mt7530_priv *priv = ds->priv;
+-
+-	mt7531_sgmii_validate(priv, port, interface, supported);
+-}
+-
+-static void
+ mt753x_phylink_validate(struct dsa_switch *ds, int port,
+ 			unsigned long *supported,
+ 			struct phylink_link_state *state)
+ {
+ 	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+-	struct mt7530_priv *priv = ds->priv;
++	u32 caps;
++
++	caps = dsa_to_port(ds, port)->pl_config.mac_capabilities;
+ 
+ 	phylink_set_port_modes(mask);
++	phylink_get_linkmodes(mask, state->interface, caps);
+ 
+ 	if (state->interface != PHY_INTERFACE_MODE_TRGMII &&
+-	    !phy_interface_mode_is_8023z(state->interface)) {
+-		phylink_set(mask, 10baseT_Half);
+-		phylink_set(mask, 10baseT_Full);
+-		phylink_set(mask, 100baseT_Half);
+-		phylink_set(mask, 100baseT_Full);
++	    !phy_interface_mode_is_8023z(state->interface))
+ 		phylink_set(mask, Autoneg);
+-	}
+-
+-	/* This switch only supports 1G full-duplex. */
+-	if (state->interface != PHY_INTERFACE_MODE_MII &&
+-	    state->interface != PHY_INTERFACE_MODE_2500BASEX) {
+-		phylink_set(mask, 1000baseT_Full);
+-		phylink_set(mask, 1000baseX_Full);
+-	}
+-
+-	priv->info->mac_port_validate(ds, port, state->interface, mask);
+-
+-	phylink_set(mask, Pause);
+-	phylink_set(mask, Asym_Pause);
+ 
+ 	linkmode_and(supported, supported, mask);
+ 	linkmode_and(state->advertising, state->advertising, mask);
+@@ -3143,7 +3100,6 @@ static const struct mt753x_info mt753x_t
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
+ 		.mac_port_get_caps = mt7530_mac_port_get_caps,
+-		.mac_port_validate = mt7530_mac_port_validate,
+ 		.mac_port_get_state = mt7530_phylink_mac_link_state,
+ 		.mac_port_config = mt7530_mac_config,
+ 	},
+@@ -3154,7 +3110,6 @@ static const struct mt753x_info mt753x_t
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
+ 		.mac_port_get_caps = mt7530_mac_port_get_caps,
+-		.mac_port_validate = mt7530_mac_port_validate,
+ 		.mac_port_get_state = mt7530_phylink_mac_link_state,
+ 		.mac_port_config = mt7530_mac_config,
+ 	},
+@@ -3166,7 +3121,6 @@ static const struct mt753x_info mt753x_t
+ 		.pad_setup = mt7531_pad_setup,
+ 		.cpu_port_config = mt7531_cpu_port_config,
+ 		.mac_port_get_caps = mt7531_mac_port_get_caps,
+-		.mac_port_validate = mt7531_mac_port_validate,
+ 		.mac_port_get_state = mt7531_phylink_mac_link_state,
+ 		.mac_port_config = mt7531_mac_config,
+ 		.mac_pcs_an_restart = mt7531_sgmii_restart_an,
+@@ -3228,7 +3182,6 @@ mt7530_probe(struct mdio_device *mdiodev
+ 	if (!priv->info->sw_setup || !priv->info->pad_setup ||
+ 	    !priv->info->phy_read || !priv->info->phy_write ||
+ 	    !priv->info->mac_port_get_caps ||
+-	    !priv->info->mac_port_validate ||
+ 	    !priv->info->mac_port_get_state || !priv->info->mac_port_config)
+ 		return -EINVAL;
+ 
diff --git a/target/linux/generic/backport-5.15/705-07-v5.19-net-dsa-mt7530-partially-convert-to-phylink_pcs.patch b/target/linux/generic/backport-5.15/705-07-v5.19-net-dsa-mt7530-partially-convert-to-phylink_pcs.patch
new file mode 100644
index 0000000000..8a66b7fb0b
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-07-v5.19-net-dsa-mt7530-partially-convert-to-phylink_pcs.patch
@@ -0,0 +1,385 @@
+From fd993fd59d96d5e2d5972ec4ca1f9651025c987b Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:27 +0100
+Subject: [PATCH 07/13] net: dsa: mt7530: partially convert to phylink_pcs
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Partially convert the mt7530 driver to use phylink's PCS support. This
+is a partial implementation as we don't move anything into the
+pcs_config method yet - this driver supports SGMII or 1000BASE-X
+without in-band.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 144 +++++++++++++++++++++++----------------
+ drivers/net/dsa/mt7530.h |  21 +++---
+ 2 files changed, 95 insertions(+), 70 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -24,6 +24,11 @@
+ 
+ #include "mt7530.h"
+ 
++static struct mt753x_pcs *pcs_to_mt753x_pcs(struct phylink_pcs *pcs)
++{
++	return container_of(pcs, struct mt753x_pcs, pcs);
++}
++
+ /* String, offset, and register size in bytes if different from 4 bytes */
+ static const struct mt7530_mib_desc mt7530_mib[] = {
+ 	MIB_DESC(1, 0x00, "TxDrop"),
+@@ -2517,12 +2522,11 @@ static int mt7531_rgmii_setup(struct mt7
+ 	return 0;
+ }
+ 
+-static void
+-mt7531_sgmii_link_up_force(struct dsa_switch *ds, int port,
+-			   unsigned int mode, phy_interface_t interface,
+-			   int speed, int duplex)
++static void mt7531_pcs_link_up(struct phylink_pcs *pcs, unsigned int mode,
++			       phy_interface_t interface, int speed, int duplex)
+ {
+-	struct mt7530_priv *priv = ds->priv;
++	struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
++	int port = pcs_to_mt753x_pcs(pcs)->port;
+ 	unsigned int val;
+ 
+ 	/* For adjusting speed and duplex of SGMII force mode. */
+@@ -2548,6 +2552,9 @@ mt7531_sgmii_link_up_force(struct dsa_sw
+ 
+ 	/* MT7531 SGMII 1G force mode can only work in full duplex mode,
+ 	 * no matter MT7531_SGMII_FORCE_HALF_DUPLEX is set or not.
++	 *
++	 * The speed check is unnecessary as the MAC capabilities apply
++	 * this restriction. --rmk
+ 	 */
+ 	if ((speed == SPEED_10 || speed == SPEED_100) &&
+ 	    duplex != DUPLEX_FULL)
+@@ -2623,9 +2630,10 @@ static int mt7531_sgmii_setup_mode_an(st
+ 	return 0;
+ }
+ 
+-static void mt7531_sgmii_restart_an(struct dsa_switch *ds, int port)
++static void mt7531_pcs_an_restart(struct phylink_pcs *pcs)
+ {
+-	struct mt7530_priv *priv = ds->priv;
++	struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
++	int port = pcs_to_mt753x_pcs(pcs)->port;
+ 	u32 val;
+ 
+ 	/* Only restart AN when AN is enabled */
+@@ -2682,6 +2690,24 @@ mt753x_mac_config(struct dsa_switch *ds,
+ 	return priv->info->mac_port_config(ds, port, mode, state->interface);
+ }
+ 
++static struct phylink_pcs *
++mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port,
++			      phy_interface_t interface)
++{
++	struct mt7530_priv *priv = ds->priv;
++
++	switch (interface) {
++	case PHY_INTERFACE_MODE_TRGMII:
++	case PHY_INTERFACE_MODE_SGMII:
++	case PHY_INTERFACE_MODE_1000BASEX:
++	case PHY_INTERFACE_MODE_2500BASEX:
++		return &priv->pcs[port].pcs;
++
++	default:
++		return NULL;
++	}
++}
++
+ static void
+ mt753x_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ 			  const struct phylink_link_state *state)
+@@ -2743,17 +2769,6 @@ unsupported:
+ 		mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
+ }
+ 
+-static void
+-mt753x_phylink_mac_an_restart(struct dsa_switch *ds, int port)
+-{
+-	struct mt7530_priv *priv = ds->priv;
+-
+-	if (!priv->info->mac_pcs_an_restart)
+-		return;
+-
+-	priv->info->mac_pcs_an_restart(ds, port);
+-}
+-
+ static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port,
+ 					 unsigned int mode,
+ 					 phy_interface_t interface)
+@@ -2763,16 +2778,13 @@ static void mt753x_phylink_mac_link_down
+ 	mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+ }
+ 
+-static void mt753x_mac_pcs_link_up(struct dsa_switch *ds, int port,
+-				   unsigned int mode, phy_interface_t interface,
+-				   int speed, int duplex)
++static void mt753x_phylink_pcs_link_up(struct phylink_pcs *pcs,
++				       unsigned int mode,
++				       phy_interface_t interface,
++				       int speed, int duplex)
+ {
+-	struct mt7530_priv *priv = ds->priv;
+-
+-	if (!priv->info->mac_pcs_link_up)
+-		return;
+-
+-	priv->info->mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
++	if (pcs->ops->pcs_link_up)
++		pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex);
+ }
+ 
+ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
+@@ -2785,8 +2797,6 @@ static void mt753x_phylink_mac_link_up(s
+ 	struct mt7530_priv *priv = ds->priv;
+ 	u32 mcr;
+ 
+-	mt753x_mac_pcs_link_up(ds, port, mode, interface, speed, duplex);
+-
+ 	mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
+ 
+ 	/* MT753x MAC works in 1G full duplex mode for all up-clocked
+@@ -2866,6 +2876,8 @@ mt7531_cpu_port_config(struct dsa_switch
+ 		return ret;
+ 	mt7530_write(priv, MT7530_PMCR_P(port),
+ 		     PMCR_CPU_PORT_SETTING(priv->id));
++	mt753x_phylink_pcs_link_up(&priv->pcs[port].pcs, MLO_AN_FIXED,
++				   interface, speed, DUPLEX_FULL);
+ 	mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
+ 				   speed, DUPLEX_FULL, true, true);
+ 
+@@ -2905,16 +2917,13 @@ mt753x_phylink_validate(struct dsa_switc
+ 	linkmode_and(state->advertising, state->advertising, mask);
+ }
+ 
+-static int
+-mt7530_phylink_mac_link_state(struct dsa_switch *ds, int port,
+-			      struct phylink_link_state *state)
++static void mt7530_pcs_get_state(struct phylink_pcs *pcs,
++				 struct phylink_link_state *state)
+ {
+-	struct mt7530_priv *priv = ds->priv;
++	struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
++	int port = pcs_to_mt753x_pcs(pcs)->port;
+ 	u32 pmsr;
+ 
+-	if (port < 0 || port >= MT7530_NUM_PORTS)
+-		return -EINVAL;
+-
+ 	pmsr = mt7530_read(priv, MT7530_PMSR_P(port));
+ 
+ 	state->link = (pmsr & PMSR_LINK);
+@@ -2941,8 +2950,6 @@ mt7530_phylink_mac_link_state(struct dsa
+ 		state->pause |= MLO_PAUSE_RX;
+ 	if (pmsr & PMSR_TX_FC)
+ 		state->pause |= MLO_PAUSE_TX;
+-
+-	return 1;
+ }
+ 
+ static int
+@@ -2984,32 +2991,49 @@ mt7531_sgmii_pcs_get_state_an(struct mt7
+ 	return 0;
+ }
+ 
+-static int
+-mt7531_phylink_mac_link_state(struct dsa_switch *ds, int port,
+-			      struct phylink_link_state *state)
++static void mt7531_pcs_get_state(struct phylink_pcs *pcs,
++				 struct phylink_link_state *state)
+ {
+-	struct mt7530_priv *priv = ds->priv;
++	struct mt7530_priv *priv = pcs_to_mt753x_pcs(pcs)->priv;
++	int port = pcs_to_mt753x_pcs(pcs)->port;
+ 
+ 	if (state->interface == PHY_INTERFACE_MODE_SGMII)
+-		return mt7531_sgmii_pcs_get_state_an(priv, port, state);
+-
+-	return -EOPNOTSUPP;
++		mt7531_sgmii_pcs_get_state_an(priv, port, state);
++	else
++		state->link = false;
+ }
+ 
+-static int
+-mt753x_phylink_mac_link_state(struct dsa_switch *ds, int port,
+-			      struct phylink_link_state *state)
++static int mt753x_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
++			     phy_interface_t interface,
++			     const unsigned long *advertising,
++			     bool permit_pause_to_mac)
+ {
+-	struct mt7530_priv *priv = ds->priv;
++	return 0;
++}
+ 
+-	return priv->info->mac_port_get_state(ds, port, state);
++static void mt7530_pcs_an_restart(struct phylink_pcs *pcs)
++{
+ }
+ 
++static const struct phylink_pcs_ops mt7530_pcs_ops = {
++	.pcs_get_state = mt7530_pcs_get_state,
++	.pcs_config = mt753x_pcs_config,
++	.pcs_an_restart = mt7530_pcs_an_restart,
++};
++
++static const struct phylink_pcs_ops mt7531_pcs_ops = {
++	.pcs_get_state = mt7531_pcs_get_state,
++	.pcs_config = mt753x_pcs_config,
++	.pcs_an_restart = mt7531_pcs_an_restart,
++	.pcs_link_up = mt7531_pcs_link_up,
++};
++
+ static int
+ mt753x_setup(struct dsa_switch *ds)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+ 	int ret = priv->info->sw_setup(ds);
++	int i;
+ 
+ 	if (ret)
+ 		return ret;
+@@ -3022,6 +3046,13 @@ mt753x_setup(struct dsa_switch *ds)
+ 	if (ret && priv->irq)
+ 		mt7530_free_irq_common(priv);
+ 
++	/* Initialise the PCS devices */
++	for (i = 0; i < priv->ds->num_ports; i++) {
++		priv->pcs[i].pcs.ops = priv->info->pcs_ops;
++		priv->pcs[i].priv = priv;
++		priv->pcs[i].port = i;
++	}
++
+ 	return ret;
+ }
+ 
+@@ -3083,9 +3114,8 @@ static const struct dsa_switch_ops mt753
+ 	.port_mirror_del	= mt753x_port_mirror_del,
+ 	.phylink_get_caps	= mt753x_phylink_get_caps,
+ 	.phylink_validate	= mt753x_phylink_validate,
+-	.phylink_mac_link_state	= mt753x_phylink_mac_link_state,
++	.phylink_mac_select_pcs	= mt753x_phylink_mac_select_pcs,
+ 	.phylink_mac_config	= mt753x_phylink_mac_config,
+-	.phylink_mac_an_restart	= mt753x_phylink_mac_an_restart,
+ 	.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,
+@@ -3095,36 +3125,34 @@ static const struct dsa_switch_ops mt753
+ static const struct mt753x_info mt753x_table[] = {
+ 	[ID_MT7621] = {
+ 		.id = ID_MT7621,
++		.pcs_ops = &mt7530_pcs_ops,
+ 		.sw_setup = mt7530_setup,
+ 		.phy_read = mt7530_phy_read,
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
+ 		.mac_port_get_caps = mt7530_mac_port_get_caps,
+-		.mac_port_get_state = mt7530_phylink_mac_link_state,
+ 		.mac_port_config = mt7530_mac_config,
+ 	},
+ 	[ID_MT7530] = {
+ 		.id = ID_MT7530,
++		.pcs_ops = &mt7530_pcs_ops,
+ 		.sw_setup = mt7530_setup,
+ 		.phy_read = mt7530_phy_read,
+ 		.phy_write = mt7530_phy_write,
+ 		.pad_setup = mt7530_pad_clk_setup,
+ 		.mac_port_get_caps = mt7530_mac_port_get_caps,
+-		.mac_port_get_state = mt7530_phylink_mac_link_state,
+ 		.mac_port_config = mt7530_mac_config,
+ 	},
+ 	[ID_MT7531] = {
+ 		.id = ID_MT7531,
++		.pcs_ops = &mt7531_pcs_ops,
+ 		.sw_setup = mt7531_setup,
+ 		.phy_read = mt7531_ind_phy_read,
+ 		.phy_write = mt7531_ind_phy_write,
+ 		.pad_setup = mt7531_pad_setup,
+ 		.cpu_port_config = mt7531_cpu_port_config,
+ 		.mac_port_get_caps = mt7531_mac_port_get_caps,
+-		.mac_port_get_state = mt7531_phylink_mac_link_state,
+ 		.mac_port_config = mt7531_mac_config,
+-		.mac_pcs_an_restart = mt7531_sgmii_restart_an,
+-		.mac_pcs_link_up = mt7531_sgmii_link_up_force,
+ 	},
+ };
+ 
+@@ -3182,7 +3210,7 @@ mt7530_probe(struct mdio_device *mdiodev
+ 	if (!priv->info->sw_setup || !priv->info->pad_setup ||
+ 	    !priv->info->phy_read || !priv->info->phy_write ||
+ 	    !priv->info->mac_port_get_caps ||
+-	    !priv->info->mac_port_get_state || !priv->info->mac_port_config)
++	    !priv->info->mac_port_config)
+ 		return -EINVAL;
+ 
+ 	priv->id = priv->info->id;
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -741,6 +741,12 @@ static const char *p5_intf_modes(unsigne
+ 
+ struct mt7530_priv;
+ 
++struct mt753x_pcs {
++	struct phylink_pcs pcs;
++	struct mt7530_priv *priv;
++	int port;
++};
++
+ /* struct mt753x_info -	This is the main data structure for holding the specific
+  *			part for each supported device
+  * @sw_setup:		Holding the handler to a device initialization
+@@ -752,18 +758,14 @@ struct mt7530_priv;
+  *			port
+  * @mac_port_validate:	Holding the way to set addition validate type for a
+  *			certan MAC port
+- * @mac_port_get_state: Holding the way getting the MAC/PCS state for a certain
+- *			MAC port
+  * @mac_port_config:	Holding the way setting up the PHY attribute to a
+  *			certain MAC port
+- * @mac_pcs_an_restart	Holding the way restarting PCS autonegotiation for a
+- *			certain MAC port
+- * @mac_pcs_link_up:	Holding the way setting up the PHY attribute to the pcs
+- *			of the certain MAC port
+  */
+ struct mt753x_info {
+ 	enum mt753x_id id;
+ 
++	const struct phylink_pcs_ops *pcs_ops;
++
+ 	int (*sw_setup)(struct dsa_switch *ds);
+ 	int (*phy_read)(struct mt7530_priv *priv, int port, int regnum);
+ 	int (*phy_write)(struct mt7530_priv *priv, int port, int regnum, u16 val);
+@@ -774,15 +776,9 @@ struct mt753x_info {
+ 	void (*mac_port_validate)(struct dsa_switch *ds, int port,
+ 				  phy_interface_t interface,
+ 				  unsigned long *supported);
+-	int (*mac_port_get_state)(struct dsa_switch *ds, int port,
+-				  struct phylink_link_state *state);
+ 	int (*mac_port_config)(struct dsa_switch *ds, int port,
+ 			       unsigned int mode,
+ 			       phy_interface_t interface);
+-	void (*mac_pcs_an_restart)(struct dsa_switch *ds, int port);
+-	void (*mac_pcs_link_up)(struct dsa_switch *ds, int port,
+-				unsigned int mode, phy_interface_t interface,
+-				int speed, int duplex);
+ };
+ 
+ /* struct mt7530_priv -	This is the main data structure for holding the state
+@@ -824,6 +820,7 @@ struct mt7530_priv {
+ 	u8			mirror_tx;
+ 
+ 	struct mt7530_port	ports[MT7530_NUM_PORTS];
++	struct mt753x_pcs	pcs[MT7530_NUM_PORTS];
+ 	/* protect among processes for registers access*/
+ 	struct mutex reg_mutex;
+ 	int irq;
diff --git a/target/linux/generic/backport-5.15/705-08-v5.19-net-dsa-mt7530-move-autoneg-handling-to-PCS-validati.patch b/target/linux/generic/backport-5.15/705-08-v5.19-net-dsa-mt7530-move-autoneg-handling-to-PCS-validati.patch
new file mode 100644
index 0000000000..2d8b4d5d57
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-08-v5.19-net-dsa-mt7530-move-autoneg-handling-to-PCS-validati.patch
@@ -0,0 +1,80 @@
+From 2b0ee6768f3ac09072e5fd60b36580924e1cfa1c Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:32 +0100
+Subject: [PATCH 08/13] net: dsa: mt7530: move autoneg handling to PCS
+ validation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Move the autoneg bit handling to the PCS validation, which allows us to
+get rid of mt753x_phylink_validate() and rely on the default
+phylink_generic_validate() implementation for the MAC side.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 28 ++++++++++------------------
+ 1 file changed, 10 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2896,25 +2896,16 @@ static void mt753x_phylink_get_caps(stru
+ 	priv->info->mac_port_get_caps(ds, port, config);
+ }
+ 
+-static void
+-mt753x_phylink_validate(struct dsa_switch *ds, int port,
+-			unsigned long *supported,
+-			struct phylink_link_state *state)
+-{
+-	__ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, };
+-	u32 caps;
+-
+-	caps = dsa_to_port(ds, port)->pl_config.mac_capabilities;
+-
+-	phylink_set_port_modes(mask);
+-	phylink_get_linkmodes(mask, state->interface, caps);
++static int mt753x_pcs_validate(struct phylink_pcs *pcs,
++			       unsigned long *supported,
++			       const struct phylink_link_state *state)
++{
++	/* Autonegotiation is not supported in TRGMII nor 802.3z modes */
++	if (state->interface == PHY_INTERFACE_MODE_TRGMII ||
++	    phy_interface_mode_is_8023z(state->interface))
++		phylink_clear(supported, Autoneg);
+ 
+-	if (state->interface != PHY_INTERFACE_MODE_TRGMII &&
+-	    !phy_interface_mode_is_8023z(state->interface))
+-		phylink_set(mask, Autoneg);
+-
+-	linkmode_and(supported, supported, mask);
+-	linkmode_and(state->advertising, state->advertising, mask);
++	return 0;
+ }
+ 
+ static void mt7530_pcs_get_state(struct phylink_pcs *pcs,
+@@ -3016,12 +3007,14 @@ static void mt7530_pcs_an_restart(struct
+ }
+ 
+ static const struct phylink_pcs_ops mt7530_pcs_ops = {
++	.pcs_validate = mt753x_pcs_validate,
+ 	.pcs_get_state = mt7530_pcs_get_state,
+ 	.pcs_config = mt753x_pcs_config,
+ 	.pcs_an_restart = mt7530_pcs_an_restart,
+ };
+ 
+ static const struct phylink_pcs_ops mt7531_pcs_ops = {
++	.pcs_validate = mt753x_pcs_validate,
+ 	.pcs_get_state = mt7531_pcs_get_state,
+ 	.pcs_config = mt753x_pcs_config,
+ 	.pcs_an_restart = mt7531_pcs_an_restart,
+@@ -3113,7 +3106,6 @@ static const struct dsa_switch_ops mt753
+ 	.port_mirror_add	= mt753x_port_mirror_add,
+ 	.port_mirror_del	= mt753x_port_mirror_del,
+ 	.phylink_get_caps	= mt753x_phylink_get_caps,
+-	.phylink_validate	= mt753x_phylink_validate,
+ 	.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,
diff --git a/target/linux/generic/backport-5.15/705-09-v5.19-net-dsa-mt7530-mark-as-non-legacy.patch b/target/linux/generic/backport-5.15/705-09-v5.19-net-dsa-mt7530-mark-as-non-legacy.patch
new file mode 100644
index 0000000000..849a9925a1
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-09-v5.19-net-dsa-mt7530-mark-as-non-legacy.patch
@@ -0,0 +1,34 @@
+From 5bc26de9bfaa6bb5539c09d4435dced98f429cfc Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 11 Apr 2022 10:46:37 +0100
+Subject: [PATCH 09/13] net: dsa: mt7530: mark as non-legacy
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The mt7530 driver does not make use of the speed, duplex, pause or
+advertisement in its phylink_mac_config() implementation, so it can be
+marked as a non-legacy driver.
+
+Tested-by: Marek Behún <kabel at kernel.org>
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni at redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2893,6 +2893,12 @@ static void mt753x_phylink_get_caps(stru
+ 	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE |
+ 				   MAC_10 | MAC_100 | MAC_1000FD;
+ 
++	/* This driver does not make use of the speed, duplex, pause or the
++	 * advertisement in its mac_config, so it is safe to mark this driver
++	 * as non-legacy.
++	 */
++	config->legacy_pre_march2020 = false;
++
+ 	priv->info->mac_port_get_caps(ds, port, config);
+ }
+ 
diff --git a/target/linux/generic/backport-5.15/705-10-v5.19-net-dsa-mt753x-fix-pcs-conversion-regression.patch b/target/linux/generic/backport-5.15/705-10-v5.19-net-dsa-mt753x-fix-pcs-conversion-regression.patch
new file mode 100644
index 0000000000..89f6e7509b
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-10-v5.19-net-dsa-mt753x-fix-pcs-conversion-regression.patch
@@ -0,0 +1,116 @@
+From 1f15b5e8733115cee65342bcaafeaf0368809fae Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel at armlinux.org.uk>
+Date: Mon, 25 Apr 2022 22:28:02 +0100
+Subject: [PATCH 10/13] net: dsa: mt753x: fix pcs conversion regression
+
+Daniel Golle reports that the conversion of mt753x to phylink PCS caused
+an oops as below.
+
+The problem is with the placement of the PCS initialisation, which
+occurs after mt7531_setup() has been called. However, burited in this
+function is a call to setup the CPU port, which requires the PCS
+structure to be already setup.
+
+Fix this by changing the initialisation order.
+
+Unable to handle kernel NULL pointer dereference at virtual address 0000000000000020
+Mem abort info:
+  ESR = 0x96000005
+  EC = 0x25: DABT (current EL), IL = 32 bits
+  SET = 0, FnV = 0
+  EA = 0, S1PTW = 0
+  FSC = 0x05: level 1 translation fault
+Data abort info:
+  ISV = 0, ISS = 0x00000005
+  CM = 0, WnR = 0
+user pgtable: 4k pages, 39-bit VAs, pgdp=0000000046057000
+[0000000000000020] pgd=0000000000000000, p4d=0000000000000000, pud=0000000000000000
+Internal error: Oops: 96000005 [#1] SMP
+Modules linked in:
+CPU: 0 PID: 32 Comm: kworker/u4:1 Tainted: G S 5.18.0-rc3-next-20220422+ #0
+Hardware name: Bananapi BPI-R64 (DT)
+Workqueue: events_unbound deferred_probe_work_func
+pstate: 60000005 (nZCv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
+pc : mt7531_cpu_port_config+0xcc/0x1b0
+lr : mt7531_cpu_port_config+0xc0/0x1b0
+sp : ffffffc008d5b980
+x29: ffffffc008d5b990 x28: ffffff80060562c8 x27: 00000000f805633b
+x26: ffffff80001a8880 x25: 00000000000009c4 x24: 0000000000000016
+x23: ffffff8005eb6470 x22: 0000000000003600 x21: ffffff8006948080
+x20: 0000000000000000 x19: 0000000000000006 x18: 0000000000000000
+x17: 0000000000000001 x16: 0000000000000001 x15: 02963607fcee069e
+x14: 0000000000000000 x13: 0000000000000030 x12: 0101010101010101
+x11: ffffffc037302000 x10: 0000000000000870 x9 : ffffffc008d5b800
+x8 : ffffff800028f950 x7 : 0000000000000001 x6 : 00000000662b3000
+x5 : 00000000000002f0 x4 : 0000000000000000 x3 : ffffff800028f080
+x2 : 0000000000000000 x1 : ffffff800028f080 x0 : 0000000000000000
+Call trace:
+ mt7531_cpu_port_config+0xcc/0x1b0
+ mt753x_cpu_port_enable+0x24/0x1f0
+ mt7531_setup+0x49c/0x5c0
+ mt753x_setup+0x20/0x31c
+ dsa_register_switch+0x8bc/0x1020
+ mt7530_probe+0x118/0x200
+ mdio_probe+0x30/0x64
+ really_probe.part.0+0x98/0x280
+ __driver_probe_device+0x94/0x140
+ driver_probe_device+0x40/0x114
+ __device_attach_driver+0xb0/0x10c
+ bus_for_each_drv+0x64/0xa0
+ __device_attach+0xa8/0x16c
+ device_initial_probe+0x10/0x20
+ bus_probe_device+0x94/0x9c
+ deferred_probe_work_func+0x80/0xb4
+ process_one_work+0x200/0x3a0
+ worker_thread+0x260/0x4c0
+ kthread+0xd4/0xe0
+ ret_from_fork+0x10/0x20
+Code: 9409e911 937b7e60 8b0002a0 f9405800 (f9401005)
+---[ end trace 0000000000000000 ]---
+
+Reported-by: Daniel Golle <daniel at makrotopia.org>
+Tested-by: Daniel Golle <daniel at makrotopia.org>
+Fixes: cbd1f243bc41 ("net: dsa: mt7530: partially convert to phylink_pcs")
+Signed-off-by: Russell King (Oracle) <rmk+kernel at armlinux.org.uk>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Link: https://lore.kernel.org/r/E1nj6FW-007WZB-5Y@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 18 +++++++++---------
+ 1 file changed, 9 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -3031,9 +3031,16 @@ static int
+ mt753x_setup(struct dsa_switch *ds)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+-	int ret = priv->info->sw_setup(ds);
+-	int i;
++	int i, ret;
+ 
++	/* Initialise the PCS devices */
++	for (i = 0; i < priv->ds->num_ports; i++) {
++		priv->pcs[i].pcs.ops = priv->info->pcs_ops;
++		priv->pcs[i].priv = priv;
++		priv->pcs[i].port = i;
++	}
++
++	ret = priv->info->sw_setup(ds);
+ 	if (ret)
+ 		return ret;
+ 
+@@ -3045,13 +3052,6 @@ mt753x_setup(struct dsa_switch *ds)
+ 	if (ret && priv->irq)
+ 		mt7530_free_irq_common(priv);
+ 
+-	/* Initialise the PCS devices */
+-	for (i = 0; i < priv->ds->num_ports; i++) {
+-		priv->pcs[i].pcs.ops = priv->info->pcs_ops;
+-		priv->pcs[i].priv = priv;
+-		priv->pcs[i].port = i;
+-	}
+-
+ 	return ret;
+ }
+ 
diff --git a/target/linux/generic/backport-5.15/705-11-v6.0-net-dsa-mt7530-rework-mt7530_hw_vlan_-add-del.patch b/target/linux/generic/backport-5.15/705-11-v6.0-net-dsa-mt7530-rework-mt7530_hw_vlan_-add-del.patch
new file mode 100644
index 0000000000..77b4fa1102
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-11-v6.0-net-dsa-mt7530-rework-mt7530_hw_vlan_-add-del.patch
@@ -0,0 +1,87 @@
+From e26be16262e1fc1e9f1798c12762663bd9c265c6 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w at public-files.de>
+Date: Fri, 10 Jun 2022 19:05:37 +0200
+Subject: [PATCH 11/13] net: dsa: mt7530: rework mt7530_hw_vlan_{add,del}
+
+Rework vlan_add/vlan_del functions in preparation for dynamic cpu port.
+
+Currently BIT(MT7530_CPU_PORT) is added to new_members, even though
+mt7530_port_vlan_add() will be called on the CPU port too.
+
+Let DSA core decide when to call port_vlan_add for the CPU port, rather
+than doing it implicitly.
+
+We can do autonomous forwarding in a certain VLAN, but not add br0 to that
+VLAN and avoid flooding the CPU with those packets, if software knows it
+doesn't need to process them.
+
+Suggested-by: Vladimir Oltean <olteanv at gmail.com>
+Signed-off-by: Frank Wunderlich <frank-w at public-files.de>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 30 ++++++++++++------------------
+ 1 file changed, 12 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1522,11 +1522,11 @@ static void
+ mt7530_hw_vlan_add(struct mt7530_priv *priv,
+ 		   struct mt7530_hw_vlan_entry *entry)
+ {
++	struct dsa_port *dp = dsa_to_port(priv->ds, entry->port);
+ 	u8 new_members;
+ 	u32 val;
+ 
+-	new_members = entry->old_members | BIT(entry->port) |
+-		      BIT(MT7530_CPU_PORT);
++	new_members = entry->old_members | BIT(entry->port);
+ 
+ 	/* Validate the entry with independent learning, create egress tag per
+ 	 * VLAN and joining the port as one of the port members.
+@@ -1537,22 +1537,20 @@ mt7530_hw_vlan_add(struct mt7530_priv *p
+ 
+ 	/* Decide whether adding tag or not for those outgoing packets from the
+ 	 * port inside the VLAN.
+-	 */
+-	val = entry->untagged ? MT7530_VLAN_EGRESS_UNTAG :
+-				MT7530_VLAN_EGRESS_TAG;
+-	mt7530_rmw(priv, MT7530_VAWD2,
+-		   ETAG_CTRL_P_MASK(entry->port),
+-		   ETAG_CTRL_P(entry->port, val));
+-
+-	/* CPU port is always taken as a tagged port for serving more than one
++	 * CPU port is always taken as a tagged port for serving more than one
+ 	 * VLANs across and also being applied with egress type stack mode for
+ 	 * that VLAN tags would be appended after hardware special tag used as
+ 	 * DSA tag.
+ 	 */
++	if (dsa_port_is_cpu(dp))
++		val = MT7530_VLAN_EGRESS_STACK;
++	else if (entry->untagged)
++		val = MT7530_VLAN_EGRESS_UNTAG;
++	else
++		val = MT7530_VLAN_EGRESS_TAG;
+ 	mt7530_rmw(priv, MT7530_VAWD2,
+-		   ETAG_CTRL_P_MASK(MT7530_CPU_PORT),
+-		   ETAG_CTRL_P(MT7530_CPU_PORT,
+-			       MT7530_VLAN_EGRESS_STACK));
++		   ETAG_CTRL_P_MASK(entry->port),
++		   ETAG_CTRL_P(entry->port, val));
+ }
+ 
+ static void
+@@ -1571,11 +1569,7 @@ mt7530_hw_vlan_del(struct mt7530_priv *p
+ 		return;
+ 	}
+ 
+-	/* If certain member apart from CPU port is still alive in the VLAN,
+-	 * the entry would be kept valid. Otherwise, the entry is got to be
+-	 * disabled.
+-	 */
+-	if (new_members && new_members != BIT(MT7530_CPU_PORT)) {
++	if (new_members) {
+ 		val = IVL_MAC | VTAG_EN | PORT_MEM(new_members) |
+ 		      VLAN_VALID;
+ 		mt7530_write(priv, MT7530_VAWD1, val);
diff --git a/target/linux/generic/backport-5.15/705-12-v6.0-net-dsa-mt7530-rework-mt753-01-_setup.patch b/target/linux/generic/backport-5.15/705-12-v6.0-net-dsa-mt7530-rework-mt753-01-_setup.patch
new file mode 100644
index 0000000000..2324336ed8
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-12-v6.0-net-dsa-mt7530-rework-mt753-01-_setup.patch
@@ -0,0 +1,75 @@
+From 1f0dfd443eea7fc3e818e96f7c8264913ba41859 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w at public-files.de>
+Date: Fri, 10 Jun 2022 19:05:38 +0200
+Subject: [PATCH 12/13] net: dsa: mt7530: rework mt753[01]_setup
+
+Enumerate available cpu-ports instead of using hardcoded constant.
+
+Suggested-by: Vladimir Oltean <olteanv at gmail.com>
+Signed-off-by: Frank Wunderlich <frank-w at public-files.de>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 25 +++++++++++++++++++++----
+ 1 file changed, 21 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2087,11 +2087,12 @@ static int
+ mt7530_setup(struct dsa_switch *ds)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
++	struct device_node *dn = NULL;
+ 	struct device_node *phy_node;
+ 	struct device_node *mac_np;
+ 	struct mt7530_dummy_poll p;
+ 	phy_interface_t interface;
+-	struct device_node *dn;
++	struct dsa_port *cpu_dp;
+ 	u32 id, val;
+ 	int ret, i;
+ 
+@@ -2099,7 +2100,19 @@ mt7530_setup(struct dsa_switch *ds)
+ 	 * controller also is the container for two GMACs nodes representing
+ 	 * as two netdev instances.
+ 	 */
+-	dn = dsa_to_port(ds, MT7530_CPU_PORT)->master->dev.of_node->parent;
++	dsa_switch_for_each_cpu_port(cpu_dp, ds) {
++		dn = cpu_dp->master->dev.of_node->parent;
++		/* It doesn't matter which CPU port is found first,
++		 * their masters should share the same parent OF node
++		 */
++		break;
++	}
++
++	if (!dn) {
++		dev_err(ds->dev, "parent OF node of DSA master not found");
++		return -EINVAL;
++	}
++
+ 	ds->assisted_learning_on_cpu_port = true;
+ 	ds->mtu_enforcement_ingress = true;
+ 
+@@ -2261,6 +2274,7 @@ mt7531_setup(struct dsa_switch *ds)
+ {
+ 	struct mt7530_priv *priv = ds->priv;
+ 	struct mt7530_dummy_poll p;
++	struct dsa_port *cpu_dp;
+ 	u32 val, id;
+ 	int ret, i;
+ 
+@@ -2333,8 +2347,11 @@ mt7531_setup(struct dsa_switch *ds)
+ 				 CORE_PLL_GROUP4, val);
+ 
+ 	/* BPDU to CPU port */
+-	mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
+-		   BIT(MT7530_CPU_PORT));
++	dsa_switch_for_each_cpu_port(cpu_dp, ds) {
++		mt7530_rmw(priv, MT7531_CFC, MT7531_CPU_PMAP_MASK,
++			   BIT(cpu_dp->index));
++		break;
++	}
+ 	mt7530_rmw(priv, MT753X_BPC, MT753X_BPDU_PORT_FW_MASK,
+ 		   MT753X_BPDU_CPU_ONLY);
+ 
diff --git a/target/linux/generic/backport-5.15/705-13-v6.0-net-dsa-mt7530-get-cpu-port-via-dp-cpu_dp-instead-of.patch b/target/linux/generic/backport-5.15/705-13-v6.0-net-dsa-mt7530-get-cpu-port-via-dp-cpu_dp-instead-of.patch
new file mode 100644
index 0000000000..3b5ce7363f
--- /dev/null
+++ b/target/linux/generic/backport-5.15/705-13-v6.0-net-dsa-mt7530-get-cpu-port-via-dp-cpu_dp-instead-of.patch
@@ -0,0 +1,117 @@
+From ad2606f6fafae3a7d41c4f2af5554c8f6adecbc7 Mon Sep 17 00:00:00 2001
+From: Frank Wunderlich <frank-w at public-files.de>
+Date: Fri, 10 Jun 2022 19:05:39 +0200
+Subject: [PATCH 13/13] net: dsa: mt7530: get cpu-port via dp->cpu_dp instead
+ of constant
+
+Replace last occurences of hardcoded cpu-port by cpu_dp member of
+dsa_port struct.
+
+Now the constant can be dropped.
+
+Suggested-by: Vladimir Oltean <olteanv at gmail.com>
+Signed-off-by: Frank Wunderlich <frank-w at public-files.de>
+Reviewed-by: Vladimir Oltean <olteanv at gmail.com>
+Reviewed-by: Florian Fainelli <f.fainelli at gmail.com>
+Signed-off-by: Jakub Kicinski <kuba at kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 27 ++++++++++++++++++++-------
+ drivers/net/dsa/mt7530.h |  1 -
+ 2 files changed, 20 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1038,6 +1038,7 @@ static int
+ mt7530_port_enable(struct dsa_switch *ds, int port,
+ 		   struct phy_device *phy)
+ {
++	struct dsa_port *dp = dsa_to_port(ds, port);
+ 	struct mt7530_priv *priv = ds->priv;
+ 
+ 	mutex_lock(&priv->reg_mutex);
+@@ -1046,7 +1047,11 @@ mt7530_port_enable(struct dsa_switch *ds
+ 	 * restore the port matrix if the port is the member of a certain
+ 	 * bridge.
+ 	 */
+-	priv->ports[port].pm |= PCR_MATRIX(BIT(MT7530_CPU_PORT));
++	if (dsa_port_is_user(dp)) {
++		struct dsa_port *cpu_dp = dp->cpu_dp;
++
++		priv->ports[port].pm |= PCR_MATRIX(BIT(cpu_dp->index));
++	}
+ 	priv->ports[port].enable = true;
+ 	mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
+ 		   priv->ports[port].pm);
+@@ -1194,7 +1199,8 @@ mt7530_port_bridge_join(struct dsa_switc
+ 			struct net_device *bridge)
+ {
+ 	struct dsa_port *dp = dsa_to_port(ds, port), *other_dp;
+-	u32 port_bitmap = BIT(MT7530_CPU_PORT);
++	struct dsa_port *cpu_dp = dp->cpu_dp;
++	u32 port_bitmap = BIT(cpu_dp->index);
+ 	struct mt7530_priv *priv = ds->priv;
+ 
+ 	mutex_lock(&priv->reg_mutex);
+@@ -1271,9 +1277,12 @@ mt7530_port_set_vlan_unaware(struct dsa_
+ 	 * the CPU port get out of VLAN filtering mode.
+ 	 */
+ 	if (all_user_ports_removed) {
+-		mt7530_write(priv, MT7530_PCR_P(MT7530_CPU_PORT),
++		struct dsa_port *dp = dsa_to_port(ds, port);
++		struct dsa_port *cpu_dp = dp->cpu_dp;
++
++		mt7530_write(priv, MT7530_PCR_P(cpu_dp->index),
+ 			     PCR_MATRIX(dsa_user_ports(priv->ds)));
+-		mt7530_write(priv, MT7530_PVC_P(MT7530_CPU_PORT), PORT_SPEC_TAG
++		mt7530_write(priv, MT7530_PVC_P(cpu_dp->index), PORT_SPEC_TAG
+ 			     | PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
+ 	}
+ }
+@@ -1311,6 +1320,7 @@ mt7530_port_bridge_leave(struct dsa_swit
+ 			 struct net_device *bridge)
+ {
+ 	struct dsa_port *dp = dsa_to_port(ds, port), *other_dp;
++	struct dsa_port *cpu_dp = dp->cpu_dp;
+ 	struct mt7530_priv *priv = ds->priv;
+ 
+ 	mutex_lock(&priv->reg_mutex);
+@@ -1339,8 +1349,8 @@ mt7530_port_bridge_leave(struct dsa_swit
+ 	 */
+ 	if (priv->ports[port].enable)
+ 		mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
+-			   PCR_MATRIX(BIT(MT7530_CPU_PORT)));
+-	priv->ports[port].pm = PCR_MATRIX(BIT(MT7530_CPU_PORT));
++			   PCR_MATRIX(BIT(cpu_dp->index)));
++	priv->ports[port].pm = PCR_MATRIX(BIT(cpu_dp->index));
+ 
+ 	/* When a port is removed from the bridge, the port would be set up
+ 	 * back to the default as is at initial boot which is a VLAN-unaware
+@@ -1503,6 +1513,9 @@ static int
+ mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
+ 			   struct netlink_ext_ack *extack)
+ {
++	struct dsa_port *dp = dsa_to_port(ds, port);
++	struct dsa_port *cpu_dp = dp->cpu_dp;
++
+ 	if (vlan_filtering) {
+ 		/* The port is being kept as VLAN-unaware port when bridge is
+ 		 * set up with vlan_filtering not being set, Otherwise, the
+@@ -1510,7 +1523,7 @@ mt7530_port_vlan_filtering(struct dsa_sw
+ 		 * for becoming a VLAN-aware port.
+ 		 */
+ 		mt7530_port_set_vlan_aware(ds, port);
+-		mt7530_port_set_vlan_aware(ds, MT7530_CPU_PORT);
++		mt7530_port_set_vlan_aware(ds, cpu_dp->index);
+ 	} else {
+ 		mt7530_port_set_vlan_unaware(ds, port);
+ 	}
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -8,7 +8,6 @@
+ 
+ #define MT7530_NUM_PORTS		7
+ #define MT7530_NUM_PHYS			5
+-#define MT7530_CPU_PORT			6
+ #define MT7530_NUM_FDB_RECORDS		2048
+ #define MT7530_ALL_MEMBERS		0xff
+ 
diff --git a/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch
index 1786bf0345..77cf63b809 100644
--- a/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch
+++ b/target/linux/generic/backport-5.15/765-1-net-next-net-dsa-reorder-PHY-initialization-with-MTU-setup-in.patch
@@ -22,7 +22,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
 
 --- a/net/dsa/slave.c
 +++ b/net/dsa/slave.c
-@@ -1986,13 +1986,6 @@ int dsa_slave_create(struct dsa_port *po
+@@ -1977,13 +1977,6 @@ int dsa_slave_create(struct dsa_port *po
  	port->slave = slave_dev;
  	dsa_slave_setup_tagger(slave_dev);
  
@@ -36,7 +36,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  	netif_carrier_off(slave_dev);
  
  	ret = dsa_slave_phy_setup(slave_dev);
-@@ -2004,6 +1997,13 @@ int dsa_slave_create(struct dsa_port *po
+@@ -1995,6 +1988,13 @@ int dsa_slave_create(struct dsa_port *po
  	}
  
  	rtnl_lock();
diff --git a/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch
index c2493a08fd..50aa5d8f0d 100644
--- a/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch
+++ b/target/linux/generic/backport-5.15/765-2-net-next-net-dsa-merge-rtnl_lock-sections-in-dsa_slave_create.patch
@@ -16,7 +16,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
 
 --- a/net/dsa/slave.c
 +++ b/net/dsa/slave.c
-@@ -1997,14 +1997,12 @@ int dsa_slave_create(struct dsa_port *po
+@@ -1988,14 +1988,12 @@ int dsa_slave_create(struct dsa_port *po
  	}
  
  	rtnl_lock();
diff --git a/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch
index d73b745586..7c6a3a3f8d 100644
--- a/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch
+++ b/target/linux/generic/backport-5.15/766-01-net-dsa-provide-switch-operations-for-tracking-the-m.patch
@@ -68,7 +68,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p)
  {
  	return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED;
-@@ -916,6 +926,13 @@ struct dsa_switch_ops {
+@@ -949,6 +959,13 @@ struct dsa_switch_ops {
  	int	(*tag_8021q_vlan_add)(struct dsa_switch *ds, int port, u16 vid,
  				      u16 flags);
  	int	(*tag_8021q_vlan_del)(struct dsa_switch *ds, int port, u16 vid);
@@ -175,7 +175,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  
 --- a/net/dsa/slave.c
 +++ b/net/dsa/slave.c
-@@ -2320,6 +2320,36 @@ static int dsa_slave_netdevice_event(str
+@@ -2311,6 +2311,36 @@ static int dsa_slave_netdevice_event(str
  		err = dsa_port_lag_change(dp, info->lower_state_info);
  		return notifier_from_errno(err);
  	}
@@ -212,7 +212,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  	case NETDEV_GOING_DOWN: {
  		struct dsa_port *dp, *cpu_dp;
  		struct dsa_switch_tree *dst;
-@@ -2331,6 +2361,8 @@ static int dsa_slave_netdevice_event(str
+@@ -2322,6 +2352,8 @@ static int dsa_slave_netdevice_event(str
  		cpu_dp = dev->dsa_ptr;
  		dst = cpu_dp->ds->dst;
  
diff --git a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch
index 4b5c474204..e3e338bd4f 100644
--- a/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch
+++ b/target/linux/generic/pending-5.15/702-net-ethernet-mtk_eth_soc-enable-threaded-NAPI.patch
@@ -10,7 +10,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
 
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -2443,8 +2443,8 @@ static irqreturn_t mtk_handle_irq_rx(int
+@@ -2381,8 +2381,8 @@ static irqreturn_t mtk_handle_irq_rx(int
  
  	eth->rx_events++;
  	if (likely(napi_schedule_prep(&eth->rx_napi))) {
@@ -20,7 +20,7 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  	}
  
  	return IRQ_HANDLED;
-@@ -2456,8 +2456,8 @@ static irqreturn_t mtk_handle_irq_tx(int
+@@ -2394,8 +2394,8 @@ static irqreturn_t mtk_handle_irq_tx(int
  
  	eth->tx_events++;
  	if (likely(napi_schedule_prep(&eth->tx_napi))) {
@@ -30,12 +30,12 @@ Signed-off-by: Felix Fietkau <nbd at nbd.name>
  	}
  
  	return IRQ_HANDLED;
-@@ -3623,6 +3623,8 @@ static int mtk_probe(struct platform_dev
+@@ -3585,6 +3585,8 @@ static int mtk_probe(struct platform_dev
  	 * for NAPI to work
  	 */
  	init_dummy_netdev(&eth->dummy_dev);
 +	eth->dummy_dev.threaded = 1;
 +	strcpy(eth->dummy_dev.name, "mtk_eth");
  	netif_napi_add(&eth->dummy_dev, &eth->tx_napi, mtk_napi_tx,
- 		       MTK_NAPI_WEIGHT);
+ 		       NAPI_POLL_WEIGHT);
  	netif_napi_add(&eth->dummy_dev, &eth->rx_napi, mtk_napi_rx,
diff --git a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch
index 24b64c6ce6..d6e7f40f3b 100644
--- a/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch
+++ b/target/linux/generic/pending-5.15/703-phy-add-detach-callback-to-struct-phy_driver.patch
@@ -23,7 +23,7 @@ Signed-off-by: Gabor Juhos <juhosg at openwrt.org>
  			sysfs_remove_link(&dev->dev.kobj, "phydev");
 --- a/include/linux/phy.h
 +++ b/include/linux/phy.h
-@@ -789,6 +789,12 @@ struct phy_driver {
+@@ -823,6 +823,12 @@ struct phy_driver {
  	/** @handle_interrupt: Override default interrupt handling */
  	irqreturn_t (*handle_interrupt)(struct phy_device *phydev);
  
diff --git a/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch b/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch
index deb25e652d..4c0d1001e0 100644
--- a/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch
+++ b/target/linux/mediatek/patches-5.15/510-net-mediatek-add-flow-offload-for-mt7623.patch
@@ -14,7 +14,7 @@ Signed-off-by: Frank Wunderlich <frank-w at public-files.de>
 
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -3675,6 +3675,7 @@ static const struct mtk_soc_data mt2701_
+@@ -3637,6 +3637,7 @@ static const struct mtk_soc_data mt2701_
  	.hw_features = MTK_HW_FEATURES,
  	.required_clks = MT7623_CLKS_BITMAP,
  	.required_pctl = true,
diff --git a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch
index 45c650b34a..de1079ffae 100644
--- a/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch
+++ b/target/linux/mediatek/patches-5.15/703-v5.17-net-ethernet-mtk_eth_soc-implement-Clause-45-MDIO-ac.patch
@@ -103,7 +103,7 @@ Signed-off-by: David S. Miller <davem at davemloft.net>
  
  	ret = mtk_mdio_busy_wait(eth);
  	if (ret < 0)
-@@ -683,6 +726,7 @@ static int mtk_mdio_init(struct mtk_eth
+@@ -621,6 +664,7 @@ static int mtk_mdio_init(struct mtk_eth
  	eth->mii_bus->name = "mdio";
  	eth->mii_bus->read = mtk_mdio_read;
  	eth->mii_bus->write = mtk_mdio_write;
diff --git a/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch b/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch
deleted file mode 100644
index a7878ecb1b..0000000000
--- a/target/linux/mediatek/patches-5.15/704-net-ethernet-mtk_eth_soc-announce-2500baseT.patch
+++ /dev/null
@@ -1,10 +0,0 @@
---- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-+++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -667,6 +667,7 @@ static void mtk_validate(struct phylink_
- 		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_SGMII)) {
- 			phylink_set(mask, 1000baseT_Full);
- 			phylink_set(mask, 1000baseX_Full);
-+			phylink_set(mask, 2500baseT_Full);
- 			phylink_set(mask, 2500baseX_Full);
- 		}
- 		if (MTK_HAS_CAPS(mac->hw->soc->caps, MTK_RGMII)) {
diff --git a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch
index f6ac8360ee..8a39c81e01 100644
--- a/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch
+++ b/target/linux/ramips/patches-5.15/700-net-ethernet-mediatek-support-net-labels.patch
@@ -14,7 +14,7 @@ Signed-off-by: René van Dorst <opensource at vdorst.com>
 
 --- a/drivers/net/ethernet/mediatek/mtk_eth_soc.c
 +++ b/drivers/net/ethernet/mediatek/mtk_eth_soc.c
-@@ -3290,6 +3290,7 @@ static const struct net_device_ops mtk_n
+@@ -3228,6 +3228,7 @@ static const struct net_device_ops mtk_n
  
  static int mtk_add_mac(struct mtk_eth *eth, struct device_node *np)
  {
@@ -22,7 +22,7 @@ Signed-off-by: René van Dorst <opensource at vdorst.com>
  	const __be32 *_id = of_get_property(np, "reg", NULL);
  	phy_interface_t phy_mode;
  	struct phylink *phylink;
-@@ -3385,6 +3386,9 @@ static int mtk_add_mac(struct mtk_eth *e
+@@ -3347,6 +3348,9 @@ static int mtk_add_mac(struct mtk_eth *e
  	else
  		eth->netdev[id]->max_mtu = MTK_MAX_RX_LENGTH_2K - MTK_RX_ETH_HLEN;
  
diff --git a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch
index afdfc892d5..063b317fd5 100644
--- a/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch
+++ b/target/linux/ramips/patches-5.15/720-Revert-net-phy-simplify-phy_link_change-arguments.patch
@@ -95,7 +95,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
  		phydev->mii_ts->link_state(phydev->mii_ts, phydev);
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
-@@ -946,7 +946,8 @@ void phylink_destroy(struct phylink *pl)
+@@ -1315,7 +1315,8 @@ void phylink_destroy(struct phylink *pl)
  }
  EXPORT_SYMBOL_GPL(phylink_destroy);
  
@@ -107,7 +107,7 @@ still required by target/linux/ramips/files/drivers/net/ethernet/ralink/mdio.c
  	bool tx_pause, rx_pause;
 --- a/include/linux/phy.h
 +++ b/include/linux/phy.h
-@@ -669,7 +669,7 @@ struct phy_device {
+@@ -703,7 +703,7 @@ struct phy_device {
  	u8 mdix;
  	u8 mdix_ctrl;
  
diff --git a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch
index 97086fa950..365bdc6880 100644
--- a/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch
+++ b/target/linux/ramips/patches-5.15/721-NET-no-auto-carrier-off-support.patch
@@ -37,7 +37,7 @@ Signed-off-by: John Crispin <blogic at openwrt.org>
  		break;
 --- a/include/linux/phy.h
 +++ b/include/linux/phy.h
-@@ -586,6 +586,7 @@ struct phy_device {
+@@ -620,6 +620,7 @@ struct phy_device {
  	unsigned downshifted_rate:1;
  	unsigned is_on_sfp_module:1;
  	unsigned mac_managed_pm:1;




More information about the lede-commits mailing list