* [PATCH RFC net-next 1/9] net: mdio: add clause 73 to ethtool conversion helper
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
@ 2023-05-17 14:11 ` Russell King (Oracle)
2023-05-17 14:11 ` [PATCH RFC net-next 2/9] net: phylink: remove duplicated linkmode pause resolution Russell King (Oracle)
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:11 UTC (permalink / raw)
To: Jose Abreu; +Cc: Andrew Lunn, Heiner Kallweit, netdev
Add a helper to convert a clause 73 advertisement to an ethtool bitmap.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
include/linux/mdio.h | 39 +++++++++++++++++++++++++++++++++++++++
include/uapi/linux/mdio.h | 24 ++++++++++++++++++++++++
2 files changed, 63 insertions(+)
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 27013d6bf24a..0670cc6e067c 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -486,6 +486,45 @@ static inline u32 linkmode_adv_to_mii_10base_t1_t(unsigned long *adv)
return result;
}
+/**
+ * mii_c73_mod_linkmode - convert a Clause 73 advertisement to linkmodes
+ * @adv: linkmode advertisement setting
+ * @lpa: array of three u16s containing the advertisement
+ *
+ * Convert an IEEE 802.3 Clause 73 advertisement to ethtool link modes.
+ */
+static inline void mii_c73_mod_linkmode(unsigned long *adv, u16 *lpa)
+{
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT,
+ adv, lpa[0] & MDIO_AN_C73_0_PAUSE);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
+ adv, lpa[0] & MDIO_AN_C73_0_ASM_DIR);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_1000BASE_KX);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_10GBASE_KX4);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_40GBASE_KR4);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_40GBASE_CR4);
+ /* 100GBASE_CR10 and 100GBASE_KP4 not implemented */
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_100GBASE_KR4);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_100GBASE_CR4);
+ /* 25GBASE_R_S not implemented */
+ /* The 25GBASE_R bit can be used for 25Gbase KR or CR modes */
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_25GBASE_R);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_25GBASE_R);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ adv, lpa[1] & MDIO_AN_C73_1_10GBASE_KR);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT,
+ adv, lpa[2] & MDIO_AN_C73_2_2500BASE_KX);
+ /* 5GBASE_KR not implemented */
+}
+
int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
index 256b463e47a6..b826598d1e94 100644
--- a/include/uapi/linux/mdio.h
+++ b/include/uapi/linux/mdio.h
@@ -231,6 +231,30 @@
#define MDIO_PMA_EXTABLE_BT1 0x0800 /* BASE-T1 ability */
#define MDIO_PMA_EXTABLE_NBT 0x4000 /* 2.5/5GBASE-T ability */
+/* AN Clause 73 linkword */
+#define MDIO_AN_C73_0_S_MASK GENMASK(4, 0)
+#define MDIO_AN_C73_0_E_MASK GENMASK(9, 5)
+#define MDIO_AN_C73_0_PAUSE BIT(10)
+#define MDIO_AN_C73_0_ASM_DIR BIT(11)
+#define MDIO_AN_C73_0_C2 BIT(12)
+#define MDIO_AN_C73_0_RF BIT(13)
+#define MDIO_AN_C73_0_ACK BIT(14)
+#define MDIO_AN_C73_0_NP BIT(15)
+#define MDIO_AN_C73_1_T_MASK GENMASK(4, 0)
+#define MDIO_AN_C73_1_1000BASE_KX BIT(5)
+#define MDIO_AN_C73_1_10GBASE_KX4 BIT(6)
+#define MDIO_AN_C73_1_10GBASE_KR BIT(7)
+#define MDIO_AN_C73_1_40GBASE_KR4 BIT(8)
+#define MDIO_AN_C73_1_40GBASE_CR4 BIT(9)
+#define MDIO_AN_C73_1_100GBASE_CR10 BIT(10)
+#define MDIO_AN_C73_1_100GBASE_KP4 BIT(11)
+#define MDIO_AN_C73_1_100GBASE_KR4 BIT(12)
+#define MDIO_AN_C73_1_100GBASE_CR4 BIT(13)
+#define MDIO_AN_C73_1_25GBASE_R_S BIT(14)
+#define MDIO_AN_C73_1_25GBASE_R BIT(15)
+#define MDIO_AN_C73_2_2500BASE_KX BIT(0)
+#define MDIO_AN_C73_2_5GBASE_KR BIT(1)
+
/* PHY XGXS lane state register. */
#define MDIO_PHYXS_LNSTAT_SYNC0 0x0001
#define MDIO_PHYXS_LNSTAT_SYNC1 0x0002
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 2/9] net: phylink: remove duplicated linkmode pause resolution
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
2023-05-17 14:11 ` [PATCH RFC net-next 1/9] net: mdio: add clause 73 to ethtool conversion helper Russell King (Oracle)
@ 2023-05-17 14:11 ` Russell King (Oracle)
2023-05-17 14:11 ` [PATCH RFC net-next 3/9] net: phylink: add function to resolve clause 73 negotiation Russell King (Oracle)
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:11 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
Phylink had two chunks of code virtually the same for resolving the
negotiated pause modes. Factor this down to one function.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phylink.c | 15 ++++-----------
1 file changed, 4 insertions(+), 11 deletions(-)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 7db67ff2812c..9cc152f3506a 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -980,11 +980,10 @@ static void phylink_apply_manual_flow(struct phylink *pl,
state->pause = pl->link_config.pause;
}
-static void phylink_resolve_flow(struct phylink_link_state *state)
+static void phylink_resolve_an_pause(struct phylink_link_state *state)
{
bool tx_pause, rx_pause;
- state->pause = MLO_PAUSE_NONE;
if (state->duplex == DUPLEX_FULL) {
linkmode_resolve_pause(state->advertising,
state->lp_advertising,
@@ -1196,7 +1195,8 @@ static void phylink_get_fixed_state(struct phylink *pl,
else if (pl->link_gpio)
state->link = !!gpiod_get_value_cansleep(pl->link_gpio);
- phylink_resolve_flow(state);
+ state->pause = MLO_PAUSE_NONE;
+ phylink_resolve_an_pause(state);
}
static void phylink_mac_initial_config(struct phylink *pl, bool force_restart)
@@ -3219,7 +3219,6 @@ static const struct sfp_upstream_ops sfp_phylink_ops = {
static void phylink_decode_c37_word(struct phylink_link_state *state,
uint16_t config_reg, int speed)
{
- bool tx_pause, rx_pause;
int fd_bit;
if (speed == SPEED_2500)
@@ -3238,13 +3237,7 @@ static void phylink_decode_c37_word(struct phylink_link_state *state,
state->link = false;
}
- linkmode_resolve_pause(state->advertising, state->lp_advertising,
- &tx_pause, &rx_pause);
-
- if (tx_pause)
- state->pause |= MLO_PAUSE_TX;
- if (rx_pause)
- state->pause |= MLO_PAUSE_RX;
+ phylink_resolve_an_pause(state);
}
static void phylink_decode_sgmii_word(struct phylink_link_state *state,
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 3/9] net: phylink: add function to resolve clause 73 negotiation
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
2023-05-17 14:11 ` [PATCH RFC net-next 1/9] net: mdio: add clause 73 to ethtool conversion helper Russell King (Oracle)
2023-05-17 14:11 ` [PATCH RFC net-next 2/9] net: phylink: remove duplicated linkmode pause resolution Russell King (Oracle)
@ 2023-05-17 14:11 ` Russell King (Oracle)
2023-05-17 14:12 ` [PATCH RFC net-next 4/9] net: pcs: xpcs: clean up reading clause 73 link partner advertisement Russell King (Oracle)
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:11 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
Add a function to resolve clause 73 negotiation according to the
priority resolution function described in clause 73.3.6.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/phy/phylink.c | 39 +++++++++++++++++++++++++++++++++++++++
include/linux/phylink.h | 2 ++
2 files changed, 41 insertions(+)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 9cc152f3506a..bd2d373460dd 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -3216,6 +3216,45 @@ static const struct sfp_upstream_ops sfp_phylink_ops = {
/* Helpers for MAC drivers */
+static struct {
+ int bit;
+ int speed;
+} phylink_c73_priority_resolution[] = {
+ { ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, SPEED_100000 },
+ { ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, SPEED_100000 },
+ /* 100GBASE-KP4 and 100GBASE-CR10 not supported */
+ { ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, SPEED_40000 },
+ { ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, SPEED_40000 },
+ { ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, SPEED_10000 },
+ { ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, SPEED_10000 },
+ /* 5GBASE-KR not supported */
+ { ETHTOOL_LINK_MODE_2500baseX_Full_BIT, SPEED_2500 },
+ { ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, SPEED_1000 },
+};
+
+void phylink_resolve_c73(struct phylink_link_state *state)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(phylink_c73_priority_resolution); i++) {
+ int bit = phylink_c73_priority_resolution[i].bit;
+ if (linkmode_test_bit(bit, state->advertising) &&
+ linkmode_test_bit(bit, state->lp_advertising))
+ break;
+ }
+
+ if (i < ARRAY_SIZE(phylink_c73_priority_resolution)) {
+ state->speed = phylink_c73_priority_resolution[i].speed;
+ state->duplex = DUPLEX_FULL;
+ } else {
+ /* negotiation failure */
+ state->link = false;
+ }
+
+ phylink_resolve_an_pause(state);
+}
+EXPORT_SYMBOL_GPL(phylink_resolve_c73);
+
static void phylink_decode_c37_word(struct phylink_link_state *state,
uint16_t config_reg, int speed)
{
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index bb782f05ad08..0cf07d7d11b8 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -656,6 +656,8 @@ int phylink_mii_c22_pcs_config(struct mdio_device *pcs, unsigned int mode,
const unsigned long *advertising);
void phylink_mii_c22_pcs_an_restart(struct mdio_device *pcs);
+void phylink_resolve_c73(struct phylink_link_state *state);
+
void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs,
struct phylink_link_state *state);
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 4/9] net: pcs: xpcs: clean up reading clause 73 link partner advertisement
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
` (2 preceding siblings ...)
2023-05-17 14:11 ` [PATCH RFC net-next 3/9] net: phylink: add function to resolve clause 73 negotiation Russell King (Oracle)
@ 2023-05-17 14:12 ` Russell King (Oracle)
2023-05-17 14:12 ` [PATCH RFC net-next 5/9] net: pcs: xpcs: use mii_c73_to_linkmode() helper Russell King (Oracle)
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:12 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
Read the clause 73 link partner advertisement in a loop and then
translate to the ethtool modes.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/pcs/pcs-xpcs.c | 39 +++++++++++++++++---------------------
drivers/net/pcs/pcs-xpcs.h | 3 ---
2 files changed, 17 insertions(+), 25 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index f19d48c94fe0..b8d69a78f484 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -487,7 +487,7 @@ static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
return ret;
if (ret & MDIO_AN_STAT1_COMPLETE) {
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
+ ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA);
if (ret < 0)
return ret;
@@ -506,7 +506,8 @@ static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
- int ret;
+ u16 lpa[3];
+ int i, ret;
ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
if (ret < 0)
@@ -519,32 +520,26 @@ static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
phylink_set(state->lp_advertising, Autoneg);
- /* Clause 73 outcome */
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL3);
- if (ret < 0)
- return ret;
-
- if (ret & DW_C73_2500KX)
- phylink_set(state->lp_advertising, 2500baseX_Full);
+ /* Read Clause 73 link partner advertisement */
+ for (i = ARRAY_SIZE(lpa); --i >= 0; ) {
+ ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA + i);
+ if (ret < 0)
+ return ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL2);
- if (ret < 0)
- return ret;
+ lpa[i] = ret;
+ }
- if (ret & DW_C73_1000KX)
+ if (lpa[2] & DW_C73_2500KX)
+ phylink_set(state->lp_advertising, 2500baseX_Full);
+ if (lpa[1] & DW_C73_1000KX)
phylink_set(state->lp_advertising, 1000baseKX_Full);
- if (ret & DW_C73_10000KX4)
+ if (lpa[1] & DW_C73_10000KX4)
phylink_set(state->lp_advertising, 10000baseKX4_Full);
- if (ret & DW_C73_10000KR)
+ if (lpa[1] & DW_C73_10000KR)
phylink_set(state->lp_advertising, 10000baseKR_Full);
-
- ret = xpcs_read(xpcs, MDIO_MMD_AN, DW_SR_AN_LP_ABL1);
- if (ret < 0)
- return ret;
-
- if (ret & DW_C73_PAUSE)
+ if (lpa[0] & DW_C73_PAUSE)
phylink_set(state->lp_advertising, Pause);
- if (ret & DW_C73_ASYM_PAUSE)
+ if (lpa[0] & DW_C73_ASYM_PAUSE)
phylink_set(state->lp_advertising, Asym_Pause);
linkmode_and(state->lp_advertising, state->lp_advertising,
diff --git a/drivers/net/pcs/pcs-xpcs.h b/drivers/net/pcs/pcs-xpcs.h
index 770df50323a0..68c6b5a62088 100644
--- a/drivers/net/pcs/pcs-xpcs.h
+++ b/drivers/net/pcs/pcs-xpcs.h
@@ -32,9 +32,6 @@
#define DW_SR_AN_ADV1 0x10
#define DW_SR_AN_ADV2 0x11
#define DW_SR_AN_ADV3 0x12
-#define DW_SR_AN_LP_ABL1 0x13
-#define DW_SR_AN_LP_ABL2 0x14
-#define DW_SR_AN_LP_ABL3 0x15
/* Clause 73 Defines */
/* AN_LP_ABL1 */
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 5/9] net: pcs: xpcs: use mii_c73_to_linkmode() helper
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
` (3 preceding siblings ...)
2023-05-17 14:12 ` [PATCH RFC net-next 4/9] net: pcs: xpcs: clean up reading clause 73 link partner advertisement Russell King (Oracle)
@ 2023-05-17 14:12 ` Russell King (Oracle)
2023-05-17 14:12 ` [PATCH RFC net-next 6/9] net: pcs: xpcs: correct lp_advertising contents Russell King (Oracle)
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:12 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
Convert xpcs clause 73 reading to use the newly introduced
mii_c73_to_linkmode() helper to translate the link partner
advertisement to an ethtool bitmap.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/pcs/pcs-xpcs.c | 13 +------------
1 file changed, 1 insertion(+), 12 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index b8d69a78f484..16fcc7891f92 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -529,18 +529,7 @@ static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
lpa[i] = ret;
}
- if (lpa[2] & DW_C73_2500KX)
- phylink_set(state->lp_advertising, 2500baseX_Full);
- if (lpa[1] & DW_C73_1000KX)
- phylink_set(state->lp_advertising, 1000baseKX_Full);
- if (lpa[1] & DW_C73_10000KX4)
- phylink_set(state->lp_advertising, 10000baseKX4_Full);
- if (lpa[1] & DW_C73_10000KR)
- phylink_set(state->lp_advertising, 10000baseKR_Full);
- if (lpa[0] & DW_C73_PAUSE)
- phylink_set(state->lp_advertising, Pause);
- if (lpa[0] & DW_C73_ASYM_PAUSE)
- phylink_set(state->lp_advertising, Asym_Pause);
+ mii_c73_mod_linkmode(state->lp_advertising, lpa);
linkmode_and(state->lp_advertising, state->lp_advertising,
state->advertising);
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 6/9] net: pcs: xpcs: correct lp_advertising contents
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
` (4 preceding siblings ...)
2023-05-17 14:12 ` [PATCH RFC net-next 5/9] net: pcs: xpcs: use mii_c73_to_linkmode() helper Russell King (Oracle)
@ 2023-05-17 14:12 ` Russell King (Oracle)
2023-05-17 14:12 ` [PATCH RFC net-next 7/9] net: pcs: xpcs: correct pause resolution Russell King (Oracle)
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:12 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
lp_advertising is supposed to reflect the link partner's advertisement
unmodified by the local advertisement, but xpcs bitwise ands it with
the local advertisement prior to calculating the resolution of the
negotiation.
Fix this by moving the bitwise and to xpcs_resolve_lpa_c73() so it can
place the results in a temporary bitmap before passing that to
ixpcs_get_max_usxgmii_speed().
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/pcs/pcs-xpcs.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 16fcc7891f92..43115d04c01a 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -531,18 +531,19 @@ static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
mii_c73_mod_linkmode(state->lp_advertising, lpa);
- linkmode_and(state->lp_advertising, state->lp_advertising,
- state->advertising);
return 0;
}
static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
- int max_speed = xpcs_get_max_usxgmii_speed(state->lp_advertising);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(res);
+
+ /* Calculate the union of the advertising masks */
+ linkmode_and(res, state->lp_advertising, state->advertising);
state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
- state->speed = max_speed;
+ state->speed = xpcs_get_max_usxgmii_speed(res);
state->duplex = DUPLEX_FULL;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 7/9] net: pcs: xpcs: correct pause resolution
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
` (5 preceding siblings ...)
2023-05-17 14:12 ` [PATCH RFC net-next 6/9] net: pcs: xpcs: correct lp_advertising contents Russell King (Oracle)
@ 2023-05-17 14:12 ` Russell King (Oracle)
2023-05-17 14:12 ` [PATCH RFC net-next 8/9] net: pcs: xpcs: use phylink_resolve_c73() helper Russell King (Oracle)
2023-05-17 14:12 ` [PATCH RFC net-next 9/9] net: pcs: xpcs: avoid reading STAT1 more than once Russell King (Oracle)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:12 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
xpcs was indicating symmetric pause should be enabled regardless of
the advertisements by either party. Fix this to use
linkmode_resolve_pause() now that we're no longer obliterating the
link partner's advertisement by logically anding it with our own.
This is transitional, the function will be entirely replaced with
phylink_resolve_c73() in the following patch.
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/pcs/pcs-xpcs.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 43115d04c01a..beed799a69a7 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -538,11 +538,20 @@ static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(res);
+ bool tx_pause, rx_pause;
/* Calculate the union of the advertising masks */
linkmode_and(res, state->lp_advertising, state->advertising);
- state->pause = MLO_PAUSE_TX | MLO_PAUSE_RX;
+ /* Resolve pause modes */
+ linkmode_resolve_pause(state->advertising, state->lp_advertising,
+ &tx_pause, &rx_pause);
+
+ if (tx_pause)
+ state->pause |= MLO_PAUSE_TX;
+ if (rx_pause)
+ state->pause |= MLO_PAUSE_RX;
+
state->speed = xpcs_get_max_usxgmii_speed(res);
state->duplex = DUPLEX_FULL;
}
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 8/9] net: pcs: xpcs: use phylink_resolve_c73() helper
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
` (6 preceding siblings ...)
2023-05-17 14:12 ` [PATCH RFC net-next 7/9] net: pcs: xpcs: correct pause resolution Russell King (Oracle)
@ 2023-05-17 14:12 ` Russell King (Oracle)
2023-05-17 14:12 ` [PATCH RFC net-next 9/9] net: pcs: xpcs: avoid reading STAT1 more than once Russell King (Oracle)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:12 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
Use phylink_resolve_c73() to resolve the clause 73 autonegotiation
result.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/pcs/pcs-xpcs.c | 40 +-------------------------------------
1 file changed, 1 insertion(+), 39 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index beed799a69a7..c5fe944f48dd 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -336,22 +336,6 @@ static int xpcs_read_link_c73(struct dw_xpcs *xpcs)
return link;
}
-static int xpcs_get_max_usxgmii_speed(const unsigned long *supported)
-{
- int max = SPEED_UNKNOWN;
-
- if (phylink_test(supported, 1000baseKX_Full))
- max = SPEED_1000;
- if (phylink_test(supported, 2500baseX_Full))
- max = SPEED_2500;
- if (phylink_test(supported, 10000baseKX4_Full))
- max = SPEED_10000;
- if (phylink_test(supported, 10000baseKR_Full))
- max = SPEED_10000;
-
- return max;
-}
-
static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
{
int ret, speed_sel;
@@ -534,28 +518,6 @@ static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
return 0;
}
-static void xpcs_resolve_lpa_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
-{
- __ETHTOOL_DECLARE_LINK_MODE_MASK(res);
- bool tx_pause, rx_pause;
-
- /* Calculate the union of the advertising masks */
- linkmode_and(res, state->lp_advertising, state->advertising);
-
- /* Resolve pause modes */
- linkmode_resolve_pause(state->advertising, state->lp_advertising,
- &tx_pause, &rx_pause);
-
- if (tx_pause)
- state->pause |= MLO_PAUSE_TX;
- if (rx_pause)
- state->pause |= MLO_PAUSE_RX;
-
- state->speed = xpcs_get_max_usxgmii_speed(res);
- state->duplex = DUPLEX_FULL;
-}
-
static int xpcs_get_max_xlgmii_speed(struct dw_xpcs *xpcs,
struct phylink_link_state *state)
{
@@ -940,7 +902,7 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) {
state->an_complete = true;
xpcs_read_lpa_c73(xpcs, state);
- xpcs_resolve_lpa_c73(xpcs, state);
+ phylink_resolve_c73(state);
} else if (an_enabled) {
state->link = 0;
} else if (state->link) {
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread* [PATCH RFC net-next 9/9] net: pcs: xpcs: avoid reading STAT1 more than once
2023-05-17 14:11 [PATCH RFC v2 net-next 0/9] net: pcs: xpcs: cleanups for clause 73 support Russell King (Oracle)
` (7 preceding siblings ...)
2023-05-17 14:12 ` [PATCH RFC net-next 8/9] net: pcs: xpcs: use phylink_resolve_c73() helper Russell King (Oracle)
@ 2023-05-17 14:12 ` Russell King (Oracle)
8 siblings, 0 replies; 10+ messages in thread
From: Russell King (Oracle) @ 2023-05-17 14:12 UTC (permalink / raw)
To: Jose Abreu
Cc: Andrew Lunn, Heiner Kallweit, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, netdev
Avoid reading the STAT1 registers more than once while getting the PCS
state, as this register contains latching-low bits that are lost after
the first read.
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
---
drivers/net/pcs/pcs-xpcs.c | 91 +++++++++++++++++++++-----------------
1 file changed, 50 insertions(+), 41 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index c5fe944f48dd..00cbd522f59a 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -271,15 +271,12 @@ static int xpcs_soft_reset(struct dw_xpcs *xpcs,
})
static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
+ struct phylink_link_state *state,
+ u16 pcs_stat1)
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (ret & MDIO_STAT1_FAULT) {
+ if (pcs_stat1 & MDIO_STAT1_FAULT) {
xpcs_warn(xpcs, state, "Link fault condition detected!\n");
return -EFAULT;
}
@@ -321,21 +318,6 @@ static int xpcs_read_fault_c73(struct dw_xpcs *xpcs,
return 0;
}
-static int xpcs_read_link_c73(struct dw_xpcs *xpcs)
-{
- bool link = true;
- int ret;
-
- ret = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (!(ret & MDIO_STAT1_LSTATUS))
- link = false;
-
- return link;
-}
-
static void xpcs_config_usxgmii(struct dw_xpcs *xpcs, int speed)
{
int ret, speed_sel;
@@ -462,15 +444,11 @@ static int xpcs_config_aneg_c73(struct dw_xpcs *xpcs,
static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
struct phylink_link_state *state,
- const struct xpcs_compat *compat)
+ const struct xpcs_compat *compat, u16 an_stat1)
{
int ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (ret & MDIO_AN_STAT1_COMPLETE) {
+ if (an_stat1 & MDIO_AN_STAT1_COMPLETE) {
ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_AN_LPA);
if (ret < 0)
return ret;
@@ -488,16 +466,12 @@ static int xpcs_aneg_done_c73(struct dw_xpcs *xpcs,
}
static int xpcs_read_lpa_c73(struct dw_xpcs *xpcs,
- struct phylink_link_state *state)
+ struct phylink_link_state *state, u16 an_stat1)
{
u16 lpa[3];
int i, ret;
- ret = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
- if (ret < 0)
- return ret;
-
- if (!(ret & MDIO_AN_STAT1_LPABLE)) {
+ if (!(an_stat1 & MDIO_AN_STAT1_LPABLE)) {
phylink_clear(state->lp_advertising, Autoneg);
return 0;
}
@@ -880,13 +854,25 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
const struct xpcs_compat *compat)
{
bool an_enabled;
+ int pcs_stat1;
+ int an_stat1;
int ret;
+ /* The link status bit is latching-low, so it is important to
+ * avoid unnecessary re-reads of this register to avoid missing
+ * a link-down event.
+ */
+ pcs_stat1 = xpcs_read(xpcs, MDIO_MMD_PCS, MDIO_STAT1);
+ if (pcs_stat1 < 0) {
+ state->link = false;
+ return pcs_stat1;
+ }
+
/* Link needs to be read first ... */
- state->link = xpcs_read_link_c73(xpcs) > 0 ? 1 : 0;
+ state->link = !!(pcs_stat1 & MDIO_STAT1_LSTATUS);
/* ... and then we check the faults. */
- ret = xpcs_read_fault_c73(xpcs, state);
+ ret = xpcs_read_fault_c73(xpcs, state, pcs_stat1);
if (ret) {
ret = xpcs_soft_reset(xpcs, compat);
if (ret)
@@ -897,15 +883,38 @@ static int xpcs_get_state_c73(struct dw_xpcs *xpcs,
return xpcs_do_config(xpcs, state->interface, MLO_AN_INBAND, NULL);
}
+ /* There is no point doing anything else if the link is down. */
+ if (!state->link)
+ return 0;
+
an_enabled = linkmode_test_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
state->advertising);
- if (an_enabled && xpcs_aneg_done_c73(xpcs, state, compat)) {
- state->an_complete = true;
- xpcs_read_lpa_c73(xpcs, state);
+ if (an_enabled) {
+ /* The link status bit is latching-low, so it is important to
+ * avoid unnecessary re-reads of this register to avoid missing
+ * a link-down event.
+ */
+ an_stat1 = xpcs_read(xpcs, MDIO_MMD_AN, MDIO_STAT1);
+ if (an_stat1 < 0) {
+ state->link = false;
+ return an_stat1;
+ }
+
+ state->an_complete = xpcs_aneg_done_c73(xpcs, state, compat,
+ an_stat1);
+ if (!state->an_complete) {
+ state->link = false;
+ return 0;
+ }
+
+ ret = xpcs_read_lpa_c73(xpcs, state, an_stat1);
+ if (ret < 0) {
+ state->link = false;
+ return ret;
+ }
+
phylink_resolve_c73(state);
- } else if (an_enabled) {
- state->link = 0;
- } else if (state->link) {
+ } else {
xpcs_resolve_pma(xpcs, state);
}
--
2.30.2
^ permalink raw reply related [flat|nested] 10+ messages in thread