lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20221114210740.3332937-1-sean.anderson@seco.com>
Date:   Mon, 14 Nov 2022 16:07:39 -0500
From:   Sean Anderson <sean.anderson@...o.com>
To:     Andrew Lunn <andrew@...n.ch>,
        Heiner Kallweit <hkallweit1@...il.com>,
        Russell King <linux@...linux.org.uk>, netdev@...r.kernel.org
Cc:     Eric Dumazet <edumazet@...gle.com>,
        Vladimir Oltean <olteanv@...il.com>,
        Tim Harvey <tharvey@...eworks.com>,
        "David S . Miller" <davem@...emloft.net>,
        linux-kernel@...r.kernel.org, Paolo Abeni <pabeni@...hat.com>,
        Jakub Kicinski <kuba@...nel.org>,
        Sean Anderson <sean.anderson@...o.com>
Subject: [PATCH] phy: aquantia: Configure SERDES mode by default

When autonegotiation completes, the phy interface will be set based on
the global config register for that speed. If the SERDES mode is set to
something which the MAC does not support, then the link will not come
up. The register reference says that the SERDES mode should default to
XFI, but for some phys lower speeds default to XFI/2 (5G XFI). To ensure
the link comes up correctly, configure the SERDES mode.

We use the same configuration for all interfaces. We don't advertise
any speeds faster than the interface mode, so they won't be selected.
We default to pause-based rate adaptation, but enable USXGMII rate
adaptation for USXGMII. I'm not sure if this is correct for
SGMII; it might need USXGMII adaptation instead.

This effectively disables switching interface mode depending on the
speed, in favor of using rate adaptation. If this is not desired, we
would need some kind of API to configure things.

Signed-off-by: Sean Anderson <sean.anderson@...o.com>
---

 drivers/net/phy/aquantia_main.c | 65 +++++++++++++++++++++++++++++++++
 1 file changed, 65 insertions(+)

diff --git a/drivers/net/phy/aquantia_main.c b/drivers/net/phy/aquantia_main.c
index 47a76df36b74..88a3defb632c 100644
--- a/drivers/net/phy/aquantia_main.c
+++ b/drivers/net/phy/aquantia_main.c
@@ -109,6 +109,10 @@
 #define VEND1_GLOBAL_CFG_RATE_ADAPT_NONE	0
 #define VEND1_GLOBAL_CFG_RATE_ADAPT_USX		1
 #define VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE	2
+#define VEND1_GLOBAL_CFG_SERDES_MODE		GENMASK(2, 0)
+#define VEND1_GLOBAL_CFG_SERDES_MODE_XFI	0
+#define VEND1_GLOBAL_CFG_SERDES_MODE_SGMII	3
+#define VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII	4
 
 #define VEND1_GLOBAL_RSVD_STAT1			0xc885
 #define VEND1_GLOBAL_RSVD_STAT1_FW_BUILD_ID	GENMASK(7, 4)
@@ -558,6 +562,63 @@ static void aqr107_chip_info(struct phy_device *phydev)
 		   fw_major, fw_minor, build_id, prov_id);
 }
 
+static int aqr107_global_config_init(struct phy_device *phydev)
+{
+	u16 mask = VEND1_GLOBAL_CFG_RATE_ADAPT | VEND1_GLOBAL_CFG_SERDES_MODE;
+	u16 val, serdes_mode, rate_adapt = VEND1_GLOBAL_CFG_RATE_ADAPT_PAUSE;
+	u16 config_regs[] = {
+		VEND1_GLOBAL_CFG_10M,
+		VEND1_GLOBAL_CFG_100M,
+		VEND1_GLOBAL_CFG_1G,
+		VEND1_GLOBAL_CFG_2_5G,
+		VEND1_GLOBAL_CFG_5G,
+		VEND1_GLOBAL_CFG_10G,
+	};
+	int i, ret;
+
+	switch (phydev->interface) {
+	case PHY_INTERFACE_MODE_SGMII:
+	case PHY_INTERFACE_MODE_1000BASEKX:
+		rate_adapt = VEND1_GLOBAL_CFG_RATE_ADAPT_USX;
+		serdes_mode = VEND1_GLOBAL_CFG_SERDES_MODE_SGMII;
+		break;
+
+	case PHY_INTERFACE_MODE_2500BASEX:
+		serdes_mode = VEND1_GLOBAL_CFG_SERDES_MODE_OCSGMII;
+		break;
+
+	case PHY_INTERFACE_MODE_USXGMII:
+		rate_adapt = VEND1_GLOBAL_CFG_RATE_ADAPT_USX;
+		fallthrough;
+	case PHY_INTERFACE_MODE_XGMII:
+	case PHY_INTERFACE_MODE_10GKR:
+	case PHY_INTERFACE_MODE_10GBASER:
+	case PHY_INTERFACE_MODE_XAUI:
+	case PHY_INTERFACE_MODE_RXAUI:
+		serdes_mode = VEND1_GLOBAL_CFG_SERDES_MODE_XFI;
+		break;
+
+	default:
+		WARN_ON_ONCE(1);
+		return -EINVAL;
+	}
+
+	val = FIELD_PREP(VEND1_GLOBAL_CFG_RATE_ADAPT, rate_adapt);
+	val |= FIELD_PREP(VEND1_GLOBAL_CFG_SERDES_MODE, serdes_mode);
+
+	for (i = 0; i < ARRAY_SIZE(config_regs); i++) {
+		ret = phy_modify_mmd(phydev, MDIO_MMD_VEND1, config_regs[i],
+				     mask, val);
+		if (ret) {
+			phydev_err(phydev, "could not initialize register %x\n",
+				   config_regs[i]);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int aqr107_config_init(struct phy_device *phydev)
 {
 	int ret;
@@ -581,6 +642,10 @@ static int aqr107_config_init(struct phy_device *phydev)
 	if (!ret)
 		aqr107_chip_info(phydev);
 
+	ret = aqr107_global_config_init(phydev);
+	if (ret)
+		return ret;
+
 	return aqr107_set_downshift(phydev, MDIO_AN_VEND_PROV_DOWNSHIFT_DFLT);
 }
 
-- 
2.35.1.1320.gc452695387.dirty

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ