linux/drivers/net/ethernet/samsung/sxgbe/sxgbe_ethtool.c
<<
>>
Prefs
   1/* 10G controller driver for Samsung SoCs
   2 *
   3 * Copyright (C) 2013 Samsung Electronics Co., Ltd.
   4 *              http://www.samsung.com
   5 *
   6 * Author: Siva Reddy Kallam <siva.kallam@samsung.com>
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
  14
  15#include <linux/clk.h>
  16#include <linux/interrupt.h>
  17#include <linux/kernel.h>
  18#include <linux/netdevice.h>
  19#include <linux/net_tstamp.h>
  20#include <linux/phy.h>
  21#include <linux/ptp_clock_kernel.h>
  22
  23#include "sxgbe_common.h"
  24#include "sxgbe_reg.h"
  25#include "sxgbe_dma.h"
  26
  27struct sxgbe_stats {
  28        char stat_string[ETH_GSTRING_LEN];
  29        int sizeof_stat;
  30        int stat_offset;
  31};
  32
  33#define SXGBE_STAT(m)                                           \
  34{                                                               \
  35        #m,                                                     \
  36        FIELD_SIZEOF(struct sxgbe_extra_stats, m),              \
  37        offsetof(struct sxgbe_priv_data, xstats.m)              \
  38}
  39
  40static const struct sxgbe_stats sxgbe_gstrings_stats[] = {
  41        /* TX/RX IRQ events */
  42        SXGBE_STAT(tx_process_stopped_irq),
  43        SXGBE_STAT(tx_ctxt_desc_err),
  44        SXGBE_STAT(tx_threshold),
  45        SXGBE_STAT(rx_threshold),
  46        SXGBE_STAT(tx_pkt_n),
  47        SXGBE_STAT(rx_pkt_n),
  48        SXGBE_STAT(normal_irq_n),
  49        SXGBE_STAT(tx_normal_irq_n),
  50        SXGBE_STAT(rx_normal_irq_n),
  51        SXGBE_STAT(napi_poll),
  52        SXGBE_STAT(tx_clean),
  53        SXGBE_STAT(tx_reset_ic_bit),
  54        SXGBE_STAT(rx_process_stopped_irq),
  55        SXGBE_STAT(rx_underflow_irq),
  56
  57        /* Bus access errors */
  58        SXGBE_STAT(fatal_bus_error_irq),
  59        SXGBE_STAT(tx_read_transfer_err),
  60        SXGBE_STAT(tx_write_transfer_err),
  61        SXGBE_STAT(tx_desc_access_err),
  62        SXGBE_STAT(tx_buffer_access_err),
  63        SXGBE_STAT(tx_data_transfer_err),
  64        SXGBE_STAT(rx_read_transfer_err),
  65        SXGBE_STAT(rx_write_transfer_err),
  66        SXGBE_STAT(rx_desc_access_err),
  67        SXGBE_STAT(rx_buffer_access_err),
  68        SXGBE_STAT(rx_data_transfer_err),
  69
  70        /* EEE-LPI stats */
  71        SXGBE_STAT(tx_lpi_entry_n),
  72        SXGBE_STAT(tx_lpi_exit_n),
  73        SXGBE_STAT(rx_lpi_entry_n),
  74        SXGBE_STAT(rx_lpi_exit_n),
  75        SXGBE_STAT(eee_wakeup_error_n),
  76
  77        /* RX specific */
  78        /* L2 error */
  79        SXGBE_STAT(rx_code_gmii_err),
  80        SXGBE_STAT(rx_watchdog_err),
  81        SXGBE_STAT(rx_crc_err),
  82        SXGBE_STAT(rx_gaint_pkt_err),
  83        SXGBE_STAT(ip_hdr_err),
  84        SXGBE_STAT(ip_payload_err),
  85        SXGBE_STAT(overflow_error),
  86
  87        /* L2 Pkt type */
  88        SXGBE_STAT(len_pkt),
  89        SXGBE_STAT(mac_ctl_pkt),
  90        SXGBE_STAT(dcb_ctl_pkt),
  91        SXGBE_STAT(arp_pkt),
  92        SXGBE_STAT(oam_pkt),
  93        SXGBE_STAT(untag_okt),
  94        SXGBE_STAT(other_pkt),
  95        SXGBE_STAT(svlan_tag_pkt),
  96        SXGBE_STAT(cvlan_tag_pkt),
  97        SXGBE_STAT(dvlan_ocvlan_icvlan_pkt),
  98        SXGBE_STAT(dvlan_osvlan_isvlan_pkt),
  99        SXGBE_STAT(dvlan_osvlan_icvlan_pkt),
 100        SXGBE_STAT(dvan_ocvlan_icvlan_pkt),
 101
 102        /* L3/L4 Pkt type */
 103        SXGBE_STAT(not_ip_pkt),
 104        SXGBE_STAT(ip4_tcp_pkt),
 105        SXGBE_STAT(ip4_udp_pkt),
 106        SXGBE_STAT(ip4_icmp_pkt),
 107        SXGBE_STAT(ip4_unknown_pkt),
 108        SXGBE_STAT(ip6_tcp_pkt),
 109        SXGBE_STAT(ip6_udp_pkt),
 110        SXGBE_STAT(ip6_icmp_pkt),
 111        SXGBE_STAT(ip6_unknown_pkt),
 112
 113        /* Filter specific */
 114        SXGBE_STAT(vlan_filter_match),
 115        SXGBE_STAT(sa_filter_fail),
 116        SXGBE_STAT(da_filter_fail),
 117        SXGBE_STAT(hash_filter_pass),
 118        SXGBE_STAT(l3_filter_match),
 119        SXGBE_STAT(l4_filter_match),
 120
 121        /* RX context specific */
 122        SXGBE_STAT(timestamp_dropped),
 123        SXGBE_STAT(rx_msg_type_no_ptp),
 124        SXGBE_STAT(rx_ptp_type_sync),
 125        SXGBE_STAT(rx_ptp_type_follow_up),
 126        SXGBE_STAT(rx_ptp_type_delay_req),
 127        SXGBE_STAT(rx_ptp_type_delay_resp),
 128        SXGBE_STAT(rx_ptp_type_pdelay_req),
 129        SXGBE_STAT(rx_ptp_type_pdelay_resp),
 130        SXGBE_STAT(rx_ptp_type_pdelay_follow_up),
 131        SXGBE_STAT(rx_ptp_announce),
 132        SXGBE_STAT(rx_ptp_mgmt),
 133        SXGBE_STAT(rx_ptp_signal),
 134        SXGBE_STAT(rx_ptp_resv_msg_type),
 135};
 136#define SXGBE_STATS_LEN ARRAY_SIZE(sxgbe_gstrings_stats)
 137
 138static int sxgbe_get_eee(struct net_device *dev,
 139                         struct ethtool_eee *edata)
 140{
 141        struct sxgbe_priv_data *priv = netdev_priv(dev);
 142
 143        if (!priv->hw_cap.eee)
 144                return -EOPNOTSUPP;
 145
 146        edata->eee_enabled = priv->eee_enabled;
 147        edata->eee_active = priv->eee_active;
 148        edata->tx_lpi_timer = priv->tx_lpi_timer;
 149
 150        return phy_ethtool_get_eee(dev->phydev, edata);
 151}
 152
 153static int sxgbe_set_eee(struct net_device *dev,
 154                         struct ethtool_eee *edata)
 155{
 156        struct sxgbe_priv_data *priv = netdev_priv(dev);
 157
 158        priv->eee_enabled = edata->eee_enabled;
 159
 160        if (!priv->eee_enabled) {
 161                sxgbe_disable_eee_mode(priv);
 162        } else {
 163                /* We are asking for enabling the EEE but it is safe
 164                 * to verify all by invoking the eee_init function.
 165                 * In case of failure it will return an error.
 166                 */
 167                priv->eee_enabled = sxgbe_eee_init(priv);
 168                if (!priv->eee_enabled)
 169                        return -EOPNOTSUPP;
 170
 171                /* Do not change tx_lpi_timer in case of failure */
 172                priv->tx_lpi_timer = edata->tx_lpi_timer;
 173        }
 174
 175        return phy_ethtool_set_eee(dev->phydev, edata);
 176}
 177
 178static void sxgbe_getdrvinfo(struct net_device *dev,
 179                             struct ethtool_drvinfo *info)
 180{
 181        strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 182        strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 183}
 184
 185static u32 sxgbe_getmsglevel(struct net_device *dev)
 186{
 187        struct sxgbe_priv_data *priv = netdev_priv(dev);
 188        return priv->msg_enable;
 189}
 190
 191static void sxgbe_setmsglevel(struct net_device *dev, u32 level)
 192{
 193        struct sxgbe_priv_data *priv = netdev_priv(dev);
 194        priv->msg_enable = level;
 195}
 196
 197static void sxgbe_get_strings(struct net_device *dev, u32 stringset, u8 *data)
 198{
 199        int i;
 200        u8 *p = data;
 201
 202        switch (stringset) {
 203        case ETH_SS_STATS:
 204                for (i = 0; i < SXGBE_STATS_LEN; i++) {
 205                        memcpy(p, sxgbe_gstrings_stats[i].stat_string,
 206                               ETH_GSTRING_LEN);
 207                        p += ETH_GSTRING_LEN;
 208                }
 209                break;
 210        default:
 211                WARN_ON(1);
 212                break;
 213        }
 214}
 215
 216static int sxgbe_get_sset_count(struct net_device *netdev, int sset)
 217{
 218        int len;
 219
 220        switch (sset) {
 221        case ETH_SS_STATS:
 222                len = SXGBE_STATS_LEN;
 223                return len;
 224        default:
 225                return -EINVAL;
 226        }
 227}
 228
 229static void sxgbe_get_ethtool_stats(struct net_device *dev,
 230                                    struct ethtool_stats *dummy, u64 *data)
 231{
 232        struct sxgbe_priv_data *priv = netdev_priv(dev);
 233        int i;
 234        char *p;
 235
 236        if (priv->eee_enabled) {
 237                int val = phy_get_eee_err(dev->phydev);
 238
 239                if (val)
 240                        priv->xstats.eee_wakeup_error_n = val;
 241        }
 242
 243        for (i = 0; i < SXGBE_STATS_LEN; i++) {
 244                p = (char *)priv + sxgbe_gstrings_stats[i].stat_offset;
 245                data[i] = (sxgbe_gstrings_stats[i].sizeof_stat == sizeof(u64))
 246                        ? (*(u64 *)p) : (*(u32 *)p);
 247        }
 248}
 249
 250static void sxgbe_get_channels(struct net_device *dev,
 251                               struct ethtool_channels *channel)
 252{
 253        channel->max_rx = SXGBE_MAX_RX_CHANNELS;
 254        channel->max_tx = SXGBE_MAX_TX_CHANNELS;
 255        channel->rx_count = SXGBE_RX_QUEUES;
 256        channel->tx_count = SXGBE_TX_QUEUES;
 257}
 258
 259static u32 sxgbe_riwt2usec(u32 riwt, struct sxgbe_priv_data *priv)
 260{
 261        unsigned long clk = clk_get_rate(priv->sxgbe_clk);
 262
 263        if (!clk)
 264                return 0;
 265
 266        return (riwt * 256) / (clk / 1000000);
 267}
 268
 269static u32 sxgbe_usec2riwt(u32 usec, struct sxgbe_priv_data *priv)
 270{
 271        unsigned long clk = clk_get_rate(priv->sxgbe_clk);
 272
 273        if (!clk)
 274                return 0;
 275
 276        return (usec * (clk / 1000000)) / 256;
 277}
 278
 279static int sxgbe_get_coalesce(struct net_device *dev,
 280                              struct ethtool_coalesce *ec)
 281{
 282        struct sxgbe_priv_data *priv = netdev_priv(dev);
 283
 284        if (priv->use_riwt)
 285                ec->rx_coalesce_usecs = sxgbe_riwt2usec(priv->rx_riwt, priv);
 286
 287        return 0;
 288}
 289
 290static int sxgbe_set_coalesce(struct net_device *dev,
 291                              struct ethtool_coalesce *ec)
 292{
 293        struct sxgbe_priv_data *priv = netdev_priv(dev);
 294        unsigned int rx_riwt;
 295
 296        if (!ec->rx_coalesce_usecs)
 297                return -EINVAL;
 298
 299        rx_riwt = sxgbe_usec2riwt(ec->rx_coalesce_usecs, priv);
 300
 301        if ((rx_riwt > SXGBE_MAX_DMA_RIWT) || (rx_riwt < SXGBE_MIN_DMA_RIWT))
 302                return -EINVAL;
 303        else if (!priv->use_riwt)
 304                return -EOPNOTSUPP;
 305
 306        priv->rx_riwt = rx_riwt;
 307        priv->hw->dma->rx_watchdog(priv->ioaddr, priv->rx_riwt);
 308
 309        return 0;
 310}
 311
 312static int sxgbe_get_rss_hash_opts(struct sxgbe_priv_data *priv,
 313                                   struct ethtool_rxnfc *cmd)
 314{
 315        cmd->data = 0;
 316
 317        /* Report default options for RSS on sxgbe */
 318        switch (cmd->flow_type) {
 319        case TCP_V4_FLOW:
 320        case UDP_V4_FLOW:
 321                cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 322        case SCTP_V4_FLOW:
 323        case AH_ESP_V4_FLOW:
 324        case AH_V4_FLOW:
 325        case ESP_V4_FLOW:
 326        case IPV4_FLOW:
 327                cmd->data |= RXH_IP_SRC | RXH_IP_DST;
 328                break;
 329        case TCP_V6_FLOW:
 330        case UDP_V6_FLOW:
 331                cmd->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 332        case SCTP_V6_FLOW:
 333        case AH_ESP_V6_FLOW:
 334        case AH_V6_FLOW:
 335        case ESP_V6_FLOW:
 336        case IPV6_FLOW:
 337                cmd->data |= RXH_IP_SRC | RXH_IP_DST;
 338                break;
 339        default:
 340                return -EINVAL;
 341        }
 342
 343        return 0;
 344}
 345
 346static int sxgbe_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 347                           u32 *rule_locs)
 348{
 349        struct sxgbe_priv_data *priv = netdev_priv(dev);
 350        int ret = -EOPNOTSUPP;
 351
 352        switch (cmd->cmd) {
 353        case ETHTOOL_GRXFH:
 354                ret = sxgbe_get_rss_hash_opts(priv, cmd);
 355                break;
 356        default:
 357                break;
 358        }
 359
 360        return ret;
 361}
 362
 363static int sxgbe_set_rss_hash_opt(struct sxgbe_priv_data *priv,
 364                                  struct ethtool_rxnfc *cmd)
 365{
 366        u32 reg_val = 0;
 367
 368        /* RSS does not support anything other than hashing
 369         * to queues on src and dst IPs and ports
 370         */
 371        if (cmd->data & ~(RXH_IP_SRC | RXH_IP_DST |
 372                          RXH_L4_B_0_1 | RXH_L4_B_2_3))
 373                return -EINVAL;
 374
 375        switch (cmd->flow_type) {
 376        case TCP_V4_FLOW:
 377        case TCP_V6_FLOW:
 378                if (!(cmd->data & RXH_IP_SRC) ||
 379                    !(cmd->data & RXH_IP_DST) ||
 380                    !(cmd->data & RXH_L4_B_0_1) ||
 381                    !(cmd->data & RXH_L4_B_2_3))
 382                        return -EINVAL;
 383                reg_val = SXGBE_CORE_RSS_CTL_TCP4TE;
 384                break;
 385        case UDP_V4_FLOW:
 386        case UDP_V6_FLOW:
 387                if (!(cmd->data & RXH_IP_SRC) ||
 388                    !(cmd->data & RXH_IP_DST) ||
 389                    !(cmd->data & RXH_L4_B_0_1) ||
 390                    !(cmd->data & RXH_L4_B_2_3))
 391                        return -EINVAL;
 392                reg_val = SXGBE_CORE_RSS_CTL_UDP4TE;
 393                break;
 394        case SCTP_V4_FLOW:
 395        case AH_ESP_V4_FLOW:
 396        case AH_V4_FLOW:
 397        case ESP_V4_FLOW:
 398        case AH_ESP_V6_FLOW:
 399        case AH_V6_FLOW:
 400        case ESP_V6_FLOW:
 401        case SCTP_V6_FLOW:
 402        case IPV4_FLOW:
 403        case IPV6_FLOW:
 404                if (!(cmd->data & RXH_IP_SRC) ||
 405                    !(cmd->data & RXH_IP_DST) ||
 406                    (cmd->data & RXH_L4_B_0_1) ||
 407                    (cmd->data & RXH_L4_B_2_3))
 408                        return -EINVAL;
 409                reg_val = SXGBE_CORE_RSS_CTL_IP2TE;
 410                break;
 411        default:
 412                return -EINVAL;
 413        }
 414
 415        /* Read SXGBE RSS control register and update */
 416        reg_val |= readl(priv->ioaddr + SXGBE_CORE_RSS_CTL_REG);
 417        writel(reg_val, priv->ioaddr + SXGBE_CORE_RSS_CTL_REG);
 418        readl(priv->ioaddr + SXGBE_CORE_RSS_CTL_REG);
 419
 420        return 0;
 421}
 422
 423static int sxgbe_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *cmd)
 424{
 425        struct sxgbe_priv_data *priv = netdev_priv(dev);
 426        int ret = -EOPNOTSUPP;
 427
 428        switch (cmd->cmd) {
 429        case ETHTOOL_SRXFH:
 430                ret = sxgbe_set_rss_hash_opt(priv, cmd);
 431                break;
 432        default:
 433                break;
 434        }
 435
 436        return ret;
 437}
 438
 439static void sxgbe_get_regs(struct net_device *dev,
 440                           struct ethtool_regs *regs, void *space)
 441{
 442        struct sxgbe_priv_data *priv = netdev_priv(dev);
 443        u32 *reg_space = (u32 *)space;
 444        int reg_offset;
 445        int reg_ix = 0;
 446        void __iomem *ioaddr = priv->ioaddr;
 447
 448        memset(reg_space, 0x0, REG_SPACE_SIZE);
 449
 450        /* MAC registers */
 451        for (reg_offset = START_MAC_REG_OFFSET;
 452             reg_offset <= MAX_MAC_REG_OFFSET; reg_offset += 4) {
 453                reg_space[reg_ix] = readl(ioaddr + reg_offset);
 454                reg_ix++;
 455        }
 456
 457        /* MTL registers */
 458        for (reg_offset = START_MTL_REG_OFFSET;
 459             reg_offset <= MAX_MTL_REG_OFFSET; reg_offset += 4) {
 460                reg_space[reg_ix] = readl(ioaddr + reg_offset);
 461                reg_ix++;
 462        }
 463
 464        /* DMA registers */
 465        for (reg_offset = START_DMA_REG_OFFSET;
 466             reg_offset <= MAX_DMA_REG_OFFSET; reg_offset += 4) {
 467                reg_space[reg_ix] = readl(ioaddr + reg_offset);
 468                reg_ix++;
 469        }
 470
 471        BUG_ON(reg_ix * 4 > REG_SPACE_SIZE);
 472}
 473
 474static int sxgbe_get_regs_len(struct net_device *dev)
 475{
 476        return REG_SPACE_SIZE;
 477}
 478
 479static const struct ethtool_ops sxgbe_ethtool_ops = {
 480        .get_drvinfo = sxgbe_getdrvinfo,
 481        .get_msglevel = sxgbe_getmsglevel,
 482        .set_msglevel = sxgbe_setmsglevel,
 483        .get_link = ethtool_op_get_link,
 484        .get_strings = sxgbe_get_strings,
 485        .get_ethtool_stats = sxgbe_get_ethtool_stats,
 486        .get_sset_count = sxgbe_get_sset_count,
 487        .get_channels = sxgbe_get_channels,
 488        .get_coalesce = sxgbe_get_coalesce,
 489        .set_coalesce = sxgbe_set_coalesce,
 490        .get_rxnfc = sxgbe_get_rxnfc,
 491        .set_rxnfc = sxgbe_set_rxnfc,
 492        .get_regs = sxgbe_get_regs,
 493        .get_regs_len = sxgbe_get_regs_len,
 494        .get_eee = sxgbe_get_eee,
 495        .set_eee = sxgbe_set_eee,
 496        .get_link_ksettings = phy_ethtool_get_link_ksettings,
 497        .set_link_ksettings = phy_ethtool_set_link_ksettings,
 498};
 499
 500void sxgbe_set_ethtool_ops(struct net_device *netdev)
 501{
 502        netdev->ethtool_ops = &sxgbe_ethtool_ops;
 503}
 504