From nobody Sat May 30 09:29:23 2026 Received: from mail-qk1-f179.google.com (mail-qk1-f179.google.com [209.85.222.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 4B30147CC96 for ; Mon, 11 May 2026 18:26:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778523970; cv=none; b=O5qvItIhro3gGNMVnW9hGBphUuHodDVqIr1faiBg6Efjn2TzJdxl8ayn004Ktze1kMIU+hf8xqszi3A0/iShXrhUBVsezNHYx5fvLhvYn5RagBCvArMm6fX7Vo1xb97T7n03NO6L3u4aX93w5BvtREB1X2P1BsOWkBCAT45ST18= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778523970; c=relaxed/simple; bh=w41p+XuSWxGXnKnkYfxFdCURnDMoorLE5URRZqMD+dA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=qeb1uJnj/rq6EyrnvBZtu2Q0GrHduNLPUbI55KPEttfHfUTxT64/lPxBSSAQeyZBgE4zxa2kDoxiIetsPZg0+/HqR+gIw7eOGEm0o6LeUKQ+AEaJork0qMU5S2MGb4mHKq1NoFW3fmeIErH4ZYDm2e7AvDOVJ33LBtbSArXOifk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=YtyScQAV; arc=none smtp.client-ip=209.85.222.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="YtyScQAV" Received: by mail-qk1-f179.google.com with SMTP id af79cd13be357-8ea8563c693so505788885a.2 for ; Mon, 11 May 2026 11:26:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778523968; x=1779128768; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=qGg607mDB+aA+0BtLq6p1jTSY7WNpk5M8K/OgQPTtdk=; b=YtyScQAVT8ZIi/dS3Ya1eLa1bHFmEWpTBLzdi1YCKSAwwcjbx+1c4tC1pYyr9E7bsN AHrjKaVII18Vgs35fj0G3vwd3KrBqsE0qPFoQ+iTJHFtwkBJZzjQHIlOyHkvh/weKb9N B9MXMmxhFOD0ad95ugtf6Tj85ewBNw3esiMruA3JGGfsYeISueAtmjHmrqNoSMRf5lNM JwZDQ3RvPaRP+nuLFpdNUpH14V+9H5pXhFJicZa/wAQLcLngL2WM0u5tGTUdUzQlti6X 6Kqw9va/3bh4v/juABLbu+N7sUqsJtuj9J1GHBsDwPQV/vkPVjJGAv4H3O26c8SkpVor Lv0g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778523968; x=1779128768; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=qGg607mDB+aA+0BtLq6p1jTSY7WNpk5M8K/OgQPTtdk=; b=pBjcRAWR1j/oyig7/ycyHVgj3TJq8DL3vWxrJL7YVKWRFOugcBZgIl/1vt8Xfxk1Gq vtoEDq+lSRaY0nJOUXPNyvoZgbp8kPmeJjv38yaQwkg5r+p5cRkI2WqFcwxlTTDo6Oao vSBQtajMJaFCc3EvbyYIv56HWDivY+Bjd5phfKYJ6NpkEh4XXCAjeA9mNbUT6ATNoxy7 GvTMEOu2v3mWWhN5rHtOMsoF3OccKb/GRJSiZohALHzDOm7BloMpcLzMISrgTJ7uAbcs V4EkQC+wIwX4e+xuIeu5MCLIL0rKO6YhKoTOSoyncJo0hNgrhfV9z+YH+cJ4KhLrE69P dh4Q== X-Forwarded-Encrypted: i=1; AFNElJ9bZnbcvHTbaygmOMW6ElaX843R5SiEhrmqAc2f21atwuoAg7v0/gpzoHKXm7+XN+JkGlktvnGllWHECvs=@vger.kernel.org X-Gm-Message-State: AOJu0YxRxr9BiZ5l2Q2H9YnYwEzrly5lwUyVpWhm1B8so+oIZF4+mqyN H4q4DJofjTvlvFMwG5jnjwV+HiExyFAHp/Y/GLhCjiBKsS/XUNDauTeb X-Gm-Gg: Acq92OFJ8lGTL0ti5ISowB/FBxb4oiKGED664l5udj+CMVbzJCVHf3TDKm3OgQfJjmM Qp++3N1TafSEs/2bTVZLvFuYBLeZGPPbJUQi8VBXyJ46Q2FWWA5JVwChLzJPp2p3SYJ7Gxjc4+P t3bscToR94Gir8hbwl7rNfdwptMmhRkaYOuFIYfC3vrpa7Q6it15d2KGXtaEz9f7ciI+NcxcN24 I8zhEnngHqjduSksPaNJeXQQh6w3cv8CL7iGcWCkT5GJ3+DM0VzSJIDiafVdaE5Q/kvJgLoK0T/ /TY+cLeoeCHI8qZcSLD1En4caWhFYvt6ga22fwYOsX9EILeh5x0yVlQgZa9+YFGfyKIxRwQpLAj VTslwmmZV0pSZOFrZYsLKPhgS9znLiaPxhZJzUqMYQ2B0e2Q0mPGS3vFd5nF+sIWVteKC9pW61H gsVlySZoPd7SEJv0ScvDhhO5t6eHfQrT0mlrCfey5GBlSYQb+bA2lwEA820s1t7/Pc+5/ea9QXc cIRiw== X-Received: by 2002:a05:620a:40d1:b0:8ea:f0e0:26dc with SMTP id af79cd13be357-904d4d54625mr4121831885a.24.1778523968159; Mon, 11 May 2026 11:26:08 -0700 (PDT) Received: from PF5YBGDS.localdomain ([163.114.130.1]) by smtp.gmail.com with ESMTPSA id af79cd13be357-907b8d9ea06sm1111346885a.20.2026.05.11.11.26.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 May 2026 11:26:07 -0700 (PDT) From: mike.marciniszyn@gmail.com To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Heiner Kallweit , Russell King , Kees Cook , Andrew Lunn Cc: mike.marciniszyn@gmail.com, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 1/2] net: pcs: xpcs: Add hooks for xpcs configuration of rsfec Date: Mon, 11 May 2026 14:26:03 -0400 Message-ID: <20260511182604.1338-2-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260511182604.1338-1-mike.marciniszyn@gmail.com> References: <20260511182604.1338-1-mike.marciniszyn@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" The DW PCS IP data sheet calls out the need to populate these vendor registers when operating at speeds above 10Gbps. This change enables the correct FEC settings to enable RS-FEC encoding on the link which is the standard used for most links at these higher speeds. Note that the overwriting of the MDIO_PMA_RSFEC_CTRL register is intentional and consistent DW PCS IP requirements. Reviewed-by: Alexander Duyck Signed-off-by: Mike Marciniszyn (Meta) --- v2: - Allow mdiobus probing for addr 0 and addr 1 - Add xpcs_find* helpers based on phy_find* to avoid hardcoded addresses - Remove xpcs_bus write and use mdiodev_c45_write instead - Address comment on use of MDIO_PMA_RSFEC_CTRL v1: https://lore.kernel.org/all/20260506190904.4029-2-mike.marciniszyn@gmai= l.com/ drivers/net/ethernet/meta/fbnic/fbnmdiodev_c45_writeic_mdio.c | 3 +- drivers/net/pcs/pcs-xpcs.c | 105 +++++++++++++++++++ drivers/net/pcs/pcs-xpcs.h | 6 ++ include/uapi/linux/mdio.h | 3 + 4 files changed, 115 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c b/drivers/net/eth= ernet/meta/fbnic/fbnic_mdio.c index fe3a4ce88413..e29534dd1e0c 100644 --- a/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c +++ b/drivers/net/ethernet/meta/fbnic/fbnic_mdio.c @@ -263,8 +263,7 @@ int fbnic_mdiobus_create(struct fbnic_dev *fbd) bus->read_c45 =3D &fbnic_mdio_read_c45; bus->write_c45 =3D &fbnic_mdio_write_c45; =20 - /* Disable PHY auto probing. We will add PCS manually */ - bus->phy_mask =3D ~0; + bus->phy_mask =3D GENMASK(31, 2); =20 bus->parent =3D fbd->dev; bus->priv =3D fbd; diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index e69fa2f0a0e8..14f89e56958c 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -1402,6 +1402,107 @@ static int xpcs_read_ids(struct dw_xpcs *xpcs) return 0; } =20 +static int xpcs_get_pma_mmd(struct dw_xpcs *xpcs) +{ + int devs1, b; + + devs1 =3D xpcs_read(xpcs, MDIO_MMD_PMAPMD, MDIO_DEVS1); + if (devs1 < 0) + return devs1; + + /* Locate the PMA closest to the PCS as this should be the one provided + * with the DW IP. This is identified by being the PMA with the + * highest MMD device address. + */ + devs1 &=3D MDIO_DEVS_SEP_PMA1 | MDIO_DEVS_SEP_PMA2 | MDIO_DEVS_SEP_PMA3 | + MDIO_DEVS_SEP_PMA4 | MDIO_DEVS_PMAPMD; + b =3D fls(devs1); + if (b) + return b - 1; + + return -ENODEV; +} + +struct pma_pcs_values { + int lanes; + u16 rsfec_ctrl; +}; + +static struct mdio_device *xpcs_find_first_mdev(struct dw_xpcs *xpcs) +{ + struct phy_device *p =3D phy_find_first(xpcs->mdiodev->bus); + + if (!p) + return NULL; + return &p->mdio; +} + +static struct mdio_device * +xpcs_find_next_mdev(struct dw_xpcs *xpcs, struct mdio_device *mdev) +{ + struct phy_device *p =3D container_of(mdev, struct phy_device, mdio), *n; + + n =3D phy_find_next(xpcs->mdiodev->bus, p); + if (!n) + return NULL; + return &n->mdio; +} + +static int +xpcs_config_rsfec_pma(struct dw_xpcs *xpcs, const struct pma_pcs_values *v) +{ + struct mdio_device *mdev; + int ret =3D 0, i, pma_mmd; + + pma_mmd =3D xpcs_get_pma_mmd(xpcs); + if (pma_mmd < 1) + return pma_mmd; + + mdev =3D xpcs_find_first_mdev(xpcs); + if (!mdev) + return -ENODEV; + + for (i =3D 0; mdev && ret >=3D 0 && i < v->lanes; + i++, mdev =3D xpcs_find_next_mdev(xpcs, mdev)) { + ret =3D mdiodev_c45_write(mdev, pma_mmd, MDIO_PMA_RSFEC_CTRL, + v->rsfec_ctrl); + } + if (!ret && i < v->lanes) + return -ENODEV; + + return ret; +} + +static int xpcs_25gbaser_pma_config(struct dw_xpcs *xpcs) +{ + const struct pma_pcs_values v =3D { + .rsfec_ctrl =3D 0, + .lanes =3D 1, + }; + + return xpcs_config_rsfec_pma(xpcs, &v); +} + +static int xpcs_50gbaser_pma_config(struct dw_xpcs *xpcs) +{ + const struct pma_pcs_values v =3D { + .rsfec_ctrl =3D DW_VR_RSFEC_CTRL_TC_PAD_ALTER, + .lanes =3D 2, + }; + + return xpcs_config_rsfec_pma(xpcs, &v); +} + +static int xpcs_100gbasep_pma_config(struct dw_xpcs *xpcs) +{ + const struct pma_pcs_values v =3D { + .rsfec_ctrl =3D MDIO_PMA_RSFEC_CTRL_4LANE_PMD, + .lanes =3D 2, + }; + + return xpcs_config_rsfec_pma(xpcs, &v); +} + static const struct dw_xpcs_compat synopsys_xpcs_compat[] =3D { { .interface =3D PHY_INTERFACE_MODE_USXGMII, @@ -1415,6 +1516,7 @@ static const struct dw_xpcs_compat synopsys_xpcs_comp= at[] =3D { .interface =3D PHY_INTERFACE_MODE_25GBASER, .supported =3D xpcs_25gbaser_features, .an_mode =3D DW_AN_C73, + .pma_config =3D xpcs_25gbaser_pma_config, }, { .interface =3D PHY_INTERFACE_MODE_XLGMII, .supported =3D xpcs_xlgmii_features, @@ -1423,14 +1525,17 @@ static const struct dw_xpcs_compat synopsys_xpcs_co= mpat[] =3D { .interface =3D PHY_INTERFACE_MODE_50GBASER, .supported =3D xpcs_50gbaser_features, .an_mode =3D DW_AN_C73, + .pma_config =3D xpcs_50gbaser_pma_config, }, { .interface =3D PHY_INTERFACE_MODE_LAUI, .supported =3D xpcs_50gbaser2_features, .an_mode =3D DW_AN_C73, + .pma_config =3D xpcs_50gbaser_pma_config, }, { .interface =3D PHY_INTERFACE_MODE_100GBASEP, .supported =3D xpcs_100gbasep_features, .an_mode =3D DW_AN_C73, + .pma_config =3D xpcs_100gbasep_pma_config, }, { .interface =3D PHY_INTERFACE_MODE_10GBASER, .supported =3D xpcs_10gbaser_features, diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h index 929fa238445e..187cdec30e70 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) =20 +/* Clause 133 defines */ +/* RSFEC transcode pad alter + * DW vendor extension in RS-FEC control + */ +#define DW_VR_RSFEC_CTRL_TC_PAD_ALTER BIT(10) + #define DW_XPCS_INFO_DECLARE(_name, _pcs, _pma) \ static const struct dw_xpcs_info _name =3D { .pcs =3D _pcs, .pma =3D _pma= } =20 diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h index b2541c948fc1..5219c877b2cf 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 = */ =20 +/* RSFEC PMA Control register */ +#define MDIO_PMA_RSFEC_CTRL_4LANE_PMD BIT(3) + /* PMA 10GBASE-R Fast Retrain status and control register. */ #define MDIO_PMA_10GBR_FSRT_ENABLE 0x0001 /* Fast retrain enable */ =20 --=20 2.43.0 From nobody Sat May 30 09:29:23 2026 Received: from mail-qk1-f179.google.com (mail-qk1-f179.google.com [209.85.222.179]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 61F3647CC86 for ; Mon, 11 May 2026 18:26:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.222.179 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778523973; cv=none; b=lZGS/zH7ilsSthTJsUNWa0sxciJdrRQ2cL32iBEvdGlNWc3ZaX9+VS+Oc2j3UCQJLRLCq6blGlc6OgL5ezIZsn/6AOPsSakkGsGAq8oVupNtxxQC59VmYJElu1LbWy6sgkyHXhfsZVp65f1Z+Ep+5HKHXKXLri3ORroB+AR5ReU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778523973; c=relaxed/simple; bh=xoHMDWCFTSWyp3aBg4y+YZIB2hZX8iQkmdTvgMWUAZ0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Zq58L1X/0K9DrrDAMH+P6RO0PfLatofZRrHa/4TWdflW0ug2k+fa/c7SPhDfGygta7F7gsOVQ9uh6IOQm1LByZ+drZ+L7Y5OSmDsjWFSG1fzFLcrh3KPP6EUAGCtAhEz4UkGm46dKZ3lKmB7TL0Ank+f2O47ErzGTYZ8tZeEnco= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=MESTEDx9; arc=none smtp.client-ip=209.85.222.179 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="MESTEDx9" Received: by mail-qk1-f179.google.com with SMTP id af79cd13be357-900fa9f178dso502324685a.1 for ; Mon, 11 May 2026 11:26:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1778523970; x=1779128770; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=jlZDG9AXqyTKh8LYQTP8pOzQ0gI9zF6LBr6ESWvufs4=; b=MESTEDx9ITox0/NVJbsjWUN23veTlCoh7nyRKqd8MKqK6/m6WR5KBSHi6elaAUIbeC E84Vd8IbwRjfs7JP9cfK7g29SZgc2w6q4S/5sNjlh3dwJnJIb+Yx5C1B9eZlVW+V55jT YZ25cJTWq9MPSzI+VZTU0mItCYVJGF+nH8yBztK8yHScUIaL5lP1Yg+yOepR9YN0RbaF 1KQ/9NdWSO4Zaycx6J3o3JtXfhEMlGY4ekl20PlNc9i4YW4nOqDOibyk67j6GvqVIpoF HwGA9q95R73+JnL8faPVlzfjlvMmghBJpQkRi/ipnCDqxAojXMo+5Wml/a0q9FBxuV3I zS0Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778523970; x=1779128770; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=jlZDG9AXqyTKh8LYQTP8pOzQ0gI9zF6LBr6ESWvufs4=; b=WF12KVKtEDGBSjyG/8XERGYhut4bnyWX2p7TbmnpyzBD1zYiPpOmc11VGoLlufHCoM x/1W2NYOY5S7vgvS50Cvtxkubq/+zUAeau3ILYaJO/H7osCNsMsjmdI8eH6nYTISFinR g7/ylGyJFYbiernec0m3HNqFjsVq/k93u4dpcPW5yJVWZi0IskwCvMBmRSMz5cWhAxP7 zy0haX6s1jOMsNoaMwNF7VmeA+y1lMXQjrOl3buTfmkg5oAWm7rWC+mMZm5Kzw1zdLNN hJmaLTTJqmUmb+50Em23nyvM45lsWm0rqSx3b0ZkDmwiQ5pd1iBqifVrpw9n40OqFGMQ Lcyg== X-Forwarded-Encrypted: i=1; AFNElJ/o83CNCgsiY3sr0hMlLDaNyP+Il2xGtTNRRRzIGBqIAKznBIu8RkvVCtQ9ZNwPbxFrwqpThbKX54KV3uQ=@vger.kernel.org X-Gm-Message-State: AOJu0YzjHNpdzAeWpyyrYCwIjZbnvcsM4OGojjFMGx7dfJaPQCqzoN+k 7u+5GXUHPkjMoSeycEYXd1gTVbb0wYkLZWDYBBcsGAkORkMwKuNxOsm1 X-Gm-Gg: Acq92OECEaqoFES8qwRTP2H17Hs53f9gUwxC+QzIflkFt4sHQ2MlWRsrv2TvD2p+JrY +dcfT+mFhhVg2Q8pznf1WD/jnOU9h+3UtS0fpY2SD/MX5JQir1mfueieC/NO5nFEoL8vyrw5+g6 ZUEusWNinosNmmdGJKiPywMeN85nc1gERp6QImsvvMsHReTcRRwi+0dMT7i6DR/1DT/WZ/MxAiE bEnMpqYRi987bco37tC6OfrZ12cFOQxTiELg6BV3bLyV7Yk+VXRzk9DK2Gdv8H5kdxyf1RWEcWc R64N6scoMyFRe418B0Dnju1y+e+mfOw1YDZhdQ5kK3dQQG2F74nMeROb+WngzdMEmWLvsLdRX3Y DOHqcc6g7zGCdHQzu+UIayAYGnh6f09kR3cnJZ6Q0F5+Aa1fXb8Kl2ezzqO+3g6FkM2AWyvYXwW 7E3eXpQ0pOoeu61hN0V9Z80j4bPjd5d1Hf0U9ruep8biPD/Tw6aYj6kkqc X-Received: by 2002:a05:620a:2949:b0:908:a0e2:289f with SMTP id af79cd13be357-9090ebc2bd7mr1568419085a.18.1778523970057; Mon, 11 May 2026 11:26:10 -0700 (PDT) Received: from PF5YBGDS.localdomain ([163.114.130.1]) by smtp.gmail.com with ESMTPSA id af79cd13be357-907b8d9ea06sm1111346885a.20.2026.05.11.11.26.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 11 May 2026 11:26:08 -0700 (PDT) From: mike.marciniszyn@gmail.com To: Alexander Duyck , Jakub Kicinski , kernel-team@meta.com, Andrew Lunn , "David S. Miller" , Eric Dumazet , Paolo Abeni , Heiner Kallweit , Russell King , Kees Cook , Andrew Lunn Cc: mike.marciniszyn@gmail.com, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH net-next v2 2/2] net: pcs: xpcs: Add handling for 4 channel rsfec device Date: Mon, 11 May 2026 14:26:04 -0400 Message-ID: <20260511182604.1338-3-mike.marciniszyn@gmail.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260511182604.1338-1-mike.marciniszyn@gmail.com> References: <20260511182604.1338-1-mike.marciniszyn@gmail.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" From: "Mike Marciniszyn (Meta)" 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 Signed-off-by: Mike Marciniszyn (Meta) --- v2: - Replace xpcs_write_pcs_prtad() wiht xpcs_write_pcs_mdev() to avoid hardcoded prtaddr value v1: https://lore.kernel.org/all/20260506190904.4029-3-mike.marciniszyn@gmai= l.com/ drivers/net/pcs/pcs-xpcs.c | 91 +++++++++++++++++++++++++++++++++++++- drivers/net/pcs/pcs-xpcs.h | 25 +++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c index 14f89e56958c..42d64f7ebf34 100644 --- a/drivers/net/pcs/pcs-xpcs.c +++ b/drivers/net/pcs/pcs-xpcs.c @@ -1423,9 +1423,39 @@ static int xpcs_get_pma_mmd(struct dw_xpcs *xpcs) return -ENODEV; } =20 +/* 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[] =3D { + {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[] =3D { + {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; }; =20 static struct mdio_device *xpcs_find_first_mdev(struct dw_xpcs *xpcs) @@ -1448,11 +1478,38 @@ xpcs_find_next_mdev(struct dw_xpcs *xpcs, struct md= io_device *mdev) return &n->mdio; } =20 +#define XPCS_VL_TO_REG(vl, lh) \ + (((vl) * 2) + DW_VR_MII_PCS_VL0_##lh) + +static int +xpcs_write_pcs_mdev(struct mdio_device *mdev, int reg, u16 val) +{ + return mdiodev_c45_write(mdev, MDIO_MMD_PCS, reg, val); +} + +static int +xpcs_config_vl_markers(struct dw_xpcs *xpcs, int vl, struct mdio_device *m= dev, + const struct lane_markers *m) +{ + int ret; + + /* m0, m1, m2 written to _L and _H registers + * + * _L =3D (m1 << 8) | m0 + * _H =3D m2 + */ + ret =3D xpcs_write_pcs_mdev(mdev, XPCS_VL_TO_REG(vl, L), + ((u16)m->m1 << 8) | m->m0); + if (ret < 0) + return ret; + return xpcs_write_pcs_mdev(mdev, 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 =3D 0, i, vl, pma_mmd; struct mdio_device *mdev; - int ret =3D 0, i, pma_mmd; =20 pma_mmd =3D xpcs_get_pma_mmd(xpcs); if (pma_mmd < 1) @@ -1464,6 +1521,23 @@ xpcs_config_rsfec_pma(struct dw_xpcs *xpcs, const st= ruct pma_pcs_values *v) =20 for (i =3D 0; mdev && ret >=3D 0 && i < v->lanes; i++, mdev =3D xpcs_find_next_mdev(xpcs, mdev)) { + /* code word markings */ + for (vl =3D 0; mdev && ret >=3D 0 && vl < 4; vl++) + ret =3D xpcs_config_vl_markers(xpcs, vl, mdev, + !vl ? &v->vl0_markers[0] : + &v->vl123_markers[vl - 1]); + if (ret < 0) + break; + /* vendor registers */ + ret =3D xpcs_write_pcs_mdev(mdev, DW_VR_MII_PCS_VL_INTVL, + v->vl_intvl); + if (ret < 0) + break; + ret =3D xpcs_write_pcs_mdev(mdev, DW_VR_MII_PCS_PCS_MODE, + v->pcs_mode); + if (ret < 0) + break; + /* rsfec register */ ret =3D mdiodev_c45_write(mdev, pma_mmd, MDIO_PMA_RSFEC_CTRL, v->rsfec_ctrl); } @@ -1478,6 +1552,13 @@ static int xpcs_25gbaser_pma_config(struct dw_xpcs *= xpcs) const struct pma_pcs_values v =3D { .rsfec_ctrl =3D 0, .lanes =3D 1, + /* 25g markers from 100g and 50g tables per 802.3-2022 + * 108.5.2.4 + */ + .vl0_markers =3D &xpcs_100gbaser_markers[0], + .vl123_markers =3D &xpcs_50gbaser_markers[1], + .vl_intvl =3D 20479, + .pcs_mode =3D DW_VR_MII_PCS_MODE_CLAUSE107, }; =20 return xpcs_config_rsfec_pma(xpcs, &v); @@ -1488,6 +1569,10 @@ static int xpcs_50gbaser_pma_config(struct dw_xpcs *= xpcs) const struct pma_pcs_values v =3D { .rsfec_ctrl =3D DW_VR_RSFEC_CTRL_TC_PAD_ALTER, .lanes =3D 2, + .vl0_markers =3D &xpcs_50gbaser_markers[0], + .vl123_markers =3D &xpcs_50gbaser_markers[1], + .pcs_mode =3D 0, + .vl_intvl =3D 20479, }; =20 return xpcs_config_rsfec_pma(xpcs, &v); @@ -1498,6 +1583,10 @@ static int xpcs_100gbasep_pma_config(struct dw_xpcs = *xpcs) const struct pma_pcs_values v =3D { .rsfec_ctrl =3D MDIO_PMA_RSFEC_CTRL_4LANE_PMD, .lanes =3D 2, + .vl0_markers =3D &xpcs_100gbaser_markers[0], + .vl123_markers =3D &xpcs_100gbaser_markers[1], + .pcs_mode =3D DW_VR_MII_PCS_MODE_DISABLE_MLD, + .vl_intvl =3D 16383, }; =20 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) =20 +/* 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 =3D { .pcs =3D _pcs, .pma =3D _pma= } =20 --=20 2.43.0