linux/drivers/net/ethernet/cavium/thunder/nicvf_ethtool.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2015 Cavium, Inc.
   3 *
   4 * This program is free software; you can redistribute it and/or modify it
   5 * under the terms of version 2 of the GNU General Public License
   6 * as published by the Free Software Foundation.
   7 */
   8
   9/* ETHTOOL Support for VNIC_VF Device*/
  10
  11#include <linux/pci.h>
  12
  13#include "nic_reg.h"
  14#include "nic.h"
  15#include "nicvf_queues.h"
  16#include "q_struct.h"
  17#include "thunder_bgx.h"
  18
  19#define DRV_NAME        "thunder-nicvf"
  20#define DRV_VERSION     "1.0"
  21
  22struct nicvf_stat {
  23        char name[ETH_GSTRING_LEN];
  24        unsigned int index;
  25};
  26
  27#define NICVF_HW_STAT(stat) { \
  28        .name = #stat, \
  29        .index = offsetof(struct nicvf_hw_stats, stat) / sizeof(u64), \
  30}
  31
  32#define NICVF_DRV_STAT(stat) { \
  33        .name = #stat, \
  34        .index = offsetof(struct nicvf_drv_stats, stat) / sizeof(u64), \
  35}
  36
  37static const struct nicvf_stat nicvf_hw_stats[] = {
  38        NICVF_HW_STAT(rx_bytes),
  39        NICVF_HW_STAT(rx_ucast_frames),
  40        NICVF_HW_STAT(rx_bcast_frames),
  41        NICVF_HW_STAT(rx_mcast_frames),
  42        NICVF_HW_STAT(rx_fcs_errors),
  43        NICVF_HW_STAT(rx_l2_errors),
  44        NICVF_HW_STAT(rx_drop_red),
  45        NICVF_HW_STAT(rx_drop_red_bytes),
  46        NICVF_HW_STAT(rx_drop_overrun),
  47        NICVF_HW_STAT(rx_drop_overrun_bytes),
  48        NICVF_HW_STAT(rx_drop_bcast),
  49        NICVF_HW_STAT(rx_drop_mcast),
  50        NICVF_HW_STAT(rx_drop_l3_bcast),
  51        NICVF_HW_STAT(rx_drop_l3_mcast),
  52        NICVF_HW_STAT(rx_bgx_truncated_pkts),
  53        NICVF_HW_STAT(rx_jabber_errs),
  54        NICVF_HW_STAT(rx_fcs_errs),
  55        NICVF_HW_STAT(rx_bgx_errs),
  56        NICVF_HW_STAT(rx_prel2_errs),
  57        NICVF_HW_STAT(rx_l2_hdr_malformed),
  58        NICVF_HW_STAT(rx_oversize),
  59        NICVF_HW_STAT(rx_undersize),
  60        NICVF_HW_STAT(rx_l2_len_mismatch),
  61        NICVF_HW_STAT(rx_l2_pclp),
  62        NICVF_HW_STAT(rx_ip_ver_errs),
  63        NICVF_HW_STAT(rx_ip_csum_errs),
  64        NICVF_HW_STAT(rx_ip_hdr_malformed),
  65        NICVF_HW_STAT(rx_ip_payload_malformed),
  66        NICVF_HW_STAT(rx_ip_ttl_errs),
  67        NICVF_HW_STAT(rx_l3_pclp),
  68        NICVF_HW_STAT(rx_l4_malformed),
  69        NICVF_HW_STAT(rx_l4_csum_errs),
  70        NICVF_HW_STAT(rx_udp_len_errs),
  71        NICVF_HW_STAT(rx_l4_port_errs),
  72        NICVF_HW_STAT(rx_tcp_flag_errs),
  73        NICVF_HW_STAT(rx_tcp_offset_errs),
  74        NICVF_HW_STAT(rx_l4_pclp),
  75        NICVF_HW_STAT(rx_truncated_pkts),
  76        NICVF_HW_STAT(tx_bytes_ok),
  77        NICVF_HW_STAT(tx_ucast_frames_ok),
  78        NICVF_HW_STAT(tx_bcast_frames_ok),
  79        NICVF_HW_STAT(tx_mcast_frames_ok),
  80};
  81
  82static const struct nicvf_stat nicvf_drv_stats[] = {
  83        NICVF_DRV_STAT(rx_frames_ok),
  84        NICVF_DRV_STAT(rx_frames_64),
  85        NICVF_DRV_STAT(rx_frames_127),
  86        NICVF_DRV_STAT(rx_frames_255),
  87        NICVF_DRV_STAT(rx_frames_511),
  88        NICVF_DRV_STAT(rx_frames_1023),
  89        NICVF_DRV_STAT(rx_frames_1518),
  90        NICVF_DRV_STAT(rx_frames_jumbo),
  91        NICVF_DRV_STAT(rx_drops),
  92        NICVF_DRV_STAT(rcv_buffer_alloc_failures),
  93        NICVF_DRV_STAT(tx_frames_ok),
  94        NICVF_DRV_STAT(tx_tso),
  95        NICVF_DRV_STAT(tx_drops),
  96        NICVF_DRV_STAT(tx_timeout),
  97        NICVF_DRV_STAT(txq_stop),
  98        NICVF_DRV_STAT(txq_wake),
  99};
 100
 101static const struct nicvf_stat nicvf_queue_stats[] = {
 102        { "bytes", 0 },
 103        { "frames", 1 },
 104};
 105
 106static const unsigned int nicvf_n_hw_stats = ARRAY_SIZE(nicvf_hw_stats);
 107static const unsigned int nicvf_n_drv_stats = ARRAY_SIZE(nicvf_drv_stats);
 108static const unsigned int nicvf_n_queue_stats = ARRAY_SIZE(nicvf_queue_stats);
 109
 110static int nicvf_get_settings(struct net_device *netdev,
 111                              struct ethtool_cmd *cmd)
 112{
 113        struct nicvf *nic = netdev_priv(netdev);
 114
 115        cmd->supported = 0;
 116        cmd->transceiver = XCVR_EXTERNAL;
 117
 118        if (!nic->link_up) {
 119                cmd->duplex = DUPLEX_UNKNOWN;
 120                ethtool_cmd_speed_set(cmd, SPEED_UNKNOWN);
 121                return 0;
 122        }
 123
 124        if (nic->speed <= 1000) {
 125                cmd->port = PORT_MII;
 126                cmd->autoneg = AUTONEG_ENABLE;
 127        } else {
 128                cmd->port = PORT_FIBRE;
 129                cmd->autoneg = AUTONEG_DISABLE;
 130        }
 131        cmd->duplex = nic->duplex;
 132        ethtool_cmd_speed_set(cmd, nic->speed);
 133
 134        return 0;
 135}
 136
 137static u32 nicvf_get_link(struct net_device *netdev)
 138{
 139        struct nicvf *nic = netdev_priv(netdev);
 140
 141        return nic->link_up;
 142}
 143
 144static void nicvf_get_drvinfo(struct net_device *netdev,
 145                              struct ethtool_drvinfo *info)
 146{
 147        struct nicvf *nic = netdev_priv(netdev);
 148
 149        strlcpy(info->driver, DRV_NAME, sizeof(info->driver));
 150        strlcpy(info->version, DRV_VERSION, sizeof(info->version));
 151        strlcpy(info->bus_info, pci_name(nic->pdev), sizeof(info->bus_info));
 152}
 153
 154static u32 nicvf_get_msglevel(struct net_device *netdev)
 155{
 156        struct nicvf *nic = netdev_priv(netdev);
 157
 158        return nic->msg_enable;
 159}
 160
 161static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl)
 162{
 163        struct nicvf *nic = netdev_priv(netdev);
 164
 165        nic->msg_enable = lvl;
 166}
 167
 168static void nicvf_get_qset_strings(struct nicvf *nic, u8 **data, int qset)
 169{
 170        int stats, qidx;
 171        int start_qidx = qset * MAX_RCV_QUEUES_PER_QS;
 172
 173        for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
 174                for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
 175                        sprintf(*data, "rxq%d: %s", qidx + start_qidx,
 176                                nicvf_queue_stats[stats].name);
 177                        *data += ETH_GSTRING_LEN;
 178                }
 179        }
 180
 181        for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
 182                for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
 183                        sprintf(*data, "txq%d: %s", qidx + start_qidx,
 184                                nicvf_queue_stats[stats].name);
 185                        *data += ETH_GSTRING_LEN;
 186                }
 187        }
 188}
 189
 190static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
 191{
 192        struct nicvf *nic = netdev_priv(netdev);
 193        int stats;
 194        int sqs;
 195
 196        if (sset != ETH_SS_STATS)
 197                return;
 198
 199        for (stats = 0; stats < nicvf_n_hw_stats; stats++) {
 200                memcpy(data, nicvf_hw_stats[stats].name, ETH_GSTRING_LEN);
 201                data += ETH_GSTRING_LEN;
 202        }
 203
 204        for (stats = 0; stats < nicvf_n_drv_stats; stats++) {
 205                memcpy(data, nicvf_drv_stats[stats].name, ETH_GSTRING_LEN);
 206                data += ETH_GSTRING_LEN;
 207        }
 208
 209        nicvf_get_qset_strings(nic, &data, 0);
 210
 211        for (sqs = 0; sqs < nic->sqs_count; sqs++) {
 212                if (!nic->snicvf[sqs])
 213                        continue;
 214                nicvf_get_qset_strings(nic->snicvf[sqs], &data, sqs + 1);
 215        }
 216
 217        for (stats = 0; stats < BGX_RX_STATS_COUNT; stats++) {
 218                sprintf(data, "bgx_rxstat%d: ", stats);
 219                data += ETH_GSTRING_LEN;
 220        }
 221
 222        for (stats = 0; stats < BGX_TX_STATS_COUNT; stats++) {
 223                sprintf(data, "bgx_txstat%d: ", stats);
 224                data += ETH_GSTRING_LEN;
 225        }
 226}
 227
 228static int nicvf_get_sset_count(struct net_device *netdev, int sset)
 229{
 230        struct nicvf *nic = netdev_priv(netdev);
 231        int qstats_count;
 232        int sqs;
 233
 234        if (sset != ETH_SS_STATS)
 235                return -EINVAL;
 236
 237        qstats_count = nicvf_n_queue_stats *
 238                       (nic->qs->rq_cnt + nic->qs->sq_cnt);
 239        for (sqs = 0; sqs < nic->sqs_count; sqs++) {
 240                struct nicvf *snic;
 241
 242                snic = nic->snicvf[sqs];
 243                if (!snic)
 244                        continue;
 245                qstats_count += nicvf_n_queue_stats *
 246                                (snic->qs->rq_cnt + snic->qs->sq_cnt);
 247        }
 248
 249        return nicvf_n_hw_stats + nicvf_n_drv_stats +
 250                qstats_count +
 251                BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;
 252}
 253
 254static void nicvf_get_qset_stats(struct nicvf *nic,
 255                                 struct ethtool_stats *stats, u64 **data)
 256{
 257        int stat, qidx;
 258
 259        if (!nic)
 260                return;
 261
 262        for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
 263                nicvf_update_rq_stats(nic, qidx);
 264                for (stat = 0; stat < nicvf_n_queue_stats; stat++)
 265                        *((*data)++) = ((u64 *)&nic->qs->rq[qidx].stats)
 266                                        [nicvf_queue_stats[stat].index];
 267        }
 268
 269        for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
 270                nicvf_update_sq_stats(nic, qidx);
 271                for (stat = 0; stat < nicvf_n_queue_stats; stat++)
 272                        *((*data)++) = ((u64 *)&nic->qs->sq[qidx].stats)
 273                                        [nicvf_queue_stats[stat].index];
 274        }
 275}
 276
 277static void nicvf_get_ethtool_stats(struct net_device *netdev,
 278                                    struct ethtool_stats *stats, u64 *data)
 279{
 280        struct nicvf *nic = netdev_priv(netdev);
 281        int stat;
 282        int sqs;
 283
 284        nicvf_update_stats(nic);
 285
 286        /* Update LMAC stats */
 287        nicvf_update_lmac_stats(nic);
 288
 289        for (stat = 0; stat < nicvf_n_hw_stats; stat++)
 290                *(data++) = ((u64 *)&nic->hw_stats)
 291                                [nicvf_hw_stats[stat].index];
 292        for (stat = 0; stat < nicvf_n_drv_stats; stat++)
 293                *(data++) = ((u64 *)&nic->drv_stats)
 294                                [nicvf_drv_stats[stat].index];
 295
 296        nicvf_get_qset_stats(nic, stats, &data);
 297
 298        for (sqs = 0; sqs < nic->sqs_count; sqs++) {
 299                if (!nic->snicvf[sqs])
 300                        continue;
 301                nicvf_get_qset_stats(nic->snicvf[sqs], stats, &data);
 302        }
 303
 304        for (stat = 0; stat < BGX_RX_STATS_COUNT; stat++)
 305                *(data++) = nic->bgx_stats.rx_stats[stat];
 306        for (stat = 0; stat < BGX_TX_STATS_COUNT; stat++)
 307                *(data++) = nic->bgx_stats.tx_stats[stat];
 308}
 309
 310static int nicvf_get_regs_len(struct net_device *dev)
 311{
 312        return sizeof(u64) * NIC_VF_REG_COUNT;
 313}
 314
 315static void nicvf_get_regs(struct net_device *dev,
 316                           struct ethtool_regs *regs, void *reg)
 317{
 318        struct nicvf *nic = netdev_priv(dev);
 319        u64 *p = (u64 *)reg;
 320        u64 reg_offset;
 321        int mbox, key, stat, q;
 322        int i = 0;
 323
 324        regs->version = 0;
 325        memset(p, 0, NIC_VF_REG_COUNT);
 326
 327        p[i++] = nicvf_reg_read(nic, NIC_VNIC_CFG);
 328        /* Mailbox registers */
 329        for (mbox = 0; mbox < NIC_PF_VF_MAILBOX_SIZE; mbox++)
 330                p[i++] = nicvf_reg_read(nic,
 331                                        NIC_VF_PF_MAILBOX_0_1 | (mbox << 3));
 332
 333        p[i++] = nicvf_reg_read(nic, NIC_VF_INT);
 334        p[i++] = nicvf_reg_read(nic, NIC_VF_INT_W1S);
 335        p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1C);
 336        p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1S);
 337        p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG);
 338
 339        for (key = 0; key < RSS_HASH_KEY_SIZE; key++)
 340                p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_KEY_0_4 | (key << 3));
 341
 342        /* Tx/Rx statistics */
 343        for (stat = 0; stat < TX_STATS_ENUM_LAST; stat++)
 344                p[i++] = nicvf_reg_read(nic,
 345                                        NIC_VNIC_TX_STAT_0_4 | (stat << 3));
 346
 347        for (i = 0; i < RX_STATS_ENUM_LAST; i++)
 348                p[i++] = nicvf_reg_read(nic,
 349                                        NIC_VNIC_RX_STAT_0_13 | (stat << 3));
 350
 351        p[i++] = nicvf_reg_read(nic, NIC_QSET_RQ_GEN_CFG);
 352
 353        /* All completion queue's registers */
 354        for (q = 0; q < MAX_CMP_QUEUES_PER_QS; q++) {
 355                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG, q);
 356                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG2, q);
 357                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_THRESH, q);
 358                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_BASE, q);
 359                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, q);
 360                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_TAIL, q);
 361                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DOOR, q);
 362                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS, q);
 363                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS2, q);
 364                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DEBUG, q);
 365        }
 366
 367        /* All receive queue's registers */
 368        for (q = 0; q < MAX_RCV_QUEUES_PER_QS; q++) {
 369                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_CFG, q);
 370                p[i++] = nicvf_queue_reg_read(nic,
 371                                                  NIC_QSET_RQ_0_7_STAT_0_1, q);
 372                reg_offset = NIC_QSET_RQ_0_7_STAT_0_1 | (1 << 3);
 373                p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);
 374        }
 375
 376        for (q = 0; q < MAX_SND_QUEUES_PER_QS; q++) {
 377                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CFG, q);
 378                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_THRESH, q);
 379                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_BASE, q);
 380                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_HEAD, q);
 381                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_TAIL, q);
 382                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q);
 383                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q);
 384                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q);
 385                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CNM_CHG, q);
 386                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q);
 387                reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3);
 388                p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);
 389        }
 390
 391        for (q = 0; q < MAX_RCV_BUF_DESC_RINGS_PER_QS; q++) {
 392                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_CFG, q);
 393                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_THRESH, q);
 394                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_BASE, q);
 395                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_HEAD, q);
 396                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_TAIL, q);
 397                p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_DOOR, q);
 398                p[i++] = nicvf_queue_reg_read(nic,
 399                                              NIC_QSET_RBDR_0_1_STATUS0, q);
 400                p[i++] = nicvf_queue_reg_read(nic,
 401                                              NIC_QSET_RBDR_0_1_STATUS1, q);
 402                reg_offset = NIC_QSET_RBDR_0_1_PREFETCH_STATUS;
 403                p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);
 404        }
 405}
 406
 407static int nicvf_get_coalesce(struct net_device *netdev,
 408                              struct ethtool_coalesce *cmd)
 409{
 410        struct nicvf *nic = netdev_priv(netdev);
 411
 412        cmd->rx_coalesce_usecs = nic->cq_coalesce_usecs;
 413        return 0;
 414}
 415
 416static void nicvf_get_ringparam(struct net_device *netdev,
 417                                struct ethtool_ringparam *ring)
 418{
 419        struct nicvf *nic = netdev_priv(netdev);
 420        struct queue_set *qs = nic->qs;
 421
 422        ring->rx_max_pending = MAX_RCV_BUF_COUNT;
 423        ring->rx_pending = qs->rbdr_len;
 424        ring->tx_max_pending = MAX_SND_QUEUE_LEN;
 425        ring->tx_pending = qs->sq_len;
 426}
 427
 428static int nicvf_get_rss_hash_opts(struct nicvf *nic,
 429                                   struct ethtool_rxnfc *info)
 430{
 431        info->data = 0;
 432
 433        switch (info->flow_type) {
 434        case TCP_V4_FLOW:
 435        case TCP_V6_FLOW:
 436        case UDP_V4_FLOW:
 437        case UDP_V6_FLOW:
 438        case SCTP_V4_FLOW:
 439        case SCTP_V6_FLOW:
 440                info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
 441        case IPV4_FLOW:
 442        case IPV6_FLOW:
 443                info->data |= RXH_IP_SRC | RXH_IP_DST;
 444                break;
 445        default:
 446                return -EINVAL;
 447        }
 448
 449        return 0;
 450}
 451
 452static int nicvf_get_rxnfc(struct net_device *dev,
 453                           struct ethtool_rxnfc *info, u32 *rules)
 454{
 455        struct nicvf *nic = netdev_priv(dev);
 456        int ret = -EOPNOTSUPP;
 457
 458        switch (info->cmd) {
 459        case ETHTOOL_GRXRINGS:
 460                info->data = nic->rx_queues;
 461                ret = 0;
 462                break;
 463        case ETHTOOL_GRXFH:
 464                return nicvf_get_rss_hash_opts(nic, info);
 465        default:
 466                break;
 467        }
 468        return ret;
 469}
 470
 471static int nicvf_set_rss_hash_opts(struct nicvf *nic,
 472                                   struct ethtool_rxnfc *info)
 473{
 474        struct nicvf_rss_info *rss = &nic->rss_info;
 475        u64 rss_cfg = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG);
 476
 477        if (!rss->enable)
 478                netdev_err(nic->netdev,
 479                           "RSS is disabled, hash cannot be set\n");
 480
 481        netdev_info(nic->netdev, "Set RSS flow type = %d, data = %lld\n",
 482                    info->flow_type, info->data);
 483
 484        if (!(info->data & RXH_IP_SRC) || !(info->data & RXH_IP_DST))
 485                return -EINVAL;
 486
 487        switch (info->flow_type) {
 488        case TCP_V4_FLOW:
 489        case TCP_V6_FLOW:
 490                switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 491                case 0:
 492                        rss_cfg &= ~(1ULL << RSS_HASH_TCP);
 493                        break;
 494                case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 495                        rss_cfg |= (1ULL << RSS_HASH_TCP);
 496                        break;
 497                default:
 498                        return -EINVAL;
 499                }
 500                break;
 501        case UDP_V4_FLOW:
 502        case UDP_V6_FLOW:
 503                switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 504                case 0:
 505                        rss_cfg &= ~(1ULL << RSS_HASH_UDP);
 506                        break;
 507                case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 508                        rss_cfg |= (1ULL << RSS_HASH_UDP);
 509                        break;
 510                default:
 511                        return -EINVAL;
 512                }
 513                break;
 514        case SCTP_V4_FLOW:
 515        case SCTP_V6_FLOW:
 516                switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
 517                case 0:
 518                        rss_cfg &= ~(1ULL << RSS_HASH_L4ETC);
 519                        break;
 520                case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
 521                        rss_cfg |= (1ULL << RSS_HASH_L4ETC);
 522                        break;
 523                default:
 524                        return -EINVAL;
 525                }
 526                break;
 527        case IPV4_FLOW:
 528        case IPV6_FLOW:
 529                rss_cfg = RSS_HASH_IP;
 530                break;
 531        default:
 532                return -EINVAL;
 533        }
 534
 535        nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, rss_cfg);
 536        return 0;
 537}
 538
 539static int nicvf_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
 540{
 541        struct nicvf *nic = netdev_priv(dev);
 542
 543        switch (info->cmd) {
 544        case ETHTOOL_SRXFH:
 545                return nicvf_set_rss_hash_opts(nic, info);
 546        default:
 547                break;
 548        }
 549        return -EOPNOTSUPP;
 550}
 551
 552static u32 nicvf_get_rxfh_key_size(struct net_device *netdev)
 553{
 554        return RSS_HASH_KEY_SIZE * sizeof(u64);
 555}
 556
 557static u32 nicvf_get_rxfh_indir_size(struct net_device *dev)
 558{
 559        struct nicvf *nic = netdev_priv(dev);
 560
 561        return nic->rss_info.rss_size;
 562}
 563
 564static int nicvf_get_rxfh(struct net_device *dev, u32 *indir, u8 *hkey,
 565                          u8 *hfunc)
 566{
 567        struct nicvf *nic = netdev_priv(dev);
 568        struct nicvf_rss_info *rss = &nic->rss_info;
 569        int idx;
 570
 571        if (indir) {
 572                for (idx = 0; idx < rss->rss_size; idx++)
 573                        indir[idx] = rss->ind_tbl[idx];
 574        }
 575
 576        if (hkey)
 577                memcpy(hkey, rss->key, RSS_HASH_KEY_SIZE * sizeof(u64));
 578
 579        if (hfunc)
 580                *hfunc = ETH_RSS_HASH_TOP;
 581
 582        return 0;
 583}
 584
 585static int nicvf_set_rxfh(struct net_device *dev, const u32 *indir,
 586                          const u8 *hkey, u8 hfunc)
 587{
 588        struct nicvf *nic = netdev_priv(dev);
 589        struct nicvf_rss_info *rss = &nic->rss_info;
 590        int idx;
 591
 592        if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
 593                return -EOPNOTSUPP;
 594
 595        if (!rss->enable) {
 596                netdev_err(nic->netdev,
 597                           "RSS is disabled, cannot change settings\n");
 598                return -EIO;
 599        }
 600
 601        if (indir) {
 602                for (idx = 0; idx < rss->rss_size; idx++)
 603                        rss->ind_tbl[idx] = indir[idx];
 604        }
 605
 606        if (hkey) {
 607                memcpy(rss->key, hkey, RSS_HASH_KEY_SIZE * sizeof(u64));
 608                nicvf_set_rss_key(nic);
 609        }
 610
 611        nicvf_config_rss(nic);
 612        return 0;
 613}
 614
 615/* Get no of queues device supports and current queue count */
 616static void nicvf_get_channels(struct net_device *dev,
 617                               struct ethtool_channels *channel)
 618{
 619        struct nicvf *nic = netdev_priv(dev);
 620
 621        memset(channel, 0, sizeof(*channel));
 622
 623        channel->max_rx = nic->max_queues;
 624        channel->max_tx = nic->max_queues;
 625
 626        channel->rx_count = nic->rx_queues;
 627        channel->tx_count = nic->tx_queues;
 628}
 629
 630/* Set no of Tx, Rx queues to be used */
 631static int nicvf_set_channels(struct net_device *dev,
 632                              struct ethtool_channels *channel)
 633{
 634        struct nicvf *nic = netdev_priv(dev);
 635        int err = 0;
 636        bool if_up = netif_running(dev);
 637        int cqcount;
 638
 639        if (!channel->rx_count || !channel->tx_count)
 640                return -EINVAL;
 641        if (channel->rx_count > nic->max_queues)
 642                return -EINVAL;
 643        if (channel->tx_count > nic->max_queues)
 644                return -EINVAL;
 645
 646        if (if_up)
 647                nicvf_stop(dev);
 648
 649        cqcount = max(channel->rx_count, channel->tx_count);
 650
 651        if (cqcount > MAX_CMP_QUEUES_PER_QS) {
 652                nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS);
 653                nic->sqs_count = (nic->sqs_count / MAX_CMP_QUEUES_PER_QS) - 1;
 654        } else {
 655                nic->sqs_count = 0;
 656        }
 657
 658        nic->qs->rq_cnt = min_t(u32, channel->rx_count, MAX_RCV_QUEUES_PER_QS);
 659        nic->qs->sq_cnt = min_t(u32, channel->tx_count, MAX_SND_QUEUES_PER_QS);
 660        nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
 661
 662        nic->rx_queues = channel->rx_count;
 663        nic->tx_queues = channel->tx_count;
 664        err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues);
 665        if (err)
 666                return err;
 667
 668        if (if_up)
 669                nicvf_open(dev);
 670
 671        netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
 672                    nic->tx_queues, nic->rx_queues);
 673
 674        return err;
 675}
 676
 677static const struct ethtool_ops nicvf_ethtool_ops = {
 678        .get_settings           = nicvf_get_settings,
 679        .get_link               = nicvf_get_link,
 680        .get_drvinfo            = nicvf_get_drvinfo,
 681        .get_msglevel           = nicvf_get_msglevel,
 682        .set_msglevel           = nicvf_set_msglevel,
 683        .get_strings            = nicvf_get_strings,
 684        .get_sset_count         = nicvf_get_sset_count,
 685        .get_ethtool_stats      = nicvf_get_ethtool_stats,
 686        .get_regs_len           = nicvf_get_regs_len,
 687        .get_regs               = nicvf_get_regs,
 688        .get_coalesce           = nicvf_get_coalesce,
 689        .get_ringparam          = nicvf_get_ringparam,
 690        .get_rxnfc              = nicvf_get_rxnfc,
 691        .set_rxnfc              = nicvf_set_rxnfc,
 692        .get_rxfh_key_size      = nicvf_get_rxfh_key_size,
 693        .get_rxfh_indir_size    = nicvf_get_rxfh_indir_size,
 694        .get_rxfh               = nicvf_get_rxfh,
 695        .set_rxfh               = nicvf_set_rxfh,
 696        .get_channels           = nicvf_get_channels,
 697        .set_channels           = nicvf_set_channels,
 698        .get_ts_info            = ethtool_op_get_ts_info,
 699};
 700
 701void nicvf_set_ethtool_ops(struct net_device *netdev)
 702{
 703        netdev->ethtool_ops = &nicvf_ethtool_ops;
 704}
 705