root/drivers/staging/fsl-dpaa2/ethsw/ethsw-ethtool.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ethsw_get_drvinfo
  2. ethsw_get_link_ksettings
  3. ethsw_set_link_ksettings
  4. ethsw_ethtool_get_sset_count
  5. ethsw_ethtool_get_strings
  6. ethsw_ethtool_get_stats

   1 // SPDX-License-Identifier: GPL-2.0
   2 /*
   3  * DPAA2 Ethernet Switch ethtool support
   4  *
   5  * Copyright 2014-2016 Freescale Semiconductor Inc.
   6  * Copyright 2017-2018 NXP
   7  *
   8  */
   9 
  10 #include "ethsw.h"
  11 
  12 static struct {
  13         enum dpsw_counter id;
  14         char name[ETH_GSTRING_LEN];
  15 } ethsw_ethtool_counters[] =  {
  16         {DPSW_CNT_ING_FRAME,            "rx frames"},
  17         {DPSW_CNT_ING_BYTE,             "rx bytes"},
  18         {DPSW_CNT_ING_FLTR_FRAME,       "rx filtered frames"},
  19         {DPSW_CNT_ING_FRAME_DISCARD,    "rx discarded frames"},
  20         {DPSW_CNT_ING_BCAST_FRAME,      "rx b-cast frames"},
  21         {DPSW_CNT_ING_BCAST_BYTES,      "rx b-cast bytes"},
  22         {DPSW_CNT_ING_MCAST_FRAME,      "rx m-cast frames"},
  23         {DPSW_CNT_ING_MCAST_BYTE,       "rx m-cast bytes"},
  24         {DPSW_CNT_EGR_FRAME,            "tx frames"},
  25         {DPSW_CNT_EGR_BYTE,             "tx bytes"},
  26         {DPSW_CNT_EGR_FRAME_DISCARD,    "tx discarded frames"},
  27 
  28 };
  29 
  30 #define ETHSW_NUM_COUNTERS      ARRAY_SIZE(ethsw_ethtool_counters)
  31 
  32 static void ethsw_get_drvinfo(struct net_device *netdev,
  33                               struct ethtool_drvinfo *drvinfo)
  34 {
  35         struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  36         u16 version_major, version_minor;
  37         int err;
  38 
  39         strlcpy(drvinfo->driver, KBUILD_MODNAME, sizeof(drvinfo->driver));
  40 
  41         err = dpsw_get_api_version(port_priv->ethsw_data->mc_io, 0,
  42                                    &version_major,
  43                                    &version_minor);
  44         if (err)
  45                 strlcpy(drvinfo->fw_version, "N/A",
  46                         sizeof(drvinfo->fw_version));
  47         else
  48                 snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
  49                          "%u.%u", version_major, version_minor);
  50 
  51         strlcpy(drvinfo->bus_info, dev_name(netdev->dev.parent->parent),
  52                 sizeof(drvinfo->bus_info));
  53 }
  54 
  55 static int
  56 ethsw_get_link_ksettings(struct net_device *netdev,
  57                          struct ethtool_link_ksettings *link_ksettings)
  58 {
  59         struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  60         struct dpsw_link_state state = {0};
  61         int err = 0;
  62 
  63         err = dpsw_if_get_link_state(port_priv->ethsw_data->mc_io, 0,
  64                                      port_priv->ethsw_data->dpsw_handle,
  65                                      port_priv->idx,
  66                                      &state);
  67         if (err) {
  68                 netdev_err(netdev, "ERROR %d getting link state\n", err);
  69                 goto out;
  70         }
  71 
  72         /* At the moment, we have no way of interrogating the DPMAC
  73          * from the DPSW side or there may not exist a DPMAC at all.
  74          * Report only autoneg state, duplexity and speed.
  75          */
  76         if (state.options & DPSW_LINK_OPT_AUTONEG)
  77                 link_ksettings->base.autoneg = AUTONEG_ENABLE;
  78         if (!(state.options & DPSW_LINK_OPT_HALF_DUPLEX))
  79                 link_ksettings->base.duplex = DUPLEX_FULL;
  80         link_ksettings->base.speed = state.rate;
  81 
  82 out:
  83         return err;
  84 }
  85 
  86 static int
  87 ethsw_set_link_ksettings(struct net_device *netdev,
  88                          const struct ethtool_link_ksettings *link_ksettings)
  89 {
  90         struct ethsw_port_priv *port_priv = netdev_priv(netdev);
  91         struct ethsw_core *ethsw = port_priv->ethsw_data;
  92         struct dpsw_link_cfg cfg = {0};
  93         bool if_running;
  94         int err = 0, ret;
  95 
  96         /* Interface needs to be down to change link settings */
  97         if_running = netif_running(netdev);
  98         if (if_running) {
  99                 err = dpsw_if_disable(ethsw->mc_io, 0,
 100                                       ethsw->dpsw_handle,
 101                                       port_priv->idx);
 102                 if (err) {
 103                         netdev_err(netdev, "dpsw_if_disable err %d\n", err);
 104                         return err;
 105                 }
 106         }
 107 
 108         cfg.rate = link_ksettings->base.speed;
 109         if (link_ksettings->base.autoneg == AUTONEG_ENABLE)
 110                 cfg.options |= DPSW_LINK_OPT_AUTONEG;
 111         else
 112                 cfg.options &= ~DPSW_LINK_OPT_AUTONEG;
 113         if (link_ksettings->base.duplex  == DUPLEX_HALF)
 114                 cfg.options |= DPSW_LINK_OPT_HALF_DUPLEX;
 115         else
 116                 cfg.options &= ~DPSW_LINK_OPT_HALF_DUPLEX;
 117 
 118         err = dpsw_if_set_link_cfg(port_priv->ethsw_data->mc_io, 0,
 119                                    port_priv->ethsw_data->dpsw_handle,
 120                                    port_priv->idx,
 121                                    &cfg);
 122 
 123         if (if_running) {
 124                 ret = dpsw_if_enable(ethsw->mc_io, 0,
 125                                      ethsw->dpsw_handle,
 126                                      port_priv->idx);
 127                 if (ret) {
 128                         netdev_err(netdev, "dpsw_if_enable err %d\n", ret);
 129                         return ret;
 130                 }
 131         }
 132         return err;
 133 }
 134 
 135 static int ethsw_ethtool_get_sset_count(struct net_device *dev, int sset)
 136 {
 137         switch (sset) {
 138         case ETH_SS_STATS:
 139                 return ETHSW_NUM_COUNTERS;
 140         default:
 141                 return -EOPNOTSUPP;
 142         }
 143 }
 144 
 145 static void ethsw_ethtool_get_strings(struct net_device *netdev,
 146                                       u32 stringset, u8 *data)
 147 {
 148         int i;
 149 
 150         switch (stringset) {
 151         case ETH_SS_STATS:
 152                 for (i = 0; i < ETHSW_NUM_COUNTERS; i++)
 153                         memcpy(data + i * ETH_GSTRING_LEN,
 154                                ethsw_ethtool_counters[i].name, ETH_GSTRING_LEN);
 155                 break;
 156         }
 157 }
 158 
 159 static void ethsw_ethtool_get_stats(struct net_device *netdev,
 160                                     struct ethtool_stats *stats,
 161                                     u64 *data)
 162 {
 163         struct ethsw_port_priv *port_priv = netdev_priv(netdev);
 164         int i, err;
 165 
 166         for (i = 0; i < ETHSW_NUM_COUNTERS; i++) {
 167                 err = dpsw_if_get_counter(port_priv->ethsw_data->mc_io, 0,
 168                                           port_priv->ethsw_data->dpsw_handle,
 169                                           port_priv->idx,
 170                                           ethsw_ethtool_counters[i].id,
 171                                           &data[i]);
 172                 if (err)
 173                         netdev_err(netdev, "dpsw_if_get_counter[%s] err %d\n",
 174                                    ethsw_ethtool_counters[i].name, err);
 175         }
 176 }
 177 
 178 const struct ethtool_ops ethsw_port_ethtool_ops = {
 179         .get_drvinfo            = ethsw_get_drvinfo,
 180         .get_link               = ethtool_op_get_link,
 181         .get_link_ksettings     = ethsw_get_link_ksettings,
 182         .set_link_ksettings     = ethsw_set_link_ksettings,
 183         .get_strings            = ethsw_ethtool_get_strings,
 184         .get_ethtool_stats      = ethsw_ethtool_get_stats,
 185         .get_sset_count         = ethsw_ethtool_get_sset_count,
 186 };

/* [<][>][^][v][top][bottom][index][help] */