892 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (C) 2015 Cavium, Inc.4 */5 6/* ETHTOOL Support for VNIC_VF Device*/7 8#include <linux/ethtool.h>9#include <linux/pci.h>10#include <linux/net_tstamp.h>11 12#include "nic_reg.h"13#include "nic.h"14#include "nicvf_queues.h"15#include "q_struct.h"16#include "thunder_bgx.h"17#include "../common/cavium_ptp.h"18 19#define DRV_NAME "nicvf"20 21struct nicvf_stat {22 char name[ETH_GSTRING_LEN];23 unsigned int index;24};25 26#define NICVF_HW_STAT(stat) { \27 .name = #stat, \28 .index = offsetof(struct nicvf_hw_stats, stat) / sizeof(u64), \29}30 31#define NICVF_DRV_STAT(stat) { \32 .name = #stat, \33 .index = offsetof(struct nicvf_drv_stats, stat) / sizeof(u64), \34}35 36static const struct nicvf_stat nicvf_hw_stats[] = {37 NICVF_HW_STAT(rx_bytes),38 NICVF_HW_STAT(rx_frames),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_drops),43 NICVF_HW_STAT(rx_drop_red),44 NICVF_HW_STAT(rx_drop_red_bytes),45 NICVF_HW_STAT(rx_drop_overrun),46 NICVF_HW_STAT(rx_drop_overrun_bytes),47 NICVF_HW_STAT(rx_drop_bcast),48 NICVF_HW_STAT(rx_drop_mcast),49 NICVF_HW_STAT(rx_drop_l3_bcast),50 NICVF_HW_STAT(rx_drop_l3_mcast),51 NICVF_HW_STAT(rx_fcs_errors),52 NICVF_HW_STAT(rx_l2_errors),53 NICVF_HW_STAT(tx_bytes),54 NICVF_HW_STAT(tx_frames),55 NICVF_HW_STAT(tx_ucast_frames),56 NICVF_HW_STAT(tx_bcast_frames),57 NICVF_HW_STAT(tx_mcast_frames),58 NICVF_HW_STAT(tx_drops),59};60 61static const struct nicvf_stat nicvf_drv_stats[] = {62 NICVF_DRV_STAT(rx_bgx_truncated_pkts),63 NICVF_DRV_STAT(rx_jabber_errs),64 NICVF_DRV_STAT(rx_fcs_errs),65 NICVF_DRV_STAT(rx_bgx_errs),66 NICVF_DRV_STAT(rx_prel2_errs),67 NICVF_DRV_STAT(rx_l2_hdr_malformed),68 NICVF_DRV_STAT(rx_oversize),69 NICVF_DRV_STAT(rx_undersize),70 NICVF_DRV_STAT(rx_l2_len_mismatch),71 NICVF_DRV_STAT(rx_l2_pclp),72 NICVF_DRV_STAT(rx_ip_ver_errs),73 NICVF_DRV_STAT(rx_ip_csum_errs),74 NICVF_DRV_STAT(rx_ip_hdr_malformed),75 NICVF_DRV_STAT(rx_ip_payload_malformed),76 NICVF_DRV_STAT(rx_ip_ttl_errs),77 NICVF_DRV_STAT(rx_l3_pclp),78 NICVF_DRV_STAT(rx_l4_malformed),79 NICVF_DRV_STAT(rx_l4_csum_errs),80 NICVF_DRV_STAT(rx_udp_len_errs),81 NICVF_DRV_STAT(rx_l4_port_errs),82 NICVF_DRV_STAT(rx_tcp_flag_errs),83 NICVF_DRV_STAT(rx_tcp_offset_errs),84 NICVF_DRV_STAT(rx_l4_pclp),85 NICVF_DRV_STAT(rx_truncated_pkts),86 87 NICVF_DRV_STAT(tx_desc_fault),88 NICVF_DRV_STAT(tx_hdr_cons_err),89 NICVF_DRV_STAT(tx_subdesc_err),90 NICVF_DRV_STAT(tx_max_size_exceeded),91 NICVF_DRV_STAT(tx_imm_size_oflow),92 NICVF_DRV_STAT(tx_data_seq_err),93 NICVF_DRV_STAT(tx_mem_seq_err),94 NICVF_DRV_STAT(tx_lock_viol),95 NICVF_DRV_STAT(tx_data_fault),96 NICVF_DRV_STAT(tx_tstmp_conflict),97 NICVF_DRV_STAT(tx_tstmp_timeout),98 NICVF_DRV_STAT(tx_mem_fault),99 NICVF_DRV_STAT(tx_csum_overlap),100 NICVF_DRV_STAT(tx_csum_overflow),101 102 NICVF_DRV_STAT(tx_tso),103 NICVF_DRV_STAT(tx_timeout),104 NICVF_DRV_STAT(txq_stop),105 NICVF_DRV_STAT(txq_wake),106 NICVF_DRV_STAT(rcv_buffer_alloc_failures),107 NICVF_DRV_STAT(page_alloc),108};109 110static const struct nicvf_stat nicvf_queue_stats[] = {111 { "bytes", 0 },112 { "frames", 1 },113};114 115static const unsigned int nicvf_n_hw_stats = ARRAY_SIZE(nicvf_hw_stats);116static const unsigned int nicvf_n_drv_stats = ARRAY_SIZE(nicvf_drv_stats);117static const unsigned int nicvf_n_queue_stats = ARRAY_SIZE(nicvf_queue_stats);118 119static int nicvf_get_link_ksettings(struct net_device *netdev,120 struct ethtool_link_ksettings *cmd)121{122 struct nicvf *nic = netdev_priv(netdev);123 u32 supported, advertising;124 125 supported = 0;126 advertising = 0;127 128 if (!nic->link_up) {129 cmd->base.duplex = DUPLEX_UNKNOWN;130 cmd->base.speed = SPEED_UNKNOWN;131 return 0;132 }133 134 switch (nic->speed) {135 case SPEED_1000:136 cmd->base.port = PORT_MII | PORT_TP;137 cmd->base.autoneg = AUTONEG_ENABLE;138 supported |= SUPPORTED_MII | SUPPORTED_TP;139 supported |= SUPPORTED_1000baseT_Full |140 SUPPORTED_1000baseT_Half |141 SUPPORTED_100baseT_Full |142 SUPPORTED_100baseT_Half |143 SUPPORTED_10baseT_Full |144 SUPPORTED_10baseT_Half;145 supported |= SUPPORTED_Autoneg;146 advertising |= ADVERTISED_1000baseT_Full |147 ADVERTISED_1000baseT_Half |148 ADVERTISED_100baseT_Full |149 ADVERTISED_100baseT_Half |150 ADVERTISED_10baseT_Full |151 ADVERTISED_10baseT_Half;152 break;153 case SPEED_10000:154 if (nic->mac_type == BGX_MODE_RXAUI) {155 cmd->base.port = PORT_TP;156 supported |= SUPPORTED_TP;157 } else {158 cmd->base.port = PORT_FIBRE;159 supported |= SUPPORTED_FIBRE;160 }161 cmd->base.autoneg = AUTONEG_DISABLE;162 supported |= SUPPORTED_10000baseT_Full;163 break;164 case SPEED_40000:165 cmd->base.port = PORT_FIBRE;166 cmd->base.autoneg = AUTONEG_DISABLE;167 supported |= SUPPORTED_FIBRE;168 supported |= SUPPORTED_40000baseCR4_Full;169 break;170 }171 cmd->base.duplex = nic->duplex;172 cmd->base.speed = nic->speed;173 174 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,175 supported);176 ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,177 advertising);178 179 return 0;180}181 182static u32 nicvf_get_link(struct net_device *netdev)183{184 struct nicvf *nic = netdev_priv(netdev);185 186 return nic->link_up;187}188 189static void nicvf_get_drvinfo(struct net_device *netdev,190 struct ethtool_drvinfo *info)191{192 struct nicvf *nic = netdev_priv(netdev);193 194 strscpy(info->driver, DRV_NAME, sizeof(info->driver));195 strscpy(info->bus_info, pci_name(nic->pdev), sizeof(info->bus_info));196}197 198static u32 nicvf_get_msglevel(struct net_device *netdev)199{200 struct nicvf *nic = netdev_priv(netdev);201 202 return nic->msg_enable;203}204 205static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl)206{207 struct nicvf *nic = netdev_priv(netdev);208 209 nic->msg_enable = lvl;210}211 212static void nicvf_get_qset_strings(struct nicvf *nic, u8 **data, int qset)213{214 int stats, qidx;215 int start_qidx = qset * MAX_RCV_QUEUES_PER_QS;216 217 for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {218 for (stats = 0; stats < nicvf_n_queue_stats; stats++) {219 sprintf(*data, "rxq%d: %s", qidx + start_qidx,220 nicvf_queue_stats[stats].name);221 *data += ETH_GSTRING_LEN;222 }223 }224 225 for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {226 for (stats = 0; stats < nicvf_n_queue_stats; stats++) {227 sprintf(*data, "txq%d: %s", qidx + start_qidx,228 nicvf_queue_stats[stats].name);229 *data += ETH_GSTRING_LEN;230 }231 }232}233 234static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)235{236 struct nicvf *nic = netdev_priv(netdev);237 int stats;238 int sqs;239 240 if (sset != ETH_SS_STATS)241 return;242 243 for (stats = 0; stats < nicvf_n_hw_stats; stats++) {244 memcpy(data, nicvf_hw_stats[stats].name, ETH_GSTRING_LEN);245 data += ETH_GSTRING_LEN;246 }247 248 for (stats = 0; stats < nicvf_n_drv_stats; stats++) {249 memcpy(data, nicvf_drv_stats[stats].name, ETH_GSTRING_LEN);250 data += ETH_GSTRING_LEN;251 }252 253 nicvf_get_qset_strings(nic, &data, 0);254 255 for (sqs = 0; sqs < nic->sqs_count; sqs++) {256 if (!nic->snicvf[sqs])257 continue;258 nicvf_get_qset_strings(nic->snicvf[sqs], &data, sqs + 1);259 }260 261 for (stats = 0; stats < BGX_RX_STATS_COUNT; stats++) {262 sprintf(data, "bgx_rxstat%d: ", stats);263 data += ETH_GSTRING_LEN;264 }265 266 for (stats = 0; stats < BGX_TX_STATS_COUNT; stats++) {267 sprintf(data, "bgx_txstat%d: ", stats);268 data += ETH_GSTRING_LEN;269 }270}271 272static int nicvf_get_sset_count(struct net_device *netdev, int sset)273{274 struct nicvf *nic = netdev_priv(netdev);275 int qstats_count;276 int sqs;277 278 if (sset != ETH_SS_STATS)279 return -EINVAL;280 281 qstats_count = nicvf_n_queue_stats *282 (nic->qs->rq_cnt + nic->qs->sq_cnt);283 for (sqs = 0; sqs < nic->sqs_count; sqs++) {284 struct nicvf *snic;285 286 snic = nic->snicvf[sqs];287 if (!snic)288 continue;289 qstats_count += nicvf_n_queue_stats *290 (snic->qs->rq_cnt + snic->qs->sq_cnt);291 }292 293 return nicvf_n_hw_stats + nicvf_n_drv_stats +294 qstats_count +295 BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;296}297 298static void nicvf_get_qset_stats(struct nicvf *nic,299 struct ethtool_stats *stats, u64 **data)300{301 int stat, qidx;302 303 if (!nic)304 return;305 306 for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {307 nicvf_update_rq_stats(nic, qidx);308 for (stat = 0; stat < nicvf_n_queue_stats; stat++)309 *((*data)++) = ((u64 *)&nic->qs->rq[qidx].stats)310 [nicvf_queue_stats[stat].index];311 }312 313 for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {314 nicvf_update_sq_stats(nic, qidx);315 for (stat = 0; stat < nicvf_n_queue_stats; stat++)316 *((*data)++) = ((u64 *)&nic->qs->sq[qidx].stats)317 [nicvf_queue_stats[stat].index];318 }319}320 321static void nicvf_get_ethtool_stats(struct net_device *netdev,322 struct ethtool_stats *stats, u64 *data)323{324 struct nicvf *nic = netdev_priv(netdev);325 int stat, tmp_stats;326 int sqs, cpu;327 328 nicvf_update_stats(nic);329 330 /* Update LMAC stats */331 nicvf_update_lmac_stats(nic);332 333 for (stat = 0; stat < nicvf_n_hw_stats; stat++)334 *(data++) = ((u64 *)&nic->hw_stats)335 [nicvf_hw_stats[stat].index];336 for (stat = 0; stat < nicvf_n_drv_stats; stat++) {337 tmp_stats = 0;338 for_each_possible_cpu(cpu)339 tmp_stats += ((u64 *)per_cpu_ptr(nic->drv_stats, cpu))340 [nicvf_drv_stats[stat].index];341 *(data++) = tmp_stats;342 }343 344 nicvf_get_qset_stats(nic, stats, &data);345 346 for (sqs = 0; sqs < nic->sqs_count; sqs++) {347 if (!nic->snicvf[sqs])348 continue;349 nicvf_get_qset_stats(nic->snicvf[sqs], stats, &data);350 }351 352 for (stat = 0; stat < BGX_RX_STATS_COUNT; stat++)353 *(data++) = nic->bgx_stats.rx_stats[stat];354 for (stat = 0; stat < BGX_TX_STATS_COUNT; stat++)355 *(data++) = nic->bgx_stats.tx_stats[stat];356}357 358static int nicvf_get_regs_len(struct net_device *dev)359{360 return sizeof(u64) * NIC_VF_REG_COUNT;361}362 363static void nicvf_get_regs(struct net_device *dev,364 struct ethtool_regs *regs, void *reg)365{366 struct nicvf *nic = netdev_priv(dev);367 u64 *p = (u64 *)reg;368 u64 reg_offset;369 int mbox, key, stat, q;370 int i = 0;371 372 regs->version = 0;373 memset(p, 0, NIC_VF_REG_COUNT);374 375 p[i++] = nicvf_reg_read(nic, NIC_VNIC_CFG);376 /* Mailbox registers */377 for (mbox = 0; mbox < NIC_PF_VF_MAILBOX_SIZE; mbox++)378 p[i++] = nicvf_reg_read(nic,379 NIC_VF_PF_MAILBOX_0_1 | (mbox << 3));380 381 p[i++] = nicvf_reg_read(nic, NIC_VF_INT);382 p[i++] = nicvf_reg_read(nic, NIC_VF_INT_W1S);383 p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1C);384 p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1S);385 p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG);386 387 for (key = 0; key < RSS_HASH_KEY_SIZE; key++)388 p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_KEY_0_4 | (key << 3));389 390 /* Tx/Rx statistics */391 for (stat = 0; stat < TX_STATS_ENUM_LAST; stat++)392 p[i++] = nicvf_reg_read(nic,393 NIC_VNIC_TX_STAT_0_4 | (stat << 3));394 395 for (i = 0; i < RX_STATS_ENUM_LAST; i++)396 p[i++] = nicvf_reg_read(nic,397 NIC_VNIC_RX_STAT_0_13 | (stat << 3));398 399 p[i++] = nicvf_reg_read(nic, NIC_QSET_RQ_GEN_CFG);400 401 /* All completion queue's registers */402 for (q = 0; q < MAX_CMP_QUEUES_PER_QS; q++) {403 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG, q);404 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG2, q);405 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_THRESH, q);406 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_BASE, q);407 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, q);408 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_TAIL, q);409 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DOOR, q);410 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS, q);411 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS2, q);412 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DEBUG, q);413 }414 415 /* All receive queue's registers */416 for (q = 0; q < MAX_RCV_QUEUES_PER_QS; q++) {417 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_CFG, q);418 p[i++] = nicvf_queue_reg_read(nic,419 NIC_QSET_RQ_0_7_STAT_0_1, q);420 reg_offset = NIC_QSET_RQ_0_7_STAT_0_1 | (1 << 3);421 p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);422 }423 424 for (q = 0; q < MAX_SND_QUEUES_PER_QS; q++) {425 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CFG, q);426 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_THRESH, q);427 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_BASE, q);428 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_HEAD, q);429 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_TAIL, q);430 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q);431 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q);432 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q);433 /* Padding, was NIC_QSET_SQ_0_7_CNM_CHG, which434 * produces bus errors when read435 */436 p[i++] = 0;437 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q);438 reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3);439 p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);440 }441 442 for (q = 0; q < MAX_RCV_BUF_DESC_RINGS_PER_QS; q++) {443 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_CFG, q);444 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_THRESH, q);445 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_BASE, q);446 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_HEAD, q);447 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_TAIL, q);448 p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_DOOR, q);449 p[i++] = nicvf_queue_reg_read(nic,450 NIC_QSET_RBDR_0_1_STATUS0, q);451 p[i++] = nicvf_queue_reg_read(nic,452 NIC_QSET_RBDR_0_1_STATUS1, q);453 reg_offset = NIC_QSET_RBDR_0_1_PREFETCH_STATUS;454 p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);455 }456}457 458static int nicvf_get_coalesce(struct net_device *netdev,459 struct ethtool_coalesce *cmd,460 struct kernel_ethtool_coalesce *kernel_coal,461 struct netlink_ext_ack *extack)462{463 struct nicvf *nic = netdev_priv(netdev);464 465 cmd->rx_coalesce_usecs = nic->cq_coalesce_usecs;466 return 0;467}468 469static void nicvf_get_ringparam(struct net_device *netdev,470 struct ethtool_ringparam *ring,471 struct kernel_ethtool_ringparam *kernel_ring,472 struct netlink_ext_ack *extack)473{474 struct nicvf *nic = netdev_priv(netdev);475 struct queue_set *qs = nic->qs;476 477 ring->rx_max_pending = MAX_CMP_QUEUE_LEN;478 ring->rx_pending = qs->cq_len;479 ring->tx_max_pending = MAX_SND_QUEUE_LEN;480 ring->tx_pending = qs->sq_len;481}482 483static int nicvf_set_ringparam(struct net_device *netdev,484 struct ethtool_ringparam *ring,485 struct kernel_ethtool_ringparam *kernel_ring,486 struct netlink_ext_ack *extack)487{488 struct nicvf *nic = netdev_priv(netdev);489 struct queue_set *qs = nic->qs;490 u32 rx_count, tx_count;491 492 /* Due to HW errata this is not supported on T88 pass 1.x silicon */493 if (pass1_silicon(nic->pdev))494 return -EINVAL;495 496 if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))497 return -EINVAL;498 499 tx_count = clamp_t(u32, ring->tx_pending,500 MIN_SND_QUEUE_LEN, MAX_SND_QUEUE_LEN);501 rx_count = clamp_t(u32, ring->rx_pending,502 MIN_CMP_QUEUE_LEN, MAX_CMP_QUEUE_LEN);503 504 if ((tx_count == qs->sq_len) && (rx_count == qs->cq_len))505 return 0;506 507 /* Permitted lengths are 1K, 2K, 4K, 8K, 16K, 32K, 64K */508 qs->sq_len = rounddown_pow_of_two(tx_count);509 qs->cq_len = rounddown_pow_of_two(rx_count);510 511 if (netif_running(netdev)) {512 nicvf_stop(netdev);513 nicvf_open(netdev);514 }515 516 return 0;517}518 519static int nicvf_get_rss_hash_opts(struct nicvf *nic,520 struct ethtool_rxnfc *info)521{522 info->data = 0;523 524 switch (info->flow_type) {525 case TCP_V4_FLOW:526 case TCP_V6_FLOW:527 case UDP_V4_FLOW:528 case UDP_V6_FLOW:529 case SCTP_V4_FLOW:530 case SCTP_V6_FLOW:531 info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;532 fallthrough;533 case IPV4_FLOW:534 case IPV6_FLOW:535 info->data |= RXH_IP_SRC | RXH_IP_DST;536 break;537 default:538 return -EINVAL;539 }540 541 return 0;542}543 544static int nicvf_get_rxnfc(struct net_device *dev,545 struct ethtool_rxnfc *info, u32 *rules)546{547 struct nicvf *nic = netdev_priv(dev);548 int ret = -EOPNOTSUPP;549 550 switch (info->cmd) {551 case ETHTOOL_GRXRINGS:552 info->data = nic->rx_queues;553 ret = 0;554 break;555 case ETHTOOL_GRXFH:556 return nicvf_get_rss_hash_opts(nic, info);557 default:558 break;559 }560 return ret;561}562 563static int nicvf_set_rss_hash_opts(struct nicvf *nic,564 struct ethtool_rxnfc *info)565{566 struct nicvf_rss_info *rss = &nic->rss_info;567 u64 rss_cfg = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG);568 569 if (!rss->enable)570 netdev_err(nic->netdev,571 "RSS is disabled, hash cannot be set\n");572 573 netdev_info(nic->netdev, "Set RSS flow type = %d, data = %lld\n",574 info->flow_type, info->data);575 576 if (!(info->data & RXH_IP_SRC) || !(info->data & RXH_IP_DST))577 return -EINVAL;578 579 switch (info->flow_type) {580 case TCP_V4_FLOW:581 case TCP_V6_FLOW:582 switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {583 case 0:584 rss_cfg &= ~(1ULL << RSS_HASH_TCP);585 break;586 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):587 rss_cfg |= (1ULL << RSS_HASH_TCP);588 break;589 default:590 return -EINVAL;591 }592 break;593 case UDP_V4_FLOW:594 case UDP_V6_FLOW:595 switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {596 case 0:597 rss_cfg &= ~(1ULL << RSS_HASH_UDP);598 break;599 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):600 rss_cfg |= (1ULL << RSS_HASH_UDP);601 break;602 default:603 return -EINVAL;604 }605 break;606 case SCTP_V4_FLOW:607 case SCTP_V6_FLOW:608 switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {609 case 0:610 rss_cfg &= ~(1ULL << RSS_HASH_L4ETC);611 break;612 case (RXH_L4_B_0_1 | RXH_L4_B_2_3):613 rss_cfg |= (1ULL << RSS_HASH_L4ETC);614 break;615 default:616 return -EINVAL;617 }618 break;619 case IPV4_FLOW:620 case IPV6_FLOW:621 rss_cfg = RSS_HASH_IP;622 break;623 default:624 return -EINVAL;625 }626 627 nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, rss_cfg);628 return 0;629}630 631static int nicvf_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)632{633 struct nicvf *nic = netdev_priv(dev);634 635 switch (info->cmd) {636 case ETHTOOL_SRXFH:637 return nicvf_set_rss_hash_opts(nic, info);638 default:639 break;640 }641 return -EOPNOTSUPP;642}643 644static u32 nicvf_get_rxfh_key_size(struct net_device *netdev)645{646 return RSS_HASH_KEY_SIZE * sizeof(u64);647}648 649static u32 nicvf_get_rxfh_indir_size(struct net_device *dev)650{651 struct nicvf *nic = netdev_priv(dev);652 653 return nic->rss_info.rss_size;654}655 656static int nicvf_get_rxfh(struct net_device *dev,657 struct ethtool_rxfh_param *rxfh)658{659 struct nicvf *nic = netdev_priv(dev);660 struct nicvf_rss_info *rss = &nic->rss_info;661 int idx;662 663 if (rxfh->indir) {664 for (idx = 0; idx < rss->rss_size; idx++)665 rxfh->indir[idx] = rss->ind_tbl[idx];666 }667 668 if (rxfh->key)669 memcpy(rxfh->key, rss->key, RSS_HASH_KEY_SIZE * sizeof(u64));670 671 rxfh->hfunc = ETH_RSS_HASH_TOP;672 673 return 0;674}675 676static int nicvf_set_rxfh(struct net_device *dev,677 struct ethtool_rxfh_param *rxfh,678 struct netlink_ext_ack *extack)679{680 struct nicvf *nic = netdev_priv(dev);681 struct nicvf_rss_info *rss = &nic->rss_info;682 int idx;683 684 if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&685 rxfh->hfunc != ETH_RSS_HASH_TOP)686 return -EOPNOTSUPP;687 688 if (!rss->enable) {689 netdev_err(nic->netdev,690 "RSS is disabled, cannot change settings\n");691 return -EIO;692 }693 694 if (rxfh->indir) {695 for (idx = 0; idx < rss->rss_size; idx++)696 rss->ind_tbl[idx] = rxfh->indir[idx];697 }698 699 if (rxfh->key) {700 memcpy(rss->key, rxfh->key, RSS_HASH_KEY_SIZE * sizeof(u64));701 nicvf_set_rss_key(nic);702 }703 704 nicvf_config_rss(nic);705 return 0;706}707 708/* Get no of queues device supports and current queue count */709static void nicvf_get_channels(struct net_device *dev,710 struct ethtool_channels *channel)711{712 struct nicvf *nic = netdev_priv(dev);713 714 memset(channel, 0, sizeof(*channel));715 716 channel->max_rx = nic->max_queues;717 channel->max_tx = nic->max_queues;718 719 channel->rx_count = nic->rx_queues;720 channel->tx_count = nic->tx_queues;721}722 723/* Set no of Tx, Rx queues to be used */724static int nicvf_set_channels(struct net_device *dev,725 struct ethtool_channels *channel)726{727 struct nicvf *nic = netdev_priv(dev);728 int err = 0;729 bool if_up = netif_running(dev);730 u8 cqcount, txq_count;731 732 if (!channel->rx_count || !channel->tx_count)733 return -EINVAL;734 if (channel->rx_count > nic->max_queues)735 return -EINVAL;736 if (channel->tx_count > nic->max_queues)737 return -EINVAL;738 739 if (channel->tx_count + channel->rx_count > nic->max_queues) {740 if (nic->xdp_prog) {741 netdev_err(nic->netdev,742 "XDP mode, RXQs + TXQs > Max %d\n",743 nic->max_queues);744 return -EINVAL;745 }746 747 xdp_clear_features_flag(nic->netdev);748 } else if (!pass1_silicon(nic->pdev)) {749 xdp_set_features_flag(dev, NETDEV_XDP_ACT_BASIC);750 }751 752 if (if_up)753 nicvf_stop(dev);754 755 nic->rx_queues = channel->rx_count;756 nic->tx_queues = channel->tx_count;757 if (!nic->xdp_prog)758 nic->xdp_tx_queues = 0;759 else760 nic->xdp_tx_queues = channel->rx_count;761 762 txq_count = nic->xdp_tx_queues + nic->tx_queues;763 cqcount = max(nic->rx_queues, txq_count);764 765 if (cqcount > MAX_CMP_QUEUES_PER_QS) {766 nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS);767 nic->sqs_count = (nic->sqs_count / MAX_CMP_QUEUES_PER_QS) - 1;768 } else {769 nic->sqs_count = 0;770 }771 772 nic->qs->rq_cnt = min_t(u8, nic->rx_queues, MAX_RCV_QUEUES_PER_QS);773 nic->qs->sq_cnt = min_t(u8, txq_count, MAX_SND_QUEUES_PER_QS);774 nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);775 776 err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues);777 if (err)778 return err;779 780 if (if_up)781 nicvf_open(dev);782 783 netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",784 nic->tx_queues, nic->rx_queues);785 786 return err;787}788 789static void nicvf_get_pauseparam(struct net_device *dev,790 struct ethtool_pauseparam *pause)791{792 struct nicvf *nic = netdev_priv(dev);793 union nic_mbx mbx = {};794 795 /* Supported only for 10G/40G interfaces */796 if ((nic->mac_type == BGX_MODE_SGMII) ||797 (nic->mac_type == BGX_MODE_QSGMII) ||798 (nic->mac_type == BGX_MODE_RGMII))799 return;800 801 mbx.pfc.msg = NIC_MBOX_MSG_PFC;802 mbx.pfc.get = 1;803 if (!nicvf_send_msg_to_pf(nic, &mbx)) {804 pause->autoneg = nic->pfc.autoneg;805 pause->rx_pause = nic->pfc.fc_rx;806 pause->tx_pause = nic->pfc.fc_tx;807 }808}809 810static int nicvf_set_pauseparam(struct net_device *dev,811 struct ethtool_pauseparam *pause)812{813 struct nicvf *nic = netdev_priv(dev);814 union nic_mbx mbx = {};815 816 /* Supported only for 10G/40G interfaces */817 if ((nic->mac_type == BGX_MODE_SGMII) ||818 (nic->mac_type == BGX_MODE_QSGMII) ||819 (nic->mac_type == BGX_MODE_RGMII))820 return -EOPNOTSUPP;821 822 if (pause->autoneg)823 return -EOPNOTSUPP;824 825 mbx.pfc.msg = NIC_MBOX_MSG_PFC;826 mbx.pfc.get = 0;827 mbx.pfc.fc_rx = pause->rx_pause;828 mbx.pfc.fc_tx = pause->tx_pause;829 if (nicvf_send_msg_to_pf(nic, &mbx))830 return -EAGAIN;831 832 nic->pfc.fc_rx = pause->rx_pause;833 nic->pfc.fc_tx = pause->tx_pause;834 835 return 0;836}837 838static int nicvf_get_ts_info(struct net_device *netdev,839 struct kernel_ethtool_ts_info *info)840{841 struct nicvf *nic = netdev_priv(netdev);842 843 if (!nic->ptp_clock)844 return ethtool_op_get_ts_info(netdev, info);845 846 info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |847 SOF_TIMESTAMPING_TX_HARDWARE |848 SOF_TIMESTAMPING_RX_HARDWARE |849 SOF_TIMESTAMPING_RAW_HARDWARE;850 851 info->phc_index = cavium_ptp_clock_index(nic->ptp_clock);852 853 info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);854 855 info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |856 (1 << HWTSTAMP_FILTER_ALL);857 858 return 0;859}860 861static const struct ethtool_ops nicvf_ethtool_ops = {862 .get_link = nicvf_get_link,863 .get_drvinfo = nicvf_get_drvinfo,864 .get_msglevel = nicvf_get_msglevel,865 .set_msglevel = nicvf_set_msglevel,866 .get_strings = nicvf_get_strings,867 .get_sset_count = nicvf_get_sset_count,868 .get_ethtool_stats = nicvf_get_ethtool_stats,869 .get_regs_len = nicvf_get_regs_len,870 .get_regs = nicvf_get_regs,871 .get_coalesce = nicvf_get_coalesce,872 .get_ringparam = nicvf_get_ringparam,873 .set_ringparam = nicvf_set_ringparam,874 .get_rxnfc = nicvf_get_rxnfc,875 .set_rxnfc = nicvf_set_rxnfc,876 .get_rxfh_key_size = nicvf_get_rxfh_key_size,877 .get_rxfh_indir_size = nicvf_get_rxfh_indir_size,878 .get_rxfh = nicvf_get_rxfh,879 .set_rxfh = nicvf_set_rxfh,880 .get_channels = nicvf_get_channels,881 .set_channels = nicvf_set_channels,882 .get_pauseparam = nicvf_get_pauseparam,883 .set_pauseparam = nicvf_set_pauseparam,884 .get_ts_info = nicvf_get_ts_info,885 .get_link_ksettings = nicvf_get_link_ksettings,886};887 888void nicvf_set_ethtool_ops(struct net_device *netdev)889{890 netdev->ethtool_ops = &nicvf_ethtool_ops;891}892