* Re: [PATCH net-next v1 1/5] net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay @ 2026-10-10 13:13 netdev-bot+sashiko 0 siblings, 0 replies; 3+ messages in thread From: netdev-bot+sashiko @ 2026-10-10 13:13 UTC (permalink / raw) To: claudiu.manoil; +Cc: netdev, s32, bhelgaas, linux-pci, linux-kernel, kuba Thank you for your contribution! Sashiko AI review found 7 potential issue(s) to consider. Critical: 0 · High: 0 · Medium: 4 · Low: 3 If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [Medium] On the new pseudo-MAC overlay path, the driver treats PCR[PSPEED] as the boot-time source of truth for link speed, but then… - [Medium] enetc4_link_init() uses `of_node_check_flag(node, OF_DYNAMIC)` to mean "empty PCI-synthesized node with no fixed-link description",… - [Medium] The overlay's `speed = <2500>` is documented as a placeholder (enetc4_pseudo_mac.dtso header, the enetc4_pl_get_fixed_state()… - [Medium] When of_overlay_fdt_apply() fails, the partly applied overlay changeset is leaked. - [Low] Not reported (baseline: discard). - [Low] The comment above the __dtbo_enetc4_pseudo_mac_begin/_end externs in enetc4_pf.c says the blob is "created by cmd_wrap_S_dtb in… - [Low] Not reported (baseline: discard). -- net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay This adds support for ENETCv4 pseudo-MAC ports that have no static DT description. The driver applies an embedded fixed-link DT overlay onto the PCI function's dynamic OF node. A phylink get_fixed_state callback then reports the link speed, which is read from PCR[PSPEED]. > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c > index 71c971618388b..7999355b5b9f5 100644 > --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c [ ... ] > @@ -12,6 +12,10 @@ > > #define ENETC_SI_MAX_RING_NUM 8 > > +/* embedded overlay blob, created by cmd_wrap_S_dtb in scripts/Makefile.lib */ [Severity: Low] This isn't a bug, but the comment points to the wrong file. At this revision, cmd_wrap_S_dtb and the %.dtbo.S rule live in scripts/Makefile.dtbs, and scripts/Makefile.lib does not contain them. The comment looks like it was copied from drivers/misc/lan966x_pci.c. > +extern char __dtbo_enetc4_pseudo_mac_begin[]; > +extern char __dtbo_enetc4_pseudo_mac_end[]; > + [ ... ] > +/* Pseudo-MAC ports have no real PHY; the link is fixed. The overlay puts > + * phylink into fixed-link mode, but the operating speed is taken live from > + * PCR[PSPEED] here rather than from the DT 'speed' cell. > + */ > +static void enetc4_pl_get_fixed_state(struct phylink_config *config, > + struct phylink_link_state *state) > +{ > + struct enetc_pf *pf = phylink_to_enetc_pf(config); > + int speed; > + > + enetc4_get_pcr_speed(&pf->si->hw, &speed); > + > + state->link = 1; > + state->an_complete = 1; > + state->duplex = DUPLEX_FULL; > + state->speed = enetc_phylink_match_pseudo_mac_speed(speed); [Severity: Medium] Can this rewrite the PCR[PSPEED] value that firmware programmed? enetc_phylink_match_pseudo_mac_speed() rounds down to the nearest table entry. phylink then passes the rounded speed to enetc4_pl_mac_link_up(). That function calls enetc4_set_port_speed() without checking for a pseudo-MAC port: enetc4_set_port_speed() { ... if (speed == old_speed) return; val = enetc_port_rd(&priv->si->hw, ENETC4_PCR) & (~PCR_PSPEED); val |= PCR_PSPEED_VAL(speed); enetc_port_wr(&priv->si->hw, ENETC4_PCR, val); priv->speed = speed; } priv->speed starts at 0, so the first link-up always writes PCR. PCR_PSPEED is a linear field in 10 Mbps units. If firmware or the switch owner set a speed that is not in the table, such as 3000 or 40000 Mbps, it would be overwritten with 2500 or 25000. Later get_fixed_state reads would then return the rounded value, and the original setting stays lost until reset. The commit message says the speed is "determined at boot time by the Port PCR[PSPEED] register configuration". Should enetc4_set_port_speed() skip pseudo-MAC ports here? > +} > + [ ... ] > +static int enetc4_apply_overlay(struct enetc_ndev_priv *priv) > +{ > + u32 size = __dtbo_enetc4_pseudo_mac_end - __dtbo_enetc4_pseudo_mac_begin; > + struct device_node *np = dev_of_node(priv->dev); > + int err; > + > + if (!np) > + return dev_err_probe(priv->dev, -ENODEV, > + "Missing of_node for Pseudo-MAC port\n"); > + > + err = of_overlay_fdt_apply(__dtbo_enetc4_pseudo_mac_begin, size, > + &priv->ovcs_id, np); > + if (err) > + return dev_err_probe(priv->dev, err, > + "Failed to apply fixed-link overlay\n"); [Severity: Medium] Does this leak the overlay changeset when of_overlay_fdt_apply() fails? of_overlay_fdt_apply() sets *ret_ovcs_id even when of_overlay_apply() fails. Its kernel-doc says: * On error return, the changeset may be partially applied. This is especially * likely if an OF_OVERLAY_POST_APPLY notifier returns an error. In this case * the caller should call of_overlay_remove() with the value in *@ret_ovcs_id. Here the error is returned without calling of_overlay_remove(). Then enetc4_link_init() does a plain return err, which skips the err_mdiobus_create label where enetc4_put_overlay() is called. Next, enetc4_pf_netdev_create() jumps to err_link_init and calls free_netdev(), which frees the only copy of priv->ovcs_id. That would leak the overlay_changeset, its FDT copy, the unflattened tree and the IDR slot. Any partly applied nodes would also stay under the PCI function's OF node. Could this failure path call enetc4_put_overlay(), or use goto err_mdiobus_create in enetc4_link_init()? > + > + return 0; > +} > + > static int enetc4_link_init(struct enetc_ndev_priv *priv, > struct device_node *node) > { > + bool dynamic = node && of_node_check_flag(node, OF_DYNAMIC); > struct enetc_pf *pf = enetc_si_priv(priv->si); > struct device *dev = priv->dev; > int err; > > - err = of_get_phy_mode(node, &pf->if_mode); > - if (err) { > - dev_err(dev, "Failed to get PHY mode\n"); > - return err; > + /* Pseudo-MAC ENETCs are described by a runtime fixed-link overlay > + * rather than static DT. This covers both a missing OF node and a > + * PCI-synthesized (OF_DYNAMIC) node, which is an empty node created > + * by the PCI core and thus carries no fixed-link description. > + */ > + if (enetc_is_pseudo_mac(priv->si) && (!node || dynamic)) { [Severity: Medium] Does OF_DYNAMIC reliably mean the node has no link description? The flag only records that the node was allocated at runtime. Nodes created by any runtime overlay or changeset have it as well. A PCI-created node also keeps it after another overlay adds phy-mode or fixed-link to it. The node from of_pci_make_dev_node() is not empty either, because of_pci_add_properties() adds reg, compatible, ranges and other properties. Suppose a runtime overlay supplies a pseudo-MAC node with its own phy-mode and fixed-link, or link-gpios. This branch would then: - force phy-mode to INTERNAL - merge the driver's dtbo over the existing fixed-link child, overwriting speed and full-duplex - block removal of the earlier overlay, because node_overlaps_later_cs() would refuse it - install get_fixed_state phylink_get_fixed_state() checks the callback before the link GPIO: if (pl->config->get_fixed_state) pl->config->get_fixed_state(pl->config, state); else if (pl->link_gpio) state->link = !!gpiod_get_value_cansleep(pl->link_gpio); So a configured link GPIO would never be read, and the link would always be reported up. Before this patch, such nodes went through of_get_phy_mode() and phylink's normal fixed-link handling. Would it be better to check for an existing fixed-link child or phy-mode property instead of OF_DYNAMIC? > + pf->if_mode = PHY_INTERFACE_MODE_INTERNAL; > + > + err = enetc4_apply_overlay(priv); > + if (err) > + return err; > + [ ... ] > diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso b/drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso > new file mode 100644 > index 0000000000000..e3d3e4259fbd4 > --- /dev/null > +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso [ ... ] > + * This overlay is applied by the ENETC4 PF driver onto the PCI function's own > + * dynamic OF node (created by the PCI core when CONFIG_PCI_DYNAMIC_OF_NODES > + * is enabled). The overlay only selects fixed-link mode and carries the duplex > + * setting; the 'speed' property is a placeholder. [ ... ] > + __overlay__ { > + fixed-link { > + speed = <2500>; [Severity: Medium] Is this speed value really just a placeholder? phylink_parse_fixedlink() reads it into pl->link_config.speed and then does: c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex, pl->supported, true); This limits pl->supported and link_config.lp_advertising to the 2500 Mbps modes. enetc4_pl_get_fixed_state() later overrides only state->speed, duplex and link. phylink_ethtool_ksettings_get() copies pl->supported into its result but takes the speed from phylink_get_fixed_state(). On a port whose PSPEED decodes to 10000, ethtool would show Speed: 10000Mb/s while listing only 2500 Mbps modes as supported and as advertised by the link partner. pl->link_config.speed is also used to validate ethtool -s requests in fixed mode. Are the "placeholder" descriptions accurate in this file, in the enetc4_pl_get_fixed_state() comment and in the commit message? > + full-duplex; > + }; > + }; > + }; > +}; [ ... ] -- Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/cover.1791548316.git.claudiu.manoil%40nxp.com ^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH net-next v1 0/5] net: enetc: S32N79 pseudo-MAC (PPM) networking support @ 2026-10-09 12:40 Claudiu Manoil 2026-10-09 12:40 ` [PATCH net-next v1 1/5] net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay Claudiu Manoil 0 siblings, 1 reply; 3+ messages in thread From: Claudiu Manoil @ 2026-10-09 12:40 UTC (permalink / raw) To: netdev; +Cc: s32, Rob Herring, Saravana Kannan, devicetree This series adds networking support for the ENETCv4.4 pseudo-MAC (PPM) ports found on the NXP S32N79 SoC. On S32N79, the ENETCv4 ports are not wired to any external PHY/MII; instead they are internal "pseudo-MAC" links into the on-chip NETC switch. These links are proprietary, expose no standard IEEE interface, and run at a speed fixed at boot time by the Port PCR[PSPEED] register. A key use case is a port that has no "ethernet" DT node at all: NETC is reached over PCI from a host that probes the ENETC, while the internal NETC switch it connects to is not owned by Linux. Such a port must have its fixed link synthesized at probe time. Rather than hand-building a software node, the driver describes the fixed link with a self-contained DT overlay (following the lan966x PCI approach), applied unmodified via of_overlay_fdt_apply() onto the PCI function's dynamic OF node (CONFIG_PCI_DYNAMIC_OF_NODES). phylink then picks up the fixed-link node through dev_fwnode(); the real operating speed is sourced live from PCR[PSPEED]. The series touches three subsystems: - net/enetc: pseudo-MAC overlay support + probing of 4.4 devices - arm64 dts: NETC IEP18 ECAM node on S32N79 and its RDB board enable - PCI: a quirk creating the OF node for the ENETC PMAC functions Because this is primarily a networking feature and the pieces are interdependent at runtime, it would be most convenient to merge the whole series through the netdev tree. Patch 1 has a runtime (not Kconfig) dependency on CONFIG_PCI_DYNAMIC_OF_NODES; absent that, the pseudo-MAC probe path fails gracefully with -ENODEV. v1: initial submission. Claudiu Manoil (5): net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay net: enetc: Enable probing of version 4.4 devices arm64: dts: s32n79: add NETC IEP18 ECAM node for ENETC PPM ports arm64: dts: s32n79-rdb: enable NETC IEP18 PCI: Create OF node for NXP ENETC pseudo-MAC functions arch/arm64/boot/dts/freescale/s32n79-rdb.dts | 4 + arch/arm64/boot/dts/freescale/s32n79.dtsi | 24 +++++ drivers/net/ethernet/freescale/enetc/Kconfig | 1 + drivers/net/ethernet/freescale/enetc/Makefile | 1 + drivers/net/ethernet/freescale/enetc/enetc.c | 12 +++ drivers/net/ethernet/freescale/enetc/enetc.h | 1 + .../net/ethernet/freescale/enetc/enetc4_pf.c | 98 +++++++++++++++++-- .../freescale/enetc/enetc4_pseudo_mac.dtso | 32 ++++++ .../net/ethernet/freescale/enetc/enetc_hw.h | 1 + .../freescale/enetc/enetc_pf_common.c | 41 +++++++- .../freescale/enetc/enetc_pf_common.h | 1 + drivers/pci/quirks.c | 2 + 12 files changed, 209 insertions(+), 9 deletions(-) create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso base-commit: d8674294aefef02266c4d47ad10131f1bffbe534 -- 2.34.1 ^ permalink raw reply [flat|nested] 3+ messages in thread
* [PATCH net-next v1 1/5] net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay 2026-10-09 12:40 [PATCH net-next v1 0/5] net: enetc: S32N79 pseudo-MAC (PPM) networking support Claudiu Manoil @ 2026-10-09 12:40 ` Claudiu Manoil 2026-10-10 2:26 ` Frank Li 0 siblings, 1 reply; 3+ messages in thread From: Claudiu Manoil @ 2026-10-09 12:40 UTC (permalink / raw) To: netdev Cc: s32, Vladimir Oltean, Wei Fang, Clark Wang, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Saravana Kannan, Russell King, linux-kernel, imx, devicetree ENETCv4 has special internal links when connected to the on-chip NETC switch via internal switch ports, called pseudo-MAC links. These pseudo-MACs are proprietary, they don't implement any standard IEEE interface (like MII), and can be modeled as fixed links with the link speed determined at boot time by the Port PCR[PSPEED] register configuration. We also need to be able to probe the ENETCv4 Ports featuring pseudo-MACs as pure PCI devices, i.e. without any "ethernet" DT node representation. The typical use case for this consists in a board with NETC connected via PCI to another host which probes the ENETC. Note that in this scenario, the pseudo-MAC ENETCs are connected internally to a NETC switch that is not owned by Linux. Since such a port has no "ethernet" DT node, its fixed link has to be synthesized at probe time. Rather than hand-building a named software node, describe the fixed link with a self-contained device-tree overlay, following the approach used by the Microchip lan966x PCI driver. The overlay is compiled from enetc4_pseudo_mac.dtso into a .dtbo blob and embedded in the driver via the kernel's dtbo wrapping (__dtbo_*_begin/_end symbols). The overlay fragment uses an empty target-path, so it is grafted onto the base node passed to of_overlay_fdt_apply(), i.e. the PCI function's own dynamic OF node (created by the PCI core when CONFIG_PCI_DYNAMIC_OF_NODES is enabled). The fixed-link node is therefore spliced directly onto the ENETC netdev's fwnode, exactly as if it had come from static DT, and phylink picks it up through dev_fwnode(). The overlay only adds a new fixed-link node; it deliberately does not add a phy-mode property. A device-tree overlay may only add new nodes (which are tracked with the OF_OVERLAY flag and freed cleanly on removal), not new properties onto an already-live node such as the PCI function's dynamic OF node. The phy-mode is instead set programmatically by the driver (pf->if_mode) before the overlay is applied. The pseudo-MAC overlay path is selected when the port has no OF node, or when it only has the empty PCI-synthesized node (OF_DYNAMIC), which carries no fixed-link description. Ports described by static DT take the regular of_get_phy_mode() path instead. The overlay blob is applied unmodified, it only selects fixed-link mode and carries the duplex setting; its 'speed' cell is a placeholder. The real operating speed is sourced live from PCR[PSPEED] through the phylink get_fixed_state callback, which lets the driver override the fixed-link state at link time. The overlay is removed on teardown and on the probe error unwind. The driver gains a build dependency on OF_OVERLAY. In addition, the node-less pseudo-MAC path has a runtime dependency on CONFIG_PCI_DYNAMIC_OF_NODES: that is what makes the PCI core synthesize the per-function OF node (of_pci_make_dev_node()) that the overlay is applied onto. This is intentionally not a hard Kconfig dependency, since the ENETC4 driver also serves regular ports described by static DT; when PCI_DYNAMIC_OF_NODES is absent the PCI function has no of_node and the pseudo-MAC probe path fails gracefully with a clear -ENODEV error. Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com> --- drivers/net/ethernet/freescale/enetc/Kconfig | 1 + drivers/net/ethernet/freescale/enetc/Makefile | 1 + drivers/net/ethernet/freescale/enetc/enetc.h | 1 + .../net/ethernet/freescale/enetc/enetc4_pf.c | 98 +++++++++++++++++-- .../freescale/enetc/enetc4_pseudo_mac.dtso | 32 ++++++ .../freescale/enetc/enetc_pf_common.c | 41 +++++++- .../freescale/enetc/enetc_pf_common.h | 1 + 7 files changed, 166 insertions(+), 9 deletions(-) create mode 100644 drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso diff --git a/drivers/net/ethernet/freescale/enetc/Kconfig b/drivers/net/ethernet/freescale/enetc/Kconfig index f425f82a6213..a323f4235802 100644 --- a/drivers/net/ethernet/freescale/enetc/Kconfig +++ b/drivers/net/ethernet/freescale/enetc/Kconfig @@ -49,6 +49,7 @@ config NXP_ENETC4 tristate "ENETC4 PF driver" depends on PTP_1588_CLOCK_OPTIONAL depends on PCI_MSI + depends on OF_OVERLAY select FSL_ENETC_CORE select FSL_ENETC_MDIO select NXP_ENETC_PF_COMMON diff --git a/drivers/net/ethernet/freescale/enetc/Makefile b/drivers/net/ethernet/freescale/enetc/Makefile index 10ab6694c314..86aa73de3f84 100644 --- a/drivers/net/ethernet/freescale/enetc/Makefile +++ b/drivers/net/ethernet/freescale/enetc/Makefile @@ -16,6 +16,7 @@ fsl-enetc-$(CONFIG_FSL_ENETC_QOS) += enetc_qos.o obj-$(CONFIG_NXP_ENETC4) += nxp-enetc4.o nxp-enetc4-y := enetc4_pf.o +nxp-enetc4-y += enetc4_pseudo_mac.dtbo.o nxp-enetc4-$(CONFIG_DEBUG_FS) += enetc4_debugfs.o obj-$(CONFIG_FSL_ENETC_VF) += fsl-enetc-vf.o diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h index d9e91832a9c1..02b44ea53807 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc.h +++ b/drivers/net/ethernet/freescale/enetc/enetc.h @@ -500,6 +500,7 @@ struct enetc_ndev_priv { struct clk *ref_clk; /* RGMII/RMII reference clock */ u64 sysclk_freq; /* NETC system clock frequency */ + int ovcs_id; }; #define ENETC_CBD(R, i) (&(((struct enetc_cbd *)((R).bd_base))[i])) diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c index 71c971618388..7999355b5b9f 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc4_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pf.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) -/* Copyright 2024 NXP */ +/* Copyright 2024, 2026 NXP */ #include <linux/clk.h> #include <linux/module.h> @@ -12,6 +12,10 @@ #define ENETC_SI_MAX_RING_NUM 8 +/* embedded overlay blob, created by cmd_wrap_S_dtb in scripts/Makefile.lib */ +extern char __dtbo_enetc4_pseudo_mac_begin[]; +extern char __dtbo_enetc4_pseudo_mac_end[]; + static void enetc4_get_port_caps(struct enetc_pf *pf) { struct enetc_hw *hw = &pf->si->hw; @@ -932,6 +936,32 @@ static void enetc4_pl_mac_link_down(struct phylink_config *config, enetc4_mac_tx_graceful_stop(pf); } +static void enetc4_get_pcr_speed(struct enetc_hw *hw, int *speed) +{ + u32 val = enetc_port_rd(hw, ENETC4_PCR); + int pspeed = FIELD_GET(PCR_PSPEED, val); + + *speed = (pspeed + 1) * 10; +} + +/* Pseudo-MAC ports have no real PHY; the link is fixed. The overlay puts + * phylink into fixed-link mode, but the operating speed is taken live from + * PCR[PSPEED] here rather than from the DT 'speed' cell. + */ +static void enetc4_pl_get_fixed_state(struct phylink_config *config, + struct phylink_link_state *state) +{ + struct enetc_pf *pf = phylink_to_enetc_pf(config); + int speed; + + enetc4_get_pcr_speed(&pf->si->hw, &speed); + + state->link = 1; + state->an_complete = 1; + state->duplex = DUPLEX_FULL; + state->speed = enetc_phylink_match_pseudo_mac_speed(speed); +} + static const struct phylink_mac_ops enetc_pl_mac_ops = { .mac_select_pcs = enetc4_pl_mac_select_pcs, .mac_config = enetc4_pl_mac_config, @@ -946,23 +976,76 @@ static void enetc4_pci_remove(void *data) enetc_pci_remove(pdev); } +static void enetc4_put_overlay(struct enetc_ndev_priv *priv) +{ + if (!priv->ovcs_id) + return; + + of_overlay_remove(&priv->ovcs_id); + priv->ovcs_id = 0; +} + +static int enetc4_apply_overlay(struct enetc_ndev_priv *priv) +{ + u32 size = __dtbo_enetc4_pseudo_mac_end - __dtbo_enetc4_pseudo_mac_begin; + struct device_node *np = dev_of_node(priv->dev); + int err; + + if (!np) + return dev_err_probe(priv->dev, -ENODEV, + "Missing of_node for Pseudo-MAC port\n"); + + err = of_overlay_fdt_apply(__dtbo_enetc4_pseudo_mac_begin, size, + &priv->ovcs_id, np); + if (err) + return dev_err_probe(priv->dev, err, + "Failed to apply fixed-link overlay\n"); + + return 0; +} + static int enetc4_link_init(struct enetc_ndev_priv *priv, struct device_node *node) { + bool dynamic = node && of_node_check_flag(node, OF_DYNAMIC); struct enetc_pf *pf = enetc_si_priv(priv->si); struct device *dev = priv->dev; int err; - err = of_get_phy_mode(node, &pf->if_mode); - if (err) { - dev_err(dev, "Failed to get PHY mode\n"); - return err; + /* Pseudo-MAC ENETCs are described by a runtime fixed-link overlay + * rather than static DT. This covers both a missing OF node and a + * PCI-synthesized (OF_DYNAMIC) node, which is an empty node created + * by the PCI core and thus carries no fixed-link description. + */ + if (enetc_is_pseudo_mac(priv->si) && (!node || dynamic)) { + pf->if_mode = PHY_INTERFACE_MODE_INTERNAL; + + err = enetc4_apply_overlay(priv); + if (err) + return err; + + /* Source the fixed-link speed live from PCR[PSPEED] instead + * of the overlay 'speed' cell. + */ + pf->phylink_config.get_fixed_state = enetc4_pl_get_fixed_state; + + /* The overlay was grafted onto dev's own of_node, so phylink + * will find the fixed-link via dev_fwnode(dev). Use that node + * for the subsequent MDIO/phylink setup below. + */ + node = dev_of_node(dev); + } else { + err = of_get_phy_mode(node, &pf->if_mode); + if (err) { + dev_err(dev, "Failed to get PHY mode\n"); + return err; + } } err = enetc_mdiobus_create(pf, node); if (err) { dev_err(dev, "Failed to create MDIO bus\n"); - return err; + goto err_mdiobus_create; } err = enetc_phylink_create(priv, node, &enetc_pl_mac_ops); @@ -975,6 +1058,8 @@ static int enetc4_link_init(struct enetc_ndev_priv *priv, err_phylink_create: enetc_mdiobus_destroy(pf); +err_mdiobus_create: + enetc4_put_overlay(priv); return err; } @@ -985,6 +1070,7 @@ static void enetc4_link_deinit(struct enetc_ndev_priv *priv) enetc_phylink_destroy(priv); enetc_mdiobus_destroy(pf); + enetc4_put_overlay(priv); } static void enetc4_pf_link_status_task(struct work_struct *work) diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso b/drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso new file mode 100644 index 000000000000..e3d3e4259fbd --- /dev/null +++ b/drivers/net/ethernet/freescale/enetc/enetc4_pseudo_mac.dtso @@ -0,0 +1,32 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Device-tree overlay for ENETC v4 Pseudo-MAC (PPM) ports. + * + * ENETCv4 pseudo-MACs are proprietary internal links to the on-chip NETC + * switch; they implement no standard MII interface and are modeled as a + * fixed link whose speed is set at boot time from the Port PCR[PSPEED] + * field. + * + * This overlay is applied by the ENETC4 PF driver onto the PCI function's own + * dynamic OF node (created by the PCI core when CONFIG_PCI_DYNAMIC_OF_NODES + * is enabled). The overlay only selects fixed-link mode and carries the duplex + * setting; the 'speed' property is a placeholder. + * + * Copyright 2026 NXP + */ + +/dts-v1/; +/plugin/; + +/ { + fragment@0 { + target-path = ""; + + __overlay__ { + fixed-link { + speed = <2500>; + full-duplex; + }; + }; + }; +}; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c index 8206884294a4..3ba46c3a7670 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c @@ -436,6 +436,43 @@ void enetc_mdiobus_destroy(struct enetc_pf *pf) } EXPORT_SYMBOL_GPL(enetc_mdiobus_destroy); +static struct { + unsigned long mac_cap; + int speed; /* descending order sorted */ +} enetc_phylink_pseudo_mac_caps[] = { + { MAC_25000FD, SPEED_25000 }, + { MAC_20000FD, SPEED_20000 }, + { MAC_10000FD, SPEED_10000 }, + { MAC_5000FD, SPEED_5000 }, + { MAC_2500FD, SPEED_2500 }, + { MAC_1000FD, SPEED_1000 }, + { MAC_100FD, SPEED_100 }, + { MAC_10FD, SPEED_10 }, +}; + +static unsigned long enetc_phylink_get_pseudo_mac_caps(void) +{ + unsigned long mac_caps = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(enetc_phylink_pseudo_mac_caps); i++) + mac_caps |= enetc_phylink_pseudo_mac_caps[i].mac_cap; + + return mac_caps; +} + +int enetc_phylink_match_pseudo_mac_speed(int speed) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(enetc_phylink_pseudo_mac_caps); i++) + if (enetc_phylink_pseudo_mac_caps[i].speed <= speed) + return enetc_phylink_pseudo_mac_caps[i].speed; + + return SPEED_UNKNOWN; +} +EXPORT_SYMBOL_GPL(enetc_phylink_match_pseudo_mac_speed); + int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node, const struct phylink_mac_ops *ops) { @@ -471,9 +508,7 @@ int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node, phy_interface_set_rgmii(pf->phylink_config.supported_interfaces); } else { - mac_caps |= MAC_10FD | MAC_100FD | MAC_1000FD | MAC_2500FD | - MAC_5000FD | MAC_10000FD | MAC_20000FD | - MAC_25000FD; + mac_caps |= enetc_phylink_get_pseudo_mac_caps(); } pf->phylink_config.mac_capabilities = mac_caps; diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h index c9eed879d5a3..aede1aad6362 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.h @@ -13,6 +13,7 @@ void enetc_mdiobus_destroy(struct enetc_pf *pf); int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node, const struct phylink_mac_ops *ops); void enetc_phylink_destroy(struct enetc_ndev_priv *priv); +int enetc_phylink_match_pseudo_mac_speed(int speed); void enetc_set_default_rss_key(struct enetc_pf *pf); int enetc_vlan_rx_add_vid(struct net_device *ndev, __be16 prot, u16 vid); int enetc_vlan_rx_del_vid(struct net_device *ndev, __be16 prot, u16 vid); -- 2.34.1 ^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH net-next v1 1/5] net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay 2026-10-09 12:40 ` [PATCH net-next v1 1/5] net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay Claudiu Manoil @ 2026-10-10 2:26 ` Frank Li 0 siblings, 0 replies; 3+ messages in thread From: Frank Li @ 2026-10-10 2:26 UTC (permalink / raw) To: Claudiu Manoil Cc: netdev, s32, Vladimir Oltean, Wei Fang, Clark Wang, Andrew Lunn, David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni, Rob Herring, Saravana Kannan, Russell King, linux-kernel, imx, devicetree On Fri, Oct 09, 2026 at 03:40:30PM +0300, Claudiu Manoil wrote: > [You don't often get email from claudiu.manoil@nxp.com. Learn why this is important at https://aka.ms/LearnAboutSenderIdentification ] > > ENETCv4 has special internal links when connected to the on-chip NETC > switch via internal switch ports, called pseudo-MAC links. These > pseudo-MACs are proprietary, they don't implement any standard IEEE > interface (like MII), and can be modeled as fixed links with the link > speed determined at boot time by the Port PCR[PSPEED] register > configuration. > > We also need to be able to probe the ENETCv4 Ports featuring pseudo-MACs > as pure PCI devices, i.e. without any "ethernet" DT node representation. > The typical use case for this consists in a board with NETC connected > via PCI to another host which probes the ENETC. Note that in this > scenario, the pseudo-MAC ENETCs are connected internally to a NETC > switch that is not owned by Linux. > > Since such a port has no "ethernet" DT node, its fixed link has to be > synthesized at probe time. Rather than hand-building a named software > node, describe the fixed link with a self-contained device-tree overlay, > following the approach used by the Microchip lan966x PCI driver. The > overlay is compiled from enetc4_pseudo_mac.dtso into a .dtbo blob and > embedded in the driver via the kernel's dtbo wrapping > (__dtbo_*_begin/_end symbols). > > The overlay fragment uses an empty target-path, so it is grafted onto > the base node passed to of_overlay_fdt_apply(), i.e. the PCI function's > own dynamic OF node (created by the PCI core when > CONFIG_PCI_DYNAMIC_OF_NODES is enabled). The fixed-link node is therefore > spliced directly onto the ENETC netdev's fwnode, exactly as if it had > come from static DT, and phylink picks it up through dev_fwnode(). > > The overlay only adds a new fixed-link node; it deliberately does not add > a phy-mode property. A device-tree overlay may only add new nodes (which > are tracked with the OF_OVERLAY flag and freed cleanly on removal), not > new properties onto an already-live node such as the PCI function's > dynamic OF node. The phy-mode is instead set programmatically by the driver > (pf->if_mode) before the overlay is applied. > > The pseudo-MAC overlay path is selected when the port has no OF node, or > when it only has the empty PCI-synthesized node (OF_DYNAMIC), which > carries no fixed-link description. Ports described by static DT take the > regular of_get_phy_mode() path instead. > > The overlay blob is applied unmodified, it only selects fixed-link > mode and carries the duplex setting; its 'speed' cell is a placeholder. > The real operating speed is sourced live from PCR[PSPEED] through the > phylink get_fixed_state callback, which lets the driver override the > fixed-link state at link time. The overlay is removed on teardown and on > the probe error unwind. > > The driver gains a build dependency on OF_OVERLAY. In addition, the > node-less pseudo-MAC path has a runtime dependency on > CONFIG_PCI_DYNAMIC_OF_NODES: that is what makes the PCI core synthesize > the per-function OF node (of_pci_make_dev_node()) that the overlay is > applied onto. This is intentionally not a hard Kconfig dependency, since > the ENETC4 driver also serves regular ports described by static DT; when > PCI_DYNAMIC_OF_NODES is absent the PCI function has no of_node and the > pseudo-MAC probe path fails gracefully with a clear -ENODEV error. > > Signed-off-by: Claudiu Manoil <claudiu.manoil@nxp.com> > --- > drivers/net/ethernet/freescale/enetc/Kconfig | 1 + > drivers/net/ethernet/freescale/enetc/Makefile | 1 + > drivers/net/ethernet/freescale/enetc/enetc.h | 1 + > .../net/ethernet/freescale/enetc/enetc4_pf.c | 98 +++++++++++++++++-- > .../freescale/enetc/enetc4_pseudo_mac.dtso | 32 ++++++ Not sure why need dt overlay here, there are already dymatic update dts by of_changeset_* API, like of_changeset_create_node(). Frank ^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-10-10 13:13 UTC | newest] Thread overview: 3+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-10-10 13:13 [PATCH net-next v1 1/5] net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay netdev-bot+sashiko -- strict thread matches above, loose matches on Subject: below -- 2026-10-09 12:40 [PATCH net-next v1 0/5] net: enetc: S32N79 pseudo-MAC (PPM) networking support Claudiu Manoil 2026-10-09 12:40 ` [PATCH net-next v1 1/5] net: enetc: Add pseudo-MAC support for ENETCv4 Ports via a DT overlay Claudiu Manoil 2026-10-10 2:26 ` Frank Li
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox