xref: /dpdk/drivers/net/nfp/nfp_net_common.c (revision 72d1dea62c2c99cfcf524f4ddf57a7e5c27a1a1e)
111e9eae4SChaoyong He /* SPDX-License-Identifier: BSD-3-Clause
211e9eae4SChaoyong He  * Copyright (c) 2014-2018 Netronome Systems, Inc.
311e9eae4SChaoyong He  * All rights reserved.
411e9eae4SChaoyong He  *
511e9eae4SChaoyong He  * Small portions derived from code Copyright(c) 2010-2015 Intel Corporation.
611e9eae4SChaoyong He  */
711e9eae4SChaoyong He 
811e9eae4SChaoyong He #include "nfp_net_common.h"
911e9eae4SChaoyong He 
1011e9eae4SChaoyong He #include <rte_alarm.h>
1111e9eae4SChaoyong He 
1211e9eae4SChaoyong He #include "flower/nfp_flower_representor.h"
1311e9eae4SChaoyong He #include "nfd3/nfp_nfd3.h"
1411e9eae4SChaoyong He #include "nfdk/nfp_nfdk.h"
1511e9eae4SChaoyong He #include "nfpcore/nfp_mip.h"
1611e9eae4SChaoyong He #include "nfpcore/nfp_nsp.h"
1711e9eae4SChaoyong He #include "nfp_logs.h"
1811e9eae4SChaoyong He 
1911e9eae4SChaoyong He #define NFP_TX_MAX_SEG       UINT8_MAX
2011e9eae4SChaoyong He #define NFP_TX_MAX_MTU_SEG   8
2111e9eae4SChaoyong He 
2211e9eae4SChaoyong He /*
2311e9eae4SChaoyong He  * This is used by the reconfig protocol. It sets the maximum time waiting in
2411e9eae4SChaoyong He  * milliseconds before a reconfig timeout happens.
2511e9eae4SChaoyong He  */
2611e9eae4SChaoyong He #define NFP_NET_POLL_TIMEOUT    5000
2711e9eae4SChaoyong He 
2811e9eae4SChaoyong He #define NFP_NET_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */
2911e9eae4SChaoyong He #define NFP_NET_LINK_UP_CHECK_TIMEOUT   1000 /* ms */
3011e9eae4SChaoyong He 
3111e9eae4SChaoyong He /* Maximum supported NFP frame size (MTU + layer 2 headers) */
3211e9eae4SChaoyong He #define NFP_FRAME_SIZE_MAX        10048
3311e9eae4SChaoyong He #define DEFAULT_FLBUF_SIZE        9216
3411e9eae4SChaoyong He 
3511e9eae4SChaoyong He enum nfp_xstat_group {
3611e9eae4SChaoyong He 	NFP_XSTAT_GROUP_NET,
3711e9eae4SChaoyong He 	NFP_XSTAT_GROUP_MAC
3811e9eae4SChaoyong He };
3911e9eae4SChaoyong He 
4011e9eae4SChaoyong He struct nfp_xstat {
4111e9eae4SChaoyong He 	char name[RTE_ETH_XSTATS_NAME_SIZE];
4211e9eae4SChaoyong He 	int offset;
4311e9eae4SChaoyong He 	enum nfp_xstat_group group;
4411e9eae4SChaoyong He };
4511e9eae4SChaoyong He 
4611e9eae4SChaoyong He #define NFP_XSTAT_NET(_name, _offset) {                 \
4711e9eae4SChaoyong He 	.name = _name,                                  \
4811e9eae4SChaoyong He 	.offset = NFP_NET_CFG_STATS_##_offset,          \
4911e9eae4SChaoyong He 	.group = NFP_XSTAT_GROUP_NET,                   \
5011e9eae4SChaoyong He }
5111e9eae4SChaoyong He 
5211e9eae4SChaoyong He #define NFP_XSTAT_MAC(_name, _offset) {                 \
5311e9eae4SChaoyong He 	.name = _name,                                  \
5411e9eae4SChaoyong He 	.offset = NFP_MAC_STATS_##_offset,              \
5511e9eae4SChaoyong He 	.group = NFP_XSTAT_GROUP_MAC,                   \
5611e9eae4SChaoyong He }
5711e9eae4SChaoyong He 
5811e9eae4SChaoyong He static const struct nfp_xstat nfp_net_xstats[] = {
5911e9eae4SChaoyong He 	/*
6011e9eae4SChaoyong He 	 * Basic xstats available on both VF and PF.
6111e9eae4SChaoyong He 	 * Note that in case new statistics of group NFP_XSTAT_GROUP_NET
6211e9eae4SChaoyong He 	 * are added to this array, they must appear before any statistics
6311e9eae4SChaoyong He 	 * of group NFP_XSTAT_GROUP_MAC.
6411e9eae4SChaoyong He 	 */
6511e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_packets_mc", RX_MC_FRAMES),
6611e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_packets_mc", TX_MC_FRAMES),
6711e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_packets_bc", RX_BC_FRAMES),
6811e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_packets_bc", TX_BC_FRAMES),
6911e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_uc", RX_UC_OCTETS),
7011e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_uc", TX_UC_OCTETS),
7111e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_mc", RX_MC_OCTETS),
7211e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_mc", TX_MC_OCTETS),
7311e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_bc", RX_BC_OCTETS),
7411e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_bc", TX_BC_OCTETS),
7511e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_missed_erros", TX_DISCARDS),
7611e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_pass_pkts", APP0_FRAMES),
7711e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_pass_bytes", APP0_BYTES),
7811e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app1_pkts", APP1_FRAMES),
7911e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app1_bytes", APP1_BYTES),
8011e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app2_pkts", APP2_FRAMES),
8111e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app2_bytes", APP2_BYTES),
8211e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app3_pkts", APP3_FRAMES),
8311e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app3_bytes", APP3_BYTES),
8411e9eae4SChaoyong He 	/*
8511e9eae4SChaoyong He 	 * MAC xstats available only on PF. These statistics are not available for VFs as the
8611e9eae4SChaoyong He 	 * PF is not initialized when the VF is initialized as it is still bound to the kernel
8711e9eae4SChaoyong He 	 * driver. As such, the PMD cannot obtain a CPP handle and access the rtsym_table in order
8811e9eae4SChaoyong He 	 * to get the pointer to the start of the MAC statistics counters.
8911e9eae4SChaoyong He 	 */
9011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_octets", RX_IN_OCTS),
9111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frame_too_long_errors", RX_FRAME_TOO_LONG_ERRORS),
9211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_range_length_errors", RX_RANGE_LENGTH_ERRORS),
9311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_vlan_received_ok", RX_VLAN_RECEIVED_OK),
9411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_errors", RX_IN_ERRORS),
9511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_broadcast_pkts", RX_IN_BROADCAST_PKTS),
9611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_drop_events", RX_DROP_EVENTS),
9711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_alignment_errors", RX_ALIGNMENT_ERRORS),
9811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_mac_ctrl_frames", RX_PAUSE_MAC_CTRL_FRAMES),
9911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frames_received_ok", RX_FRAMES_RECEIVED_OK),
10011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frame_check_sequence_errors", RX_FRAME_CHECK_SEQ_ERRORS),
10111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_unicast_pkts", RX_UNICAST_PKTS),
10211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_multicast_pkts", RX_MULTICAST_PKTS),
10311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts", RX_PKTS),
10411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_undersize_pkts", RX_UNDERSIZE_PKTS),
10511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_64_octets", RX_PKTS_64_OCTS),
10611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_65_to_127_octets", RX_PKTS_65_TO_127_OCTS),
10711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_128_to_255_octets", RX_PKTS_128_TO_255_OCTS),
10811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_256_to_511_octets", RX_PKTS_256_TO_511_OCTS),
10911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_512_to_1023_octets", RX_PKTS_512_TO_1023_OCTS),
11011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_1024_to_1518_octets", RX_PKTS_1024_TO_1518_OCTS),
11111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_1519_to_max_octets", RX_PKTS_1519_TO_MAX_OCTS),
11211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_jabbers", RX_JABBERS),
11311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_fragments", RX_FRAGMENTS),
11411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_oversize_pkts", RX_OVERSIZE_PKTS),
11511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class0", RX_PAUSE_FRAMES_CLASS0),
11611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class1", RX_PAUSE_FRAMES_CLASS1),
11711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class2", RX_PAUSE_FRAMES_CLASS2),
11811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class3", RX_PAUSE_FRAMES_CLASS3),
11911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class4", RX_PAUSE_FRAMES_CLASS4),
12011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class5", RX_PAUSE_FRAMES_CLASS5),
12111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class6", RX_PAUSE_FRAMES_CLASS6),
12211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class7", RX_PAUSE_FRAMES_CLASS7),
12311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_mac_ctrl_frames_received", RX_MAC_CTRL_FRAMES_REC),
12411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_mac_head_drop", RX_MAC_HEAD_DROP),
12511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_queue_drop", TX_QUEUE_DROP),
12611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_octets", TX_OUT_OCTS),
12711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_vlan_transmitted_ok", TX_VLAN_TRANSMITTED_OK),
12811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_errors", TX_OUT_ERRORS),
12911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_broadcast_pkts", TX_BROADCAST_PKTS),
13011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_mac_ctrl_frames", TX_PAUSE_MAC_CTRL_FRAMES),
13111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_frames_transmitted_ok", TX_FRAMES_TRANSMITTED_OK),
13211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_unicast_pkts", TX_UNICAST_PKTS),
13311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_multicast_pkts", TX_MULTICAST_PKTS),
13411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_64_octets", TX_PKTS_64_OCTS),
13511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_65_to_127_octets", TX_PKTS_65_TO_127_OCTS),
13611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_128_to_255_octets", TX_PKTS_128_TO_255_OCTS),
13711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_256_to_511_octets", TX_PKTS_256_TO_511_OCTS),
13811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_512_to_1023_octets", TX_PKTS_512_TO_1023_OCTS),
13911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_1024_to_1518_octets", TX_PKTS_1024_TO_1518_OCTS),
14011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_1519_to_max_octets", TX_PKTS_1519_TO_MAX_OCTS),
14111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class0", TX_PAUSE_FRAMES_CLASS0),
14211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class1", TX_PAUSE_FRAMES_CLASS1),
14311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class2", TX_PAUSE_FRAMES_CLASS2),
14411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class3", TX_PAUSE_FRAMES_CLASS3),
14511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class4", TX_PAUSE_FRAMES_CLASS4),
14611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class5", TX_PAUSE_FRAMES_CLASS5),
14711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class6", TX_PAUSE_FRAMES_CLASS6),
14811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class7", TX_PAUSE_FRAMES_CLASS7),
14911e9eae4SChaoyong He };
15011e9eae4SChaoyong He 
15111e9eae4SChaoyong He static const uint32_t nfp_net_link_speed_nfp2rte[] = {
15211e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = RTE_ETH_SPEED_NUM_NONE,
15311e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = RTE_ETH_SPEED_NUM_NONE,
15411e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_1G]          = RTE_ETH_SPEED_NUM_1G,
15511e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_10G]         = RTE_ETH_SPEED_NUM_10G,
15611e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_25G]         = RTE_ETH_SPEED_NUM_25G,
15711e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_40G]         = RTE_ETH_SPEED_NUM_40G,
15811e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_50G]         = RTE_ETH_SPEED_NUM_50G,
15911e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_100G]        = RTE_ETH_SPEED_NUM_100G,
16011e9eae4SChaoyong He };
16111e9eae4SChaoyong He 
16211e9eae4SChaoyong He static uint16_t
16311e9eae4SChaoyong He nfp_net_link_speed_rte2nfp(uint16_t speed)
16411e9eae4SChaoyong He {
16511e9eae4SChaoyong He 	uint16_t i;
16611e9eae4SChaoyong He 
16711e9eae4SChaoyong He 	for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) {
16811e9eae4SChaoyong He 		if (speed == nfp_net_link_speed_nfp2rte[i])
16911e9eae4SChaoyong He 			return i;
17011e9eae4SChaoyong He 	}
17111e9eae4SChaoyong He 
17211e9eae4SChaoyong He 	return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;
17311e9eae4SChaoyong He }
17411e9eae4SChaoyong He 
17511e9eae4SChaoyong He static void
17611e9eae4SChaoyong He nfp_net_notify_port_speed(struct nfp_net_hw *hw,
17711e9eae4SChaoyong He 		struct rte_eth_link *link)
17811e9eae4SChaoyong He {
17911e9eae4SChaoyong He 	/*
18011e9eae4SChaoyong He 	 * Read the link status from NFP_NET_CFG_STS. If the link is down
18111e9eae4SChaoyong He 	 * then write the link speed NFP_NET_CFG_STS_LINK_RATE_UNKNOWN to
18211e9eae4SChaoyong He 	 * NFP_NET_CFG_STS_NSP_LINK_RATE.
18311e9eae4SChaoyong He 	 */
18411e9eae4SChaoyong He 	if (link->link_status == RTE_ETH_LINK_DOWN) {
185f58bde00SChaoyong He 		nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE,
186f58bde00SChaoyong He 				NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);
18711e9eae4SChaoyong He 		return;
18811e9eae4SChaoyong He 	}
18911e9eae4SChaoyong He 
19011e9eae4SChaoyong He 	/*
19111e9eae4SChaoyong He 	 * Link is up so write the link speed from the eth_table to
19211e9eae4SChaoyong He 	 * NFP_NET_CFG_STS_NSP_LINK_RATE.
19311e9eae4SChaoyong He 	 */
194f58bde00SChaoyong He 	nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE,
19511e9eae4SChaoyong He 			nfp_net_link_speed_rte2nfp(link->link_speed));
19611e9eae4SChaoyong He }
19711e9eae4SChaoyong He 
19811e9eae4SChaoyong He /* The length of firmware version string */
19911e9eae4SChaoyong He #define FW_VER_LEN        32
20011e9eae4SChaoyong He 
20111e9eae4SChaoyong He static int
202*72d1dea6SChaoyong He nfp_reconfig_real(struct nfp_hw *hw,
20311e9eae4SChaoyong He 		uint32_t update)
20411e9eae4SChaoyong He {
20511e9eae4SChaoyong He 	uint32_t cnt;
20611e9eae4SChaoyong He 	uint32_t new;
20711e9eae4SChaoyong He 	struct timespec wait;
20811e9eae4SChaoyong He 
20911e9eae4SChaoyong He 	PMD_DRV_LOG(DEBUG, "Writing to the configuration queue (%p)...",
210*72d1dea6SChaoyong He 			hw->qcp_cfg);
21111e9eae4SChaoyong He 
212*72d1dea6SChaoyong He 	if (hw->qcp_cfg == NULL) {
21311e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Bad configuration queue pointer");
21411e9eae4SChaoyong He 		return -ENXIO;
21511e9eae4SChaoyong He 	}
21611e9eae4SChaoyong He 
217*72d1dea6SChaoyong He 	nfp_qcp_ptr_add(hw->qcp_cfg, NFP_QCP_WRITE_PTR, 1);
21811e9eae4SChaoyong He 
21911e9eae4SChaoyong He 	wait.tv_sec = 0;
22011e9eae4SChaoyong He 	wait.tv_nsec = 1000000; /* 1ms */
22111e9eae4SChaoyong He 
22211e9eae4SChaoyong He 	PMD_DRV_LOG(DEBUG, "Polling for update ack...");
22311e9eae4SChaoyong He 
22411e9eae4SChaoyong He 	/* Poll update field, waiting for NFP to ack the config */
22511e9eae4SChaoyong He 	for (cnt = 0; ; cnt++) {
226*72d1dea6SChaoyong He 		new = nn_cfg_readl(hw, NFP_NET_CFG_UPDATE);
22711e9eae4SChaoyong He 		if (new == 0)
22811e9eae4SChaoyong He 			break;
22911e9eae4SChaoyong He 
23011e9eae4SChaoyong He 		if ((new & NFP_NET_CFG_UPDATE_ERR) != 0) {
23111e9eae4SChaoyong He 			PMD_DRV_LOG(ERR, "Reconfig error: %#08x", new);
23211e9eae4SChaoyong He 			return -1;
23311e9eae4SChaoyong He 		}
23411e9eae4SChaoyong He 
23511e9eae4SChaoyong He 		if (cnt >= NFP_NET_POLL_TIMEOUT) {
23611e9eae4SChaoyong He 			PMD_DRV_LOG(ERR, "Reconfig timeout for %#08x after %u ms",
23711e9eae4SChaoyong He 					update, cnt);
23811e9eae4SChaoyong He 			return -EIO;
23911e9eae4SChaoyong He 		}
24011e9eae4SChaoyong He 
24111e9eae4SChaoyong He 		nanosleep(&wait, 0); /* Waiting for a 1ms */
24211e9eae4SChaoyong He 	}
24311e9eae4SChaoyong He 
24411e9eae4SChaoyong He 	PMD_DRV_LOG(DEBUG, "Ack DONE");
24511e9eae4SChaoyong He 	return 0;
24611e9eae4SChaoyong He }
24711e9eae4SChaoyong He 
24811e9eae4SChaoyong He /**
24911e9eae4SChaoyong He  * Reconfigure the NIC.
25011e9eae4SChaoyong He  *
25111e9eae4SChaoyong He  * Write the update word to the BAR and ping the reconfig queue. Then poll
25211e9eae4SChaoyong He  * until the firmware has acknowledged the update by zeroing the update word.
25311e9eae4SChaoyong He  *
25411e9eae4SChaoyong He  * @param hw
25511e9eae4SChaoyong He  *   Device to reconfigure.
25611e9eae4SChaoyong He  * @param ctrl
25711e9eae4SChaoyong He  *   The value for the ctrl field in the BAR config.
25811e9eae4SChaoyong He  * @param update
25911e9eae4SChaoyong He  *   The value for the update field in the BAR config.
26011e9eae4SChaoyong He  *
26111e9eae4SChaoyong He  * @return
26211e9eae4SChaoyong He  *   - (0) if OK to reconfigure the device.
26311e9eae4SChaoyong He  *   - (-EIO) if I/O err and fail to reconfigure the device.
26411e9eae4SChaoyong He  */
26511e9eae4SChaoyong He int
266*72d1dea6SChaoyong He nfp_reconfig(struct nfp_hw *hw,
26711e9eae4SChaoyong He 		uint32_t ctrl,
26811e9eae4SChaoyong He 		uint32_t update)
26911e9eae4SChaoyong He {
27011e9eae4SChaoyong He 	int ret;
27111e9eae4SChaoyong He 
27211e9eae4SChaoyong He 	rte_spinlock_lock(&hw->reconfig_lock);
27311e9eae4SChaoyong He 
274*72d1dea6SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_CTRL, ctrl);
275*72d1dea6SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update);
27611e9eae4SChaoyong He 
27711e9eae4SChaoyong He 	rte_wmb();
27811e9eae4SChaoyong He 
279*72d1dea6SChaoyong He 	ret = nfp_reconfig_real(hw, update);
28011e9eae4SChaoyong He 
28111e9eae4SChaoyong He 	rte_spinlock_unlock(&hw->reconfig_lock);
28211e9eae4SChaoyong He 
28311e9eae4SChaoyong He 	if (ret != 0) {
284*72d1dea6SChaoyong He 		PMD_DRV_LOG(ERR, "Error nfp reconfig: ctrl=%#08x update=%#08x",
28511e9eae4SChaoyong He 				ctrl, update);
28611e9eae4SChaoyong He 		return -EIO;
28711e9eae4SChaoyong He 	}
28811e9eae4SChaoyong He 
28911e9eae4SChaoyong He 	return 0;
29011e9eae4SChaoyong He }
29111e9eae4SChaoyong He 
29211e9eae4SChaoyong He /**
29311e9eae4SChaoyong He  * Reconfigure the NIC for the extend ctrl BAR.
29411e9eae4SChaoyong He  *
29511e9eae4SChaoyong He  * Write the update word to the BAR and ping the reconfig queue. Then poll
29611e9eae4SChaoyong He  * until the firmware has acknowledged the update by zeroing the update word.
29711e9eae4SChaoyong He  *
29811e9eae4SChaoyong He  * @param hw
29911e9eae4SChaoyong He  *   Device to reconfigure.
30011e9eae4SChaoyong He  * @param ctrl_ext
30111e9eae4SChaoyong He  *   The value for the first word of extend ctrl field in the BAR config.
30211e9eae4SChaoyong He  * @param update
30311e9eae4SChaoyong He  *   The value for the update field in the BAR config.
30411e9eae4SChaoyong He  *
30511e9eae4SChaoyong He  * @return
30611e9eae4SChaoyong He  *   - (0) if OK to reconfigure the device.
30711e9eae4SChaoyong He  *   - (-EIO) if I/O err and fail to reconfigure the device.
30811e9eae4SChaoyong He  */
30911e9eae4SChaoyong He int
310*72d1dea6SChaoyong He nfp_ext_reconfig(struct nfp_hw *hw,
31111e9eae4SChaoyong He 		uint32_t ctrl_ext,
31211e9eae4SChaoyong He 		uint32_t update)
31311e9eae4SChaoyong He {
31411e9eae4SChaoyong He 	int ret;
31511e9eae4SChaoyong He 
31611e9eae4SChaoyong He 	rte_spinlock_lock(&hw->reconfig_lock);
31711e9eae4SChaoyong He 
318*72d1dea6SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_CTRL_WORD1, ctrl_ext);
319*72d1dea6SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, update);
32011e9eae4SChaoyong He 
32111e9eae4SChaoyong He 	rte_wmb();
32211e9eae4SChaoyong He 
323*72d1dea6SChaoyong He 	ret = nfp_reconfig_real(hw, update);
32411e9eae4SChaoyong He 
32511e9eae4SChaoyong He 	rte_spinlock_unlock(&hw->reconfig_lock);
32611e9eae4SChaoyong He 
32711e9eae4SChaoyong He 	if (ret != 0) {
328*72d1dea6SChaoyong He 		PMD_DRV_LOG(ERR, "Error nfp ext reconfig: ctrl_ext=%#08x update=%#08x",
32911e9eae4SChaoyong He 				ctrl_ext, update);
33011e9eae4SChaoyong He 		return -EIO;
33111e9eae4SChaoyong He 	}
33211e9eae4SChaoyong He 
33311e9eae4SChaoyong He 	return 0;
33411e9eae4SChaoyong He }
33511e9eae4SChaoyong He 
33611e9eae4SChaoyong He /**
33711e9eae4SChaoyong He  * Reconfigure the firmware via the mailbox
33811e9eae4SChaoyong He  *
33911e9eae4SChaoyong He  * @param hw
34011e9eae4SChaoyong He  *   Device to reconfigure
34111e9eae4SChaoyong He  * @param mbox_cmd
34211e9eae4SChaoyong He  *   The value for the mailbox command
34311e9eae4SChaoyong He  *
34411e9eae4SChaoyong He  * @return
34511e9eae4SChaoyong He  *   - (0) if OK to reconfigure by the mailbox.
34611e9eae4SChaoyong He  *   - (-EIO) if I/O err and fail to reconfigure by the mailbox
34711e9eae4SChaoyong He  */
34811e9eae4SChaoyong He int
34911e9eae4SChaoyong He nfp_net_mbox_reconfig(struct nfp_net_hw *hw,
35011e9eae4SChaoyong He 		uint32_t mbox_cmd)
35111e9eae4SChaoyong He {
35211e9eae4SChaoyong He 	int ret;
35311e9eae4SChaoyong He 	uint32_t mbox;
35411e9eae4SChaoyong He 
35511e9eae4SChaoyong He 	mbox = hw->tlv_caps.mbox_off;
35611e9eae4SChaoyong He 
357*72d1dea6SChaoyong He 	rte_spinlock_lock(&hw->super.reconfig_lock);
35811e9eae4SChaoyong He 
359f58bde00SChaoyong He 	nn_cfg_writeq(&hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd);
360f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX);
36111e9eae4SChaoyong He 
36211e9eae4SChaoyong He 	rte_wmb();
36311e9eae4SChaoyong He 
364*72d1dea6SChaoyong He 	ret = nfp_reconfig_real(&hw->super, NFP_NET_CFG_UPDATE_MBOX);
36511e9eae4SChaoyong He 
366*72d1dea6SChaoyong He 	rte_spinlock_unlock(&hw->super.reconfig_lock);
36711e9eae4SChaoyong He 
36811e9eae4SChaoyong He 	if (ret != 0) {
36911e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x",
37011e9eae4SChaoyong He 				mbox_cmd, NFP_NET_CFG_UPDATE_MBOX);
37111e9eae4SChaoyong He 		return -EIO;
37211e9eae4SChaoyong He 	}
37311e9eae4SChaoyong He 
374f58bde00SChaoyong He 	return nn_cfg_readl(&hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET);
37511e9eae4SChaoyong He }
37611e9eae4SChaoyong He 
37711e9eae4SChaoyong He /*
37811e9eae4SChaoyong He  * Configure an Ethernet device.
37911e9eae4SChaoyong He  *
38011e9eae4SChaoyong He  * This function must be invoked first before any other function in the Ethernet API.
38111e9eae4SChaoyong He  * This function can also be re-invoked when a device is in the stopped state.
38211e9eae4SChaoyong He  *
38311e9eae4SChaoyong He  * A DPDK app sends info about how many queues to use and how  those queues
38411e9eae4SChaoyong He  * need to be configured. This is used by the DPDK core and it makes sure no
38511e9eae4SChaoyong He  * more queues than those advertised by the driver are requested.
38611e9eae4SChaoyong He  * This function is called after that internal process.
38711e9eae4SChaoyong He  */
38811e9eae4SChaoyong He int
38911e9eae4SChaoyong He nfp_net_configure(struct rte_eth_dev *dev)
39011e9eae4SChaoyong He {
39111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
39211e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
39311e9eae4SChaoyong He 	struct rte_eth_rxmode *rxmode;
39411e9eae4SChaoyong He 	struct rte_eth_txmode *txmode;
39511e9eae4SChaoyong He 
39611e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
39711e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
39811e9eae4SChaoyong He 	rxmode = &dev_conf->rxmode;
39911e9eae4SChaoyong He 	txmode = &dev_conf->txmode;
40011e9eae4SChaoyong He 
40111e9eae4SChaoyong He 	if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0)
40211e9eae4SChaoyong He 		rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
40311e9eae4SChaoyong He 
40411e9eae4SChaoyong He 	/* Checking TX mode */
40511e9eae4SChaoyong He 	if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
40611e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "TX mq_mode DCB and VMDq not supported");
40711e9eae4SChaoyong He 		return -EINVAL;
40811e9eae4SChaoyong He 	}
40911e9eae4SChaoyong He 
41011e9eae4SChaoyong He 	/* Checking RX mode */
41111e9eae4SChaoyong He 	if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 &&
41275a76c73SChaoyong He 			(hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) == 0) {
41311e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "RSS not supported");
41411e9eae4SChaoyong He 		return -EINVAL;
41511e9eae4SChaoyong He 	}
41611e9eae4SChaoyong He 
41711e9eae4SChaoyong He 	/* Checking MTU set */
41811e9eae4SChaoyong He 	if (rxmode->mtu > NFP_FRAME_SIZE_MAX) {
41911e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "MTU (%u) larger than NFP_FRAME_SIZE_MAX (%u)",
42011e9eae4SChaoyong He 				rxmode->mtu, NFP_FRAME_SIZE_MAX);
42111e9eae4SChaoyong He 		return -ERANGE;
42211e9eae4SChaoyong He 	}
42311e9eae4SChaoyong He 
42411e9eae4SChaoyong He 	return 0;
42511e9eae4SChaoyong He }
42611e9eae4SChaoyong He 
42711e9eae4SChaoyong He void
42811e9eae4SChaoyong He nfp_net_log_device_information(const struct nfp_net_hw *hw)
42911e9eae4SChaoyong He {
43075a76c73SChaoyong He 	uint32_t cap = hw->super.cap;
43175a76c73SChaoyong He 
43211e9eae4SChaoyong He 	PMD_INIT_LOG(INFO, "VER: %u.%u, Maximum supported MTU: %d",
43311e9eae4SChaoyong He 			hw->ver.major, hw->ver.minor, hw->max_mtu);
43411e9eae4SChaoyong He 
43575a76c73SChaoyong He 	PMD_INIT_LOG(INFO, "CAP: %#x, %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", cap,
43675a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_PROMISC   ? "PROMISC "   : "",
43775a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2BC      ? "L2BCFILT "  : "",
43875a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2MC      ? "L2MCFILT "  : "",
43975a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXCSUM    ? "RXCSUM "    : "",
44075a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXCSUM    ? "TXCSUM "    : "",
44175a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXVLAN    ? "RXVLAN "    : "",
44275a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXVLAN    ? "TXVLAN "    : "",
44375a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXVLAN_V2 ? "RXVLANv2 "  : "",
44475a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXVLAN_V2 ? "TXVLANv2 "  : "",
44575a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXQINQ    ? "RXQINQ "    : "",
44675a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_SCATTER   ? "SCATTER "   : "",
44775a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_GATHER    ? "GATHER "    : "",
44875a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_LIVE_ADDR ? "LIVE_ADDR " : "",
44975a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_LSO       ? "TSO "       : "",
45075a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_LSO2      ? "TSOv2 "     : "",
45175a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RSS       ? "RSS "       : "",
45275a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RSS2      ? "RSSv2 "     : "");
45311e9eae4SChaoyong He 
45411e9eae4SChaoyong He 	PMD_INIT_LOG(INFO, "max_rx_queues: %u, max_tx_queues: %u",
45511e9eae4SChaoyong He 			hw->max_rx_queues, hw->max_tx_queues);
45611e9eae4SChaoyong He }
45711e9eae4SChaoyong He 
45811e9eae4SChaoyong He static inline void
45911e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(struct nfp_net_hw *hw,
46011e9eae4SChaoyong He 		uint32_t *ctrl)
46111e9eae4SChaoyong He {
46275a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0)
46311e9eae4SChaoyong He 		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN_V2;
46475a76c73SChaoyong He 	else if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN) != 0)
46511e9eae4SChaoyong He 		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN;
46611e9eae4SChaoyong He }
46711e9eae4SChaoyong He 
46811e9eae4SChaoyong He void
46911e9eae4SChaoyong He nfp_net_enable_queues(struct rte_eth_dev *dev)
47011e9eae4SChaoyong He {
47111e9eae4SChaoyong He 	uint16_t i;
47211e9eae4SChaoyong He 	struct nfp_net_hw *hw;
47311e9eae4SChaoyong He 	uint64_t enabled_queues;
47411e9eae4SChaoyong He 
47511e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
47611e9eae4SChaoyong He 
47711e9eae4SChaoyong He 	/* Enabling the required TX queues in the device */
47811e9eae4SChaoyong He 	enabled_queues = 0;
47911e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++)
48011e9eae4SChaoyong He 		enabled_queues |= (1 << i);
48111e9eae4SChaoyong He 
482f58bde00SChaoyong He 	nn_cfg_writeq(&hw->super, NFP_NET_CFG_TXRS_ENABLE, enabled_queues);
48311e9eae4SChaoyong He 
48411e9eae4SChaoyong He 	/* Enabling the required RX queues in the device */
48511e9eae4SChaoyong He 	enabled_queues = 0;
48611e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++)
48711e9eae4SChaoyong He 		enabled_queues |= (1 << i);
48811e9eae4SChaoyong He 
489f58bde00SChaoyong He 	nn_cfg_writeq(&hw->super, NFP_NET_CFG_RXRS_ENABLE, enabled_queues);
49011e9eae4SChaoyong He }
49111e9eae4SChaoyong He 
49211e9eae4SChaoyong He void
49311e9eae4SChaoyong He nfp_net_disable_queues(struct rte_eth_dev *dev)
49411e9eae4SChaoyong He {
49511e9eae4SChaoyong He 	uint32_t update;
49611e9eae4SChaoyong He 	uint32_t new_ctrl;
497*72d1dea6SChaoyong He 	struct nfp_hw *hw;
498*72d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
49911e9eae4SChaoyong He 
500*72d1dea6SChaoyong He 	net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
501*72d1dea6SChaoyong He 	hw = &net_hw->super;
50211e9eae4SChaoyong He 
503*72d1dea6SChaoyong He 	nn_cfg_writeq(hw, NFP_NET_CFG_TXRS_ENABLE, 0);
504*72d1dea6SChaoyong He 	nn_cfg_writeq(hw, NFP_NET_CFG_RXRS_ENABLE, 0);
50511e9eae4SChaoyong He 
506*72d1dea6SChaoyong He 	new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_ENABLE;
50711e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN |
50811e9eae4SChaoyong He 			NFP_NET_CFG_UPDATE_RING |
50911e9eae4SChaoyong He 			NFP_NET_CFG_UPDATE_MSIX;
51011e9eae4SChaoyong He 
511*72d1dea6SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_RINGCFG) != 0)
51211e9eae4SChaoyong He 		new_ctrl &= ~NFP_NET_CFG_CTRL_RINGCFG;
51311e9eae4SChaoyong He 
51411e9eae4SChaoyong He 	/* If an error when reconfig we avoid to change hw state */
515*72d1dea6SChaoyong He 	if (nfp_reconfig(hw, new_ctrl, update) != 0)
51611e9eae4SChaoyong He 		return;
51711e9eae4SChaoyong He 
518*72d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
51911e9eae4SChaoyong He }
52011e9eae4SChaoyong He 
52111e9eae4SChaoyong He void
52211e9eae4SChaoyong He nfp_net_params_setup(struct nfp_net_hw *hw)
52311e9eae4SChaoyong He {
524f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, hw->mtu);
525f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_FLBUFSZ, hw->flbufsz);
52611e9eae4SChaoyong He }
52711e9eae4SChaoyong He 
52811e9eae4SChaoyong He void
52911e9eae4SChaoyong He nfp_net_cfg_queue_setup(struct nfp_net_hw *hw)
53011e9eae4SChaoyong He {
531464a535bSChaoyong He 	hw->super.qcp_cfg = hw->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
53211e9eae4SChaoyong He }
53311e9eae4SChaoyong He 
53411e9eae4SChaoyong He void
53511e9eae4SChaoyong He nfp_net_write_mac(struct nfp_net_hw *hw,
53611e9eae4SChaoyong He 		uint8_t *mac)
53711e9eae4SChaoyong He {
53811e9eae4SChaoyong He 	uint32_t mac0;
53911e9eae4SChaoyong He 	uint16_t mac1;
54011e9eae4SChaoyong He 
54111e9eae4SChaoyong He 	mac0 = *(uint32_t *)mac;
5428980792dSChaoyong He 	nn_writel(rte_cpu_to_be_32(mac0), hw->super.ctrl_bar + NFP_NET_CFG_MACADDR);
54311e9eae4SChaoyong He 
54411e9eae4SChaoyong He 	mac += 4;
54511e9eae4SChaoyong He 	mac1 = *(uint16_t *)mac;
54611e9eae4SChaoyong He 	nn_writew(rte_cpu_to_be_16(mac1),
5478980792dSChaoyong He 			hw->super.ctrl_bar + NFP_NET_CFG_MACADDR + 6);
54811e9eae4SChaoyong He }
54911e9eae4SChaoyong He 
55011e9eae4SChaoyong He int
55111e9eae4SChaoyong He nfp_net_set_mac_addr(struct rte_eth_dev *dev,
55211e9eae4SChaoyong He 		struct rte_ether_addr *mac_addr)
55311e9eae4SChaoyong He {
55411e9eae4SChaoyong He 	uint32_t ctrl;
55511e9eae4SChaoyong He 	uint32_t update;
556*72d1dea6SChaoyong He 	struct nfp_hw *hw;
557*72d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
55811e9eae4SChaoyong He 
559*72d1dea6SChaoyong He 	net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
560*72d1dea6SChaoyong He 	hw = &net_hw->super;
561*72d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 &&
562*72d1dea6SChaoyong He 			(hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) {
56311e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "MAC address unable to change when port enabled");
56411e9eae4SChaoyong He 		return -EBUSY;
56511e9eae4SChaoyong He 	}
56611e9eae4SChaoyong He 
56711e9eae4SChaoyong He 	/* Writing new MAC to the specific port BAR address */
568*72d1dea6SChaoyong He 	nfp_net_write_mac(net_hw, (uint8_t *)mac_addr);
56911e9eae4SChaoyong He 
57011e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_MACADDR;
571*72d1dea6SChaoyong He 	ctrl = hw->ctrl;
572*72d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 &&
573*72d1dea6SChaoyong He 			(hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) != 0)
57411e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_LIVE_ADDR;
57511e9eae4SChaoyong He 
57611e9eae4SChaoyong He 	/* Signal the NIC about the change */
577*72d1dea6SChaoyong He 	if (nfp_reconfig(hw, ctrl, update) != 0) {
57811e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "MAC address update failed");
57911e9eae4SChaoyong He 		return -EIO;
58011e9eae4SChaoyong He 	}
58111e9eae4SChaoyong He 
58211e9eae4SChaoyong He 	return 0;
58311e9eae4SChaoyong He }
58411e9eae4SChaoyong He 
58511e9eae4SChaoyong He int
58611e9eae4SChaoyong He nfp_configure_rx_interrupt(struct rte_eth_dev *dev,
58711e9eae4SChaoyong He 		struct rte_intr_handle *intr_handle)
58811e9eae4SChaoyong He {
58911e9eae4SChaoyong He 	uint16_t i;
59011e9eae4SChaoyong He 	struct nfp_net_hw *hw;
59111e9eae4SChaoyong He 
59211e9eae4SChaoyong He 	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
59311e9eae4SChaoyong He 				dev->data->nb_rx_queues) != 0) {
59411e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Failed to allocate %d rx_queues intr_vec",
59511e9eae4SChaoyong He 				dev->data->nb_rx_queues);
59611e9eae4SChaoyong He 		return -ENOMEM;
59711e9eae4SChaoyong He 	}
59811e9eae4SChaoyong He 
59911e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
60011e9eae4SChaoyong He 
60111e9eae4SChaoyong He 	if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) {
60211e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with UIO");
60311e9eae4SChaoyong He 		/* UIO just supports one queue and no LSC */
604f58bde00SChaoyong He 		nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(0), 0);
60511e9eae4SChaoyong He 		if (rte_intr_vec_list_index_set(intr_handle, 0, 0) != 0)
60611e9eae4SChaoyong He 			return -1;
60711e9eae4SChaoyong He 	} else {
60811e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with VFIO");
60911e9eae4SChaoyong He 		for (i = 0; i < dev->data->nb_rx_queues; i++) {
61011e9eae4SChaoyong He 			/*
61111e9eae4SChaoyong He 			 * The first msix vector is reserved for non
61211e9eae4SChaoyong He 			 * efd interrupts.
61311e9eae4SChaoyong He 			 */
614f58bde00SChaoyong He 			nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(i), i + 1);
61511e9eae4SChaoyong He 			if (rte_intr_vec_list_index_set(intr_handle, i, i + 1) != 0)
61611e9eae4SChaoyong He 				return -1;
61711e9eae4SChaoyong He 		}
61811e9eae4SChaoyong He 	}
61911e9eae4SChaoyong He 
62011e9eae4SChaoyong He 	/* Avoiding TX interrupts */
621b4b6988aSChaoyong He 	hw->super.ctrl |= NFP_NET_CFG_CTRL_MSIX_TX_OFF;
62211e9eae4SChaoyong He 	return 0;
62311e9eae4SChaoyong He }
62411e9eae4SChaoyong He 
62511e9eae4SChaoyong He uint32_t
62611e9eae4SChaoyong He nfp_check_offloads(struct rte_eth_dev *dev)
62711e9eae4SChaoyong He {
62811e9eae4SChaoyong He 	uint32_t ctrl = 0;
62911e9eae4SChaoyong He 	uint64_t rx_offload;
63011e9eae4SChaoyong He 	uint64_t tx_offload;
63111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
63211e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
63311e9eae4SChaoyong He 
63411e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
63511e9eae4SChaoyong He 
63611e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
63711e9eae4SChaoyong He 	rx_offload = dev_conf->rxmode.offloads;
63811e9eae4SChaoyong He 	tx_offload = dev_conf->txmode.offloads;
63911e9eae4SChaoyong He 
64011e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0) {
64175a76c73SChaoyong He 		if ((hw->super.cap & NFP_NET_CFG_CTRL_RXCSUM) != 0)
64211e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_RXCSUM;
64311e9eae4SChaoyong He 	}
64411e9eae4SChaoyong He 
64511e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0)
64611e9eae4SChaoyong He 		nfp_net_enable_rxvlan_cap(hw, &ctrl);
64711e9eae4SChaoyong He 
64811e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) {
64975a76c73SChaoyong He 		if ((hw->super.cap & NFP_NET_CFG_CTRL_RXQINQ) != 0)
65011e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
65111e9eae4SChaoyong He 	}
65211e9eae4SChaoyong He 
65311e9eae4SChaoyong He 	hw->mtu = dev->data->mtu;
65411e9eae4SChaoyong He 
65511e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) != 0) {
65675a76c73SChaoyong He 		if ((hw->super.cap & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0)
65711e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_TXVLAN_V2;
65875a76c73SChaoyong He 		else if ((hw->super.cap & NFP_NET_CFG_CTRL_TXVLAN) != 0)
65911e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_TXVLAN;
66011e9eae4SChaoyong He 	}
66111e9eae4SChaoyong He 
66211e9eae4SChaoyong He 	/* L2 broadcast */
66375a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_L2BC) != 0)
66411e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_L2BC;
66511e9eae4SChaoyong He 
66611e9eae4SChaoyong He 	/* L2 multicast */
66775a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_L2MC) != 0)
66811e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_L2MC;
66911e9eae4SChaoyong He 
67011e9eae4SChaoyong He 	/* TX checksum offload */
67111e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0 ||
67211e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0 ||
67311e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0)
67411e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
67511e9eae4SChaoyong He 
67611e9eae4SChaoyong He 	/* LSO offload */
67711e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) != 0 ||
67811e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) != 0) {
67975a76c73SChaoyong He 		if ((hw->super.cap & NFP_NET_CFG_CTRL_LSO) != 0)
68011e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_LSO;
68111e9eae4SChaoyong He 		else
68211e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_LSO2;
68311e9eae4SChaoyong He 	}
68411e9eae4SChaoyong He 
68511e9eae4SChaoyong He 	/* RX gather */
68611e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0)
68711e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_GATHER;
68811e9eae4SChaoyong He 
68911e9eae4SChaoyong He 	return ctrl;
69011e9eae4SChaoyong He }
69111e9eae4SChaoyong He 
69211e9eae4SChaoyong He int
69311e9eae4SChaoyong He nfp_net_promisc_enable(struct rte_eth_dev *dev)
69411e9eae4SChaoyong He {
69511e9eae4SChaoyong He 	int ret;
696*72d1dea6SChaoyong He 	uint32_t update;
69711e9eae4SChaoyong He 	uint32_t new_ctrl;
698*72d1dea6SChaoyong He 	struct nfp_hw *hw;
699*72d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
70011e9eae4SChaoyong He 	struct nfp_flower_representor *repr;
70111e9eae4SChaoyong He 
70211e9eae4SChaoyong He 	if ((dev->data->dev_flags & RTE_ETH_DEV_REPRESENTOR) != 0) {
70311e9eae4SChaoyong He 		repr = dev->data->dev_private;
704*72d1dea6SChaoyong He 		net_hw = repr->app_fw_flower->pf_hw;
70511e9eae4SChaoyong He 	} else {
706*72d1dea6SChaoyong He 		net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
70711e9eae4SChaoyong He 	}
70811e9eae4SChaoyong He 
709*72d1dea6SChaoyong He 	hw = &net_hw->super;
710*72d1dea6SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) {
71111e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Promiscuous mode not supported");
71211e9eae4SChaoyong He 		return -ENOTSUP;
71311e9eae4SChaoyong He 	}
71411e9eae4SChaoyong He 
715*72d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) != 0) {
71611e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "Promiscuous mode already enabled");
71711e9eae4SChaoyong He 		return 0;
71811e9eae4SChaoyong He 	}
71911e9eae4SChaoyong He 
720*72d1dea6SChaoyong He 	new_ctrl = hw->ctrl | NFP_NET_CFG_CTRL_PROMISC;
72111e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
72211e9eae4SChaoyong He 
723*72d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
72411e9eae4SChaoyong He 	if (ret != 0)
72511e9eae4SChaoyong He 		return ret;
72611e9eae4SChaoyong He 
727*72d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
72811e9eae4SChaoyong He 
72911e9eae4SChaoyong He 	return 0;
73011e9eae4SChaoyong He }
73111e9eae4SChaoyong He 
73211e9eae4SChaoyong He int
73311e9eae4SChaoyong He nfp_net_promisc_disable(struct rte_eth_dev *dev)
73411e9eae4SChaoyong He {
73511e9eae4SChaoyong He 	int ret;
736*72d1dea6SChaoyong He 	uint32_t update;
73711e9eae4SChaoyong He 	uint32_t new_ctrl;
738*72d1dea6SChaoyong He 	struct nfp_hw *hw;
739*72d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
74011e9eae4SChaoyong He 
741*72d1dea6SChaoyong He 	net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
742*72d1dea6SChaoyong He 	hw = &net_hw->super;
74311e9eae4SChaoyong He 
744*72d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) == 0) {
74511e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "Promiscuous mode already disabled");
74611e9eae4SChaoyong He 		return 0;
74711e9eae4SChaoyong He 	}
74811e9eae4SChaoyong He 
749*72d1dea6SChaoyong He 	new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_PROMISC;
75011e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
75111e9eae4SChaoyong He 
752*72d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
75311e9eae4SChaoyong He 	if (ret != 0)
75411e9eae4SChaoyong He 		return ret;
75511e9eae4SChaoyong He 
756*72d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
75711e9eae4SChaoyong He 
75811e9eae4SChaoyong He 	return 0;
75911e9eae4SChaoyong He }
76011e9eae4SChaoyong He 
76111e9eae4SChaoyong He /*
76211e9eae4SChaoyong He  * Return 0 means link status changed, -1 means not changed
76311e9eae4SChaoyong He  *
76411e9eae4SChaoyong He  * Wait to complete is needed as it can take up to 9 seconds to get the Link
76511e9eae4SChaoyong He  * status.
76611e9eae4SChaoyong He  */
76711e9eae4SChaoyong He int
76811e9eae4SChaoyong He nfp_net_link_update(struct rte_eth_dev *dev,
76911e9eae4SChaoyong He 		__rte_unused int wait_to_complete)
77011e9eae4SChaoyong He {
77111e9eae4SChaoyong He 	int ret;
77211e9eae4SChaoyong He 	uint32_t i;
77311e9eae4SChaoyong He 	struct nfp_net_hw *hw;
77411e9eae4SChaoyong He 	uint32_t nn_link_status;
77511e9eae4SChaoyong He 	struct rte_eth_link link;
77611e9eae4SChaoyong He 	struct nfp_eth_table *nfp_eth_table;
77711e9eae4SChaoyong He 
77811e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
77911e9eae4SChaoyong He 
78011e9eae4SChaoyong He 	memset(&link, 0, sizeof(struct rte_eth_link));
78111e9eae4SChaoyong He 
78211e9eae4SChaoyong He 	/* Read link status */
783f58bde00SChaoyong He 	nn_link_status = nn_cfg_readw(&hw->super, NFP_NET_CFG_STS);
78411e9eae4SChaoyong He 	if ((nn_link_status & NFP_NET_CFG_STS_LINK) != 0)
78511e9eae4SChaoyong He 		link.link_status = RTE_ETH_LINK_UP;
78611e9eae4SChaoyong He 
78711e9eae4SChaoyong He 	link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
78811e9eae4SChaoyong He 	link.link_speed = RTE_ETH_SPEED_NUM_NONE;
78911e9eae4SChaoyong He 
79011e9eae4SChaoyong He 	if (link.link_status == RTE_ETH_LINK_UP) {
79111e9eae4SChaoyong He 		if (hw->pf_dev != NULL) {
79211e9eae4SChaoyong He 			nfp_eth_table = hw->pf_dev->nfp_eth_table;
79311e9eae4SChaoyong He 			if (nfp_eth_table != NULL) {
79411e9eae4SChaoyong He 				uint32_t speed = nfp_eth_table->ports[hw->idx].speed;
79511e9eae4SChaoyong He 				for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) {
79611e9eae4SChaoyong He 					if (nfp_net_link_speed_nfp2rte[i] == speed) {
79711e9eae4SChaoyong He 						link.link_speed = speed;
79811e9eae4SChaoyong He 						break;
79911e9eae4SChaoyong He 					}
80011e9eae4SChaoyong He 				}
80111e9eae4SChaoyong He 			}
80211e9eae4SChaoyong He 		} else {
80311e9eae4SChaoyong He 			/*
80411e9eae4SChaoyong He 			 * Shift and mask nn_link_status so that it is effectively the value
80511e9eae4SChaoyong He 			 * at offset NFP_NET_CFG_STS_NSP_LINK_RATE.
80611e9eae4SChaoyong He 			 */
80711e9eae4SChaoyong He 			nn_link_status = (nn_link_status >> NFP_NET_CFG_STS_LINK_RATE_SHIFT) &
80811e9eae4SChaoyong He 					NFP_NET_CFG_STS_LINK_RATE_MASK;
80911e9eae4SChaoyong He 			if (nn_link_status < RTE_DIM(nfp_net_link_speed_nfp2rte))
81011e9eae4SChaoyong He 				link.link_speed = nfp_net_link_speed_nfp2rte[nn_link_status];
81111e9eae4SChaoyong He 		}
81211e9eae4SChaoyong He 	}
81311e9eae4SChaoyong He 
81411e9eae4SChaoyong He 	ret = rte_eth_linkstatus_set(dev, &link);
81511e9eae4SChaoyong He 	if (ret == 0) {
81611e9eae4SChaoyong He 		if (link.link_status != 0)
81711e9eae4SChaoyong He 			PMD_DRV_LOG(INFO, "NIC Link is Up");
81811e9eae4SChaoyong He 		else
81911e9eae4SChaoyong He 			PMD_DRV_LOG(INFO, "NIC Link is Down");
82011e9eae4SChaoyong He 	}
82111e9eae4SChaoyong He 
82211e9eae4SChaoyong He 	/*
82311e9eae4SChaoyong He 	 * Notify the port to update the speed value in the CTRL BAR from NSP.
82411e9eae4SChaoyong He 	 * Not applicable for VFs as the associated PF is still attached to the
82511e9eae4SChaoyong He 	 * kernel driver.
82611e9eae4SChaoyong He 	 */
82711e9eae4SChaoyong He 	if (hw->pf_dev != NULL)
82811e9eae4SChaoyong He 		nfp_net_notify_port_speed(hw, &link);
82911e9eae4SChaoyong He 
83011e9eae4SChaoyong He 	return ret;
83111e9eae4SChaoyong He }
83211e9eae4SChaoyong He 
83311e9eae4SChaoyong He int
83411e9eae4SChaoyong He nfp_net_stats_get(struct rte_eth_dev *dev,
83511e9eae4SChaoyong He 		struct rte_eth_stats *stats)
83611e9eae4SChaoyong He {
83711e9eae4SChaoyong He 	uint16_t i;
83811e9eae4SChaoyong He 	struct nfp_net_hw *hw;
83911e9eae4SChaoyong He 	struct rte_eth_stats nfp_dev_stats;
84011e9eae4SChaoyong He 
84111e9eae4SChaoyong He 	if (stats == NULL)
84211e9eae4SChaoyong He 		return -EINVAL;
84311e9eae4SChaoyong He 
84411e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
84511e9eae4SChaoyong He 
84611e9eae4SChaoyong He 	memset(&nfp_dev_stats, 0, sizeof(nfp_dev_stats));
84711e9eae4SChaoyong He 
84811e9eae4SChaoyong He 	/* Reading per RX ring stats */
84911e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
85011e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
85111e9eae4SChaoyong He 			break;
85211e9eae4SChaoyong He 
85311e9eae4SChaoyong He 		nfp_dev_stats.q_ipackets[i] =
854f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i));
85511e9eae4SChaoyong He 		nfp_dev_stats.q_ipackets[i] -=
85611e9eae4SChaoyong He 				hw->eth_stats_base.q_ipackets[i];
85711e9eae4SChaoyong He 
85811e9eae4SChaoyong He 		nfp_dev_stats.q_ibytes[i] =
859f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8);
86011e9eae4SChaoyong He 		nfp_dev_stats.q_ibytes[i] -=
86111e9eae4SChaoyong He 				hw->eth_stats_base.q_ibytes[i];
86211e9eae4SChaoyong He 	}
86311e9eae4SChaoyong He 
86411e9eae4SChaoyong He 	/* Reading per TX ring stats */
86511e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
86611e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
86711e9eae4SChaoyong He 			break;
86811e9eae4SChaoyong He 
86911e9eae4SChaoyong He 		nfp_dev_stats.q_opackets[i] =
870f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i));
87111e9eae4SChaoyong He 		nfp_dev_stats.q_opackets[i] -= hw->eth_stats_base.q_opackets[i];
87211e9eae4SChaoyong He 
87311e9eae4SChaoyong He 		nfp_dev_stats.q_obytes[i] =
874f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8);
87511e9eae4SChaoyong He 		nfp_dev_stats.q_obytes[i] -= hw->eth_stats_base.q_obytes[i];
87611e9eae4SChaoyong He 	}
87711e9eae4SChaoyong He 
878f58bde00SChaoyong He 	nfp_dev_stats.ipackets = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES);
87911e9eae4SChaoyong He 	nfp_dev_stats.ipackets -= hw->eth_stats_base.ipackets;
88011e9eae4SChaoyong He 
881f58bde00SChaoyong He 	nfp_dev_stats.ibytes = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS);
88211e9eae4SChaoyong He 	nfp_dev_stats.ibytes -= hw->eth_stats_base.ibytes;
88311e9eae4SChaoyong He 
88411e9eae4SChaoyong He 	nfp_dev_stats.opackets =
885f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES);
88611e9eae4SChaoyong He 	nfp_dev_stats.opackets -= hw->eth_stats_base.opackets;
88711e9eae4SChaoyong He 
88811e9eae4SChaoyong He 	nfp_dev_stats.obytes =
889f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS);
89011e9eae4SChaoyong He 	nfp_dev_stats.obytes -= hw->eth_stats_base.obytes;
89111e9eae4SChaoyong He 
89211e9eae4SChaoyong He 	/* Reading general device stats */
89311e9eae4SChaoyong He 	nfp_dev_stats.ierrors =
894f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS);
89511e9eae4SChaoyong He 	nfp_dev_stats.ierrors -= hw->eth_stats_base.ierrors;
89611e9eae4SChaoyong He 
89711e9eae4SChaoyong He 	nfp_dev_stats.oerrors =
898f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS);
89911e9eae4SChaoyong He 	nfp_dev_stats.oerrors -= hw->eth_stats_base.oerrors;
90011e9eae4SChaoyong He 
90111e9eae4SChaoyong He 	/* RX ring mbuf allocation failures */
90211e9eae4SChaoyong He 	nfp_dev_stats.rx_nombuf = dev->data->rx_mbuf_alloc_failed;
90311e9eae4SChaoyong He 
90411e9eae4SChaoyong He 	nfp_dev_stats.imissed =
905f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS);
90611e9eae4SChaoyong He 	nfp_dev_stats.imissed -= hw->eth_stats_base.imissed;
90711e9eae4SChaoyong He 
90811e9eae4SChaoyong He 	memcpy(stats, &nfp_dev_stats, sizeof(*stats));
90911e9eae4SChaoyong He 	return 0;
91011e9eae4SChaoyong He }
91111e9eae4SChaoyong He 
91211e9eae4SChaoyong He /*
91311e9eae4SChaoyong He  * hw->eth_stats_base records the per counter starting point.
91411e9eae4SChaoyong He  * Lets update it now.
91511e9eae4SChaoyong He  */
91611e9eae4SChaoyong He int
91711e9eae4SChaoyong He nfp_net_stats_reset(struct rte_eth_dev *dev)
91811e9eae4SChaoyong He {
91911e9eae4SChaoyong He 	uint16_t i;
92011e9eae4SChaoyong He 	struct nfp_net_hw *hw;
92111e9eae4SChaoyong He 
92211e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
92311e9eae4SChaoyong He 
92411e9eae4SChaoyong He 	/* Reading per RX ring stats */
92511e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
92611e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
92711e9eae4SChaoyong He 			break;
92811e9eae4SChaoyong He 
92911e9eae4SChaoyong He 		hw->eth_stats_base.q_ipackets[i] =
930f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i));
93111e9eae4SChaoyong He 
93211e9eae4SChaoyong He 		hw->eth_stats_base.q_ibytes[i] =
933f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8);
93411e9eae4SChaoyong He 	}
93511e9eae4SChaoyong He 
93611e9eae4SChaoyong He 	/* Reading per TX ring stats */
93711e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
93811e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
93911e9eae4SChaoyong He 			break;
94011e9eae4SChaoyong He 
94111e9eae4SChaoyong He 		hw->eth_stats_base.q_opackets[i] =
942f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i));
94311e9eae4SChaoyong He 
94411e9eae4SChaoyong He 		hw->eth_stats_base.q_obytes[i] =
945f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8);
94611e9eae4SChaoyong He 	}
94711e9eae4SChaoyong He 
94811e9eae4SChaoyong He 	hw->eth_stats_base.ipackets =
949f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES);
95011e9eae4SChaoyong He 
95111e9eae4SChaoyong He 	hw->eth_stats_base.ibytes =
952f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS);
95311e9eae4SChaoyong He 
95411e9eae4SChaoyong He 	hw->eth_stats_base.opackets =
955f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES);
95611e9eae4SChaoyong He 
95711e9eae4SChaoyong He 	hw->eth_stats_base.obytes =
958f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS);
95911e9eae4SChaoyong He 
96011e9eae4SChaoyong He 	/* Reading general device stats */
96111e9eae4SChaoyong He 	hw->eth_stats_base.ierrors =
962f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS);
96311e9eae4SChaoyong He 
96411e9eae4SChaoyong He 	hw->eth_stats_base.oerrors =
965f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS);
96611e9eae4SChaoyong He 
96711e9eae4SChaoyong He 	/* RX ring mbuf allocation failures */
96811e9eae4SChaoyong He 	dev->data->rx_mbuf_alloc_failed = 0;
96911e9eae4SChaoyong He 
97011e9eae4SChaoyong He 	hw->eth_stats_base.imissed =
971f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS);
97211e9eae4SChaoyong He 
97311e9eae4SChaoyong He 	return 0;
97411e9eae4SChaoyong He }
97511e9eae4SChaoyong He 
97611e9eae4SChaoyong He uint32_t
97711e9eae4SChaoyong He nfp_net_xstats_size(const struct rte_eth_dev *dev)
97811e9eae4SChaoyong He {
97911e9eae4SChaoyong He 	uint32_t count;
98011e9eae4SChaoyong He 	struct nfp_net_hw *hw;
98111e9eae4SChaoyong He 	const uint32_t size = RTE_DIM(nfp_net_xstats);
98211e9eae4SChaoyong He 
98311e9eae4SChaoyong He 	/* If the device is a VF, then there will be no MAC stats */
98411e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
98511e9eae4SChaoyong He 	if (hw->mac_stats == NULL) {
98611e9eae4SChaoyong He 		for (count = 0; count < size; count++) {
98711e9eae4SChaoyong He 			if (nfp_net_xstats[count].group == NFP_XSTAT_GROUP_MAC)
98811e9eae4SChaoyong He 				break;
98911e9eae4SChaoyong He 		}
99011e9eae4SChaoyong He 
99111e9eae4SChaoyong He 		return count;
99211e9eae4SChaoyong He 	}
99311e9eae4SChaoyong He 
99411e9eae4SChaoyong He 	return size;
99511e9eae4SChaoyong He }
99611e9eae4SChaoyong He 
99711e9eae4SChaoyong He static const struct nfp_xstat *
99811e9eae4SChaoyong He nfp_net_xstats_info(const struct rte_eth_dev *dev,
99911e9eae4SChaoyong He 		uint32_t index)
100011e9eae4SChaoyong He {
100111e9eae4SChaoyong He 	if (index >= nfp_net_xstats_size(dev)) {
100211e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "xstat index out of bounds");
100311e9eae4SChaoyong He 		return NULL;
100411e9eae4SChaoyong He 	}
100511e9eae4SChaoyong He 
100611e9eae4SChaoyong He 	return &nfp_net_xstats[index];
100711e9eae4SChaoyong He }
100811e9eae4SChaoyong He 
100911e9eae4SChaoyong He static uint64_t
101011e9eae4SChaoyong He nfp_net_xstats_value(const struct rte_eth_dev *dev,
101111e9eae4SChaoyong He 		uint32_t index,
101211e9eae4SChaoyong He 		bool raw)
101311e9eae4SChaoyong He {
101411e9eae4SChaoyong He 	uint64_t value;
101511e9eae4SChaoyong He 	struct nfp_net_hw *hw;
101611e9eae4SChaoyong He 	struct nfp_xstat xstat;
101711e9eae4SChaoyong He 
101811e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
101911e9eae4SChaoyong He 	xstat = nfp_net_xstats[index];
102011e9eae4SChaoyong He 
102111e9eae4SChaoyong He 	if (xstat.group == NFP_XSTAT_GROUP_MAC)
102211e9eae4SChaoyong He 		value = nn_readq(hw->mac_stats + xstat.offset);
102311e9eae4SChaoyong He 	else
1024f58bde00SChaoyong He 		value = nn_cfg_readq(&hw->super, xstat.offset);
102511e9eae4SChaoyong He 
102611e9eae4SChaoyong He 	if (raw)
102711e9eae4SChaoyong He 		return value;
102811e9eae4SChaoyong He 
102911e9eae4SChaoyong He 	/*
103011e9eae4SChaoyong He 	 * A baseline value of each statistic counter is recorded when stats are "reset".
103111e9eae4SChaoyong He 	 * Thus, the value returned by this function need to be decremented by this
103211e9eae4SChaoyong He 	 * baseline value. The result is the count of this statistic since the last time
103311e9eae4SChaoyong He 	 * it was "reset".
103411e9eae4SChaoyong He 	 */
103511e9eae4SChaoyong He 	return value - hw->eth_xstats_base[index].value;
103611e9eae4SChaoyong He }
103711e9eae4SChaoyong He 
103811e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */
103911e9eae4SChaoyong He int
104011e9eae4SChaoyong He nfp_net_xstats_get_names(struct rte_eth_dev *dev,
104111e9eae4SChaoyong He 		struct rte_eth_xstat_name *xstats_names,
104211e9eae4SChaoyong He 		unsigned int size)
104311e9eae4SChaoyong He {
104411e9eae4SChaoyong He 	uint32_t id;
104511e9eae4SChaoyong He 	uint32_t nfp_size;
104611e9eae4SChaoyong He 	uint32_t read_size;
104711e9eae4SChaoyong He 
104811e9eae4SChaoyong He 	nfp_size = nfp_net_xstats_size(dev);
104911e9eae4SChaoyong He 
105011e9eae4SChaoyong He 	if (xstats_names == NULL)
105111e9eae4SChaoyong He 		return nfp_size;
105211e9eae4SChaoyong He 
105311e9eae4SChaoyong He 	/* Read at most NFP xstats number of names. */
105411e9eae4SChaoyong He 	read_size = RTE_MIN(size, nfp_size);
105511e9eae4SChaoyong He 
105611e9eae4SChaoyong He 	for (id = 0; id < read_size; id++)
105711e9eae4SChaoyong He 		rte_strlcpy(xstats_names[id].name, nfp_net_xstats[id].name,
105811e9eae4SChaoyong He 				RTE_ETH_XSTATS_NAME_SIZE);
105911e9eae4SChaoyong He 
106011e9eae4SChaoyong He 	return read_size;
106111e9eae4SChaoyong He }
106211e9eae4SChaoyong He 
106311e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */
106411e9eae4SChaoyong He int
106511e9eae4SChaoyong He nfp_net_xstats_get(struct rte_eth_dev *dev,
106611e9eae4SChaoyong He 		struct rte_eth_xstat *xstats,
106711e9eae4SChaoyong He 		unsigned int n)
106811e9eae4SChaoyong He {
106911e9eae4SChaoyong He 	uint32_t id;
107011e9eae4SChaoyong He 	uint32_t nfp_size;
107111e9eae4SChaoyong He 	uint32_t read_size;
107211e9eae4SChaoyong He 
107311e9eae4SChaoyong He 	nfp_size = nfp_net_xstats_size(dev);
107411e9eae4SChaoyong He 
107511e9eae4SChaoyong He 	if (xstats == NULL)
107611e9eae4SChaoyong He 		return nfp_size;
107711e9eae4SChaoyong He 
107811e9eae4SChaoyong He 	/* Read at most NFP xstats number of values. */
107911e9eae4SChaoyong He 	read_size = RTE_MIN(n, nfp_size);
108011e9eae4SChaoyong He 
108111e9eae4SChaoyong He 	for (id = 0; id < read_size; id++) {
108211e9eae4SChaoyong He 		xstats[id].id = id;
108311e9eae4SChaoyong He 		xstats[id].value = nfp_net_xstats_value(dev, id, false);
108411e9eae4SChaoyong He 	}
108511e9eae4SChaoyong He 
108611e9eae4SChaoyong He 	return read_size;
108711e9eae4SChaoyong He }
108811e9eae4SChaoyong He 
108911e9eae4SChaoyong He /*
109011e9eae4SChaoyong He  * NOTE: The only caller rte_eth_xstats_get_names_by_id() ensures dev,
109111e9eae4SChaoyong He  * ids, xstats_names and size are valid, and non-NULL.
109211e9eae4SChaoyong He  */
109311e9eae4SChaoyong He int
109411e9eae4SChaoyong He nfp_net_xstats_get_names_by_id(struct rte_eth_dev *dev,
109511e9eae4SChaoyong He 		const uint64_t *ids,
109611e9eae4SChaoyong He 		struct rte_eth_xstat_name *xstats_names,
109711e9eae4SChaoyong He 		unsigned int size)
109811e9eae4SChaoyong He {
109911e9eae4SChaoyong He 	uint32_t i;
110011e9eae4SChaoyong He 	uint32_t read_size;
110111e9eae4SChaoyong He 
110211e9eae4SChaoyong He 	/* Read at most NFP xstats number of names. */
110311e9eae4SChaoyong He 	read_size = RTE_MIN(size, nfp_net_xstats_size(dev));
110411e9eae4SChaoyong He 
110511e9eae4SChaoyong He 	for (i = 0; i < read_size; i++) {
110611e9eae4SChaoyong He 		const struct nfp_xstat *xstat;
110711e9eae4SChaoyong He 
110811e9eae4SChaoyong He 		/* Make sure ID is valid for device. */
110911e9eae4SChaoyong He 		xstat = nfp_net_xstats_info(dev, ids[i]);
111011e9eae4SChaoyong He 		if (xstat == NULL)
111111e9eae4SChaoyong He 			return -EINVAL;
111211e9eae4SChaoyong He 
111311e9eae4SChaoyong He 		rte_strlcpy(xstats_names[i].name, xstat->name,
111411e9eae4SChaoyong He 				RTE_ETH_XSTATS_NAME_SIZE);
111511e9eae4SChaoyong He 	}
111611e9eae4SChaoyong He 
111711e9eae4SChaoyong He 	return read_size;
111811e9eae4SChaoyong He }
111911e9eae4SChaoyong He 
112011e9eae4SChaoyong He /*
112111e9eae4SChaoyong He  * NOTE: The only caller rte_eth_xstats_get_by_id() ensures dev,
112211e9eae4SChaoyong He  * ids, values and n are valid, and non-NULL.
112311e9eae4SChaoyong He  */
112411e9eae4SChaoyong He int
112511e9eae4SChaoyong He nfp_net_xstats_get_by_id(struct rte_eth_dev *dev,
112611e9eae4SChaoyong He 		const uint64_t *ids,
112711e9eae4SChaoyong He 		uint64_t *values,
112811e9eae4SChaoyong He 		unsigned int n)
112911e9eae4SChaoyong He {
113011e9eae4SChaoyong He 	uint32_t i;
113111e9eae4SChaoyong He 	uint32_t read_size;
113211e9eae4SChaoyong He 
113311e9eae4SChaoyong He 	/* Read at most NFP xstats number of values. */
113411e9eae4SChaoyong He 	read_size = RTE_MIN(n, nfp_net_xstats_size(dev));
113511e9eae4SChaoyong He 
113611e9eae4SChaoyong He 	for (i = 0; i < read_size; i++) {
113711e9eae4SChaoyong He 		const struct nfp_xstat *xstat;
113811e9eae4SChaoyong He 
113911e9eae4SChaoyong He 		/* Make sure index is valid for device. */
114011e9eae4SChaoyong He 		xstat = nfp_net_xstats_info(dev, ids[i]);
114111e9eae4SChaoyong He 		if (xstat == NULL)
114211e9eae4SChaoyong He 			return -EINVAL;
114311e9eae4SChaoyong He 
114411e9eae4SChaoyong He 		values[i] = nfp_net_xstats_value(dev, ids[i], false);
114511e9eae4SChaoyong He 	}
114611e9eae4SChaoyong He 
114711e9eae4SChaoyong He 	return read_size;
114811e9eae4SChaoyong He }
114911e9eae4SChaoyong He 
115011e9eae4SChaoyong He int
115111e9eae4SChaoyong He nfp_net_xstats_reset(struct rte_eth_dev *dev)
115211e9eae4SChaoyong He {
115311e9eae4SChaoyong He 	uint32_t id;
115411e9eae4SChaoyong He 	uint32_t read_size;
115511e9eae4SChaoyong He 	struct nfp_net_hw *hw;
115611e9eae4SChaoyong He 
115711e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
115811e9eae4SChaoyong He 	read_size = nfp_net_xstats_size(dev);
115911e9eae4SChaoyong He 
116011e9eae4SChaoyong He 	for (id = 0; id < read_size; id++) {
116111e9eae4SChaoyong He 		hw->eth_xstats_base[id].id = id;
116211e9eae4SChaoyong He 		hw->eth_xstats_base[id].value = nfp_net_xstats_value(dev, id, true);
116311e9eae4SChaoyong He 	}
116411e9eae4SChaoyong He 
116511e9eae4SChaoyong He 	/* Successfully reset xstats, now call function to reset basic stats. */
116611e9eae4SChaoyong He 	return nfp_net_stats_reset(dev);
116711e9eae4SChaoyong He }
116811e9eae4SChaoyong He 
116911e9eae4SChaoyong He void
117011e9eae4SChaoyong He nfp_net_rx_desc_limits(struct nfp_net_hw *hw,
117111e9eae4SChaoyong He 		uint16_t *min_rx_desc,
117211e9eae4SChaoyong He 		uint16_t *max_rx_desc)
117311e9eae4SChaoyong He {
117411e9eae4SChaoyong He 	*max_rx_desc = hw->dev_info->max_qc_size;
117511e9eae4SChaoyong He 	*min_rx_desc = hw->dev_info->min_qc_size;
117611e9eae4SChaoyong He }
117711e9eae4SChaoyong He 
117811e9eae4SChaoyong He void
117911e9eae4SChaoyong He nfp_net_tx_desc_limits(struct nfp_net_hw *hw,
118011e9eae4SChaoyong He 		uint16_t *min_tx_desc,
118111e9eae4SChaoyong He 		uint16_t *max_tx_desc)
118211e9eae4SChaoyong He {
118311e9eae4SChaoyong He 	uint16_t tx_dpp;
118411e9eae4SChaoyong He 
118511e9eae4SChaoyong He 	if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
118611e9eae4SChaoyong He 		tx_dpp = NFD3_TX_DESC_PER_PKT;
118711e9eae4SChaoyong He 	else
118811e9eae4SChaoyong He 		tx_dpp = NFDK_TX_DESC_PER_SIMPLE_PKT;
118911e9eae4SChaoyong He 
119011e9eae4SChaoyong He 	*max_tx_desc = hw->dev_info->max_qc_size / tx_dpp;
119111e9eae4SChaoyong He 	*min_tx_desc = hw->dev_info->min_qc_size / tx_dpp;
119211e9eae4SChaoyong He }
119311e9eae4SChaoyong He 
119411e9eae4SChaoyong He int
119511e9eae4SChaoyong He nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
119611e9eae4SChaoyong He {
119711e9eae4SChaoyong He 	uint32_t cap_extend;
119811e9eae4SChaoyong He 	uint16_t min_rx_desc;
119911e9eae4SChaoyong He 	uint16_t max_rx_desc;
120011e9eae4SChaoyong He 	uint16_t min_tx_desc;
120111e9eae4SChaoyong He 	uint16_t max_tx_desc;
120211e9eae4SChaoyong He 	struct nfp_net_hw *hw;
120311e9eae4SChaoyong He 
120411e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
120511e9eae4SChaoyong He 
120611e9eae4SChaoyong He 	nfp_net_rx_desc_limits(hw, &min_rx_desc, &max_rx_desc);
120711e9eae4SChaoyong He 	nfp_net_tx_desc_limits(hw, &min_tx_desc, &max_tx_desc);
120811e9eae4SChaoyong He 
120911e9eae4SChaoyong He 	dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues;
121011e9eae4SChaoyong He 	dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues;
121111e9eae4SChaoyong He 	dev_info->min_rx_bufsize = RTE_ETHER_MIN_MTU;
121211e9eae4SChaoyong He 
121311e9eae4SChaoyong He 	/**
121411e9eae4SChaoyong He 	 * The maximum rx packet length (max_rx_pktlen) is set to the
121511e9eae4SChaoyong He 	 * maximum supported frame size that the NFP can handle. This
121611e9eae4SChaoyong He 	 * includes layer 2 headers, CRC and other metadata that can
121711e9eae4SChaoyong He 	 * optionally be used.
121811e9eae4SChaoyong He 	 * The maximum layer 3 MTU (max_mtu) is read from hardware,
121911e9eae4SChaoyong He 	 * which was set by the firmware loaded onto the card.
122011e9eae4SChaoyong He 	 */
122111e9eae4SChaoyong He 	dev_info->max_rx_pktlen = NFP_FRAME_SIZE_MAX;
122211e9eae4SChaoyong He 	dev_info->max_mtu = hw->max_mtu;
122311e9eae4SChaoyong He 	dev_info->min_mtu = RTE_ETHER_MIN_MTU;
122411e9eae4SChaoyong He 	/* Next should change when PF support is implemented */
122511e9eae4SChaoyong He 	dev_info->max_mac_addrs = 1;
122611e9eae4SChaoyong He 
122775a76c73SChaoyong He 	if ((hw->super.cap & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) != 0)
122811e9eae4SChaoyong He 		dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
122911e9eae4SChaoyong He 
123075a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_RXQINQ) != 0)
123111e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
123211e9eae4SChaoyong He 
123375a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_RXCSUM) != 0)
123411e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
123511e9eae4SChaoyong He 				RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
123611e9eae4SChaoyong He 				RTE_ETH_RX_OFFLOAD_TCP_CKSUM;
123711e9eae4SChaoyong He 
123875a76c73SChaoyong He 	if ((hw->super.cap & (NFP_NET_CFG_CTRL_TXVLAN | NFP_NET_CFG_CTRL_TXVLAN_V2)) != 0)
123911e9eae4SChaoyong He 		dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
124011e9eae4SChaoyong He 
124175a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_TXCSUM) != 0)
124211e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
124311e9eae4SChaoyong He 				RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
124411e9eae4SChaoyong He 				RTE_ETH_TX_OFFLOAD_TCP_CKSUM;
124511e9eae4SChaoyong He 
124675a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0) {
124711e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO;
124875a76c73SChaoyong He 		if ((hw->super.cap & NFP_NET_CFG_CTRL_VXLAN) != 0)
124911e9eae4SChaoyong He 			dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO;
125011e9eae4SChaoyong He 	}
125111e9eae4SChaoyong He 
125275a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_GATHER) != 0)
125311e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
125411e9eae4SChaoyong He 
125575a76c73SChaoyong He 	cap_extend = hw->super.cap_ext;
125611e9eae4SChaoyong He 	if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
125711e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY;
125811e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY;
125911e9eae4SChaoyong He 	}
126011e9eae4SChaoyong He 
126111e9eae4SChaoyong He 	dev_info->default_rxconf = (struct rte_eth_rxconf) {
126211e9eae4SChaoyong He 		.rx_thresh = {
126311e9eae4SChaoyong He 			.pthresh = DEFAULT_RX_PTHRESH,
126411e9eae4SChaoyong He 			.hthresh = DEFAULT_RX_HTHRESH,
126511e9eae4SChaoyong He 			.wthresh = DEFAULT_RX_WTHRESH,
126611e9eae4SChaoyong He 		},
126711e9eae4SChaoyong He 		.rx_free_thresh = DEFAULT_RX_FREE_THRESH,
126811e9eae4SChaoyong He 		.rx_drop_en = 0,
126911e9eae4SChaoyong He 	};
127011e9eae4SChaoyong He 
127111e9eae4SChaoyong He 	dev_info->default_txconf = (struct rte_eth_txconf) {
127211e9eae4SChaoyong He 		.tx_thresh = {
127311e9eae4SChaoyong He 			.pthresh = DEFAULT_TX_PTHRESH,
127411e9eae4SChaoyong He 			.hthresh = DEFAULT_TX_HTHRESH,
127511e9eae4SChaoyong He 			.wthresh = DEFAULT_TX_WTHRESH,
127611e9eae4SChaoyong He 		},
127711e9eae4SChaoyong He 		.tx_free_thresh = DEFAULT_TX_FREE_THRESH,
127811e9eae4SChaoyong He 		.tx_rs_thresh = DEFAULT_TX_RSBIT_THRESH,
127911e9eae4SChaoyong He 	};
128011e9eae4SChaoyong He 
128111e9eae4SChaoyong He 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
128211e9eae4SChaoyong He 		.nb_max = max_rx_desc,
128311e9eae4SChaoyong He 		.nb_min = min_rx_desc,
128411e9eae4SChaoyong He 		.nb_align = NFP_ALIGN_RING_DESC,
128511e9eae4SChaoyong He 	};
128611e9eae4SChaoyong He 
128711e9eae4SChaoyong He 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
128811e9eae4SChaoyong He 		.nb_max = max_tx_desc,
128911e9eae4SChaoyong He 		.nb_min = min_tx_desc,
129011e9eae4SChaoyong He 		.nb_align = NFP_ALIGN_RING_DESC,
129111e9eae4SChaoyong He 		.nb_seg_max = NFP_TX_MAX_SEG,
129211e9eae4SChaoyong He 		.nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG,
129311e9eae4SChaoyong He 	};
129411e9eae4SChaoyong He 
129575a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) != 0) {
129611e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
129711e9eae4SChaoyong He 
129811e9eae4SChaoyong He 		dev_info->flow_type_rss_offloads = RTE_ETH_RSS_IPV4 |
129911e9eae4SChaoyong He 				RTE_ETH_RSS_NONFRAG_IPV4_TCP |
130011e9eae4SChaoyong He 				RTE_ETH_RSS_NONFRAG_IPV4_UDP |
130111e9eae4SChaoyong He 				RTE_ETH_RSS_NONFRAG_IPV4_SCTP |
130211e9eae4SChaoyong He 				RTE_ETH_RSS_IPV6 |
130311e9eae4SChaoyong He 				RTE_ETH_RSS_NONFRAG_IPV6_TCP |
130411e9eae4SChaoyong He 				RTE_ETH_RSS_NONFRAG_IPV6_UDP |
130511e9eae4SChaoyong He 				RTE_ETH_RSS_NONFRAG_IPV6_SCTP;
130611e9eae4SChaoyong He 
130711e9eae4SChaoyong He 		dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
130811e9eae4SChaoyong He 		dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;
130911e9eae4SChaoyong He 	}
131011e9eae4SChaoyong He 
131111e9eae4SChaoyong He 	dev_info->speed_capa = RTE_ETH_LINK_SPEED_1G |
131211e9eae4SChaoyong He 			RTE_ETH_LINK_SPEED_10G |
131311e9eae4SChaoyong He 			RTE_ETH_LINK_SPEED_25G |
131411e9eae4SChaoyong He 			RTE_ETH_LINK_SPEED_40G |
131511e9eae4SChaoyong He 			RTE_ETH_LINK_SPEED_50G |
131611e9eae4SChaoyong He 			RTE_ETH_LINK_SPEED_100G;
131711e9eae4SChaoyong He 
131811e9eae4SChaoyong He 	return 0;
131911e9eae4SChaoyong He }
132011e9eae4SChaoyong He 
132111e9eae4SChaoyong He int
132211e9eae4SChaoyong He nfp_net_common_init(struct rte_pci_device *pci_dev,
132311e9eae4SChaoyong He 		struct nfp_net_hw *hw)
132411e9eae4SChaoyong He {
132511e9eae4SChaoyong He 	const int stride = 4;
132611e9eae4SChaoyong He 
132711e9eae4SChaoyong He 	hw->device_id = pci_dev->id.device_id;
132811e9eae4SChaoyong He 	hw->vendor_id = pci_dev->id.vendor_id;
132911e9eae4SChaoyong He 	hw->subsystem_device_id = pci_dev->id.subsystem_device_id;
133011e9eae4SChaoyong He 	hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id;
133111e9eae4SChaoyong He 
1332f58bde00SChaoyong He 	hw->max_rx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_RXRINGS);
1333f58bde00SChaoyong He 	hw->max_tx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_TXRINGS);
133411e9eae4SChaoyong He 	if (hw->max_rx_queues == 0 || hw->max_tx_queues == 0) {
133511e9eae4SChaoyong He 		PMD_INIT_LOG(ERR, "Device %s can not be used, there are no valid queue "
133611e9eae4SChaoyong He 				"pairs for use", pci_dev->name);
133711e9eae4SChaoyong He 		return -ENODEV;
133811e9eae4SChaoyong He 	}
133911e9eae4SChaoyong He 
134011e9eae4SChaoyong He 	nfp_net_cfg_read_version(hw);
134111e9eae4SChaoyong He 	if (!nfp_net_is_valid_nfd_version(hw->ver))
134211e9eae4SChaoyong He 		return -EINVAL;
134311e9eae4SChaoyong He 
134411e9eae4SChaoyong He 	if (nfp_net_check_dma_mask(hw, pci_dev->name) != 0)
134511e9eae4SChaoyong He 		return -ENODEV;
134611e9eae4SChaoyong He 
134711e9eae4SChaoyong He 	/* Get some of the read-only fields from the config BAR */
1348f58bde00SChaoyong He 	hw->super.cap = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP);
1349f58bde00SChaoyong He 	hw->super.cap_ext = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP_WORD1);
1350f58bde00SChaoyong He 	hw->max_mtu = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_MTU);
135111e9eae4SChaoyong He 	hw->flbufsz = DEFAULT_FLBUF_SIZE;
135211e9eae4SChaoyong He 
135311e9eae4SChaoyong He 	nfp_net_init_metadata_format(hw);
135411e9eae4SChaoyong He 
135511e9eae4SChaoyong He 	/* Read the Rx offset configured from firmware */
135611e9eae4SChaoyong He 	if (hw->ver.major < 2)
135711e9eae4SChaoyong He 		hw->rx_offset = NFP_NET_RX_OFFSET;
135811e9eae4SChaoyong He 	else
1359f58bde00SChaoyong He 		hw->rx_offset = nn_cfg_readl(&hw->super, NFP_NET_CFG_RX_OFFSET_ADDR);
136011e9eae4SChaoyong He 
1361b4b6988aSChaoyong He 	hw->super.ctrl = 0;
136211e9eae4SChaoyong He 	hw->stride_rx = stride;
136311e9eae4SChaoyong He 	hw->stride_tx = stride;
136411e9eae4SChaoyong He 
136511e9eae4SChaoyong He 	return 0;
136611e9eae4SChaoyong He }
136711e9eae4SChaoyong He 
136811e9eae4SChaoyong He const uint32_t *
136911e9eae4SChaoyong He nfp_net_supported_ptypes_get(struct rte_eth_dev *dev)
137011e9eae4SChaoyong He {
137111e9eae4SChaoyong He 	struct nfp_net_hw *net_hw;
137211e9eae4SChaoyong He 	static const uint32_t ptypes[] = {
137311e9eae4SChaoyong He 		RTE_PTYPE_L2_ETHER,
137411e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4,
137511e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4_EXT,
137611e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6,
137711e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6_EXT,
137811e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
137911e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
138011e9eae4SChaoyong He 		RTE_PTYPE_L4_TCP,
138111e9eae4SChaoyong He 		RTE_PTYPE_L4_UDP,
138211e9eae4SChaoyong He 		RTE_PTYPE_L4_FRAG,
138311e9eae4SChaoyong He 		RTE_PTYPE_L4_NONFRAG,
138411e9eae4SChaoyong He 		RTE_PTYPE_L4_ICMP,
138511e9eae4SChaoyong He 		RTE_PTYPE_L4_SCTP,
138611e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_VXLAN,
138711e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_NVGRE,
138811e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_GENEVE,
138911e9eae4SChaoyong He 		RTE_PTYPE_INNER_L2_ETHER,
139011e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4,
139111e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4_EXT,
139211e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6,
139311e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6_EXT,
139411e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
139511e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
139611e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_TCP,
139711e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_UDP,
139811e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_FRAG,
139911e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_NONFRAG,
140011e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_ICMP,
140111e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_SCTP,
140211e9eae4SChaoyong He 	};
140311e9eae4SChaoyong He 
140411e9eae4SChaoyong He 	if (dev->rx_pkt_burst != nfp_net_recv_pkts)
140511e9eae4SChaoyong He 		return NULL;
140611e9eae4SChaoyong He 
140711e9eae4SChaoyong He 	net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
140875a76c73SChaoyong He 	if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
140911e9eae4SChaoyong He 		return NULL;
141011e9eae4SChaoyong He 
141111e9eae4SChaoyong He 	return ptypes;
141211e9eae4SChaoyong He }
141311e9eae4SChaoyong He 
141411e9eae4SChaoyong He int
141511e9eae4SChaoyong He nfp_rx_queue_intr_enable(struct rte_eth_dev *dev,
141611e9eae4SChaoyong He 		uint16_t queue_id)
141711e9eae4SChaoyong He {
141811e9eae4SChaoyong He 	uint16_t base = 0;
141911e9eae4SChaoyong He 	struct nfp_net_hw *hw;
142011e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
142111e9eae4SChaoyong He 
142211e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
142311e9eae4SChaoyong He 	if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO)
142411e9eae4SChaoyong He 		base = 1;
142511e9eae4SChaoyong He 
142611e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
142711e9eae4SChaoyong He 	rte_wmb();
142811e9eae4SChaoyong He 
142911e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1430f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id),
143111e9eae4SChaoyong He 			NFP_NET_CFG_ICR_UNMASKED);
143211e9eae4SChaoyong He 	return 0;
143311e9eae4SChaoyong He }
143411e9eae4SChaoyong He 
143511e9eae4SChaoyong He int
143611e9eae4SChaoyong He nfp_rx_queue_intr_disable(struct rte_eth_dev *dev,
143711e9eae4SChaoyong He 		uint16_t queue_id)
143811e9eae4SChaoyong He {
143911e9eae4SChaoyong He 	uint16_t base = 0;
144011e9eae4SChaoyong He 	struct nfp_net_hw *hw;
144111e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
144211e9eae4SChaoyong He 
144311e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
144411e9eae4SChaoyong He 	if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO)
144511e9eae4SChaoyong He 		base = 1;
144611e9eae4SChaoyong He 
144711e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
144811e9eae4SChaoyong He 	rte_wmb();
144911e9eae4SChaoyong He 
145011e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1451f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), NFP_NET_CFG_ICR_RXTX);
145211e9eae4SChaoyong He 
145311e9eae4SChaoyong He 	return 0;
145411e9eae4SChaoyong He }
145511e9eae4SChaoyong He 
145611e9eae4SChaoyong He static void
145711e9eae4SChaoyong He nfp_net_dev_link_status_print(struct rte_eth_dev *dev)
145811e9eae4SChaoyong He {
145911e9eae4SChaoyong He 	struct rte_eth_link link;
146011e9eae4SChaoyong He 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
146111e9eae4SChaoyong He 
146211e9eae4SChaoyong He 	rte_eth_linkstatus_get(dev, &link);
146311e9eae4SChaoyong He 	if (link.link_status != 0)
146411e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s",
146511e9eae4SChaoyong He 				dev->data->port_id, link.link_speed,
146611e9eae4SChaoyong He 				link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX ?
146711e9eae4SChaoyong He 				"full-duplex" : "half-duplex");
146811e9eae4SChaoyong He 	else
146911e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, " Port %d: Link Down", dev->data->port_id);
147011e9eae4SChaoyong He 
147111e9eae4SChaoyong He 	PMD_DRV_LOG(INFO, "PCI Address: " PCI_PRI_FMT,
147211e9eae4SChaoyong He 			pci_dev->addr.domain, pci_dev->addr.bus,
147311e9eae4SChaoyong He 			pci_dev->addr.devid, pci_dev->addr.function);
147411e9eae4SChaoyong He }
147511e9eae4SChaoyong He 
147611e9eae4SChaoyong He /*
147711e9eae4SChaoyong He  * Unmask an interrupt
147811e9eae4SChaoyong He  *
147911e9eae4SChaoyong He  * If MSI-X auto-masking is enabled clear the mask bit, otherwise
148011e9eae4SChaoyong He  * clear the ICR for the entry.
148111e9eae4SChaoyong He  */
148211e9eae4SChaoyong He static void
148311e9eae4SChaoyong He nfp_net_irq_unmask(struct rte_eth_dev *dev)
148411e9eae4SChaoyong He {
148511e9eae4SChaoyong He 	struct nfp_net_hw *hw;
148611e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
148711e9eae4SChaoyong He 
148811e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
148911e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
149011e9eae4SChaoyong He 
149111e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
149211e9eae4SChaoyong He 	rte_wmb();
149311e9eae4SChaoyong He 
1494b4b6988aSChaoyong He 	if ((hw->super.ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) != 0) {
149511e9eae4SChaoyong He 		/* If MSI-X auto-masking is used, clear the entry */
149611e9eae4SChaoyong He 		rte_intr_ack(pci_dev->intr_handle);
149711e9eae4SChaoyong He 	} else {
1498f58bde00SChaoyong He 		nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(NFP_NET_IRQ_LSC_IDX),
149911e9eae4SChaoyong He 				NFP_NET_CFG_ICR_UNMASKED);
150011e9eae4SChaoyong He 	}
150111e9eae4SChaoyong He }
150211e9eae4SChaoyong He 
150311e9eae4SChaoyong He /**
150411e9eae4SChaoyong He  * Interrupt handler which shall be registered for alarm callback for delayed
150511e9eae4SChaoyong He  * handling specific interrupt to wait for the stable nic state. As the NIC
150611e9eae4SChaoyong He  * interrupt state is not stable for nfp after link is just down, it needs
150711e9eae4SChaoyong He  * to wait 4 seconds to get the stable status.
150811e9eae4SChaoyong He  *
150911e9eae4SChaoyong He  * @param param
151011e9eae4SChaoyong He  *   The address of parameter (struct rte_eth_dev *)
151111e9eae4SChaoyong He  */
151211e9eae4SChaoyong He void
151311e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler(void *param)
151411e9eae4SChaoyong He {
151511e9eae4SChaoyong He 	struct rte_eth_dev *dev = param;
151611e9eae4SChaoyong He 
151711e9eae4SChaoyong He 	nfp_net_link_update(dev, 0);
151811e9eae4SChaoyong He 	rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
151911e9eae4SChaoyong He 
152011e9eae4SChaoyong He 	nfp_net_dev_link_status_print(dev);
152111e9eae4SChaoyong He 
152211e9eae4SChaoyong He 	/* Unmasking */
152311e9eae4SChaoyong He 	nfp_net_irq_unmask(dev);
152411e9eae4SChaoyong He }
152511e9eae4SChaoyong He 
152611e9eae4SChaoyong He void
152711e9eae4SChaoyong He nfp_net_dev_interrupt_handler(void *param)
152811e9eae4SChaoyong He {
152911e9eae4SChaoyong He 	int64_t timeout;
153011e9eae4SChaoyong He 	struct rte_eth_link link;
153111e9eae4SChaoyong He 	struct rte_eth_dev *dev = param;
153211e9eae4SChaoyong He 
153311e9eae4SChaoyong He 	PMD_DRV_LOG(DEBUG, "We got a LSC interrupt!!!");
153411e9eae4SChaoyong He 
153511e9eae4SChaoyong He 	rte_eth_linkstatus_get(dev, &link);
153611e9eae4SChaoyong He 
153711e9eae4SChaoyong He 	nfp_net_link_update(dev, 0);
153811e9eae4SChaoyong He 
153911e9eae4SChaoyong He 	/* Likely to up */
154011e9eae4SChaoyong He 	if (link.link_status == 0) {
154111e9eae4SChaoyong He 		/* Handle it 1 sec later, wait it being stable */
154211e9eae4SChaoyong He 		timeout = NFP_NET_LINK_UP_CHECK_TIMEOUT;
154311e9eae4SChaoyong He 	} else {  /* Likely to down */
154411e9eae4SChaoyong He 		/* Handle it 4 sec later, wait it being stable */
154511e9eae4SChaoyong He 		timeout = NFP_NET_LINK_DOWN_CHECK_TIMEOUT;
154611e9eae4SChaoyong He 	}
154711e9eae4SChaoyong He 
154811e9eae4SChaoyong He 	if (rte_eal_alarm_set(timeout * 1000,
154911e9eae4SChaoyong He 			nfp_net_dev_interrupt_delayed_handler,
155011e9eae4SChaoyong He 			(void *)dev) != 0) {
155111e9eae4SChaoyong He 		PMD_INIT_LOG(ERR, "Error setting alarm");
155211e9eae4SChaoyong He 		/* Unmasking */
155311e9eae4SChaoyong He 		nfp_net_irq_unmask(dev);
155411e9eae4SChaoyong He 	}
155511e9eae4SChaoyong He }
155611e9eae4SChaoyong He 
155711e9eae4SChaoyong He int
155811e9eae4SChaoyong He nfp_net_dev_mtu_set(struct rte_eth_dev *dev,
155911e9eae4SChaoyong He 		uint16_t mtu)
156011e9eae4SChaoyong He {
156111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
156211e9eae4SChaoyong He 
156311e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
156411e9eae4SChaoyong He 
156511e9eae4SChaoyong He 	/* MTU setting is forbidden if port is started */
156611e9eae4SChaoyong He 	if (dev->data->dev_started) {
156711e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "port %d must be stopped before configuration",
156811e9eae4SChaoyong He 				dev->data->port_id);
156911e9eae4SChaoyong He 		return -EBUSY;
157011e9eae4SChaoyong He 	}
157111e9eae4SChaoyong He 
157211e9eae4SChaoyong He 	/* MTU larger than current mbufsize not supported */
157311e9eae4SChaoyong He 	if (mtu > hw->flbufsz) {
157411e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "MTU (%u) larger than current mbufsize (%u) not supported",
157511e9eae4SChaoyong He 				mtu, hw->flbufsz);
157611e9eae4SChaoyong He 		return -ERANGE;
157711e9eae4SChaoyong He 	}
157811e9eae4SChaoyong He 
157911e9eae4SChaoyong He 	/* Writing to configuration space */
1580f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, mtu);
158111e9eae4SChaoyong He 
158211e9eae4SChaoyong He 	hw->mtu = mtu;
158311e9eae4SChaoyong He 
158411e9eae4SChaoyong He 	return 0;
158511e9eae4SChaoyong He }
158611e9eae4SChaoyong He 
158711e9eae4SChaoyong He int
158811e9eae4SChaoyong He nfp_net_vlan_offload_set(struct rte_eth_dev *dev,
158911e9eae4SChaoyong He 		int mask)
159011e9eae4SChaoyong He {
159111e9eae4SChaoyong He 	int ret;
159211e9eae4SChaoyong He 	uint32_t update;
159311e9eae4SChaoyong He 	uint32_t new_ctrl;
1594*72d1dea6SChaoyong He 	struct nfp_hw *hw;
159511e9eae4SChaoyong He 	uint64_t rx_offload;
1596*72d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
159711e9eae4SChaoyong He 	uint32_t rxvlan_ctrl = 0;
159811e9eae4SChaoyong He 
1599*72d1dea6SChaoyong He 	net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1600*72d1dea6SChaoyong He 	hw = &net_hw->super;
1601*72d1dea6SChaoyong He 
160211e9eae4SChaoyong He 	rx_offload = dev->data->dev_conf.rxmode.offloads;
1603*72d1dea6SChaoyong He 	new_ctrl = hw->ctrl;
160411e9eae4SChaoyong He 
160511e9eae4SChaoyong He 	/* VLAN stripping setting */
160611e9eae4SChaoyong He 	if ((mask & RTE_ETH_VLAN_STRIP_MASK) != 0) {
1607*72d1dea6SChaoyong He 		nfp_net_enable_rxvlan_cap(net_hw, &rxvlan_ctrl);
160811e9eae4SChaoyong He 		if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0)
160911e9eae4SChaoyong He 			new_ctrl |= rxvlan_ctrl;
161011e9eae4SChaoyong He 		else
161111e9eae4SChaoyong He 			new_ctrl &= ~rxvlan_ctrl;
161211e9eae4SChaoyong He 	}
161311e9eae4SChaoyong He 
161411e9eae4SChaoyong He 	/* QinQ stripping setting */
161511e9eae4SChaoyong He 	if ((mask & RTE_ETH_QINQ_STRIP_MASK) != 0) {
161611e9eae4SChaoyong He 		if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0)
161711e9eae4SChaoyong He 			new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
161811e9eae4SChaoyong He 		else
161911e9eae4SChaoyong He 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ;
162011e9eae4SChaoyong He 	}
162111e9eae4SChaoyong He 
1622*72d1dea6SChaoyong He 	if (new_ctrl == hw->ctrl)
162311e9eae4SChaoyong He 		return 0;
162411e9eae4SChaoyong He 
162511e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
162611e9eae4SChaoyong He 
1627*72d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
162811e9eae4SChaoyong He 	if (ret != 0)
162911e9eae4SChaoyong He 		return ret;
163011e9eae4SChaoyong He 
1631*72d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
163211e9eae4SChaoyong He 
163311e9eae4SChaoyong He 	return 0;
163411e9eae4SChaoyong He }
163511e9eae4SChaoyong He 
163611e9eae4SChaoyong He static int
163711e9eae4SChaoyong He nfp_net_rss_reta_write(struct rte_eth_dev *dev,
163811e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
163911e9eae4SChaoyong He 		uint16_t reta_size)
164011e9eae4SChaoyong He {
164111e9eae4SChaoyong He 	uint16_t i;
164211e9eae4SChaoyong He 	uint16_t j;
164311e9eae4SChaoyong He 	uint16_t idx;
164411e9eae4SChaoyong He 	uint8_t mask;
164511e9eae4SChaoyong He 	uint32_t reta;
164611e9eae4SChaoyong He 	uint16_t shift;
164711e9eae4SChaoyong He 	struct nfp_net_hw *hw;
164811e9eae4SChaoyong He 
164911e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
165011e9eae4SChaoyong He 
165111e9eae4SChaoyong He 	if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) {
165211e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%hu)"
165311e9eae4SChaoyong He 				" doesn't match hardware can supported (%d)",
165411e9eae4SChaoyong He 				reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
165511e9eae4SChaoyong He 		return -EINVAL;
165611e9eae4SChaoyong He 	}
165711e9eae4SChaoyong He 
165811e9eae4SChaoyong He 	/*
165911e9eae4SChaoyong He 	 * Update Redirection Table. There are 128 8bit-entries which can be
166011e9eae4SChaoyong He 	 * manage as 32 32bit-entries.
166111e9eae4SChaoyong He 	 */
166211e9eae4SChaoyong He 	for (i = 0; i < reta_size; i += 4) {
166311e9eae4SChaoyong He 		/* Handling 4 RSS entries per loop */
166411e9eae4SChaoyong He 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
166511e9eae4SChaoyong He 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
166611e9eae4SChaoyong He 		mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF);
166711e9eae4SChaoyong He 		if (mask == 0)
166811e9eae4SChaoyong He 			continue;
166911e9eae4SChaoyong He 
167011e9eae4SChaoyong He 		reta = 0;
167111e9eae4SChaoyong He 
167211e9eae4SChaoyong He 		/* If all 4 entries were set, don't need read RETA register */
167311e9eae4SChaoyong He 		if (mask != 0xF)
1674f58bde00SChaoyong He 			reta = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_ITBL + i);
167511e9eae4SChaoyong He 
167611e9eae4SChaoyong He 		for (j = 0; j < 4; j++) {
167711e9eae4SChaoyong He 			if ((mask & (0x1 << j)) == 0)
167811e9eae4SChaoyong He 				continue;
167911e9eae4SChaoyong He 
168011e9eae4SChaoyong He 			/* Clearing the entry bits */
168111e9eae4SChaoyong He 			if (mask != 0xF)
168211e9eae4SChaoyong He 				reta &= ~(0xFF << (8 * j));
168311e9eae4SChaoyong He 
168411e9eae4SChaoyong He 			reta |= reta_conf[idx].reta[shift + j] << (8 * j);
168511e9eae4SChaoyong He 		}
168611e9eae4SChaoyong He 
1687f58bde00SChaoyong He 		nn_cfg_writel(&hw->super, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift, reta);
168811e9eae4SChaoyong He 	}
168911e9eae4SChaoyong He 
169011e9eae4SChaoyong He 	return 0;
169111e9eae4SChaoyong He }
169211e9eae4SChaoyong He 
169311e9eae4SChaoyong He /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
169411e9eae4SChaoyong He int
169511e9eae4SChaoyong He nfp_net_reta_update(struct rte_eth_dev *dev,
169611e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
169711e9eae4SChaoyong He 		uint16_t reta_size)
169811e9eae4SChaoyong He {
169911e9eae4SChaoyong He 	int ret;
170011e9eae4SChaoyong He 	uint32_t update;
1701*72d1dea6SChaoyong He 	struct nfp_hw *hw;
1702*72d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
170311e9eae4SChaoyong He 
1704*72d1dea6SChaoyong He 	net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1705*72d1dea6SChaoyong He 	hw = &net_hw->super;
1706*72d1dea6SChaoyong He 
1707*72d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
170811e9eae4SChaoyong He 		return -EINVAL;
170911e9eae4SChaoyong He 
171011e9eae4SChaoyong He 	ret = nfp_net_rss_reta_write(dev, reta_conf, reta_size);
171111e9eae4SChaoyong He 	if (ret != 0)
171211e9eae4SChaoyong He 		return ret;
171311e9eae4SChaoyong He 
171411e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_RSS;
171511e9eae4SChaoyong He 
1716*72d1dea6SChaoyong He 	if (nfp_reconfig(hw, hw->ctrl, update) != 0)
171711e9eae4SChaoyong He 		return -EIO;
171811e9eae4SChaoyong He 
171911e9eae4SChaoyong He 	return 0;
172011e9eae4SChaoyong He }
172111e9eae4SChaoyong He 
172211e9eae4SChaoyong He /* Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. */
172311e9eae4SChaoyong He int
172411e9eae4SChaoyong He nfp_net_reta_query(struct rte_eth_dev *dev,
172511e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
172611e9eae4SChaoyong He 		uint16_t reta_size)
172711e9eae4SChaoyong He {
172811e9eae4SChaoyong He 	uint16_t i;
172911e9eae4SChaoyong He 	uint16_t j;
173011e9eae4SChaoyong He 	uint16_t idx;
173111e9eae4SChaoyong He 	uint8_t mask;
173211e9eae4SChaoyong He 	uint32_t reta;
173311e9eae4SChaoyong He 	uint16_t shift;
173411e9eae4SChaoyong He 	struct nfp_net_hw *hw;
173511e9eae4SChaoyong He 
173611e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1737b4b6988aSChaoyong He 	if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
173811e9eae4SChaoyong He 		return -EINVAL;
173911e9eae4SChaoyong He 
174011e9eae4SChaoyong He 	if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) {
174111e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d)"
174211e9eae4SChaoyong He 				" doesn't match hardware can supported (%d)",
174311e9eae4SChaoyong He 				reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
174411e9eae4SChaoyong He 		return -EINVAL;
174511e9eae4SChaoyong He 	}
174611e9eae4SChaoyong He 
174711e9eae4SChaoyong He 	/*
174811e9eae4SChaoyong He 	 * Reading Redirection Table. There are 128 8bit-entries which can be
174911e9eae4SChaoyong He 	 * manage as 32 32bit-entries.
175011e9eae4SChaoyong He 	 */
175111e9eae4SChaoyong He 	for (i = 0; i < reta_size; i += 4) {
175211e9eae4SChaoyong He 		/* Handling 4 RSS entries per loop */
175311e9eae4SChaoyong He 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
175411e9eae4SChaoyong He 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
175511e9eae4SChaoyong He 		mask = (reta_conf[idx].mask >> shift) & 0xF;
175611e9eae4SChaoyong He 
175711e9eae4SChaoyong He 		if (mask == 0)
175811e9eae4SChaoyong He 			continue;
175911e9eae4SChaoyong He 
1760f58bde00SChaoyong He 		reta = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift);
176111e9eae4SChaoyong He 		for (j = 0; j < 4; j++) {
176211e9eae4SChaoyong He 			if ((mask & (0x1 << j)) == 0)
176311e9eae4SChaoyong He 				continue;
176411e9eae4SChaoyong He 
176511e9eae4SChaoyong He 			reta_conf[idx].reta[shift + j] =
176611e9eae4SChaoyong He 					(uint8_t)((reta >> (8 * j)) & 0xF);
176711e9eae4SChaoyong He 		}
176811e9eae4SChaoyong He 	}
176911e9eae4SChaoyong He 
177011e9eae4SChaoyong He 	return 0;
177111e9eae4SChaoyong He }
177211e9eae4SChaoyong He 
177311e9eae4SChaoyong He static int
177411e9eae4SChaoyong He nfp_net_rss_hash_write(struct rte_eth_dev *dev,
177511e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
177611e9eae4SChaoyong He {
177711e9eae4SChaoyong He 	uint8_t i;
177811e9eae4SChaoyong He 	uint8_t key;
177911e9eae4SChaoyong He 	uint64_t rss_hf;
178011e9eae4SChaoyong He 	struct nfp_net_hw *hw;
178111e9eae4SChaoyong He 	uint32_t cfg_rss_ctrl = 0;
178211e9eae4SChaoyong He 
178311e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
178411e9eae4SChaoyong He 
178511e9eae4SChaoyong He 	/* Writing the key byte by byte */
178611e9eae4SChaoyong He 	for (i = 0; i < rss_conf->rss_key_len; i++) {
178711e9eae4SChaoyong He 		memcpy(&key, &rss_conf->rss_key[i], 1);
1788f58bde00SChaoyong He 		nn_cfg_writeb(&hw->super, NFP_NET_CFG_RSS_KEY + i, key);
178911e9eae4SChaoyong He 	}
179011e9eae4SChaoyong He 
179111e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
179211e9eae4SChaoyong He 
179311e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_IPV4) != 0)
179411e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4;
179511e9eae4SChaoyong He 
179611e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) != 0)
179711e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_TCP;
179811e9eae4SChaoyong He 
179911e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) != 0)
180011e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_UDP;
180111e9eae4SChaoyong He 
180211e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) != 0)
180311e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_SCTP;
180411e9eae4SChaoyong He 
180511e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_IPV6) != 0)
180611e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6;
180711e9eae4SChaoyong He 
180811e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) != 0)
180911e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_TCP;
181011e9eae4SChaoyong He 
181111e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) != 0)
181211e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_UDP;
181311e9eae4SChaoyong He 
181411e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) != 0)
181511e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_SCTP;
181611e9eae4SChaoyong He 
181711e9eae4SChaoyong He 	cfg_rss_ctrl |= NFP_NET_CFG_RSS_MASK;
181811e9eae4SChaoyong He 	cfg_rss_ctrl |= NFP_NET_CFG_RSS_TOEPLITZ;
181911e9eae4SChaoyong He 
182011e9eae4SChaoyong He 	/* Configuring where to apply the RSS hash */
1821f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_RSS_CTRL, cfg_rss_ctrl);
182211e9eae4SChaoyong He 
182311e9eae4SChaoyong He 	/* Writing the key size */
1824f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_RSS_KEY_SZ, rss_conf->rss_key_len);
182511e9eae4SChaoyong He 
182611e9eae4SChaoyong He 	return 0;
182711e9eae4SChaoyong He }
182811e9eae4SChaoyong He 
182911e9eae4SChaoyong He int
183011e9eae4SChaoyong He nfp_net_rss_hash_update(struct rte_eth_dev *dev,
183111e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
183211e9eae4SChaoyong He {
183311e9eae4SChaoyong He 	uint32_t update;
183411e9eae4SChaoyong He 	uint64_t rss_hf;
1835*72d1dea6SChaoyong He 	struct nfp_hw *hw;
1836*72d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
183711e9eae4SChaoyong He 
1838*72d1dea6SChaoyong He 	net_hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
1839*72d1dea6SChaoyong He 	hw = &net_hw->super;
184011e9eae4SChaoyong He 
184111e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
184211e9eae4SChaoyong He 
184311e9eae4SChaoyong He 	/* Checking if RSS is enabled */
1844*72d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) {
184511e9eae4SChaoyong He 		if (rss_hf != 0) {
184611e9eae4SChaoyong He 			PMD_DRV_LOG(ERR, "RSS unsupported");
184711e9eae4SChaoyong He 			return -EINVAL;
184811e9eae4SChaoyong He 		}
184911e9eae4SChaoyong He 
185011e9eae4SChaoyong He 		return 0; /* Nothing to do */
185111e9eae4SChaoyong He 	}
185211e9eae4SChaoyong He 
185311e9eae4SChaoyong He 	if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) {
185411e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "RSS hash key too long");
185511e9eae4SChaoyong He 		return -EINVAL;
185611e9eae4SChaoyong He 	}
185711e9eae4SChaoyong He 
185811e9eae4SChaoyong He 	nfp_net_rss_hash_write(dev, rss_conf);
185911e9eae4SChaoyong He 
186011e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_RSS;
186111e9eae4SChaoyong He 
1862*72d1dea6SChaoyong He 	if (nfp_reconfig(hw, hw->ctrl, update) != 0)
186311e9eae4SChaoyong He 		return -EIO;
186411e9eae4SChaoyong He 
186511e9eae4SChaoyong He 	return 0;
186611e9eae4SChaoyong He }
186711e9eae4SChaoyong He 
186811e9eae4SChaoyong He int
186911e9eae4SChaoyong He nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev,
187011e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
187111e9eae4SChaoyong He {
187211e9eae4SChaoyong He 	uint8_t i;
187311e9eae4SChaoyong He 	uint8_t key;
187411e9eae4SChaoyong He 	uint64_t rss_hf;
187511e9eae4SChaoyong He 	uint32_t cfg_rss_ctrl;
187611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
187711e9eae4SChaoyong He 
187811e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
187911e9eae4SChaoyong He 
1880b4b6988aSChaoyong He 	if ((hw->super.ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
188111e9eae4SChaoyong He 		return -EINVAL;
188211e9eae4SChaoyong He 
188311e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
1884f58bde00SChaoyong He 	cfg_rss_ctrl = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_CTRL);
188511e9eae4SChaoyong He 
188611e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4) != 0)
188711e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_IPV4;
188811e9eae4SChaoyong He 
188911e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_TCP) != 0)
189011e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
189111e9eae4SChaoyong He 
189211e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_TCP) != 0)
189311e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
189411e9eae4SChaoyong He 
189511e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_UDP) != 0)
189611e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
189711e9eae4SChaoyong He 
189811e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_UDP) != 0)
189911e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
190011e9eae4SChaoyong He 
190111e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6) != 0)
190211e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_IPV6;
190311e9eae4SChaoyong He 
190411e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_SCTP) != 0)
190511e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_SCTP;
190611e9eae4SChaoyong He 
190711e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_SCTP) != 0)
190811e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_SCTP;
190911e9eae4SChaoyong He 
191011e9eae4SChaoyong He 	/* Propagate current RSS hash functions to caller */
191111e9eae4SChaoyong He 	rss_conf->rss_hf = rss_hf;
191211e9eae4SChaoyong He 
191311e9eae4SChaoyong He 	/* Reading the key size */
1914f58bde00SChaoyong He 	rss_conf->rss_key_len = nn_cfg_readl(&hw->super, NFP_NET_CFG_RSS_KEY_SZ);
191511e9eae4SChaoyong He 
191611e9eae4SChaoyong He 	/* Reading the key byte a byte */
191711e9eae4SChaoyong He 	for (i = 0; i < rss_conf->rss_key_len; i++) {
1918f58bde00SChaoyong He 		key = nn_cfg_readb(&hw->super, NFP_NET_CFG_RSS_KEY + i);
191911e9eae4SChaoyong He 		memcpy(&rss_conf->rss_key[i], &key, 1);
192011e9eae4SChaoyong He 	}
192111e9eae4SChaoyong He 
192211e9eae4SChaoyong He 	return 0;
192311e9eae4SChaoyong He }
192411e9eae4SChaoyong He 
192511e9eae4SChaoyong He int
192611e9eae4SChaoyong He nfp_net_rss_config_default(struct rte_eth_dev *dev)
192711e9eae4SChaoyong He {
192811e9eae4SChaoyong He 	int ret;
192911e9eae4SChaoyong He 	uint8_t i;
193011e9eae4SChaoyong He 	uint8_t j;
193111e9eae4SChaoyong He 	uint16_t queue = 0;
193211e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
193311e9eae4SChaoyong He 	struct rte_eth_rss_conf rss_conf;
193411e9eae4SChaoyong He 	uint16_t rx_queues = dev->data->nb_rx_queues;
193511e9eae4SChaoyong He 	struct rte_eth_rss_reta_entry64 nfp_reta_conf[2];
193611e9eae4SChaoyong He 
193711e9eae4SChaoyong He 	nfp_reta_conf[0].mask = ~0x0;
193811e9eae4SChaoyong He 	nfp_reta_conf[1].mask = ~0x0;
193911e9eae4SChaoyong He 
194011e9eae4SChaoyong He 	for (i = 0; i < 0x40; i += 8) {
194111e9eae4SChaoyong He 		for (j = i; j < (i + 8); j++) {
194211e9eae4SChaoyong He 			nfp_reta_conf[0].reta[j] = queue;
194311e9eae4SChaoyong He 			nfp_reta_conf[1].reta[j] = queue++;
194411e9eae4SChaoyong He 			queue %= rx_queues;
194511e9eae4SChaoyong He 		}
194611e9eae4SChaoyong He 	}
194711e9eae4SChaoyong He 
194811e9eae4SChaoyong He 	ret = nfp_net_rss_reta_write(dev, nfp_reta_conf, 0x80);
194911e9eae4SChaoyong He 	if (ret != 0)
195011e9eae4SChaoyong He 		return ret;
195111e9eae4SChaoyong He 
195211e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
195311e9eae4SChaoyong He 	if (dev_conf == NULL) {
195411e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Wrong rss conf");
195511e9eae4SChaoyong He 		return -EINVAL;
195611e9eae4SChaoyong He 	}
195711e9eae4SChaoyong He 
195811e9eae4SChaoyong He 	rss_conf = dev_conf->rx_adv_conf.rss_conf;
195911e9eae4SChaoyong He 	ret = nfp_net_rss_hash_write(dev, &rss_conf);
196011e9eae4SChaoyong He 
196111e9eae4SChaoyong He 	return ret;
196211e9eae4SChaoyong He }
196311e9eae4SChaoyong He 
196411e9eae4SChaoyong He void
196511e9eae4SChaoyong He nfp_net_stop_rx_queue(struct rte_eth_dev *dev)
196611e9eae4SChaoyong He {
196711e9eae4SChaoyong He 	uint16_t i;
196811e9eae4SChaoyong He 	struct nfp_net_rxq *this_rx_q;
196911e9eae4SChaoyong He 
197011e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
197111e9eae4SChaoyong He 		this_rx_q = dev->data->rx_queues[i];
197211e9eae4SChaoyong He 		nfp_net_reset_rx_queue(this_rx_q);
197311e9eae4SChaoyong He 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
197411e9eae4SChaoyong He 	}
197511e9eae4SChaoyong He }
197611e9eae4SChaoyong He 
197711e9eae4SChaoyong He void
197811e9eae4SChaoyong He nfp_net_close_rx_queue(struct rte_eth_dev *dev)
197911e9eae4SChaoyong He {
198011e9eae4SChaoyong He 	uint16_t i;
198111e9eae4SChaoyong He 	struct nfp_net_rxq *this_rx_q;
198211e9eae4SChaoyong He 
198311e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
198411e9eae4SChaoyong He 		this_rx_q = dev->data->rx_queues[i];
198511e9eae4SChaoyong He 		nfp_net_reset_rx_queue(this_rx_q);
198611e9eae4SChaoyong He 		nfp_net_rx_queue_release(dev, i);
198711e9eae4SChaoyong He 	}
198811e9eae4SChaoyong He }
198911e9eae4SChaoyong He 
199011e9eae4SChaoyong He void
199111e9eae4SChaoyong He nfp_net_stop_tx_queue(struct rte_eth_dev *dev)
199211e9eae4SChaoyong He {
199311e9eae4SChaoyong He 	uint16_t i;
199411e9eae4SChaoyong He 	struct nfp_net_txq *this_tx_q;
199511e9eae4SChaoyong He 
199611e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
199711e9eae4SChaoyong He 		this_tx_q = dev->data->tx_queues[i];
199811e9eae4SChaoyong He 		nfp_net_reset_tx_queue(this_tx_q);
199911e9eae4SChaoyong He 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
200011e9eae4SChaoyong He 	}
200111e9eae4SChaoyong He }
200211e9eae4SChaoyong He 
200311e9eae4SChaoyong He void
200411e9eae4SChaoyong He nfp_net_close_tx_queue(struct rte_eth_dev *dev)
200511e9eae4SChaoyong He {
200611e9eae4SChaoyong He 	uint16_t i;
200711e9eae4SChaoyong He 	struct nfp_net_txq *this_tx_q;
200811e9eae4SChaoyong He 
200911e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
201011e9eae4SChaoyong He 		this_tx_q = dev->data->tx_queues[i];
201111e9eae4SChaoyong He 		nfp_net_reset_tx_queue(this_tx_q);
201211e9eae4SChaoyong He 		nfp_net_tx_queue_release(dev, i);
201311e9eae4SChaoyong He 	}
201411e9eae4SChaoyong He }
201511e9eae4SChaoyong He 
201611e9eae4SChaoyong He int
2017*72d1dea6SChaoyong He nfp_net_set_vxlan_port(struct nfp_net_hw *net_hw,
201811e9eae4SChaoyong He 		size_t idx,
201911e9eae4SChaoyong He 		uint16_t port)
202011e9eae4SChaoyong He {
202111e9eae4SChaoyong He 	int ret;
202211e9eae4SChaoyong He 	uint32_t i;
2023*72d1dea6SChaoyong He 	struct nfp_hw *hw = &net_hw->super;
202411e9eae4SChaoyong He 
202511e9eae4SChaoyong He 	if (idx >= NFP_NET_N_VXLAN_PORTS) {
202611e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The idx value is out of range.");
202711e9eae4SChaoyong He 		return -ERANGE;
202811e9eae4SChaoyong He 	}
202911e9eae4SChaoyong He 
2030*72d1dea6SChaoyong He 	net_hw->vxlan_ports[idx] = port;
203111e9eae4SChaoyong He 
203211e9eae4SChaoyong He 	for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) {
2033*72d1dea6SChaoyong He 		nn_cfg_writel(hw, NFP_NET_CFG_VXLAN_PORT + i * sizeof(port),
2034*72d1dea6SChaoyong He 				(net_hw->vxlan_ports[i + 1] << 16) | net_hw->vxlan_ports[i]);
203511e9eae4SChaoyong He 	}
203611e9eae4SChaoyong He 
203711e9eae4SChaoyong He 	rte_spinlock_lock(&hw->reconfig_lock);
203811e9eae4SChaoyong He 
2039*72d1dea6SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_VXLAN);
204011e9eae4SChaoyong He 	rte_wmb();
204111e9eae4SChaoyong He 
2042*72d1dea6SChaoyong He 	ret = nfp_reconfig_real(hw, NFP_NET_CFG_UPDATE_VXLAN);
204311e9eae4SChaoyong He 
204411e9eae4SChaoyong He 	rte_spinlock_unlock(&hw->reconfig_lock);
204511e9eae4SChaoyong He 
204611e9eae4SChaoyong He 	return ret;
204711e9eae4SChaoyong He }
204811e9eae4SChaoyong He 
204911e9eae4SChaoyong He /*
205011e9eae4SChaoyong He  * The firmware with NFD3 can not handle DMA address requiring more
205111e9eae4SChaoyong He  * than 40 bits.
205211e9eae4SChaoyong He  */
205311e9eae4SChaoyong He int
205411e9eae4SChaoyong He nfp_net_check_dma_mask(struct nfp_net_hw *hw,
205511e9eae4SChaoyong He 		char *name)
205611e9eae4SChaoyong He {
205711e9eae4SChaoyong He 	if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3 &&
205811e9eae4SChaoyong He 			rte_mem_check_dma_mask(40) != 0) {
205911e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Device %s can't be used: restricted dma mask to 40 bits!",
206011e9eae4SChaoyong He 				name);
206111e9eae4SChaoyong He 		return -ENODEV;
206211e9eae4SChaoyong He 	}
206311e9eae4SChaoyong He 
206411e9eae4SChaoyong He 	return 0;
206511e9eae4SChaoyong He }
206611e9eae4SChaoyong He 
206711e9eae4SChaoyong He void
206811e9eae4SChaoyong He nfp_net_init_metadata_format(struct nfp_net_hw *hw)
206911e9eae4SChaoyong He {
207011e9eae4SChaoyong He 	/*
207111e9eae4SChaoyong He 	 * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of
207211e9eae4SChaoyong He 	 * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2)
207311e9eae4SChaoyong He 	 * also indicate that we are using chained metadata.
207411e9eae4SChaoyong He 	 */
207511e9eae4SChaoyong He 	if (hw->ver.major == 4) {
207611e9eae4SChaoyong He 		hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
207775a76c73SChaoyong He 	} else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) {
207811e9eae4SChaoyong He 		hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
207911e9eae4SChaoyong He 		/*
208075a76c73SChaoyong He 		 * RSS is incompatible with chained metadata. hw->super.cap just represents
208111e9eae4SChaoyong He 		 * firmware's ability rather than the firmware's configuration. We decide
208275a76c73SChaoyong He 		 * to reduce the confusion to allow us can use hw->super.cap to identify RSS later.
208311e9eae4SChaoyong He 		 */
208475a76c73SChaoyong He 		hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS;
208511e9eae4SChaoyong He 	} else {
208611e9eae4SChaoyong He 		hw->meta_format = NFP_NET_METAFORMAT_SINGLE;
208711e9eae4SChaoyong He 	}
208811e9eae4SChaoyong He }
208911e9eae4SChaoyong He 
209011e9eae4SChaoyong He void
209111e9eae4SChaoyong He nfp_net_cfg_read_version(struct nfp_net_hw *hw)
209211e9eae4SChaoyong He {
209311e9eae4SChaoyong He 	union {
209411e9eae4SChaoyong He 		uint32_t whole;
209511e9eae4SChaoyong He 		struct nfp_net_fw_ver split;
209611e9eae4SChaoyong He 	} version;
209711e9eae4SChaoyong He 
2098f58bde00SChaoyong He 	version.whole = nn_cfg_readl(&hw->super, NFP_NET_CFG_VERSION);
209911e9eae4SChaoyong He 	hw->ver = version.split;
210011e9eae4SChaoyong He }
210111e9eae4SChaoyong He 
210211e9eae4SChaoyong He static void
210311e9eae4SChaoyong He nfp_net_get_nsp_info(struct nfp_net_hw *hw,
210411e9eae4SChaoyong He 		char *nsp_version)
210511e9eae4SChaoyong He {
210611e9eae4SChaoyong He 	struct nfp_nsp *nsp;
210711e9eae4SChaoyong He 
210811e9eae4SChaoyong He 	nsp = nfp_nsp_open(hw->cpp);
210911e9eae4SChaoyong He 	if (nsp == NULL)
211011e9eae4SChaoyong He 		return;
211111e9eae4SChaoyong He 
211211e9eae4SChaoyong He 	snprintf(nsp_version, FW_VER_LEN, "%hu.%hu",
211311e9eae4SChaoyong He 			nfp_nsp_get_abi_ver_major(nsp),
211411e9eae4SChaoyong He 			nfp_nsp_get_abi_ver_minor(nsp));
211511e9eae4SChaoyong He 
211611e9eae4SChaoyong He 	nfp_nsp_close(nsp);
211711e9eae4SChaoyong He }
211811e9eae4SChaoyong He 
211911e9eae4SChaoyong He static void
212011e9eae4SChaoyong He nfp_net_get_mip_name(struct nfp_net_hw *hw,
212111e9eae4SChaoyong He 		char *mip_name)
212211e9eae4SChaoyong He {
212311e9eae4SChaoyong He 	struct nfp_mip *mip;
212411e9eae4SChaoyong He 
212511e9eae4SChaoyong He 	mip = nfp_mip_open(hw->cpp);
212611e9eae4SChaoyong He 	if (mip == NULL)
212711e9eae4SChaoyong He 		return;
212811e9eae4SChaoyong He 
212911e9eae4SChaoyong He 	snprintf(mip_name, FW_VER_LEN, "%s", nfp_mip_name(mip));
213011e9eae4SChaoyong He 
213111e9eae4SChaoyong He 	nfp_mip_close(mip);
213211e9eae4SChaoyong He }
213311e9eae4SChaoyong He 
213411e9eae4SChaoyong He static void
213511e9eae4SChaoyong He nfp_net_get_app_name(struct nfp_net_hw *hw,
213611e9eae4SChaoyong He 		char *app_name)
213711e9eae4SChaoyong He {
213811e9eae4SChaoyong He 	switch (hw->pf_dev->app_fw_id) {
213911e9eae4SChaoyong He 	case NFP_APP_FW_CORE_NIC:
214011e9eae4SChaoyong He 		snprintf(app_name, FW_VER_LEN, "%s", "nic");
214111e9eae4SChaoyong He 		break;
214211e9eae4SChaoyong He 	case NFP_APP_FW_FLOWER_NIC:
214311e9eae4SChaoyong He 		snprintf(app_name, FW_VER_LEN, "%s", "flower");
214411e9eae4SChaoyong He 		break;
214511e9eae4SChaoyong He 	default:
214611e9eae4SChaoyong He 		snprintf(app_name, FW_VER_LEN, "%s", "unknown");
214711e9eae4SChaoyong He 		break;
214811e9eae4SChaoyong He 	}
214911e9eae4SChaoyong He }
215011e9eae4SChaoyong He 
215111e9eae4SChaoyong He int
215211e9eae4SChaoyong He nfp_net_firmware_version_get(struct rte_eth_dev *dev,
215311e9eae4SChaoyong He 		char *fw_version,
215411e9eae4SChaoyong He 		size_t fw_size)
215511e9eae4SChaoyong He {
215611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
215711e9eae4SChaoyong He 	char mip_name[FW_VER_LEN];
215811e9eae4SChaoyong He 	char app_name[FW_VER_LEN];
215911e9eae4SChaoyong He 	char nsp_version[FW_VER_LEN];
216011e9eae4SChaoyong He 	char vnic_version[FW_VER_LEN];
216111e9eae4SChaoyong He 
216211e9eae4SChaoyong He 	if (fw_size < FW_VER_LEN)
216311e9eae4SChaoyong He 		return FW_VER_LEN;
216411e9eae4SChaoyong He 
216511e9eae4SChaoyong He 	hw = NFP_NET_DEV_PRIVATE_TO_HW(dev->data->dev_private);
216611e9eae4SChaoyong He 
216711e9eae4SChaoyong He 	snprintf(vnic_version, FW_VER_LEN, "%d.%d.%d.%d",
216811e9eae4SChaoyong He 			hw->ver.extend, hw->ver.class,
216911e9eae4SChaoyong He 			hw->ver.major, hw->ver.minor);
217011e9eae4SChaoyong He 
217111e9eae4SChaoyong He 	nfp_net_get_nsp_info(hw, nsp_version);
217211e9eae4SChaoyong He 	nfp_net_get_mip_name(hw, mip_name);
217311e9eae4SChaoyong He 	nfp_net_get_app_name(hw, app_name);
217411e9eae4SChaoyong He 
217511e9eae4SChaoyong He 	snprintf(fw_version, FW_VER_LEN, "%s %s %s %s",
217611e9eae4SChaoyong He 			vnic_version, nsp_version, mip_name, app_name);
217711e9eae4SChaoyong He 
217811e9eae4SChaoyong He 	return 0;
217911e9eae4SChaoyong He }
218011e9eae4SChaoyong He 
218111e9eae4SChaoyong He int
218211e9eae4SChaoyong He nfp_repr_firmware_version_get(struct rte_eth_dev *dev,
218311e9eae4SChaoyong He 		char *fw_version,
218411e9eae4SChaoyong He 		size_t fw_size)
218511e9eae4SChaoyong He {
218611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
218711e9eae4SChaoyong He 	char mip_name[FW_VER_LEN];
218811e9eae4SChaoyong He 	char app_name[FW_VER_LEN];
218911e9eae4SChaoyong He 	char nsp_version[FW_VER_LEN];
219011e9eae4SChaoyong He 	struct nfp_flower_representor *repr;
219111e9eae4SChaoyong He 
219211e9eae4SChaoyong He 	if (fw_size < FW_VER_LEN)
219311e9eae4SChaoyong He 		return FW_VER_LEN;
219411e9eae4SChaoyong He 
219511e9eae4SChaoyong He 	repr = dev->data->dev_private;
219611e9eae4SChaoyong He 	hw = repr->app_fw_flower->pf_hw;
219711e9eae4SChaoyong He 
219811e9eae4SChaoyong He 	nfp_net_get_nsp_info(hw, nsp_version);
219911e9eae4SChaoyong He 	nfp_net_get_mip_name(hw, mip_name);
220011e9eae4SChaoyong He 	nfp_net_get_app_name(hw, app_name);
220111e9eae4SChaoyong He 
220211e9eae4SChaoyong He 	snprintf(fw_version, FW_VER_LEN, "* %s %s %s",
220311e9eae4SChaoyong He 			nsp_version, mip_name, app_name);
220411e9eae4SChaoyong He 
220511e9eae4SChaoyong He 	return 0;
220611e9eae4SChaoyong He }
220711e9eae4SChaoyong He 
220811e9eae4SChaoyong He bool
220911e9eae4SChaoyong He nfp_net_is_valid_nfd_version(struct nfp_net_fw_ver version)
221011e9eae4SChaoyong He {
221111e9eae4SChaoyong He 	uint8_t nfd_version = version.extend;
221211e9eae4SChaoyong He 
221311e9eae4SChaoyong He 	if (nfd_version == NFP_NET_CFG_VERSION_DP_NFD3)
221411e9eae4SChaoyong He 		return true;
221511e9eae4SChaoyong He 
221611e9eae4SChaoyong He 	if (nfd_version == NFP_NET_CFG_VERSION_DP_NFDK) {
221711e9eae4SChaoyong He 		if (version.major < 5) {
221811e9eae4SChaoyong He 			PMD_INIT_LOG(ERR, "NFDK must use ABI 5 or newer, found: %d",
221911e9eae4SChaoyong He 					version.major);
222011e9eae4SChaoyong He 			return false;
222111e9eae4SChaoyong He 		}
222211e9eae4SChaoyong He 
222311e9eae4SChaoyong He 		return true;
222411e9eae4SChaoyong He 	}
222511e9eae4SChaoyong He 
222611e9eae4SChaoyong He 	return false;
222711e9eae4SChaoyong He }
2228