Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Ethtool support for Altera Triple-Speed Ethernet MAC driver
0003  * Copyright (C) 2008-2014 Altera Corporation. All rights reserved
0004  *
0005  * Contributors:
0006  *   Dalon Westergreen
0007  *   Thomas Chou
0008  *   Ian Abbott
0009  *   Yuriy Kozlov
0010  *   Tobias Klauser
0011  *   Andriy Smolskyy
0012  *   Roman Bulgakov
0013  *   Dmytro Mytarchuk
0014  *
0015  * Original driver contributed by SLS.
0016  * Major updates contributed by GlobalLogic
0017  */
0018 
0019 #include <linux/ethtool.h>
0020 #include <linux/kernel.h>
0021 #include <linux/netdevice.h>
0022 #include <linux/phy.h>
0023 
0024 #include "altera_tse.h"
0025 
0026 #define TSE_STATS_LEN   31
0027 #define TSE_NUM_REGS    128
0028 
0029 static char const stat_gstrings[][ETH_GSTRING_LEN] = {
0030     "tx_packets",
0031     "rx_packets",
0032     "rx_crc_errors",
0033     "rx_align_errors",
0034     "tx_bytes",
0035     "rx_bytes",
0036     "tx_pause",
0037     "rx_pause",
0038     "rx_errors",
0039     "tx_errors",
0040     "rx_unicast",
0041     "rx_multicast",
0042     "rx_broadcast",
0043     "tx_discards",
0044     "tx_unicast",
0045     "tx_multicast",
0046     "tx_broadcast",
0047     "ether_drops",
0048     "rx_total_bytes",
0049     "rx_total_packets",
0050     "rx_undersize",
0051     "rx_oversize",
0052     "rx_64_bytes",
0053     "rx_65_127_bytes",
0054     "rx_128_255_bytes",
0055     "rx_256_511_bytes",
0056     "rx_512_1023_bytes",
0057     "rx_1024_1518_bytes",
0058     "rx_gte_1519_bytes",
0059     "rx_jabbers",
0060     "rx_runts",
0061 };
0062 
0063 static void tse_get_drvinfo(struct net_device *dev,
0064                 struct ethtool_drvinfo *info)
0065 {
0066     struct altera_tse_private *priv = netdev_priv(dev);
0067     u32 rev = ioread32(&priv->mac_dev->megacore_revision);
0068 
0069     strcpy(info->driver, "altera_tse");
0070     snprintf(info->fw_version, ETHTOOL_FWVERS_LEN, "v%d.%d",
0071          rev & 0xFFFF, (rev & 0xFFFF0000) >> 16);
0072     sprintf(info->bus_info, "platform");
0073 }
0074 
0075 /* Fill in a buffer with the strings which correspond to the
0076  * stats
0077  */
0078 static void tse_gstrings(struct net_device *dev, u32 stringset, u8 *buf)
0079 {
0080     memcpy(buf, stat_gstrings, TSE_STATS_LEN * ETH_GSTRING_LEN);
0081 }
0082 
0083 static void tse_fill_stats(struct net_device *dev, struct ethtool_stats *dummy,
0084                u64 *buf)
0085 {
0086     struct altera_tse_private *priv = netdev_priv(dev);
0087     u64 ext;
0088 
0089     buf[0] = csrrd32(priv->mac_dev,
0090              tse_csroffs(frames_transmitted_ok));
0091     buf[1] = csrrd32(priv->mac_dev,
0092              tse_csroffs(frames_received_ok));
0093     buf[2] = csrrd32(priv->mac_dev,
0094              tse_csroffs(frames_check_sequence_errors));
0095     buf[3] = csrrd32(priv->mac_dev,
0096              tse_csroffs(alignment_errors));
0097 
0098     /* Extended aOctetsTransmittedOK counter */
0099     ext = (u64) csrrd32(priv->mac_dev,
0100                 tse_csroffs(msb_octets_transmitted_ok)) << 32;
0101 
0102     ext |= csrrd32(priv->mac_dev,
0103                tse_csroffs(octets_transmitted_ok));
0104     buf[4] = ext;
0105 
0106     /* Extended aOctetsReceivedOK counter */
0107     ext = (u64) csrrd32(priv->mac_dev,
0108                 tse_csroffs(msb_octets_received_ok)) << 32;
0109 
0110     ext |= csrrd32(priv->mac_dev,
0111                tse_csroffs(octets_received_ok));
0112     buf[5] = ext;
0113 
0114     buf[6] = csrrd32(priv->mac_dev,
0115              tse_csroffs(tx_pause_mac_ctrl_frames));
0116     buf[7] = csrrd32(priv->mac_dev,
0117              tse_csroffs(rx_pause_mac_ctrl_frames));
0118     buf[8] = csrrd32(priv->mac_dev,
0119              tse_csroffs(if_in_errors));
0120     buf[9] = csrrd32(priv->mac_dev,
0121              tse_csroffs(if_out_errors));
0122     buf[10] = csrrd32(priv->mac_dev,
0123               tse_csroffs(if_in_ucast_pkts));
0124     buf[11] = csrrd32(priv->mac_dev,
0125               tse_csroffs(if_in_multicast_pkts));
0126     buf[12] = csrrd32(priv->mac_dev,
0127               tse_csroffs(if_in_broadcast_pkts));
0128     buf[13] = csrrd32(priv->mac_dev,
0129               tse_csroffs(if_out_discards));
0130     buf[14] = csrrd32(priv->mac_dev,
0131               tse_csroffs(if_out_ucast_pkts));
0132     buf[15] = csrrd32(priv->mac_dev,
0133               tse_csroffs(if_out_multicast_pkts));
0134     buf[16] = csrrd32(priv->mac_dev,
0135               tse_csroffs(if_out_broadcast_pkts));
0136     buf[17] = csrrd32(priv->mac_dev,
0137               tse_csroffs(ether_stats_drop_events));
0138 
0139     /* Extended etherStatsOctets counter */
0140     ext = (u64) csrrd32(priv->mac_dev,
0141                 tse_csroffs(msb_ether_stats_octets)) << 32;
0142     ext |= csrrd32(priv->mac_dev,
0143                tse_csroffs(ether_stats_octets));
0144     buf[18] = ext;
0145 
0146     buf[19] = csrrd32(priv->mac_dev,
0147               tse_csroffs(ether_stats_pkts));
0148     buf[20] = csrrd32(priv->mac_dev,
0149               tse_csroffs(ether_stats_undersize_pkts));
0150     buf[21] = csrrd32(priv->mac_dev,
0151               tse_csroffs(ether_stats_oversize_pkts));
0152     buf[22] = csrrd32(priv->mac_dev,
0153               tse_csroffs(ether_stats_pkts_64_octets));
0154     buf[23] = csrrd32(priv->mac_dev,
0155               tse_csroffs(ether_stats_pkts_65to127_octets));
0156     buf[24] = csrrd32(priv->mac_dev,
0157               tse_csroffs(ether_stats_pkts_128to255_octets));
0158     buf[25] = csrrd32(priv->mac_dev,
0159               tse_csroffs(ether_stats_pkts_256to511_octets));
0160     buf[26] = csrrd32(priv->mac_dev,
0161               tse_csroffs(ether_stats_pkts_512to1023_octets));
0162     buf[27] = csrrd32(priv->mac_dev,
0163               tse_csroffs(ether_stats_pkts_1024to1518_octets));
0164     buf[28] = csrrd32(priv->mac_dev,
0165               tse_csroffs(ether_stats_pkts_1519tox_octets));
0166     buf[29] = csrrd32(priv->mac_dev,
0167               tse_csroffs(ether_stats_jabbers));
0168     buf[30] = csrrd32(priv->mac_dev,
0169               tse_csroffs(ether_stats_fragments));
0170 }
0171 
0172 static int tse_sset_count(struct net_device *dev, int sset)
0173 {
0174     switch (sset) {
0175     case ETH_SS_STATS:
0176         return TSE_STATS_LEN;
0177     default:
0178         return -EOPNOTSUPP;
0179     }
0180 }
0181 
0182 static u32 tse_get_msglevel(struct net_device *dev)
0183 {
0184     struct altera_tse_private *priv = netdev_priv(dev);
0185     return priv->msg_enable;
0186 }
0187 
0188 static void tse_set_msglevel(struct net_device *dev, uint32_t data)
0189 {
0190     struct altera_tse_private *priv = netdev_priv(dev);
0191     priv->msg_enable = data;
0192 }
0193 
0194 static int tse_reglen(struct net_device *dev)
0195 {
0196     return TSE_NUM_REGS * sizeof(u32);
0197 }
0198 
0199 static void tse_get_regs(struct net_device *dev, struct ethtool_regs *regs,
0200              void *regbuf)
0201 {
0202     int i;
0203     struct altera_tse_private *priv = netdev_priv(dev);
0204     u32 *buf = regbuf;
0205 
0206     /* Set version to a known value, so ethtool knows
0207      * how to do any special formatting of this data.
0208      * This version number will need to change if and
0209      * when this register table is changed.
0210      *
0211      * version[31:0] = 1: Dump the first 128 TSE Registers
0212      *      Upper bits are all 0 by default
0213      *
0214      * Upper 16-bits will indicate feature presence for
0215      * Ethtool register decoding in future version.
0216      */
0217 
0218     regs->version = 1;
0219 
0220     for (i = 0; i < TSE_NUM_REGS; i++)
0221         buf[i] = csrrd32(priv->mac_dev, i * 4);
0222 }
0223 
0224 static const struct ethtool_ops tse_ethtool_ops = {
0225     .get_drvinfo = tse_get_drvinfo,
0226     .get_regs_len = tse_reglen,
0227     .get_regs = tse_get_regs,
0228     .get_link = ethtool_op_get_link,
0229     .get_strings = tse_gstrings,
0230     .get_sset_count = tse_sset_count,
0231     .get_ethtool_stats = tse_fill_stats,
0232     .get_msglevel = tse_get_msglevel,
0233     .set_msglevel = tse_set_msglevel,
0234     .get_link_ksettings = phy_ethtool_get_link_ksettings,
0235     .set_link_ksettings = phy_ethtool_set_link_ksettings,
0236 };
0237 
0238 void altera_tse_set_ethtool_ops(struct net_device *netdev)
0239 {
0240     netdev->ethtool_ops = &tse_ethtool_ops;
0241 }