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        strcpy(info->version, "v8.0");
  71        snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d",
  72                 rev & 0xFFFF, (rev & 0xFFFF0000) >> 16);
  73        sprintf(info->bus_info, "platform");
  74}
  75
  76/* Fill in a buffer with the strings which correspond to the
  77 * stats
  78 */
  79static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf)
  80{
  81        memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN);
  82}
  83
  84static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
  85                           u64 *buf)
  86{
  87        struct altera_tse_private *priv = netdev_priv(dev);
  88        u64 ext;
  89
  90        buf[0] = csrrd32(priv->mac_dev,
  91                         tse_csroffs(frames_transmitted_ok));
  92        buf[1] = csrrd32(priv->mac_dev,
  93                         tse_csroffs(frames_received_ok));
  94        buf[2] = csrrd32(priv->mac_dev,
  95                         tse_csroffs(frames_check_sequence_errors));
  96        buf[3] = csrrd32(priv->mac_dev,
  97                         tse_csroffs(alignment_errors));
  98
  99        /* Extended aOctetsTransmittedOK counter */
 100        ext = (u64) csrrd32(priv->mac_dev,
 101                            tse_csroffs(msb_octets_transmitted_ok)) << 32;
 102
 103        ext |= csrrd32(priv->mac_dev,
 104                       tse_csroffs(octets_transmitted_ok));
 105        buf[4] = ext;
 106
 107        /* Extended aOctetsReceivedOK counter */
 108        ext = (u64) csrrd32(priv->mac_dev,
 109                            tse_csroffs(msb_octets_received_ok)) << 32;
 110
 111        ext |= csrrd32(priv->mac_dev,
 112                       tse_csroffs(octets_received_ok));
 113        buf[5] = ext;
 114
 115        buf[6] = csrrd32(priv->mac_dev,
 116                         tse_csroffs(tx_pause_mac_ctrl_frames));
 117        buf[7] = csrrd32(priv->mac_dev,
 118                         tse_csroffs(rx_pause_mac_ctrl_frames));
 119        buf[8] = csrrd32(priv->mac_dev,
 120                         tse_csroffs(if_in_errors));
 121        buf[9] = csrrd32(priv->mac_dev,
 122                         tse_csroffs(if_out_errors));
 123        buf[10] = csrrd32(priv->mac_dev,
 124                          tse_csroffs(if_in_ucast_pkts));
 125        buf[11] = csrrd32(priv->mac_dev,
 126                          tse_csroffs(if_in_multicast_pkts));
 127        buf[12] = csrrd32(priv->mac_dev,
 128                          tse_csroffs(if_in_broadcast_pkts));
 129        buf[13] = csrrd32(priv->mac_dev,
 130                          tse_csroffs(if_out_discards));
 131        buf[14] = csrrd32(priv->mac_dev,
 132                          tse_csroffs(if_out_ucast_pkts));
 133        buf[15] = csrrd32(priv->mac_dev,
 134                          tse_csroffs(if_out_multicast_pkts));
 135        buf[16] = csrrd32(priv->mac_dev,
 136                          tse_csroffs(if_out_broadcast_pkts));
 137        buf[17] = csrrd32(priv->mac_dev,
 138                          tse_csroffs(ether_stats_drop_events));
 139
 140        /* Extended etherStatsOctets counter */
 141        ext = (u64) csrrd32(priv->mac_dev,
 142                            tse_csroffs(msb_ether_stats_octets)) << 32;
 143        ext |= csrrd32(priv->mac_dev,
 144                       tse_csroffs(ether_stats_octets));
 145        buf[18] = ext;
 146
 147        buf[19] = csrrd32(priv->mac_dev,
 148                          tse_csroffs(ether_stats_pkts));
 149        buf[20] = csrrd32(priv->mac_dev,
 150                          tse_csroffs(ether_stats_undersize_pkts));
 151        buf[21] = csrrd32(priv->mac_dev,
 152                          tse_csroffs(ether_stats_oversize_pkts));
 153        buf[22] = csrrd32(priv->mac_dev,
 154                          tse_csroffs(ether_stats_pkts_64_octets));
 155        buf[23] = csrrd32(priv->mac_dev,
 156                          tse_csroffs(ether_stats_pkts_65to127_octets));
 157        buf[24] = csrrd32(priv->mac_dev,
 158                          tse_csroffs(ether_stats_pkts_128to255_octets));
 159        buf[25] = csrrd32(priv->mac_dev,
 160                          tse_csroffs(ether_stats_pkts_256to511_octets));
 161        buf[26] = csrrd32(priv->mac_dev,
 162                          tse_csroffs(ether_stats_pkts_512to1023_octets));
 163        buf[27] = csrrd32(priv->mac_dev,
 164                          tse_csroffs(ether_stats_pkts_1024to1518_octets));
 165        buf[28] = csrrd32(priv->mac_dev,
 166                          tse_csroffs(ether_stats_pkts_1519tox_octets));
 167        buf[29] = csrrd32(priv->mac_dev,
 168                          tse_csroffs(ether_stats_jabbers));
 169        buf[30] = csrrd32(priv->mac_dev,
 170                          tse_csroffs(ether_stats_fragments));
 171}
 172
 173static int tse_sset_count(struct net_device *dev, int sset)
 174{
 175        switch (sset) {
 176        case ETH_SS_STATS:
 177                return TSE_STATS_LEN;
 178        default:
 179                return -EOPNOTSUPP;
 180        }
 181}
 182
 183static u32 tse_get_msglevel(struct net_device *dev)
 184{
 185        struct altera_tse_private *priv = netdev_priv(dev);
 186        return priv->msg_enable;
 187}
 188
 189static void tse_set_msglevel(struct net_device *dev, uint32_t data)
 190{
 191        struct altera_tse_private *priv = netdev_priv(dev);
 192        priv->msg_enable = data;
 193}
 194
 195static int tse_reglen(struct net_device *dev)
 196{
 197        return TSE_NUM_REGS * sizeof(u32);
 198}
 199
 200static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs,
 201                         void *regbuf)
 202{
 203        int i;
 204        struct altera_tse_private *priv = netdev_priv(dev);
 205        u32 *buf = regbuf;
 206
 207        /* Set version to a known value, so ethtool knows
 208         * how to do any special formatting of this data.
 209         * This version number will need to change if and
 210         * when this register table is changed.
 211         *
 212         * version[31:0] = 1: Dump the first 128 TSE Registers
 213         *      Upper bits are all 0 by default
 214         *
 215         * Upper 16-bits will indicate feature presence for
 216         * Ethtool register decoding in future version.
 217         */
 218
 219        regs->version = 1;
 220
 221        for (i = 0; i < TSE_NUM_REGS; i++)
 222                buf[i] = csrrd32(priv->mac_dev, i * 4);
 223}
 224
 225static const struct ethtool_ops tse_ethtool_ops = {
 226        .get_drvinfo = tse_get_drvinfo,
 227        .get_regs_len = tse_reglen,
 228        .get_regs = tse_get_regs,
 229        .get_link = ethtool_op_get_link,
 230        .get_strings = tse_gstrings,
 231        .get_sset_count = tse_sset_count,
 232        .get_ethtool_stats = tse_fill_stats,
 233        .get_msglevel = tse_get_msglevel,
 234        .set_msglevel = tse_set_msglevel,
 235        .get_link_ksettings = phy_ethtool_get_link_ksettings,
 236        .set_link_ksettings = phy_ethtool_set_link_ksettings,
 237};
 238
 239void altera_tse_set_ethtool_ops(struct net_device *netdev)
 240{
 241        netdev->ethtool_ops = &tse_ethtool_ops;
 242}
 243