From bcbf4a406a653b68dabb5a8196192d4b6d971aff Mon Sep 17 00:00:00 2001 From: Christian Marangi Date: Sun, 17 May 2026 12:42:29 +0200 Subject: [PATCH] generic: update pending PCS patch with .fill_available_pcs OP While implementing standalone PCS support for DSA, it was found that making the MAC driver passing the available_pcs array is limiting and problematic for memory handling and allocation. To better handle this, change the logic and make phylink allocate the struct and make the MAC driver implement a function in phylink_config .fill_available_pcs to fill the PCS array. Update the Airoha and Mediatek driver to reflect this new implementation. Link: https://github.com/openwrt/openwrt/pull/23413 (cherry picked from commit 627cd79e1cdc5a93fd81b90ab78beabdb026a82e) Link: https://github.com/openwrt/openwrt/pull/24823 Signed-off-by: Christian Marangi --- ...roduce-internal-phylink-PCS-handling.patch | 100 ++++++++++++++---- ...phylink_release_pcs-to-externally-re.patch | 2 +- ...ink-support-late-PCS-provider-attach.patch | 6 +- ...et-phylink-add-.pcs_link_down-PCS-OP.patch | 4 +- .../patches-6.12/730-add-pcs-rtl-otto.patch | 4 +- 5 files changed, 85 insertions(+), 31 deletions(-) diff --git a/target/linux/generic/pending-6.12/770-02-net-phylink-introduce-internal-phylink-PCS-handling.patch b/target/linux/generic/pending-6.12/770-02-net-phylink-introduce-internal-phylink-PCS-handling.patch index d7c00f38af5..622be40d1cb 100644 --- a/target/linux/generic/pending-6.12/770-02-net-phylink-introduce-internal-phylink-PCS-handling.patch +++ b/target/linux/generic/pending-6.12/770-02-net-phylink-introduce-internal-phylink-PCS-handling.patch @@ -210,13 +210,13 @@ Signed-off-by: Christian Marangi + break; + } + } -+ + +- pcs_changed = pl->pcs != pcs; + if (!pcs_found) { + phylink_err(pl, + "couldn't find a PCS for %s\n", + phy_modes(state->interface)); - -- pcs_changed = pl->pcs != pcs; ++ + pl->major_config_failed = true; + return; + } @@ -245,28 +245,70 @@ Signed-off-by: Christian Marangi pl->pcs = pcs; } -@@ -1931,8 +2006,9 @@ struct phylink *phylink_create(struct ph +@@ -1909,6 +1984,44 @@ int phylink_set_fixed_link(struct phylin + } + EXPORT_SYMBOL_GPL(phylink_set_fixed_link); + ++static int phylink_fill_available_pcs(struct phylink *pl, ++ struct phylink_config *config) ++{ ++ struct phylink_pcs **pcss; ++ int i, ret; ++ ++ if (!config->num_available_pcs) ++ return 0; ++ ++ if (!config->fill_available_pcs) { ++ dev_err(config->dev, ++ "phylink: error: num_available_pcs defined but no fill_available_pcs\n"); ++ return -EINVAL; ++ } ++ ++ pcss = kcalloc(config->num_available_pcs, sizeof(*pcss), GFP_KERNEL); ++ if (!pcss) ++ return -ENOMEM; ++ ++ ret = config->fill_available_pcs(config, pcss, config->num_available_pcs); ++ if (ret) ++ goto out; ++ ++ for (i = 0; i < config->num_available_pcs; i++) { ++ struct phylink_pcs *pcs = pcss[i]; ++ ++ if (!pcs) ++ continue; ++ ++ list_add(&pcs->list, &pl->pcs_list); ++ } ++ ++out: ++ kfree(pcss); ++ ++ return ret; ++} ++ + /** + * phylink_create() - create a phylink instance + * @config: a pointer to the target &struct phylink_config +@@ -1931,6 +2044,7 @@ struct phylink *phylink_create(struct ph const struct phylink_mac_ops *mac_ops) { bool using_mac_select_pcs = false; + struct phylink_pcs *pcs; struct phylink *pl; -- int ret; -+ int i, ret; + int ret; - /* Validate the supplied configuration */ - if (phy_interface_empty(config->supported_interfaces)) { -@@ -1952,9 +2028,21 @@ struct phylink *phylink_create(struct ph +@@ -1952,9 +2066,21 @@ struct phylink *phylink_create(struct ph mutex_init(&pl->state_mutex); INIT_WORK(&pl->resolve, phylink_resolve); + INIT_LIST_HEAD(&pl->pcs_list); + + /* Fill the PCS list with available PCS from phylink config */ -+ for (i = 0; i < config->num_available_pcs; i++) { -+ pcs = config->available_pcs[i]; -+ -+ list_add(&pcs->list, &pl->pcs_list); ++ ret = phylink_fill_available_pcs(pl, config); ++ if (ret) { ++ kfree(pl); ++ return ERR_PTR(ret); + } phy_interface_copy(pl->supported_interfaces, @@ -278,7 +320,7 @@ Signed-off-by: Christian Marangi pl->config = config; if (config->type == PHYLINK_NETDEV) { -@@ -2024,10 +2112,16 @@ EXPORT_SYMBOL_GPL(phylink_create); +@@ -2025,10 +2151,16 @@ EXPORT_SYMBOL_GPL(phylink_create); */ void phylink_destroy(struct phylink *pl) { @@ -295,7 +337,7 @@ Signed-off-by: Christian Marangi cancel_work_sync(&pl->resolve); kfree(pl); } -@@ -2472,6 +2566,7 @@ static irqreturn_t phylink_link_handler( +@@ -2473,6 +2605,7 @@ static irqreturn_t phylink_link_handler( */ void phylink_start(struct phylink *pl) { @@ -303,7 +345,7 @@ Signed-off-by: Christian Marangi bool poll = false; ASSERT_RTNL(); -@@ -2498,6 +2593,10 @@ void phylink_start(struct phylink *pl) +@@ -2499,6 +2632,10 @@ void phylink_start(struct phylink *pl) pl->pcs_state = PCS_STATE_STARTED; @@ -314,7 +356,7 @@ Signed-off-by: Christian Marangi phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED); if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) { -@@ -2542,6 +2641,8 @@ EXPORT_SYMBOL_GPL(phylink_start); +@@ -2543,6 +2680,8 @@ EXPORT_SYMBOL_GPL(phylink_start); */ void phylink_stop(struct phylink *pl) { @@ -323,7 +365,7 @@ Signed-off-by: Christian Marangi ASSERT_RTNL(); if (pl->sfp_bus) -@@ -2559,6 +2660,14 @@ void phylink_stop(struct phylink *pl) +@@ -2560,6 +2699,14 @@ void phylink_stop(struct phylink *pl) pl->pcs_state = PCS_STATE_DOWN; phylink_pcs_disable(pl->pcs); @@ -340,31 +382,43 @@ Signed-off-by: Christian Marangi --- a/include/linux/phylink.h +++ b/include/linux/phylink.h -@@ -147,7 +147,11 @@ enum phylink_op_type { +@@ -10,6 +10,7 @@ struct ethtool_cmd; + struct fwnode_handle; + struct net_device; + struct phylink; ++struct phylink_pcs; + + enum { + MLO_PAUSE_NONE, +@@ -147,7 +148,13 @@ 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. + * @pcs_interfaces: bitmap describing for which PHY_INTERFACE_MODE_xxx a + * dedicated PCS is required. * @mac_capabilities: MAC pause/speed/duplex capabilities. -+ * @available_pcs: array of available phylink_pcs PCS + * @num_available_pcs: num of available phylink_pcs PCS ++ * @fill_available_pcs: callback to fill the available PCS in the passed ++ * array struct of phylink_pcs PCS available_pcs up to ++ * num_available_pcs. */ struct phylink_config { struct device *dev; -@@ -159,7 +163,11 @@ struct phylink_config { +@@ -159,7 +166,13 @@ struct phylink_config { void (*get_fixed_state)(struct phylink_config *config, struct phylink_link_state *state); DECLARE_PHY_INTERFACE_MASK(supported_interfaces); + DECLARE_PHY_INTERFACE_MASK(pcs_interfaces); unsigned long mac_capabilities; + -+ struct phylink_pcs **available_pcs; + unsigned int num_available_pcs; ++ int (*fill_available_pcs)(struct phylink_config *config, ++ struct phylink_pcs **available_pcs, ++ unsigned int num_available_pcs); }; void phylink_limit_mac_speed(struct phylink_config *config, u32 max_speed); -@@ -417,6 +425,9 @@ struct phylink_pcs { +@@ -417,6 +430,9 @@ struct phylink_pcs { bool neg_mode; bool poll; bool rxc_always_on; diff --git a/target/linux/generic/pending-6.12/770-03-net-phylink-add-phylink_release_pcs-to-externally-re.patch b/target/linux/generic/pending-6.12/770-03-net-phylink-add-phylink_release_pcs-to-externally-re.patch index 72d920c241f..95969645af6 100644 --- a/target/linux/generic/pending-6.12/770-03-net-phylink-add-phylink_release_pcs-to-externally-re.patch +++ b/target/linux/generic/pending-6.12/770-03-net-phylink-add-phylink_release_pcs-to-externally-re.patch @@ -123,7 +123,7 @@ Signed-off-by: Christian Marangi /* If configuration of the interface failed, force the link down --- a/include/linux/phylink.h +++ b/include/linux/phylink.h -@@ -632,6 +632,8 @@ void phylink_disconnect_phy(struct phyli +@@ -637,6 +637,8 @@ void phylink_disconnect_phy(struct phyli int phylink_set_fixed_link(struct phylink *, const struct phylink_link_state *); diff --git a/target/linux/generic/pending-6.12/770-05-net-phylink-support-late-PCS-provider-attach.patch b/target/linux/generic/pending-6.12/770-05-net-phylink-support-late-PCS-provider-attach.patch index d54779c4b41..2af52463b8b 100644 --- a/target/linux/generic/pending-6.12/770-05-net-phylink-support-late-PCS-provider-attach.patch +++ b/target/linux/generic/pending-6.12/770-05-net-phylink-support-late-PCS-provider-attach.patch @@ -110,9 +110,9 @@ Signed-off-by: Christian Marangi /* What interface are supported by the current link. * Can change on removal or addition of new PCS. -@@ -2039,6 +2041,51 @@ int phylink_set_fixed_link(struct phylin +@@ -2077,6 +2079,51 @@ out: + return ret; } - EXPORT_SYMBOL_GPL(phylink_set_fixed_link); +static int pcs_provider_notify(struct notifier_block *self, + unsigned long val, void *data) @@ -162,7 +162,7 @@ Signed-off-by: Christian Marangi /** * phylink_create() - create a phylink instance * @config: a pointer to the target &struct phylink_config -@@ -2099,6 +2146,11 @@ struct phylink *phylink_create(struct ph +@@ -2137,6 +2184,11 @@ struct phylink *phylink_create(struct ph pl->supported_interfaces, pcs->supported_interfaces); diff --git a/target/linux/generic/pending-6.12/770-07-net-phylink-add-.pcs_link_down-PCS-OP.patch b/target/linux/generic/pending-6.12/770-07-net-phylink-add-.pcs_link_down-PCS-OP.patch index 648aa832208..4ed702de8f9 100644 --- a/target/linux/generic/pending-6.12/770-07-net-phylink-add-.pcs_link_down-PCS-OP.patch +++ b/target/linux/generic/pending-6.12/770-07-net-phylink-add-.pcs_link_down-PCS-OP.patch @@ -46,7 +46,7 @@ Signed-off-by: Christian Marangi phylink_info(pl, "Link is Down\n"); --- a/include/linux/phylink.h +++ b/include/linux/phylink.h -@@ -443,6 +443,7 @@ struct phylink_pcs { +@@ -448,6 +448,7 @@ struct phylink_pcs { * @pcs_an_restart: restart 802.3z BaseX autonegotiation. * @pcs_link_up: program the PCS for the resolved link configuration * (where necessary). @@ -54,7 +54,7 @@ Signed-off-by: Christian Marangi * @pcs_pre_init: configure PCS components necessary for MAC hardware * initialization e.g. RX clock for stmmac. */ -@@ -466,6 +467,7 @@ struct phylink_pcs_ops { +@@ -471,6 +472,7 @@ struct phylink_pcs_ops { void (*pcs_an_restart)(struct phylink_pcs *pcs); void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode, phy_interface_t interface, int speed, int duplex); diff --git a/target/linux/realtek/patches-6.12/730-add-pcs-rtl-otto.patch b/target/linux/realtek/patches-6.12/730-add-pcs-rtl-otto.patch index 27927bd8919..f82a00cf4cf 100644 --- a/target/linux/realtek/patches-6.12/730-add-pcs-rtl-otto.patch +++ b/target/linux/realtek/patches-6.12/730-add-pcs-rtl-otto.patch @@ -11,7 +11,7 @@ Signed-off-by: Markus Stockhausen --- --- a/drivers/net/pcs/Kconfig +++ b/drivers/net/pcs/Kconfig -@@ -36,6 +36,14 @@ config PCS_MTK_USXGMII +@@ -43,6 +43,14 @@ config PCS_MTK_USXGMII 1000Base-X, 2500Base-X and Cisco SGMII are supported on the same differential pairs via an embedded LynxI PHY. @@ -28,7 +28,7 @@ Signed-off-by: Markus Stockhausen depends on OF && (ARCH_RZN1 || COMPILE_TEST) --- a/drivers/net/pcs/Makefile +++ b/drivers/net/pcs/Makefile -@@ -7,5 +7,6 @@ pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs. +@@ -8,5 +8,6 @@ pcs_xpcs-$(CONFIG_PCS_XPCS) := pcs-xpcs. obj-$(CONFIG_PCS_XPCS) += pcs_xpcs.o obj-$(CONFIG_PCS_LYNX) += pcs-lynx.o obj-$(CONFIG_PCS_MTK_LYNXI) += pcs-mtk-lynxi.o