net: phy: mxl-gpy: add PHY-level statistics via ethtool
Report PCS receive error counts for all supported GPY115x, GPY2xx and MxL862xx PHYs. Accumulate the vendor-specific PHY_ERRCNT read-clear counter (SEL=RXERR) in .update_stats() and expose it as both IEEE 802.3 SymbolErrorDuringCarrier and generic rx_errors via .get_phy_stats(). Signed-off-by: Daniel Golle <daniel@makrotopia.org> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Link: https://patch.msgid.link/0029a2fb29bfdcc26abff828d2e18400067b5c58.1773587924.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
8737d7194d
commit
05c1fc56d3
1 changed files with 64 additions and 2 deletions
|
|
@ -38,12 +38,17 @@
|
|||
#define PHY_CTL1_MDICD BIT(3)
|
||||
#define PHY_CTL1_MDIAB BIT(2)
|
||||
#define PHY_CTL1_AMDIX BIT(0)
|
||||
#define PHY_ERRCNT 0x15 /* Error counter */
|
||||
#define PHY_MIISTAT 0x18 /* MII state */
|
||||
#define PHY_IMASK 0x19 /* interrupt mask */
|
||||
#define PHY_ISTAT 0x1A /* interrupt status */
|
||||
#define PHY_LED 0x1B /* LEDs */
|
||||
#define PHY_FWV 0x1E /* firmware version */
|
||||
|
||||
#define PHY_ERRCNT_SEL GENMASK(11, 8)
|
||||
#define PHY_ERRCNT_COUNT GENMASK(7, 0)
|
||||
#define PHY_ERRCNT_SEL_RXERR 0
|
||||
|
||||
#define PHY_MIISTAT_SPD_MASK GENMASK(2, 0)
|
||||
#define PHY_MIISTAT_DPX BIT(3)
|
||||
#define PHY_MIISTAT_LS BIT(10)
|
||||
|
|
@ -134,6 +139,7 @@ struct gpy_priv {
|
|||
u8 fw_major;
|
||||
u8 fw_minor;
|
||||
u32 wolopts;
|
||||
u64 rx_errors;
|
||||
|
||||
/* It takes 3 seconds to fully switch out of loopback mode before
|
||||
* it can safely re-enter loopback mode. Record the time when
|
||||
|
|
@ -331,8 +337,9 @@ out:
|
|||
|
||||
static int gpy_config_init(struct phy_device *phydev)
|
||||
{
|
||||
/* Nothing to configure. Configuration Requirement Placeholder */
|
||||
return 0;
|
||||
/* Count MDI RX errors (SymbolErrorDuringCarrier) */
|
||||
return phy_write(phydev, PHY_ERRCNT,
|
||||
FIELD_PREP(PHY_ERRCNT_SEL, PHY_ERRCNT_SEL_RXERR));
|
||||
}
|
||||
|
||||
static int gpy21x_config_init(struct phy_device *phydev)
|
||||
|
|
@ -1067,6 +1074,31 @@ static int gpy_config_inband(struct phy_device *phydev, unsigned int modes)
|
|||
VSPEC1_SGMII_ANEN_ANRS);
|
||||
}
|
||||
|
||||
static int gpy_update_stats(struct phy_device *phydev)
|
||||
{
|
||||
struct gpy_priv *priv = phydev->priv;
|
||||
int ret;
|
||||
|
||||
/* PHY_ERRCNT: 8-bit read-clear counter, SEL set to RXERR */
|
||||
ret = phy_read(phydev, PHY_ERRCNT);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
priv->rx_errors += FIELD_GET(PHY_ERRCNT_COUNT, ret);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void gpy_get_phy_stats(struct phy_device *phydev,
|
||||
struct ethtool_eth_phy_stats *eth_stats,
|
||||
struct ethtool_phy_stats *stats)
|
||||
{
|
||||
struct gpy_priv *priv = phydev->priv;
|
||||
|
||||
eth_stats->SymbolErrorDuringCarrier = priv->rx_errors;
|
||||
stats->rx_errors = priv->rx_errors;
|
||||
}
|
||||
|
||||
static struct phy_driver gpy_drivers[] = {
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY2xx),
|
||||
|
|
@ -1091,6 +1123,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY115B,
|
||||
|
|
@ -1116,6 +1150,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY115C),
|
||||
|
|
@ -1140,6 +1176,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY211B,
|
||||
|
|
@ -1165,6 +1203,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY211C),
|
||||
|
|
@ -1189,6 +1229,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY212B,
|
||||
|
|
@ -1214,6 +1256,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY212C),
|
||||
|
|
@ -1238,6 +1282,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
.phy_id = PHY_ID_GPY215B,
|
||||
|
|
@ -1263,6 +1309,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY215C),
|
||||
|
|
@ -1287,6 +1335,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY241B),
|
||||
|
|
@ -1306,6 +1356,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY241BM),
|
||||
|
|
@ -1325,6 +1377,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_GPY245B),
|
||||
|
|
@ -1344,6 +1398,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_MXL86211C),
|
||||
|
|
@ -1368,6 +1424,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
.led_hw_control_set = gpy_led_hw_control_set,
|
||||
.led_polarity_set = gpy_led_polarity_set,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
},
|
||||
{
|
||||
PHY_ID_MATCH_MODEL(PHY_ID_MXL86252),
|
||||
|
|
@ -1385,6 +1443,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
.led_brightness_set = gpy_led_brightness_set,
|
||||
.led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
|
|
@ -1407,6 +1467,8 @@ static struct phy_driver gpy_drivers[] = {
|
|||
.set_wol = gpy_set_wol,
|
||||
.get_wol = gpy_get_wol,
|
||||
.set_loopback = gpy_loopback,
|
||||
.update_stats = gpy_update_stats,
|
||||
.get_phy_stats = gpy_get_phy_stats,
|
||||
.led_brightness_set = gpy_led_brightness_set,
|
||||
.led_hw_is_supported = gpy_led_hw_is_supported,
|
||||
.led_hw_control_get = gpy_led_hw_control_get,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue