From: mike.marciniszyn@gmail.com
To: Andrew Lunn <andrew@lunn.ch>,
Heiner Kallweit <hkallweit1@gmail.com>,
Russell King <linux@armlinux.org.uk>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Alexander Duyck <alexanderduyck@fb.com>,
Kees Cook <kees@kernel.org>
Cc: mike.marciniszyn@gmail.com, netdev@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: [PATCH net-next 2/2] net: pcs: xpcs: Add handling for 4 channel rsfec device
Date: Wed, 6 May 2026 15:09:04 -0400 [thread overview]
Message-ID: <20260506190904.4029-3-mike.marciniszyn@gmail.com> (raw)
In-Reply-To: <20260506190904.4029-1-mike.marciniszyn@gmail.com>
From: "Mike Marciniszyn (Meta)" <mike.marciniszyn@gmail.com>
This patch introduces the configuration of vendor specific
registers for alignment encoding, PCS Mode, and VL_INTVL
over the one or two instances as required.
The DW_PCS IP specification calls out the need to configure both
lanes identically when using 2 lane modes such as 50-R2 and 100-R2, so
the programming is repeated for each lane.
The encoding tables are derived from the IEEE 8023-2022 spec sections
82.2.7 and tables 82-2 and 82-3 for the alignment markers and their
insertion.
Note that there is a conflict between VRs DW_VR_XS_PCS_DIG_STS and
and the DW_PCS_IP DW_VR_MII_PCS_PCS_MODE. The bit mask for
DW_VR_XS_PCS_DIG_STS/RX_FIFO_ERR fits within the reserved bits for
the DW_PCS IP the DW_VR_MII_PCS_PCS_MODE register so there is no issue.
There is also a confict between DW_VR_MII_PCS_VL_INTVL and
DW_VR_MII_AN_INTR_STS but an_mode differs, so again there is no issue.
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Signed-off-by: Mike Marciniszyn (Meta) <mike.marciniszyn@gmail.com>
---
drivers/net/pcs/pcs-xpcs.c | 90 +++++++++++++++++++++++++++++++++++++-
drivers/net/pcs/pcs-xpcs.h | 25 +++++++++++
2 files changed, 114 insertions(+), 1 deletion(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 0987621632a7..c42eacafad91 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -1429,21 +1429,94 @@ static int xpcs_get_pma_mmd(struct dw_xpcs *xpcs)
return -ENODEV;
}
+/* m0 - m2 from Table 82-2/82-3
+ * m4 - m6 are skipped since they are inversions of m0 - m2.
+ * Inverted parity fields (IEEE 82.2.8) bip3 and bip7 are omitted.
+ */
+struct lane_markers {
+ u8 m0, m1, m2;
+};
+
+/* Alignment marker encodings, see table 82-2 in IEEE 802.3-2022 */
+static const struct lane_markers xpcs_100gbaser_markers[] = {
+ {0xc1, 0x68, 0x21},
+ {0x9d, 0x71, 0x8e},
+ {0x59, 0x4b, 0xe8},
+ {0x4d, 0x95, 0x7b},
+};
+
+/* Alignment marker encodings, see table 82-3 in IEEE 802.3-2022
+ * The content of the 50G markers is identical to 40G values (IEEE 133.2.2).
+ */
+static const struct lane_markers xpcs_50gbaser_markers[] = {
+ {0x90, 0x76, 0x47},
+ {0xf0, 0xc4, 0xe6},
+ {0xc5, 0x65, 0x9b},
+ {0xa2, 0x79, 0x3d},
+};
+
struct pma_pcs_values {
+ const struct lane_markers *vl0_markers;
+ const struct lane_markers *vl123_markers;
int lanes;
u16 rsfec_ctrl;
+ u16 pcs_mode;
+ u16 vl_intvl;
};
+#define XPCS_VL_TO_REG(vl, lh) \
+ (((vl) * 2) + DW_VR_MII_PCS_VL0_##lh)
+
+static int xpcs_write_pcs_prtad(struct dw_xpcs *xpcs, int prtad, int reg,
+ u16 val)
+{
+ return xpcs_bus_write(xpcs, prtad, MDIO_MMD_PCS, reg, val);
+}
+
+static int xpcs_config_vl_markers(struct dw_xpcs *xpcs, int vl, int addr,
+ const struct lane_markers *m)
+{
+ int ret;
+
+ /* m0, m1, m2 written to _L and _H registers
+ *
+ * _L = (m1 << 8) | m0
+ * _H = m2
+ */
+ ret = xpcs_write_pcs_prtad(xpcs, addr, XPCS_VL_TO_REG(vl, L),
+ ((u16)m->m1 << 8) | m->m0);
+ if (ret < 0)
+ return ret;
+ return xpcs_write_pcs_prtad(xpcs, addr, XPCS_VL_TO_REG(vl, H), m->m2);
+}
+
static int
xpcs_config_rsfec_pma(struct dw_xpcs *xpcs, const struct pma_pcs_values *v)
{
- int ret = 0, i, pma_mmd;
+ int ret = 0, i, vl, pma_mmd;
pma_mmd = xpcs_get_pma_mmd(xpcs);
if (pma_mmd < 1)
return pma_mmd;
for (i = 0; ret >= 0 && i < v->lanes; i++) {
+ /* code word markings */
+ for (vl = 0; ret >= 0 && vl < 4; vl++)
+ ret = xpcs_config_vl_markers(xpcs, vl, i,
+ !vl ? &v->vl0_markers[0] :
+ &v->vl123_markers[vl - 1]);
+ if (ret < 0)
+ break;
+ /* vendor registers */
+ ret = xpcs_write_pcs_prtad(xpcs, i, DW_VR_MII_PCS_VL_INTVL,
+ v->vl_intvl);
+ if (ret < 0)
+ break;
+ ret = xpcs_write_pcs_prtad(xpcs, i, DW_VR_MII_PCS_PCS_MODE,
+ v->pcs_mode);
+ if (ret < 0)
+ break;
+ /* rsfec register */
ret = xpcs_bus_write(xpcs, i, pma_mmd, MDIO_PMA_RSFEC_CTRL,
v->rsfec_ctrl);
}
@@ -1455,6 +1528,13 @@ static int xpcs_25gbaser_pma_config(struct dw_xpcs *xpcs)
const struct pma_pcs_values v = {
.rsfec_ctrl = 0,
.lanes = 1,
+ /* 25g markers from 100g and 50g tables per 802.3-2022
+ * 108.5.2.4
+ */
+ .vl0_markers = &xpcs_100gbaser_markers[0],
+ .vl123_markers = &xpcs_50gbaser_markers[1],
+ .vl_intvl = 20479,
+ .pcs_mode = DW_VR_MII_PCS_MODE_CLAUSE107,
};
return xpcs_config_rsfec_pma(xpcs, &v);
@@ -1465,6 +1545,10 @@ 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,
.lanes = 2,
+ .vl0_markers = &xpcs_50gbaser_markers[0],
+ .vl123_markers = &xpcs_50gbaser_markers[1],
+ .pcs_mode = 0,
+ .vl_intvl = 20479,
};
return xpcs_config_rsfec_pma(xpcs, &v);
@@ -1475,6 +1559,10 @@ static int xpcs_100gbasep_pma_config(struct dw_xpcs *xpcs)
const struct pma_pcs_values v = {
.rsfec_ctrl = MDIO_PMA_RSFEC_CTRL_4LANE_PMD,
.lanes = 2,
+ .vl0_markers = &xpcs_100gbaser_markers[0],
+ .vl123_markers = &xpcs_100gbaser_markers[1],
+ .pcs_mode = DW_VR_MII_PCS_MODE_DISABLE_MLD,
+ .vl_intvl = 16383,
};
return xpcs_config_rsfec_pma(xpcs, &v);
diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h
index 187cdec30e70..8161d75370e6 100644
--- a/drivers/net/pcs/pcs-xpcs.h
+++ b/drivers/net/pcs/pcs-xpcs.h
@@ -100,6 +100,31 @@
*/
#define DW_VR_RSFEC_CTRL_TC_PAD_ALTER BIT(10)
+/* Vendor specific 4 channel PCS registers */
+
+/* DW_VR_MII_PCS_VL_INTVL and DW_VR_MII_AN_INTR_STS conflict
+ * but code paths are different
+ */
+#define DW_VR_MII_PCS_VL_INTVL 0x8002
+/* 0x8008 - 0x800f */
+#define DW_VR_MII_PCS_VL0_L 0x8008
+#define DW_VR_MII_PCS_VL0_H 0x8009
+#define DW_VR_MII_PCS_PCS_MODE 0x8010
+
+/* DW_VR_MII_PCS_PCS_MODE bits */
+#define DW_VR_MII_PCS_MODE_HI_BER25 BIT(2)
+#define DW_VR_MII_PCS_MODE_DISABLE_MLD BIT(1)
+#define DW_VR_MII_PCS_MODE_CLAUSE49 BIT(0)
+
+/* 25G requires these two bits are set.
+ *
+ * The CLAUSE49 bit changes the interface with the MAC
+ * to 64 bit and the BER25 bit changes the measurement
+ * interval to 2ms.
+ */
+#define DW_VR_MII_PCS_MODE_CLAUSE107 \
+ (DW_VR_MII_PCS_MODE_HI_BER25 | DW_VR_MII_PCS_MODE_CLAUSE49)
+
#define DW_XPCS_INFO_DECLARE(_name, _pcs, _pma) \
static const struct dw_xpcs_info _name = { .pcs = _pcs, .pma = _pma }
--
2.43.0
prev parent reply other threads:[~2026-05-06 19:09 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-06 19:09 [PATCH net-next 0/2] second series for xpcs based rsfec configuration mike.marciniszyn
2026-05-06 19:09 ` [PATCH net-next 1/2] net: pcs: xpcs: Add hooks for xpcs configuration of rsfec mike.marciniszyn
2026-05-06 19:09 ` mike.marciniszyn [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260506190904.4029-3-mike.marciniszyn@gmail.com \
--to=mike.marciniszyn@gmail.com \
--cc=alexanderduyck@fb.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=hkallweit1@gmail.com \
--cc=kees@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux@armlinux.org.uk \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox