Re: [net-next PATCH v4 3/4] net: pcs: xpcs: Add hooks for xpcs configuration of rsfec
Jakub Kicinski <[email protected]> Mon, 3 Aug 2026 18:48:42 -0700
| Newsgroups | org.kernel.vger.netdev,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
This is an AI-generated review of your patch. The human sending this email has considered the AI review valid, or at least plausible. --- --- Patch [3]: [net-next PATCH v4 3/4] net: pcs: xpcs: Add hooks for xpcs configuration of rsfec --- commit 6935ace349fd9a75ff7b20b38cca3d38ecc8571b Author: Mike Marciniszyn (Meta) <[email protected]> net: pcs: xpcs: Add hooks for xpcs configuration of rsfec This adds a per-interface-mode .pma_config hook to the Synopsys xPCS compat table and uses it to write MDIO_PMA_RSFEC_CTRL for 25GBASE-R, 50GBASE-R, LAUI and 100GBASE-P. A new vendor bit is added to pcs-xpcs.h and a new bit define is added to include/uapi/linux/mdio.h. A few questions below. > diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c > index a6b993745f3be..3800c129dae2e 100644 > --- a/drivers/net/pcs/pcs-xpcs.c > +++ b/drivers/net/pcs/pcs-xpcs.c > @@ -1394,6 +1394,69 @@ static int xpcs_read_ids(struct dw_xpcs *xpcs) > return 0; > } > > +struct pma_pcs_values { > + int channels; > + u16 rsfec_ctrl; > +}; > + > +static int > +xpcs_config_rsfec_pma(struct dw_xpcs *xpcs, const struct pma_pcs_values *v) > +{ > + /* fbnic's DW IP exposes the RS-FEC PMA at SEP_PMA1, so use it > + * directly. Scanning DEVS1 for the correct PMA MMD is left as future > + * work for enabling a non-fbnic device on this PCS. > + */ > + int pma_mmd = MDIO_MMD_SEP_PMA1; > + int ret = 0, i; > + > + for (i = 0; ret >= 0 && i < v->channels; i++) { > + ret = xpcs_mdev_write_ch(xpcs, i, pma_mmd, > + MDIO_PMA_RSFEC_CTRL, v->rsfec_ctrl); > + } > + > + return ret; > +} [Severity: Medium] [Finding: main-1-0] [Sources: opus-5, sonnet-5] The comment states the SEP_PMA1 placement is an fbnic property, but the hooks below are attached to synopsys_xpcs_compat[], which xpcs_identify() selects for every device matching DW_XPCS_ID/DW_XPCS_ID_MASK (stmmac via xpcs_create_fwnode()/xpcs_create_mdiodev(), ksz9477, txgbe SP). Should these hooks be gated on xpcs->info.pma, or live in a device specific compat table? The file already has both mechanisms: xpcs_do_config() checks WX_TXGBE_XPCS_PMA_10G_ID, xpcs_create() checks MP_FBNIC_XPCS_PMA_100G_ID, and nxp_sja1105_xpcs_compat / nxp_sja1110_xpcs_compat show the separate table approach. There is also no MDIO_DEVS1 / MDIO_DEVS_SEP_PMA1 presence check before writing, so on a DW xPCS that does not implement SEP_PMA1 this writes into an MMD that may not exist. Is that intended? Second question on the same loop: the iteration count comes from v->channels rather than xpcs->channels. Given: drivers/net/pcs/pcs-xpcs.c:xpcs_mdev_write_ch() { if (ch >= xpcs->channels) return -ENXIO; ... } and xpcs_do_config() propagating the pma_config() error, wouldn't a single channel xPCS instance selecting PHY_INTERFACE_MODE_LAUI or PHY_INTERFACE_MODE_100GBASEP (both .channels = 2 below) fail interface configuration outright with -ENXIO, after channel 0 has already been written and with no unwind of that write? In the current tree fbnic creates its PCS with two addresses so xpcs->channels is 2 and this is not reachable today, and the 25G Wangxun AML part never instantiates an xPCS at all, so this looks latent rather than an active regression. Would deriving the loop bound from xpcs->channels avoid it entirely? > + > +static int xpcs_25gbaser_pma_config(struct dw_xpcs *xpcs) > +{ > + const struct pma_pcs_values v = { > + .rsfec_ctrl = 0, > + .channels = 1, > + }; [Severity: Medium] [Finding: main-1-1] [Sources: opus-5] The commit message says this "enables the correct FEC settings to enable RS-FEC encoding on the link". Which write sets an RS-FEC enable bit? For 25GBASE-R the value written to MDIO_PMA_RSFEC_CTRL is a literal 0. The other three hooks write only DW_VR_RSFEC_CTRL_TC_PAD_ALTER (BIT(10)) or MDIO_PMA_RSFEC_CTRL_4LANE_PMD (BIT(3)). Also, xpcs_config_rsfec_pma() does a full 16-bit write rather than a masked update via the existing xpcs_modify() helper, so the RS-FEC enable / bypass-correction / bypass-indication bits of this standards-defined register are unconditionally cleared. Is it safe to discard whatever firmware or an earlier bring-up stage programmed there? A related question on the keying: the value depends only on phy_interface_t and not on the selected FEC mode. fbnic handles FBNIC_AUI_LAUI2 with FBNIC_FEC_OFF in fbnic_mac_get_link_status(), yet PHY_INTERFACE_MODE_LAUI here always programs the transcode pad alter bit, and FBNIC_AUI_25GAUI with FBNIC_FEC_RS still ends up writing 0. Should the register contents track the negotiated FEC mode? Nothing reads the register back or checks an RS-FEC status bit afterwards, so a wrong value would be silent. > + > + return xpcs_config_rsfec_pma(xpcs, &v); > +} > + > +static int xpcs_50gbaser_pma_config(struct dw_xpcs *xpcs) > +{ > + const struct pma_pcs_values v = { > + .rsfec_ctrl = DW_VR_RSFEC_CTRL_TC_PAD_ALTER, > + .channels = 1, > + }; > + > + return xpcs_config_rsfec_pma(xpcs, &v); > +} > + > +static int xpcs_50gbaser2_pma_config(struct dw_xpcs *xpcs) > +{ > + const struct pma_pcs_values v = { > + .rsfec_ctrl = DW_VR_RSFEC_CTRL_TC_PAD_ALTER, > + .channels = 2, > + }; > + > + return xpcs_config_rsfec_pma(xpcs, &v); > +} > + > +static int xpcs_100gbasep_pma_config(struct dw_xpcs *xpcs) > +{ > + const struct pma_pcs_values v = { > + .rsfec_ctrl = MDIO_PMA_RSFEC_CTRL_4LANE_PMD, > + .channels = 2, > + }; > + > + return xpcs_config_rsfec_pma(xpcs, &v); > +} > + > static const struct dw_xpcs_compat synopsys_xpcs_compat[] = { [ ... ] > diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h > index 36f4906e689a8..ab47d6dd050c7 100644 > --- a/drivers/net/pcs/pcs-xpcs.h > +++ b/drivers/net/pcs/pcs-xpcs.h > @@ -94,6 +94,12 @@ > #define DW_VR_MII_DIG_CTRL2_TX_POL_INV BIT(4) > #define DW_VR_MII_DIG_CTRL2_RX_POL_INV BIT(0) > > +/* Clause 133 defines */ > +/* RSFEC transcode pad alter > + * DW vendor extension in RS-FEC control > + */ > +#define DW_VR_RSFEC_CTRL_TC_PAD_ALTER BIT(10) [Severity: Low] [Finding: main-3-8] [Sources: opus-5] This isn't a bug, but is "Clause 133" the right reference here? In IEEE 802.3-2022 the RS-FEC sublayer and its MDIO registers are Clause 134 (Clause 108 for 25G RS-FEC), and Clause 133 is a PCS clause. The next patch in this series cites "IEEE 133.2.2" for PCS alignment marker content, which suggests the same. Also, the macro name implies a register macro DW_VR_RSFEC_CTRL, which does not exist anywhere in the tree; the register actually written is MDIO_PMA_RSFEC_CTRL in MDIO_MMD_SEP_PMA1. The rest of the file prefixes a bit macro with the register macro it belongs to, for example DW_VR_MII_DIG_CTRL2 -> DW_VR_MII_DIG_CTRL2_TX_POL_INV. The define is also placed right after the DW_VR_MII_* block, which is MMD 31 vendor MII, while this bit belongs to a PMA MMD register. Would moving it and renaming it to match the register make this clearer? > + > #define DW_XPCS_INFO_DECLARE(_name, _pcs, _pma) \ > static const struct dw_xpcs_info _name = { .pcs = _pcs, .pma = _pma } > > diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h > index b2541c948fc1e..5219c877b2cfd 100644 > --- a/include/uapi/linux/mdio.h > +++ b/include/uapi/linux/mdio.h > @@ -317,6 +317,9 @@ > #define MDIO_PMA_10GBR_FECABLE_ABLE 0x0001 /* FEC ability */ > #define MDIO_PMA_10GBR_FECABLE_ERRABLE 0x0002 /* FEC error indic. ability */ > > +/* RSFEC PMA Control register */ > +#define MDIO_PMA_RSFEC_CTRL_4LANE_PMD BIT(3) > + [Severity: Low] [Finding: main-1-2] [Sources: opus-5] This isn't a bug, but could the IEEE clause and table that define bit 3 of register 1.200 be cited here? Since the sibling bit of the same register added by this patch (DW_VR_RSFEC_CTRL_TC_PAD_ALTER) is described as a DW vendor extension and kept in the driver header, it is hard to tell from the patch whether bit 3 is genuinely standard or also Synopsys specific. If it is vendor specific, pcs-xpcs.h with a DW_VR_ prefix would be the better home. Placement is also a little odd: the new define sits inside the 10GBASE-R FEC ability block, between MDIO_PMA_10GBR_FECABLE_ERRABLE and MDIO_PMA_10GBR_FSRT_ENABLE, rather than next to the MDIO_PMA_RSFEC_CTRL register definition earlier in the file. Would moving it beside MDIO_PMA_RSFEC_CTRL be preferable? > /* PMA 10GBASE-R Fast Retrain status and control register. */ > #define MDIO_PMA_10GBR_FSRT_ENABLE 0x0001 /* Fast retrain enable */ >