[<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