125763b3cSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
24863dea3SSunil Goutham /*
34863dea3SSunil Goutham * Copyright (C) 2015 Cavium, Inc.
44863dea3SSunil Goutham */
54863dea3SSunil Goutham
64863dea3SSunil Goutham /* ETHTOOL Support for VNIC_VF Device*/
74863dea3SSunil Goutham
8cc69837fSJakub Kicinski #include <linux/ethtool.h>
94863dea3SSunil Goutham #include <linux/pci.h>
104a875509SSunil Goutham #include <linux/net_tstamp.h>
114863dea3SSunil Goutham
124863dea3SSunil Goutham #include "nic_reg.h"
134863dea3SSunil Goutham #include "nic.h"
144863dea3SSunil Goutham #include "nicvf_queues.h"
154863dea3SSunil Goutham #include "q_struct.h"
164863dea3SSunil Goutham #include "thunder_bgx.h"
174a875509SSunil Goutham #include "../common/cavium_ptp.h"
184863dea3SSunil Goutham
196b9e6547SVadim Lomovtsev #define DRV_NAME "nicvf"
204863dea3SSunil Goutham
214863dea3SSunil Goutham struct nicvf_stat {
224863dea3SSunil Goutham char name[ETH_GSTRING_LEN];
234863dea3SSunil Goutham unsigned int index;
244863dea3SSunil Goutham };
254863dea3SSunil Goutham
264863dea3SSunil Goutham #define NICVF_HW_STAT(stat) { \
274863dea3SSunil Goutham .name = #stat, \
284863dea3SSunil Goutham .index = offsetof(struct nicvf_hw_stats, stat) / sizeof(u64), \
294863dea3SSunil Goutham }
304863dea3SSunil Goutham
314863dea3SSunil Goutham #define NICVF_DRV_STAT(stat) { \
324863dea3SSunil Goutham .name = #stat, \
334863dea3SSunil Goutham .index = offsetof(struct nicvf_drv_stats, stat) / sizeof(u64), \
344863dea3SSunil Goutham }
354863dea3SSunil Goutham
364863dea3SSunil Goutham static const struct nicvf_stat nicvf_hw_stats[] = {
37a2dc5dedSSunil Goutham NICVF_HW_STAT(rx_bytes),
38964cb69bSSunil Goutham NICVF_HW_STAT(rx_frames),
39a2dc5dedSSunil Goutham NICVF_HW_STAT(rx_ucast_frames),
40a2dc5dedSSunil Goutham NICVF_HW_STAT(rx_bcast_frames),
41a2dc5dedSSunil Goutham NICVF_HW_STAT(rx_mcast_frames),
42964cb69bSSunil Goutham NICVF_HW_STAT(rx_drops),
434863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_red),
444863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_red_bytes),
454863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_overrun),
464863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_overrun_bytes),
474863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_bcast),
484863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_mcast),
494863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_l3_bcast),
504863dea3SSunil Goutham NICVF_HW_STAT(rx_drop_l3_mcast),
51964cb69bSSunil Goutham NICVF_HW_STAT(rx_fcs_errors),
52964cb69bSSunil Goutham NICVF_HW_STAT(rx_l2_errors),
53964cb69bSSunil Goutham NICVF_HW_STAT(tx_bytes),
54964cb69bSSunil Goutham NICVF_HW_STAT(tx_frames),
55964cb69bSSunil Goutham NICVF_HW_STAT(tx_ucast_frames),
56964cb69bSSunil Goutham NICVF_HW_STAT(tx_bcast_frames),
57964cb69bSSunil Goutham NICVF_HW_STAT(tx_mcast_frames),
58964cb69bSSunil Goutham NICVF_HW_STAT(tx_drops),
594863dea3SSunil Goutham };
604863dea3SSunil Goutham
614863dea3SSunil Goutham static const struct nicvf_stat nicvf_drv_stats[] = {
62964cb69bSSunil Goutham NICVF_DRV_STAT(rx_bgx_truncated_pkts),
63964cb69bSSunil Goutham NICVF_DRV_STAT(rx_jabber_errs),
64964cb69bSSunil Goutham NICVF_DRV_STAT(rx_fcs_errs),
65964cb69bSSunil Goutham NICVF_DRV_STAT(rx_bgx_errs),
66964cb69bSSunil Goutham NICVF_DRV_STAT(rx_prel2_errs),
67964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l2_hdr_malformed),
68964cb69bSSunil Goutham NICVF_DRV_STAT(rx_oversize),
69964cb69bSSunil Goutham NICVF_DRV_STAT(rx_undersize),
70964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l2_len_mismatch),
71964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l2_pclp),
72964cb69bSSunil Goutham NICVF_DRV_STAT(rx_ip_ver_errs),
73964cb69bSSunil Goutham NICVF_DRV_STAT(rx_ip_csum_errs),
74964cb69bSSunil Goutham NICVF_DRV_STAT(rx_ip_hdr_malformed),
75964cb69bSSunil Goutham NICVF_DRV_STAT(rx_ip_payload_malformed),
76964cb69bSSunil Goutham NICVF_DRV_STAT(rx_ip_ttl_errs),
77964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l3_pclp),
78964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l4_malformed),
79964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l4_csum_errs),
80964cb69bSSunil Goutham NICVF_DRV_STAT(rx_udp_len_errs),
81964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l4_port_errs),
82964cb69bSSunil Goutham NICVF_DRV_STAT(rx_tcp_flag_errs),
83964cb69bSSunil Goutham NICVF_DRV_STAT(rx_tcp_offset_errs),
84964cb69bSSunil Goutham NICVF_DRV_STAT(rx_l4_pclp),
85964cb69bSSunil Goutham NICVF_DRV_STAT(rx_truncated_pkts),
86964cb69bSSunil Goutham
87964cb69bSSunil Goutham NICVF_DRV_STAT(tx_desc_fault),
88964cb69bSSunil Goutham NICVF_DRV_STAT(tx_hdr_cons_err),
89964cb69bSSunil Goutham NICVF_DRV_STAT(tx_subdesc_err),
90964cb69bSSunil Goutham NICVF_DRV_STAT(tx_max_size_exceeded),
91964cb69bSSunil Goutham NICVF_DRV_STAT(tx_imm_size_oflow),
92964cb69bSSunil Goutham NICVF_DRV_STAT(tx_data_seq_err),
93964cb69bSSunil Goutham NICVF_DRV_STAT(tx_mem_seq_err),
94964cb69bSSunil Goutham NICVF_DRV_STAT(tx_lock_viol),
95964cb69bSSunil Goutham NICVF_DRV_STAT(tx_data_fault),
96964cb69bSSunil Goutham NICVF_DRV_STAT(tx_tstmp_conflict),
97964cb69bSSunil Goutham NICVF_DRV_STAT(tx_tstmp_timeout),
98964cb69bSSunil Goutham NICVF_DRV_STAT(tx_mem_fault),
99964cb69bSSunil Goutham NICVF_DRV_STAT(tx_csum_overlap),
100964cb69bSSunil Goutham NICVF_DRV_STAT(tx_csum_overflow),
101964cb69bSSunil Goutham
1024863dea3SSunil Goutham NICVF_DRV_STAT(tx_tso),
103a05d4845SThanneeru Srinivasulu NICVF_DRV_STAT(tx_timeout),
10474840b83SSunil Goutham NICVF_DRV_STAT(txq_stop),
10574840b83SSunil Goutham NICVF_DRV_STAT(txq_wake),
1065836b442SSunil Goutham NICVF_DRV_STAT(rcv_buffer_alloc_failures),
1075836b442SSunil Goutham NICVF_DRV_STAT(page_alloc),
1084863dea3SSunil Goutham };
1094863dea3SSunil Goutham
1104863dea3SSunil Goutham static const struct nicvf_stat nicvf_queue_stats[] = {
1114863dea3SSunil Goutham { "bytes", 0 },
1124863dea3SSunil Goutham { "frames", 1 },
1134863dea3SSunil Goutham };
1144863dea3SSunil Goutham
1154863dea3SSunil Goutham static const unsigned int nicvf_n_hw_stats = ARRAY_SIZE(nicvf_hw_stats);
1164863dea3SSunil Goutham static const unsigned int nicvf_n_drv_stats = ARRAY_SIZE(nicvf_drv_stats);
1174863dea3SSunil Goutham static const unsigned int nicvf_n_queue_stats = ARRAY_SIZE(nicvf_queue_stats);
1184863dea3SSunil Goutham
nicvf_get_link_ksettings(struct net_device * netdev,struct ethtool_link_ksettings * cmd)119bfd8d977SPhilippe Reynes static int nicvf_get_link_ksettings(struct net_device *netdev,
120bfd8d977SPhilippe Reynes struct ethtool_link_ksettings *cmd)
1214863dea3SSunil Goutham {
1224863dea3SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
123bfd8d977SPhilippe Reynes u32 supported, advertising;
1244863dea3SSunil Goutham
125bfd8d977SPhilippe Reynes supported = 0;
126bfd8d977SPhilippe Reynes advertising = 0;
1270b72a9a1SSunil Goutham
1280b72a9a1SSunil Goutham if (!nic->link_up) {
129bfd8d977SPhilippe Reynes cmd->base.duplex = DUPLEX_UNKNOWN;
130bfd8d977SPhilippe Reynes cmd->base.speed = SPEED_UNKNOWN;
1310b72a9a1SSunil Goutham return 0;
1320b72a9a1SSunil Goutham }
1330b72a9a1SSunil Goutham
1341cc70259SThanneeru Srinivasulu switch (nic->speed) {
1351cc70259SThanneeru Srinivasulu case SPEED_1000:
136bfd8d977SPhilippe Reynes cmd->base.port = PORT_MII | PORT_TP;
137bfd8d977SPhilippe Reynes cmd->base.autoneg = AUTONEG_ENABLE;
138bfd8d977SPhilippe Reynes supported |= SUPPORTED_MII | SUPPORTED_TP;
139bfd8d977SPhilippe Reynes supported |= SUPPORTED_1000baseT_Full |
1401cc70259SThanneeru Srinivasulu SUPPORTED_1000baseT_Half |
1411cc70259SThanneeru Srinivasulu SUPPORTED_100baseT_Full |
1421cc70259SThanneeru Srinivasulu SUPPORTED_100baseT_Half |
1431cc70259SThanneeru Srinivasulu SUPPORTED_10baseT_Full |
1441cc70259SThanneeru Srinivasulu SUPPORTED_10baseT_Half;
145bfd8d977SPhilippe Reynes supported |= SUPPORTED_Autoneg;
146bfd8d977SPhilippe Reynes advertising |= ADVERTISED_1000baseT_Full |
1471cc70259SThanneeru Srinivasulu ADVERTISED_1000baseT_Half |
1481cc70259SThanneeru Srinivasulu ADVERTISED_100baseT_Full |
1491cc70259SThanneeru Srinivasulu ADVERTISED_100baseT_Half |
1501cc70259SThanneeru Srinivasulu ADVERTISED_10baseT_Full |
1511cc70259SThanneeru Srinivasulu ADVERTISED_10baseT_Half;
1521cc70259SThanneeru Srinivasulu break;
1531cc70259SThanneeru Srinivasulu case SPEED_10000:
1541cc70259SThanneeru Srinivasulu if (nic->mac_type == BGX_MODE_RXAUI) {
155bfd8d977SPhilippe Reynes cmd->base.port = PORT_TP;
156bfd8d977SPhilippe Reynes supported |= SUPPORTED_TP;
1574863dea3SSunil Goutham } else {
158bfd8d977SPhilippe Reynes cmd->base.port = PORT_FIBRE;
159bfd8d977SPhilippe Reynes supported |= SUPPORTED_FIBRE;
1601cc70259SThanneeru Srinivasulu }
161bfd8d977SPhilippe Reynes cmd->base.autoneg = AUTONEG_DISABLE;
162bfd8d977SPhilippe Reynes supported |= SUPPORTED_10000baseT_Full;
1631cc70259SThanneeru Srinivasulu break;
1641cc70259SThanneeru Srinivasulu case SPEED_40000:
165bfd8d977SPhilippe Reynes cmd->base.port = PORT_FIBRE;
166bfd8d977SPhilippe Reynes cmd->base.autoneg = AUTONEG_DISABLE;
167bfd8d977SPhilippe Reynes supported |= SUPPORTED_FIBRE;
168bfd8d977SPhilippe Reynes supported |= SUPPORTED_40000baseCR4_Full;
1691cc70259SThanneeru Srinivasulu break;
1704863dea3SSunil Goutham }
171bfd8d977SPhilippe Reynes cmd->base.duplex = nic->duplex;
172bfd8d977SPhilippe Reynes cmd->base.speed = nic->speed;
173bfd8d977SPhilippe Reynes
174bfd8d977SPhilippe Reynes ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
175bfd8d977SPhilippe Reynes supported);
176bfd8d977SPhilippe Reynes ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
177bfd8d977SPhilippe Reynes advertising);
1784863dea3SSunil Goutham
1794863dea3SSunil Goutham return 0;
1804863dea3SSunil Goutham }
1814863dea3SSunil Goutham
nicvf_get_link(struct net_device * netdev)1820b72a9a1SSunil Goutham static u32 nicvf_get_link(struct net_device *netdev)
1830b72a9a1SSunil Goutham {
1840b72a9a1SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
1850b72a9a1SSunil Goutham
1860b72a9a1SSunil Goutham return nic->link_up;
1870b72a9a1SSunil Goutham }
1880b72a9a1SSunil Goutham
nicvf_get_drvinfo(struct net_device * netdev,struct ethtool_drvinfo * info)1894863dea3SSunil Goutham static void nicvf_get_drvinfo(struct net_device *netdev,
1904863dea3SSunil Goutham struct ethtool_drvinfo *info)
1914863dea3SSunil Goutham {
1924863dea3SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
1934863dea3SSunil Goutham
194f029c781SWolfram Sang strscpy(info->driver, DRV_NAME, sizeof(info->driver));
195f029c781SWolfram Sang strscpy(info->bus_info, pci_name(nic->pdev), sizeof(info->bus_info));
1964863dea3SSunil Goutham }
1974863dea3SSunil Goutham
nicvf_get_msglevel(struct net_device * netdev)1984863dea3SSunil Goutham static u32 nicvf_get_msglevel(struct net_device *netdev)
1994863dea3SSunil Goutham {
2004863dea3SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
2014863dea3SSunil Goutham
2024863dea3SSunil Goutham return nic->msg_enable;
2034863dea3SSunil Goutham }
2044863dea3SSunil Goutham
nicvf_set_msglevel(struct net_device * netdev,u32 lvl)2054863dea3SSunil Goutham static void nicvf_set_msglevel(struct net_device *netdev, u32 lvl)
2064863dea3SSunil Goutham {
2074863dea3SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
2084863dea3SSunil Goutham
2094863dea3SSunil Goutham nic->msg_enable = lvl;
2104863dea3SSunil Goutham }
2114863dea3SSunil Goutham
nicvf_get_qset_strings(struct nicvf * nic,u8 ** data,int qset)21292dc8769SSunil Goutham static void nicvf_get_qset_strings(struct nicvf *nic, u8 **data, int qset)
21392dc8769SSunil Goutham {
21492dc8769SSunil Goutham int stats, qidx;
21592dc8769SSunil Goutham int start_qidx = qset * MAX_RCV_QUEUES_PER_QS;
21692dc8769SSunil Goutham
21792dc8769SSunil Goutham for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
21892dc8769SSunil Goutham for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
21992dc8769SSunil Goutham sprintf(*data, "rxq%d: %s", qidx + start_qidx,
22092dc8769SSunil Goutham nicvf_queue_stats[stats].name);
22192dc8769SSunil Goutham *data += ETH_GSTRING_LEN;
22292dc8769SSunil Goutham }
22392dc8769SSunil Goutham }
22492dc8769SSunil Goutham
22592dc8769SSunil Goutham for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
22692dc8769SSunil Goutham for (stats = 0; stats < nicvf_n_queue_stats; stats++) {
22792dc8769SSunil Goutham sprintf(*data, "txq%d: %s", qidx + start_qidx,
22892dc8769SSunil Goutham nicvf_queue_stats[stats].name);
22992dc8769SSunil Goutham *data += ETH_GSTRING_LEN;
23092dc8769SSunil Goutham }
23192dc8769SSunil Goutham }
23292dc8769SSunil Goutham }
23392dc8769SSunil Goutham
nicvf_get_strings(struct net_device * netdev,u32 sset,u8 * data)2344863dea3SSunil Goutham static void nicvf_get_strings(struct net_device *netdev, u32 sset, u8 *data)
2354863dea3SSunil Goutham {
236c62cd3c4SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
23792dc8769SSunil Goutham int stats;
23892dc8769SSunil Goutham int sqs;
2394863dea3SSunil Goutham
2404863dea3SSunil Goutham if (sset != ETH_SS_STATS)
2414863dea3SSunil Goutham return;
2424863dea3SSunil Goutham
2434863dea3SSunil Goutham for (stats = 0; stats < nicvf_n_hw_stats; stats++) {
2444863dea3SSunil Goutham memcpy(data, nicvf_hw_stats[stats].name, ETH_GSTRING_LEN);
2454863dea3SSunil Goutham data += ETH_GSTRING_LEN;
2464863dea3SSunil Goutham }
2474863dea3SSunil Goutham
2484863dea3SSunil Goutham for (stats = 0; stats < nicvf_n_drv_stats; stats++) {
2494863dea3SSunil Goutham memcpy(data, nicvf_drv_stats[stats].name, ETH_GSTRING_LEN);
2504863dea3SSunil Goutham data += ETH_GSTRING_LEN;
2514863dea3SSunil Goutham }
2524863dea3SSunil Goutham
25392dc8769SSunil Goutham nicvf_get_qset_strings(nic, &data, 0);
2544863dea3SSunil Goutham
25592dc8769SSunil Goutham for (sqs = 0; sqs < nic->sqs_count; sqs++) {
25692dc8769SSunil Goutham if (!nic->snicvf[sqs])
25792dc8769SSunil Goutham continue;
25892dc8769SSunil Goutham nicvf_get_qset_strings(nic->snicvf[sqs], &data, sqs + 1);
2594863dea3SSunil Goutham }
2604863dea3SSunil Goutham
2614863dea3SSunil Goutham for (stats = 0; stats < BGX_RX_STATS_COUNT; stats++) {
2624863dea3SSunil Goutham sprintf(data, "bgx_rxstat%d: ", stats);
2634863dea3SSunil Goutham data += ETH_GSTRING_LEN;
2644863dea3SSunil Goutham }
2654863dea3SSunil Goutham
2664863dea3SSunil Goutham for (stats = 0; stats < BGX_TX_STATS_COUNT; stats++) {
2674863dea3SSunil Goutham sprintf(data, "bgx_txstat%d: ", stats);
2684863dea3SSunil Goutham data += ETH_GSTRING_LEN;
2694863dea3SSunil Goutham }
2704863dea3SSunil Goutham }
2714863dea3SSunil Goutham
nicvf_get_sset_count(struct net_device * netdev,int sset)2724863dea3SSunil Goutham static int nicvf_get_sset_count(struct net_device *netdev, int sset)
2734863dea3SSunil Goutham {
274c62cd3c4SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
27592dc8769SSunil Goutham int qstats_count;
27692dc8769SSunil Goutham int sqs;
277c62cd3c4SSunil Goutham
2784863dea3SSunil Goutham if (sset != ETH_SS_STATS)
2794863dea3SSunil Goutham return -EINVAL;
2804863dea3SSunil Goutham
28192dc8769SSunil Goutham qstats_count = nicvf_n_queue_stats *
28292dc8769SSunil Goutham (nic->qs->rq_cnt + nic->qs->sq_cnt);
28392dc8769SSunil Goutham for (sqs = 0; sqs < nic->sqs_count; sqs++) {
28492dc8769SSunil Goutham struct nicvf *snic;
28592dc8769SSunil Goutham
28692dc8769SSunil Goutham snic = nic->snicvf[sqs];
28792dc8769SSunil Goutham if (!snic)
28892dc8769SSunil Goutham continue;
28992dc8769SSunil Goutham qstats_count += nicvf_n_queue_stats *
29092dc8769SSunil Goutham (snic->qs->rq_cnt + snic->qs->sq_cnt);
29192dc8769SSunil Goutham }
29292dc8769SSunil Goutham
2934863dea3SSunil Goutham return nicvf_n_hw_stats + nicvf_n_drv_stats +
29492dc8769SSunil Goutham qstats_count +
2954863dea3SSunil Goutham BGX_RX_STATS_COUNT + BGX_TX_STATS_COUNT;
2964863dea3SSunil Goutham }
2974863dea3SSunil Goutham
nicvf_get_qset_stats(struct nicvf * nic,struct ethtool_stats * stats,u64 ** data)29892dc8769SSunil Goutham static void nicvf_get_qset_stats(struct nicvf *nic,
29992dc8769SSunil Goutham struct ethtool_stats *stats, u64 **data)
30092dc8769SSunil Goutham {
30192dc8769SSunil Goutham int stat, qidx;
30292dc8769SSunil Goutham
30392dc8769SSunil Goutham if (!nic)
30492dc8769SSunil Goutham return;
30592dc8769SSunil Goutham
30692dc8769SSunil Goutham for (qidx = 0; qidx < nic->qs->rq_cnt; qidx++) {
30792dc8769SSunil Goutham nicvf_update_rq_stats(nic, qidx);
30892dc8769SSunil Goutham for (stat = 0; stat < nicvf_n_queue_stats; stat++)
30992dc8769SSunil Goutham *((*data)++) = ((u64 *)&nic->qs->rq[qidx].stats)
31092dc8769SSunil Goutham [nicvf_queue_stats[stat].index];
31192dc8769SSunil Goutham }
31292dc8769SSunil Goutham
31392dc8769SSunil Goutham for (qidx = 0; qidx < nic->qs->sq_cnt; qidx++) {
31492dc8769SSunil Goutham nicvf_update_sq_stats(nic, qidx);
31592dc8769SSunil Goutham for (stat = 0; stat < nicvf_n_queue_stats; stat++)
31692dc8769SSunil Goutham *((*data)++) = ((u64 *)&nic->qs->sq[qidx].stats)
31792dc8769SSunil Goutham [nicvf_queue_stats[stat].index];
31892dc8769SSunil Goutham }
31992dc8769SSunil Goutham }
32092dc8769SSunil Goutham
nicvf_get_ethtool_stats(struct net_device * netdev,struct ethtool_stats * stats,u64 * data)3214863dea3SSunil Goutham static void nicvf_get_ethtool_stats(struct net_device *netdev,
3224863dea3SSunil Goutham struct ethtool_stats *stats, u64 *data)
3234863dea3SSunil Goutham {
3244863dea3SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
325964cb69bSSunil Goutham int stat, tmp_stats;
326964cb69bSSunil Goutham int sqs, cpu;
3274863dea3SSunil Goutham
3284863dea3SSunil Goutham nicvf_update_stats(nic);
3294863dea3SSunil Goutham
3304863dea3SSunil Goutham /* Update LMAC stats */
3314863dea3SSunil Goutham nicvf_update_lmac_stats(nic);
3324863dea3SSunil Goutham
3334863dea3SSunil Goutham for (stat = 0; stat < nicvf_n_hw_stats; stat++)
334a2dc5dedSSunil Goutham *(data++) = ((u64 *)&nic->hw_stats)
3354863dea3SSunil Goutham [nicvf_hw_stats[stat].index];
336964cb69bSSunil Goutham for (stat = 0; stat < nicvf_n_drv_stats; stat++) {
337964cb69bSSunil Goutham tmp_stats = 0;
338964cb69bSSunil Goutham for_each_possible_cpu(cpu)
339964cb69bSSunil Goutham tmp_stats += ((u64 *)per_cpu_ptr(nic->drv_stats, cpu))
3404863dea3SSunil Goutham [nicvf_drv_stats[stat].index];
341964cb69bSSunil Goutham *(data++) = tmp_stats;
342964cb69bSSunil Goutham }
3434863dea3SSunil Goutham
34492dc8769SSunil Goutham nicvf_get_qset_stats(nic, stats, &data);
3454863dea3SSunil Goutham
34692dc8769SSunil Goutham for (sqs = 0; sqs < nic->sqs_count; sqs++) {
34792dc8769SSunil Goutham if (!nic->snicvf[sqs])
34892dc8769SSunil Goutham continue;
34992dc8769SSunil Goutham nicvf_get_qset_stats(nic->snicvf[sqs], stats, &data);
3504863dea3SSunil Goutham }
3514863dea3SSunil Goutham
3524863dea3SSunil Goutham for (stat = 0; stat < BGX_RX_STATS_COUNT; stat++)
3534863dea3SSunil Goutham *(data++) = nic->bgx_stats.rx_stats[stat];
3544863dea3SSunil Goutham for (stat = 0; stat < BGX_TX_STATS_COUNT; stat++)
3554863dea3SSunil Goutham *(data++) = nic->bgx_stats.tx_stats[stat];
3564863dea3SSunil Goutham }
3574863dea3SSunil Goutham
nicvf_get_regs_len(struct net_device * dev)3584863dea3SSunil Goutham static int nicvf_get_regs_len(struct net_device *dev)
3594863dea3SSunil Goutham {
3604863dea3SSunil Goutham return sizeof(u64) * NIC_VF_REG_COUNT;
3614863dea3SSunil Goutham }
3624863dea3SSunil Goutham
nicvf_get_regs(struct net_device * dev,struct ethtool_regs * regs,void * reg)3634863dea3SSunil Goutham static void nicvf_get_regs(struct net_device *dev,
3644863dea3SSunil Goutham struct ethtool_regs *regs, void *reg)
3654863dea3SSunil Goutham {
3664863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
3674863dea3SSunil Goutham u64 *p = (u64 *)reg;
3684863dea3SSunil Goutham u64 reg_offset;
3694863dea3SSunil Goutham int mbox, key, stat, q;
3704863dea3SSunil Goutham int i = 0;
3714863dea3SSunil Goutham
3724863dea3SSunil Goutham regs->version = 0;
3734863dea3SSunil Goutham memset(p, 0, NIC_VF_REG_COUNT);
3744863dea3SSunil Goutham
3754863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_VNIC_CFG);
3764863dea3SSunil Goutham /* Mailbox registers */
3774863dea3SSunil Goutham for (mbox = 0; mbox < NIC_PF_VF_MAILBOX_SIZE; mbox++)
3784863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic,
3794863dea3SSunil Goutham NIC_VF_PF_MAILBOX_0_1 | (mbox << 3));
3804863dea3SSunil Goutham
3814863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_VF_INT);
3824863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_VF_INT_W1S);
3834863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1C);
3844863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_VF_ENA_W1S);
3854863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG);
3864863dea3SSunil Goutham
3874863dea3SSunil Goutham for (key = 0; key < RSS_HASH_KEY_SIZE; key++)
3884863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_VNIC_RSS_KEY_0_4 | (key << 3));
3894863dea3SSunil Goutham
3904863dea3SSunil Goutham /* Tx/Rx statistics */
3914863dea3SSunil Goutham for (stat = 0; stat < TX_STATS_ENUM_LAST; stat++)
3924863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic,
3934863dea3SSunil Goutham NIC_VNIC_TX_STAT_0_4 | (stat << 3));
3944863dea3SSunil Goutham
3954863dea3SSunil Goutham for (i = 0; i < RX_STATS_ENUM_LAST; i++)
3964863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic,
3974863dea3SSunil Goutham NIC_VNIC_RX_STAT_0_13 | (stat << 3));
3984863dea3SSunil Goutham
3994863dea3SSunil Goutham p[i++] = nicvf_reg_read(nic, NIC_QSET_RQ_GEN_CFG);
4004863dea3SSunil Goutham
4014863dea3SSunil Goutham /* All completion queue's registers */
4024863dea3SSunil Goutham for (q = 0; q < MAX_CMP_QUEUES_PER_QS; q++) {
4034863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG, q);
4044863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_CFG2, q);
4054863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_THRESH, q);
4064863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_BASE, q);
4074863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_HEAD, q);
4084863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_TAIL, q);
4094863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DOOR, q);
4104863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS, q);
4114863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_STATUS2, q);
4124863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_CQ_0_7_DEBUG, q);
4134863dea3SSunil Goutham }
4144863dea3SSunil Goutham
4154863dea3SSunil Goutham /* All receive queue's registers */
4164863dea3SSunil Goutham for (q = 0; q < MAX_RCV_QUEUES_PER_QS; q++) {
4174863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RQ_0_7_CFG, q);
4184863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic,
4194863dea3SSunil Goutham NIC_QSET_RQ_0_7_STAT_0_1, q);
4204863dea3SSunil Goutham reg_offset = NIC_QSET_RQ_0_7_STAT_0_1 | (1 << 3);
4214863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);
4224863dea3SSunil Goutham }
4234863dea3SSunil Goutham
4244863dea3SSunil Goutham for (q = 0; q < MAX_SND_QUEUES_PER_QS; q++) {
4254863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_CFG, q);
4264863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_THRESH, q);
4274863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_BASE, q);
4284863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_HEAD, q);
4294863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_TAIL, q);
4304863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DOOR, q);
4314863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STATUS, q);
4324863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_DEBUG, q);
4331423661fSDavid Daney /* Padding, was NIC_QSET_SQ_0_7_CNM_CHG, which
4341423661fSDavid Daney * produces bus errors when read
4351423661fSDavid Daney */
4361423661fSDavid Daney p[i++] = 0;
4374863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_SQ_0_7_STAT_0_1, q);
4384863dea3SSunil Goutham reg_offset = NIC_QSET_SQ_0_7_STAT_0_1 | (1 << 3);
4394863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);
4404863dea3SSunil Goutham }
4414863dea3SSunil Goutham
4424863dea3SSunil Goutham for (q = 0; q < MAX_RCV_BUF_DESC_RINGS_PER_QS; q++) {
4434863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_CFG, q);
4444863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_THRESH, q);
4454863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_BASE, q);
4464863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_HEAD, q);
4474863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_TAIL, q);
4484863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, NIC_QSET_RBDR_0_1_DOOR, q);
4494863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic,
4504863dea3SSunil Goutham NIC_QSET_RBDR_0_1_STATUS0, q);
4514863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic,
4524863dea3SSunil Goutham NIC_QSET_RBDR_0_1_STATUS1, q);
4534863dea3SSunil Goutham reg_offset = NIC_QSET_RBDR_0_1_PREFETCH_STATUS;
4544863dea3SSunil Goutham p[i++] = nicvf_queue_reg_read(nic, reg_offset, q);
4554863dea3SSunil Goutham }
4564863dea3SSunil Goutham }
4574863dea3SSunil Goutham
nicvf_get_coalesce(struct net_device * netdev,struct ethtool_coalesce * cmd,struct kernel_ethtool_coalesce * kernel_coal,struct netlink_ext_ack * extack)4584863dea3SSunil Goutham static int nicvf_get_coalesce(struct net_device *netdev,
459f3ccfda1SYufeng Mo struct ethtool_coalesce *cmd,
460f3ccfda1SYufeng Mo struct kernel_ethtool_coalesce *kernel_coal,
461f3ccfda1SYufeng Mo struct netlink_ext_ack *extack)
4624863dea3SSunil Goutham {
4634863dea3SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
4644863dea3SSunil Goutham
4654863dea3SSunil Goutham cmd->rx_coalesce_usecs = nic->cq_coalesce_usecs;
4664863dea3SSunil Goutham return 0;
4674863dea3SSunil Goutham }
4684863dea3SSunil Goutham
nicvf_get_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)4694863dea3SSunil Goutham static void nicvf_get_ringparam(struct net_device *netdev,
47074624944SHao Chen struct ethtool_ringparam *ring,
47174624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
47274624944SHao Chen struct netlink_ext_ack *extack)
4734863dea3SSunil Goutham {
4744863dea3SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
4754863dea3SSunil Goutham struct queue_set *qs = nic->qs;
4764863dea3SSunil Goutham
477fff4ffddSSunil Goutham ring->rx_max_pending = MAX_CMP_QUEUE_LEN;
478fff4ffddSSunil Goutham ring->rx_pending = qs->cq_len;
4794863dea3SSunil Goutham ring->tx_max_pending = MAX_SND_QUEUE_LEN;
4804863dea3SSunil Goutham ring->tx_pending = qs->sq_len;
4814863dea3SSunil Goutham }
4824863dea3SSunil Goutham
nicvf_set_ringparam(struct net_device * netdev,struct ethtool_ringparam * ring,struct kernel_ethtool_ringparam * kernel_ring,struct netlink_ext_ack * extack)483fff4ffddSSunil Goutham static int nicvf_set_ringparam(struct net_device *netdev,
48474624944SHao Chen struct ethtool_ringparam *ring,
48574624944SHao Chen struct kernel_ethtool_ringparam *kernel_ring,
48674624944SHao Chen struct netlink_ext_ack *extack)
487fff4ffddSSunil Goutham {
488fff4ffddSSunil Goutham struct nicvf *nic = netdev_priv(netdev);
489fff4ffddSSunil Goutham struct queue_set *qs = nic->qs;
490fff4ffddSSunil Goutham u32 rx_count, tx_count;
491fff4ffddSSunil Goutham
492fff4ffddSSunil Goutham /* Due to HW errata this is not supported on T88 pass 1.x silicon */
493fff4ffddSSunil Goutham if (pass1_silicon(nic->pdev))
494fff4ffddSSunil Goutham return -EINVAL;
495fff4ffddSSunil Goutham
496fff4ffddSSunil Goutham if ((ring->rx_mini_pending) || (ring->rx_jumbo_pending))
497fff4ffddSSunil Goutham return -EINVAL;
498fff4ffddSSunil Goutham
499fff4ffddSSunil Goutham tx_count = clamp_t(u32, ring->tx_pending,
500fff4ffddSSunil Goutham MIN_SND_QUEUE_LEN, MAX_SND_QUEUE_LEN);
501fff4ffddSSunil Goutham rx_count = clamp_t(u32, ring->rx_pending,
502fff4ffddSSunil Goutham MIN_CMP_QUEUE_LEN, MAX_CMP_QUEUE_LEN);
503fff4ffddSSunil Goutham
504fff4ffddSSunil Goutham if ((tx_count == qs->sq_len) && (rx_count == qs->cq_len))
505fff4ffddSSunil Goutham return 0;
506fff4ffddSSunil Goutham
507fff4ffddSSunil Goutham /* Permitted lengths are 1K, 2K, 4K, 8K, 16K, 32K, 64K */
508fff4ffddSSunil Goutham qs->sq_len = rounddown_pow_of_two(tx_count);
509fff4ffddSSunil Goutham qs->cq_len = rounddown_pow_of_two(rx_count);
510fff4ffddSSunil Goutham
511fff4ffddSSunil Goutham if (netif_running(netdev)) {
512fff4ffddSSunil Goutham nicvf_stop(netdev);
513fff4ffddSSunil Goutham nicvf_open(netdev);
514fff4ffddSSunil Goutham }
515fff4ffddSSunil Goutham
516fff4ffddSSunil Goutham return 0;
517fff4ffddSSunil Goutham }
518fff4ffddSSunil Goutham
nicvf_get_rss_hash_opts(struct nicvf * nic,struct ethtool_rxnfc * info)5194863dea3SSunil Goutham static int nicvf_get_rss_hash_opts(struct nicvf *nic,
5204863dea3SSunil Goutham struct ethtool_rxnfc *info)
5214863dea3SSunil Goutham {
5224863dea3SSunil Goutham info->data = 0;
5234863dea3SSunil Goutham
5244863dea3SSunil Goutham switch (info->flow_type) {
5254863dea3SSunil Goutham case TCP_V4_FLOW:
5264863dea3SSunil Goutham case TCP_V6_FLOW:
5274863dea3SSunil Goutham case UDP_V4_FLOW:
5284863dea3SSunil Goutham case UDP_V6_FLOW:
5294863dea3SSunil Goutham case SCTP_V4_FLOW:
5304863dea3SSunil Goutham case SCTP_V6_FLOW:
5314863dea3SSunil Goutham info->data |= RXH_L4_B_0_1 | RXH_L4_B_2_3;
532df561f66SGustavo A. R. Silva fallthrough;
5334863dea3SSunil Goutham case IPV4_FLOW:
5344863dea3SSunil Goutham case IPV6_FLOW:
5354863dea3SSunil Goutham info->data |= RXH_IP_SRC | RXH_IP_DST;
5364863dea3SSunil Goutham break;
5374863dea3SSunil Goutham default:
5384863dea3SSunil Goutham return -EINVAL;
5394863dea3SSunil Goutham }
5404863dea3SSunil Goutham
5414863dea3SSunil Goutham return 0;
5424863dea3SSunil Goutham }
5434863dea3SSunil Goutham
nicvf_get_rxnfc(struct net_device * dev,struct ethtool_rxnfc * info,u32 * rules)5444863dea3SSunil Goutham static int nicvf_get_rxnfc(struct net_device *dev,
5454863dea3SSunil Goutham struct ethtool_rxnfc *info, u32 *rules)
5464863dea3SSunil Goutham {
5474863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
5484863dea3SSunil Goutham int ret = -EOPNOTSUPP;
5494863dea3SSunil Goutham
5504863dea3SSunil Goutham switch (info->cmd) {
5514863dea3SSunil Goutham case ETHTOOL_GRXRINGS:
55292dc8769SSunil Goutham info->data = nic->rx_queues;
5534863dea3SSunil Goutham ret = 0;
5544863dea3SSunil Goutham break;
5554863dea3SSunil Goutham case ETHTOOL_GRXFH:
5564863dea3SSunil Goutham return nicvf_get_rss_hash_opts(nic, info);
5574863dea3SSunil Goutham default:
5584863dea3SSunil Goutham break;
5594863dea3SSunil Goutham }
5604863dea3SSunil Goutham return ret;
5614863dea3SSunil Goutham }
5624863dea3SSunil Goutham
nicvf_set_rss_hash_opts(struct nicvf * nic,struct ethtool_rxnfc * info)5634863dea3SSunil Goutham static int nicvf_set_rss_hash_opts(struct nicvf *nic,
5644863dea3SSunil Goutham struct ethtool_rxnfc *info)
5654863dea3SSunil Goutham {
5664863dea3SSunil Goutham struct nicvf_rss_info *rss = &nic->rss_info;
5674863dea3SSunil Goutham u64 rss_cfg = nicvf_reg_read(nic, NIC_VNIC_RSS_CFG);
5684863dea3SSunil Goutham
5694863dea3SSunil Goutham if (!rss->enable)
5704863dea3SSunil Goutham netdev_err(nic->netdev,
5714863dea3SSunil Goutham "RSS is disabled, hash cannot be set\n");
5724863dea3SSunil Goutham
5734863dea3SSunil Goutham netdev_info(nic->netdev, "Set RSS flow type = %d, data = %lld\n",
5744863dea3SSunil Goutham info->flow_type, info->data);
5754863dea3SSunil Goutham
5764863dea3SSunil Goutham if (!(info->data & RXH_IP_SRC) || !(info->data & RXH_IP_DST))
5774863dea3SSunil Goutham return -EINVAL;
5784863dea3SSunil Goutham
5794863dea3SSunil Goutham switch (info->flow_type) {
5804863dea3SSunil Goutham case TCP_V4_FLOW:
5814863dea3SSunil Goutham case TCP_V6_FLOW:
5824863dea3SSunil Goutham switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
5834863dea3SSunil Goutham case 0:
5844863dea3SSunil Goutham rss_cfg &= ~(1ULL << RSS_HASH_TCP);
5854863dea3SSunil Goutham break;
5864863dea3SSunil Goutham case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
5874863dea3SSunil Goutham rss_cfg |= (1ULL << RSS_HASH_TCP);
5884863dea3SSunil Goutham break;
5894863dea3SSunil Goutham default:
5904863dea3SSunil Goutham return -EINVAL;
5914863dea3SSunil Goutham }
5924863dea3SSunil Goutham break;
5934863dea3SSunil Goutham case UDP_V4_FLOW:
5944863dea3SSunil Goutham case UDP_V6_FLOW:
5954863dea3SSunil Goutham switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
5964863dea3SSunil Goutham case 0:
5974863dea3SSunil Goutham rss_cfg &= ~(1ULL << RSS_HASH_UDP);
5984863dea3SSunil Goutham break;
5994863dea3SSunil Goutham case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
6004863dea3SSunil Goutham rss_cfg |= (1ULL << RSS_HASH_UDP);
6014863dea3SSunil Goutham break;
6024863dea3SSunil Goutham default:
6034863dea3SSunil Goutham return -EINVAL;
6044863dea3SSunil Goutham }
6054863dea3SSunil Goutham break;
6064863dea3SSunil Goutham case SCTP_V4_FLOW:
6074863dea3SSunil Goutham case SCTP_V6_FLOW:
6084863dea3SSunil Goutham switch (info->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)) {
6094863dea3SSunil Goutham case 0:
6104863dea3SSunil Goutham rss_cfg &= ~(1ULL << RSS_HASH_L4ETC);
6114863dea3SSunil Goutham break;
6124863dea3SSunil Goutham case (RXH_L4_B_0_1 | RXH_L4_B_2_3):
6134863dea3SSunil Goutham rss_cfg |= (1ULL << RSS_HASH_L4ETC);
6144863dea3SSunil Goutham break;
6154863dea3SSunil Goutham default:
6164863dea3SSunil Goutham return -EINVAL;
6174863dea3SSunil Goutham }
6184863dea3SSunil Goutham break;
6194863dea3SSunil Goutham case IPV4_FLOW:
6204863dea3SSunil Goutham case IPV6_FLOW:
6214863dea3SSunil Goutham rss_cfg = RSS_HASH_IP;
6224863dea3SSunil Goutham break;
6234863dea3SSunil Goutham default:
6244863dea3SSunil Goutham return -EINVAL;
6254863dea3SSunil Goutham }
6264863dea3SSunil Goutham
6274863dea3SSunil Goutham nicvf_reg_write(nic, NIC_VNIC_RSS_CFG, rss_cfg);
6284863dea3SSunil Goutham return 0;
6294863dea3SSunil Goutham }
6304863dea3SSunil Goutham
nicvf_set_rxnfc(struct net_device * dev,struct ethtool_rxnfc * info)6314863dea3SSunil Goutham static int nicvf_set_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info)
6324863dea3SSunil Goutham {
6334863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
6344863dea3SSunil Goutham
6354863dea3SSunil Goutham switch (info->cmd) {
6364863dea3SSunil Goutham case ETHTOOL_SRXFH:
6374863dea3SSunil Goutham return nicvf_set_rss_hash_opts(nic, info);
6384863dea3SSunil Goutham default:
6394863dea3SSunil Goutham break;
6404863dea3SSunil Goutham }
6414863dea3SSunil Goutham return -EOPNOTSUPP;
6424863dea3SSunil Goutham }
6434863dea3SSunil Goutham
nicvf_get_rxfh_key_size(struct net_device * netdev)6444863dea3SSunil Goutham static u32 nicvf_get_rxfh_key_size(struct net_device *netdev)
6454863dea3SSunil Goutham {
6464863dea3SSunil Goutham return RSS_HASH_KEY_SIZE * sizeof(u64);
6474863dea3SSunil Goutham }
6484863dea3SSunil Goutham
nicvf_get_rxfh_indir_size(struct net_device * dev)6494863dea3SSunil Goutham static u32 nicvf_get_rxfh_indir_size(struct net_device *dev)
6504863dea3SSunil Goutham {
6514863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
6524863dea3SSunil Goutham
6534863dea3SSunil Goutham return nic->rss_info.rss_size;
6544863dea3SSunil Goutham }
6554863dea3SSunil Goutham
nicvf_get_rxfh(struct net_device * dev,u32 * indir,u8 * hkey,u8 * hfunc)6564863dea3SSunil Goutham static int nicvf_get_rxfh(struct net_device *dev, u32 *indir, u8 *hkey,
6574863dea3SSunil Goutham u8 *hfunc)
6584863dea3SSunil Goutham {
6594863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
6604863dea3SSunil Goutham struct nicvf_rss_info *rss = &nic->rss_info;
6614863dea3SSunil Goutham int idx;
6624863dea3SSunil Goutham
6634863dea3SSunil Goutham if (indir) {
6644863dea3SSunil Goutham for (idx = 0; idx < rss->rss_size; idx++)
6654863dea3SSunil Goutham indir[idx] = rss->ind_tbl[idx];
6664863dea3SSunil Goutham }
6674863dea3SSunil Goutham
6684863dea3SSunil Goutham if (hkey)
6694863dea3SSunil Goutham memcpy(hkey, rss->key, RSS_HASH_KEY_SIZE * sizeof(u64));
6704863dea3SSunil Goutham
6714863dea3SSunil Goutham if (hfunc)
6724863dea3SSunil Goutham *hfunc = ETH_RSS_HASH_TOP;
6734863dea3SSunil Goutham
6744863dea3SSunil Goutham return 0;
6754863dea3SSunil Goutham }
6764863dea3SSunil Goutham
nicvf_set_rxfh(struct net_device * dev,const u32 * indir,const u8 * hkey,const u8 hfunc)6774863dea3SSunil Goutham static int nicvf_set_rxfh(struct net_device *dev, const u32 *indir,
678171d87acSRobert Richter const u8 *hkey, const u8 hfunc)
6794863dea3SSunil Goutham {
6804863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
6814863dea3SSunil Goutham struct nicvf_rss_info *rss = &nic->rss_info;
6824863dea3SSunil Goutham int idx;
6834863dea3SSunil Goutham
68489987844SAleksey Makarov if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP)
6854863dea3SSunil Goutham return -EOPNOTSUPP;
6864863dea3SSunil Goutham
68738bb5d4fSSunil Goutham if (!rss->enable) {
68838bb5d4fSSunil Goutham netdev_err(nic->netdev,
68938bb5d4fSSunil Goutham "RSS is disabled, cannot change settings\n");
69038bb5d4fSSunil Goutham return -EIO;
69138bb5d4fSSunil Goutham }
69238bb5d4fSSunil Goutham
6934863dea3SSunil Goutham if (indir) {
6944863dea3SSunil Goutham for (idx = 0; idx < rss->rss_size; idx++)
6954863dea3SSunil Goutham rss->ind_tbl[idx] = indir[idx];
6964863dea3SSunil Goutham }
6974863dea3SSunil Goutham
6984863dea3SSunil Goutham if (hkey) {
6994863dea3SSunil Goutham memcpy(rss->key, hkey, RSS_HASH_KEY_SIZE * sizeof(u64));
7004863dea3SSunil Goutham nicvf_set_rss_key(nic);
7014863dea3SSunil Goutham }
7024863dea3SSunil Goutham
7034863dea3SSunil Goutham nicvf_config_rss(nic);
7044863dea3SSunil Goutham return 0;
7054863dea3SSunil Goutham }
7064863dea3SSunil Goutham
7074863dea3SSunil Goutham /* Get no of queues device supports and current queue count */
nicvf_get_channels(struct net_device * dev,struct ethtool_channels * channel)7084863dea3SSunil Goutham static void nicvf_get_channels(struct net_device *dev,
7094863dea3SSunil Goutham struct ethtool_channels *channel)
7104863dea3SSunil Goutham {
7114863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
7124863dea3SSunil Goutham
7134863dea3SSunil Goutham memset(channel, 0, sizeof(*channel));
7144863dea3SSunil Goutham
71592dc8769SSunil Goutham channel->max_rx = nic->max_queues;
71692dc8769SSunil Goutham channel->max_tx = nic->max_queues;
7174863dea3SSunil Goutham
71892dc8769SSunil Goutham channel->rx_count = nic->rx_queues;
71992dc8769SSunil Goutham channel->tx_count = nic->tx_queues;
7204863dea3SSunil Goutham }
7214863dea3SSunil Goutham
7224863dea3SSunil Goutham /* Set no of Tx, Rx queues to be used */
nicvf_set_channels(struct net_device * dev,struct ethtool_channels * channel)7234863dea3SSunil Goutham static int nicvf_set_channels(struct net_device *dev,
7244863dea3SSunil Goutham struct ethtool_channels *channel)
7254863dea3SSunil Goutham {
7264863dea3SSunil Goutham struct nicvf *nic = netdev_priv(dev);
7274863dea3SSunil Goutham int err = 0;
728c62cd3c4SSunil Goutham bool if_up = netif_running(dev);
72905c773f5SSunil Goutham u8 cqcount, txq_count;
7304863dea3SSunil Goutham
7314863dea3SSunil Goutham if (!channel->rx_count || !channel->tx_count)
7324863dea3SSunil Goutham return -EINVAL;
73392dc8769SSunil Goutham if (channel->rx_count > nic->max_queues)
7344863dea3SSunil Goutham return -EINVAL;
73592dc8769SSunil Goutham if (channel->tx_count > nic->max_queues)
7364863dea3SSunil Goutham return -EINVAL;
7374863dea3SSunil Goutham
738*3c249fe4SLorenzo Bianconi if (channel->tx_count + channel->rx_count > nic->max_queues) {
739*3c249fe4SLorenzo Bianconi if (nic->xdp_prog) {
74005c773f5SSunil Goutham netdev_err(nic->netdev,
74105c773f5SSunil Goutham "XDP mode, RXQs + TXQs > Max %d\n",
74205c773f5SSunil Goutham nic->max_queues);
74305c773f5SSunil Goutham return -EINVAL;
74405c773f5SSunil Goutham }
74505c773f5SSunil Goutham
746*3c249fe4SLorenzo Bianconi xdp_clear_features_flag(nic->netdev);
747*3c249fe4SLorenzo Bianconi } else if (!pass1_silicon(nic->pdev)) {
748*3c249fe4SLorenzo Bianconi xdp_set_features_flag(dev, NETDEV_XDP_ACT_BASIC);
749*3c249fe4SLorenzo Bianconi }
750*3c249fe4SLorenzo Bianconi
751c62cd3c4SSunil Goutham if (if_up)
752c62cd3c4SSunil Goutham nicvf_stop(dev);
753c62cd3c4SSunil Goutham
75405c773f5SSunil Goutham nic->rx_queues = channel->rx_count;
75505c773f5SSunil Goutham nic->tx_queues = channel->tx_count;
75605c773f5SSunil Goutham if (!nic->xdp_prog)
75705c773f5SSunil Goutham nic->xdp_tx_queues = 0;
75805c773f5SSunil Goutham else
75905c773f5SSunil Goutham nic->xdp_tx_queues = channel->rx_count;
76005c773f5SSunil Goutham
76105c773f5SSunil Goutham txq_count = nic->xdp_tx_queues + nic->tx_queues;
76205c773f5SSunil Goutham cqcount = max(nic->rx_queues, txq_count);
76392dc8769SSunil Goutham
76492dc8769SSunil Goutham if (cqcount > MAX_CMP_QUEUES_PER_QS) {
76592dc8769SSunil Goutham nic->sqs_count = roundup(cqcount, MAX_CMP_QUEUES_PER_QS);
76692dc8769SSunil Goutham nic->sqs_count = (nic->sqs_count / MAX_CMP_QUEUES_PER_QS) - 1;
76792dc8769SSunil Goutham } else {
76892dc8769SSunil Goutham nic->sqs_count = 0;
76992dc8769SSunil Goutham }
77092dc8769SSunil Goutham
77105c773f5SSunil Goutham nic->qs->rq_cnt = min_t(u8, nic->rx_queues, MAX_RCV_QUEUES_PER_QS);
77205c773f5SSunil Goutham nic->qs->sq_cnt = min_t(u8, txq_count, MAX_SND_QUEUES_PER_QS);
7734863dea3SSunil Goutham nic->qs->cq_cnt = max(nic->qs->rq_cnt, nic->qs->sq_cnt);
7744863dea3SSunil Goutham
77592dc8769SSunil Goutham err = nicvf_set_real_num_queues(dev, nic->tx_queues, nic->rx_queues);
7764863dea3SSunil Goutham if (err)
7774863dea3SSunil Goutham return err;
7784863dea3SSunil Goutham
779c62cd3c4SSunil Goutham if (if_up)
7804863dea3SSunil Goutham nicvf_open(dev);
781c62cd3c4SSunil Goutham
7824863dea3SSunil Goutham netdev_info(dev, "Setting num Tx rings to %d, Rx rings to %d success\n",
78392dc8769SSunil Goutham nic->tx_queues, nic->rx_queues);
7844863dea3SSunil Goutham
7854863dea3SSunil Goutham return err;
7864863dea3SSunil Goutham }
7874863dea3SSunil Goutham
nicvf_get_pauseparam(struct net_device * dev,struct ethtool_pauseparam * pause)788430da208SSunil Goutham static void nicvf_get_pauseparam(struct net_device *dev,
789430da208SSunil Goutham struct ethtool_pauseparam *pause)
790430da208SSunil Goutham {
791430da208SSunil Goutham struct nicvf *nic = netdev_priv(dev);
792430da208SSunil Goutham union nic_mbx mbx = {};
793430da208SSunil Goutham
794430da208SSunil Goutham /* Supported only for 10G/40G interfaces */
795430da208SSunil Goutham if ((nic->mac_type == BGX_MODE_SGMII) ||
796430da208SSunil Goutham (nic->mac_type == BGX_MODE_QSGMII) ||
797430da208SSunil Goutham (nic->mac_type == BGX_MODE_RGMII))
798430da208SSunil Goutham return;
799430da208SSunil Goutham
800430da208SSunil Goutham mbx.pfc.msg = NIC_MBOX_MSG_PFC;
801430da208SSunil Goutham mbx.pfc.get = 1;
802430da208SSunil Goutham if (!nicvf_send_msg_to_pf(nic, &mbx)) {
803430da208SSunil Goutham pause->autoneg = nic->pfc.autoneg;
804430da208SSunil Goutham pause->rx_pause = nic->pfc.fc_rx;
805430da208SSunil Goutham pause->tx_pause = nic->pfc.fc_tx;
806430da208SSunil Goutham }
807430da208SSunil Goutham }
808430da208SSunil Goutham
nicvf_set_pauseparam(struct net_device * dev,struct ethtool_pauseparam * pause)809430da208SSunil Goutham static int nicvf_set_pauseparam(struct net_device *dev,
810430da208SSunil Goutham struct ethtool_pauseparam *pause)
811430da208SSunil Goutham {
812430da208SSunil Goutham struct nicvf *nic = netdev_priv(dev);
813430da208SSunil Goutham union nic_mbx mbx = {};
814430da208SSunil Goutham
815430da208SSunil Goutham /* Supported only for 10G/40G interfaces */
816430da208SSunil Goutham if ((nic->mac_type == BGX_MODE_SGMII) ||
817430da208SSunil Goutham (nic->mac_type == BGX_MODE_QSGMII) ||
818430da208SSunil Goutham (nic->mac_type == BGX_MODE_RGMII))
819430da208SSunil Goutham return -EOPNOTSUPP;
820430da208SSunil Goutham
821430da208SSunil Goutham if (pause->autoneg)
822430da208SSunil Goutham return -EOPNOTSUPP;
823430da208SSunil Goutham
824430da208SSunil Goutham mbx.pfc.msg = NIC_MBOX_MSG_PFC;
825430da208SSunil Goutham mbx.pfc.get = 0;
826430da208SSunil Goutham mbx.pfc.fc_rx = pause->rx_pause;
827430da208SSunil Goutham mbx.pfc.fc_tx = pause->tx_pause;
828430da208SSunil Goutham if (nicvf_send_msg_to_pf(nic, &mbx))
829430da208SSunil Goutham return -EAGAIN;
830430da208SSunil Goutham
831430da208SSunil Goutham nic->pfc.fc_rx = pause->rx_pause;
832430da208SSunil Goutham nic->pfc.fc_tx = pause->tx_pause;
833430da208SSunil Goutham
834430da208SSunil Goutham return 0;
835430da208SSunil Goutham }
836430da208SSunil Goutham
nicvf_get_ts_info(struct net_device * netdev,struct ethtool_ts_info * info)8374a875509SSunil Goutham static int nicvf_get_ts_info(struct net_device *netdev,
8384a875509SSunil Goutham struct ethtool_ts_info *info)
8394a875509SSunil Goutham {
8404a875509SSunil Goutham struct nicvf *nic = netdev_priv(netdev);
8414a875509SSunil Goutham
8424a875509SSunil Goutham if (!nic->ptp_clock)
8434a875509SSunil Goutham return ethtool_op_get_ts_info(netdev, info);
8444a875509SSunil Goutham
8454a875509SSunil Goutham info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
8464a875509SSunil Goutham SOF_TIMESTAMPING_RX_SOFTWARE |
8474a875509SSunil Goutham SOF_TIMESTAMPING_SOFTWARE |
8484a875509SSunil Goutham SOF_TIMESTAMPING_TX_HARDWARE |
8494a875509SSunil Goutham SOF_TIMESTAMPING_RX_HARDWARE |
8504a875509SSunil Goutham SOF_TIMESTAMPING_RAW_HARDWARE;
8514a875509SSunil Goutham
8524a875509SSunil Goutham info->phc_index = cavium_ptp_clock_index(nic->ptp_clock);
8534a875509SSunil Goutham
8544a875509SSunil Goutham info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
8554a875509SSunil Goutham
8564a875509SSunil Goutham info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
8574a875509SSunil Goutham (1 << HWTSTAMP_FILTER_ALL);
8584a875509SSunil Goutham
8594a875509SSunil Goutham return 0;
8604a875509SSunil Goutham }
8614a875509SSunil Goutham
8624863dea3SSunil Goutham static const struct ethtool_ops nicvf_ethtool_ops = {
8630b72a9a1SSunil Goutham .get_link = nicvf_get_link,
8644863dea3SSunil Goutham .get_drvinfo = nicvf_get_drvinfo,
8654863dea3SSunil Goutham .get_msglevel = nicvf_get_msglevel,
8664863dea3SSunil Goutham .set_msglevel = nicvf_set_msglevel,
8674863dea3SSunil Goutham .get_strings = nicvf_get_strings,
8684863dea3SSunil Goutham .get_sset_count = nicvf_get_sset_count,
8694863dea3SSunil Goutham .get_ethtool_stats = nicvf_get_ethtool_stats,
8704863dea3SSunil Goutham .get_regs_len = nicvf_get_regs_len,
8714863dea3SSunil Goutham .get_regs = nicvf_get_regs,
8724863dea3SSunil Goutham .get_coalesce = nicvf_get_coalesce,
8734863dea3SSunil Goutham .get_ringparam = nicvf_get_ringparam,
874fff4ffddSSunil Goutham .set_ringparam = nicvf_set_ringparam,
8754863dea3SSunil Goutham .get_rxnfc = nicvf_get_rxnfc,
8764863dea3SSunil Goutham .set_rxnfc = nicvf_set_rxnfc,
8774863dea3SSunil Goutham .get_rxfh_key_size = nicvf_get_rxfh_key_size,
8784863dea3SSunil Goutham .get_rxfh_indir_size = nicvf_get_rxfh_indir_size,
8794863dea3SSunil Goutham .get_rxfh = nicvf_get_rxfh,
8804863dea3SSunil Goutham .set_rxfh = nicvf_set_rxfh,
8814863dea3SSunil Goutham .get_channels = nicvf_get_channels,
8824863dea3SSunil Goutham .set_channels = nicvf_set_channels,
883430da208SSunil Goutham .get_pauseparam = nicvf_get_pauseparam,
884430da208SSunil Goutham .set_pauseparam = nicvf_set_pauseparam,
8854a875509SSunil Goutham .get_ts_info = nicvf_get_ts_info,
886bfd8d977SPhilippe Reynes .get_link_ksettings = nicvf_get_link_ksettings,
8874863dea3SSunil Goutham };
8884863dea3SSunil Goutham
nicvf_set_ethtool_ops(struct net_device * netdev)8894863dea3SSunil Goutham void nicvf_set_ethtool_ops(struct net_device *netdev)
8904863dea3SSunil Goutham {
8914863dea3SSunil Goutham netdev->ethtool_ops = &nicvf_ethtool_ops;
8924863dea3SSunil Goutham }
893