2023-02-06 13:51:44

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 00/23] net: add EEE support for KSZ9477 and AR8035 with i.MX6

changes v5:
- spell fixes
- move part of genphy_c45_read_eee_abilities() to
genphy_c45_read_eee_cap1()
- validate MDIO_PCS_EEE_ABLE register against 0xffff val.
- rename *eee_100_10000* to *eee_cap1*
- use linkmode_intersects(phydev->supported, PHY_EEE_CAP1_FEATURES)
instead of !linkmode_empty()
- add documentation to linkmode/register helpers

changes v4:
- remove following helpers:
mmd_eee_cap_to_ethtool_sup_t
mmd_eee_adv_to_ethtool_adv_t
ethtool_adv_to_mmd_eee_adv_t
and port drivers from this helpers to linkmode helpers.
- rebase against latest net-next
- port phy_init_eee() to genphy_c45_eee_is_active()

changes v3:
- rework some parts of EEE infrastructure and move it to c45 code.
- add supported_eee storage and start using it in EEE code and by the
micrel driver.
- add EEE support for ar8035 PHY
- add SmartEEE support to FEC i.MX series.

changes v2:
- use phydev->supported instead of reading MII_BMSR regiaster
- fix @get_eee > @set_eee

With this patch series we provide EEE control for KSZ9477 family of switches and
AR8035 with i.MX6 configuration.
According to my tests, on a system with KSZ8563 switch and 100Mbit idle link,
we consume 0,192W less power per port if EEE is enabled.

Oleksij Rempel (23):
net: dsa: microchip: enable EEE support
net: phy: add genphy_c45_read_eee_abilities() function
net: phy: micrel: add ksz9477_get_features()
net: phy: export phy_check_valid() function
net: phy: add genphy_c45_ethtool_get/set_eee() support
net: phy: c22: migrate to genphy_c45_write_eee_adv()
net: phy: c45: migrate to genphy_c45_write_eee_adv()
net: phy: migrate phy_init_eee() to genphy_c45_eee_is_active()
net: phy: start using genphy_c45_ethtool_get/set_eee()
net: phy: add driver specific get/set_eee support
net: phy: at803x: implement ethtool access to SmartEEE functionality
net: phy: at803x: ar8035: fix EEE support for half duplex links
net: phy: add PHY specifica flag to signal SmartEEE support
net: phy: at803x: add PHY_SMART_EEE flag to AR8035
net: phy: add phy_has_smarteee() helper
net: fec: add support for PHYs with SmartEEE support
e1000e: replace EEE ethtool helpers to linkmode variants
igb: replace EEE ethtool helpers to linkmode variants
igc: replace EEE ethtool helpers to linkmode variants
tg3: replace EEE ethtool helpers to linkmode variants
r8152: replace EEE ethtool helpers to linkmode variants
net: usb: ax88179_178a: replace EEE ethtool helpers to linkmode
variants
net: mdio: drop EEE ethtool helpers in favor to linkmode variants

drivers/net/dsa/microchip/ksz_common.c | 65 ++++
drivers/net/ethernet/broadcom/tg3.c | 9 +-
drivers/net/ethernet/freescale/fec_main.c | 22 +-
drivers/net/ethernet/intel/e1000e/ethtool.c | 16 +-
drivers/net/ethernet/intel/igb/igb_ethtool.c | 23 +-
drivers/net/ethernet/intel/igc/igc_ethtool.c | 12 +-
drivers/net/phy/at803x.c | 142 ++++++++-
drivers/net/phy/micrel.c | 21 ++
drivers/net/phy/phy-c45.c | 316 ++++++++++++++++++-
drivers/net/phy/phy.c | 155 ++-------
drivers/net/phy/phy_device.c | 26 +-
drivers/net/usb/ax88179_178a.c | 24 +-
drivers/net/usb/r8152.c | 34 +-
include/linux/mdio.h | 167 +++++-----
include/linux/phy.h | 28 ++
include/uapi/linux/mdio.h | 8 +
16 files changed, 808 insertions(+), 260 deletions(-)

--
2.30.2



2023-02-06 13:51:45

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 10/23] net: phy: add driver specific get/set_eee support

Not all PHYs can be handled by generic phy_ethtool_get/set_eee()
functions. So, add driver specific get/set_eee support.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/phy.c | 6 ++++++
include/linux/phy.h | 5 +++++
2 files changed, 11 insertions(+)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 2f1041a7211e..c42df62df302 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1520,6 +1520,9 @@ int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
if (!phydev->drv)
return -EIO;

+ if (phydev->drv->get_eee)
+ return phydev->drv->get_eee(phydev, data);
+
return genphy_c45_ethtool_get_eee(phydev, data);
}
EXPORT_SYMBOL(phy_ethtool_get_eee);
@@ -1536,6 +1539,9 @@ int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
if (!phydev->drv)
return -EIO;

+ if (phydev->drv->set_eee)
+ return phydev->drv->set_eee(phydev, data);
+
return genphy_c45_ethtool_set_eee(phydev, data);
}
EXPORT_SYMBOL(phy_ethtool_set_eee);
diff --git a/include/linux/phy.h b/include/linux/phy.h
index ef0e3212f68e..b14ca4b06607 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1051,6 +1051,11 @@ struct phy_driver {
/** @get_plca_status: Return the current PLCA status info */
int (*get_plca_status)(struct phy_device *dev,
struct phy_plca_status *plca_st);
+
+ /** @get_eee: Return the current EEE configuration */
+ int (*get_eee)(struct phy_device *phydev, struct ethtool_eee *e);
+ /** @set_eee: Set the EEE configuration */
+ int (*set_eee)(struct phy_device *phydev, struct ethtool_eee *e);
};
#define to_phy_driver(d) container_of(to_mdio_common_driver(d), \
struct phy_driver, mdiodrv)
--
2.30.2


2023-02-06 13:51:48

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 22/23] net: usb: ax88179_178a: replace EEE ethtool helpers to linkmode variants

Replace EEE ethtool helpers with linkmode variants. This will
reduce similar code snippets and prepare ethtool EEE interface to linkmode
migration.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/usb/ax88179_178a.c | 24 +++++++++++++++++-------
1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/drivers/net/usb/ax88179_178a.c b/drivers/net/usb/ax88179_178a.c
index aff39bf3161d..77cc795ef6ee 100644
--- a/drivers/net/usb/ax88179_178a.c
+++ b/drivers/net/usb/ax88179_178a.c
@@ -652,6 +652,9 @@ static int ax88179_set_link_ksettings(struct net_device *net,
static int
ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data)
{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_able) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_lp) = {};
int val;

/* Get Supported EEE */
@@ -659,21 +662,24 @@ ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data)
MDIO_MMD_PCS);
if (val < 0)
return val;
- data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_able, val);
+ ethtool_convert_link_mode_to_legacy_u32(&data->supported, lm_able);

/* Get advertisement EEE */
val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_ADV,
MDIO_MMD_AN);
if (val < 0)
return val;
- data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_adv, val);
+ ethtool_convert_link_mode_to_legacy_u32(&data->advertised, lm_adv);

/* Get LP advertisement EEE */
val = ax88179_phy_read_mmd_indirect(dev, MDIO_AN_EEE_LPABLE,
MDIO_MMD_AN);
if (val < 0)
return val;
- data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_lp, val);
+ ethtool_convert_link_mode_to_legacy_u32(&data->lp_advertised, lm_lp);

return 0;
}
@@ -681,7 +687,11 @@ ax88179_ethtool_get_eee(struct usbnet *dev, struct ethtool_eee *data)
static int
ax88179_ethtool_set_eee(struct usbnet *dev, struct ethtool_eee *data)
{
- u16 tmp16 = ethtool_adv_to_mmd_eee_adv_t(data->advertised);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
+ u16 tmp16;
+
+ adv[0] = data->advertised;
+ tmp16 = linkmode_to_mii_eee_cap1_t(adv);

return ax88179_phy_write_mmd_indirect(dev, MDIO_AN_EEE_ADV,
MDIO_MMD_AN, tmp16);
@@ -706,7 +716,7 @@ static int ax88179_chk_eee(struct usbnet *dev)
return false;
}

- cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
+ cap = eee_cap & (MDIO_EEE_100TX | MDIO_EEE_1000T);
if (!cap) {
priv->eee_active = 0;
return false;
@@ -729,8 +739,8 @@ static int ax88179_chk_eee(struct usbnet *dev)
return false;
}

- adv = mmd_eee_adv_to_ethtool_adv_t(eee_adv);
- lp = mmd_eee_adv_to_ethtool_adv_t(eee_lp);
+ adv = eee_adv & (MDIO_EEE_100TX | MDIO_EEE_1000T);
+ lp = eee_lp & (MDIO_EEE_100TX | MDIO_EEE_1000T);
supported = (ecmd.speed == SPEED_1000) ?
SUPPORTED_1000baseT_Full :
SUPPORTED_100baseT_Full;
--
2.30.2


2023-02-06 13:51:50

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 21/23] r8152: replace EEE ethtool helpers to linkmode variants

Replace EEE ethtool helpers with linkmode variants. This will
reduce similar code snippets and prepare ethtool EEE interface to linkmode
migration.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/usb/r8152.c | 34 +++++++++++++++++++++++++---------
1 file changed, 25 insertions(+), 9 deletions(-)

diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c
index decb5ba56a25..5195859a8e17 100644
--- a/drivers/net/usb/r8152.c
+++ b/drivers/net/usb/r8152.c
@@ -8745,17 +8745,23 @@ static void rtl8152_get_strings(struct net_device *dev, u32 stringset, u8 *data)

static int r8152_get_eee(struct r8152 *tp, struct ethtool_eee *eee)
{
- u32 lp, adv, supported = 0;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_able) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_lp) = {};
+ u32 lp, adv, supported;
u16 val;

val = r8152_mmd_read(tp, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
- supported = mmd_eee_cap_to_ethtool_sup_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_able, val);
+ ethtool_convert_link_mode_to_legacy_u32(&supported, lm_able);

val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
- adv = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_adv, val);
+ ethtool_convert_link_mode_to_legacy_u32(&adv, lm_adv);

val = r8152_mmd_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
- lp = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_lp, val);
+ ethtool_convert_link_mode_to_legacy_u32(&lp, lm_lp);

eee->eee_enabled = tp->eee_en;
eee->eee_active = !!(supported & adv & lp);
@@ -8768,7 +8774,11 @@ static int r8152_get_eee(struct r8152 *tp, struct ethtool_eee *eee)

static int r8152_set_eee(struct r8152 *tp, struct ethtool_eee *eee)
{
- u16 val = ethtool_adv_to_mmd_eee_adv_t(eee->advertised);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
+ u16 val;
+
+ adv[0] = eee->advertised;
+ val = linkmode_to_mii_eee_cap1_t(adv);

tp->eee_en = eee->eee_enabled;
tp->eee_adv = val;
@@ -8780,17 +8790,23 @@ static int r8152_set_eee(struct r8152 *tp, struct ethtool_eee *eee)

static int r8153_get_eee(struct r8152 *tp, struct ethtool_eee *eee)
{
- u32 lp, adv, supported = 0;
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_able) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_lp) = {};
+ u32 lp, adv, supported;
u16 val;

val = ocp_reg_read(tp, OCP_EEE_ABLE);
- supported = mmd_eee_cap_to_ethtool_sup_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_able, val);
+ ethtool_convert_link_mode_to_legacy_u32(&supported, lm_able);

val = ocp_reg_read(tp, OCP_EEE_ADV);
- adv = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_adv, val);
+ ethtool_convert_link_mode_to_legacy_u32(&adv, lm_adv);

val = ocp_reg_read(tp, OCP_EEE_LPABLE);
- lp = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(lm_lp, val);
+ ethtool_convert_link_mode_to_legacy_u32(&lp, lm_lp);

eee->eee_enabled = tp->eee_en;
eee->eee_active = !!(supported & adv & lp);
--
2.30.2


2023-02-06 13:51:53

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 11/23] net: phy: at803x: implement ethtool access to SmartEEE functionality

If AR8035 PHY is used with a MAC without EEE support
(iMX6, etc), then we need to process ethtool_eee::tx_lpi_timer and
tx_lpi_enabled by the PHY driver. So, add get/set_eee support for this
functionality.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/at803x.c | 109 +++++++++++++++++++++++++++++++++++++--
1 file changed, 104 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 22f4458274aa..9eb4439b0afc 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -166,8 +166,18 @@

#define AT803X_MMD3_SMARTEEE_CTL1 0x805b
#define AT803X_MMD3_SMARTEEE_CTL2 0x805c
+#define AT803X_MMD3_SMARTEEE_LPI_TIME_LOW GENMASK(15, 0)
+#define AT803X_MMD3_SMARTEEE_LPI_TIME_15_0 GENMASK(15, 0)
#define AT803X_MMD3_SMARTEEE_CTL3 0x805d
#define AT803X_MMD3_SMARTEEE_CTL3_LPI_EN BIT(8)
+#define AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH GENMASK(7, 0)
+#define AT803X_MMD3_SMARTEEE_LPI_TIME_23_16 GENMASK(23, 16)
+/* Tx LPI timer resolution */
+#define AT803X_MMD3_SMARTEEE_LPI_TIME_RESOL_NS 163840
+#define AT803X_MMD3_SMARTEEE_LPI_TIME_MAX_US \
+ ((GENMASK(23, 0) * AT803X_MMD3_SMARTEEE_LPI_TIME_RESOL_NS) / \
+ NSEC_PER_USEC)
+#define AT803X_MMD3_SMARTEEE_LPI_TIME_DEF_US 335544

#define ATH9331_PHY_ID 0x004dd041
#define ATH8030_PHY_ID 0x004dd076
@@ -951,17 +961,26 @@ static int at803x_get_features(struct phy_device *phydev)
return 0;
}

-static int at803x_smarteee_config(struct phy_device *phydev)
+static int at803x_smarteee_config(struct phy_device *phydev, bool enable,
+ u32 tx_lpi_timer_us)
{
struct at803x_priv *priv = phydev->priv;
+ u64 tx_lpi_timer_raw;
+ u64 tx_lpi_timer_ns;
u16 mask = 0, val = 0;
int ret;

- if (priv->flags & AT803X_DISABLE_SMARTEEE)
+ if (priv->flags & AT803X_DISABLE_SMARTEEE || !enable)
return phy_modify_mmd(phydev, MDIO_MMD_PCS,
AT803X_MMD3_SMARTEEE_CTL3,
AT803X_MMD3_SMARTEEE_CTL3_LPI_EN, 0);

+ if (tx_lpi_timer_us > AT803X_MMD3_SMARTEEE_LPI_TIME_MAX_US) {
+ phydev_err(phydev, "Max LPI timer is %lu microsecs\n",
+ AT803X_MMD3_SMARTEEE_LPI_TIME_MAX_US);
+ return -EINVAL;
+ }
+
if (priv->smarteee_lpi_tw_1g) {
mask |= 0xff00;
val |= priv->smarteee_lpi_tw_1g << 8;
@@ -978,9 +997,27 @@ static int at803x_smarteee_config(struct phy_device *phydev)
if (ret)
return ret;

+ tx_lpi_timer_ns = tx_lpi_timer_us * NSEC_PER_USEC;
+ tx_lpi_timer_raw =
+ DIV_ROUND_CLOSEST_ULL(tx_lpi_timer_ns,
+ AT803X_MMD3_SMARTEEE_LPI_TIME_RESOL_NS);
+ val = FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_LOW,
+ FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_15_0,
+ tx_lpi_timer_raw));
+
+ ret = phy_write_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL2,
+ val);
+ if (ret)
+ return ret;
+
+ val = AT803X_MMD3_SMARTEEE_CTL3_LPI_EN |
+ FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH,
+ FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_23_16,
+ tx_lpi_timer_raw));
+
return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3,
- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN,
- AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN |
+ AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH, val);
}

static int at803x_clk_out_config(struct phy_device *phydev)
@@ -1067,7 +1104,8 @@ static int at803x_config_init(struct phy_device *phydev)
if (ret < 0)
return ret;

- ret = at803x_smarteee_config(phydev);
+ ret = at803x_smarteee_config(phydev, true,
+ AT803X_MMD3_SMARTEEE_LPI_TIME_DEF_US);
if (ret < 0)
return ret;

@@ -1612,6 +1650,65 @@ static int at803x_cable_test_start(struct phy_device *phydev)
return 0;
}

+static int at803x_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+ struct at803x_priv *priv = phydev->priv;
+ u32 tx_timer_raw;
+ u64 tx_timer_ns;
+ int ret;
+
+ /* If SmartEEE is not enabled, it is expected that tx_lpi_* fields
+ * are processed by the MAC driver.
+ */
+ if (priv->flags & AT803X_DISABLE_SMARTEEE)
+ return genphy_c45_ethtool_get_eee(phydev, data);
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_MMD3_SMARTEEE_CTL2);
+ tx_timer_raw = FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_15_0,
+ FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_LOW,
+ ret));
+ if (ret < 0)
+ return ret;
+
+ ret = phy_read_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_MMD3_SMARTEEE_CTL3);
+ if (ret < 0)
+ return ret;
+
+ tx_timer_raw |= FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_23_16,
+ FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH,
+ ret));
+ tx_timer_ns = tx_timer_raw * AT803X_MMD3_SMARTEEE_LPI_TIME_RESOL_NS;
+ data->tx_lpi_timer = DIV_ROUND_CLOSEST_ULL(tx_timer_ns, NSEC_PER_USEC);
+
+ data->tx_lpi_enabled = !!(ret & AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+
+ return genphy_c45_ethtool_get_eee(phydev, data);
+}
+
+static int at803x_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
+{
+ struct at803x_priv *priv = phydev->priv;
+ int ret;
+
+ /* If SmartEEE is not enabled, it is expected that tx_lpi_* fields
+ * are processed by the MAC driver.
+ */
+ if (priv->flags & AT803X_DISABLE_SMARTEEE)
+ return genphy_c45_ethtool_set_eee(phydev, data);
+
+ /* Changing Tx LPI on/off or Tx LPI timer settings
+ * do not require link reset.
+ */
+ ret = at803x_smarteee_config(phydev, data->tx_lpi_enabled,
+ data->tx_lpi_timer);
+ if (ret)
+ return ret;
+
+ return genphy_c45_ethtool_set_eee(phydev, data);
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2038,6 +2135,8 @@ static struct phy_driver at803x_driver[] = {
.set_tunable = at803x_set_tunable,
.cable_test_start = at803x_cable_test_start,
.cable_test_get_status = at803x_cable_test_get_status,
+ .get_eee = at803x_get_eee,
+ .set_eee = at803x_set_eee,
}, {
/* Qualcomm Atheros AR8030 */
.phy_id = ATH8030_PHY_ID,
--
2.30.2


2023-02-06 13:51:55

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 15/23] net: phy: add phy_has_smarteee() helper

Add helper to identify PHYs with SmartEEE support.

Signed-off-by: Oleksij Rempel <[email protected]>
---
include/linux/phy.h | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/include/linux/phy.h b/include/linux/phy.h
index 7b50cf099b2d..2378b81321df 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1407,6 +1407,15 @@ static inline bool phy_polling_mode(struct phy_device *phydev)
return phydev->irq == PHY_POLL;
}

+/**
+ * phy_has_rxtstamp - Tests whether a PHY supports SmartEEE.
+ * @phydev: the phy_device struct
+ */
+static inline bool phy_has_smarteee(struct phy_device *phydev)
+{
+ return phydev && phydev->drv && !!(phydev->drv->flags & PHY_SMART_EEE);
+}
+
/**
* phy_has_hwtstamp - Tests whether a PHY time stamp configuration.
* @phydev: the phy_device struct
--
2.30.2


2023-02-06 13:52:03

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 16/23] net: fec: add support for PHYs with SmartEEE support

Ethernet controller in i.MX6*/i.MX7* series do not provide EEE support.
But this chips are used sometimes in combinations with SmartEEE capable
PHYs.
So, instead of aborting get/set_eee access on MACs without EEE support,
ask PHY if it is able to do the EEE job by using SmartEEE.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/ethernet/freescale/fec_main.c | 22 ++++++++++++++++++----
1 file changed, 18 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index c73e25f8995e..00f3703db69d 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3102,8 +3102,15 @@ fec_enet_get_eee(struct net_device *ndev, struct ethtool_eee *edata)
struct fec_enet_private *fep = netdev_priv(ndev);
struct ethtool_eee *p = &fep->eee;

- if (!(fep->quirks & FEC_QUIRK_HAS_EEE))
- return -EOPNOTSUPP;
+ if (!(fep->quirks & FEC_QUIRK_HAS_EEE)) {
+ if (!netif_running(ndev))
+ return -ENETDOWN;
+
+ if (!phy_has_smarteee(ndev->phydev))
+ return -EOPNOTSUPP;
+
+ return phy_ethtool_get_eee(ndev->phydev, edata);
+ }

if (!netif_running(ndev))
return -ENETDOWN;
@@ -3123,8 +3130,15 @@ fec_enet_set_eee(struct net_device *ndev, struct ethtool_eee *edata)
struct ethtool_eee *p = &fep->eee;
int ret = 0;

- if (!(fep->quirks & FEC_QUIRK_HAS_EEE))
- return -EOPNOTSUPP;
+ if (!(fep->quirks & FEC_QUIRK_HAS_EEE)) {
+ if (!netif_running(ndev))
+ return -ENETDOWN;
+
+ if (!phy_has_smarteee(ndev->phydev))
+ return -EOPNOTSUPP;
+
+ return phy_ethtool_set_eee(ndev->phydev, edata);
+ }

if (!netif_running(ndev))
return -ENETDOWN;
--
2.30.2


2023-02-06 13:52:07

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 23/23] net: mdio: drop EEE ethtool helpers in favor to linkmode variants

IEEE 802.3 specification provides more EEE capable link modes as this
helpers will be able to handle. So, remove them in favor of:
mii_eee_cap1_mod_linkmode_t
linkmode_to_mii_eee_cap1_t

Signed-off-by: Oleksij Rempel <[email protected]>
---
include/linux/mdio.h | 83 --------------------------------------------
1 file changed, 83 deletions(-)

diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 6776eea770fa..082a9115b5e2 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -205,89 +205,6 @@ mdio45_ethtool_ksettings_get(const struct mdio_if_info *mdio,
extern int mdio_mii_ioctl(const struct mdio_if_info *mdio,
struct mii_ioctl_data *mii_data, int cmd);

-/**
- * mmd_eee_cap_to_ethtool_sup_t
- * @eee_cap: value of the MMD EEE Capability register
- *
- * A small helper function that translates MMD EEE Capability (3.20) bits
- * to ethtool supported settings.
- */
-static inline u32 mmd_eee_cap_to_ethtool_sup_t(u16 eee_cap)
-{
- u32 supported = 0;
-
- if (eee_cap & MDIO_EEE_100TX)
- supported |= SUPPORTED_100baseT_Full;
- if (eee_cap & MDIO_EEE_1000T)
- supported |= SUPPORTED_1000baseT_Full;
- if (eee_cap & MDIO_EEE_10GT)
- supported |= SUPPORTED_10000baseT_Full;
- if (eee_cap & MDIO_EEE_1000KX)
- supported |= SUPPORTED_1000baseKX_Full;
- if (eee_cap & MDIO_EEE_10GKX4)
- supported |= SUPPORTED_10000baseKX4_Full;
- if (eee_cap & MDIO_EEE_10GKR)
- supported |= SUPPORTED_10000baseKR_Full;
-
- return supported;
-}
-
-/**
- * mmd_eee_adv_to_ethtool_adv_t
- * @eee_adv: value of the MMD EEE Advertisement/Link Partner Ability registers
- *
- * A small helper function that translates the MMD EEE Advertisment (7.60)
- * and MMD EEE Link Partner Ability (7.61) bits to ethtool advertisement
- * settings.
- */
-static inline u32 mmd_eee_adv_to_ethtool_adv_t(u16 eee_adv)
-{
- u32 adv = 0;
-
- if (eee_adv & MDIO_EEE_100TX)
- adv |= ADVERTISED_100baseT_Full;
- if (eee_adv & MDIO_EEE_1000T)
- adv |= ADVERTISED_1000baseT_Full;
- if (eee_adv & MDIO_EEE_10GT)
- adv |= ADVERTISED_10000baseT_Full;
- if (eee_adv & MDIO_EEE_1000KX)
- adv |= ADVERTISED_1000baseKX_Full;
- if (eee_adv & MDIO_EEE_10GKX4)
- adv |= ADVERTISED_10000baseKX4_Full;
- if (eee_adv & MDIO_EEE_10GKR)
- adv |= ADVERTISED_10000baseKR_Full;
-
- return adv;
-}
-
-/**
- * ethtool_adv_to_mmd_eee_adv_t
- * @adv: the ethtool advertisement settings
- *
- * A small helper function that translates ethtool advertisement settings
- * to EEE advertisements for the MMD EEE Advertisement (7.60) and
- * MMD EEE Link Partner Ability (7.61) registers.
- */
-static inline u16 ethtool_adv_to_mmd_eee_adv_t(u32 adv)
-{
- u16 reg = 0;
-
- if (adv & ADVERTISED_100baseT_Full)
- reg |= MDIO_EEE_100TX;
- if (adv & ADVERTISED_1000baseT_Full)
- reg |= MDIO_EEE_1000T;
- if (adv & ADVERTISED_10000baseT_Full)
- reg |= MDIO_EEE_10GT;
- if (adv & ADVERTISED_1000baseKX_Full)
- reg |= MDIO_EEE_1000KX;
- if (adv & ADVERTISED_10000baseKX4_Full)
- reg |= MDIO_EEE_10GKX4;
- if (adv & ADVERTISED_10000baseKR_Full)
- reg |= MDIO_EEE_10GKR;
-
- return reg;
-}
-
/**
* linkmode_adv_to_mii_10gbt_adv_t
* @advertising: the linkmode advertisement settings
--
2.30.2


2023-02-06 13:52:09

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 18/23] igb: replace EEE ethtool helpers to linkmode variants

Replace EEE ethtool helpers with linkmode variants. This will
reduce similar code snippets and prepare ethtool EEE interface to linkmode
migration.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/ethernet/intel/igb/igb_ethtool.c | 23 +++++++++++++++-----
1 file changed, 17 insertions(+), 6 deletions(-)

diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 7d60da1b7bf4..5aa4c28fc447 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -3026,6 +3026,8 @@ static int igb_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
{
struct igb_adapter *adapter = netdev_priv(netdev);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lp) = {};
struct e1000_hw *hw = &adapter->hw;
u32 ret_val;
u16 phy_data;
@@ -3036,9 +3038,12 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)

edata->supported = (SUPPORTED_1000baseT_Full |
SUPPORTED_100baseT_Full);
- if (!hw->dev_spec._82575.eee_disable)
- edata->advertised =
- mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert);
+
+ if (!hw->dev_spec._82575.eee_disable) {
+ mii_eee_cap1_mod_linkmode_t(adv, adapter->eee_advert);
+ ethtool_convert_link_mode_to_legacy_u32(&edata->advertised,
+ adv);
+ }

/* The IPCNFG and EEER registers are not supported on I354. */
if (hw->mac.type == e1000_i354) {
@@ -3064,7 +3069,9 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
if (ret_val)
return -ENODATA;

- edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
+ mii_eee_cap1_mod_linkmode_t(lp, phy_data);
+ ethtool_convert_link_mode_to_legacy_u32(&edata->lp_advertised,
+ lp);
break;
case e1000_i354:
case e1000_i210:
@@ -3075,7 +3082,9 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
if (ret_val)
return -ENODATA;

- edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
+ mii_eee_cap1_mod_linkmode_t(lp, phy_data);
+ ethtool_convert_link_mode_to_legacy_u32(&edata->lp_advertised,
+ lp);

break;
default:
@@ -3105,6 +3114,7 @@ static int igb_set_eee(struct net_device *netdev,
struct ethtool_eee *edata)
{
struct igb_adapter *adapter = netdev_priv(netdev);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
struct e1000_hw *hw = &adapter->hw;
struct ethtool_eee eee_curr;
bool adv1g_eee = true, adv100m_eee = true;
@@ -3149,7 +3159,8 @@ static int igb_set_eee(struct net_device *netdev,
return -EINVAL;
}

- adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
+ adv[0] = edata->advertised;
+ adapter->eee_advert = linkmode_to_mii_eee_cap1_t(adv);
if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) {
hw->dev_spec._82575.eee_disable = !edata->eee_enabled;
adapter->flags |= IGB_FLAG_EEE;
--
2.30.2


2023-02-06 13:52:30

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 01/23] net: dsa: microchip: enable EEE support

Some of KSZ9477 family switches provides EEE support. To enable it, we
just need to register set_mac_eee/set_mac_eee handlers and validate
supported chip version and port.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/dsa/microchip/ksz_common.c | 65 ++++++++++++++++++++++++++
1 file changed, 65 insertions(+)

diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 46becc0382d6..0a2d78253d17 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2673,6 +2673,69 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
return -EOPNOTSUPP;
}

+static int ksz_validate_eee(struct dsa_switch *ds, int port)
+{
+ struct ksz_device *dev = ds->priv;
+
+ if (!dev->info->internal_phy[port])
+ return -EOPNOTSUPP;
+
+ switch (dev->chip_id) {
+ case KSZ8563_CHIP_ID:
+ case KSZ9477_CHIP_ID:
+ case KSZ9563_CHIP_ID:
+ case KSZ9567_CHIP_ID:
+ case KSZ9893_CHIP_ID:
+ case KSZ9896_CHIP_ID:
+ case KSZ9897_CHIP_ID:
+ return 0;
+ }
+
+ return -EOPNOTSUPP;
+}
+
+static int ksz_get_mac_eee(struct dsa_switch *ds, int port,
+ struct ethtool_eee *e)
+{
+ int ret;
+
+ ret = ksz_validate_eee(ds, port);
+ if (ret)
+ return ret;
+
+ /* There is no documented control of Tx LPI configuration. */
+ e->tx_lpi_enabled = true;
+ /* There is no documented control of Tx LPI timer. According to tests
+ * Tx LPI timer seems to be set by default to minimal value.
+ */
+ e->tx_lpi_timer = 0;
+
+ return 0;
+}
+
+static int ksz_set_mac_eee(struct dsa_switch *ds, int port,
+ struct ethtool_eee *e)
+{
+ struct ksz_device *dev = ds->priv;
+ int ret;
+
+ ret = ksz_validate_eee(ds, port);
+ if (ret)
+ return ret;
+
+ if (!e->tx_lpi_enabled) {
+ dev_err(dev->dev, "Disabling EEE Tx LPI is not supported\n");
+ return -EINVAL;
+ }
+
+ if (e->tx_lpi_timer) {
+ dev_err(dev->dev, "Setting EEE Tx LPI timer is not supported\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static void ksz_set_xmii(struct ksz_device *dev, int port,
phy_interface_t interface)
{
@@ -3130,6 +3193,8 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.port_txtstamp = ksz_port_txtstamp,
.port_rxtstamp = ksz_port_rxtstamp,
.port_setup_tc = ksz_setup_tc,
+ .get_mac_eee = ksz_get_mac_eee,
+ .set_mac_eee = ksz_set_mac_eee,
};

struct ksz_device *ksz_switch_alloc(struct device *base, void *priv)
--
2.30.2


2023-02-06 13:52:36

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 02/23] 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]>
---
drivers/net/phy/phy-c45.c | 70 ++++++++++++++++++++++++++++++++++++
drivers/net/phy/phy_device.c | 16 +++++++++
include/linux/mdio.h | 26 ++++++++++++++
include/linux/phy.h | 5 +++
4 files changed, 117 insertions(+)

diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 9f9565a4819d..3ae642d3ae14 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -661,6 +661,76 @@ int genphy_c45_read_mdix(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);

+/**
+ * genphy_c45_read_eee_cap1 - read supported EEE link modes from register 3.20
+ * @phydev: target phy_device struct
+ */
+static int genphy_c45_read_eee_cap1(struct phy_device *phydev)
+{
+ int val;
+
+ /* IEEE 802.3-2018 45.2.3.10 EEE control and capability 1
+ * (Register 3.20)
+ */
+ val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
+ if (val < 0)
+ return val;
+
+ /* The 802.3 2018 standard says the top 2 bits are reserved and should
+ * read as 0. Also, it seems unlikely anybody will build a PHY which
+ * supports 100GBASE-R deep sleep all the way down to 100BASE-TX EEE.
+ * If MDIO_PCS_EEE_ABLE is 0xffff assume EEE is not supported.
+ */
+ if (val == GENMASK(15, 0))
+ return 0;
+
+ mii_eee_cap1_mod_linkmode_t(phydev->supported_eee, val);
+
+ /* Some buggy devices indicate EEE link modes in MDIO_PCS_EEE_ABLE
+ * which they don't support as indicated by BMSR, ESTATUS etc.
+ */
+ linkmode_and(phydev->supported_eee, phydev->supported_eee,
+ phydev->supported);
+
+ return 0;
+}
+
+/**
+ * genphy_c45_read_eee_abilities - read supported EEE link modes
+ * @phydev: target phy_device struct
+ */
+int genphy_c45_read_eee_abilities(struct phy_device *phydev)
+{
+ int val;
+
+ /* There is not indicator whether optional register
+ * "EEE control and capability 1" (3.20) is supported. Read it only
+ * on devices with appropriate linkmodes.
+ */
+ if (linkmode_intersects(phydev->supported, PHY_EEE_CAP1_FEATURES)) {
+ val = genphy_c45_read_eee_cap1(phydev);
+ if (val)
+ return val;
+ }
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
+ phydev->supported)) {
+ /* IEEE 802.3cg-2019 45.2.1.186b 10BASE-T1L PMA status register
+ * (Register 1.2295)
+ */
+ val = phy_read_mmd(phydev, MDIO_MMD_PMAPMD, MDIO_PMA_10T1L_STAT);
+ if (val < 0)
+ return val;
+
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
+ phydev->supported_eee,
+ val & MDIO_PMA_10T1L_STAT_EEE);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(genphy_c45_read_eee_abilities);
+
/**
* genphy_c45_pma_read_abilities - read supported link modes from PMA
* @phydev: target phy_device struct
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index a3917c7acbd3..66a4e62009bb 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -132,6 +132,18 @@ static const int phy_10gbit_full_features_array[] = {
ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
};

+static const int phy_eee_cap1_features_array[] = {
+ ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+ ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+};
+
+__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init;
+EXPORT_SYMBOL_GPL(phy_eee_cap1_features);
+
static void features_init(void)
{
/* 10/100 half/full*/
@@ -213,6 +225,10 @@ static void features_init(void)
linkmode_set_bit_array(phy_10gbit_fec_features_array,
ARRAY_SIZE(phy_10gbit_fec_features_array),
phy_10gbit_fec_features);
+ linkmode_set_bit_array(phy_eee_cap1_features_array,
+ ARRAY_SIZE(phy_eee_cap1_features_array),
+ phy_eee_cap1_features);
+
}

void phy_device_free(struct phy_device *phydev)
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index c0da30d63b1d..1549e73d9a56 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -402,6 +402,32 @@ static inline u32 linkmode_adv_to_mii_t1_adv_m_t(unsigned long *advertising)
return result;
}

+/**
+ * mii_eee_cap1_mod_linkmode_t
+ * @adv: target the linkmode advertisement settings
+ * @val: register value
+ *
+ * A function that translates value of following registers to the linkmode:
+ * IEEE 802.3-2018 45.2.3.10 "EEE control and capability 1" register (3.20)
+ * IEEE 802.3-2018 45.2.7.13 "EEE advertisement 1" register (7.60)
+ * IEEE 802.3-2018 45.2.7.14 "EEE "link partner ability 1 register (7.61)
+ */
+static inline void mii_eee_cap1_mod_linkmode_t(unsigned long *adv, u32 val)
+{
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
+ adv, val & MDIO_EEE_100TX);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
+ adv, val & MDIO_EEE_1000T);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
+ adv, val & MDIO_EEE_10GT);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
+ adv, val & MDIO_EEE_1000KX);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
+ adv, val & MDIO_EEE_10GKX4);
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
+ adv, val & MDIO_EEE_10GKR);
+}
+
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/linux/phy.h b/include/linux/phy.h
index fbeba4fee8d4..fc4d630bb1da 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -52,6 +52,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
+extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_eee_cap1_features) __ro_after_init;

#define PHY_BASIC_FEATURES ((unsigned long *)&phy_basic_features)
#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
#define PHY_10GBIT_FEATURES ((unsigned long *)&phy_10gbit_features)
#define PHY_10GBIT_FEC_FEATURES ((unsigned long *)&phy_10gbit_fec_features)
#define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features)
+#define PHY_EEE_CAP1_FEATURES ((unsigned long *)&phy_eee_cap1_features)

extern const int phy_basic_ports_array[3];
extern const int phy_fibre_port_array[1];
@@ -676,6 +678,8 @@ struct phy_device {
__ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
/* used with phy_speed_down */
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
+ /* used for eee validation */
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_eee);

/* Host supported PHY interface types. Should be ignored if empty. */
DECLARE_PHY_INTERFACE_MASK(host_interfaces);
@@ -1737,6 +1741,7 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev);
int genphy_c45_an_disable_aneg(struct phy_device *phydev);
int genphy_c45_read_mdix(struct phy_device *phydev);
int genphy_c45_pma_read_abilities(struct phy_device *phydev);
+int genphy_c45_read_eee_abilities(struct phy_device *phydev);
int genphy_c45_pma_baset1_read_master_slave(struct phy_device *phydev);
int genphy_c45_read_status(struct phy_device *phydev);
int genphy_c45_baset1_read_status(struct phy_device *phydev);
--
2.30.2


2023-02-06 13:52:38

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 19/23] igc: replace EEE ethtool helpers to linkmode variants

Replace EEE ethtool helpers with linkmode variants. This will
reduce similar code snippets and prepare ethtool EEE interface to linkmode
migration.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/ethernet/intel/igc/igc_ethtool.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/intel/igc/igc_ethtool.c b/drivers/net/ethernet/intel/igc/igc_ethtool.c
index 5a26a7805ef8..012406f2e8cc 100644
--- a/drivers/net/ethernet/intel/igc/igc_ethtool.c
+++ b/drivers/net/ethernet/intel/igc/igc_ethtool.c
@@ -1582,12 +1582,14 @@ static int igc_ethtool_get_eee(struct net_device *netdev,
struct ethtool_eee *edata)
{
struct igc_adapter *adapter = netdev_priv(netdev);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
struct igc_hw *hw = &adapter->hw;
u32 eeer;

- if (hw->dev_spec._base.eee_enable)
- edata->advertised =
- mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert);
+ if (hw->dev_spec._base.eee_enable) {
+ mii_eee_cap1_mod_linkmode_t(adv, adapter->eee_advert);
+ ethtool_convert_link_mode_to_legacy_u32(&edata->advertised, adv);
+ }

*edata = adapter->eee;
edata->supported = SUPPORTED_Autoneg;
@@ -1623,6 +1625,7 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
struct ethtool_eee *edata)
{
struct igc_adapter *adapter = netdev_priv(netdev);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
struct igc_hw *hw = &adapter->hw;
struct ethtool_eee eee_curr;
s32 ret_val;
@@ -1655,7 +1658,8 @@ static int igc_ethtool_set_eee(struct net_device *netdev,
return -EINVAL;
}

- adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
+ adv[0] = edata->advertised;
+ adapter->eee_advert = linkmode_to_mii_eee_cap1_t(adv);
if (hw->dev_spec._base.eee_enable != edata->eee_enabled) {
hw->dev_spec._base.eee_enable = edata->eee_enabled;
adapter->flags |= IGC_FLAG_EEE;
--
2.30.2


2023-02-06 13:52:40

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 05/23] net: phy: add genphy_c45_ethtool_get/set_eee() support

Add replacement for phy_ethtool_get/set_eee() functions.

Current phy_ethtool_get/set_eee() implementation is great and it is
possible to make it even better:
- this functionality is for devices implementing parts of IEEE 802.3
specification beyond Clause 22. The better place for this code is
phy-c45.c
- currently it is able to do read/write operations on PHYs with
different abilities to not existing registers. It is better to
use stored supported_eee abilities to avoid false read/write
operations.
- the eee_active detection will provide wrong results on not supported
link modes. It is better to validate speed/duplex properties against
supported EEE link modes.
- it is able to support only limited amount of link modes. We have more
EEE link modes...

By refactoring this code I address most of this point except of the last
one. Adding additional EEE link modes will need more work.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/phy-c45.c | 235 ++++++++++++++++++++++++++++++++++++++
include/linux/mdio.h | 58 ++++++++++
include/linux/phy.h | 7 ++
include/uapi/linux/mdio.h | 8 ++
4 files changed, 308 insertions(+)

diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 3ae642d3ae14..38361df1e669 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -661,6 +661,129 @@ int genphy_c45_read_mdix(struct phy_device *phydev)
}
EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);

+/**
+ * genphy_c45_write_eee_adv - write advertised EEE link modes
+ * @phydev: target phy_device struct
+ * @adv: the linkmode advertisement settings
+ */
+int genphy_c45_write_eee_adv(struct phy_device *phydev, unsigned long *adv)
+{
+ int val, changed;
+
+ if (linkmode_intersects(phydev->supported, PHY_EEE_CAP1_FEATURES)) {
+ val = linkmode_to_mii_eee_cap1_t(adv);
+
+ /* In eee_broken_modes are stored MDIO_AN_EEE_ADV specific raw
+ * register values.
+ */
+ val &= ~phydev->eee_broken_modes;
+
+ /* IEEE 802.3-2018 45.2.7.13 EEE advertisement 1
+ * (Register 7.60)
+ */
+ val = phy_modify_mmd_changed(phydev, MDIO_MMD_AN,
+ MDIO_AN_EEE_ADV,
+ MDIO_EEE_100TX | MDIO_EEE_1000T |
+ MDIO_EEE_10GT | MDIO_EEE_1000KX |
+ MDIO_EEE_10GKX4 | MDIO_EEE_10GKR,
+ val);
+ if (val < 0)
+ return val;
+ if (val > 0)
+ changed = 1;
+ }
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
+ phydev->supported_eee)) {
+ val = linkmode_adv_to_mii_10base_t1_t(adv);
+ /* IEEE 802.3cg-2019 45.2.7.25 10BASE-T1 AN control register
+ * (Register 7.526)
+ */
+ val = phy_modify_mmd_changed(phydev, MDIO_MMD_AN,
+ MDIO_AN_10BT1_AN_CTRL,
+ MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L,
+ val);
+ if (val < 0)
+ return val;
+ if (val > 0)
+ changed = 1;
+ }
+
+ return changed;
+}
+
+/**
+ * genphy_c45_read_eee_adv - read advertised EEE link modes
+ * @phydev: target phy_device struct
+ * @adv: the linkmode advertisement status
+ */
+static int genphy_c45_read_eee_adv(struct phy_device *phydev,
+ unsigned long *adv)
+{
+ int val;
+
+ if (linkmode_intersects(phydev->supported, PHY_EEE_CAP1_FEATURES)) {
+ /* IEEE 802.3-2018 45.2.7.13 EEE advertisement 1
+ * (Register 7.60)
+ */
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
+ if (val < 0)
+ return val;
+
+ mii_eee_cap1_mod_linkmode_t(adv, val);
+ }
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
+ phydev->supported_eee)) {
+ /* IEEE 802.3cg-2019 45.2.7.25 10BASE-T1 AN control register
+ * (Register 7.526)
+ */
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10BT1_AN_CTRL);
+ if (val < 0)
+ return val;
+
+ mii_10base_t1_adv_mod_linkmode_t(adv, val);
+ }
+
+ return 0;
+}
+
+/**
+ * genphy_c45_read_eee_lpa - read advertised LP EEE link modes
+ * @phydev: target phy_device struct
+ * @lpa: the linkmode LP advertisement status
+ */
+static int genphy_c45_read_eee_lpa(struct phy_device *phydev,
+ unsigned long *lpa)
+{
+ int val;
+
+ if (linkmode_intersects(phydev->supported, PHY_EEE_CAP1_FEATURES)) {
+ /* IEEE 802.3-2018 45.2.7.14 EEE link partner ability 1
+ * (Register 7.61)
+ */
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
+ if (val < 0)
+ return val;
+
+ mii_eee_cap1_mod_linkmode_t(lpa, val);
+ }
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
+ phydev->supported_eee)) {
+ /* IEEE 802.3cg-2019 45.2.7.26 10BASE-T1 AN status register
+ * (Register 7.527)
+ */
+ val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_10BT1_AN_STAT);
+ if (val < 0)
+ return val;
+
+ mii_10base_t1_adv_mod_linkmode_t(lpa, val);
+ }
+
+ return 0;
+}
+
/**
* genphy_c45_read_eee_cap1 - read supported EEE link modes from register 3.20
* @phydev: target phy_device struct
@@ -1194,6 +1317,118 @@ int genphy_c45_plca_get_status(struct phy_device *phydev,
}
EXPORT_SYMBOL_GPL(genphy_c45_plca_get_status);

+/**
+ * genphy_c45_eee_is_active - get EEE supported and status
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it reports the possible state of EEE functionality.
+ */
+int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned long *adv,
+ unsigned long *lp, bool *is_enabled)
+{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_lp) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
+ bool eee_enabled, eee_active;
+ int ret;
+
+ ret = genphy_c45_read_eee_adv(phydev, tmp_adv);
+ if (ret)
+ return ret;
+
+ ret = genphy_c45_read_eee_lpa(phydev, tmp_lp);
+ if (ret)
+ return ret;
+
+ eee_enabled = !linkmode_empty(tmp_adv);
+ linkmode_and(common, tmp_adv, tmp_lp);
+ if (eee_enabled && !linkmode_empty(common))
+ eee_active = phy_check_valid(phydev->speed, phydev->duplex,
+ common);
+ else
+ eee_active = false;
+
+ if (adv)
+ linkmode_copy(adv, tmp_adv);
+ if (lp)
+ linkmode_copy(lp, tmp_lp);
+ if (is_enabled)
+ *is_enabled = eee_enabled;
+
+ return eee_active;
+}
+EXPORT_SYMBOL(genphy_c45_eee_is_active);
+
+/**
+ * genphy_c45_ethtool_get_eee - get EEE supported and status
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it reports the Supported/Advertisement/LP Advertisement
+ * capabilities.
+ */
+int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
+ struct ethtool_eee *data)
+{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lp) = {};
+ bool overflow = false, is_enabled;
+ int ret;
+
+ ret = genphy_c45_eee_is_active(phydev, adv, lp, &is_enabled);
+ if (ret < 0)
+ return ret;
+
+ data->eee_enabled = is_enabled;
+ data->eee_active = ret;
+
+ if (!ethtool_convert_link_mode_to_legacy_u32(&data->supported,
+ phydev->supported_eee))
+ overflow = true;
+ if (!ethtool_convert_link_mode_to_legacy_u32(&data->advertised, adv))
+ overflow = true;
+ if (!ethtool_convert_link_mode_to_legacy_u32(&data->lp_advertised, lp))
+ overflow = true;
+
+ if (overflow)
+ phydev_warn(phydev, "Not all supported or advertised EEE link modes were passed to the user space\n");
+
+ return 0;
+}
+EXPORT_SYMBOL(genphy_c45_ethtool_get_eee);
+
+/**
+ * genphy_c45_ethtool_set_eee - get EEE supported and status
+ * @phydev: target phy_device struct
+ * @data: ethtool_eee data
+ *
+ * Description: it reportes the Supported/Advertisement/LP Advertisement
+ * capabilities.
+ */
+int genphy_c45_ethtool_set_eee(struct phy_device *phydev,
+ struct ethtool_eee *data)
+{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
+ int ret;
+
+ if (data->eee_enabled) {
+ if (data->advertised)
+ adv[0] = data->advertised;
+ else
+ linkmode_copy(adv, phydev->supported_eee);
+ }
+
+ ret = genphy_c45_write_eee_adv(phydev, adv);
+ if (ret < 0)
+ return ret;
+ if (ret > 0)
+ return phy_restart_aneg(phydev);
+
+ return 0;
+}
+EXPORT_SYMBOL(genphy_c45_ethtool_set_eee);
+
struct phy_driver genphy_c45_driver = {
.phy_id = 0xffffffff,
.phy_id_mask = 0xffffffff,
diff --git a/include/linux/mdio.h b/include/linux/mdio.h
index 1549e73d9a56..6776eea770fa 100644
--- a/include/linux/mdio.h
+++ b/include/linux/mdio.h
@@ -428,6 +428,64 @@ static inline void mii_eee_cap1_mod_linkmode_t(unsigned long *adv, u32 val)
adv, val & MDIO_EEE_10GKR);
}

+/**
+ * mii_eee_cap1_mod_linkmode_t
+ * @adv: the linkmode advertisement settings
+ *
+ * A function that translates linkmode to value for IEEE 802.3-2018 45.2.7.13
+ * "EEE advertisement 1" register (7.60)
+ */
+static inline u32 linkmode_to_mii_eee_cap1_t(unsigned long *adv)
+{
+ u32 result = 0;
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, adv))
+ result |= MDIO_EEE_100TX;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, adv))
+ result |= MDIO_EEE_1000T;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, adv))
+ result |= MDIO_EEE_10GT;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, adv))
+ result |= MDIO_EEE_1000KX;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, adv))
+ result |= MDIO_EEE_10GKX4;
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, adv))
+ result |= MDIO_EEE_10GKR;
+
+ return result;
+}
+
+/**
+ * mii_10base_t1_adv_mod_linkmode_t
+ * @adv: linkmode advertisement settings
+ * @val: register value
+ *
+ * A function that translates IEEE 802.3cg-2019 45.2.7.26 "10BASE-T1 AN status"
+ * register (7.527) value to the linkmode.
+ */
+static inline void mii_10base_t1_adv_mod_linkmode_t(unsigned long *adv, u16 val)
+{
+ linkmode_mod_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT,
+ adv, val & MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L);
+}
+
+/**
+ * linkmode_adv_to_mii_10base_t1_t
+ * @adv: linkmode advertisement settings
+ *
+ * A function that translates the linkmode to IEEE 802.3cg-2019 45.2.7.25
+ * "10BASE-T1 AN control" register (7.526) value.
+ */
+static inline u32 linkmode_adv_to_mii_10base_t1_t(unsigned long *adv)
+{
+ u32 result = 0;
+
+ if (linkmode_test_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, adv))
+ result |= MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L;
+
+ return result;
+}
+
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/linux/phy.h b/include/linux/phy.h
index d6b078dd61dd..ef0e3212f68e 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1757,6 +1757,13 @@ int genphy_c45_plca_set_cfg(struct phy_device *phydev,
const struct phy_plca_cfg *plca_cfg);
int genphy_c45_plca_get_status(struct phy_device *phydev,
struct phy_plca_status *plca_st);
+int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned long *adv,
+ unsigned long *lp, bool *is_enabled);
+int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
+ struct ethtool_eee *data);
+int genphy_c45_ethtool_set_eee(struct phy_device *phydev,
+ struct ethtool_eee *data);
+int genphy_c45_write_eee_adv(struct phy_device *phydev, unsigned long *adv);

/* Generic C45 PHY driver */
extern struct phy_driver genphy_c45_driver;
diff --git a/include/uapi/linux/mdio.h b/include/uapi/linux/mdio.h
index 75b7257a51e1..256b463e47a6 100644
--- a/include/uapi/linux/mdio.h
+++ b/include/uapi/linux/mdio.h
@@ -79,6 +79,8 @@
#define MDIO_AN_T1_LP_L 517 /* BASE-T1 AN LP Base Page ability register [15:0] */
#define MDIO_AN_T1_LP_M 518 /* BASE-T1 AN LP Base Page ability register [31:16] */
#define MDIO_AN_T1_LP_H 519 /* BASE-T1 AN LP Base Page ability register [47:32] */
+#define MDIO_AN_10BT1_AN_CTRL 526 /* 10BASE-T1 AN control register */
+#define MDIO_AN_10BT1_AN_STAT 527 /* 10BASE-T1 AN status register */
#define MDIO_PMA_PMD_BT1_CTRL 2100 /* BASE-T1 PMA/PMD control register */

/* LASI (Link Alarm Status Interrupt) registers, defined by XENPAK MSA. */
@@ -340,6 +342,12 @@
#define MDIO_AN_T1_LP_H_10L_TX_HI_REQ 0x1000 /* 10BASE-T1L High Level LP Transmit Request */
#define MDIO_AN_T1_LP_H_10L_TX_HI 0x2000 /* 10BASE-T1L High Level LP Transmit Ability */

+/* 10BASE-T1 AN control register */
+#define MDIO_AN_10BT1_AN_CTRL_ADV_EEE_T1L 0x4000 /* 10BASE-T1L EEE ability advertisement */
+
+/* 10BASE-T1 AN status register */
+#define MDIO_AN_10BT1_AN_STAT_LPA_EEE_T1L 0x4000 /* 10BASE-T1L LP EEE ability advertisement */
+
/* BASE-T1 PMA/PMD control register */
#define MDIO_PMA_PMD_BT1_CTRL_CFG_MST 0x4000 /* MASTER-SLAVE config value */

--
2.30.2


2023-02-06 13:52:56

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 14/23] net: phy: at803x: add PHY_SMART_EEE flag to AR8035

AR8035 is one of the PHYs with SmartEEE functionality. This flag will be
used by one of next patches on the i.MX FEC driver.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/at803x.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 5ab43eb63581..94dbec0a992c 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -2147,7 +2147,7 @@ static struct phy_driver at803x_driver[] = {
/* Qualcomm Atheros AR8035 */
PHY_ID_MATCH_EXACT(ATH8035_PHY_ID),
.name = "Qualcomm Atheros AR8035",
- .flags = PHY_POLL_CABLE_TEST,
+ .flags = PHY_POLL_CABLE_TEST | PHY_SMART_EEE,
.probe = at803x_probe,
.remove = at803x_remove,
.config_aneg = at803x_config_aneg,
--
2.30.2


2023-02-06 13:53:01

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 09/23] net: phy: start using genphy_c45_ethtool_get/set_eee()

All preparations are done. Now we can start using new functions and remove
the old code.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/phy.c | 60 ++-----------------------------------------
1 file changed, 2 insertions(+), 58 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 36533746630e..2f1041a7211e 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1517,33 +1517,10 @@ EXPORT_SYMBOL(phy_get_eee_err);
*/
int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
{
- int val;
-
if (!phydev->drv)
return -EIO;

- /* Get Supported EEE */
- val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
- if (val < 0)
- return val;
- data->supported = mmd_eee_cap_to_ethtool_sup_t(val);
-
- /* Get advertisement EEE */
- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
- if (val < 0)
- return val;
- data->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
- data->eee_enabled = !!data->advertised;
-
- /* Get LP advertisement EEE */
- val = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
- if (val < 0)
- return val;
- data->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
-
- data->eee_active = !!(data->advertised & data->lp_advertised);
-
- return 0;
+ return genphy_c45_ethtool_get_eee(phydev, data);
}
EXPORT_SYMBOL(phy_ethtool_get_eee);

@@ -1556,43 +1533,10 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
*/
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
{
- int cap, old_adv, adv = 0, ret;
-
if (!phydev->drv)
return -EIO;

- /* Get Supported EEE */
- cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
- if (cap < 0)
- return cap;
-
- old_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
- if (old_adv < 0)
- return old_adv;
-
- if (data->eee_enabled) {
- adv = !data->advertised ? cap :
- ethtool_adv_to_mmd_eee_adv_t(data->advertised) & cap;
- /* Mask prohibited EEE modes */
- adv &= ~phydev->eee_broken_modes;
- }
-
- if (old_adv != adv) {
- ret = phy_write_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV, adv);
- if (ret < 0)
- return ret;
-
- /* Restart autonegotiation so the new modes get sent to the
- * link partner.
- */
- if (phydev->autoneg == AUTONEG_ENABLE) {
- ret = phy_restart_aneg(phydev);
- if (ret < 0)
- return ret;
- }
- }
-
- return 0;
+ return genphy_c45_ethtool_set_eee(phydev, data);
}
EXPORT_SYMBOL(phy_ethtool_set_eee);

--
2.30.2


2023-02-06 13:53:05

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 20/23] tg3: replace EEE ethtool helpers to linkmode variants

Replace EEE ethtool helpers with linkmode variants. This will
reduce similar code snippets and prepare ethtool EEE interface to linkmode
migration.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/ethernet/broadcom/tg3.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 58747292521d..ba1913e88372 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -2339,6 +2339,8 @@ static void tg3_phy_apply_otp(struct tg3 *tp)

static void tg3_eee_pull_config(struct tg3 *tp, struct ethtool_eee *eee)
{
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lp) = {};
u32 val;
struct ethtool_eee *dest = &tp->eee;

@@ -2361,13 +2363,16 @@ static void tg3_eee_pull_config(struct tg3 *tp, struct ethtool_eee *eee)
/* Pull lp advertised settings */
if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE, &val))
return;
- dest->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(lp, val);
+ ethtool_convert_link_mode_to_legacy_u32(&dest->lp_advertised, lp);
+

/* Pull advertised and eee_enabled settings */
if (tg3_phy_cl45_read(tp, MDIO_MMD_AN, MDIO_AN_EEE_ADV, &val))
return;
dest->eee_enabled = !!val;
- dest->advertised = mmd_eee_adv_to_ethtool_adv_t(val);
+ mii_eee_cap1_mod_linkmode_t(adv, val);
+ ethtool_convert_link_mode_to_legacy_u32(&dest->advertised, adv);

/* Pull tx_lpi_enabled */
val = tr32(TG3_CPMU_EEE_MODE);
--
2.30.2


2023-02-06 13:53:08

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 17/23] e1000e: replace EEE ethtool helpers to linkmode variants

Replace EEE ethtool helpers with linkmode variants. This will
reduce similar code snippets and prepare ethtool EEE interface to linkmode
migration.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/ethernet/intel/e1000e/ethtool.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/intel/e1000e/ethtool.c b/drivers/net/ethernet/intel/e1000e/ethtool.c
index 721f86fd5802..13c728626068 100644
--- a/drivers/net/ethernet/intel/e1000e/ethtool.c
+++ b/drivers/net/ethernet/intel/e1000e/ethtool.c
@@ -2188,6 +2188,9 @@ static int e1000_get_rxnfc(struct net_device *netdev,
static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_able) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_adv) = {};
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(lm_lp) = {};
struct e1000_hw *hw = &adapter->hw;
u16 cap_addr, lpa_addr, pcs_stat_addr, phy_data;
u32 ret_val;
@@ -2222,16 +2225,19 @@ static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
ret_val = e1000_read_emi_reg_locked(hw, cap_addr, &phy_data);
if (ret_val)
goto release;
- edata->supported = mmd_eee_cap_to_ethtool_sup_t(phy_data);
+ mii_eee_cap1_mod_linkmode_t(lm_able, phy_data);
+ ethtool_convert_link_mode_to_legacy_u32(&edata->supported, lm_able);

/* EEE Advertised */
- edata->advertised = mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert);
+ mii_eee_cap1_mod_linkmode_t(lm_adv, adapter->eee_advert);
+ ethtool_convert_link_mode_to_legacy_u32(&edata->advertised, lm_adv);

/* EEE Link Partner Advertised */
ret_val = e1000_read_emi_reg_locked(hw, lpa_addr, &phy_data);
if (ret_val)
goto release;
- edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
+ mii_eee_cap1_mod_linkmode_t(lm_lp, phy_data);
+ ethtool_convert_link_mode_to_legacy_u32(&edata->lp_advertised, lm_lp);

/* EEE PCS Status */
ret_val = e1000_read_emi_reg_locked(hw, pcs_stat_addr, &phy_data);
@@ -2264,6 +2270,7 @@ static int e1000e_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
{
struct e1000_adapter *adapter = netdev_priv(netdev);
+ __ETHTOOL_DECLARE_LINK_MODE_MASK(adv) = {};
struct e1000_hw *hw = &adapter->hw;
struct ethtool_eee eee_curr;
s32 ret_val;
@@ -2287,7 +2294,8 @@ static int e1000e_set_eee(struct net_device *netdev, struct ethtool_eee *edata)
return -EINVAL;
}

- adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
+ adv[0] = edata->advertised;
+ adapter->eee_advert = linkmode_to_mii_eee_cap1_t(adv);

hw->dev_spec.ich8lan.eee_disable = !edata->eee_enabled;

--
2.30.2


2023-02-06 13:53:10

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 08/23] net: phy: migrate phy_init_eee() to genphy_c45_eee_is_active()

Reduce code duplicated by migrating phy_init_eee() to
genphy_c45_eee_is_active().

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/phy.c | 89 +++++++------------------------------------
1 file changed, 14 insertions(+), 75 deletions(-)

diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 41cfb24c48c1..36533746630e 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1457,30 +1457,6 @@ void phy_mac_interrupt(struct phy_device *phydev)
}
EXPORT_SYMBOL(phy_mac_interrupt);

-static void mmd_eee_adv_to_linkmode(unsigned long *advertising, u16 eee_adv)
-{
- linkmode_zero(advertising);
-
- if (eee_adv & MDIO_EEE_100TX)
- linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT,
- advertising);
- if (eee_adv & MDIO_EEE_1000T)
- linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
- advertising);
- if (eee_adv & MDIO_EEE_10GT)
- linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
- advertising);
- if (eee_adv & MDIO_EEE_1000KX)
- linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
- advertising);
- if (eee_adv & MDIO_EEE_10GKX4)
- linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
- advertising);
- if (eee_adv & MDIO_EEE_10GKR)
- linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
- advertising);
-}
-
/**
* phy_init_eee - init and check the EEE feature
* @phydev: target phy_device struct
@@ -1493,62 +1469,25 @@ static void mmd_eee_adv_to_linkmode(unsigned long *advertising, u16 eee_adv)
*/
int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
{
+ int ret;
+
if (!phydev->drv)
return -EIO;

- /* According to 802.3az,the EEE is supported only in full duplex-mode.
- */
- if (phydev->duplex == DUPLEX_FULL) {
- __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
- __ETHTOOL_DECLARE_LINK_MODE_MASK(lp);
- __ETHTOOL_DECLARE_LINK_MODE_MASK(adv);
- int eee_lp, eee_cap, eee_adv;
- int status;
- u32 cap;
-
- /* Read phy status to properly get the right settings */
- status = phy_read_status(phydev);
- if (status)
- return status;
-
- /* First check if the EEE ability is supported */
- eee_cap = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
- if (eee_cap <= 0)
- goto eee_exit_err;
-
- cap = mmd_eee_cap_to_ethtool_sup_t(eee_cap);
- if (!cap)
- goto eee_exit_err;
-
- /* Check which link settings negotiated and verify it in
- * the EEE advertising registers.
- */
- eee_lp = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_LPABLE);
- if (eee_lp <= 0)
- goto eee_exit_err;
-
- eee_adv = phy_read_mmd(phydev, MDIO_MMD_AN, MDIO_AN_EEE_ADV);
- if (eee_adv <= 0)
- goto eee_exit_err;
-
- mmd_eee_adv_to_linkmode(adv, eee_adv);
- mmd_eee_adv_to_linkmode(lp, eee_lp);
- linkmode_and(common, adv, lp);
-
- if (!phy_check_valid(phydev->speed, phydev->duplex, common))
- goto eee_exit_err;
+ ret = genphy_c45_eee_is_active(phydev, NULL, NULL, NULL);
+ if (ret < 0)
+ return ret;
+ if (!ret)
+ return -EPROTONOSUPPORT;

- if (clk_stop_enable)
- /* Configure the PHY to stop receiving xMII
- * clock while it is signaling LPI.
- */
- phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
- MDIO_PCS_CTRL1_CLKSTOP_EN);
+ if (clk_stop_enable)
+ /* Configure the PHY to stop receiving xMII
+ * clock while it is signaling LPI.
+ */
+ ret = phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
+ MDIO_PCS_CTRL1_CLKSTOP_EN);

- return 0; /* EEE supported */
- }
-eee_exit_err:
- return -EPROTONOSUPPORT;
+ return ret < 0 ? ret : 0;
}
EXPORT_SYMBOL(phy_init_eee);

--
2.30.2


2023-02-06 13:53:14

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 07/23] net: phy: c45: migrate to genphy_c45_write_eee_adv()

Migrate from genphy_config_eee_advert() to genphy_c45_write_eee_adv().

It should work as before except write operation to the EEE adv registers
will be done only if some EEE abilities was detected.

If some driver will have a regression, related driver should provide own
.get_features callback. See micrel.c:ksz9477_get_features() as example.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/phy-c45.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 38361df1e669..23ecb12714b6 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -262,7 +262,11 @@ int genphy_c45_an_config_aneg(struct phy_device *phydev)
linkmode_and(phydev->advertising, phydev->advertising,
phydev->supported);

- changed = genphy_config_eee_advert(phydev);
+ ret = genphy_c45_write_eee_adv(phydev, phydev->supported_eee);
+ if (ret < 0)
+ return ret;
+ else if (ret)
+ changed = true;

if (genphy_c45_baset1_able(phydev))
return genphy_c45_baset1_an_config_aneg(phydev);
@@ -968,6 +972,11 @@ int genphy_c45_pma_read_abilities(struct phy_device *phydev)
}
}

+ /* This is optional functionality. If not supported, we may get an error
+ * which should be ignored.
+ */
+ genphy_c45_read_eee_abilities(phydev);
+
return 0;
}
EXPORT_SYMBOL_GPL(genphy_c45_pma_read_abilities);
--
2.30.2


2023-02-06 13:53:17

by Oleksij Rempel

[permalink] [raw]
Subject: [PATCH net-next v5 12/23] net: phy: at803x: ar8035: fix EEE support for half duplex links

If AR8035 is running with enabled EEE and LPI, it will not be able to
establish an 100BaseTX/Half or 1000BaseT/Half link. Similar issue we
will have with 100BaseTX/Full and LPI TX timer configured to less then
80msec.

To avoid this issue, we need to keep LPI disabled before link is
establish and enable it only we detected supported link configuration.

Signed-off-by: Oleksij Rempel <[email protected]>
---
drivers/net/phy/at803x.c | 41 +++++++++++++++++++++++++++++++++++-----
1 file changed, 36 insertions(+), 5 deletions(-)

diff --git a/drivers/net/phy/at803x.c b/drivers/net/phy/at803x.c
index 9eb4439b0afc..5ab43eb63581 100644
--- a/drivers/net/phy/at803x.c
+++ b/drivers/net/phy/at803x.c
@@ -313,6 +313,7 @@ struct at803x_priv {
u8 smarteee_lpi_tw_100m;
bool is_fiber;
bool is_1000basex;
+ bool tx_lpi_on;
struct regulator_dev *vddio_rdev;
struct regulator_dev *vddh_rdev;
struct regulator *vddio;
@@ -970,6 +971,8 @@ static int at803x_smarteee_config(struct phy_device *phydev, bool enable,
u16 mask = 0, val = 0;
int ret;

+ priv->tx_lpi_on = enable;
+
if (priv->flags & AT803X_DISABLE_SMARTEEE || !enable)
return phy_modify_mmd(phydev, MDIO_MMD_PCS,
AT803X_MMD3_SMARTEEE_CTL3,
@@ -1010,10 +1013,15 @@ static int at803x_smarteee_config(struct phy_device *phydev, bool enable,
if (ret)
return ret;

- val = AT803X_MMD3_SMARTEEE_CTL3_LPI_EN |
- FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH,
- FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_23_16,
- tx_lpi_timer_raw));
+ val = FIELD_PREP(AT803X_MMD3_SMARTEEE_LPI_TIME_HIGH,
+ FIELD_GET(AT803X_MMD3_SMARTEEE_LPI_TIME_23_16,
+ tx_lpi_timer_raw));
+
+ if (phydev->state == PHY_RUNNING &&
+ phy_check_valid(phydev->speed, phydev->duplex,
+ phydev->supported_eee)) {
+ val |= AT803X_MMD3_SMARTEEE_CTL3_LPI_EN;
+ }

return phy_modify_mmd(phydev, MDIO_MMD_PCS, AT803X_MMD3_SMARTEEE_CTL3,
AT803X_MMD3_SMARTEEE_CTL3_LPI_EN |
@@ -1682,7 +1690,7 @@ static int at803x_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
tx_timer_ns = tx_timer_raw * AT803X_MMD3_SMARTEEE_LPI_TIME_RESOL_NS;
data->tx_lpi_timer = DIV_ROUND_CLOSEST_ULL(tx_timer_ns, NSEC_PER_USEC);

- data->tx_lpi_enabled = !!(ret & AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+ data->tx_lpi_enabled = priv->tx_lpi_on;

return genphy_c45_ethtool_get_eee(phydev, data);
}
@@ -1709,6 +1717,28 @@ static int at803x_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
return genphy_c45_ethtool_set_eee(phydev, data);
}

+static void at8035_link_change_notify(struct phy_device *phydev)
+{
+ struct at803x_priv *priv = phydev->priv;
+
+ if (priv->flags & AT803X_DISABLE_SMARTEEE)
+ return;
+
+ if (phydev->state == PHY_RUNNING) {
+ if (priv->tx_lpi_on && phy_check_valid(phydev->speed,
+ phydev->duplex,
+ phydev->supported_eee))
+ phy_set_bits_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_MMD3_SMARTEEE_CTL3,
+ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+ } else {
+ if (priv->tx_lpi_on)
+ phy_clear_bits_mmd(phydev, MDIO_MMD_PCS,
+ AT803X_MMD3_SMARTEEE_CTL3,
+ AT803X_MMD3_SMARTEEE_CTL3_LPI_EN);
+ }
+}
+
static int qca83xx_config_init(struct phy_device *phydev)
{
u8 switch_revision;
@@ -2137,6 +2167,7 @@ static struct phy_driver at803x_driver[] = {
.cable_test_get_status = at803x_cable_test_get_status,
.get_eee = at803x_get_eee,
.set_eee = at803x_set_eee,
+ .link_change_notify = at8035_link_change_notify,
}, {
/* Qualcomm Atheros AR8030 */
.phy_id = ATH8030_PHY_ID,
--
2.30.2


2023-02-06 14:46:28

by Arun Ramadoss

[permalink] [raw]
Subject: Re: [PATCH net-next v5 02/23] net: phy: add genphy_c45_read_eee_abilities() function

Hi Oleksij,

On Mon, 2023-02-06 at 14:50 +0100, Oleksij Rempel wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
>
> 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]>
> ---
> drivers/net/phy/phy-c45.c | 70
> ++++++++++++++++++++++++++++++++++++
> drivers/net/phy/phy_device.c | 16 +++++++++
> include/linux/mdio.h | 26 ++++++++++++++
> include/linux/phy.h | 5 +++
> 4 files changed, 117 insertions(+)
>
> diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
> index 9f9565a4819d..3ae642d3ae14 100644
> --- a/drivers/net/phy/phy-c45.c
> +++ b/drivers/net/phy/phy-c45.c
> @@ -661,6 +661,76 @@ int genphy_c45_read_mdix(struct phy_device
> *phydev)
> }
> EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
>
> +/**
> + * genphy_c45_read_eee_cap1 - read supported EEE link modes from
> register 3.20
> + * @phydev: target phy_device struct
> + */
> +static int genphy_c45_read_eee_cap1(struct phy_device *phydev)
> +{
> + int val;
> +
> + /* IEEE 802.3-2018 45.2.3.10 EEE control and capability 1
> + * (Register 3.20)
> + */
> + val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_ABLE);
> + if (val < 0)
> + return val;
> +
> + /* The 802.3 2018 standard says the top 2 bits are reserved
> and should
> + * read as 0. Also, it seems unlikely anybody will build a
> PHY which
> + * supports 100GBASE-R deep sleep all the way down to
> 100BASE-TX EEE.
> + * If MDIO_PCS_EEE_ABLE is 0xffff assume EEE is not
> supported.
> + */
> + if (val == GENMASK(15, 0))

nit: Magic number can be replaced by macro.

> + return 0;
> +
> + mii_eee_cap1_mod_linkmode_t(phydev->supported_eee, val);
> +
> + /* Some buggy devices indicate EEE link modes in
> MDIO_PCS_EEE_ABLE
> + * which they don't support as indicated by BMSR, ESTATUS
> etc.
> + */
> + linkmode_and(phydev->supported_eee, phydev->supported_eee,
> + phydev->supported);
> +
> + return 0;
> +}
> +
> +
>

2023-02-06 14:54:21

by Arun Ramadoss

[permalink] [raw]
Subject: Re: [PATCH net-next v5 05/23] net: phy: add genphy_c45_ethtool_get/set_eee() support

Hi Oleksij,

On Mon, 2023-02-06 at 14:50 +0100, Oleksij Rempel wrote:
> EXTERNAL EMAIL: Do not click links or open attachments unless you
> know the content is safe
>
>
> ---
> drivers/net/phy/phy-c45.c | 235
> ++++++++++++++++++++++++++++++++++++++
> include/linux/mdio.h | 58 ++++++++++
> include/linux/phy.h | 7 ++
> include/uapi/linux/mdio.h | 8 ++
> 4 files changed, 308 insertions(+)
>
> diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
> index 3ae642d3ae14..38361df1e669 100644
> --- a/drivers/net/phy/phy-c45.c
> +++ b/drivers/net/phy/phy-c45.c
> @@ -661,6 +661,129 @@ int genphy_c45_read_mdix(struct phy_device
> *phydev)
> }
> EXPORT_SYMBOL_GPL(genphy_c45_read_mdix);
>
>
> /**
> * genphy_c45_read_eee_cap1 - read supported EEE link modes from
> register 3.20
> * @phydev: target phy_device struct
> @@ -1194,6 +1317,118 @@ int genphy_c45_plca_get_status(struct
> phy_device *phydev,
> }
> EXPORT_SYMBOL_GPL(genphy_c45_plca_get_status);
>
> +/**
> + * genphy_c45_eee_is_active - get EEE supported and status
> + * @phydev: target phy_device struct
> + * @data: ethtool_eee data

Does the comment need to update based on the function parameter.

> + *
> + * Description: it reports the possible state of EEE functionality.
> + */
> +int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned
> long *adv,
> + unsigned long *lp, bool *is_enabled)
> +{
> + __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_adv) = {};
> + __ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_lp) = {};
> + __ETHTOOL_DECLARE_LINK_MODE_MASK(common);
> + bool eee_enabled, eee_active;
> + int ret;
> +
> + ret = genphy_c45_read_eee_adv(phydev, tmp_adv);
> + if (ret)
> + return ret;
> +
> + ret = genphy_c45_read_eee_lpa(phydev, tmp_lp);
> + if (ret)
> + return ret;
> +
> + eee_enabled = !linkmode_empty(tmp_adv);
> + linkmode_and(common, tmp_adv, tmp_lp);
> + if (eee_enabled && !linkmode_empty(common))
> + eee_active = phy_check_valid(phydev->speed, phydev-
> >duplex,
> + common);
> + else
> + eee_active = false;
> +
> + if (adv)
> + linkmode_copy(adv, tmp_adv);
> + if (lp)
> + linkmode_copy(lp, tmp_lp);
> + if (is_enabled)
> + *is_enabled = eee_enabled;
> +
> + return eee_active;
> +}
> +EXPORT_SYMBOL(genphy_c45_eee_is_active);
> +
>
>
> --
> 2.30.2
>

2023-02-07 00:44:46

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next v5 02/23] net: phy: add genphy_c45_read_eee_abilities() function

> + /* The 802.3 2018 standard says the top 2 bits are reserved and should
> + * read as 0. Also, it seems unlikely anybody will build a PHY which
> + * supports 100GBASE-R deep sleep all the way down to 100BASE-TX EEE.
> + * If MDIO_PCS_EEE_ABLE is 0xffff assume EEE is not supported.
> + */
> + if (val == GENMASK(15, 0))
> + return 0;

Given the comment says 0xffff i would just use 0xffff, not GENMASK.

Other than that:

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-02-07 00:45:09

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next v5 01/23] net: dsa: microchip: enable EEE support

On Mon, Feb 06, 2023 at 02:50:28PM +0100, Oleksij Rempel wrote:
> Some of KSZ9477 family switches provides EEE support. To enable it, we
> just need to register set_mac_eee/set_mac_eee handlers and validate
> supported chip version and port.
>
> Signed-off-by: Oleksij Rempel <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-02-07 00:53:07

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next v5 07/23] net: phy: c45: migrate to genphy_c45_write_eee_adv()

On Mon, Feb 06, 2023 at 02:50:34PM +0100, Oleksij Rempel wrote:
> Migrate from genphy_config_eee_advert() to genphy_c45_write_eee_adv().
>
> It should work as before except write operation to the EEE adv registers
> will be done only if some EEE abilities was detected.
>
> If some driver will have a regression, related driver should provide own
> .get_features callback. See micrel.c:ksz9477_get_features() as example.
>
> Signed-off-by: Oleksij Rempel <[email protected]>

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-02-07 00:54:52

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next v5 08/23] net: phy: migrate phy_init_eee() to genphy_c45_eee_is_active()

On Mon, Feb 06, 2023 at 02:50:35PM +0100, Oleksij Rempel wrote:
> Reduce code duplicated by migrating phy_init_eee() to
> genphy_c45_eee_is_active().
>
> Signed-off-by: Oleksij Rempel <[email protected]>

This makes sense, but as i said in a different thread, i think the
MAC/PHY API needs improving at some point, which could result in this
function going away. But this patchset is big enough as it is.

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-02-07 01:06:05

by Andrew Lunn

[permalink] [raw]
Subject: Re: [PATCH net-next v5 09/23] net: phy: start using genphy_c45_ethtool_get/set_eee()

On Mon, Feb 06, 2023 at 02:50:36PM +0100, Oleksij Rempel wrote:
> All preparations are done. Now we can start using new functions and remove
> the old code.
>
> Signed-off-by: Oleksij Rempel <[email protected]>

This change looks correct, in that it just replaces code with other
equivalent code.

But looking at it, i started to wonder about locking. I don't see
phydev->lock held anywhere. But it does access members of phydev, in
particular speed and duplex. If the PHY state machine is running at
the same time, and phy_read_status() is called, those members can
contain invalid information.

So i think another patch is needed to add locking to these two
functions.

Otherwise:

Reviewed-by: Andrew Lunn <[email protected]>

Andrew

2023-02-08 05:20:01

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next v5 02/23] net: phy: add genphy_c45_read_eee_abilities() function

On Mon, 6 Feb 2023 14:50:29 +0100 Oleksij Rempel wrote:
> +/**
> + * mii_eee_cap1_mod_linkmode_t

A bit odd formatting - for a function it should have () at the end?

> + * @adv: target the linkmode advertisement settings
> + * @val: register value
> + *
> + * A function that translates value of following registers to the linkmode:
> + * IEEE 802.3-2018 45.2.3.10 "EEE control and capability 1" register (3.20)
> + * IEEE 802.3-2018 45.2.7.13 "EEE advertisement 1" register (7.60)
> + * IEEE 802.3-2018 45.2.7.14 "EEE "link partner ability 1 register (7.61)
> + */
> +static inline void mii_eee_cap1_mod_linkmode_t(unsigned long *adv, u32 val)
> +{

> @@ -676,6 +678,8 @@ struct phy_device {
> __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising);
> /* used with phy_speed_down */
> __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
> + /* used for eee validation */
> + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported_eee);

missing kdoc for the new field

2023-02-08 05:20:56

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next v5 15/23] net: phy: add phy_has_smarteee() helper

On Mon, 6 Feb 2023 14:50:42 +0100 Oleksij Rempel wrote:
> +/**
> + * phy_has_rxtstamp - Tests whether a PHY supports SmartEEE.

Function name needs to be updated

> + * @phydev: the phy_device struct
> + */
> +static inline bool phy_has_smarteee(struct phy_device *phydev)
> +{
> + return phydev && phydev->drv && !!(phydev->drv->flags & PHY_SMART_EEE);
> +}

2023-02-08 05:26:35

by Jakub Kicinski

[permalink] [raw]
Subject: Re: [PATCH net-next v5 00/23] net: add EEE support for KSZ9477 and AR8035 with i.MX6

On Mon, 6 Feb 2023 14:50:27 +0100 Oleksij Rempel wrote:
> With this patch series we provide EEE control for KSZ9477 family of switches and
> AR8035 with i.MX6 configuration.
> According to my tests, on a system with KSZ8563 switch and 100Mbit idle link,
> we consume 0,192W less power per port if EEE is enabled.

Can we carve this series up a little bit to avoid large reposts?
Perhaps you can hold off on reposting the cleanup patches starting
at patch 17 - repost those separately after the first 16 go in?

2023-02-08 08:30:35

by Oleksij Rempel

[permalink] [raw]
Subject: Re: [PATCH net-next v5 00/23] net: add EEE support for KSZ9477 and AR8035 with i.MX6

On Tue, Feb 07, 2023 at 09:25:55PM -0800, Jakub Kicinski wrote:
> On Mon, 6 Feb 2023 14:50:27 +0100 Oleksij Rempel wrote:
> > With this patch series we provide EEE control for KSZ9477 family of switches and
> > AR8035 with i.MX6 configuration.
> > According to my tests, on a system with KSZ8563 switch and 100Mbit idle link,
> > we consume 0,192W less power per port if EEE is enabled.
>
> Can we carve this series up a little bit to avoid large reposts?
> Perhaps you can hold off on reposting the cleanup patches starting
> at patch 17 - repost those separately after the first 16 go in?

ACK. Sounds good.
I'll make a cut on 00/09 patch. SmartEEE need probably more discussion and
changes.

--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |