root/drivers/net/ethernet/apm/xgene/xgene_enet_ethtool.c

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

DEFINITIONS

This source file includes following definitions.
  1. xgene_get_drvinfo
  2. xgene_get_link_ksettings
  3. xgene_set_link_ksettings
  4. xgene_get_strings
  5. xgene_get_sset_count
  6. xgene_get_extd_stats
  7. xgene_extd_stats_init
  8. xgene_get_ethtool_stats
  9. xgene_get_pauseparam
  10. xgene_set_pauseparam
  11. xgene_enet_set_ethtool_ops

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* Applied Micro X-Gene SoC Ethernet Driver
   3  *
   4  * Copyright (c) 2014, Applied Micro Circuits Corporation
   5  * Authors: Iyappan Subramanian <isubramanian@apm.com>
   6  */
   7 
   8 #include <linux/ethtool.h>
   9 #include "xgene_enet_main.h"
  10 
  11 struct xgene_gstrings_stats {
  12         char name[ETH_GSTRING_LEN];
  13         int offset;
  14         u32 addr;
  15         u32 mask;
  16 };
  17 
  18 #define XGENE_STAT(m) { #m, offsetof(struct rtnl_link_stats64, m) }
  19 #define XGENE_EXTD_STAT(s, a, m)                \
  20                 {                       \
  21                 .name = #s,             \
  22                 .addr = a ## _ADDR,     \
  23                 .mask = m               \
  24                 }
  25 
  26 static const struct xgene_gstrings_stats gstrings_stats[] = {
  27         XGENE_STAT(rx_packets),
  28         XGENE_STAT(tx_packets),
  29         XGENE_STAT(rx_bytes),
  30         XGENE_STAT(tx_bytes),
  31         XGENE_STAT(rx_errors),
  32         XGENE_STAT(tx_errors),
  33         XGENE_STAT(rx_length_errors),
  34         XGENE_STAT(rx_crc_errors),
  35         XGENE_STAT(rx_frame_errors),
  36         XGENE_STAT(rx_fifo_errors)
  37 };
  38 
  39 static const struct xgene_gstrings_stats gstrings_extd_stats[] = {
  40         XGENE_EXTD_STAT(tx_rx_64b_frame_cntr, TR64, 31),
  41         XGENE_EXTD_STAT(tx_rx_127b_frame_cntr, TR127, 31),
  42         XGENE_EXTD_STAT(tx_rx_255b_frame_cntr, TR255, 31),
  43         XGENE_EXTD_STAT(tx_rx_511b_frame_cntr, TR511, 31),
  44         XGENE_EXTD_STAT(tx_rx_1023b_frame_cntr, TR1K, 31),
  45         XGENE_EXTD_STAT(tx_rx_1518b_frame_cntr, TRMAX, 31),
  46         XGENE_EXTD_STAT(tx_rx_1522b_frame_cntr, TRMGV, 31),
  47         XGENE_EXTD_STAT(rx_fcs_error_cntr, RFCS, 16),
  48         XGENE_EXTD_STAT(rx_multicast_pkt_cntr, RMCA, 31),
  49         XGENE_EXTD_STAT(rx_broadcast_pkt_cntr, RBCA, 31),
  50         XGENE_EXTD_STAT(rx_ctrl_frame_pkt_cntr, RXCF, 16),
  51         XGENE_EXTD_STAT(rx_pause_frame_pkt_cntr, RXPF, 16),
  52         XGENE_EXTD_STAT(rx_unk_opcode_cntr, RXUO, 16),
  53         XGENE_EXTD_STAT(rx_align_err_cntr, RALN, 16),
  54         XGENE_EXTD_STAT(rx_frame_len_err_cntr, RFLR, 16),
  55         XGENE_EXTD_STAT(rx_frame_len_err_recov_cntr, DUMP, 0),
  56         XGENE_EXTD_STAT(rx_code_err_cntr, RCDE, 16),
  57         XGENE_EXTD_STAT(rx_carrier_sense_err_cntr, RCSE, 16),
  58         XGENE_EXTD_STAT(rx_undersize_pkt_cntr, RUND, 16),
  59         XGENE_EXTD_STAT(rx_oversize_pkt_cntr, ROVR, 16),
  60         XGENE_EXTD_STAT(rx_fragments_cntr, RFRG, 16),
  61         XGENE_EXTD_STAT(rx_jabber_cntr, RJBR, 16),
  62         XGENE_EXTD_STAT(rx_jabber_recov_cntr, DUMP, 0),
  63         XGENE_EXTD_STAT(rx_dropped_pkt_cntr, RDRP, 16),
  64         XGENE_EXTD_STAT(rx_overrun_cntr, DUMP, 0),
  65         XGENE_EXTD_STAT(tx_multicast_pkt_cntr, TMCA, 31),
  66         XGENE_EXTD_STAT(tx_broadcast_pkt_cntr, TBCA, 31),
  67         XGENE_EXTD_STAT(tx_pause_ctrl_frame_cntr, TXPF, 16),
  68         XGENE_EXTD_STAT(tx_defer_pkt_cntr, TDFR, 31),
  69         XGENE_EXTD_STAT(tx_excv_defer_pkt_cntr, TEDF, 31),
  70         XGENE_EXTD_STAT(tx_single_col_pkt_cntr, TSCL, 31),
  71         XGENE_EXTD_STAT(tx_multi_col_pkt_cntr, TMCL, 31),
  72         XGENE_EXTD_STAT(tx_late_col_pkt_cntr, TLCL, 31),
  73         XGENE_EXTD_STAT(tx_excv_col_pkt_cntr, TXCL, 31),
  74         XGENE_EXTD_STAT(tx_total_col_cntr, TNCL, 31),
  75         XGENE_EXTD_STAT(tx_pause_frames_hnrd_cntr, TPFH, 16),
  76         XGENE_EXTD_STAT(tx_drop_frame_cntr, TDRP, 16),
  77         XGENE_EXTD_STAT(tx_jabber_frame_cntr, TJBR, 12),
  78         XGENE_EXTD_STAT(tx_fcs_error_cntr, TFCS, 12),
  79         XGENE_EXTD_STAT(tx_ctrl_frame_cntr, TXCF, 12),
  80         XGENE_EXTD_STAT(tx_oversize_frame_cntr, TOVR, 12),
  81         XGENE_EXTD_STAT(tx_undersize_frame_cntr, TUND, 12),
  82         XGENE_EXTD_STAT(tx_fragments_cntr, TFRG, 12),
  83         XGENE_EXTD_STAT(tx_underrun_cntr, DUMP, 0)
  84 };
  85 
  86 #define XGENE_STATS_LEN         ARRAY_SIZE(gstrings_stats)
  87 #define XGENE_EXTD_STATS_LEN    ARRAY_SIZE(gstrings_extd_stats)
  88 #define RFCS_IDX                7
  89 #define RALN_IDX                13
  90 #define RFLR_IDX                14
  91 #define FALSE_RFLR_IDX          15
  92 #define RUND_IDX                18
  93 #define FALSE_RJBR_IDX          22
  94 #define RX_OVERRUN_IDX          24
  95 #define TFCS_IDX                38
  96 #define TFRG_IDX                42
  97 #define TX_UNDERRUN_IDX         43
  98 
  99 static void xgene_get_drvinfo(struct net_device *ndev,
 100                               struct ethtool_drvinfo *info)
 101 {
 102         struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 103         struct platform_device *pdev = pdata->pdev;
 104 
 105         strcpy(info->driver, "xgene_enet");
 106         strcpy(info->version, XGENE_DRV_VERSION);
 107         snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "N/A");
 108         sprintf(info->bus_info, "%s", pdev->name);
 109 }
 110 
 111 static int xgene_get_link_ksettings(struct net_device *ndev,
 112                                     struct ethtool_link_ksettings *cmd)
 113 {
 114         struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 115         struct phy_device *phydev = ndev->phydev;
 116         u32 supported;
 117 
 118         if (phy_interface_mode_is_rgmii(pdata->phy_mode)) {
 119                 if (phydev == NULL)
 120                         return -ENODEV;
 121 
 122                 phy_ethtool_ksettings_get(phydev, cmd);
 123 
 124                 return 0;
 125         } else if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
 126                 if (pdata->mdio_driver) {
 127                         if (!phydev)
 128                                 return -ENODEV;
 129 
 130                         phy_ethtool_ksettings_get(phydev, cmd);
 131 
 132                         return 0;
 133                 }
 134 
 135                 supported = SUPPORTED_1000baseT_Full | SUPPORTED_Autoneg |
 136                         SUPPORTED_MII;
 137                 ethtool_convert_legacy_u32_to_link_mode(
 138                         cmd->link_modes.supported,
 139                         supported);
 140                 ethtool_convert_legacy_u32_to_link_mode(
 141                         cmd->link_modes.advertising,
 142                         supported);
 143 
 144                 cmd->base.speed = SPEED_1000;
 145                 cmd->base.duplex = DUPLEX_FULL;
 146                 cmd->base.port = PORT_MII;
 147                 cmd->base.autoneg = AUTONEG_ENABLE;
 148         } else {
 149                 supported = SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE;
 150                 ethtool_convert_legacy_u32_to_link_mode(
 151                         cmd->link_modes.supported,
 152                         supported);
 153                 ethtool_convert_legacy_u32_to_link_mode(
 154                         cmd->link_modes.advertising,
 155                         supported);
 156 
 157                 cmd->base.speed = SPEED_10000;
 158                 cmd->base.duplex = DUPLEX_FULL;
 159                 cmd->base.port = PORT_FIBRE;
 160                 cmd->base.autoneg = AUTONEG_DISABLE;
 161         }
 162 
 163         return 0;
 164 }
 165 
 166 static int xgene_set_link_ksettings(struct net_device *ndev,
 167                                     const struct ethtool_link_ksettings *cmd)
 168 {
 169         struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 170         struct phy_device *phydev = ndev->phydev;
 171 
 172         if (phy_interface_mode_is_rgmii(pdata->phy_mode)) {
 173                 if (!phydev)
 174                         return -ENODEV;
 175 
 176                 return phy_ethtool_ksettings_set(phydev, cmd);
 177         }
 178 
 179         if (pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
 180                 if (pdata->mdio_driver) {
 181                         if (!phydev)
 182                                 return -ENODEV;
 183 
 184                         return phy_ethtool_ksettings_set(phydev, cmd);
 185                 }
 186         }
 187 
 188         return -EINVAL;
 189 }
 190 
 191 static void xgene_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
 192 {
 193         int i;
 194         u8 *p = data;
 195 
 196         if (stringset != ETH_SS_STATS)
 197                 return;
 198 
 199         for (i = 0; i < XGENE_STATS_LEN; i++) {
 200                 memcpy(p, gstrings_stats[i].name, ETH_GSTRING_LEN);
 201                 p += ETH_GSTRING_LEN;
 202         }
 203 
 204         for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
 205                 memcpy(p, gstrings_extd_stats[i].name, ETH_GSTRING_LEN);
 206                 p += ETH_GSTRING_LEN;
 207         }
 208 }
 209 
 210 static int xgene_get_sset_count(struct net_device *ndev, int sset)
 211 {
 212         if (sset != ETH_SS_STATS)
 213                 return -EINVAL;
 214 
 215         return XGENE_STATS_LEN + XGENE_EXTD_STATS_LEN;
 216 }
 217 
 218 static void xgene_get_extd_stats(struct xgene_enet_pdata *pdata)
 219 {
 220         u32 rx_drop, tx_drop;
 221         u32 mask, tmp;
 222         int i;
 223 
 224         for (i = 0; i < XGENE_EXTD_STATS_LEN; i++) {
 225                 tmp = xgene_enet_rd_stat(pdata, gstrings_extd_stats[i].addr);
 226                 if (gstrings_extd_stats[i].mask) {
 227                         mask = GENMASK(gstrings_extd_stats[i].mask - 1, 0);
 228                         pdata->extd_stats[i] += (tmp & mask);
 229                 }
 230         }
 231 
 232         if (pdata->phy_mode == PHY_INTERFACE_MODE_XGMII) {
 233                 /* Errata 10GE_10 - SW should intepret RALN as 0 */
 234                 pdata->extd_stats[RALN_IDX] = 0;
 235         } else {
 236                 /* Errata ENET_15 - Fixes RFCS, RFLR, TFCS counter */
 237                 pdata->extd_stats[RFCS_IDX] -= pdata->extd_stats[RALN_IDX];
 238                 pdata->extd_stats[RFLR_IDX] -= pdata->extd_stats[RUND_IDX];
 239                 pdata->extd_stats[TFCS_IDX] -= pdata->extd_stats[TFRG_IDX];
 240         }
 241 
 242         pdata->mac_ops->get_drop_cnt(pdata, &rx_drop, &tx_drop);
 243         pdata->extd_stats[RX_OVERRUN_IDX] += rx_drop;
 244         pdata->extd_stats[TX_UNDERRUN_IDX] += tx_drop;
 245 
 246         /* Errata 10GE_8 -  Update Frame recovered from Errata 10GE_8/ENET_11 */
 247         pdata->extd_stats[FALSE_RFLR_IDX] = pdata->false_rflr;
 248         /* Errata ENET_15 - Jabber Frame recov'ed from Errata 10GE_10/ENET_15 */
 249         pdata->extd_stats[FALSE_RJBR_IDX] = pdata->vlan_rjbr;
 250 }
 251 
 252 int xgene_extd_stats_init(struct xgene_enet_pdata *pdata)
 253 {
 254         pdata->extd_stats = devm_kmalloc_array(&pdata->pdev->dev,
 255                         XGENE_EXTD_STATS_LEN, sizeof(u64), GFP_KERNEL);
 256         if (!pdata->extd_stats)
 257                 return -ENOMEM;
 258 
 259         xgene_get_extd_stats(pdata);
 260         memset(pdata->extd_stats, 0, XGENE_EXTD_STATS_LEN * sizeof(u64));
 261 
 262         return 0;
 263 }
 264 
 265 static void xgene_get_ethtool_stats(struct net_device *ndev,
 266                                     struct ethtool_stats *dummy,
 267                                     u64 *data)
 268 {
 269         struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 270         struct rtnl_link_stats64 stats;
 271         int i;
 272 
 273         dev_get_stats(ndev, &stats);
 274         for (i = 0; i < XGENE_STATS_LEN; i++)
 275                 data[i] = *(u64 *)((char *)&stats + gstrings_stats[i].offset);
 276 
 277         xgene_get_extd_stats(pdata);
 278         for (i = 0; i < XGENE_EXTD_STATS_LEN; i++)
 279                 data[i + XGENE_STATS_LEN] = pdata->extd_stats[i];
 280 }
 281 
 282 static void xgene_get_pauseparam(struct net_device *ndev,
 283                                  struct ethtool_pauseparam *pp)
 284 {
 285         struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 286 
 287         pp->autoneg = pdata->pause_autoneg;
 288         pp->tx_pause = pdata->tx_pause;
 289         pp->rx_pause = pdata->rx_pause;
 290 }
 291 
 292 static int xgene_set_pauseparam(struct net_device *ndev,
 293                                 struct ethtool_pauseparam *pp)
 294 {
 295         struct xgene_enet_pdata *pdata = netdev_priv(ndev);
 296         struct phy_device *phydev = ndev->phydev;
 297 
 298         if (phy_interface_mode_is_rgmii(pdata->phy_mode) ||
 299             pdata->phy_mode == PHY_INTERFACE_MODE_SGMII) {
 300                 if (!phydev)
 301                         return -EINVAL;
 302 
 303                 if (!phy_validate_pause(phydev, pp))
 304                         return -EINVAL;
 305 
 306                 pdata->pause_autoneg = pp->autoneg;
 307                 pdata->tx_pause = pp->tx_pause;
 308                 pdata->rx_pause = pp->rx_pause;
 309 
 310                 phy_set_asym_pause(phydev, pp->rx_pause,  pp->tx_pause);
 311 
 312                 if (!pp->autoneg) {
 313                         pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
 314                         pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
 315                 }
 316         } else {
 317                 if (pp->autoneg)
 318                         return -EINVAL;
 319 
 320                 pdata->tx_pause = pp->tx_pause;
 321                 pdata->rx_pause = pp->rx_pause;
 322 
 323                 pdata->mac_ops->flowctl_tx(pdata, pdata->tx_pause);
 324                 pdata->mac_ops->flowctl_rx(pdata, pdata->rx_pause);
 325         }
 326 
 327         return 0;
 328 }
 329 
 330 static const struct ethtool_ops xgene_ethtool_ops = {
 331         .get_drvinfo = xgene_get_drvinfo,
 332         .get_link = ethtool_op_get_link,
 333         .get_strings = xgene_get_strings,
 334         .get_sset_count = xgene_get_sset_count,
 335         .get_ethtool_stats = xgene_get_ethtool_stats,
 336         .get_link_ksettings = xgene_get_link_ksettings,
 337         .set_link_ksettings = xgene_set_link_ksettings,
 338         .get_pauseparam = xgene_get_pauseparam,
 339         .set_pauseparam = xgene_set_pauseparam
 340 };
 341 
 342 void xgene_enet_set_ethtool_ops(struct net_device *ndev)
 343 {
 344         ndev->ethtool_ops = &xgene_ethtool_ops;
 345 }

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