From: Ioana Radulescu <ruxandra.radule...@nxp.com> For MC versions that support it, use the new DPNI link APIs, which allow setting/getting of advertised and supported link modes.
A mapping between DPNI link modes and ethtool ones is created to help converting from one to the other. Signed-off-by: Ioana Radulescu <ruxandra.radule...@nxp.com> Signed-off-by: Valentin Catalin Neacsu <valentin-catalin.nea...@nxp.com> Signed-off-by: Ioana Ciornei <ioana.cior...@nxp.com> --- .../net/ethernet/freescale/dpaa2/dpaa2-ethtool.c | 83 ++++++++++++++++++---- 1 file changed, 69 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c index 7b182f4b263c..38999908a388 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-ethtool.c @@ -74,6 +74,44 @@ static void dpaa2_eth_get_drvinfo(struct net_device *net_dev, sizeof(drvinfo->bus_info)); } +#define DPNI_LINK_AUTONEG_VER_MAJOR 7 +#define DPNI_LINK_AUTONEG_VER_MINOR 8 + +struct dpaa2_eth_link_mode_map { + u64 dpni_lm; + u64 ethtool_lm; +}; + +static const struct dpaa2_eth_link_mode_map dpaa2_eth_lm_map[] = { + {DPNI_ADVERTISED_10BASET_FULL, ETHTOOL_LINK_MODE_10baseT_Full_BIT}, + {DPNI_ADVERTISED_100BASET_FULL, ETHTOOL_LINK_MODE_100baseT_Full_BIT}, + {DPNI_ADVERTISED_1000BASET_FULL, ETHTOOL_LINK_MODE_1000baseT_Full_BIT}, + {DPNI_ADVERTISED_10000BASET_FULL, ETHTOOL_LINK_MODE_10000baseT_Full_BIT}, + {DPNI_ADVERTISED_AUTONEG, ETHTOOL_LINK_MODE_Autoneg_BIT}, +}; + +static void link_mode_dpni2ethtool(u64 dpni_lm, unsigned long *ethtool_lm) +{ + int i; + + bitmap_zero(ethtool_lm, __ETHTOOL_LINK_MODE_MASK_NBITS); + for (i = 0; i < ARRAY_SIZE(dpaa2_eth_lm_map); i++) { + if (dpni_lm & dpaa2_eth_lm_map[i].dpni_lm) + __set_bit(dpaa2_eth_lm_map[i].ethtool_lm, ethtool_lm); + } +} + +static void link_mode_ethtool2dpni(const unsigned long *ethtool_lm, + u64 *dpni_lm) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(dpaa2_eth_lm_map); i++) { + if (test_bit(dpaa2_eth_lm_map[i].ethtool_lm, ethtool_lm)) + *dpni_lm |= dpaa2_eth_lm_map[i].dpni_lm; + } +} + static int dpaa2_eth_get_link_ksettings(struct net_device *net_dev, struct ethtool_link_ksettings *link_settings) @@ -82,19 +120,32 @@ static void dpaa2_eth_get_drvinfo(struct net_device *net_dev, int err = 0; struct dpaa2_eth_priv *priv = netdev_priv(net_dev); - err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, &state); - if (err) { - netdev_err(net_dev, "ERROR %d getting link state\n", err); - goto out; + if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_LINK_AUTONEG_VER_MAJOR, + DPNI_LINK_AUTONEG_VER_MINOR) < 0) { + err = dpni_get_link_state(priv->mc_io, 0, priv->mc_token, + &state); + if (err) { + netdev_err(net_dev, "dpni_get_link_state failed\n"); + goto out; + } + } else { + err = dpni_get_link_state_v2(priv->mc_io, 0, priv->mc_token, + &state); + if (err) { + netdev_err(net_dev, "dpni_get_link_state_v2 failed\n"); + goto out; + } + link_mode_dpni2ethtool(state.supported, + link_settings->link_modes.supported); + link_mode_dpni2ethtool(state.advertising, + link_settings->link_modes.advertising); } - /* At the moment, we have no way of interrogating the DPMAC - * from the DPNI side - and for that matter there may exist - * no DPMAC at all. So for now we just don't report anything - * beyond the DPNI attributes. - */ if (state.options & DPNI_LINK_OPT_AUTONEG) link_settings->base.autoneg = AUTONEG_ENABLE; + else + link_settings->base.autoneg = AUTONEG_DISABLE; + if (!(state.options & DPNI_LINK_OPT_HALF_DUPLEX)) link_settings->base.duplex = DUPLEX_FULL; link_settings->base.speed = state.rate; @@ -135,12 +186,16 @@ static void dpaa2_eth_get_drvinfo(struct net_device *net_dev, else cfg.options &= ~DPNI_LINK_OPT_HALF_DUPLEX; - err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg); + if (dpaa2_eth_cmp_dpni_ver(priv, DPNI_LINK_AUTONEG_VER_MAJOR, + DPNI_LINK_AUTONEG_VER_MINOR) < 0) { + err = dpni_set_link_cfg(priv->mc_io, 0, priv->mc_token, &cfg); + } else { + link_mode_ethtool2dpni(link_settings->link_modes.advertising, + &cfg.advertising); + dpni_set_link_cfg_v2(priv->mc_io, 0, priv->mc_token, &cfg); + } if (err) - /* ethtool will be loud enough if we return an error; no point - * in putting our own error message on the console by default - */ - netdev_dbg(net_dev, "ERROR %d setting link cfg\n", err); + netdev_err(net_dev, "dpni_set_link_cfg failed"); return err; } -- 1.9.1