Skip to content

Commit 14e47d1

Browse files
oleremdavem330
authored andcommitted
net: phy: add genphy_c45_read_eee_abilities() function
Add generic function for EEE abilities defined by IEEE 802.3 specification. For now following registers are supported: - IEEE 802.3-2018 45.2.3.10 EEE control and capability 1 (Register 3.20) - IEEE 802.3cg-2019 45.2.1.186b 10BASE-T1L PMA status register (Register 1.2295) Since I was not able to find any flag signaling support of these registers, we should detect link mode abilities first and then based on these abilities doing EEE link modes detection. Results of EEE ability detection will be stored into new variable phydev->supported_eee. Signed-off-by: Oleksij Rempel <[email protected]> Reviewed-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 69d3b36 commit 14e47d1

File tree

4 files changed

+118
-0
lines changed

4 files changed

+118
-0
lines changed

drivers/net/phy/phy-c45.c

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -661,6 +661,76 @@ int genphy_c45_read_mdix(struct phy_device *phydev)
661661
}
662662
EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
663663

664+
/**
665+
* genphy_c45_read_eee_cap1 - read supported EEE link modes from register 3.20
666+
* @phydev: target phy_device struct
667+
*/
668+
static int genphy_c45_read_eee_cap1(struct phy_device *phydev)
669+
{
670+
int val;
671+
672+
/* IEEE 802.3-2018 45.2.3.10 EEE control and capability 1
673+
* (Register 3.20)
674+
*/
675+
val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
676+
if (val < 0)
677+
return val;
678+
679+
/* The 802.3 2018 standard says the top 2 bits are reserved and should
680+
* read as 0. Also, it seems unlikely anybody will build a PHY which
681+
* supports 100GBASE-R deep sleep all the way down to 100BASE-TX EEE.
682+
* If MDIO_PCS_EEE_ABLE is 0xffff assume EEE is not supported.
683+
*/
684+
if (val == 0xffff)
685+
return 0;
686+
687+
mii_eee_cap1_mod_linkmode_t(phydev->supported_eee, val);
688+
689+
/* Some buggy devices indicate EEE link modes in MDIO_PCS_EEE_ABLE
690+
* which they don't support as indicated by BMSR, ESTATUS etc.
691+
*/
692+
linkmode_and(phydev->supported_eee, phydev->supported_eee,
693+
phydev->supported);
694+
695+
return 0;
696+
}
697+
698+
/**
699+
* genphy_c45_read_eee_abilities - read supported EEE link modes
700+
* @phydev: target phy_device struct
701+
*/
702+
int genphy_c45_read_eee_abilities(struct phy_device *phydev)
703+
{
704+
int val;
705+
706+
/* There is not indicator whether optional register
707+
* "EEE control and capability 1" (3.20) is supported. Read it only
708+
* on devices with appropriate linkmodes.
709+
*/
710+
if (linkmode_intersects(phydev->supported, PHY_EEE_CAP1_FEATURES)) {
711+
val = genphy_c45_read_eee_cap1(phydev);
712+
if (val)
713+
return val;
714+
}
715+
716+
if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
717+
phydev->supported)) {
718+
/* IEEE 802.3cg-2019 45.2.1.186b 10BASE-T1L PMA status register
719+
* (Register 1.2295)
720+
*/
721+
val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10T1L_STAT);
722+
if (val < 0)
723+
return val;
724+
725+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
726+
phydev->supported_eee,
727+
val & MDIO_PMA_10T1L_STAT_EEE);
728+
}
729+
730+
return 0;
731+
}
732+
EXPORT_SYMBOL_GPL(genphy_c45_read_eee_abilities);
733+
664734
/**
665735
* genphy_c45_pma_read_abilities - read supported link modes from PMA
666736
* @phydev: target phy_device struct

drivers/net/phy/phy_device.c

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,18 @@ static const int phy_10gbit_full_features_array[] = {
132132
ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
133133
};
134134

135+
static const int phy_eee_cap1_features_array[] = {
136+
ETHTOOL_LINK_MODE_100baseT_Full_BIT,
137+
ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
138+
ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
139+
ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
140+
ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
141+
ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
142+
};
143+
144+
__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init;
145+
EXPORT_SYMBOL_GPL(phy_eee_cap1_features);
146+
135147
static void features_init(void)
136148
{
137149
/* 10/100 half/full*/
@@ -213,6 +225,10 @@ static void features_init(void)
213225
linkmode_set_bit_array(phy_10gbit_fec_features_array,
214226
ARRAY_SIZE(phy_10gbit_fec_features_array),
215227
phy_10gbit_fec_features);
228+
linkmode_set_bit_array(phy_eee_cap1_features_array,
229+
ARRAY_SIZE(phy_eee_cap1_features_array),
230+
phy_eee_cap1_features);
231+
216232
}
217233

218234
void phy_device_free(struct phy_device *phydev)

include/linux/mdio.h

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,6 +402,32 @@ static inline u32 linkmode_adv_to_mii_t1_adv_m_t(unsigned long *advertising)
402402
return result;
403403
}
404404

405+
/**
406+
* mii_eee_cap1_mod_linkmode_t()
407+
* @adv: target the linkmode advertisement settings
408+
* @val: register value
409+
*
410+
* A function that translates value of following registers to the linkmode:
411+
* IEEE 802.3-2018 45.2.3.10 "EEE control and capability 1" register (3.20)
412+
* IEEE 802.3-2018 45.2.7.13 "EEE advertisement 1" register (7.60)
413+
* IEEE 802.3-2018 45.2.7.14 "EEE "link partner ability 1 register (7.61)
414+
*/
415+
static inline void mii_eee_cap1_mod_linkmode_t(unsigned long *adv, u32 val)
416+
{
417+
linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
418+
adv, val & MDIO_EEE_100TX);
419+
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
420+
adv, val & MDIO_EEE_1000T);
421+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
422+
adv, val & MDIO_EEE_10GT);
423+
linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
424+
adv, val & MDIO_EEE_1000KX);
425+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
426+
adv, val & MDIO_EEE_10GKX4);
427+
linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
428+
adv, val & MDIO_EEE_10GKR);
429+
}
430+
405431
int __mdiobus_read(struct mii_bus *bus, int addr, u32 regnum);
406432
int __mdiobus_write(struct mii_bus *bus, int addr, u32 regnum, u16 val);
407433
int __mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,

include/linux/phy.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_
5252
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
5353
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
5454
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
55+
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init;
5556

5657
#define PHY_BASIC_FEATURES ((unsigned long *)&phy_basic_features)
5758
#define PHY_BASIC_T1_FEATURES ((unsigned long *)&phy_basic_t1_features)
@@ -62,6 +63,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_ini
6263
#define PHY_10GBIT_FEATURES ((unsigned long *)&phy_10gbit_features)
6364
#define PHY_10GBIT_FEC_FEATURES ((unsigned long *)&phy_10gbit_fec_features)
6465
#define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features)
66+
#define PHY_EEE_CAP1_FEATURES ((unsigned long *)&phy_eee_cap1_features)
6567

6668
extern const int phy_basic_ports_array[3];
6769
extern const int phy_fibre_port_array[1];
@@ -572,6 +574,7 @@ struct macsec_ops;
572574
* @supported: Combined MAC/PHY supported linkmodes
573575
* @advertising: Currently advertised linkmodes
574576
* @adv_old: Saved advertised while power saving for WoL
577+
* @supported_eee: supported PHY EEE linkmodes
575578
* @lp_advertising: Current link partner advertised linkmodes
576579
* @host_interfaces: PHY interface modes supported by host
577580
* @eee_broken_modes: Energy efficient ethernet modes which should be prohibited
@@ -676,6 +679,8 @@ struct phy_device {
676679
__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
677680
/* used with phy_speed_down */
678681
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
682+
/* used for eee validation */
683+
__ETHTOOL_DECLARE_LINK_MODE_MASK(supported_eee);
679684

680685
/* Host supported PHY interface types. Should be ignored if empty. */
681686
DECLARE_PHY_INTERFACE_MASK(host_interfaces);
@@ -1737,6 +1742,7 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev);
17371742
int genphy_c45_an_disable_aneg(struct phy_device *phydev);
17381743
int genphy_c45_read_mdix(struct phy_device *phydev);
17391744
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
1745+
int genphy_c45_read_eee_abilities(struct phy_device *phydev);
17401746
int genphy_c45_pma_baset1_read_master_slave(struct phy_device *phydev);
17411747
int genphy_c45_read_status(struct phy_device *phydev);
17421748
int genphy_c45_baset1_read_status(struct phy_device *phydev);

0 commit comments

Comments
 (0)