From 69906789e0985bb7b923d82f5ec3e4810de36a6e Mon Sep 17 00:00:00 2001 From: Daniel Golle Date: Wed, 9 Oct 2024 00:19:26 +0100 Subject: [PATCH] generic: net: phy: realtek: various improvements Follow the advise of Russell King allows to greatly improve the driver for RealTek's 1G and 2.5G Ethernet PHYs. The results are full/half duplex as well as Gbit master/slave property being read from PHY Specific Status Register (PHYSR), and fixes regarding link-partner advertisement. Fixes: #14504 Signed-off-by: Daniel Golle --- ...phy-realtek-introduce-rtl822x_probe.patch} | 14 +-- ...use-inline-functions-for-10GbE-adver.patch | 26 ---- ...check-validity-of-10GbE-link-partner.patch | 28 ----- ...ek-detect-early-version-of-RTL8221B.patch} | 2 +- ...altek-support-interrupt-of-RTL8221B.patch} | 10 +- ...read-duplex-and-gbit-master-from-PHY.patch | 117 ++++++++++++++++++ ...change-order-of-calls-in-C22-read_st.patch | 51 ++++++++ ...clear-1000Base-T-link-partner-advert.patch | 28 +++++ 8 files changed, 209 insertions(+), 67 deletions(-) rename target/linux/generic/pending-6.6/{720-06-net-phy-realtek-introduce-rtl822x_probe.patch => 720-04-net-phy-realtek-introduce-rtl822x_probe.patch} (87%) delete mode 100644 target/linux/generic/pending-6.6/720-04-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch delete mode 100644 target/linux/generic/pending-6.6/720-05-net-phy-realtek-check-validity-of-10GbE-link-partner.patch rename target/linux/generic/pending-6.6/{720-07-net-phy-realtek-detect-early-version-of-RTL8221B.patch => 720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch} (95%) rename target/linux/generic/pending-6.6/{720-08-net-phy-realtek-support-interrupt-of-RTL8221B.patch => 720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch} (89%) create mode 100644 target/linux/generic/pending-6.6/720-07-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch create mode 100644 target/linux/generic/pending-6.6/720-08-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch create mode 100644 target/linux/generic/pending-6.6/720-09-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch diff --git a/target/linux/generic/pending-6.6/720-06-net-phy-realtek-introduce-rtl822x_probe.patch b/target/linux/generic/pending-6.6/720-04-net-phy-realtek-introduce-rtl822x_probe.patch similarity index 87% rename from target/linux/generic/pending-6.6/720-06-net-phy-realtek-introduce-rtl822x_probe.patch rename to target/linux/generic/pending-6.6/720-04-net-phy-realtek-introduce-rtl822x_probe.patch index ee4de599ab..7350d3affc 100644 --- a/target/linux/generic/pending-6.6/720-06-net-phy-realtek-introduce-rtl822x_probe.patch +++ b/target/linux/generic/pending-6.6/720-04-net-phy-realtek-introduce-rtl822x_probe.patch @@ -24,7 +24,7 @@ Signed-off-by: Daniel Golle #define RTL8366RB_POWER_SAVE 0x15 #define RTL8366RB_POWER_SAVE_ON BIT(12) -@@ -1107,6 +1111,25 @@ static int rtl8221b_vn_cg_c45_match_phy_ +@@ -1102,6 +1106,25 @@ static int rtl8221b_vn_cg_c45_match_phy_ return rtlgen_is_c45_match(phydev, RTL_8221B_VN_CG, true); } @@ -50,7 +50,7 @@ Signed-off-by: Daniel Golle static int rtlgen_resume(struct phy_device *phydev) { int ret = genphy_resume(phydev); -@@ -1382,6 +1405,7 @@ static struct phy_driver realtek_drvs[] +@@ -1377,6 +1400,7 @@ static struct phy_driver realtek_drvs[] }, { PHY_ID_MATCH_EXACT(0x001cc838), .name = "RTL8226-CG 2.5Gbps PHY", @@ -58,7 +58,7 @@ Signed-off-by: Daniel Golle .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1393,6 +1417,7 @@ static struct phy_driver realtek_drvs[] +@@ -1388,6 +1412,7 @@ static struct phy_driver realtek_drvs[] }, { PHY_ID_MATCH_EXACT(0x001cc848), .name = "RTL8226B-CG_RTL8221B-CG 2.5Gbps PHY", @@ -66,7 +66,7 @@ Signed-off-by: Daniel Golle .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1406,6 +1431,7 @@ static struct phy_driver realtek_drvs[] +@@ -1401,6 +1426,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", @@ -74,7 +74,7 @@ Signed-off-by: Daniel Golle .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1419,6 +1445,7 @@ static struct phy_driver realtek_drvs[] +@@ -1414,6 +1440,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", @@ -82,7 +82,7 @@ Signed-off-by: Daniel Golle .soft_reset = genphy_soft_reset, .config_init = rtl822xb_config_init, .get_rate_matching = rtl822xb_get_rate_matching, -@@ -1430,6 +1457,7 @@ static struct phy_driver realtek_drvs[] +@@ -1425,6 +1452,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", @@ -90,7 +90,7 @@ Signed-off-by: Daniel Golle .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, .config_aneg = rtl822x_config_aneg, -@@ -1443,6 +1471,7 @@ static struct phy_driver realtek_drvs[] +@@ -1438,6 +1466,7 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", diff --git a/target/linux/generic/pending-6.6/720-04-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch b/target/linux/generic/pending-6.6/720-04-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch deleted file mode 100644 index 8b20451979..0000000000 --- a/target/linux/generic/pending-6.6/720-04-net-phy-realtek-use-inline-functions-for-10GbE-adver.patch +++ /dev/null @@ -1,26 +0,0 @@ -From 92c8b9d558160d94b981dd8a2b9c47657627ffdc Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sat, 22 Apr 2023 01:23:08 +0100 -Subject: [PATCH 2/3] net: phy: realtek: use inline functions for 10GbE - advertisement - -Use existing generic inline functions to encode local advertisement -of 10GbE link modes as well as to decode link-partner advertisement. - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/realtek.c | 22 +++++----------------- - 1 file changed, 5 insertions(+), 17 deletions(-) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -910,7 +910,8 @@ static int rtl822x_config_aneg(struct ph - - ret = phy_modify_paged_changed(phydev, 0xa5d, 0x12, - MDIO_AN_10GBT_CTRL_ADV2_5G | -- MDIO_AN_10GBT_CTRL_ADV5G, -+ MDIO_AN_10GBT_CTRL_ADV5G | -+ MDIO_AN_10GBT_CTRL_ADV10G, - adv); - if (ret < 0) - return ret; diff --git a/target/linux/generic/pending-6.6/720-05-net-phy-realtek-check-validity-of-10GbE-link-partner.patch b/target/linux/generic/pending-6.6/720-05-net-phy-realtek-check-validity-of-10GbE-link-partner.patch deleted file mode 100644 index 1ba3353f19..0000000000 --- a/target/linux/generic/pending-6.6/720-05-net-phy-realtek-check-validity-of-10GbE-link-partner.patch +++ /dev/null @@ -1,28 +0,0 @@ -From 929bb4d3cfbc7878326c0771a01a636d49c54b40 Mon Sep 17 00:00:00 2001 -From: Daniel Golle -Date: Sat, 22 Apr 2023 01:25:39 +0100 -Subject: [PATCH 3/3] net: phy: realtek: check validity of 10GbE link-partner - advertisement - -Only use link-partner advertisement bits for 10GbE modes if they are -actually valid. Check LOCALOK and REMOTEOK bits and clear 10GbE modes -unless both of them are set. - -Signed-off-by: Daniel Golle ---- - drivers/net/phy/realtek.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/drivers/net/phy/realtek.c -+++ b/drivers/net/phy/realtek.c -@@ -950,6 +950,10 @@ static int rtl822x_read_status(struct ph - if (lpadv < 0) - return lpadv; - -+ if (!(lpadv & MDIO_AN_10GBT_STAT_REMOK) || -+ !(lpadv & MDIO_AN_10GBT_STAT_LOCOK)) -+ lpadv = 0; -+ - mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, - lpadv); - } diff --git a/target/linux/generic/pending-6.6/720-07-net-phy-realtek-detect-early-version-of-RTL8221B.patch b/target/linux/generic/pending-6.6/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch similarity index 95% rename from target/linux/generic/pending-6.6/720-07-net-phy-realtek-detect-early-version-of-RTL8221B.patch rename to target/linux/generic/pending-6.6/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch index cca5da0e13..204d7a0414 100644 --- a/target/linux/generic/pending-6.6/720-07-net-phy-realtek-detect-early-version-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/720-05-net-phy-realtek-detect-early-version-of-RTL8221B.patch @@ -14,7 +14,7 @@ Signed-off-by: Daniel Golle Signed-off-by: Mieczyslaw Nalewaj --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -1085,10 +1085,32 @@ static int rtl8226_match_phy_device(stru +@@ -1080,10 +1080,32 @@ static int rtl8226_match_phy_device(stru static int rtlgen_is_c45_match(struct phy_device *phydev, unsigned int id, bool is_c45) { diff --git a/target/linux/generic/pending-6.6/720-08-net-phy-realtek-support-interrupt-of-RTL8221B.patch b/target/linux/generic/pending-6.6/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch similarity index 89% rename from target/linux/generic/pending-6.6/720-08-net-phy-realtek-support-interrupt-of-RTL8221B.patch rename to target/linux/generic/pending-6.6/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch index ee28bfbcfc..0ae7b385cd 100644 --- a/target/linux/generic/pending-6.6/720-08-net-phy-realtek-support-interrupt-of-RTL8221B.patch +++ b/target/linux/generic/pending-6.6/720-06-net-phy-realtek-support-interrupt-of-RTL8221B.patch @@ -12,7 +12,7 @@ Signed-off-by: Jianhui Zhao --- a/drivers/net/phy/realtek.c +++ b/drivers/net/phy/realtek.c -@@ -1287,6 +1287,51 @@ static irqreturn_t rtl9000a_handle_inter +@@ -1282,6 +1282,51 @@ static irqreturn_t rtl9000a_handle_inter return IRQ_HANDLED; } @@ -64,7 +64,7 @@ Signed-off-by: Jianhui Zhao static struct phy_driver realtek_drvs[] = { { PHY_ID_MATCH_EXACT(0x00008201), -@@ -1453,6 +1498,8 @@ static struct phy_driver realtek_drvs[] +@@ -1448,6 +1493,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c22_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C22)", @@ -73,7 +73,7 @@ Signed-off-by: Jianhui Zhao .probe = rtl822x_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, -@@ -1467,6 +1514,8 @@ static struct phy_driver realtek_drvs[] +@@ -1462,6 +1509,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vb_cg_c45_match_phy_device, .name = "RTL8221B-VB-CG 2.5Gbps PHY (C45)", @@ -82,7 +82,7 @@ Signed-off-by: Jianhui Zhao .probe = rtl822x_probe, .soft_reset = genphy_soft_reset, .config_init = rtl822xb_config_init, -@@ -1479,6 +1528,8 @@ static struct phy_driver realtek_drvs[] +@@ -1474,6 +1523,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c22_match_phy_device, .name = "RTL8221B-VM-CG 2.5Gbps PHY (C22)", @@ -91,7 +91,7 @@ Signed-off-by: Jianhui Zhao .probe = rtl822x_probe, .soft_reset = genphy_soft_reset, .get_features = rtl822x_get_features, -@@ -1493,6 +1544,8 @@ static struct phy_driver realtek_drvs[] +@@ -1488,6 +1539,8 @@ static struct phy_driver realtek_drvs[] }, { .match_phy_device = rtl8221b_vn_cg_c45_match_phy_device, .name = "RTL8221B-VN-CG 2.5Gbps PHY (C45)", diff --git a/target/linux/generic/pending-6.6/720-07-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch b/target/linux/generic/pending-6.6/720-07-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch new file mode 100644 index 0000000000..d609d596af --- /dev/null +++ b/target/linux/generic/pending-6.6/720-07-net-phy-realtek-read-duplex-and-gbit-master-from-PHY.patch @@ -0,0 +1,117 @@ +From 66d82d3f04623e9c096e12c10ca51141c345ee84 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 8 Oct 2024 20:59:51 +0100 +Subject: [PATCH] net: phy: realtek: read duplex and gbit master from PHYSR + register + +The PHYSR MMD register is present and defined equally for all RTL82xx +Ethernet PHYs. +Read duplex and gbit master bits from rtlgen_decode_speed() and rename +it to rtlgen_decode_physr(). + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 48 ++++++++++++++++++++++++++++++++------- + 1 file changed, 40 insertions(+), 8 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -80,20 +80,24 @@ + + #define RTL822X_VND2_GANLPAR 0xa414 + +-#define RTL822X_VND2_PHYSR 0xa434 +- + #define RTL8221B_PHYCR1 0xa430 + #define RTL8221B_PHYCR1_ALDPS_EN BIT(2) + #define RTL8221B_PHYCR1_ALDPS_XTAL_OFF_EN BIT(12) + ++#define RTL_VND2_PHYSR 0xa434 ++#define RTL_VND2_PHYSR_LINK BIT(2) ++#define RTL_VND2_PHYSR_DUPLEX BIT(3) ++#define RTL_VND2_PHYSR_SPEEDL GENMASK(5, 4) ++#define RTL_VND2_PHYSR_SPEEDH GENMASK(10, 9) ++#define RTL_VND2_PHYSR_MASTER BIT(11) ++#define RTL_VND2_PHYSR_SPEED_MASK (RTL_VND2_PHYSR_SPEEDL | RTL_VND2_PHYSR_SPEEDH) ++ + #define RTL8366RB_POWER_SAVE 0x15 + #define RTL8366RB_POWER_SAVE_ON BIT(12) + + #define RTL9000A_GINMR 0x14 + #define RTL9000A_GINMR_LINK_STATUS BIT(4) + +-#define RTLGEN_SPEED_MASK 0x0630 +- + #define RTL_GENERIC_PHYID 0x001cc800 + #define RTL_8211FVD_PHYID 0x001cc878 + #define RTL_8221B_VB_CG 0x001cc849 +@@ -661,9 +665,24 @@ static int rtl8366rb_config_init(struct + } + + /* get actual speed to cover the downshift case */ +-static void rtlgen_decode_speed(struct phy_device *phydev, int val) ++static void rtlgen_decode_physr(struct phy_device *phydev, int val) + { +- switch (val & RTLGEN_SPEED_MASK) { ++ /* bit 2 ++ * 0: Link not OK ++ * 1: Link OK ++ */ ++ phydev->link = !!(val & RTL_VND2_PHYSR_LINK); ++ ++ /* bit 3 ++ * 0: Half Duplex ++ * 1: Full Duplex ++ */ ++ if (val & RTL_VND2_PHYSR_DUPLEX) ++ phydev->duplex = DUPLEX_FULL; ++ else ++ phydev->duplex = DUPLEX_HALF; ++ ++ switch (val & RTL_VND2_PHYSR_SPEED_MASK) { + case 0x0000: + phydev->speed = SPEED_10; + break; +@@ -685,6 +704,19 @@ static void rtlgen_decode_speed(struct p + default: + break; + } ++ ++ /* bit 11 ++ * 0: Slave Mode ++ * 1: Master Mode ++ */ ++ if (phydev->speed >= 1000) { ++ if (val & RTL_VND2_PHYSR_MASTER) ++ phydev->master_slave_state = MASTER_SLAVE_STATE_MASTER; ++ else ++ phydev->master_slave_state = MASTER_SLAVE_STATE_SLAVE; ++ } else { ++ phydev->master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED; ++ } + } + + static int rtlgen_read_status(struct phy_device *phydev) +@@ -702,7 +734,7 @@ static int rtlgen_read_status(struct phy + if (val < 0) + return val; + +- rtlgen_decode_speed(phydev, val); ++ rtlgen_decode_physr(phydev, val); + + return 0; + } +@@ -1030,11 +1062,11 @@ static int rtl822x_c45_read_status(struc + return 0; + + /* Read actual speed from vendor register. */ +- val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL822X_VND2_PHYSR); ++ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, RTL_VND2_PHYSR); + if (val < 0) + return val; + +- rtlgen_decode_speed(phydev, val); ++ rtlgen_decode_physr(phydev, val); + + return 0; + } diff --git a/target/linux/generic/pending-6.6/720-08-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch b/target/linux/generic/pending-6.6/720-08-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch new file mode 100644 index 0000000000..8a7ad8afa8 --- /dev/null +++ b/target/linux/generic/pending-6.6/720-08-net-phy-realtek-change-order-of-calls-in-C22-read_st.patch @@ -0,0 +1,51 @@ +From eaca24de0c0e64145c130759207da32594d2e5d1 Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 8 Oct 2024 21:05:47 +0100 +Subject: [PATCH 2/3] net: phy: realtek: change order of calls in C22 + read_status() + +Always call rtlgen_read_status() first, so genphy_read_status() which +is called by it clears bits in case auto-negotiation has not completed. +Also clear 10GBT link-partner advertisement bits in case auto-negotiation +is disabled or has not completed. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -979,17 +979,25 @@ static void rtl822xb_update_interface(st + + static int rtl822x_read_status(struct phy_device *phydev) + { +- if (phydev->autoneg == AUTONEG_ENABLE) { +- int lpadv = phy_read_paged(phydev, 0xa5d, 0x13); ++ int lpadv, ret; + +- if (lpadv < 0) +- return lpadv; ++ ret = rtlgen_read_status(phydev); ++ if (ret < 0) ++ return ret; + +- mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, +- lpadv); ++ if (phydev->autoneg == AUTONEG_DISABLE || ++ !phydev->autoneg_complete) { ++ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ return 0; + } + +- return rtlgen_read_status(phydev); ++ lpadv = phy_read_paged(phydev, 0xa5d, 0x13); ++ if (lpadv < 0) ++ return lpadv; ++ ++ mii_10gbt_stat_mod_linkmode_lpa_t(phydev->lp_advertising, lpadv); ++ ++ return 0; + } + + static int rtl822xb_read_status(struct phy_device *phydev) diff --git a/target/linux/generic/pending-6.6/720-09-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch b/target/linux/generic/pending-6.6/720-09-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch new file mode 100644 index 0000000000..824be84c68 --- /dev/null +++ b/target/linux/generic/pending-6.6/720-09-net-phy-realtek-clear-1000Base-T-link-partner-advert.patch @@ -0,0 +1,28 @@ +From 8b137d1e405dc90300ba577db44c70f0e026636e Mon Sep 17 00:00:00 2001 +From: Daniel Golle +Date: Tue, 8 Oct 2024 21:09:19 +0100 +Subject: [PATCH 3/3] net: phy: realtek: clear 1000Base-T link partner + advertisement + +Clear 1000Base-T link partner advertisement bits in Clause-45 +read_status() function in case auto-negotiation is disabled or has not +been completed. + +Signed-off-by: Daniel Golle +--- + drivers/net/phy/realtek.c | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/drivers/net/phy/realtek.c ++++ b/drivers/net/phy/realtek.c +@@ -1056,6 +1056,10 @@ static int rtl822x_c45_read_status(struc + if (ret < 0) + return ret; + ++ if (phydev->autoneg == AUTONEG_DISABLE || ++ !genphy_c45_aneg_done(phydev)) ++ mii_stat1000_mod_linkmode_lpa_t(phydev->lp_advertising, 0); ++ + /* Vendor register as C45 has no standardized support for 1000BaseT */ + if (phydev->autoneg == AUTONEG_ENABLE) { + val = phy_read_mmd(phydev, MDIO_MMD_VEND2, -- 2.30.2