diff mbox series

[RFC,net-next,2/8] net: pcs: xpcs: check for supported PHY interface modes in phylink_validate

Message ID 20210527204528.3490126-3-olteanv@gmail.com (mailing list archive)
State Superseded
Delegated to: Netdev Maintainers
Headers show
Series Convert xpcs to phylink_pcs_ops | expand

Checks

Context Check Description
netdev/apply fail Patch does not apply to net-next
netdev/tree_selection success Clearly marked for net-next

Commit Message

Vladimir Oltean May 27, 2021, 8:45 p.m. UTC
From: Vladimir Oltean <vladimir.oltean@nxp.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@nxp.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 mbox series

Patch

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);
 };