2 * Copyright (C) 2015-2017 Netronome Systems, Inc.
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
9 * The BSD 2-Clause License:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
36 * Netronome network device driver: ethtool support
37 * Authors: Jakub Kicinski <jakub.kicinski@netronome.com>
38 * Jason McMullan <jason.mcmullan@netronome.com>
39 * Rolf Neugebauer <rolf.neugebauer@netronome.com>
40 * Brad Petrus <brad.petrus@netronome.com>
43 #include <linux/bitfield.h>
44 #include <linux/kernel.h>
45 #include <linux/netdevice.h>
46 #include <linux/etherdevice.h>
47 #include <linux/interrupt.h>
48 #include <linux/pci.h>
49 #include <linux/ethtool.h>
51 #include "nfpcore/nfp.h"
52 #include "nfpcore/nfp_nsp_eth.h"
53 #include "nfp_net_ctrl.h"
57 NFP_DUMP_NSP_DIAG
= 0,
60 /* Support for stats. Returns netdev, driver, and device stats */
61 enum { NETDEV_ET_STATS
, NFP_NET_DRV_ET_STATS
, NFP_NET_DEV_ET_STATS
};
62 struct _nfp_net_et_stats
{
63 char name
[ETH_GSTRING_LEN
];
69 #define NN_ET_NETDEV_STAT(m) NETDEV_ET_STATS, \
70 FIELD_SIZEOF(struct net_device_stats, m), \
71 offsetof(struct net_device_stats, m)
72 /* For stats in the control BAR (other than Q stats) */
73 #define NN_ET_DEV_STAT(m) NFP_NET_DEV_ET_STATS, \
76 static const struct _nfp_net_et_stats nfp_net_et_stats
[] = {
78 {"rx_packets", NN_ET_NETDEV_STAT(rx_packets
)},
79 {"tx_packets", NN_ET_NETDEV_STAT(tx_packets
)},
80 {"rx_bytes", NN_ET_NETDEV_STAT(rx_bytes
)},
81 {"tx_bytes", NN_ET_NETDEV_STAT(tx_bytes
)},
82 {"rx_errors", NN_ET_NETDEV_STAT(rx_errors
)},
83 {"tx_errors", NN_ET_NETDEV_STAT(tx_errors
)},
84 {"rx_dropped", NN_ET_NETDEV_STAT(rx_dropped
)},
85 {"tx_dropped", NN_ET_NETDEV_STAT(tx_dropped
)},
86 {"multicast", NN_ET_NETDEV_STAT(multicast
)},
87 {"collisions", NN_ET_NETDEV_STAT(collisions
)},
88 {"rx_over_errors", NN_ET_NETDEV_STAT(rx_over_errors
)},
89 {"rx_crc_errors", NN_ET_NETDEV_STAT(rx_crc_errors
)},
90 {"rx_frame_errors", NN_ET_NETDEV_STAT(rx_frame_errors
)},
91 {"rx_fifo_errors", NN_ET_NETDEV_STAT(rx_fifo_errors
)},
92 {"rx_missed_errors", NN_ET_NETDEV_STAT(rx_missed_errors
)},
93 {"tx_aborted_errors", NN_ET_NETDEV_STAT(tx_aborted_errors
)},
94 {"tx_carrier_errors", NN_ET_NETDEV_STAT(tx_carrier_errors
)},
95 {"tx_fifo_errors", NN_ET_NETDEV_STAT(tx_fifo_errors
)},
96 /* Stats from the device */
97 {"dev_rx_discards", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_DISCARDS
)},
98 {"dev_rx_errors", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_ERRORS
)},
99 {"dev_rx_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_OCTETS
)},
100 {"dev_rx_uc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_UC_OCTETS
)},
101 {"dev_rx_mc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_MC_OCTETS
)},
102 {"dev_rx_bc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_BC_OCTETS
)},
103 {"dev_rx_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_FRAMES
)},
104 {"dev_rx_mc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_MC_FRAMES
)},
105 {"dev_rx_bc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_RX_BC_FRAMES
)},
107 {"dev_tx_discards", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_DISCARDS
)},
108 {"dev_tx_errors", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_ERRORS
)},
109 {"dev_tx_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_OCTETS
)},
110 {"dev_tx_uc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_UC_OCTETS
)},
111 {"dev_tx_mc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_MC_OCTETS
)},
112 {"dev_tx_bc_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_BC_OCTETS
)},
113 {"dev_tx_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_FRAMES
)},
114 {"dev_tx_mc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_MC_FRAMES
)},
115 {"dev_tx_bc_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_TX_BC_FRAMES
)},
117 {"bpf_pass_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP0_FRAMES
)},
118 {"bpf_pass_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP0_BYTES
)},
119 /* see comments in outro functions in nfp_bpf_jit.c to find out
120 * how different BPF modes use app-specific counters
122 {"bpf_app1_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP1_FRAMES
)},
123 {"bpf_app1_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP1_BYTES
)},
124 {"bpf_app2_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP2_FRAMES
)},
125 {"bpf_app2_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP2_BYTES
)},
126 {"bpf_app3_pkts", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP3_FRAMES
)},
127 {"bpf_app3_bytes", NN_ET_DEV_STAT(NFP_NET_CFG_STATS_APP3_BYTES
)},
130 #define NN_ET_GLOBAL_STATS_LEN ARRAY_SIZE(nfp_net_et_stats)
131 #define NN_ET_RVEC_STATS_LEN (nn->dp.num_r_vecs * 3)
132 #define NN_ET_RVEC_GATHER_STATS 7
133 #define NN_ET_QUEUE_STATS_LEN ((nn->dp.num_tx_rings + nn->dp.num_rx_rings) * 2)
134 #define NN_ET_STATS_LEN (NN_ET_GLOBAL_STATS_LEN + NN_ET_RVEC_GATHER_STATS + \
135 NN_ET_RVEC_STATS_LEN + NN_ET_QUEUE_STATS_LEN)
137 static void nfp_net_get_nspinfo(struct nfp_net
*nn
, char *version
)
144 nsp
= nfp_nsp_open(nn
->cpp
);
148 snprintf(version
, ETHTOOL_FWVERS_LEN
, "sp:%hu.%hu",
149 nfp_nsp_get_abi_ver_major(nsp
),
150 nfp_nsp_get_abi_ver_minor(nsp
));
155 static void nfp_net_get_drvinfo(struct net_device
*netdev
,
156 struct ethtool_drvinfo
*drvinfo
)
158 char nsp_version
[ETHTOOL_FWVERS_LEN
] = {};
159 struct nfp_net
*nn
= netdev_priv(netdev
);
161 strlcpy(drvinfo
->driver
, nn
->pdev
->driver
->name
,
162 sizeof(drvinfo
->driver
));
163 strlcpy(drvinfo
->version
, nfp_driver_version
, sizeof(drvinfo
->version
));
165 nfp_net_get_nspinfo(nn
, nsp_version
);
166 snprintf(drvinfo
->fw_version
, sizeof(drvinfo
->fw_version
),
168 nn
->fw_ver
.resv
, nn
->fw_ver
.class,
169 nn
->fw_ver
.major
, nn
->fw_ver
.minor
, nsp_version
);
170 strlcpy(drvinfo
->bus_info
, pci_name(nn
->pdev
),
171 sizeof(drvinfo
->bus_info
));
173 drvinfo
->n_stats
= NN_ET_STATS_LEN
;
174 drvinfo
->regdump_len
= NFP_NET_CFG_BAR_SZ
;
178 * nfp_net_get_link_ksettings - Get Link Speed settings
179 * @netdev: network interface device structure
180 * @cmd: ethtool command
182 * Reports speed settings based on info in the BAR provided by the fw.
185 nfp_net_get_link_ksettings(struct net_device
*netdev
,
186 struct ethtool_link_ksettings
*cmd
)
188 static const u32 ls_to_ethtool
[] = {
189 [NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED
] = 0,
190 [NFP_NET_CFG_STS_LINK_RATE_UNKNOWN
] = SPEED_UNKNOWN
,
191 [NFP_NET_CFG_STS_LINK_RATE_1G
] = SPEED_1000
,
192 [NFP_NET_CFG_STS_LINK_RATE_10G
] = SPEED_10000
,
193 [NFP_NET_CFG_STS_LINK_RATE_25G
] = SPEED_25000
,
194 [NFP_NET_CFG_STS_LINK_RATE_40G
] = SPEED_40000
,
195 [NFP_NET_CFG_STS_LINK_RATE_50G
] = SPEED_50000
,
196 [NFP_NET_CFG_STS_LINK_RATE_100G
] = SPEED_100000
,
198 struct nfp_net
*nn
= netdev_priv(netdev
);
201 ethtool_link_ksettings_add_link_mode(cmd
, supported
, FIBRE
);
202 cmd
->base
.port
= PORT_OTHER
;
203 cmd
->base
.speed
= SPEED_UNKNOWN
;
204 cmd
->base
.duplex
= DUPLEX_UNKNOWN
;
207 cmd
->base
.autoneg
= nn
->eth_port
->aneg
!= NFP_ANEG_DISABLED
?
208 AUTONEG_ENABLE
: AUTONEG_DISABLE
;
210 if (!netif_carrier_ok(netdev
))
213 /* Use link speed from ETH table if available, otherwise try the BAR */
214 if (nn
->eth_port
&& nfp_net_link_changed_read_clear(nn
))
215 nfp_net_refresh_port_config(nn
);
216 /* Separate if - on FW error the port could've disappeared from table */
218 cmd
->base
.port
= nn
->eth_port
->port_type
;
219 cmd
->base
.speed
= nn
->eth_port
->speed
;
220 cmd
->base
.duplex
= DUPLEX_FULL
;
224 sts
= nn_readl(nn
, NFP_NET_CFG_STS
);
226 ls
= FIELD_GET(NFP_NET_CFG_STS_LINK_RATE
, sts
);
227 if (ls
== NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED
)
230 if (ls
== NFP_NET_CFG_STS_LINK_RATE_UNKNOWN
||
231 ls
>= ARRAY_SIZE(ls_to_ethtool
))
234 cmd
->base
.speed
= ls_to_ethtool
[sts
];
235 cmd
->base
.duplex
= DUPLEX_FULL
;
240 static void nfp_net_get_ringparam(struct net_device
*netdev
,
241 struct ethtool_ringparam
*ring
)
243 struct nfp_net
*nn
= netdev_priv(netdev
);
245 ring
->rx_max_pending
= NFP_NET_MAX_RX_DESCS
;
246 ring
->tx_max_pending
= NFP_NET_MAX_TX_DESCS
;
247 ring
->rx_pending
= nn
->dp
.rxd_cnt
;
248 ring
->tx_pending
= nn
->dp
.txd_cnt
;
251 static int nfp_net_set_ring_size(struct nfp_net
*nn
, u32 rxd_cnt
, u32 txd_cnt
)
253 struct nfp_net_dp
*dp
;
255 dp
= nfp_net_clone_dp(nn
);
259 dp
->rxd_cnt
= rxd_cnt
;
260 dp
->txd_cnt
= txd_cnt
;
262 return nfp_net_ring_reconfig(nn
, dp
);
265 static int nfp_net_set_ringparam(struct net_device
*netdev
,
266 struct ethtool_ringparam
*ring
)
268 struct nfp_net
*nn
= netdev_priv(netdev
);
269 u32 rxd_cnt
, txd_cnt
;
271 /* We don't have separate queues/rings for small/large frames. */
272 if (ring
->rx_mini_pending
|| ring
->rx_jumbo_pending
)
275 /* Round up to supported values */
276 rxd_cnt
= roundup_pow_of_two(ring
->rx_pending
);
277 txd_cnt
= roundup_pow_of_two(ring
->tx_pending
);
279 if (rxd_cnt
< NFP_NET_MIN_RX_DESCS
|| rxd_cnt
> NFP_NET_MAX_RX_DESCS
||
280 txd_cnt
< NFP_NET_MIN_TX_DESCS
|| txd_cnt
> NFP_NET_MAX_TX_DESCS
)
283 if (nn
->dp
.rxd_cnt
== rxd_cnt
&& nn
->dp
.txd_cnt
== txd_cnt
)
286 nn_dbg(nn
, "Change ring size: RxQ %u->%u, TxQ %u->%u\n",
287 nn
->dp
.rxd_cnt
, rxd_cnt
, nn
->dp
.txd_cnt
, txd_cnt
);
289 return nfp_net_set_ring_size(nn
, rxd_cnt
, txd_cnt
);
292 static void nfp_net_get_strings(struct net_device
*netdev
,
293 u32 stringset
, u8
*data
)
295 struct nfp_net
*nn
= netdev_priv(netdev
);
301 for (i
= 0; i
< NN_ET_GLOBAL_STATS_LEN
; i
++) {
302 memcpy(p
, nfp_net_et_stats
[i
].name
, ETH_GSTRING_LEN
);
303 p
+= ETH_GSTRING_LEN
;
305 for (i
= 0; i
< nn
->dp
.num_r_vecs
; i
++) {
306 sprintf(p
, "rvec_%u_rx_pkts", i
);
307 p
+= ETH_GSTRING_LEN
;
308 sprintf(p
, "rvec_%u_tx_pkts", i
);
309 p
+= ETH_GSTRING_LEN
;
310 sprintf(p
, "rvec_%u_tx_busy", i
);
311 p
+= ETH_GSTRING_LEN
;
313 strncpy(p
, "hw_rx_csum_ok", ETH_GSTRING_LEN
);
314 p
+= ETH_GSTRING_LEN
;
315 strncpy(p
, "hw_rx_csum_inner_ok", ETH_GSTRING_LEN
);
316 p
+= ETH_GSTRING_LEN
;
317 strncpy(p
, "hw_rx_csum_err", ETH_GSTRING_LEN
);
318 p
+= ETH_GSTRING_LEN
;
319 strncpy(p
, "hw_tx_csum", ETH_GSTRING_LEN
);
320 p
+= ETH_GSTRING_LEN
;
321 strncpy(p
, "hw_tx_inner_csum", ETH_GSTRING_LEN
);
322 p
+= ETH_GSTRING_LEN
;
323 strncpy(p
, "tx_gather", ETH_GSTRING_LEN
);
324 p
+= ETH_GSTRING_LEN
;
325 strncpy(p
, "tx_lso", ETH_GSTRING_LEN
);
326 p
+= ETH_GSTRING_LEN
;
327 for (i
= 0; i
< nn
->dp
.num_tx_rings
; i
++) {
328 sprintf(p
, "txq_%u_pkts", i
);
329 p
+= ETH_GSTRING_LEN
;
330 sprintf(p
, "txq_%u_bytes", i
);
331 p
+= ETH_GSTRING_LEN
;
333 for (i
= 0; i
< nn
->dp
.num_rx_rings
; i
++) {
334 sprintf(p
, "rxq_%u_pkts", i
);
335 p
+= ETH_GSTRING_LEN
;
336 sprintf(p
, "rxq_%u_bytes", i
);
337 p
+= ETH_GSTRING_LEN
;
343 static void nfp_net_get_stats(struct net_device
*netdev
,
344 struct ethtool_stats
*stats
, u64
*data
)
346 u64 gathered_stats
[NN_ET_RVEC_GATHER_STATS
] = {};
347 struct nfp_net
*nn
= netdev_priv(netdev
);
348 struct rtnl_link_stats64
*netdev_stats
;
349 struct rtnl_link_stats64 temp
= {};
350 u64 tmp
[NN_ET_RVEC_GATHER_STATS
];
355 netdev_stats
= dev_get_stats(netdev
, &temp
);
357 for (i
= 0; i
< NN_ET_GLOBAL_STATS_LEN
; i
++) {
358 switch (nfp_net_et_stats
[i
].type
) {
359 case NETDEV_ET_STATS
:
360 p
= (char *)netdev_stats
+ nfp_net_et_stats
[i
].off
;
361 data
[i
] = nfp_net_et_stats
[i
].sz
== sizeof(u64
) ?
362 *(u64
*)p
: *(u32
*)p
;
365 case NFP_NET_DEV_ET_STATS
:
366 io_p
= nn
->dp
.ctrl_bar
+ nfp_net_et_stats
[i
].off
;
367 data
[i
] = readq(io_p
);
371 for (j
= 0; j
< nn
->dp
.num_r_vecs
; j
++) {
375 start
= u64_stats_fetch_begin(&nn
->r_vecs
[j
].rx_sync
);
376 data
[i
++] = nn
->r_vecs
[j
].rx_pkts
;
377 tmp
[0] = nn
->r_vecs
[j
].hw_csum_rx_ok
;
378 tmp
[1] = nn
->r_vecs
[j
].hw_csum_rx_inner_ok
;
379 tmp
[2] = nn
->r_vecs
[j
].hw_csum_rx_error
;
380 } while (u64_stats_fetch_retry(&nn
->r_vecs
[j
].rx_sync
, start
));
383 start
= u64_stats_fetch_begin(&nn
->r_vecs
[j
].tx_sync
);
384 data
[i
++] = nn
->r_vecs
[j
].tx_pkts
;
385 data
[i
++] = nn
->r_vecs
[j
].tx_busy
;
386 tmp
[3] = nn
->r_vecs
[j
].hw_csum_tx
;
387 tmp
[4] = nn
->r_vecs
[j
].hw_csum_tx_inner
;
388 tmp
[5] = nn
->r_vecs
[j
].tx_gather
;
389 tmp
[6] = nn
->r_vecs
[j
].tx_lso
;
390 } while (u64_stats_fetch_retry(&nn
->r_vecs
[j
].tx_sync
, start
));
392 for (k
= 0; k
< NN_ET_RVEC_GATHER_STATS
; k
++)
393 gathered_stats
[k
] += tmp
[k
];
395 for (j
= 0; j
< NN_ET_RVEC_GATHER_STATS
; j
++)
396 data
[i
++] = gathered_stats
[j
];
397 for (j
= 0; j
< nn
->dp
.num_tx_rings
; j
++) {
398 io_p
= nn
->dp
.ctrl_bar
+ NFP_NET_CFG_TXR_STATS(j
);
399 data
[i
++] = readq(io_p
);
400 io_p
= nn
->dp
.ctrl_bar
+ NFP_NET_CFG_TXR_STATS(j
) + 8;
401 data
[i
++] = readq(io_p
);
403 for (j
= 0; j
< nn
->dp
.num_rx_rings
; j
++) {
404 io_p
= nn
->dp
.ctrl_bar
+ NFP_NET_CFG_RXR_STATS(j
);
405 data
[i
++] = readq(io_p
);
406 io_p
= nn
->dp
.ctrl_bar
+ NFP_NET_CFG_RXR_STATS(j
) + 8;
407 data
[i
++] = readq(io_p
);
411 static int nfp_net_get_sset_count(struct net_device
*netdev
, int sset
)
413 struct nfp_net
*nn
= netdev_priv(netdev
);
417 return NN_ET_STATS_LEN
;
423 /* RX network flow classification (RSS, filters, etc)
425 static u32
ethtool_flow_to_nfp_flag(u32 flow_type
)
427 static const u32 xlate_ethtool_to_nfp
[IPV6_FLOW
+ 1] = {
428 [TCP_V4_FLOW
] = NFP_NET_CFG_RSS_IPV4_TCP
,
429 [TCP_V6_FLOW
] = NFP_NET_CFG_RSS_IPV6_TCP
,
430 [UDP_V4_FLOW
] = NFP_NET_CFG_RSS_IPV4_UDP
,
431 [UDP_V6_FLOW
] = NFP_NET_CFG_RSS_IPV6_UDP
,
432 [IPV4_FLOW
] = NFP_NET_CFG_RSS_IPV4
,
433 [IPV6_FLOW
] = NFP_NET_CFG_RSS_IPV6
,
436 if (flow_type
>= ARRAY_SIZE(xlate_ethtool_to_nfp
))
439 return xlate_ethtool_to_nfp
[flow_type
];
442 static int nfp_net_get_rss_hash_opts(struct nfp_net
*nn
,
443 struct ethtool_rxnfc
*cmd
)
449 if (!(nn
->cap
& NFP_NET_CFG_CTRL_RSS
))
452 nfp_rss_flag
= ethtool_flow_to_nfp_flag(cmd
->flow_type
);
456 cmd
->data
|= RXH_IP_SRC
| RXH_IP_DST
;
457 if (nn
->rss_cfg
& nfp_rss_flag
)
458 cmd
->data
|= RXH_L4_B_0_1
| RXH_L4_B_2_3
;
463 static int nfp_net_get_rxnfc(struct net_device
*netdev
,
464 struct ethtool_rxnfc
*cmd
, u32
*rule_locs
)
466 struct nfp_net
*nn
= netdev_priv(netdev
);
469 case ETHTOOL_GRXRINGS
:
470 cmd
->data
= nn
->dp
.num_rx_rings
;
473 return nfp_net_get_rss_hash_opts(nn
, cmd
);
479 static int nfp_net_set_rss_hash_opt(struct nfp_net
*nn
,
480 struct ethtool_rxnfc
*nfc
)
482 u32 new_rss_cfg
= nn
->rss_cfg
;
486 if (!(nn
->cap
& NFP_NET_CFG_CTRL_RSS
))
489 /* RSS only supports IP SA/DA and L4 src/dst ports */
490 if (nfc
->data
& ~(RXH_IP_SRC
| RXH_IP_DST
|
491 RXH_L4_B_0_1
| RXH_L4_B_2_3
))
494 /* We need at least the IP SA/DA fields for hashing */
495 if (!(nfc
->data
& RXH_IP_SRC
) ||
496 !(nfc
->data
& RXH_IP_DST
))
499 nfp_rss_flag
= ethtool_flow_to_nfp_flag(nfc
->flow_type
);
503 switch (nfc
->data
& (RXH_L4_B_0_1
| RXH_L4_B_2_3
)) {
505 new_rss_cfg
&= ~nfp_rss_flag
;
507 case (RXH_L4_B_0_1
| RXH_L4_B_2_3
):
508 new_rss_cfg
|= nfp_rss_flag
;
514 new_rss_cfg
|= FIELD_PREP(NFP_NET_CFG_RSS_HFUNC
, nn
->rss_hfunc
);
515 new_rss_cfg
|= NFP_NET_CFG_RSS_MASK
;
517 if (new_rss_cfg
== nn
->rss_cfg
)
520 writel(new_rss_cfg
, nn
->dp
.ctrl_bar
+ NFP_NET_CFG_RSS_CTRL
);
521 err
= nfp_net_reconfig(nn
, NFP_NET_CFG_UPDATE_RSS
);
525 nn
->rss_cfg
= new_rss_cfg
;
527 nn_dbg(nn
, "Changed RSS config to 0x%x\n", nn
->rss_cfg
);
531 static int nfp_net_set_rxnfc(struct net_device
*netdev
,
532 struct ethtool_rxnfc
*cmd
)
534 struct nfp_net
*nn
= netdev_priv(netdev
);
538 return nfp_net_set_rss_hash_opt(nn
, cmd
);
544 static u32
nfp_net_get_rxfh_indir_size(struct net_device
*netdev
)
546 struct nfp_net
*nn
= netdev_priv(netdev
);
548 if (!(nn
->cap
& NFP_NET_CFG_CTRL_RSS
))
551 return ARRAY_SIZE(nn
->rss_itbl
);
554 static u32
nfp_net_get_rxfh_key_size(struct net_device
*netdev
)
556 struct nfp_net
*nn
= netdev_priv(netdev
);
558 if (!(nn
->cap
& NFP_NET_CFG_CTRL_RSS
))
561 return nfp_net_rss_key_sz(nn
);
564 static int nfp_net_get_rxfh(struct net_device
*netdev
, u32
*indir
, u8
*key
,
567 struct nfp_net
*nn
= netdev_priv(netdev
);
570 if (!(nn
->cap
& NFP_NET_CFG_CTRL_RSS
))
574 for (i
= 0; i
< ARRAY_SIZE(nn
->rss_itbl
); i
++)
575 indir
[i
] = nn
->rss_itbl
[i
];
577 memcpy(key
, nn
->rss_key
, nfp_net_rss_key_sz(nn
));
579 *hfunc
= nn
->rss_hfunc
;
580 if (*hfunc
>= 1 << ETH_RSS_HASH_FUNCS_COUNT
)
581 *hfunc
= ETH_RSS_HASH_UNKNOWN
;
587 static int nfp_net_set_rxfh(struct net_device
*netdev
,
588 const u32
*indir
, const u8
*key
,
591 struct nfp_net
*nn
= netdev_priv(netdev
);
594 if (!(nn
->cap
& NFP_NET_CFG_CTRL_RSS
) ||
595 !(hfunc
== ETH_RSS_HASH_NO_CHANGE
|| hfunc
== nn
->rss_hfunc
))
602 memcpy(nn
->rss_key
, key
, nfp_net_rss_key_sz(nn
));
603 nfp_net_rss_write_key(nn
);
606 for (i
= 0; i
< ARRAY_SIZE(nn
->rss_itbl
); i
++)
607 nn
->rss_itbl
[i
] = indir
[i
];
609 nfp_net_rss_write_itbl(nn
);
612 return nfp_net_reconfig(nn
, NFP_NET_CFG_UPDATE_RSS
);
615 /* Dump BAR registers
617 static int nfp_net_get_regs_len(struct net_device
*netdev
)
619 return NFP_NET_CFG_BAR_SZ
;
622 static void nfp_net_get_regs(struct net_device
*netdev
,
623 struct ethtool_regs
*regs
, void *p
)
625 struct nfp_net
*nn
= netdev_priv(netdev
);
629 regs
->version
= nn_readl(nn
, NFP_NET_CFG_VERSION
);
631 for (i
= 0; i
< NFP_NET_CFG_BAR_SZ
/ sizeof(u32
); i
++)
632 regs_buf
[i
] = readl(nn
->dp
.ctrl_bar
+ (i
* sizeof(u32
)));
635 static int nfp_net_get_coalesce(struct net_device
*netdev
,
636 struct ethtool_coalesce
*ec
)
638 struct nfp_net
*nn
= netdev_priv(netdev
);
640 if (!(nn
->cap
& NFP_NET_CFG_CTRL_IRQMOD
))
643 ec
->rx_coalesce_usecs
= nn
->rx_coalesce_usecs
;
644 ec
->rx_max_coalesced_frames
= nn
->rx_coalesce_max_frames
;
645 ec
->tx_coalesce_usecs
= nn
->tx_coalesce_usecs
;
646 ec
->tx_max_coalesced_frames
= nn
->tx_coalesce_max_frames
;
654 nfp_dump_nsp_diag(struct nfp_net
*nn
, struct ethtool_dump
*dump
, void *buffer
)
656 struct nfp_resource
*res
;
663 dump
->flag
= NFP_DUMP_NSP_DIAG
;
665 res
= nfp_resource_acquire(nn
->cpp
, NFP_RESOURCE_NSP_DIAG
);
670 if (dump
->len
!= nfp_resource_size(res
)) {
675 ret
= nfp_cpp_read(nn
->cpp
, nfp_resource_cpp_id(res
),
676 nfp_resource_address(res
),
678 if (ret
!= dump
->len
)
679 ret
= ret
< 0 ? ret
: -EIO
;
683 dump
->len
= nfp_resource_size(res
);
687 nfp_resource_release(res
);
692 static int nfp_net_set_dump(struct net_device
*netdev
, struct ethtool_dump
*val
)
694 struct nfp_net
*nn
= netdev_priv(netdev
);
699 if (val
->flag
!= NFP_DUMP_NSP_DIAG
)
702 nn
->ethtool_dump_flag
= val
->flag
;
708 nfp_net_get_dump_flag(struct net_device
*netdev
, struct ethtool_dump
*dump
)
710 return nfp_dump_nsp_diag(netdev_priv(netdev
), dump
, NULL
);
714 nfp_net_get_dump_data(struct net_device
*netdev
, struct ethtool_dump
*dump
,
717 return nfp_dump_nsp_diag(netdev_priv(netdev
), dump
, buffer
);
720 static int nfp_net_set_coalesce(struct net_device
*netdev
,
721 struct ethtool_coalesce
*ec
)
723 struct nfp_net
*nn
= netdev_priv(netdev
);
726 if (ec
->rx_coalesce_usecs_irq
||
727 ec
->rx_max_coalesced_frames_irq
||
728 ec
->tx_coalesce_usecs_irq
||
729 ec
->tx_max_coalesced_frames_irq
||
730 ec
->stats_block_coalesce_usecs
||
731 ec
->use_adaptive_rx_coalesce
||
732 ec
->use_adaptive_tx_coalesce
||
734 ec
->rx_coalesce_usecs_low
||
735 ec
->rx_max_coalesced_frames_low
||
736 ec
->tx_coalesce_usecs_low
||
737 ec
->tx_max_coalesced_frames_low
||
739 ec
->rx_coalesce_usecs_high
||
740 ec
->rx_max_coalesced_frames_high
||
741 ec
->tx_coalesce_usecs_high
||
742 ec
->tx_max_coalesced_frames_high
||
743 ec
->rate_sample_interval
)
746 /* Compute factor used to convert coalesce '_usecs' parameters to
747 * ME timestamp ticks. There are 16 ME clock cycles for each timestamp
750 factor
= nn
->me_freq_mhz
/ 16;
752 /* Each pair of (usecs, max_frames) fields specifies that interrupts
753 * should be coalesced until
754 * (usecs > 0 && time_since_first_completion >= usecs) ||
755 * (max_frames > 0 && completed_frames >= max_frames)
757 * It is illegal to set both usecs and max_frames to zero as this would
758 * cause interrupts to never be generated. To disable coalescing, set
759 * usecs = 0 and max_frames = 1.
761 * Some implementations ignore the value of max_frames and use the
762 * condition time_since_first_completion >= usecs
765 if (!(nn
->cap
& NFP_NET_CFG_CTRL_IRQMOD
))
768 /* ensure valid configuration */
769 if (!ec
->rx_coalesce_usecs
&& !ec
->rx_max_coalesced_frames
)
772 if (!ec
->tx_coalesce_usecs
&& !ec
->tx_max_coalesced_frames
)
775 if (ec
->rx_coalesce_usecs
* factor
>= ((1 << 16) - 1))
778 if (ec
->tx_coalesce_usecs
* factor
>= ((1 << 16) - 1))
781 if (ec
->rx_max_coalesced_frames
>= ((1 << 16) - 1))
784 if (ec
->tx_max_coalesced_frames
>= ((1 << 16) - 1))
787 /* configuration is valid */
788 nn
->rx_coalesce_usecs
= ec
->rx_coalesce_usecs
;
789 nn
->rx_coalesce_max_frames
= ec
->rx_max_coalesced_frames
;
790 nn
->tx_coalesce_usecs
= ec
->tx_coalesce_usecs
;
791 nn
->tx_coalesce_max_frames
= ec
->tx_max_coalesced_frames
;
793 /* write configuration to device */
794 nfp_net_coalesce_write_cfg(nn
);
795 return nfp_net_reconfig(nn
, NFP_NET_CFG_UPDATE_IRQMOD
);
798 static void nfp_net_get_channels(struct net_device
*netdev
,
799 struct ethtool_channels
*channel
)
801 struct nfp_net
*nn
= netdev_priv(netdev
);
802 unsigned int num_tx_rings
;
804 num_tx_rings
= nn
->dp
.num_tx_rings
;
806 num_tx_rings
-= nn
->dp
.num_rx_rings
;
808 channel
->max_rx
= min(nn
->max_rx_rings
, nn
->max_r_vecs
);
809 channel
->max_tx
= min(nn
->max_tx_rings
, nn
->max_r_vecs
);
810 channel
->max_combined
= min(channel
->max_rx
, channel
->max_tx
);
811 channel
->max_other
= NFP_NET_NON_Q_VECTORS
;
812 channel
->combined_count
= min(nn
->dp
.num_rx_rings
, num_tx_rings
);
813 channel
->rx_count
= nn
->dp
.num_rx_rings
- channel
->combined_count
;
814 channel
->tx_count
= num_tx_rings
- channel
->combined_count
;
815 channel
->other_count
= NFP_NET_NON_Q_VECTORS
;
818 static int nfp_net_set_num_rings(struct nfp_net
*nn
, unsigned int total_rx
,
819 unsigned int total_tx
)
821 struct nfp_net_dp
*dp
;
823 dp
= nfp_net_clone_dp(nn
);
827 dp
->num_rx_rings
= total_rx
;
828 dp
->num_tx_rings
= total_tx
;
829 /* nfp_net_check_config() will catch num_tx_rings > nn->max_tx_rings */
831 dp
->num_tx_rings
+= total_rx
;
833 return nfp_net_ring_reconfig(nn
, dp
);
836 static int nfp_net_set_channels(struct net_device
*netdev
,
837 struct ethtool_channels
*channel
)
839 struct nfp_net
*nn
= netdev_priv(netdev
);
840 unsigned int total_rx
, total_tx
;
842 /* Reject unsupported */
843 if (!channel
->combined_count
||
844 channel
->other_count
!= NFP_NET_NON_Q_VECTORS
||
845 (channel
->rx_count
&& channel
->tx_count
))
848 total_rx
= channel
->combined_count
+ channel
->rx_count
;
849 total_tx
= channel
->combined_count
+ channel
->tx_count
;
851 if (total_rx
> min(nn
->max_rx_rings
, nn
->max_r_vecs
) ||
852 total_tx
> min(nn
->max_tx_rings
, nn
->max_r_vecs
))
855 return nfp_net_set_num_rings(nn
, total_rx
, total_tx
);
858 static const struct ethtool_ops nfp_net_ethtool_ops
= {
859 .get_drvinfo
= nfp_net_get_drvinfo
,
860 .get_link
= ethtool_op_get_link
,
861 .get_ringparam
= nfp_net_get_ringparam
,
862 .set_ringparam
= nfp_net_set_ringparam
,
863 .get_strings
= nfp_net_get_strings
,
864 .get_ethtool_stats
= nfp_net_get_stats
,
865 .get_sset_count
= nfp_net_get_sset_count
,
866 .get_rxnfc
= nfp_net_get_rxnfc
,
867 .set_rxnfc
= nfp_net_set_rxnfc
,
868 .get_rxfh_indir_size
= nfp_net_get_rxfh_indir_size
,
869 .get_rxfh_key_size
= nfp_net_get_rxfh_key_size
,
870 .get_rxfh
= nfp_net_get_rxfh
,
871 .set_rxfh
= nfp_net_set_rxfh
,
872 .get_regs_len
= nfp_net_get_regs_len
,
873 .get_regs
= nfp_net_get_regs
,
874 .set_dump
= nfp_net_set_dump
,
875 .get_dump_flag
= nfp_net_get_dump_flag
,
876 .get_dump_data
= nfp_net_get_dump_data
,
877 .get_coalesce
= nfp_net_get_coalesce
,
878 .set_coalesce
= nfp_net_set_coalesce
,
879 .get_channels
= nfp_net_get_channels
,
880 .set_channels
= nfp_net_set_channels
,
881 .get_link_ksettings
= nfp_net_get_link_ksettings
,
884 void nfp_net_set_ethtool_ops(struct net_device
*netdev
)
886 netdev
->ethtool_ops
= &nfp_net_ethtool_ops
;