linux/drivers/net/ethernet/altera/altera_tse_ethtool.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* Ethtool support for Altera Triple-Speed Ethernet MAC driver
   3 * Copyright (C) 2008-2014 Altera Corporation. All rights reserved
   4 *
   5 * Contributors:
   6 *   Dalon Westergreen
   7 *   Thomas Chou
   8 *   Ian Abbott
   9 *   Yuriy Kozlov
  10 *   Tobias Klauser
  11 *   Andriy Smolskyy
  12 *   Roman Bulgakov
  13 *   Dmytro Mytarchuk
  14 *
  15 * Original driver contributed by SLS.
  16 * Major updates contributed by GlobalLogic
  17 */
  18
  19#include <linux/ethtool.h>
  20#include <linux/kernel.h>
  21#include <linux/netdevice.h>
  22#include <linux/phy.h>
  23
  24#include "altera_tse.h"
  25
  26#define TSE_STATS_LEN   31
  27#define TSE_NUM_REGS    128
  28
  29static char const stat_gstrings[][ETH_GSTRING_LEN] = {
  30        "tx_packets",
  31        "rx_packets",
  32        "rx_crc_errors",
  33        "rx_align_errors",
  34        "tx_bytes",
  35        "rx_bytes",
  36        "tx_pause",
  37        "rx_pause",
  38        "rx_errors",
  39        "tx_errors",
  40        "rx_unicast",
  41        "rx_multicast",
  42        "rx_broadcast",
  43        "tx_discards",
  44        "tx_unicast",
  45        "tx_multicast",
  46        "tx_broadcast",
  47        "ether_drops",
  48        "rx_total_bytes",
  49        "rx_total_packets",
  50        "rx_undersize",
  51        "rx_oversize",
  52        "rx_64_bytes",
  53        "rx_65_127_bytes",
  54        "rx_128_255_bytes",
  55        "rx_256_511_bytes",
  56        "rx_512_1023_bytes",
  57        "rx_1024_1518_bytes",
  58        "rx_gte_1519_bytes",
  59        "rx_jabbers",
  60        "rx_runts",
  61};
  62
  63static void tse_get_drvinfo(struct net_device *dev,
  64                            struct ethtool_drvinfo *info)
  65{
  66        struct altera_tse_private *priv = netdev_priv(dev);
  67        u32 rev = ioread32(&priv->mac_dev->megacore_revision);
  68
  69        strcpy(info->driver, "altera_tse");
  70        snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d",
  71                 rev & 0xFFFF, (rev & 0xFFFF0000) >> 16);
  72        sprintf(info->bus_info, "platform");
  73}
  74
  75/* Fill in a buffer with the strings which correspond to the
  76 * stats
  77 */
  78static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf)
  79{
  80        memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN);
  81}
  82
  83static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
  84                           u64 *buf)
  85{
  86        struct altera_tse_private *priv = netdev_priv(dev);
  87        u64 ext;
  88
  89        buf[0] = csrrd32(priv->mac_dev,
  90                         tse_csroffs(frames_transmitted_ok));
  91        buf[1] = csrrd32(priv->mac_dev,
  92                         tse_csroffs(frames_received_ok));
  93        buf[2] = csrrd32(priv->mac_dev,
  94                         tse_csroffs(frames_check_sequence_errors));
  95        buf[3] = csrrd32(priv->mac_dev,
  96                         tse_csroffs(alignment_errors));
  97
  98        /* Extended aOctetsTransmittedOK counter */
  99        ext = (u64) csrrd32(priv->mac_dev,
 100                            tse_csroffs(msb_octets_transmitted_ok)) << 32;
 101
 102        ext |= csrrd32(priv->mac_dev,
 103                       tse_csroffs(octets_transmitted_ok));
 104        buf[4] = ext;
 105
 106        /* Extended aOctetsReceivedOK counter */
 107        ext = (u64) csrrd32(priv->mac_dev,
 108                            tse_csroffs(msb_octets_received_ok)) << 32;
 109
 110        ext |= csrrd32(priv->mac_dev,
 111                       tse_csroffs(octets_received_ok));
 112        buf[5] = ext;
 113
 114        buf[6] = csrrd32(priv->mac_dev,
 115                         tse_csroffs(tx_pause_mac_ctrl_frames));
 116        buf[7] = csrrd32(priv->mac_dev,
 117                         tse_csroffs(rx_pause_mac_ctrl_frames));
 118        buf[8] = csrrd32(priv->mac_dev,
 119                         tse_csroffs(if_in_errors));
 120        buf[9] = csrrd32(priv->mac_dev,
 121                         tse_csroffs(if_out_errors));
 122        buf[10] = csrrd32(priv->mac_dev,
 123                          tse_csroffs(if_in_ucast_pkts));
 124        buf[11] = csrrd32(priv->mac_dev,
 125                          tse_csroffs(if_in_multicast_pkts));
 126        buf[12] = csrrd32(priv->mac_dev,
 127                          tse_csroffs(if_in_broadcast_pkts));
 128        buf[13] = csrrd32(priv->mac_dev,
 129                          tse_csroffs(if_out_discards));
 130        buf[14] = csrrd32(priv->mac_dev,
 131                          tse_csroffs(if_out_ucast_pkts));
 132        buf[15] = csrrd32(priv->mac_dev,
 133                          tse_csroffs(if_out_multicast_pkts));
 134        buf[16] = csrrd32(priv->mac_dev,
 135                          tse_csroffs(if_out_broadcast_pkts));
 136        buf[17] = csrrd32(priv->mac_dev,
 137                          tse_csroffs(ether_stats_drop_events));
 138
 139        /* Extended etherStatsOctets counter */
 140        ext = (u64) csrrd32(priv->mac_dev,
 141                            tse_csroffs(msb_ether_stats_octets)) << 32;
 142        ext |= csrrd32(priv->mac_dev,
 143                       tse_csroffs(ether_stats_octets));
 144        buf[18] = ext;
 145
 146        buf[19] = csrrd32(priv->mac_dev,
 147                          tse_csroffs(ether_stats_pkts));
 148        buf[20] = csrrd32(priv->mac_dev,
 149                          tse_csroffs(ether_stats_undersize_pkts));
 150        buf[21] = csrrd32(priv->mac_dev,
 151                          tse_csroffs(ether_stats_oversize_pkts));
 152        buf[22] = csrrd32(priv->mac_dev,
 153                          tse_csroffs(ether_stats_pkts_64_octets));
 154        buf[23] = csrrd32(priv->mac_dev,
 155                          tse_csroffs(ether_stats_pkts_65to127_octets));
 156        buf[24] = csrrd32(priv->mac_dev,
 157                          tse_csroffs(ether_stats_pkts_128to255_octets));
 158        buf[25] = csrrd32(priv->mac_dev,
 159                          tse_csroffs(ether_stats_pkts_256to511_octets));
 160        buf[26] = csrrd32(priv->mac_dev,
 161                          tse_csroffs(ether_stats_pkts_512to1023_octets));
 162        buf[27] = csrrd32(priv->mac_dev,
 163                          tse_csroffs(ether_stats_pkts_1024to1518_octets));
 164        buf[28] = csrrd32(priv->mac_dev,
 165                          tse_csroffs(ether_stats_pkts_1519tox_octets));
 166        buf[29] = csrrd32(priv->mac_dev,
 167                          tse_csroffs(ether_stats_jabbers));
 168        buf[30] = csrrd32(priv->mac_dev,
 169                          tse_csroffs(ether_stats_fragments));
 170}
 171
 172static int tse_sset_count(struct net_device *dev, int sset)
 173{
 174        switch (sset) {
 175        case ETH_SS_STATS:
 176                return TSE_STATS_LEN;
 177        default:
 178                return -EOPNOTSUPP;
 179        }
 180}
 181
 182static u32 tse_get_msglevel(struct net_device *dev)
 183{
 184        struct altera_tse_private *priv = netdev_priv(dev);
 185        return priv->msg_enable;
 186}
 187
 188static void tse_set_msglevel(struct net_device *dev, uint32_t data)
 189{
 190        struct altera_tse_private *priv = netdev_priv(dev);
 191        priv->msg_enable = data;
 192}
 193
 194static int tse_reglen(struct net_device *dev)
 195{
 196        return TSE_NUM_REGS * sizeof(u32);
 197}
 198
 199static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 200                         void *regbuf)
 201{
 202        int i;
 203        struct altera_tse_private *priv = netdev_priv(dev);
 204        u32 *buf = regbuf;
 205
 206        /* Set version to a known value, so ethtool knows
 207         * how to do any special formatting of this data.
 208         * This version number will need to change if and
 209         * when this register table is changed.
 210         *
 211         * version[31:0] = 1: Dump the first 128 TSE Registers
 212         *      Upper bits are all 0 by default
 213         *
 214         * Upper 16-bits will indicate feature presence for
 215         * Ethtool register decoding in future version.
 216         */
 217
 218        regs->version = 1;
 219
 220        for (i = 0; i < TSE_NUM_REGS; i++)
 221                buf[i] = csrrd32(priv->mac_dev, i * 4);
 222}
 223
 224static const struct ethtool_ops tse_ethtool_ops = {
 225        .get_drvinfo = tse_get_drvinfo,
 226        .get_regs_len = tse_reglen,
 227        .get_regs = tse_get_regs,
 228        .get_link = ethtool_op_get_link,
 229        .get_strings = tse_gstrings,
 230        .get_sset_count = tse_sset_count,
 231        .get_ethtool_stats = tse_fill_stats,
 232        .get_msglevel = tse_get_msglevel,
 233        .set_msglevel = tse_set_msglevel,
 234        .get_link_ksettings = phy_ethtool_get_link_ksettings,
 235        .set_link_ksettings = phy_ethtool_set_link_ksettings,
 236};
 237
 238void altera_tse_set_ethtool_ops(struct net_device *netdev)
 239{
 240        netdev->ethtool_ops = &tse_ethtool_ops;
 241}
 242