[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <1560470153-26155-6-git-send-email-ioana.ciornei@nxp.com>
Date: Fri, 14 Jun 2019 02:55:52 +0300
From: Ioana Ciornei <ioana.ciornei@....com>
To: linux@...linux.org.uk, hkallweit1@...il.com, f.fainelli@...il.com,
andrew@...n.ch, davem@...emloft.net
Cc: netdev@...r.kernel.org, alexandru.marginean@....com,
ruxandra.radulescu@....com,
Valentin Catalin Neacsu <valentin-catalin.neacsu@....com>,
Ioana Ciornei <ioana.ciornei@....com>
Subject: [PATCH RFC 5/6] dpaa2-eth: add autoneg support
From: Ioana Radulescu <ruxandra.radulescu@....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.radulescu@....com>
Signed-off-by: Valentin Catalin Neacsu <valentin-catalin.neacsu@....com>
Signed-off-by: Ioana Ciornei <ioana.ciornei@....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
Powered by blists - more mailing lists