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-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210527204528.3490126-3-olteanv@gmail.com>
Date:   Thu, 27 May 2021 23:45:22 +0300
From:   Vladimir Oltean <olteanv@...il.com>
To:     Jakub Kicinski <kuba@...nel.org>,
        "David S. Miller" <davem@...emloft.net>, netdev@...r.kernel.org
Cc:     Giuseppe Cavallaro <peppe.cavallaro@...com>,
        Alexandre Torgue <alexandre.torgue@...s.st.com>,
        Jose Abreu <joabreu@...opsys.com>,
        Maxime Coquelin <mcoquelin.stm32@...il.com>,
        Heiner Kallweit <hkallweit1@...il.com>,
        Russell King - ARM Linux admin <linux@...linux.org.uk>,
        Florian Fainelli <f.fainelli@...il.com>,
        Andrew Lunn <andrew@...n.ch>,
        Ong Boon Leong <boon.leong.ong@...el.com>,
        Michael Sit Wei Hong <michael.wei.hong.sit@...el.com>,
        Vladimir Oltean <vladimir.oltean@....com>
Subject: [RFC PATCH net-next 2/8] net: pcs: xpcs: check for supported PHY interface modes in phylink_validate

From: Vladimir Oltean <vladimir.oltean@....com>

The supported PHY interface types are currently deduced by reading the
PHY ID registers of the PCS, to determine whether it is an USXGMII,
10G-KR, XLGMII, SGMII PCS or whatever.

Checking whether the PCS operates in a PHY interface mode compatible
with the hardware capability is done only once: in xpcs_check_features,
called from xpcs_probe - the deduced PHY interface mode is compared to
what is specified in the device tree.

But nothing prevents phylink from changing the state->interface as a
result of plugging an SFP module with a different operating PHY
interface type.

This change deletes xpcs_check_features, removes the phy_interface_t
argument from xpcs_probe, and moves the PHY interface type check inside
the validate function, similar to what other drivers do.

Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
 .../net/ethernet/stmicro/stmmac/stmmac_mdio.c |  5 +-
 drivers/net/pcs/pcs-xpcs.c                    | 63 ++++++++++---------
 include/linux/pcs/pcs-xpcs.h                  |  5 +-
 3 files changed, 41 insertions(+), 32 deletions(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
index e293bf1ce9f3..d12dfa60b8ea 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c
@@ -512,7 +512,8 @@ int stmmac_mdio_register(struct net_device *ndev)
 	/* Try to probe the XPCS by scanning all addresses. */
 	if (priv->hw->xpcs) {
 		struct mdio_xpcs_args *xpcs = &priv->hw->xpcs_args;
-		int ret, mode = priv->plat->phy_interface;
+		int ret;
+
 		max_addr = PHY_MAX_ADDR;
 
 		xpcs->bus = new_bus;
@@ -521,7 +522,7 @@ int stmmac_mdio_register(struct net_device *ndev)
 		for (addr = 0; addr < max_addr; addr++) {
 			xpcs->addr = addr;
 
-			ret = stmmac_xpcs_probe(priv, xpcs, mode);
+			ret = stmmac_xpcs_probe(priv, xpcs);
 			if (!ret) {
 				found = 1;
 				break;
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index aa985a5aae8d..71efd5ef69e5 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -662,6 +662,30 @@ static int xpcs_validate(struct mdio_xpcs_args *xpcs,
 			 unsigned long *supported,
 			 struct phylink_link_state *state)
 {
+	bool valid_interface;
+
+	if (state->interface == PHY_INTERFACE_MODE_NA) {
+		valid_interface = true;
+	} else {
+		struct xpcs_id *id = xpcs->id;
+		int i;
+
+		valid_interface = false;
+
+		for (i = 0; id->interface[i] != PHY_INTERFACE_MODE_MAX; i++) {
+			if (id->interface[i] != state->interface)
+				continue;
+
+			valid_interface = true;
+			break;
+		}
+	}
+
+	if (!valid_interface) {
+		bitmap_zero(supported, __ETHTOOL_LINK_MODE_MASK_NBITS);
+		return 0;
+	}
+
 	linkmode_and(supported, supported, xpcs->supported);
 	linkmode_and(state->advertising, state->advertising, xpcs->supported);
 	return 0;
@@ -910,43 +934,24 @@ static u32 xpcs_get_id(struct mdio_xpcs_args *xpcs)
 	return 0xffffffff;
 }
 
-static bool xpcs_check_features(struct mdio_xpcs_args *xpcs,
-				struct xpcs_id *match,
-				phy_interface_t interface)
-{
-	int i;
-
-	for (i = 0; match->interface[i] != PHY_INTERFACE_MODE_MAX; i++) {
-		if (match->interface[i] == interface)
-			break;
-	}
-
-	if (match->interface[i] == PHY_INTERFACE_MODE_MAX)
-		return false;
-
-	for (i = 0; match->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
-		set_bit(match->supported[i], xpcs->supported);
-
-	xpcs->an_mode = match->an_mode;
-
-	return true;
-}
-
-static int xpcs_probe(struct mdio_xpcs_args *xpcs, phy_interface_t interface)
+static int xpcs_probe(struct mdio_xpcs_args *xpcs)
 {
 	u32 xpcs_id = xpcs_get_id(xpcs);
-	struct xpcs_id *match = NULL;
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(xpcs_id_list); i++) {
 		struct xpcs_id *entry = &xpcs_id_list[i];
 
-		if ((xpcs_id & entry->mask) == entry->id) {
-			match = entry;
+		if ((xpcs_id & entry->mask) != entry->id)
+			continue;
 
-			if (xpcs_check_features(xpcs, match, interface))
-				return xpcs_soft_reset(xpcs);
-		}
+		for (i = 0; entry->supported[i] != __ETHTOOL_LINK_MODE_MASK_NBITS; i++)
+			set_bit(entry->supported[i], xpcs->supported);
+
+		xpcs->id = entry;
+		xpcs->an_mode = entry->an_mode;
+
+		return xpcs_soft_reset(xpcs);
 	}
 
 	return -ENODEV;
diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h
index c4d0a2c469c7..e48636a1a078 100644
--- a/include/linux/pcs/pcs-xpcs.h
+++ b/include/linux/pcs/pcs-xpcs.h
@@ -14,9 +14,12 @@
 #define DW_AN_C73			1
 #define DW_AN_C37_SGMII			2
 
+struct xpcs_id;
+
 struct mdio_xpcs_args {
 	__ETHTOOL_DECLARE_LINK_MODE_MASK(supported);
 	struct mii_bus *bus;
+	struct xpcs_id *id;
 	int addr;
 	int an_mode;
 };
@@ -31,7 +34,7 @@ struct mdio_xpcs_ops {
 			 struct phylink_link_state *state);
 	int (*link_up)(struct mdio_xpcs_args *xpcs, int speed,
 		       phy_interface_t interface);
-	int (*probe)(struct mdio_xpcs_args *xpcs, phy_interface_t interface);
+	int (*probe)(struct mdio_xpcs_args *xpcs);
 	int (*config_eee)(struct mdio_xpcs_args *xpcs, int mult_fact_100ns,
 			  int enable);
 };
-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ