2 * Copyright (C) 2015 Cavium, Inc.
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.
9 /* ETHTOOL Support for VNIC_VF Device*/
11 #include <linux/pci.h>
15 #include "nicvf_queues.h"
17 #include "thunder_bgx.h"
19 #define DRV_NAME "thunder-nicvf"
20 #define DRV_VERSION "1.0"
23 char name
[ETH_GSTRING_LEN
];
27 #define NICVF_HW_STAT(stat) { \
29 .index = offsetof(struct nicvf_hw_stats, stat) / sizeof(u64), \
32 #define NICVF_DRV_STAT(stat) { \
34 .index = offsetof(struct nicvf_drv_stats, stat) / sizeof(u64), \
37 static const struct nicvf_stat nicvf_hw_stats
[] = {
38 NICVF_HW_STAT(rx_bytes_ok
),
39 NICVF_HW_STAT(rx_ucast_frames_ok
),
40 NICVF_HW_STAT(rx_bcast_frames_ok
),
41 NICVF_HW_STAT(rx_mcast_frames_ok
),
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(tx_bytes_ok
),
53 NICVF_HW_STAT(tx_ucast_frames_ok
),
54 NICVF_HW_STAT(tx_bcast_frames_ok
),
55 NICVF_HW_STAT(tx_mcast_frames_ok
),
58 static const struct nicvf_stat nicvf_drv_stats
[] = {
59 NICVF_DRV_STAT(rx_frames_ok
),
60 NICVF_DRV_STAT(rx_frames_64
),
61 NICVF_DRV_STAT(rx_frames_127
),
62 NICVF_DRV_STAT(rx_frames_255
),
63 NICVF_DRV_STAT(rx_frames_511
),
64 NICVF_DRV_STAT(rx_frames_1023
),
65 NICVF_DRV_STAT(rx_frames_1518
),
66 NICVF_DRV_STAT(rx_frames_jumbo
),
67 NICVF_DRV_STAT(rx_drops
),
68 NICVF_DRV_STAT(tx_frames_ok
),
69 NICVF_DRV_STAT(tx_tso
),
70 NICVF_DRV_STAT(tx_drops
),
71 NICVF_DRV_STAT(txq_stop
),
72 NICVF_DRV_STAT(txq_wake
),
75 static const struct nicvf_stat nicvf_queue_stats
[] = {
80 static const unsigned int nicvf_n_hw_stats
= ARRAY_SIZE(nicvf_hw_stats
);
81 static const unsigned int nicvf_n_drv_stats
= ARRAY_SIZE(nicvf_drv_stats
);
82 static const unsigned int nicvf_n_queue_stats
= ARRAY_SIZE(nicvf_queue_stats
);
84 static int nicvf_get_settings(struct net_device
*netdev
,
85 struct ethtool_cmd
*cmd
)
87 struct nicvf
*nic
= netdev_priv(netdev
);
90 cmd
->transceiver
= XCVR_EXTERNAL
;
91 if (nic
->speed
<= 1000) {
93 cmd
->autoneg
= AUTONEG_ENABLE
;
95 cmd
->port
= PORT_FIBRE
;
96 cmd
->autoneg
= AUTONEG_DISABLE
;
98 cmd
->duplex
= nic
->duplex
;
99 ethtool_cmd_speed_set(cmd
, nic
->speed
);
104 static void nicvf_get_drvinfo(struct net_device
*netdev
,
105 struct ethtool_drvinfo
*info
)
107 struct nicvf
*nic
= netdev_priv(netdev
);
109 strlcpy(info
->driver
, DRV_NAME
, sizeof(info
->driver
));
110 strlcpy(info
->version
, DRV_VERSION
, sizeof(info
->version
));
111 strlcpy(info
->bus_info
, pci_name(nic
->pdev
), sizeof(info
->bus_info
));
114 static u32
nicvf_get_msglevel(struct net_device
*netdev
)
116 struct nicvf
*nic
= netdev_priv(netdev
);
118 return nic
->msg_enable
;
121 static void nicvf_set_msglevel(struct net_device
*netdev
, u32 lvl
)
123 struct nicvf
*nic
= netdev_priv(netdev
);
125 nic
->msg_enable
= lvl
;
128 static void nicvf_get_strings(struct net_device
*netdev
, u32 sset
, u8
*data
)
130 struct nicvf
*nic
= netdev_priv(netdev
);
133 if (sset
!= ETH_SS_STATS
)
136 for (stats
= 0; stats
< nicvf_n_hw_stats
; stats
++) {
137 memcpy(data
, nicvf_hw_stats
[stats
].name
, ETH_GSTRING_LEN
);
138 data
+= ETH_GSTRING_LEN
;
141 for (stats
= 0; stats
< nicvf_n_drv_stats
; stats
++) {
142 memcpy(data
, nicvf_drv_stats
[stats
].name
, ETH_GSTRING_LEN
);
143 data
+= ETH_GSTRING_LEN
;
146 for (qidx
= 0; qidx
< nic
->qs
->rq_cnt
; qidx
++) {
147 for (stats
= 0; stats
< nicvf_n_queue_stats
; stats
++) {
148 sprintf(data
, "rxq%d: %s", qidx
,
149 nicvf_queue_stats
[stats
].name
);
150 data
+= ETH_GSTRING_LEN
;
154 for (qidx
= 0; qidx
< nic
->qs
->sq_cnt
; qidx
++) {
155 for (stats
= 0; stats
< nicvf_n_queue_stats
; stats
++) {
156 sprintf(data
, "txq%d: %s", qidx
,
157 nicvf_queue_stats
[stats
].name
);
158 data
+= ETH_GSTRING_LEN
;
162 for (stats
= 0; stats
< BGX_RX_STATS_COUNT
; stats
++) {
163 sprintf(data
, "bgx_rxstat%d: ", stats
);
164 data
+= ETH_GSTRING_LEN
;
167 for (stats
= 0; stats
< BGX_TX_STATS_COUNT
; stats
++) {
168 sprintf(data
, "bgx_txstat%d: ", stats
);
169 data
+= ETH_GSTRING_LEN
;
173 static int nicvf_get_sset_count(struct net_device
*netdev
, int sset
)
175 struct nicvf
*nic
= netdev_priv(netdev
);
177 if (sset
!= ETH_SS_STATS
)
180 return nicvf_n_hw_stats
+ nicvf_n_drv_stats
+
181 (nicvf_n_queue_stats
*
182 (nic
->qs
->rq_cnt
+ nic
->qs
->sq_cnt
)) +
183 BGX_RX_STATS_COUNT
+ BGX_TX_STATS_COUNT
;
186 static void nicvf_get_ethtool_stats(struct net_device
*netdev
,
187 struct ethtool_stats
*stats
, u64
*data
)
189 struct nicvf
*nic
= netdev_priv(netdev
);
192 nicvf_update_stats(nic
);
194 /* Update LMAC stats */
195 nicvf_update_lmac_stats(nic
);
197 for (stat
= 0; stat
< nicvf_n_hw_stats
; stat
++)
198 *(data
++) = ((u64
*)&nic
->stats
)
199 [nicvf_hw_stats
[stat
].index
];
200 for (stat
= 0; stat
< nicvf_n_drv_stats
; stat
++)
201 *(data
++) = ((u64
*)&nic
->drv_stats
)
202 [nicvf_drv_stats
[stat
].index
];
204 for (qidx
= 0; qidx
< nic
->qs
->rq_cnt
; qidx
++) {
205 for (stat
= 0; stat
< nicvf_n_queue_stats
; stat
++)
206 *(data
++) = ((u64
*)&nic
->qs
->rq
[qidx
].stats
)
207 [nicvf_queue_stats
[stat
].index
];
210 for (qidx
= 0; qidx
< nic
->qs
->sq_cnt
; qidx
++) {
211 for (stat
= 0; stat
< nicvf_n_queue_stats
; stat
++)
212 *(data
++) = ((u64
*)&nic
->qs
->sq
[qidx
].stats
)
213 [nicvf_queue_stats
[stat
].index
];
216 for (stat
= 0; stat
< BGX_RX_STATS_COUNT
; stat
++)
217 *(data
++) = nic
->bgx_stats
.rx_stats
[stat
];
218 for (stat
= 0; stat
< BGX_TX_STATS_COUNT
; stat
++)
219 *(data
++) = nic
->bgx_stats
.tx_stats
[stat
];
222 static int nicvf_get_regs_len(struct net_device
*dev
)
224 return sizeof(u64
) * NIC_VF_REG_COUNT
;
227 static void nicvf_get_regs(struct net_device
*dev
,
228 struct ethtool_regs
*regs
, void *reg
)
230 struct nicvf
*nic
= netdev_priv(dev
);
233 int mbox
, key
, stat
, q
;
237 memset(p
, 0, NIC_VF_REG_COUNT
);
239 p
[i
++] = nicvf_reg_read(nic
, NIC_VNIC_CFG
);
240 /* Mailbox registers */
241 for (mbox
= 0; mbox
< NIC_PF_VF_MAILBOX_SIZE
; mbox
++)
242 p
[i
++] = nicvf_reg_read(nic
,
243 NIC_VF_PF_MAILBOX_0_1
| (mbox
<< 3));
245 p
[i
++] = nicvf_reg_read(nic
, NIC_VF_INT
);
246 p
[i
++] = nicvf_reg_read(nic
, NIC_VF_INT_W1S
);
247 p
[i
++] = nicvf_reg_read(nic
, NIC_VF_ENA_W1C
);
248 p
[i
++] = nicvf_reg_read(nic
, NIC_VF_ENA_W1S
);
249 p
[i
++] = nicvf_reg_read(nic
, NIC_VNIC_RSS_CFG
);
251 for (key
= 0; key
< RSS_HASH_KEY_SIZE
; key
++)
252 p
[i
++] = nicvf_reg_read(nic
, NIC_VNIC_RSS_KEY_0_4
| (key
<< 3));
254 /* Tx/Rx statistics */
255 for (stat
= 0; stat
< TX_STATS_ENUM_LAST
; stat
++)
256 p
[i
++] = nicvf_reg_read(nic
,
257 NIC_VNIC_TX_STAT_0_4
| (stat
<< 3));
259 for (i
= 0; i
< RX_STATS_ENUM_LAST
; i
++)
260 p
[i
++] = nicvf_reg_read(nic
,
261 NIC_VNIC_RX_STAT_0_13
| (stat
<< 3));
263 p
[i
++] = nicvf_reg_read(nic
, NIC_QSET_RQ_GEN_CFG
);
265 /* All completion queue's registers */
266 for (q
= 0; q
< MAX_CMP_QUEUES_PER_QS
; q
++) {
267 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_CFG
, q
);
268 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_CFG2
, q
);
269 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_THRESH
, q
);
270 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_BASE
, q
);
271 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_HEAD
, q
);
272 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_TAIL
, q
);
273 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_DOOR
, q
);
274 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_STATUS
, q
);
275 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_STATUS2
, q
);
276 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_CQ_0_7_DEBUG
, q
);
279 /* All receive queue's registers */
280 for (q
= 0; q
< MAX_RCV_QUEUES_PER_QS
; q
++) {
281 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_RQ_0_7_CFG
, q
);
282 p
[i
++] = nicvf_queue_reg_read(nic
,
283 NIC_QSET_RQ_0_7_STAT_0_1
, q
);
284 reg_offset
= NIC_QSET_RQ_0_7_STAT_0_1
| (1 << 3);
285 p
[i
++] = nicvf_queue_reg_read(nic
, reg_offset
, q
);
288 for (q
= 0; q
< MAX_SND_QUEUES_PER_QS
; q
++) {
289 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_CFG
, q
);
290 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_THRESH
, q
);
291 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_BASE
, q
);
292 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_HEAD
, q
);
293 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_TAIL
, q
);
294 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_DOOR
, q
);
295 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_STATUS
, q
);
296 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_DEBUG
, q
);
297 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_CNM_CHG
, q
);
298 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_SQ_0_7_STAT_0_1
, q
);
299 reg_offset
= NIC_QSET_SQ_0_7_STAT_0_1
| (1 << 3);
300 p
[i
++] = nicvf_queue_reg_read(nic
, reg_offset
, q
);
303 for (q
= 0; q
< MAX_RCV_BUF_DESC_RINGS_PER_QS
; q
++) {
304 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_RBDR_0_1_CFG
, q
);
305 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_RBDR_0_1_THRESH
, q
);
306 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_RBDR_0_1_BASE
, q
);
307 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_RBDR_0_1_HEAD
, q
);
308 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_RBDR_0_1_TAIL
, q
);
309 p
[i
++] = nicvf_queue_reg_read(nic
, NIC_QSET_RBDR_0_1_DOOR
, q
);
310 p
[i
++] = nicvf_queue_reg_read(nic
,
311 NIC_QSET_RBDR_0_1_STATUS0
, q
);
312 p
[i
++] = nicvf_queue_reg_read(nic
,
313 NIC_QSET_RBDR_0_1_STATUS1
, q
);
314 reg_offset
= NIC_QSET_RBDR_0_1_PREFETCH_STATUS
;
315 p
[i
++] = nicvf_queue_reg_read(nic
, reg_offset
, q
);
319 static int nicvf_get_coalesce(struct net_device
*netdev
,
320 struct ethtool_coalesce
*cmd
)
322 struct nicvf
*nic
= netdev_priv(netdev
);
324 cmd
->rx_coalesce_usecs
= nic
->cq_coalesce_usecs
;
328 static void nicvf_get_ringparam(struct net_device
*netdev
,
329 struct ethtool_ringparam
*ring
)
331 struct nicvf
*nic
= netdev_priv(netdev
);
332 struct queue_set
*qs
= nic
->qs
;
334 ring
->rx_max_pending
= MAX_RCV_BUF_COUNT
;
335 ring
->rx_pending
= qs
->rbdr_len
;
336 ring
->tx_max_pending
= MAX_SND_QUEUE_LEN
;
337 ring
->tx_pending
= qs
->sq_len
;
340 static int nicvf_get_rss_hash_opts(struct nicvf
*nic
,
341 struct ethtool_rxnfc
*info
)
345 switch (info
->flow_type
) {
352 info
->data
|= RXH_L4_B_0_1
| RXH_L4_B_2_3
;
355 info
->data
|= RXH_IP_SRC
| RXH_IP_DST
;
364 static int nicvf_get_rxnfc(struct net_device
*dev
,
365 struct ethtool_rxnfc
*info
, u32
*rules
)
367 struct nicvf
*nic
= netdev_priv(dev
);
368 int ret
= -EOPNOTSUPP
;
371 case ETHTOOL_GRXRINGS
:
372 info
->data
= nic
->qs
->rq_cnt
;
376 return nicvf_get_rss_hash_opts(nic
, info
);
383 static int nicvf_set_rss_hash_opts(struct nicvf
*nic
,
384 struct ethtool_rxnfc
*info
)
386 struct nicvf_rss_info
*rss
= &nic
->rss_info
;
387 u64 rss_cfg
= nicvf_reg_read(nic
, NIC_VNIC_RSS_CFG
);
390 netdev_err(nic
->netdev
,
391 "RSS is disabled, hash cannot be set\n");
393 netdev_info(nic
->netdev
, "Set RSS flow type = %d, data = %lld\n",
394 info
->flow_type
, info
->data
);
396 if (!(info
->data
& RXH_IP_SRC
) || !(info
->data
& RXH_IP_DST
))
399 switch (info
->flow_type
) {
402 switch (info
->data
& (RXH_L4_B_0_1
| RXH_L4_B_2_3
)) {
404 rss_cfg
&= ~(1ULL << RSS_HASH_TCP
);
406 case (RXH_L4_B_0_1
| RXH_L4_B_2_3
):
407 rss_cfg
|= (1ULL << RSS_HASH_TCP
);
415 switch (info
->data
& (RXH_L4_B_0_1
| RXH_L4_B_2_3
)) {
417 rss_cfg
&= ~(1ULL << RSS_HASH_UDP
);
419 case (RXH_L4_B_0_1
| RXH_L4_B_2_3
):
420 rss_cfg
|= (1ULL << RSS_HASH_UDP
);
428 switch (info
->data
& (RXH_L4_B_0_1
| RXH_L4_B_2_3
)) {
430 rss_cfg
&= ~(1ULL << RSS_HASH_L4ETC
);
432 case (RXH_L4_B_0_1
| RXH_L4_B_2_3
):
433 rss_cfg
|= (1ULL << RSS_HASH_L4ETC
);
441 rss_cfg
= RSS_HASH_IP
;
447 nicvf_reg_write(nic
, NIC_VNIC_RSS_CFG
, rss_cfg
);
451 static int nicvf_set_rxnfc(struct net_device
*dev
, struct ethtool_rxnfc
*info
)
453 struct nicvf
*nic
= netdev_priv(dev
);
457 return nicvf_set_rss_hash_opts(nic
, info
);
464 static u32
nicvf_get_rxfh_key_size(struct net_device
*netdev
)
466 return RSS_HASH_KEY_SIZE
* sizeof(u64
);
469 static u32
nicvf_get_rxfh_indir_size(struct net_device
*dev
)
471 struct nicvf
*nic
= netdev_priv(dev
);
473 return nic
->rss_info
.rss_size
;
476 static int nicvf_get_rxfh(struct net_device
*dev
, u32
*indir
, u8
*hkey
,
479 struct nicvf
*nic
= netdev_priv(dev
);
480 struct nicvf_rss_info
*rss
= &nic
->rss_info
;
484 for (idx
= 0; idx
< rss
->rss_size
; idx
++)
485 indir
[idx
] = rss
->ind_tbl
[idx
];
489 memcpy(hkey
, rss
->key
, RSS_HASH_KEY_SIZE
* sizeof(u64
));
492 *hfunc
= ETH_RSS_HASH_TOP
;
497 static int nicvf_set_rxfh(struct net_device
*dev
, const u32
*indir
,
498 const u8
*hkey
, u8 hfunc
)
500 struct nicvf
*nic
= netdev_priv(dev
);
501 struct nicvf_rss_info
*rss
= &nic
->rss_info
;
504 if ((nic
->qs
->rq_cnt
<= 1) || (nic
->cpi_alg
!= CPI_ALG_NONE
)) {
510 /* We do not allow change in unsupported parameters */
511 if (hfunc
!= ETH_RSS_HASH_NO_CHANGE
&& hfunc
!= ETH_RSS_HASH_TOP
)
516 for (idx
= 0; idx
< rss
->rss_size
; idx
++)
517 rss
->ind_tbl
[idx
] = indir
[idx
];
521 memcpy(rss
->key
, hkey
, RSS_HASH_KEY_SIZE
* sizeof(u64
));
522 nicvf_set_rss_key(nic
);
525 nicvf_config_rss(nic
);
529 /* Get no of queues device supports and current queue count */
530 static void nicvf_get_channels(struct net_device
*dev
,
531 struct ethtool_channels
*channel
)
533 struct nicvf
*nic
= netdev_priv(dev
);
535 memset(channel
, 0, sizeof(*channel
));
537 channel
->max_rx
= MAX_RCV_QUEUES_PER_QS
;
538 channel
->max_tx
= MAX_SND_QUEUES_PER_QS
;
540 channel
->rx_count
= nic
->qs
->rq_cnt
;
541 channel
->tx_count
= nic
->qs
->sq_cnt
;
544 /* Set no of Tx, Rx queues to be used */
545 static int nicvf_set_channels(struct net_device
*dev
,
546 struct ethtool_channels
*channel
)
548 struct nicvf
*nic
= netdev_priv(dev
);
550 bool if_up
= netif_running(dev
);
552 if (!channel
->rx_count
|| !channel
->tx_count
)
554 if (channel
->rx_count
> MAX_RCV_QUEUES_PER_QS
)
556 if (channel
->tx_count
> MAX_SND_QUEUES_PER_QS
)
562 nic
->qs
->rq_cnt
= channel
->rx_count
;
563 nic
->qs
->sq_cnt
= channel
->tx_count
;
564 nic
->qs
->cq_cnt
= max(nic
->qs
->rq_cnt
, nic
->qs
->sq_cnt
);
566 err
= nicvf_set_real_num_queues(dev
, nic
->qs
->sq_cnt
, nic
->qs
->rq_cnt
);
573 netdev_info(dev
, "Setting num Tx rings to %d, Rx rings to %d success\n",
574 nic
->qs
->sq_cnt
, nic
->qs
->rq_cnt
);
579 static const struct ethtool_ops nicvf_ethtool_ops
= {
580 .get_settings
= nicvf_get_settings
,
581 .get_link
= ethtool_op_get_link
,
582 .get_drvinfo
= nicvf_get_drvinfo
,
583 .get_msglevel
= nicvf_get_msglevel
,
584 .set_msglevel
= nicvf_set_msglevel
,
585 .get_strings
= nicvf_get_strings
,
586 .get_sset_count
= nicvf_get_sset_count
,
587 .get_ethtool_stats
= nicvf_get_ethtool_stats
,
588 .get_regs_len
= nicvf_get_regs_len
,
589 .get_regs
= nicvf_get_regs
,
590 .get_coalesce
= nicvf_get_coalesce
,
591 .get_ringparam
= nicvf_get_ringparam
,
592 .get_rxnfc
= nicvf_get_rxnfc
,
593 .set_rxnfc
= nicvf_set_rxnfc
,
594 .get_rxfh_key_size
= nicvf_get_rxfh_key_size
,
595 .get_rxfh_indir_size
= nicvf_get_rxfh_indir_size
,
596 .get_rxfh
= nicvf_get_rxfh
,
597 .set_rxfh
= nicvf_set_rxfh
,
598 .get_channels
= nicvf_get_channels
,
599 .set_channels
= nicvf_set_channels
,
600 .get_ts_info
= ethtool_op_get_ts_info
,
603 void nicvf_set_ethtool_ops(struct net_device
*netdev
)
605 netdev
->ethtool_ops
= &nicvf_ethtool_ops
;