xref: /dpdk/drivers/net/nfp/nfp_net_common.c (revision b458a2a045979f729a64ba59eff92fe7040e3b51)
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 #define NFP_NET_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */
2311e9eae4SChaoyong He #define NFP_NET_LINK_UP_CHECK_TIMEOUT   1000 /* ms */
2411e9eae4SChaoyong He 
2511e9eae4SChaoyong He #define DEFAULT_FLBUF_SIZE        9216
262f1bfbf4SJames Hershaw #define NFP_ETH_OVERHEAD \
272f1bfbf4SJames Hershaw 	(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + RTE_VLAN_HLEN * 2)
2811e9eae4SChaoyong He 
290786add9SZerun Fu /* Only show FEC capability supported by the current speed. */
300786add9SZerun Fu #define NFP_FEC_CAPA_ENTRY_NUM  1
310786add9SZerun Fu 
3211e9eae4SChaoyong He enum nfp_xstat_group {
3311e9eae4SChaoyong He 	NFP_XSTAT_GROUP_NET,
3411e9eae4SChaoyong He 	NFP_XSTAT_GROUP_MAC
3511e9eae4SChaoyong He };
3611e9eae4SChaoyong He 
3711e9eae4SChaoyong He struct nfp_xstat {
3811e9eae4SChaoyong He 	char name[RTE_ETH_XSTATS_NAME_SIZE];
3911e9eae4SChaoyong He 	int offset;
4011e9eae4SChaoyong He 	enum nfp_xstat_group group;
4111e9eae4SChaoyong He };
4211e9eae4SChaoyong He 
4311e9eae4SChaoyong He #define NFP_XSTAT_NET(_name, _offset) {                 \
4411e9eae4SChaoyong He 	.name = _name,                                  \
4511e9eae4SChaoyong He 	.offset = NFP_NET_CFG_STATS_##_offset,          \
4611e9eae4SChaoyong He 	.group = NFP_XSTAT_GROUP_NET,                   \
4711e9eae4SChaoyong He }
4811e9eae4SChaoyong He 
4911e9eae4SChaoyong He #define NFP_XSTAT_MAC(_name, _offset) {                 \
5011e9eae4SChaoyong He 	.name = _name,                                  \
5111e9eae4SChaoyong He 	.offset = NFP_MAC_STATS_##_offset,              \
5211e9eae4SChaoyong He 	.group = NFP_XSTAT_GROUP_MAC,                   \
5311e9eae4SChaoyong He }
5411e9eae4SChaoyong He 
5511e9eae4SChaoyong He static const struct nfp_xstat nfp_net_xstats[] = {
5611e9eae4SChaoyong He 	/*
5711e9eae4SChaoyong He 	 * Basic xstats available on both VF and PF.
5811e9eae4SChaoyong He 	 * Note that in case new statistics of group NFP_XSTAT_GROUP_NET
5911e9eae4SChaoyong He 	 * are added to this array, they must appear before any statistics
6011e9eae4SChaoyong He 	 * of group NFP_XSTAT_GROUP_MAC.
6111e9eae4SChaoyong He 	 */
6211e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_packets_mc", RX_MC_FRAMES),
6311e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_packets_mc", TX_MC_FRAMES),
6411e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_packets_bc", RX_BC_FRAMES),
6511e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_packets_bc", TX_BC_FRAMES),
6611e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_uc", RX_UC_OCTETS),
6711e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_uc", TX_UC_OCTETS),
6811e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_mc", RX_MC_OCTETS),
6911e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_mc", TX_MC_OCTETS),
7011e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_bc", RX_BC_OCTETS),
7111e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_bc", TX_BC_OCTETS),
7211e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_missed_erros", TX_DISCARDS),
7311e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_pass_pkts", APP0_FRAMES),
7411e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_pass_bytes", APP0_BYTES),
7511e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app1_pkts", APP1_FRAMES),
7611e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app1_bytes", APP1_BYTES),
7711e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app2_pkts", APP2_FRAMES),
7811e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app2_bytes", APP2_BYTES),
7911e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app3_pkts", APP3_FRAMES),
8011e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app3_bytes", APP3_BYTES),
8111e9eae4SChaoyong He 	/*
8211e9eae4SChaoyong He 	 * MAC xstats available only on PF. These statistics are not available for VFs as the
8311e9eae4SChaoyong He 	 * PF is not initialized when the VF is initialized as it is still bound to the kernel
8411e9eae4SChaoyong He 	 * driver. As such, the PMD cannot obtain a CPP handle and access the rtsym_table in order
8511e9eae4SChaoyong He 	 * to get the pointer to the start of the MAC statistics counters.
8611e9eae4SChaoyong He 	 */
8711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_octets", RX_IN_OCTS),
8811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frame_too_long_errors", RX_FRAME_TOO_LONG_ERRORS),
8911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_range_length_errors", RX_RANGE_LENGTH_ERRORS),
9011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_vlan_received_ok", RX_VLAN_RECEIVED_OK),
9111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_errors", RX_IN_ERRORS),
9211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_broadcast_pkts", RX_IN_BROADCAST_PKTS),
9311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_drop_events", RX_DROP_EVENTS),
9411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_alignment_errors", RX_ALIGNMENT_ERRORS),
9511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_mac_ctrl_frames", RX_PAUSE_MAC_CTRL_FRAMES),
9611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frames_received_ok", RX_FRAMES_RECEIVED_OK),
9711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frame_check_sequence_errors", RX_FRAME_CHECK_SEQ_ERRORS),
9811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_unicast_pkts", RX_UNICAST_PKTS),
9911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_multicast_pkts", RX_MULTICAST_PKTS),
10011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts", RX_PKTS),
10111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_undersize_pkts", RX_UNDERSIZE_PKTS),
10211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_64_octets", RX_PKTS_64_OCTS),
10311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_65_to_127_octets", RX_PKTS_65_TO_127_OCTS),
10411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_128_to_255_octets", RX_PKTS_128_TO_255_OCTS),
10511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_256_to_511_octets", RX_PKTS_256_TO_511_OCTS),
10611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_512_to_1023_octets", RX_PKTS_512_TO_1023_OCTS),
10711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_1024_to_1518_octets", RX_PKTS_1024_TO_1518_OCTS),
10811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_1519_to_max_octets", RX_PKTS_1519_TO_MAX_OCTS),
10911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_jabbers", RX_JABBERS),
11011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_fragments", RX_FRAGMENTS),
11111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_oversize_pkts", RX_OVERSIZE_PKTS),
11211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class0", RX_PAUSE_FRAMES_CLASS0),
11311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class1", RX_PAUSE_FRAMES_CLASS1),
11411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class2", RX_PAUSE_FRAMES_CLASS2),
11511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class3", RX_PAUSE_FRAMES_CLASS3),
11611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class4", RX_PAUSE_FRAMES_CLASS4),
11711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class5", RX_PAUSE_FRAMES_CLASS5),
11811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class6", RX_PAUSE_FRAMES_CLASS6),
11911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class7", RX_PAUSE_FRAMES_CLASS7),
12011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_mac_ctrl_frames_received", RX_MAC_CTRL_FRAMES_REC),
12111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_mac_head_drop", RX_MAC_HEAD_DROP),
12211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_queue_drop", TX_QUEUE_DROP),
12311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_octets", TX_OUT_OCTS),
12411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_vlan_transmitted_ok", TX_VLAN_TRANSMITTED_OK),
12511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_errors", TX_OUT_ERRORS),
12611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_broadcast_pkts", TX_BROADCAST_PKTS),
12711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_mac_ctrl_frames", TX_PAUSE_MAC_CTRL_FRAMES),
12811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_frames_transmitted_ok", TX_FRAMES_TRANSMITTED_OK),
12911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_unicast_pkts", TX_UNICAST_PKTS),
13011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_multicast_pkts", TX_MULTICAST_PKTS),
13111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_64_octets", TX_PKTS_64_OCTS),
13211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_65_to_127_octets", TX_PKTS_65_TO_127_OCTS),
13311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_128_to_255_octets", TX_PKTS_128_TO_255_OCTS),
13411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_256_to_511_octets", TX_PKTS_256_TO_511_OCTS),
13511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_512_to_1023_octets", TX_PKTS_512_TO_1023_OCTS),
13611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_1024_to_1518_octets", TX_PKTS_1024_TO_1518_OCTS),
13711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_1519_to_max_octets", TX_PKTS_1519_TO_MAX_OCTS),
13811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class0", TX_PAUSE_FRAMES_CLASS0),
13911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class1", TX_PAUSE_FRAMES_CLASS1),
14011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class2", TX_PAUSE_FRAMES_CLASS2),
14111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class3", TX_PAUSE_FRAMES_CLASS3),
14211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class4", TX_PAUSE_FRAMES_CLASS4),
14311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class5", TX_PAUSE_FRAMES_CLASS5),
14411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class6", TX_PAUSE_FRAMES_CLASS6),
14511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class7", TX_PAUSE_FRAMES_CLASS7),
14611e9eae4SChaoyong He };
14711e9eae4SChaoyong He 
14811e9eae4SChaoyong He static const uint32_t nfp_net_link_speed_nfp2rte[] = {
14911e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = RTE_ETH_SPEED_NUM_NONE,
15011e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = RTE_ETH_SPEED_NUM_NONE,
15111e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_1G]          = RTE_ETH_SPEED_NUM_1G,
15211e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_10G]         = RTE_ETH_SPEED_NUM_10G,
15311e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_25G]         = RTE_ETH_SPEED_NUM_25G,
15411e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_40G]         = RTE_ETH_SPEED_NUM_40G,
15511e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_50G]         = RTE_ETH_SPEED_NUM_50G,
15611e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_100G]        = RTE_ETH_SPEED_NUM_100G,
15711e9eae4SChaoyong He };
15811e9eae4SChaoyong He 
15911e9eae4SChaoyong He static uint16_t
16011e9eae4SChaoyong He nfp_net_link_speed_rte2nfp(uint16_t speed)
16111e9eae4SChaoyong He {
16211e9eae4SChaoyong He 	uint16_t i;
16311e9eae4SChaoyong He 
16411e9eae4SChaoyong He 	for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) {
16511e9eae4SChaoyong He 		if (speed == nfp_net_link_speed_nfp2rte[i])
16611e9eae4SChaoyong He 			return i;
16711e9eae4SChaoyong He 	}
16811e9eae4SChaoyong He 
16911e9eae4SChaoyong He 	return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;
17011e9eae4SChaoyong He }
17111e9eae4SChaoyong He 
17211e9eae4SChaoyong He static void
17311e9eae4SChaoyong He nfp_net_notify_port_speed(struct nfp_net_hw *hw,
17411e9eae4SChaoyong He 		struct rte_eth_link *link)
17511e9eae4SChaoyong He {
17611e9eae4SChaoyong He 	/*
17711e9eae4SChaoyong He 	 * Read the link status from NFP_NET_CFG_STS. If the link is down
17811e9eae4SChaoyong He 	 * then write the link speed NFP_NET_CFG_STS_LINK_RATE_UNKNOWN to
17911e9eae4SChaoyong He 	 * NFP_NET_CFG_STS_NSP_LINK_RATE.
18011e9eae4SChaoyong He 	 */
18111e9eae4SChaoyong He 	if (link->link_status == RTE_ETH_LINK_DOWN) {
182f58bde00SChaoyong He 		nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE,
183f58bde00SChaoyong He 				NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);
18411e9eae4SChaoyong He 		return;
18511e9eae4SChaoyong He 	}
18611e9eae4SChaoyong He 
18711e9eae4SChaoyong He 	/*
18811e9eae4SChaoyong He 	 * Link is up so write the link speed from the eth_table to
18911e9eae4SChaoyong He 	 * NFP_NET_CFG_STS_NSP_LINK_RATE.
19011e9eae4SChaoyong He 	 */
191f58bde00SChaoyong He 	nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE,
19211e9eae4SChaoyong He 			nfp_net_link_speed_rte2nfp(link->link_speed));
19311e9eae4SChaoyong He }
19411e9eae4SChaoyong He 
19511e9eae4SChaoyong He /* The length of firmware version string */
19611e9eae4SChaoyong He #define FW_VER_LEN        32
19711e9eae4SChaoyong He 
19811e9eae4SChaoyong He /**
19911e9eae4SChaoyong He  * Reconfigure the firmware via the mailbox
20011e9eae4SChaoyong He  *
2014a9bb682SChaoyong He  * @param net_hw
20211e9eae4SChaoyong He  *   Device to reconfigure
20311e9eae4SChaoyong He  * @param mbox_cmd
20411e9eae4SChaoyong He  *   The value for the mailbox command
20511e9eae4SChaoyong He  *
20611e9eae4SChaoyong He  * @return
20711e9eae4SChaoyong He  *   - (0) if OK to reconfigure by the mailbox.
20811e9eae4SChaoyong He  *   - (-EIO) if I/O err and fail to reconfigure by the mailbox
20911e9eae4SChaoyong He  */
21011e9eae4SChaoyong He int
2114a9bb682SChaoyong He nfp_net_mbox_reconfig(struct nfp_net_hw *net_hw,
21211e9eae4SChaoyong He 		uint32_t mbox_cmd)
21311e9eae4SChaoyong He {
21411e9eae4SChaoyong He 	int ret;
21511e9eae4SChaoyong He 	uint32_t mbox;
21611e9eae4SChaoyong He 
2174a9bb682SChaoyong He 	mbox = net_hw->tlv_caps.mbox_off;
21811e9eae4SChaoyong He 
2194a9bb682SChaoyong He 	rte_spinlock_lock(&net_hw->super.reconfig_lock);
22011e9eae4SChaoyong He 
2214a9bb682SChaoyong He 	nn_cfg_writeq(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd);
2224a9bb682SChaoyong He 	nn_cfg_writel(&net_hw->super, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX);
22311e9eae4SChaoyong He 
22411e9eae4SChaoyong He 	rte_wmb();
22511e9eae4SChaoyong He 
2264a9bb682SChaoyong He 	ret = nfp_reconfig_real(&net_hw->super, NFP_NET_CFG_UPDATE_MBOX);
22711e9eae4SChaoyong He 
2284a9bb682SChaoyong He 	rte_spinlock_unlock(&net_hw->super.reconfig_lock);
22911e9eae4SChaoyong He 
23011e9eae4SChaoyong He 	if (ret != 0) {
23111e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x",
23211e9eae4SChaoyong He 				mbox_cmd, NFP_NET_CFG_UPDATE_MBOX);
23311e9eae4SChaoyong He 		return -EIO;
23411e9eae4SChaoyong He 	}
23511e9eae4SChaoyong He 
2364a9bb682SChaoyong He 	return nn_cfg_readl(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET);
23711e9eae4SChaoyong He }
23811e9eae4SChaoyong He 
239b12d2b2eSChaoyong He struct nfp_net_hw *
240b12d2b2eSChaoyong He nfp_net_get_hw(const struct rte_eth_dev *dev)
241b12d2b2eSChaoyong He {
242b12d2b2eSChaoyong He 	struct nfp_net_hw *hw;
243b12d2b2eSChaoyong He 
244c99e1db8SLong Wu 	if (rte_eth_dev_is_repr(dev)) {
245b12d2b2eSChaoyong He 		struct nfp_flower_representor *repr;
246b12d2b2eSChaoyong He 		repr = dev->data->dev_private;
247b12d2b2eSChaoyong He 		hw = repr->app_fw_flower->pf_hw;
248b12d2b2eSChaoyong He 	} else {
249b12d2b2eSChaoyong He 		hw = dev->data->dev_private;
250b12d2b2eSChaoyong He 	}
251b12d2b2eSChaoyong He 
252b12d2b2eSChaoyong He 	return hw;
253b12d2b2eSChaoyong He }
254b12d2b2eSChaoyong He 
25511e9eae4SChaoyong He /*
25611e9eae4SChaoyong He  * Configure an Ethernet device.
25711e9eae4SChaoyong He  *
25811e9eae4SChaoyong He  * This function must be invoked first before any other function in the Ethernet API.
25911e9eae4SChaoyong He  * This function can also be re-invoked when a device is in the stopped state.
26011e9eae4SChaoyong He  *
26111e9eae4SChaoyong He  * A DPDK app sends info about how many queues to use and how  those queues
26211e9eae4SChaoyong He  * need to be configured. This is used by the DPDK core and it makes sure no
26311e9eae4SChaoyong He  * more queues than those advertised by the driver are requested.
26411e9eae4SChaoyong He  * This function is called after that internal process.
26511e9eae4SChaoyong He  */
26611e9eae4SChaoyong He int
26711e9eae4SChaoyong He nfp_net_configure(struct rte_eth_dev *dev)
26811e9eae4SChaoyong He {
26911e9eae4SChaoyong He 	struct nfp_net_hw *hw;
27011e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
27111e9eae4SChaoyong He 	struct rte_eth_rxmode *rxmode;
27211e9eae4SChaoyong He 	struct rte_eth_txmode *txmode;
27311e9eae4SChaoyong He 
274b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
27511e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
27611e9eae4SChaoyong He 	rxmode = &dev_conf->rxmode;
27711e9eae4SChaoyong He 	txmode = &dev_conf->txmode;
27811e9eae4SChaoyong He 
27911e9eae4SChaoyong He 	if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0)
28011e9eae4SChaoyong He 		rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
28111e9eae4SChaoyong He 
28211e9eae4SChaoyong He 	/* Checking TX mode */
28311e9eae4SChaoyong He 	if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
28411e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "TX mq_mode DCB and VMDq not supported");
28511e9eae4SChaoyong He 		return -EINVAL;
28611e9eae4SChaoyong He 	}
28711e9eae4SChaoyong He 
28811e9eae4SChaoyong He 	/* Checking RX mode */
28911e9eae4SChaoyong He 	if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 &&
29075a76c73SChaoyong He 			(hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) == 0) {
29111e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "RSS not supported");
29211e9eae4SChaoyong He 		return -EINVAL;
29311e9eae4SChaoyong He 	}
29411e9eae4SChaoyong He 
29511e9eae4SChaoyong He 	/* Checking MTU set */
2962f1bfbf4SJames Hershaw 	if (rxmode->mtu > hw->max_mtu + NFP_ETH_OVERHEAD) {
2972f1bfbf4SJames Hershaw 		PMD_DRV_LOG(ERR, "MTU (%u) larger than the maximum possible frame size (%u)",
2982f1bfbf4SJames Hershaw 				rxmode->mtu, hw->max_mtu + NFP_ETH_OVERHEAD);
29911e9eae4SChaoyong He 		return -ERANGE;
30011e9eae4SChaoyong He 	}
30111e9eae4SChaoyong He 
30211e9eae4SChaoyong He 	return 0;
30311e9eae4SChaoyong He }
30411e9eae4SChaoyong He 
30511e9eae4SChaoyong He void
30611e9eae4SChaoyong He nfp_net_log_device_information(const struct nfp_net_hw *hw)
30711e9eae4SChaoyong He {
30875a76c73SChaoyong He 	uint32_t cap = hw->super.cap;
309cbf062e9SChaoyong He 	uint32_t cap_ext = hw->super.cap_ext;
31075a76c73SChaoyong He 
31111e9eae4SChaoyong He 	PMD_INIT_LOG(INFO, "VER: %u.%u, Maximum supported MTU: %d",
31211e9eae4SChaoyong He 			hw->ver.major, hw->ver.minor, hw->max_mtu);
31311e9eae4SChaoyong He 
314cbf062e9SChaoyong He 	PMD_INIT_LOG(INFO, "CAP: %#x", cap);
315df77f704SChaoyong He 	PMD_INIT_LOG(INFO, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
316cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_ENABLE        ? "ENABLE "      : "",
31775a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_PROMISC       ? "PROMISC "     : "",
31875a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2BC          ? "L2BCFILT "    : "",
31975a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2MC          ? "L2MCFILT "    : "",
32075a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXCSUM        ? "RXCSUM "      : "",
32175a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXCSUM        ? "TXCSUM "      : "",
32275a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXVLAN        ? "RXVLAN "      : "",
32375a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXVLAN        ? "TXVLAN "      : "",
32475a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_SCATTER       ? "SCATTER "     : "",
32575a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_GATHER        ? "GATHER "      : "",
32675a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_LSO           ? "TSO "         : "",
327cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXQINQ        ? "RXQINQ "      : "",
328cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXVLAN_V2     ? "RXVLANv2 "    : "",
329cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RINGCFG       ? "RINGCFG "     : "",
33075a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RSS           ? "RSS "         : "",
331cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_IRQMOD        ? "IRQMOD "      : "",
332cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RINGPRIO      ? "RINGPRIO "    : "",
333cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_MSIXAUTO      ? "MSIXAUTO "    : "",
334cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXRWB         ? "TXRWB "       : "",
335cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2SWITCH      ? "L2SWITCH "    : "",
336cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXVLAN_V2     ? "TXVLANv2 "    : "",
337cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_VXLAN         ? "VXLAN "       : "",
338cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_NVGRE         ? "NVGRE "       : "",
339cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_MSIX_TX_OFF   ? "MSIX_TX_OFF " : "",
340cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_LSO2          ? "TSOv2 "       : "",
341cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RSS2          ? "RSSv2 "       : "",
342cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_CSUM_COMPLETE ? "CSUM "        : "",
343df77f704SChaoyong He 			cap & NFP_NET_CFG_CTRL_LIVE_ADDR     ? "LIVE_ADDR "   : "",
344df77f704SChaoyong He 			cap & NFP_NET_CFG_CTRL_USO           ? "USO"          : "");
345cbf062e9SChaoyong He 
346cbf062e9SChaoyong He 	PMD_INIT_LOG(INFO, "CAP_WORD1: %#x", cap_ext);
347cbf062e9SChaoyong He 	PMD_INIT_LOG(INFO, "%s%s%s%s%s%s%s",
348cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE        ? "PKT_TYPE "        : "",
349cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IPSEC           ? "IPSEC "           : "",
350cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP ? "IPSEC_SM "        : "",
351cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP ? "IPSEC_LM "        : "",
352cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_MULTI_PF        ? "MULTI_PF "        : "",
353cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER      ? "FLOW_STEER "      : "",
354cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IN_ORDER        ? "VIRTIO_IN_ORDER " : "");
35511e9eae4SChaoyong He 
35611e9eae4SChaoyong He 	PMD_INIT_LOG(INFO, "max_rx_queues: %u, max_tx_queues: %u",
35711e9eae4SChaoyong He 			hw->max_rx_queues, hw->max_tx_queues);
35811e9eae4SChaoyong He }
35911e9eae4SChaoyong He 
36011e9eae4SChaoyong He static inline void
36111e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(struct nfp_net_hw *hw,
36211e9eae4SChaoyong He 		uint32_t *ctrl)
36311e9eae4SChaoyong He {
36475a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0)
36511e9eae4SChaoyong He 		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN_V2;
36675a76c73SChaoyong He 	else if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN) != 0)
36711e9eae4SChaoyong He 		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN;
36811e9eae4SChaoyong He }
36911e9eae4SChaoyong He 
37011e9eae4SChaoyong He void
37111e9eae4SChaoyong He nfp_net_enable_queues(struct rte_eth_dev *dev)
37211e9eae4SChaoyong He {
37311e9eae4SChaoyong He 	struct nfp_net_hw *hw;
37411e9eae4SChaoyong He 
375b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
37611e9eae4SChaoyong He 
37787f5b35bSChaoyong He 	nfp_enable_queues(&hw->super, dev->data->nb_rx_queues,
37887f5b35bSChaoyong He 			dev->data->nb_tx_queues);
37911e9eae4SChaoyong He }
38011e9eae4SChaoyong He 
38111e9eae4SChaoyong He void
38211e9eae4SChaoyong He nfp_net_disable_queues(struct rte_eth_dev *dev)
38311e9eae4SChaoyong He {
38472d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
38511e9eae4SChaoyong He 
386b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
38711e9eae4SChaoyong He 
38887f5b35bSChaoyong He 	nfp_disable_queues(&net_hw->super);
38911e9eae4SChaoyong He }
39011e9eae4SChaoyong He 
39111e9eae4SChaoyong He void
39211e9eae4SChaoyong He nfp_net_params_setup(struct nfp_net_hw *hw)
39311e9eae4SChaoyong He {
394f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, hw->mtu);
395f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_FLBUFSZ, hw->flbufsz);
39611e9eae4SChaoyong He }
39711e9eae4SChaoyong He 
39811e9eae4SChaoyong He void
39911e9eae4SChaoyong He nfp_net_cfg_queue_setup(struct nfp_net_hw *hw)
40011e9eae4SChaoyong He {
401464a535bSChaoyong He 	hw->super.qcp_cfg = hw->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
40211e9eae4SChaoyong He }
40311e9eae4SChaoyong He 
40411e9eae4SChaoyong He int
40511e9eae4SChaoyong He nfp_net_set_mac_addr(struct rte_eth_dev *dev,
40611e9eae4SChaoyong He 		struct rte_ether_addr *mac_addr)
40711e9eae4SChaoyong He {
40811e9eae4SChaoyong He 	uint32_t update;
409d6702227SChaoyong He 	uint32_t new_ctrl;
41072d1dea6SChaoyong He 	struct nfp_hw *hw;
41172d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
41211e9eae4SChaoyong He 
413b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
41472d1dea6SChaoyong He 	hw = &net_hw->super;
41572d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 &&
41672d1dea6SChaoyong He 			(hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) {
41711e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "MAC address unable to change when port enabled");
41811e9eae4SChaoyong He 		return -EBUSY;
41911e9eae4SChaoyong He 	}
42011e9eae4SChaoyong He 
421edbb4e1cSChaoyong He 	if (rte_is_valid_assigned_ether_addr(mac_addr) == 0) {
422edbb4e1cSChaoyong He 		PMD_DRV_LOG(ERR, "Invalid MAC address");
423edbb4e1cSChaoyong He 		return -EINVAL;
424edbb4e1cSChaoyong He 	}
425edbb4e1cSChaoyong He 
42611e9eae4SChaoyong He 	/* Writing new MAC to the specific port BAR address */
427503ac807SChaoyong He 	nfp_write_mac(hw, (uint8_t *)mac_addr);
42811e9eae4SChaoyong He 
42911e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_MACADDR;
430d6702227SChaoyong He 	new_ctrl = hw->ctrl;
43172d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 &&
43272d1dea6SChaoyong He 			(hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) != 0)
433d6702227SChaoyong He 		new_ctrl |= NFP_NET_CFG_CTRL_LIVE_ADDR;
43411e9eae4SChaoyong He 
43511e9eae4SChaoyong He 	/* Signal the NIC about the change */
436d6702227SChaoyong He 	if (nfp_reconfig(hw, new_ctrl, update) != 0) {
43711e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "MAC address update failed");
43811e9eae4SChaoyong He 		return -EIO;
43911e9eae4SChaoyong He 	}
44011e9eae4SChaoyong He 
441d6702227SChaoyong He 	hw->ctrl = new_ctrl;
442d6702227SChaoyong He 
44311e9eae4SChaoyong He 	return 0;
44411e9eae4SChaoyong He }
44511e9eae4SChaoyong He 
44611e9eae4SChaoyong He int
44711e9eae4SChaoyong He nfp_configure_rx_interrupt(struct rte_eth_dev *dev,
44811e9eae4SChaoyong He 		struct rte_intr_handle *intr_handle)
44911e9eae4SChaoyong He {
45011e9eae4SChaoyong He 	uint16_t i;
45111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
45211e9eae4SChaoyong He 
45311e9eae4SChaoyong He 	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
45411e9eae4SChaoyong He 				dev->data->nb_rx_queues) != 0) {
45511e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Failed to allocate %d rx_queues intr_vec",
45611e9eae4SChaoyong He 				dev->data->nb_rx_queues);
45711e9eae4SChaoyong He 		return -ENOMEM;
45811e9eae4SChaoyong He 	}
45911e9eae4SChaoyong He 
460b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
46111e9eae4SChaoyong He 
46211e9eae4SChaoyong He 	if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) {
46311e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with UIO");
46411e9eae4SChaoyong He 		/* UIO just supports one queue and no LSC */
465f58bde00SChaoyong He 		nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(0), 0);
46611e9eae4SChaoyong He 		if (rte_intr_vec_list_index_set(intr_handle, 0, 0) != 0)
46711e9eae4SChaoyong He 			return -1;
46811e9eae4SChaoyong He 	} else {
46911e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with VFIO");
47011e9eae4SChaoyong He 		for (i = 0; i < dev->data->nb_rx_queues; i++) {
47111e9eae4SChaoyong He 			/*
47211e9eae4SChaoyong He 			 * The first msix vector is reserved for non
47311e9eae4SChaoyong He 			 * efd interrupts.
47411e9eae4SChaoyong He 			 */
475f58bde00SChaoyong He 			nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(i), i + 1);
47611e9eae4SChaoyong He 			if (rte_intr_vec_list_index_set(intr_handle, i, i + 1) != 0)
47711e9eae4SChaoyong He 				return -1;
47811e9eae4SChaoyong He 		}
47911e9eae4SChaoyong He 	}
48011e9eae4SChaoyong He 
48111e9eae4SChaoyong He 	/* Avoiding TX interrupts */
482b4b6988aSChaoyong He 	hw->super.ctrl |= NFP_NET_CFG_CTRL_MSIX_TX_OFF;
48311e9eae4SChaoyong He 	return 0;
48411e9eae4SChaoyong He }
48511e9eae4SChaoyong He 
48611e9eae4SChaoyong He uint32_t
48711e9eae4SChaoyong He nfp_check_offloads(struct rte_eth_dev *dev)
48811e9eae4SChaoyong He {
4894a9bb682SChaoyong He 	uint32_t cap;
49011e9eae4SChaoyong He 	uint32_t ctrl = 0;
49111e9eae4SChaoyong He 	uint64_t rx_offload;
49211e9eae4SChaoyong He 	uint64_t tx_offload;
49311e9eae4SChaoyong He 	struct nfp_net_hw *hw;
49411e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
49511e9eae4SChaoyong He 
496b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
4974a9bb682SChaoyong He 	cap = hw->super.cap;
49811e9eae4SChaoyong He 
49911e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
50011e9eae4SChaoyong He 	rx_offload = dev_conf->rxmode.offloads;
50111e9eae4SChaoyong He 	tx_offload = dev_conf->txmode.offloads;
50211e9eae4SChaoyong He 
50311e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0) {
5044a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0)
50511e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_RXCSUM;
50611e9eae4SChaoyong He 	}
50711e9eae4SChaoyong He 
50811e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0)
50911e9eae4SChaoyong He 		nfp_net_enable_rxvlan_cap(hw, &ctrl);
51011e9eae4SChaoyong He 
51111e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) {
5124a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0)
51311e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
51411e9eae4SChaoyong He 	}
51511e9eae4SChaoyong He 
51611e9eae4SChaoyong He 	hw->mtu = dev->data->mtu;
51711e9eae4SChaoyong He 
51811e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) != 0) {
5194a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0)
52011e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_TXVLAN_V2;
5214a9bb682SChaoyong He 		else if ((cap & NFP_NET_CFG_CTRL_TXVLAN) != 0)
52211e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_TXVLAN;
52311e9eae4SChaoyong He 	}
52411e9eae4SChaoyong He 
52511e9eae4SChaoyong He 	/* L2 broadcast */
5264a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_L2BC) != 0)
52711e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_L2BC;
52811e9eae4SChaoyong He 
52911e9eae4SChaoyong He 	/* L2 multicast */
5304a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_L2MC) != 0)
53111e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_L2MC;
53211e9eae4SChaoyong He 
53311e9eae4SChaoyong He 	/* TX checksum offload */
53411e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0 ||
53511e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0 ||
53611e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0)
53711e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
53811e9eae4SChaoyong He 
53911e9eae4SChaoyong He 	/* LSO offload */
54011e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) != 0 ||
541df77f704SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_UDP_TSO) != 0 ||
54211e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) != 0) {
5434a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_LSO) != 0)
54411e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_LSO;
545afa83796SChaoyong He 		else if ((cap & NFP_NET_CFG_CTRL_LSO2) != 0)
54611e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_LSO2;
54711e9eae4SChaoyong He 	}
54811e9eae4SChaoyong He 
54911e9eae4SChaoyong He 	/* RX gather */
55011e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0)
55111e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_GATHER;
55211e9eae4SChaoyong He 
55311e9eae4SChaoyong He 	return ctrl;
55411e9eae4SChaoyong He }
55511e9eae4SChaoyong He 
55611e9eae4SChaoyong He int
55711e9eae4SChaoyong He nfp_net_promisc_enable(struct rte_eth_dev *dev)
55811e9eae4SChaoyong He {
55911e9eae4SChaoyong He 	int ret;
56072d1dea6SChaoyong He 	uint32_t update;
56111e9eae4SChaoyong He 	uint32_t new_ctrl;
56272d1dea6SChaoyong He 	struct nfp_hw *hw;
56372d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
56411e9eae4SChaoyong He 
565b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
56611e9eae4SChaoyong He 
56772d1dea6SChaoyong He 	hw = &net_hw->super;
56872d1dea6SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) {
56911e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Promiscuous mode not supported");
57011e9eae4SChaoyong He 		return -ENOTSUP;
57111e9eae4SChaoyong He 	}
57211e9eae4SChaoyong He 
57372d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) != 0) {
57411e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "Promiscuous mode already enabled");
57511e9eae4SChaoyong He 		return 0;
57611e9eae4SChaoyong He 	}
57711e9eae4SChaoyong He 
57872d1dea6SChaoyong He 	new_ctrl = hw->ctrl | NFP_NET_CFG_CTRL_PROMISC;
57911e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
58011e9eae4SChaoyong He 
58172d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
58211e9eae4SChaoyong He 	if (ret != 0)
58311e9eae4SChaoyong He 		return ret;
58411e9eae4SChaoyong He 
58572d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
58611e9eae4SChaoyong He 
58711e9eae4SChaoyong He 	return 0;
58811e9eae4SChaoyong He }
58911e9eae4SChaoyong He 
59011e9eae4SChaoyong He int
59111e9eae4SChaoyong He nfp_net_promisc_disable(struct rte_eth_dev *dev)
59211e9eae4SChaoyong He {
59311e9eae4SChaoyong He 	int ret;
59472d1dea6SChaoyong He 	uint32_t update;
59511e9eae4SChaoyong He 	uint32_t new_ctrl;
59672d1dea6SChaoyong He 	struct nfp_hw *hw;
59772d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
59811e9eae4SChaoyong He 
599b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
60072d1dea6SChaoyong He 	hw = &net_hw->super;
60111e9eae4SChaoyong He 
6025ff76867SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) {
6035ff76867SChaoyong He 		PMD_DRV_LOG(ERR, "Promiscuous mode not supported");
6045ff76867SChaoyong He 		return -ENOTSUP;
6055ff76867SChaoyong He 	}
6065ff76867SChaoyong He 
60772d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) == 0) {
60811e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "Promiscuous mode already disabled");
60911e9eae4SChaoyong He 		return 0;
61011e9eae4SChaoyong He 	}
61111e9eae4SChaoyong He 
61272d1dea6SChaoyong He 	new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_PROMISC;
61311e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
61411e9eae4SChaoyong He 
61572d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
61611e9eae4SChaoyong He 	if (ret != 0)
61711e9eae4SChaoyong He 		return ret;
61811e9eae4SChaoyong He 
61972d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
62011e9eae4SChaoyong He 
62111e9eae4SChaoyong He 	return 0;
62211e9eae4SChaoyong He }
62311e9eae4SChaoyong He 
6244a86c36bSQin Ke static int
6254a86c36bSQin Ke nfp_net_set_allmulticast_mode(struct rte_eth_dev *dev,
6264a86c36bSQin Ke 		bool enable)
6274a86c36bSQin Ke {
6284a86c36bSQin Ke 	int ret;
6294a86c36bSQin Ke 	uint32_t update;
6304a86c36bSQin Ke 	struct nfp_hw *hw;
6314a86c36bSQin Ke 	uint32_t cap_extend;
6324a86c36bSQin Ke 	uint32_t ctrl_extend;
6334a86c36bSQin Ke 	uint32_t new_ctrl_extend;
6344a86c36bSQin Ke 	struct nfp_net_hw *net_hw;
6354a86c36bSQin Ke 
6364a86c36bSQin Ke 	net_hw = nfp_net_get_hw(dev);
6374a86c36bSQin Ke 	hw = &net_hw->super;
6384a86c36bSQin Ke 
6394a86c36bSQin Ke 	cap_extend = hw->cap_ext;
6404a86c36bSQin Ke 	if ((cap_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0) {
6414a86c36bSQin Ke 		PMD_DRV_LOG(ERR, "Allmulticast mode not supported");
6424a86c36bSQin Ke 		return -ENOTSUP;
6434a86c36bSQin Ke 	}
6444a86c36bSQin Ke 
6454a86c36bSQin Ke 	/*
6464a86c36bSQin Ke 	 * Allmulticast mode enabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 0.
6474a86c36bSQin Ke 	 * Allmulticast mode disabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 1.
6484a86c36bSQin Ke 	 */
6494a86c36bSQin Ke 	ctrl_extend = hw->ctrl_ext;
6504a86c36bSQin Ke 	if (enable) {
6514a86c36bSQin Ke 		if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0)
6524a86c36bSQin Ke 			return 0;
6534a86c36bSQin Ke 
6544a86c36bSQin Ke 		new_ctrl_extend = ctrl_extend & ~NFP_NET_CFG_CTRL_MCAST_FILTER;
6554a86c36bSQin Ke 	} else {
6564a86c36bSQin Ke 		if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) != 0)
6574a86c36bSQin Ke 			return 0;
6584a86c36bSQin Ke 
6594a86c36bSQin Ke 		new_ctrl_extend = ctrl_extend | NFP_NET_CFG_CTRL_MCAST_FILTER;
6604a86c36bSQin Ke 	}
6614a86c36bSQin Ke 
6624a86c36bSQin Ke 	update = NFP_NET_CFG_UPDATE_GEN;
6634a86c36bSQin Ke 
6644a86c36bSQin Ke 	ret = nfp_ext_reconfig(hw, new_ctrl_extend, update);
6654a86c36bSQin Ke 	if (ret != 0)
6664a86c36bSQin Ke 		return ret;
6674a86c36bSQin Ke 
6684a86c36bSQin Ke 	hw->ctrl_ext = new_ctrl_extend;
6694a86c36bSQin Ke 	return 0;
6704a86c36bSQin Ke }
6714a86c36bSQin Ke 
6724a86c36bSQin Ke int
6734a86c36bSQin Ke nfp_net_allmulticast_enable(struct rte_eth_dev *dev)
6744a86c36bSQin Ke {
6754a86c36bSQin Ke 	return nfp_net_set_allmulticast_mode(dev, true);
6764a86c36bSQin Ke }
6774a86c36bSQin Ke 
6784a86c36bSQin Ke int
6794a86c36bSQin Ke nfp_net_allmulticast_disable(struct rte_eth_dev *dev)
6804a86c36bSQin Ke {
6814a86c36bSQin Ke 	return nfp_net_set_allmulticast_mode(dev, false);
6824a86c36bSQin Ke }
6834a86c36bSQin Ke 
6848412feedSZerun Fu static int
6858412feedSZerun Fu nfp_net_speed_aneg_update(struct rte_eth_dev *dev,
6868412feedSZerun Fu 		struct nfp_net_hw *hw,
6878412feedSZerun Fu 		struct rte_eth_link *link)
6888412feedSZerun Fu {
6898412feedSZerun Fu 	uint32_t i;
6908412feedSZerun Fu 	uint32_t speed;
6918412feedSZerun Fu 	struct nfp_eth_table *nfp_eth_table;
6928412feedSZerun Fu 	struct nfp_eth_table_port *eth_port;
6938412feedSZerun Fu 
6948412feedSZerun Fu 	/* Compare whether the current status has changed. */
6958412feedSZerun Fu 	if (dev->data->dev_link.link_status != link->link_status) {
6968412feedSZerun Fu 		nfp_eth_table = nfp_eth_read_ports(hw->cpp);
6978412feedSZerun Fu 		if (nfp_eth_table == NULL) {
6988412feedSZerun Fu 			PMD_DRV_LOG(DEBUG, "Error reading NFP ethernet table.");
6998412feedSZerun Fu 			return -EIO;
7008412feedSZerun Fu 		}
7018412feedSZerun Fu 
7028412feedSZerun Fu 		hw->pf_dev->nfp_eth_table->ports[hw->idx] = nfp_eth_table->ports[hw->idx];
7038412feedSZerun Fu 		free(nfp_eth_table);
7048412feedSZerun Fu 	}
7058412feedSZerun Fu 
7068412feedSZerun Fu 	nfp_eth_table = hw->pf_dev->nfp_eth_table;
7078412feedSZerun Fu 	eth_port = &nfp_eth_table->ports[hw->idx];
7088412feedSZerun Fu 	speed = eth_port->speed;
7098412feedSZerun Fu 
7108412feedSZerun Fu 	for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) {
7118412feedSZerun Fu 		if (nfp_net_link_speed_nfp2rte[i] == speed) {
7128412feedSZerun Fu 			link->link_speed = speed;
7138412feedSZerun Fu 			break;
7148412feedSZerun Fu 		}
7158412feedSZerun Fu 	}
7168412feedSZerun Fu 
7178412feedSZerun Fu 	if (dev->data->dev_conf.link_speeds == RTE_ETH_LINK_SPEED_AUTONEG &&
7188412feedSZerun Fu 			eth_port->supp_aneg)
7198412feedSZerun Fu 		link->link_autoneg = RTE_ETH_LINK_AUTONEG;
7208412feedSZerun Fu 
7218412feedSZerun Fu 	return 0;
7228412feedSZerun Fu }
7238412feedSZerun Fu 
724c4de52ecSChaoyong He int
725c4de52ecSChaoyong He nfp_net_link_update_common(struct rte_eth_dev *dev,
726c4de52ecSChaoyong He 		struct nfp_net_hw *hw,
727c4de52ecSChaoyong He 		struct rte_eth_link *link,
728c4de52ecSChaoyong He 		uint32_t link_status)
729c4de52ecSChaoyong He {
730c4de52ecSChaoyong He 	int ret;
731c4de52ecSChaoyong He 	uint32_t nn_link_status;
732c4de52ecSChaoyong He 
733c4de52ecSChaoyong He 	if (link->link_status == RTE_ETH_LINK_UP) {
734c4de52ecSChaoyong He 		if (hw->pf_dev != NULL) {
7358412feedSZerun Fu 			ret = nfp_net_speed_aneg_update(dev, hw, link);
7368412feedSZerun Fu 			if (ret != 0) {
7378412feedSZerun Fu 				PMD_DRV_LOG(DEBUG, "Failed to update speed and aneg.");
7388412feedSZerun Fu 				return ret;
739c4de52ecSChaoyong He 			}
740c4de52ecSChaoyong He 		} else {
741c4de52ecSChaoyong He 			/*
742c4de52ecSChaoyong He 			 * Shift and mask nn_link_status so that it is effectively the value
743c4de52ecSChaoyong He 			 * at offset NFP_NET_CFG_STS_NSP_LINK_RATE.
744c4de52ecSChaoyong He 			 */
745c4de52ecSChaoyong He 			nn_link_status = (link_status >> NFP_NET_CFG_STS_LINK_RATE_SHIFT) &
746c4de52ecSChaoyong He 					NFP_NET_CFG_STS_LINK_RATE_MASK;
747c4de52ecSChaoyong He 			if (nn_link_status < RTE_DIM(nfp_net_link_speed_nfp2rte))
748c4de52ecSChaoyong He 				link->link_speed = nfp_net_link_speed_nfp2rte[nn_link_status];
749c4de52ecSChaoyong He 		}
750c4de52ecSChaoyong He 	}
751c4de52ecSChaoyong He 
752c4de52ecSChaoyong He 	ret = rte_eth_linkstatus_set(dev, link);
753c4de52ecSChaoyong He 	if (ret == 0) {
754c4de52ecSChaoyong He 		if (link->link_status != 0)
755c4de52ecSChaoyong He 			PMD_DRV_LOG(INFO, "NIC Link is Up");
756c4de52ecSChaoyong He 		else
757c4de52ecSChaoyong He 			PMD_DRV_LOG(INFO, "NIC Link is Down");
758c4de52ecSChaoyong He 	}
759c4de52ecSChaoyong He 
760c4de52ecSChaoyong He 	return ret;
761c4de52ecSChaoyong He }
762c4de52ecSChaoyong He 
76311e9eae4SChaoyong He /*
76411e9eae4SChaoyong He  * Return 0 means link status changed, -1 means not changed
76511e9eae4SChaoyong He  *
76611e9eae4SChaoyong He  * Wait to complete is needed as it can take up to 9 seconds to get the Link
76711e9eae4SChaoyong He  * status.
76811e9eae4SChaoyong He  */
76911e9eae4SChaoyong He int
77011e9eae4SChaoyong He nfp_net_link_update(struct rte_eth_dev *dev,
77111e9eae4SChaoyong He 		__rte_unused int wait_to_complete)
77211e9eae4SChaoyong He {
77311e9eae4SChaoyong He 	int ret;
77411e9eae4SChaoyong He 	struct nfp_net_hw *hw;
77511e9eae4SChaoyong He 	uint32_t nn_link_status;
77611e9eae4SChaoyong He 	struct rte_eth_link link;
77711e9eae4SChaoyong He 
778b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
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 
789c4de52ecSChaoyong He 	ret = nfp_net_link_update_common(dev, hw, &link, nn_link_status);
7908412feedSZerun Fu 	if (ret == -EIO)
7918412feedSZerun Fu 		return ret;
79211e9eae4SChaoyong He 
79311e9eae4SChaoyong He 	/*
79411e9eae4SChaoyong He 	 * Notify the port to update the speed value in the CTRL BAR from NSP.
79511e9eae4SChaoyong He 	 * Not applicable for VFs as the associated PF is still attached to the
79611e9eae4SChaoyong He 	 * kernel driver.
79711e9eae4SChaoyong He 	 */
79811e9eae4SChaoyong He 	if (hw->pf_dev != NULL)
79911e9eae4SChaoyong He 		nfp_net_notify_port_speed(hw, &link);
80011e9eae4SChaoyong He 
80111e9eae4SChaoyong He 	return ret;
80211e9eae4SChaoyong He }
80311e9eae4SChaoyong He 
80411e9eae4SChaoyong He int
80511e9eae4SChaoyong He nfp_net_stats_get(struct rte_eth_dev *dev,
80611e9eae4SChaoyong He 		struct rte_eth_stats *stats)
80711e9eae4SChaoyong He {
80811e9eae4SChaoyong He 	uint16_t i;
80911e9eae4SChaoyong He 	struct nfp_net_hw *hw;
81011e9eae4SChaoyong He 	struct rte_eth_stats nfp_dev_stats;
81111e9eae4SChaoyong He 
81211e9eae4SChaoyong He 	if (stats == NULL)
81311e9eae4SChaoyong He 		return -EINVAL;
81411e9eae4SChaoyong He 
815b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
81611e9eae4SChaoyong He 
81711e9eae4SChaoyong He 	memset(&nfp_dev_stats, 0, sizeof(nfp_dev_stats));
81811e9eae4SChaoyong He 
81911e9eae4SChaoyong He 	/* Reading per RX ring stats */
82011e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
82111e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
82211e9eae4SChaoyong He 			break;
82311e9eae4SChaoyong He 
82411e9eae4SChaoyong He 		nfp_dev_stats.q_ipackets[i] =
825f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i));
82611e9eae4SChaoyong He 		nfp_dev_stats.q_ipackets[i] -=
82711e9eae4SChaoyong He 				hw->eth_stats_base.q_ipackets[i];
82811e9eae4SChaoyong He 
82911e9eae4SChaoyong He 		nfp_dev_stats.q_ibytes[i] =
830f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8);
83111e9eae4SChaoyong He 		nfp_dev_stats.q_ibytes[i] -=
83211e9eae4SChaoyong He 				hw->eth_stats_base.q_ibytes[i];
83311e9eae4SChaoyong He 	}
83411e9eae4SChaoyong He 
83511e9eae4SChaoyong He 	/* Reading per TX ring stats */
83611e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
83711e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
83811e9eae4SChaoyong He 			break;
83911e9eae4SChaoyong He 
84011e9eae4SChaoyong He 		nfp_dev_stats.q_opackets[i] =
841f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i));
84211e9eae4SChaoyong He 		nfp_dev_stats.q_opackets[i] -= hw->eth_stats_base.q_opackets[i];
84311e9eae4SChaoyong He 
84411e9eae4SChaoyong He 		nfp_dev_stats.q_obytes[i] =
845f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8);
84611e9eae4SChaoyong He 		nfp_dev_stats.q_obytes[i] -= hw->eth_stats_base.q_obytes[i];
84711e9eae4SChaoyong He 	}
84811e9eae4SChaoyong He 
849f58bde00SChaoyong He 	nfp_dev_stats.ipackets = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES);
85011e9eae4SChaoyong He 	nfp_dev_stats.ipackets -= hw->eth_stats_base.ipackets;
85111e9eae4SChaoyong He 
852f58bde00SChaoyong He 	nfp_dev_stats.ibytes = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS);
85311e9eae4SChaoyong He 	nfp_dev_stats.ibytes -= hw->eth_stats_base.ibytes;
85411e9eae4SChaoyong He 
85511e9eae4SChaoyong He 	nfp_dev_stats.opackets =
856f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES);
85711e9eae4SChaoyong He 	nfp_dev_stats.opackets -= hw->eth_stats_base.opackets;
85811e9eae4SChaoyong He 
85911e9eae4SChaoyong He 	nfp_dev_stats.obytes =
860f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS);
86111e9eae4SChaoyong He 	nfp_dev_stats.obytes -= hw->eth_stats_base.obytes;
86211e9eae4SChaoyong He 
86311e9eae4SChaoyong He 	/* Reading general device stats */
86411e9eae4SChaoyong He 	nfp_dev_stats.ierrors =
865f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS);
86611e9eae4SChaoyong He 	nfp_dev_stats.ierrors -= hw->eth_stats_base.ierrors;
86711e9eae4SChaoyong He 
86811e9eae4SChaoyong He 	nfp_dev_stats.oerrors =
869f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS);
87011e9eae4SChaoyong He 	nfp_dev_stats.oerrors -= hw->eth_stats_base.oerrors;
87111e9eae4SChaoyong He 
87211e9eae4SChaoyong He 	/* RX ring mbuf allocation failures */
87311e9eae4SChaoyong He 	nfp_dev_stats.rx_nombuf = dev->data->rx_mbuf_alloc_failed;
87411e9eae4SChaoyong He 
87511e9eae4SChaoyong He 	nfp_dev_stats.imissed =
876f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS);
87711e9eae4SChaoyong He 	nfp_dev_stats.imissed -= hw->eth_stats_base.imissed;
87811e9eae4SChaoyong He 
87911e9eae4SChaoyong He 	memcpy(stats, &nfp_dev_stats, sizeof(*stats));
88011e9eae4SChaoyong He 	return 0;
88111e9eae4SChaoyong He }
88211e9eae4SChaoyong He 
88311e9eae4SChaoyong He /*
88411e9eae4SChaoyong He  * hw->eth_stats_base records the per counter starting point.
88511e9eae4SChaoyong He  * Lets update it now.
88611e9eae4SChaoyong He  */
88711e9eae4SChaoyong He int
88811e9eae4SChaoyong He nfp_net_stats_reset(struct rte_eth_dev *dev)
88911e9eae4SChaoyong He {
89011e9eae4SChaoyong He 	uint16_t i;
89111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
89211e9eae4SChaoyong He 
893b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
89411e9eae4SChaoyong He 
89511e9eae4SChaoyong He 	/* Reading per RX ring stats */
89611e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
89711e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
89811e9eae4SChaoyong He 			break;
89911e9eae4SChaoyong He 
90011e9eae4SChaoyong He 		hw->eth_stats_base.q_ipackets[i] =
901f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i));
90211e9eae4SChaoyong He 
90311e9eae4SChaoyong He 		hw->eth_stats_base.q_ibytes[i] =
904f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8);
90511e9eae4SChaoyong He 	}
90611e9eae4SChaoyong He 
90711e9eae4SChaoyong He 	/* Reading per TX ring stats */
90811e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
90911e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
91011e9eae4SChaoyong He 			break;
91111e9eae4SChaoyong He 
91211e9eae4SChaoyong He 		hw->eth_stats_base.q_opackets[i] =
913f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i));
91411e9eae4SChaoyong He 
91511e9eae4SChaoyong He 		hw->eth_stats_base.q_obytes[i] =
916f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8);
91711e9eae4SChaoyong He 	}
91811e9eae4SChaoyong He 
91911e9eae4SChaoyong He 	hw->eth_stats_base.ipackets =
920f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES);
92111e9eae4SChaoyong He 
92211e9eae4SChaoyong He 	hw->eth_stats_base.ibytes =
923f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS);
92411e9eae4SChaoyong He 
92511e9eae4SChaoyong He 	hw->eth_stats_base.opackets =
926f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES);
92711e9eae4SChaoyong He 
92811e9eae4SChaoyong He 	hw->eth_stats_base.obytes =
929f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS);
93011e9eae4SChaoyong He 
93111e9eae4SChaoyong He 	/* Reading general device stats */
93211e9eae4SChaoyong He 	hw->eth_stats_base.ierrors =
933f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS);
93411e9eae4SChaoyong He 
93511e9eae4SChaoyong He 	hw->eth_stats_base.oerrors =
936f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS);
93711e9eae4SChaoyong He 
93811e9eae4SChaoyong He 	/* RX ring mbuf allocation failures */
93911e9eae4SChaoyong He 	dev->data->rx_mbuf_alloc_failed = 0;
94011e9eae4SChaoyong He 
94111e9eae4SChaoyong He 	hw->eth_stats_base.imissed =
942f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS);
94311e9eae4SChaoyong He 
94411e9eae4SChaoyong He 	return 0;
94511e9eae4SChaoyong He }
94611e9eae4SChaoyong He 
94711e9eae4SChaoyong He uint32_t
94811e9eae4SChaoyong He nfp_net_xstats_size(const struct rte_eth_dev *dev)
94911e9eae4SChaoyong He {
95011e9eae4SChaoyong He 	uint32_t count;
95111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
95211e9eae4SChaoyong He 	const uint32_t size = RTE_DIM(nfp_net_xstats);
95311e9eae4SChaoyong He 
95411e9eae4SChaoyong He 	/* If the device is a VF, then there will be no MAC stats */
955b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
95611e9eae4SChaoyong He 	if (hw->mac_stats == NULL) {
95711e9eae4SChaoyong He 		for (count = 0; count < size; count++) {
95811e9eae4SChaoyong He 			if (nfp_net_xstats[count].group == NFP_XSTAT_GROUP_MAC)
95911e9eae4SChaoyong He 				break;
96011e9eae4SChaoyong He 		}
96111e9eae4SChaoyong He 
96211e9eae4SChaoyong He 		return count;
96311e9eae4SChaoyong He 	}
96411e9eae4SChaoyong He 
96511e9eae4SChaoyong He 	return size;
96611e9eae4SChaoyong He }
96711e9eae4SChaoyong He 
96811e9eae4SChaoyong He static const struct nfp_xstat *
96911e9eae4SChaoyong He nfp_net_xstats_info(const struct rte_eth_dev *dev,
97011e9eae4SChaoyong He 		uint32_t index)
97111e9eae4SChaoyong He {
97211e9eae4SChaoyong He 	if (index >= nfp_net_xstats_size(dev)) {
97311e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "xstat index out of bounds");
97411e9eae4SChaoyong He 		return NULL;
97511e9eae4SChaoyong He 	}
97611e9eae4SChaoyong He 
97711e9eae4SChaoyong He 	return &nfp_net_xstats[index];
97811e9eae4SChaoyong He }
97911e9eae4SChaoyong He 
98011e9eae4SChaoyong He static uint64_t
98111e9eae4SChaoyong He nfp_net_xstats_value(const struct rte_eth_dev *dev,
98211e9eae4SChaoyong He 		uint32_t index,
98311e9eae4SChaoyong He 		bool raw)
98411e9eae4SChaoyong He {
98511e9eae4SChaoyong He 	uint64_t value;
98611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
98711e9eae4SChaoyong He 	struct nfp_xstat xstat;
98811e9eae4SChaoyong He 
989b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
99011e9eae4SChaoyong He 	xstat = nfp_net_xstats[index];
99111e9eae4SChaoyong He 
99211e9eae4SChaoyong He 	if (xstat.group == NFP_XSTAT_GROUP_MAC)
99311e9eae4SChaoyong He 		value = nn_readq(hw->mac_stats + xstat.offset);
99411e9eae4SChaoyong He 	else
995f58bde00SChaoyong He 		value = nn_cfg_readq(&hw->super, xstat.offset);
99611e9eae4SChaoyong He 
99711e9eae4SChaoyong He 	if (raw)
99811e9eae4SChaoyong He 		return value;
99911e9eae4SChaoyong He 
100011e9eae4SChaoyong He 	/*
100111e9eae4SChaoyong He 	 * A baseline value of each statistic counter is recorded when stats are "reset".
100211e9eae4SChaoyong He 	 * Thus, the value returned by this function need to be decremented by this
100311e9eae4SChaoyong He 	 * baseline value. The result is the count of this statistic since the last time
100411e9eae4SChaoyong He 	 * it was "reset".
100511e9eae4SChaoyong He 	 */
100611e9eae4SChaoyong He 	return value - hw->eth_xstats_base[index].value;
100711e9eae4SChaoyong He }
100811e9eae4SChaoyong He 
100911e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */
101011e9eae4SChaoyong He int
101111e9eae4SChaoyong He nfp_net_xstats_get_names(struct rte_eth_dev *dev,
101211e9eae4SChaoyong He 		struct rte_eth_xstat_name *xstats_names,
101311e9eae4SChaoyong He 		unsigned int size)
101411e9eae4SChaoyong He {
101511e9eae4SChaoyong He 	uint32_t id;
101611e9eae4SChaoyong He 	uint32_t nfp_size;
101711e9eae4SChaoyong He 	uint32_t read_size;
101811e9eae4SChaoyong He 
101911e9eae4SChaoyong He 	nfp_size = nfp_net_xstats_size(dev);
102011e9eae4SChaoyong He 
102111e9eae4SChaoyong He 	if (xstats_names == NULL)
102211e9eae4SChaoyong He 		return nfp_size;
102311e9eae4SChaoyong He 
102411e9eae4SChaoyong He 	/* Read at most NFP xstats number of names. */
102511e9eae4SChaoyong He 	read_size = RTE_MIN(size, nfp_size);
102611e9eae4SChaoyong He 
102711e9eae4SChaoyong He 	for (id = 0; id < read_size; id++)
102811e9eae4SChaoyong He 		rte_strlcpy(xstats_names[id].name, nfp_net_xstats[id].name,
102911e9eae4SChaoyong He 				RTE_ETH_XSTATS_NAME_SIZE);
103011e9eae4SChaoyong He 
103111e9eae4SChaoyong He 	return read_size;
103211e9eae4SChaoyong He }
103311e9eae4SChaoyong He 
103411e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */
103511e9eae4SChaoyong He int
103611e9eae4SChaoyong He nfp_net_xstats_get(struct rte_eth_dev *dev,
103711e9eae4SChaoyong He 		struct rte_eth_xstat *xstats,
103811e9eae4SChaoyong He 		unsigned int n)
103911e9eae4SChaoyong He {
104011e9eae4SChaoyong He 	uint32_t id;
104111e9eae4SChaoyong He 	uint32_t nfp_size;
104211e9eae4SChaoyong He 	uint32_t read_size;
104311e9eae4SChaoyong He 
104411e9eae4SChaoyong He 	nfp_size = nfp_net_xstats_size(dev);
104511e9eae4SChaoyong He 
104611e9eae4SChaoyong He 	if (xstats == NULL)
104711e9eae4SChaoyong He 		return nfp_size;
104811e9eae4SChaoyong He 
104911e9eae4SChaoyong He 	/* Read at most NFP xstats number of values. */
105011e9eae4SChaoyong He 	read_size = RTE_MIN(n, nfp_size);
105111e9eae4SChaoyong He 
105211e9eae4SChaoyong He 	for (id = 0; id < read_size; id++) {
105311e9eae4SChaoyong He 		xstats[id].id = id;
105411e9eae4SChaoyong He 		xstats[id].value = nfp_net_xstats_value(dev, id, false);
105511e9eae4SChaoyong He 	}
105611e9eae4SChaoyong He 
105711e9eae4SChaoyong He 	return read_size;
105811e9eae4SChaoyong He }
105911e9eae4SChaoyong He 
106011e9eae4SChaoyong He /*
106111e9eae4SChaoyong He  * NOTE: The only caller rte_eth_xstats_get_names_by_id() ensures dev,
106211e9eae4SChaoyong He  * ids, xstats_names and size are valid, and non-NULL.
106311e9eae4SChaoyong He  */
106411e9eae4SChaoyong He int
106511e9eae4SChaoyong He nfp_net_xstats_get_names_by_id(struct rte_eth_dev *dev,
106611e9eae4SChaoyong He 		const uint64_t *ids,
106711e9eae4SChaoyong He 		struct rte_eth_xstat_name *xstats_names,
106811e9eae4SChaoyong He 		unsigned int size)
106911e9eae4SChaoyong He {
107011e9eae4SChaoyong He 	uint32_t i;
107111e9eae4SChaoyong He 	uint32_t read_size;
107211e9eae4SChaoyong He 
107311e9eae4SChaoyong He 	/* Read at most NFP xstats number of names. */
107411e9eae4SChaoyong He 	read_size = RTE_MIN(size, nfp_net_xstats_size(dev));
107511e9eae4SChaoyong He 
107611e9eae4SChaoyong He 	for (i = 0; i < read_size; i++) {
107711e9eae4SChaoyong He 		const struct nfp_xstat *xstat;
107811e9eae4SChaoyong He 
107911e9eae4SChaoyong He 		/* Make sure ID is valid for device. */
108011e9eae4SChaoyong He 		xstat = nfp_net_xstats_info(dev, ids[i]);
108111e9eae4SChaoyong He 		if (xstat == NULL)
108211e9eae4SChaoyong He 			return -EINVAL;
108311e9eae4SChaoyong He 
108411e9eae4SChaoyong He 		rte_strlcpy(xstats_names[i].name, xstat->name,
108511e9eae4SChaoyong He 				RTE_ETH_XSTATS_NAME_SIZE);
108611e9eae4SChaoyong He 	}
108711e9eae4SChaoyong He 
108811e9eae4SChaoyong He 	return read_size;
108911e9eae4SChaoyong He }
109011e9eae4SChaoyong He 
109111e9eae4SChaoyong He /*
109211e9eae4SChaoyong He  * NOTE: The only caller rte_eth_xstats_get_by_id() ensures dev,
109311e9eae4SChaoyong He  * ids, values and n are valid, and non-NULL.
109411e9eae4SChaoyong He  */
109511e9eae4SChaoyong He int
109611e9eae4SChaoyong He nfp_net_xstats_get_by_id(struct rte_eth_dev *dev,
109711e9eae4SChaoyong He 		const uint64_t *ids,
109811e9eae4SChaoyong He 		uint64_t *values,
109911e9eae4SChaoyong He 		unsigned int n)
110011e9eae4SChaoyong He {
110111e9eae4SChaoyong He 	uint32_t i;
110211e9eae4SChaoyong He 	uint32_t read_size;
110311e9eae4SChaoyong He 
110411e9eae4SChaoyong He 	/* Read at most NFP xstats number of values. */
110511e9eae4SChaoyong He 	read_size = RTE_MIN(n, nfp_net_xstats_size(dev));
110611e9eae4SChaoyong He 
110711e9eae4SChaoyong He 	for (i = 0; i < read_size; i++) {
110811e9eae4SChaoyong He 		const struct nfp_xstat *xstat;
110911e9eae4SChaoyong He 
111011e9eae4SChaoyong He 		/* Make sure index is valid for device. */
111111e9eae4SChaoyong He 		xstat = nfp_net_xstats_info(dev, ids[i]);
111211e9eae4SChaoyong He 		if (xstat == NULL)
111311e9eae4SChaoyong He 			return -EINVAL;
111411e9eae4SChaoyong He 
111511e9eae4SChaoyong He 		values[i] = nfp_net_xstats_value(dev, ids[i], false);
111611e9eae4SChaoyong He 	}
111711e9eae4SChaoyong He 
111811e9eae4SChaoyong He 	return read_size;
111911e9eae4SChaoyong He }
112011e9eae4SChaoyong He 
112111e9eae4SChaoyong He int
112211e9eae4SChaoyong He nfp_net_xstats_reset(struct rte_eth_dev *dev)
112311e9eae4SChaoyong He {
112411e9eae4SChaoyong He 	uint32_t id;
112511e9eae4SChaoyong He 	uint32_t read_size;
112611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
112711e9eae4SChaoyong He 
1128b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
112911e9eae4SChaoyong He 	read_size = nfp_net_xstats_size(dev);
113011e9eae4SChaoyong He 
113111e9eae4SChaoyong He 	for (id = 0; id < read_size; id++) {
113211e9eae4SChaoyong He 		hw->eth_xstats_base[id].id = id;
113311e9eae4SChaoyong He 		hw->eth_xstats_base[id].value = nfp_net_xstats_value(dev, id, true);
113411e9eae4SChaoyong He 	}
113511e9eae4SChaoyong He 
113611e9eae4SChaoyong He 	/* Successfully reset xstats, now call function to reset basic stats. */
113711e9eae4SChaoyong He 	return nfp_net_stats_reset(dev);
113811e9eae4SChaoyong He }
113911e9eae4SChaoyong He 
114011e9eae4SChaoyong He void
114111e9eae4SChaoyong He nfp_net_rx_desc_limits(struct nfp_net_hw *hw,
114211e9eae4SChaoyong He 		uint16_t *min_rx_desc,
114311e9eae4SChaoyong He 		uint16_t *max_rx_desc)
114411e9eae4SChaoyong He {
114511e9eae4SChaoyong He 	*max_rx_desc = hw->dev_info->max_qc_size;
114611e9eae4SChaoyong He 	*min_rx_desc = hw->dev_info->min_qc_size;
114711e9eae4SChaoyong He }
114811e9eae4SChaoyong He 
114911e9eae4SChaoyong He void
115011e9eae4SChaoyong He nfp_net_tx_desc_limits(struct nfp_net_hw *hw,
115111e9eae4SChaoyong He 		uint16_t *min_tx_desc,
115211e9eae4SChaoyong He 		uint16_t *max_tx_desc)
115311e9eae4SChaoyong He {
115411e9eae4SChaoyong He 	uint16_t tx_dpp;
115511e9eae4SChaoyong He 
115611e9eae4SChaoyong He 	if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
115711e9eae4SChaoyong He 		tx_dpp = NFD3_TX_DESC_PER_PKT;
115811e9eae4SChaoyong He 	else
115911e9eae4SChaoyong He 		tx_dpp = NFDK_TX_DESC_PER_SIMPLE_PKT;
116011e9eae4SChaoyong He 
116111e9eae4SChaoyong He 	*max_tx_desc = hw->dev_info->max_qc_size / tx_dpp;
116211e9eae4SChaoyong He 	*min_tx_desc = hw->dev_info->min_qc_size / tx_dpp;
116311e9eae4SChaoyong He }
116411e9eae4SChaoyong He 
116511e9eae4SChaoyong He int
116611e9eae4SChaoyong He nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
116711e9eae4SChaoyong He {
11684a9bb682SChaoyong He 	uint32_t cap;
116911e9eae4SChaoyong He 	uint32_t cap_extend;
117011e9eae4SChaoyong He 	uint16_t min_rx_desc;
117111e9eae4SChaoyong He 	uint16_t max_rx_desc;
117211e9eae4SChaoyong He 	uint16_t min_tx_desc;
117311e9eae4SChaoyong He 	uint16_t max_tx_desc;
117411e9eae4SChaoyong He 	struct nfp_net_hw *hw;
117511e9eae4SChaoyong He 
1176b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
117711e9eae4SChaoyong He 
117811e9eae4SChaoyong He 	nfp_net_rx_desc_limits(hw, &min_rx_desc, &max_rx_desc);
117911e9eae4SChaoyong He 	nfp_net_tx_desc_limits(hw, &min_tx_desc, &max_tx_desc);
118011e9eae4SChaoyong He 
118111e9eae4SChaoyong He 	dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues;
118211e9eae4SChaoyong He 	dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues;
118311e9eae4SChaoyong He 	dev_info->min_rx_bufsize = RTE_ETHER_MIN_MTU;
11842f1bfbf4SJames Hershaw 	/*
11852f1bfbf4SJames Hershaw 	 * The maximum rx packet length is set to the maximum layer 3 MTU,
11862f1bfbf4SJames Hershaw 	 * plus layer 2, CRC and VLAN headers.
118711e9eae4SChaoyong He 	 * The maximum layer 3 MTU (max_mtu) is read from hardware,
118811e9eae4SChaoyong He 	 * which was set by the firmware loaded onto the card.
118911e9eae4SChaoyong He 	 */
11902f1bfbf4SJames Hershaw 	dev_info->max_rx_pktlen = hw->max_mtu + NFP_ETH_OVERHEAD;
119111e9eae4SChaoyong He 	dev_info->max_mtu = hw->max_mtu;
119211e9eae4SChaoyong He 	dev_info->min_mtu = RTE_ETHER_MIN_MTU;
119311e9eae4SChaoyong He 	/* Next should change when PF support is implemented */
119411e9eae4SChaoyong He 	dev_info->max_mac_addrs = 1;
119511e9eae4SChaoyong He 
11964a9bb682SChaoyong He 	cap = hw->super.cap;
11974a9bb682SChaoyong He 
11984a9bb682SChaoyong He 	if ((cap & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) != 0)
119911e9eae4SChaoyong He 		dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
120011e9eae4SChaoyong He 
12014a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0)
120211e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
120311e9eae4SChaoyong He 
12044a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0)
120511e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
120611e9eae4SChaoyong He 				RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
120711e9eae4SChaoyong He 				RTE_ETH_RX_OFFLOAD_TCP_CKSUM;
120811e9eae4SChaoyong He 
12094a9bb682SChaoyong He 	if ((cap & (NFP_NET_CFG_CTRL_TXVLAN | NFP_NET_CFG_CTRL_TXVLAN_V2)) != 0)
121011e9eae4SChaoyong He 		dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
121111e9eae4SChaoyong He 
12124a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_TXCSUM) != 0)
121311e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
121411e9eae4SChaoyong He 				RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
121511e9eae4SChaoyong He 				RTE_ETH_TX_OFFLOAD_TCP_CKSUM;
121611e9eae4SChaoyong He 
12174a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0) {
121811e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO;
1219df77f704SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_USO) != 0)
1220df77f704SChaoyong He 			dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_UDP_TSO;
12214a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_VXLAN) != 0)
122211e9eae4SChaoyong He 			dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO;
122311e9eae4SChaoyong He 	}
122411e9eae4SChaoyong He 
12254a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_GATHER) != 0)
122611e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
122711e9eae4SChaoyong He 
122875a76c73SChaoyong He 	cap_extend = hw->super.cap_ext;
122911e9eae4SChaoyong He 	if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
123011e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY;
123111e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY;
123211e9eae4SChaoyong He 	}
123311e9eae4SChaoyong He 
123411e9eae4SChaoyong He 	dev_info->default_rxconf = (struct rte_eth_rxconf) {
123511e9eae4SChaoyong He 		.rx_thresh = {
123611e9eae4SChaoyong He 			.pthresh = DEFAULT_RX_PTHRESH,
123711e9eae4SChaoyong He 			.hthresh = DEFAULT_RX_HTHRESH,
123811e9eae4SChaoyong He 			.wthresh = DEFAULT_RX_WTHRESH,
123911e9eae4SChaoyong He 		},
124011e9eae4SChaoyong He 		.rx_free_thresh = DEFAULT_RX_FREE_THRESH,
124111e9eae4SChaoyong He 		.rx_drop_en = 0,
124211e9eae4SChaoyong He 	};
124311e9eae4SChaoyong He 
124411e9eae4SChaoyong He 	dev_info->default_txconf = (struct rte_eth_txconf) {
124511e9eae4SChaoyong He 		.tx_thresh = {
124611e9eae4SChaoyong He 			.pthresh = DEFAULT_TX_PTHRESH,
124711e9eae4SChaoyong He 			.hthresh = DEFAULT_TX_HTHRESH,
124811e9eae4SChaoyong He 			.wthresh = DEFAULT_TX_WTHRESH,
124911e9eae4SChaoyong He 		},
125011e9eae4SChaoyong He 		.tx_free_thresh = DEFAULT_TX_FREE_THRESH,
125111e9eae4SChaoyong He 		.tx_rs_thresh = DEFAULT_TX_RSBIT_THRESH,
125211e9eae4SChaoyong He 	};
125311e9eae4SChaoyong He 
125411e9eae4SChaoyong He 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
125511e9eae4SChaoyong He 		.nb_max = max_rx_desc,
125611e9eae4SChaoyong He 		.nb_min = min_rx_desc,
125711e9eae4SChaoyong He 		.nb_align = NFP_ALIGN_RING_DESC,
125811e9eae4SChaoyong He 	};
125911e9eae4SChaoyong He 
126011e9eae4SChaoyong He 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
126111e9eae4SChaoyong He 		.nb_max = max_tx_desc,
126211e9eae4SChaoyong He 		.nb_min = min_tx_desc,
126311e9eae4SChaoyong He 		.nb_align = NFP_ALIGN_RING_DESC,
126411e9eae4SChaoyong He 		.nb_seg_max = NFP_TX_MAX_SEG,
126511e9eae4SChaoyong He 		.nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG,
126611e9eae4SChaoyong He 	};
126711e9eae4SChaoyong He 
12684a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_RSS_ANY) != 0) {
126911e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
1270*b458a2a0SLong Wu 		dev_info->flow_type_rss_offloads = NFP_NET_RSS_CAP;
127111e9eae4SChaoyong He 		dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
127211e9eae4SChaoyong He 		dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;
127311e9eae4SChaoyong He 	}
127411e9eae4SChaoyong He 
12753110ab73SZerun Fu 	/* Only PF supports getting speed capability. */
12763110ab73SZerun Fu 	if (hw->pf_dev != NULL)
12773110ab73SZerun Fu 		dev_info->speed_capa = hw->pf_dev->speed_capa;
127811e9eae4SChaoyong He 
127911e9eae4SChaoyong He 	return 0;
128011e9eae4SChaoyong He }
128111e9eae4SChaoyong He 
128211e9eae4SChaoyong He int
128311e9eae4SChaoyong He nfp_net_common_init(struct rte_pci_device *pci_dev,
128411e9eae4SChaoyong He 		struct nfp_net_hw *hw)
128511e9eae4SChaoyong He {
128611e9eae4SChaoyong He 	const int stride = 4;
128711e9eae4SChaoyong He 
128811e9eae4SChaoyong He 	hw->device_id = pci_dev->id.device_id;
128911e9eae4SChaoyong He 	hw->vendor_id = pci_dev->id.vendor_id;
129011e9eae4SChaoyong He 	hw->subsystem_device_id = pci_dev->id.subsystem_device_id;
129111e9eae4SChaoyong He 	hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id;
129211e9eae4SChaoyong He 
1293f58bde00SChaoyong He 	hw->max_rx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_RXRINGS);
1294f58bde00SChaoyong He 	hw->max_tx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_TXRINGS);
129511e9eae4SChaoyong He 	if (hw->max_rx_queues == 0 || hw->max_tx_queues == 0) {
129611e9eae4SChaoyong He 		PMD_INIT_LOG(ERR, "Device %s can not be used, there are no valid queue "
129711e9eae4SChaoyong He 				"pairs for use", pci_dev->name);
129811e9eae4SChaoyong He 		return -ENODEV;
129911e9eae4SChaoyong He 	}
130011e9eae4SChaoyong He 
130111e9eae4SChaoyong He 	nfp_net_cfg_read_version(hw);
130211e9eae4SChaoyong He 	if (!nfp_net_is_valid_nfd_version(hw->ver))
130311e9eae4SChaoyong He 		return -EINVAL;
130411e9eae4SChaoyong He 
130511e9eae4SChaoyong He 	if (nfp_net_check_dma_mask(hw, pci_dev->name) != 0)
130611e9eae4SChaoyong He 		return -ENODEV;
130711e9eae4SChaoyong He 
130811e9eae4SChaoyong He 	/* Get some of the read-only fields from the config BAR */
1309f58bde00SChaoyong He 	hw->super.cap = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP);
1310f58bde00SChaoyong He 	hw->super.cap_ext = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP_WORD1);
1311f58bde00SChaoyong He 	hw->max_mtu = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_MTU);
131211e9eae4SChaoyong He 	hw->flbufsz = DEFAULT_FLBUF_SIZE;
131311e9eae4SChaoyong He 
131411e9eae4SChaoyong He 	nfp_net_init_metadata_format(hw);
131511e9eae4SChaoyong He 
131611e9eae4SChaoyong He 	/* Read the Rx offset configured from firmware */
131711e9eae4SChaoyong He 	if (hw->ver.major < 2)
131811e9eae4SChaoyong He 		hw->rx_offset = NFP_NET_RX_OFFSET;
131911e9eae4SChaoyong He 	else
132065f6915dSChaoyong He 		hw->rx_offset = nn_cfg_readl(&hw->super, NFP_NET_CFG_RX_OFFSET);
132111e9eae4SChaoyong He 
1322b4b6988aSChaoyong He 	hw->super.ctrl = 0;
132311e9eae4SChaoyong He 	hw->stride_rx = stride;
132411e9eae4SChaoyong He 	hw->stride_tx = stride;
132511e9eae4SChaoyong He 
132611e9eae4SChaoyong He 	return 0;
132711e9eae4SChaoyong He }
132811e9eae4SChaoyong He 
132911e9eae4SChaoyong He const uint32_t *
1330ba6a168aSSivaramakrishnan Venkat nfp_net_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
133111e9eae4SChaoyong He {
133211e9eae4SChaoyong He 	struct nfp_net_hw *net_hw;
133311e9eae4SChaoyong He 	static const uint32_t ptypes[] = {
133411e9eae4SChaoyong He 		RTE_PTYPE_L2_ETHER,
133511e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4,
133611e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4_EXT,
133711e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6,
133811e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6_EXT,
133911e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
134011e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
134111e9eae4SChaoyong He 		RTE_PTYPE_L4_TCP,
134211e9eae4SChaoyong He 		RTE_PTYPE_L4_UDP,
134311e9eae4SChaoyong He 		RTE_PTYPE_L4_FRAG,
134411e9eae4SChaoyong He 		RTE_PTYPE_L4_NONFRAG,
134511e9eae4SChaoyong He 		RTE_PTYPE_L4_ICMP,
134611e9eae4SChaoyong He 		RTE_PTYPE_L4_SCTP,
134711e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_VXLAN,
134811e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_NVGRE,
134911e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_GENEVE,
135011e9eae4SChaoyong He 		RTE_PTYPE_INNER_L2_ETHER,
135111e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4,
135211e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4_EXT,
135311e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6,
135411e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6_EXT,
135511e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
135611e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
135711e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_TCP,
135811e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_UDP,
135911e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_FRAG,
136011e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_NONFRAG,
136111e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_ICMP,
136211e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_SCTP,
136311e9eae4SChaoyong He 	};
136411e9eae4SChaoyong He 
136511e9eae4SChaoyong He 	if (dev->rx_pkt_burst != nfp_net_recv_pkts)
136611e9eae4SChaoyong He 		return NULL;
136711e9eae4SChaoyong He 
13689d723baaSChaoyong He 	net_hw = dev->data->dev_private;
13699177c800SChaoyong He 	if ((net_hw->super.ctrl_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
137011e9eae4SChaoyong He 		return NULL;
137111e9eae4SChaoyong He 
1372ba6a168aSSivaramakrishnan Venkat 	*no_of_elements = RTE_DIM(ptypes);
137311e9eae4SChaoyong He 	return ptypes;
137411e9eae4SChaoyong He }
137511e9eae4SChaoyong He 
137611e9eae4SChaoyong He int
137711e9eae4SChaoyong He nfp_rx_queue_intr_enable(struct rte_eth_dev *dev,
137811e9eae4SChaoyong He 		uint16_t queue_id)
137911e9eae4SChaoyong He {
138011e9eae4SChaoyong He 	uint16_t base = 0;
138111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
138211e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
138311e9eae4SChaoyong He 
138411e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
138511e9eae4SChaoyong He 	if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO)
138611e9eae4SChaoyong He 		base = 1;
138711e9eae4SChaoyong He 
138811e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
138911e9eae4SChaoyong He 	rte_wmb();
139011e9eae4SChaoyong He 
1391b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
1392f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id),
139311e9eae4SChaoyong He 			NFP_NET_CFG_ICR_UNMASKED);
139411e9eae4SChaoyong He 	return 0;
139511e9eae4SChaoyong He }
139611e9eae4SChaoyong He 
139711e9eae4SChaoyong He int
139811e9eae4SChaoyong He nfp_rx_queue_intr_disable(struct rte_eth_dev *dev,
139911e9eae4SChaoyong He 		uint16_t queue_id)
140011e9eae4SChaoyong He {
140111e9eae4SChaoyong He 	uint16_t base = 0;
140211e9eae4SChaoyong He 	struct nfp_net_hw *hw;
140311e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
140411e9eae4SChaoyong He 
140511e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
140611e9eae4SChaoyong He 	if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO)
140711e9eae4SChaoyong He 		base = 1;
140811e9eae4SChaoyong He 
140911e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
141011e9eae4SChaoyong He 	rte_wmb();
141111e9eae4SChaoyong He 
1412b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
1413f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), NFP_NET_CFG_ICR_RXTX);
141411e9eae4SChaoyong He 
141511e9eae4SChaoyong He 	return 0;
141611e9eae4SChaoyong He }
141711e9eae4SChaoyong He 
141811e9eae4SChaoyong He static void
141911e9eae4SChaoyong He nfp_net_dev_link_status_print(struct rte_eth_dev *dev)
142011e9eae4SChaoyong He {
142111e9eae4SChaoyong He 	struct rte_eth_link link;
142211e9eae4SChaoyong He 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
142311e9eae4SChaoyong He 
142411e9eae4SChaoyong He 	rte_eth_linkstatus_get(dev, &link);
142511e9eae4SChaoyong He 	if (link.link_status != 0)
142611e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s",
142711e9eae4SChaoyong He 				dev->data->port_id, link.link_speed,
142811e9eae4SChaoyong He 				link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX ?
142911e9eae4SChaoyong He 				"full-duplex" : "half-duplex");
143011e9eae4SChaoyong He 	else
143111e9eae4SChaoyong He 		PMD_DRV_LOG(INFO, " Port %d: Link Down", dev->data->port_id);
143211e9eae4SChaoyong He 
143311e9eae4SChaoyong He 	PMD_DRV_LOG(INFO, "PCI Address: " PCI_PRI_FMT,
143411e9eae4SChaoyong He 			pci_dev->addr.domain, pci_dev->addr.bus,
143511e9eae4SChaoyong He 			pci_dev->addr.devid, pci_dev->addr.function);
143611e9eae4SChaoyong He }
143711e9eae4SChaoyong He 
143811e9eae4SChaoyong He /*
143911e9eae4SChaoyong He  * Unmask an interrupt
144011e9eae4SChaoyong He  *
144111e9eae4SChaoyong He  * If MSI-X auto-masking is enabled clear the mask bit, otherwise
144211e9eae4SChaoyong He  * clear the ICR for the entry.
144311e9eae4SChaoyong He  */
144494d0631aSPeng Zhang void
144511e9eae4SChaoyong He nfp_net_irq_unmask(struct rte_eth_dev *dev)
144611e9eae4SChaoyong He {
144711e9eae4SChaoyong He 	struct nfp_net_hw *hw;
144811e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
144911e9eae4SChaoyong He 
1450b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
145111e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
145211e9eae4SChaoyong He 
145311e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
145411e9eae4SChaoyong He 	rte_wmb();
145511e9eae4SChaoyong He 
1456b4b6988aSChaoyong He 	if ((hw->super.ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) != 0) {
145711e9eae4SChaoyong He 		/* If MSI-X auto-masking is used, clear the entry */
145811e9eae4SChaoyong He 		rte_intr_ack(pci_dev->intr_handle);
145911e9eae4SChaoyong He 	} else {
1460f58bde00SChaoyong He 		nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(NFP_NET_IRQ_LSC_IDX),
146111e9eae4SChaoyong He 				NFP_NET_CFG_ICR_UNMASKED);
146211e9eae4SChaoyong He 	}
146311e9eae4SChaoyong He }
146411e9eae4SChaoyong He 
146511e9eae4SChaoyong He /**
146611e9eae4SChaoyong He  * Interrupt handler which shall be registered for alarm callback for delayed
146711e9eae4SChaoyong He  * handling specific interrupt to wait for the stable nic state. As the NIC
146811e9eae4SChaoyong He  * interrupt state is not stable for nfp after link is just down, it needs
146911e9eae4SChaoyong He  * to wait 4 seconds to get the stable status.
147011e9eae4SChaoyong He  *
147111e9eae4SChaoyong He  * @param param
147211e9eae4SChaoyong He  *   The address of parameter (struct rte_eth_dev *)
147311e9eae4SChaoyong He  */
147411e9eae4SChaoyong He void
147511e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler(void *param)
147611e9eae4SChaoyong He {
147711e9eae4SChaoyong He 	struct rte_eth_dev *dev = param;
147811e9eae4SChaoyong He 
147911e9eae4SChaoyong He 	nfp_net_link_update(dev, 0);
148011e9eae4SChaoyong He 	rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
148111e9eae4SChaoyong He 
148211e9eae4SChaoyong He 	nfp_net_dev_link_status_print(dev);
148311e9eae4SChaoyong He 
148411e9eae4SChaoyong He 	/* Unmasking */
148511e9eae4SChaoyong He 	nfp_net_irq_unmask(dev);
148611e9eae4SChaoyong He }
148711e9eae4SChaoyong He 
148811e9eae4SChaoyong He void
148911e9eae4SChaoyong He nfp_net_dev_interrupt_handler(void *param)
149011e9eae4SChaoyong He {
149111e9eae4SChaoyong He 	int64_t timeout;
149211e9eae4SChaoyong He 	struct rte_eth_link link;
149311e9eae4SChaoyong He 	struct rte_eth_dev *dev = param;
149411e9eae4SChaoyong He 
149511e9eae4SChaoyong He 	PMD_DRV_LOG(DEBUG, "We got a LSC interrupt!!!");
149611e9eae4SChaoyong He 
149711e9eae4SChaoyong He 	rte_eth_linkstatus_get(dev, &link);
149811e9eae4SChaoyong He 
149911e9eae4SChaoyong He 	nfp_net_link_update(dev, 0);
150011e9eae4SChaoyong He 
150111e9eae4SChaoyong He 	/* Likely to up */
150211e9eae4SChaoyong He 	if (link.link_status == 0) {
150311e9eae4SChaoyong He 		/* Handle it 1 sec later, wait it being stable */
150411e9eae4SChaoyong He 		timeout = NFP_NET_LINK_UP_CHECK_TIMEOUT;
150511e9eae4SChaoyong He 	} else {  /* Likely to down */
150611e9eae4SChaoyong He 		/* Handle it 4 sec later, wait it being stable */
150711e9eae4SChaoyong He 		timeout = NFP_NET_LINK_DOWN_CHECK_TIMEOUT;
150811e9eae4SChaoyong He 	}
150911e9eae4SChaoyong He 
151011e9eae4SChaoyong He 	if (rte_eal_alarm_set(timeout * 1000,
151111e9eae4SChaoyong He 			nfp_net_dev_interrupt_delayed_handler,
151211e9eae4SChaoyong He 			(void *)dev) != 0) {
151311e9eae4SChaoyong He 		PMD_INIT_LOG(ERR, "Error setting alarm");
151411e9eae4SChaoyong He 		/* Unmasking */
151511e9eae4SChaoyong He 		nfp_net_irq_unmask(dev);
151611e9eae4SChaoyong He 	}
151711e9eae4SChaoyong He }
151811e9eae4SChaoyong He 
151911e9eae4SChaoyong He int
152011e9eae4SChaoyong He nfp_net_dev_mtu_set(struct rte_eth_dev *dev,
152111e9eae4SChaoyong He 		uint16_t mtu)
152211e9eae4SChaoyong He {
152311e9eae4SChaoyong He 	struct nfp_net_hw *hw;
152411e9eae4SChaoyong He 
1525b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
152611e9eae4SChaoyong He 
152711e9eae4SChaoyong He 	/* MTU setting is forbidden if port is started */
152811e9eae4SChaoyong He 	if (dev->data->dev_started) {
152911e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "port %d must be stopped before configuration",
153011e9eae4SChaoyong He 				dev->data->port_id);
153111e9eae4SChaoyong He 		return -EBUSY;
153211e9eae4SChaoyong He 	}
153311e9eae4SChaoyong He 
153411e9eae4SChaoyong He 	/* MTU larger than current mbufsize not supported */
153511e9eae4SChaoyong He 	if (mtu > hw->flbufsz) {
153611e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "MTU (%u) larger than current mbufsize (%u) not supported",
153711e9eae4SChaoyong He 				mtu, hw->flbufsz);
153811e9eae4SChaoyong He 		return -ERANGE;
153911e9eae4SChaoyong He 	}
154011e9eae4SChaoyong He 
154111e9eae4SChaoyong He 	/* Writing to configuration space */
1542f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, mtu);
154311e9eae4SChaoyong He 
154411e9eae4SChaoyong He 	hw->mtu = mtu;
154511e9eae4SChaoyong He 
154611e9eae4SChaoyong He 	return 0;
154711e9eae4SChaoyong He }
154811e9eae4SChaoyong He 
154911e9eae4SChaoyong He int
155011e9eae4SChaoyong He nfp_net_vlan_offload_set(struct rte_eth_dev *dev,
155111e9eae4SChaoyong He 		int mask)
155211e9eae4SChaoyong He {
155311e9eae4SChaoyong He 	int ret;
155411e9eae4SChaoyong He 	uint32_t update;
155511e9eae4SChaoyong He 	uint32_t new_ctrl;
155672d1dea6SChaoyong He 	struct nfp_hw *hw;
155711e9eae4SChaoyong He 	uint64_t rx_offload;
155872d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
155911e9eae4SChaoyong He 	uint32_t rxvlan_ctrl = 0;
156011e9eae4SChaoyong He 
1561b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
156272d1dea6SChaoyong He 	hw = &net_hw->super;
156311e9eae4SChaoyong He 	rx_offload = dev->data->dev_conf.rxmode.offloads;
156472d1dea6SChaoyong He 	new_ctrl = hw->ctrl;
156511e9eae4SChaoyong He 
156611e9eae4SChaoyong He 	/* VLAN stripping setting */
156711e9eae4SChaoyong He 	if ((mask & RTE_ETH_VLAN_STRIP_MASK) != 0) {
156872d1dea6SChaoyong He 		nfp_net_enable_rxvlan_cap(net_hw, &rxvlan_ctrl);
156911e9eae4SChaoyong He 		if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0)
157011e9eae4SChaoyong He 			new_ctrl |= rxvlan_ctrl;
157111e9eae4SChaoyong He 		else
157211e9eae4SChaoyong He 			new_ctrl &= ~rxvlan_ctrl;
157311e9eae4SChaoyong He 	}
157411e9eae4SChaoyong He 
157511e9eae4SChaoyong He 	/* QinQ stripping setting */
157611e9eae4SChaoyong He 	if ((mask & RTE_ETH_QINQ_STRIP_MASK) != 0) {
157711e9eae4SChaoyong He 		if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0)
157811e9eae4SChaoyong He 			new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
157911e9eae4SChaoyong He 		else
158011e9eae4SChaoyong He 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ;
158111e9eae4SChaoyong He 	}
158211e9eae4SChaoyong He 
158372d1dea6SChaoyong He 	if (new_ctrl == hw->ctrl)
158411e9eae4SChaoyong He 		return 0;
158511e9eae4SChaoyong He 
158611e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
158711e9eae4SChaoyong He 
158872d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
158911e9eae4SChaoyong He 	if (ret != 0)
159011e9eae4SChaoyong He 		return ret;
159111e9eae4SChaoyong He 
159272d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
159311e9eae4SChaoyong He 
159411e9eae4SChaoyong He 	return 0;
159511e9eae4SChaoyong He }
159611e9eae4SChaoyong He 
159711e9eae4SChaoyong He static int
159811e9eae4SChaoyong He nfp_net_rss_reta_write(struct rte_eth_dev *dev,
159911e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
160011e9eae4SChaoyong He 		uint16_t reta_size)
160111e9eae4SChaoyong He {
160211e9eae4SChaoyong He 	uint16_t i;
160311e9eae4SChaoyong He 	uint16_t j;
160411e9eae4SChaoyong He 	uint16_t idx;
160511e9eae4SChaoyong He 	uint8_t mask;
160611e9eae4SChaoyong He 	uint32_t reta;
160711e9eae4SChaoyong He 	uint16_t shift;
16084a9bb682SChaoyong He 	struct nfp_hw *hw;
16094a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
161011e9eae4SChaoyong He 
1611b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
16124a9bb682SChaoyong He 	hw = &net_hw->super;
161311e9eae4SChaoyong He 
161411e9eae4SChaoyong He 	if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) {
161511e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%hu)"
161611e9eae4SChaoyong He 				" doesn't match hardware can supported (%d)",
161711e9eae4SChaoyong He 				reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
161811e9eae4SChaoyong He 		return -EINVAL;
161911e9eae4SChaoyong He 	}
162011e9eae4SChaoyong He 
162111e9eae4SChaoyong He 	/*
162211e9eae4SChaoyong He 	 * Update Redirection Table. There are 128 8bit-entries which can be
162311e9eae4SChaoyong He 	 * manage as 32 32bit-entries.
162411e9eae4SChaoyong He 	 */
162511e9eae4SChaoyong He 	for (i = 0; i < reta_size; i += 4) {
162611e9eae4SChaoyong He 		/* Handling 4 RSS entries per loop */
162711e9eae4SChaoyong He 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
162811e9eae4SChaoyong He 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
162911e9eae4SChaoyong He 		mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF);
163011e9eae4SChaoyong He 		if (mask == 0)
163111e9eae4SChaoyong He 			continue;
163211e9eae4SChaoyong He 
163311e9eae4SChaoyong He 		reta = 0;
163411e9eae4SChaoyong He 
163511e9eae4SChaoyong He 		/* If all 4 entries were set, don't need read RETA register */
163611e9eae4SChaoyong He 		if (mask != 0xF)
16374a9bb682SChaoyong He 			reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + i);
163811e9eae4SChaoyong He 
163911e9eae4SChaoyong He 		for (j = 0; j < 4; j++) {
164011e9eae4SChaoyong He 			if ((mask & (0x1 << j)) == 0)
164111e9eae4SChaoyong He 				continue;
164211e9eae4SChaoyong He 
164311e9eae4SChaoyong He 			/* Clearing the entry bits */
164411e9eae4SChaoyong He 			if (mask != 0xF)
164511e9eae4SChaoyong He 				reta &= ~(0xFF << (8 * j));
164611e9eae4SChaoyong He 
164711e9eae4SChaoyong He 			reta |= reta_conf[idx].reta[shift + j] << (8 * j);
164811e9eae4SChaoyong He 		}
164911e9eae4SChaoyong He 
16504a9bb682SChaoyong He 		nn_cfg_writel(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift, reta);
165111e9eae4SChaoyong He 	}
165211e9eae4SChaoyong He 
165311e9eae4SChaoyong He 	return 0;
165411e9eae4SChaoyong He }
165511e9eae4SChaoyong He 
165611e9eae4SChaoyong He /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
165711e9eae4SChaoyong He int
165811e9eae4SChaoyong He nfp_net_reta_update(struct rte_eth_dev *dev,
165911e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
166011e9eae4SChaoyong He 		uint16_t reta_size)
166111e9eae4SChaoyong He {
166211e9eae4SChaoyong He 	int ret;
166311e9eae4SChaoyong He 	uint32_t update;
166472d1dea6SChaoyong He 	struct nfp_hw *hw;
166572d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
166611e9eae4SChaoyong He 
1667b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
166872d1dea6SChaoyong He 	hw = &net_hw->super;
166972d1dea6SChaoyong He 
167072d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
167111e9eae4SChaoyong He 		return -EINVAL;
167211e9eae4SChaoyong He 
167311e9eae4SChaoyong He 	ret = nfp_net_rss_reta_write(dev, reta_conf, reta_size);
167411e9eae4SChaoyong He 	if (ret != 0)
167511e9eae4SChaoyong He 		return ret;
167611e9eae4SChaoyong He 
167711e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_RSS;
167811e9eae4SChaoyong He 
167972d1dea6SChaoyong He 	if (nfp_reconfig(hw, hw->ctrl, update) != 0)
168011e9eae4SChaoyong He 		return -EIO;
168111e9eae4SChaoyong He 
168211e9eae4SChaoyong He 	return 0;
168311e9eae4SChaoyong He }
168411e9eae4SChaoyong He 
168511e9eae4SChaoyong He /* Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. */
168611e9eae4SChaoyong He int
168711e9eae4SChaoyong He nfp_net_reta_query(struct rte_eth_dev *dev,
168811e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
168911e9eae4SChaoyong He 		uint16_t reta_size)
169011e9eae4SChaoyong He {
169111e9eae4SChaoyong He 	uint16_t i;
169211e9eae4SChaoyong He 	uint16_t j;
169311e9eae4SChaoyong He 	uint16_t idx;
169411e9eae4SChaoyong He 	uint8_t mask;
169511e9eae4SChaoyong He 	uint32_t reta;
169611e9eae4SChaoyong He 	uint16_t shift;
16974a9bb682SChaoyong He 	struct nfp_hw *hw;
16984a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
169911e9eae4SChaoyong He 
1700b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
17014a9bb682SChaoyong He 	hw = &net_hw->super;
17024a9bb682SChaoyong He 
17034a9bb682SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
170411e9eae4SChaoyong He 		return -EINVAL;
170511e9eae4SChaoyong He 
170611e9eae4SChaoyong He 	if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) {
170711e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d)"
170811e9eae4SChaoyong He 				" doesn't match hardware can supported (%d)",
170911e9eae4SChaoyong He 				reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
171011e9eae4SChaoyong He 		return -EINVAL;
171111e9eae4SChaoyong He 	}
171211e9eae4SChaoyong He 
171311e9eae4SChaoyong He 	/*
171411e9eae4SChaoyong He 	 * Reading Redirection Table. There are 128 8bit-entries which can be
171511e9eae4SChaoyong He 	 * manage as 32 32bit-entries.
171611e9eae4SChaoyong He 	 */
171711e9eae4SChaoyong He 	for (i = 0; i < reta_size; i += 4) {
171811e9eae4SChaoyong He 		/* Handling 4 RSS entries per loop */
171911e9eae4SChaoyong He 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
172011e9eae4SChaoyong He 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
172111e9eae4SChaoyong He 		mask = (reta_conf[idx].mask >> shift) & 0xF;
172211e9eae4SChaoyong He 
172311e9eae4SChaoyong He 		if (mask == 0)
172411e9eae4SChaoyong He 			continue;
172511e9eae4SChaoyong He 
17264a9bb682SChaoyong He 		reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift);
172711e9eae4SChaoyong He 		for (j = 0; j < 4; j++) {
172811e9eae4SChaoyong He 			if ((mask & (0x1 << j)) == 0)
172911e9eae4SChaoyong He 				continue;
173011e9eae4SChaoyong He 
173111e9eae4SChaoyong He 			reta_conf[idx].reta[shift + j] =
173211e9eae4SChaoyong He 					(uint8_t)((reta >> (8 * j)) & 0xF);
173311e9eae4SChaoyong He 		}
173411e9eae4SChaoyong He 	}
173511e9eae4SChaoyong He 
173611e9eae4SChaoyong He 	return 0;
173711e9eae4SChaoyong He }
173811e9eae4SChaoyong He 
173911e9eae4SChaoyong He static int
174011e9eae4SChaoyong He nfp_net_rss_hash_write(struct rte_eth_dev *dev,
174111e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
174211e9eae4SChaoyong He {
174311e9eae4SChaoyong He 	uint8_t i;
174411e9eae4SChaoyong He 	uint8_t key;
174511e9eae4SChaoyong He 	uint64_t rss_hf;
17464a9bb682SChaoyong He 	struct nfp_hw *hw;
17474a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
174811e9eae4SChaoyong He 	uint32_t cfg_rss_ctrl = 0;
174911e9eae4SChaoyong He 
1750b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
17514a9bb682SChaoyong He 	hw = &net_hw->super;
175211e9eae4SChaoyong He 
175311e9eae4SChaoyong He 	/* Writing the key byte by byte */
175411e9eae4SChaoyong He 	for (i = 0; i < rss_conf->rss_key_len; i++) {
175511e9eae4SChaoyong He 		memcpy(&key, &rss_conf->rss_key[i], 1);
17564a9bb682SChaoyong He 		nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY + i, key);
175711e9eae4SChaoyong He 	}
175811e9eae4SChaoyong He 
175911e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
176011e9eae4SChaoyong He 
176111e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_IPV4) != 0)
176211e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4;
176311e9eae4SChaoyong He 
176411e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) != 0)
176511e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_TCP;
176611e9eae4SChaoyong He 
176711e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) != 0)
176811e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_UDP;
176911e9eae4SChaoyong He 
177011e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) != 0)
177111e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_SCTP;
177211e9eae4SChaoyong He 
177311e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_IPV6) != 0)
177411e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6;
177511e9eae4SChaoyong He 
177611e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) != 0)
177711e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_TCP;
177811e9eae4SChaoyong He 
177911e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) != 0)
178011e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_UDP;
178111e9eae4SChaoyong He 
178211e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) != 0)
178311e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_SCTP;
178411e9eae4SChaoyong He 
178511e9eae4SChaoyong He 	cfg_rss_ctrl |= NFP_NET_CFG_RSS_MASK;
1786*b458a2a0SLong Wu 
1787*b458a2a0SLong Wu 	if (rte_eth_dev_is_repr(dev))
1788*b458a2a0SLong Wu 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_CRC32;
1789*b458a2a0SLong Wu 	else
179011e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_TOEPLITZ;
179111e9eae4SChaoyong He 
179211e9eae4SChaoyong He 	/* Configuring where to apply the RSS hash */
17934a9bb682SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_RSS_CTRL, cfg_rss_ctrl);
179411e9eae4SChaoyong He 
179511e9eae4SChaoyong He 	/* Writing the key size */
17964a9bb682SChaoyong He 	nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY_SZ, rss_conf->rss_key_len);
179711e9eae4SChaoyong He 
179811e9eae4SChaoyong He 	return 0;
179911e9eae4SChaoyong He }
180011e9eae4SChaoyong He 
180111e9eae4SChaoyong He int
180211e9eae4SChaoyong He nfp_net_rss_hash_update(struct rte_eth_dev *dev,
180311e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
180411e9eae4SChaoyong He {
180511e9eae4SChaoyong He 	uint32_t update;
180611e9eae4SChaoyong He 	uint64_t rss_hf;
180772d1dea6SChaoyong He 	struct nfp_hw *hw;
180872d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
180911e9eae4SChaoyong He 
1810b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
181172d1dea6SChaoyong He 	hw = &net_hw->super;
181211e9eae4SChaoyong He 
181311e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
181411e9eae4SChaoyong He 
181511e9eae4SChaoyong He 	/* Checking if RSS is enabled */
181672d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) {
181711e9eae4SChaoyong He 		if (rss_hf != 0) {
181811e9eae4SChaoyong He 			PMD_DRV_LOG(ERR, "RSS unsupported");
181911e9eae4SChaoyong He 			return -EINVAL;
182011e9eae4SChaoyong He 		}
182111e9eae4SChaoyong He 
182211e9eae4SChaoyong He 		return 0; /* Nothing to do */
182311e9eae4SChaoyong He 	}
182411e9eae4SChaoyong He 
182511e9eae4SChaoyong He 	if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) {
182611e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "RSS hash key too long");
182711e9eae4SChaoyong He 		return -EINVAL;
182811e9eae4SChaoyong He 	}
182911e9eae4SChaoyong He 
183011e9eae4SChaoyong He 	nfp_net_rss_hash_write(dev, rss_conf);
183111e9eae4SChaoyong He 
183211e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_RSS;
183311e9eae4SChaoyong He 
183472d1dea6SChaoyong He 	if (nfp_reconfig(hw, hw->ctrl, update) != 0)
183511e9eae4SChaoyong He 		return -EIO;
183611e9eae4SChaoyong He 
183711e9eae4SChaoyong He 	return 0;
183811e9eae4SChaoyong He }
183911e9eae4SChaoyong He 
184011e9eae4SChaoyong He int
184111e9eae4SChaoyong He nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev,
184211e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
184311e9eae4SChaoyong He {
184411e9eae4SChaoyong He 	uint8_t i;
184511e9eae4SChaoyong He 	uint8_t key;
184611e9eae4SChaoyong He 	uint64_t rss_hf;
18474a9bb682SChaoyong He 	struct nfp_hw *hw;
184811e9eae4SChaoyong He 	uint32_t cfg_rss_ctrl;
18494a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
185011e9eae4SChaoyong He 
1851b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
18524a9bb682SChaoyong He 	hw = &net_hw->super;
185311e9eae4SChaoyong He 
18544a9bb682SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
185511e9eae4SChaoyong He 		return -EINVAL;
185611e9eae4SChaoyong He 
185711e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
18584a9bb682SChaoyong He 	cfg_rss_ctrl = nn_cfg_readl(hw, NFP_NET_CFG_RSS_CTRL);
185911e9eae4SChaoyong He 
186011e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4) != 0)
186111e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_IPV4;
186211e9eae4SChaoyong He 
186311e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_TCP) != 0)
186411e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
186511e9eae4SChaoyong He 
186611e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_TCP) != 0)
186711e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
186811e9eae4SChaoyong He 
186911e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_UDP) != 0)
187011e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
187111e9eae4SChaoyong He 
187211e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_UDP) != 0)
187311e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
187411e9eae4SChaoyong He 
187511e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6) != 0)
187611e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_IPV6;
187711e9eae4SChaoyong He 
187811e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_SCTP) != 0)
187911e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_SCTP;
188011e9eae4SChaoyong He 
188111e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_SCTP) != 0)
188211e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_SCTP;
188311e9eae4SChaoyong He 
188411e9eae4SChaoyong He 	/* Propagate current RSS hash functions to caller */
188511e9eae4SChaoyong He 	rss_conf->rss_hf = rss_hf;
188611e9eae4SChaoyong He 
188711e9eae4SChaoyong He 	/* Reading the key size */
18884a9bb682SChaoyong He 	rss_conf->rss_key_len = nn_cfg_readl(hw, NFP_NET_CFG_RSS_KEY_SZ);
188911e9eae4SChaoyong He 
189011e9eae4SChaoyong He 	/* Reading the key byte a byte */
189111e9eae4SChaoyong He 	for (i = 0; i < rss_conf->rss_key_len; i++) {
18924a9bb682SChaoyong He 		key = nn_cfg_readb(hw, NFP_NET_CFG_RSS_KEY + i);
189311e9eae4SChaoyong He 		memcpy(&rss_conf->rss_key[i], &key, 1);
189411e9eae4SChaoyong He 	}
189511e9eae4SChaoyong He 
189611e9eae4SChaoyong He 	return 0;
189711e9eae4SChaoyong He }
189811e9eae4SChaoyong He 
189911e9eae4SChaoyong He int
190011e9eae4SChaoyong He nfp_net_rss_config_default(struct rte_eth_dev *dev)
190111e9eae4SChaoyong He {
190211e9eae4SChaoyong He 	int ret;
190311e9eae4SChaoyong He 	uint8_t i;
190411e9eae4SChaoyong He 	uint8_t j;
190511e9eae4SChaoyong He 	uint16_t queue = 0;
190611e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
190711e9eae4SChaoyong He 	struct rte_eth_rss_conf rss_conf;
190811e9eae4SChaoyong He 	uint16_t rx_queues = dev->data->nb_rx_queues;
190911e9eae4SChaoyong He 	struct rte_eth_rss_reta_entry64 nfp_reta_conf[2];
191011e9eae4SChaoyong He 
191111e9eae4SChaoyong He 	nfp_reta_conf[0].mask = ~0x0;
191211e9eae4SChaoyong He 	nfp_reta_conf[1].mask = ~0x0;
191311e9eae4SChaoyong He 
191411e9eae4SChaoyong He 	for (i = 0; i < 0x40; i += 8) {
191511e9eae4SChaoyong He 		for (j = i; j < (i + 8); j++) {
191611e9eae4SChaoyong He 			nfp_reta_conf[0].reta[j] = queue;
191711e9eae4SChaoyong He 			nfp_reta_conf[1].reta[j] = queue++;
191811e9eae4SChaoyong He 			queue %= rx_queues;
191911e9eae4SChaoyong He 		}
192011e9eae4SChaoyong He 	}
192111e9eae4SChaoyong He 
192211e9eae4SChaoyong He 	ret = nfp_net_rss_reta_write(dev, nfp_reta_conf, 0x80);
192311e9eae4SChaoyong He 	if (ret != 0)
192411e9eae4SChaoyong He 		return ret;
192511e9eae4SChaoyong He 
192611e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
192711e9eae4SChaoyong He 	if (dev_conf == NULL) {
192811e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Wrong rss conf");
192911e9eae4SChaoyong He 		return -EINVAL;
193011e9eae4SChaoyong He 	}
193111e9eae4SChaoyong He 
193211e9eae4SChaoyong He 	rss_conf = dev_conf->rx_adv_conf.rss_conf;
193311e9eae4SChaoyong He 	ret = nfp_net_rss_hash_write(dev, &rss_conf);
193411e9eae4SChaoyong He 
193511e9eae4SChaoyong He 	return ret;
193611e9eae4SChaoyong He }
193711e9eae4SChaoyong He 
193811e9eae4SChaoyong He void
193911e9eae4SChaoyong He nfp_net_stop_rx_queue(struct rte_eth_dev *dev)
194011e9eae4SChaoyong He {
194111e9eae4SChaoyong He 	uint16_t i;
194211e9eae4SChaoyong He 	struct nfp_net_rxq *this_rx_q;
194311e9eae4SChaoyong He 
194411e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
194511e9eae4SChaoyong He 		this_rx_q = dev->data->rx_queues[i];
194611e9eae4SChaoyong He 		nfp_net_reset_rx_queue(this_rx_q);
194711e9eae4SChaoyong He 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
194811e9eae4SChaoyong He 	}
194911e9eae4SChaoyong He }
195011e9eae4SChaoyong He 
195111e9eae4SChaoyong He void
195211e9eae4SChaoyong He nfp_net_close_rx_queue(struct rte_eth_dev *dev)
195311e9eae4SChaoyong He {
195411e9eae4SChaoyong He 	uint16_t i;
195511e9eae4SChaoyong He 	struct nfp_net_rxq *this_rx_q;
195611e9eae4SChaoyong He 
195711e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
195811e9eae4SChaoyong He 		this_rx_q = dev->data->rx_queues[i];
195911e9eae4SChaoyong He 		nfp_net_reset_rx_queue(this_rx_q);
196011e9eae4SChaoyong He 		nfp_net_rx_queue_release(dev, i);
196111e9eae4SChaoyong He 	}
196211e9eae4SChaoyong He }
196311e9eae4SChaoyong He 
196411e9eae4SChaoyong He void
196511e9eae4SChaoyong He nfp_net_stop_tx_queue(struct rte_eth_dev *dev)
196611e9eae4SChaoyong He {
196711e9eae4SChaoyong He 	uint16_t i;
196811e9eae4SChaoyong He 	struct nfp_net_txq *this_tx_q;
196911e9eae4SChaoyong He 
197011e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
197111e9eae4SChaoyong He 		this_tx_q = dev->data->tx_queues[i];
197211e9eae4SChaoyong He 		nfp_net_reset_tx_queue(this_tx_q);
197311e9eae4SChaoyong He 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
197411e9eae4SChaoyong He 	}
197511e9eae4SChaoyong He }
197611e9eae4SChaoyong He 
197711e9eae4SChaoyong He void
197811e9eae4SChaoyong He nfp_net_close_tx_queue(struct rte_eth_dev *dev)
197911e9eae4SChaoyong He {
198011e9eae4SChaoyong He 	uint16_t i;
198111e9eae4SChaoyong He 	struct nfp_net_txq *this_tx_q;
198211e9eae4SChaoyong He 
198311e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
198411e9eae4SChaoyong He 		this_tx_q = dev->data->tx_queues[i];
198511e9eae4SChaoyong He 		nfp_net_reset_tx_queue(this_tx_q);
198611e9eae4SChaoyong He 		nfp_net_tx_queue_release(dev, i);
198711e9eae4SChaoyong He 	}
198811e9eae4SChaoyong He }
198911e9eae4SChaoyong He 
199011e9eae4SChaoyong He int
199172d1dea6SChaoyong He nfp_net_set_vxlan_port(struct nfp_net_hw *net_hw,
199211e9eae4SChaoyong He 		size_t idx,
199311e9eae4SChaoyong He 		uint16_t port)
199411e9eae4SChaoyong He {
199511e9eae4SChaoyong He 	int ret;
199611e9eae4SChaoyong He 	uint32_t i;
199772d1dea6SChaoyong He 	struct nfp_hw *hw = &net_hw->super;
199811e9eae4SChaoyong He 
199911e9eae4SChaoyong He 	if (idx >= NFP_NET_N_VXLAN_PORTS) {
200011e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The idx value is out of range.");
200111e9eae4SChaoyong He 		return -ERANGE;
200211e9eae4SChaoyong He 	}
200311e9eae4SChaoyong He 
200472d1dea6SChaoyong He 	net_hw->vxlan_ports[idx] = port;
200511e9eae4SChaoyong He 
200611e9eae4SChaoyong He 	for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) {
200772d1dea6SChaoyong He 		nn_cfg_writel(hw, NFP_NET_CFG_VXLAN_PORT + i * sizeof(port),
200872d1dea6SChaoyong He 				(net_hw->vxlan_ports[i + 1] << 16) | net_hw->vxlan_ports[i]);
200911e9eae4SChaoyong He 	}
201011e9eae4SChaoyong He 
201111e9eae4SChaoyong He 	rte_spinlock_lock(&hw->reconfig_lock);
201211e9eae4SChaoyong He 
201372d1dea6SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_VXLAN);
201411e9eae4SChaoyong He 	rte_wmb();
201511e9eae4SChaoyong He 
201672d1dea6SChaoyong He 	ret = nfp_reconfig_real(hw, NFP_NET_CFG_UPDATE_VXLAN);
201711e9eae4SChaoyong He 
201811e9eae4SChaoyong He 	rte_spinlock_unlock(&hw->reconfig_lock);
201911e9eae4SChaoyong He 
202011e9eae4SChaoyong He 	return ret;
202111e9eae4SChaoyong He }
202211e9eae4SChaoyong He 
202311e9eae4SChaoyong He /*
202411e9eae4SChaoyong He  * The firmware with NFD3 can not handle DMA address requiring more
202511e9eae4SChaoyong He  * than 40 bits.
202611e9eae4SChaoyong He  */
202711e9eae4SChaoyong He int
202811e9eae4SChaoyong He nfp_net_check_dma_mask(struct nfp_net_hw *hw,
202911e9eae4SChaoyong He 		char *name)
203011e9eae4SChaoyong He {
203111e9eae4SChaoyong He 	if (hw->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3 &&
203211e9eae4SChaoyong He 			rte_mem_check_dma_mask(40) != 0) {
203311e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "Device %s can't be used: restricted dma mask to 40 bits!",
203411e9eae4SChaoyong He 				name);
203511e9eae4SChaoyong He 		return -ENODEV;
203611e9eae4SChaoyong He 	}
203711e9eae4SChaoyong He 
203811e9eae4SChaoyong He 	return 0;
203911e9eae4SChaoyong He }
204011e9eae4SChaoyong He 
204111e9eae4SChaoyong He void
204211e9eae4SChaoyong He nfp_net_init_metadata_format(struct nfp_net_hw *hw)
204311e9eae4SChaoyong He {
204411e9eae4SChaoyong He 	/*
204511e9eae4SChaoyong He 	 * ABI 4.x and ctrl vNIC always use chained metadata, in other cases we allow use of
204611e9eae4SChaoyong He 	 * single metadata if only RSS(v1) is supported by hw capability, and RSS(v2)
204711e9eae4SChaoyong He 	 * also indicate that we are using chained metadata.
204811e9eae4SChaoyong He 	 */
204911e9eae4SChaoyong He 	if (hw->ver.major == 4) {
205011e9eae4SChaoyong He 		hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
205175a76c73SChaoyong He 	} else if ((hw->super.cap & NFP_NET_CFG_CTRL_CHAIN_META) != 0) {
205211e9eae4SChaoyong He 		hw->meta_format = NFP_NET_METAFORMAT_CHAINED;
205311e9eae4SChaoyong He 		/*
205475a76c73SChaoyong He 		 * RSS is incompatible with chained metadata. hw->super.cap just represents
205511e9eae4SChaoyong He 		 * firmware's ability rather than the firmware's configuration. We decide
205675a76c73SChaoyong He 		 * to reduce the confusion to allow us can use hw->super.cap to identify RSS later.
205711e9eae4SChaoyong He 		 */
205875a76c73SChaoyong He 		hw->super.cap &= ~NFP_NET_CFG_CTRL_RSS;
205911e9eae4SChaoyong He 	} else {
206011e9eae4SChaoyong He 		hw->meta_format = NFP_NET_METAFORMAT_SINGLE;
206111e9eae4SChaoyong He 	}
206211e9eae4SChaoyong He }
206311e9eae4SChaoyong He 
206411e9eae4SChaoyong He void
206511e9eae4SChaoyong He nfp_net_cfg_read_version(struct nfp_net_hw *hw)
206611e9eae4SChaoyong He {
206711e9eae4SChaoyong He 	union {
206811e9eae4SChaoyong He 		uint32_t whole;
206911e9eae4SChaoyong He 		struct nfp_net_fw_ver split;
207011e9eae4SChaoyong He 	} version;
207111e9eae4SChaoyong He 
2072f58bde00SChaoyong He 	version.whole = nn_cfg_readl(&hw->super, NFP_NET_CFG_VERSION);
207311e9eae4SChaoyong He 	hw->ver = version.split;
207411e9eae4SChaoyong He }
207511e9eae4SChaoyong He 
207611e9eae4SChaoyong He static void
207711e9eae4SChaoyong He nfp_net_get_nsp_info(struct nfp_net_hw *hw,
207811e9eae4SChaoyong He 		char *nsp_version)
207911e9eae4SChaoyong He {
208011e9eae4SChaoyong He 	struct nfp_nsp *nsp;
208111e9eae4SChaoyong He 
208211e9eae4SChaoyong He 	nsp = nfp_nsp_open(hw->cpp);
208311e9eae4SChaoyong He 	if (nsp == NULL)
208411e9eae4SChaoyong He 		return;
208511e9eae4SChaoyong He 
208611e9eae4SChaoyong He 	snprintf(nsp_version, FW_VER_LEN, "%hu.%hu",
208711e9eae4SChaoyong He 			nfp_nsp_get_abi_ver_major(nsp),
208811e9eae4SChaoyong He 			nfp_nsp_get_abi_ver_minor(nsp));
208911e9eae4SChaoyong He 
209011e9eae4SChaoyong He 	nfp_nsp_close(nsp);
209111e9eae4SChaoyong He }
209211e9eae4SChaoyong He 
209311e9eae4SChaoyong He static void
209411e9eae4SChaoyong He nfp_net_get_mip_name(struct nfp_net_hw *hw,
209511e9eae4SChaoyong He 		char *mip_name)
209611e9eae4SChaoyong He {
209711e9eae4SChaoyong He 	struct nfp_mip *mip;
209811e9eae4SChaoyong He 
209911e9eae4SChaoyong He 	mip = nfp_mip_open(hw->cpp);
210011e9eae4SChaoyong He 	if (mip == NULL)
210111e9eae4SChaoyong He 		return;
210211e9eae4SChaoyong He 
210311e9eae4SChaoyong He 	snprintf(mip_name, FW_VER_LEN, "%s", nfp_mip_name(mip));
210411e9eae4SChaoyong He 
210511e9eae4SChaoyong He 	nfp_mip_close(mip);
210611e9eae4SChaoyong He }
210711e9eae4SChaoyong He 
210811e9eae4SChaoyong He static void
210911e9eae4SChaoyong He nfp_net_get_app_name(struct nfp_net_hw *hw,
211011e9eae4SChaoyong He 		char *app_name)
211111e9eae4SChaoyong He {
211211e9eae4SChaoyong He 	switch (hw->pf_dev->app_fw_id) {
211311e9eae4SChaoyong He 	case NFP_APP_FW_CORE_NIC:
211411e9eae4SChaoyong He 		snprintf(app_name, FW_VER_LEN, "%s", "nic");
211511e9eae4SChaoyong He 		break;
211611e9eae4SChaoyong He 	case NFP_APP_FW_FLOWER_NIC:
211711e9eae4SChaoyong He 		snprintf(app_name, FW_VER_LEN, "%s", "flower");
211811e9eae4SChaoyong He 		break;
211911e9eae4SChaoyong He 	default:
212011e9eae4SChaoyong He 		snprintf(app_name, FW_VER_LEN, "%s", "unknown");
212111e9eae4SChaoyong He 		break;
212211e9eae4SChaoyong He 	}
212311e9eae4SChaoyong He }
212411e9eae4SChaoyong He 
212511e9eae4SChaoyong He int
212611e9eae4SChaoyong He nfp_net_firmware_version_get(struct rte_eth_dev *dev,
212711e9eae4SChaoyong He 		char *fw_version,
212811e9eae4SChaoyong He 		size_t fw_size)
212911e9eae4SChaoyong He {
213011e9eae4SChaoyong He 	struct nfp_net_hw *hw;
213111e9eae4SChaoyong He 	char mip_name[FW_VER_LEN];
213211e9eae4SChaoyong He 	char app_name[FW_VER_LEN];
213311e9eae4SChaoyong He 	char nsp_version[FW_VER_LEN];
213411e9eae4SChaoyong He 	char vnic_version[FW_VER_LEN];
213511e9eae4SChaoyong He 
213611e9eae4SChaoyong He 	if (fw_size < FW_VER_LEN)
213711e9eae4SChaoyong He 		return FW_VER_LEN;
213811e9eae4SChaoyong He 
2139c4de52ecSChaoyong He 	hw = nfp_net_get_hw(dev);
214011e9eae4SChaoyong He 
2141c99e1db8SLong Wu 	if (rte_eth_dev_is_repr(dev)) {
214211e9eae4SChaoyong He 		snprintf(vnic_version, FW_VER_LEN, "%d.%d.%d.%d",
214311e9eae4SChaoyong He 			hw->ver.extend, hw->ver.class,
214411e9eae4SChaoyong He 			hw->ver.major, hw->ver.minor);
2145c4de52ecSChaoyong He 	} else {
2146c4de52ecSChaoyong He 		snprintf(vnic_version, FW_VER_LEN, "*");
2147c4de52ecSChaoyong He 	}
214811e9eae4SChaoyong He 
214911e9eae4SChaoyong He 	nfp_net_get_nsp_info(hw, nsp_version);
215011e9eae4SChaoyong He 	nfp_net_get_mip_name(hw, mip_name);
215111e9eae4SChaoyong He 	nfp_net_get_app_name(hw, app_name);
215211e9eae4SChaoyong He 
215311e9eae4SChaoyong He 	snprintf(fw_version, FW_VER_LEN, "%s %s %s %s",
215411e9eae4SChaoyong He 			vnic_version, nsp_version, mip_name, app_name);
215511e9eae4SChaoyong He 
215611e9eae4SChaoyong He 	return 0;
215711e9eae4SChaoyong He }
215811e9eae4SChaoyong He 
215911e9eae4SChaoyong He bool
216011e9eae4SChaoyong He nfp_net_is_valid_nfd_version(struct nfp_net_fw_ver version)
216111e9eae4SChaoyong He {
216211e9eae4SChaoyong He 	uint8_t nfd_version = version.extend;
216311e9eae4SChaoyong He 
216411e9eae4SChaoyong He 	if (nfd_version == NFP_NET_CFG_VERSION_DP_NFD3)
216511e9eae4SChaoyong He 		return true;
216611e9eae4SChaoyong He 
216711e9eae4SChaoyong He 	if (nfd_version == NFP_NET_CFG_VERSION_DP_NFDK) {
216811e9eae4SChaoyong He 		if (version.major < 5) {
216911e9eae4SChaoyong He 			PMD_INIT_LOG(ERR, "NFDK must use ABI 5 or newer, found: %d",
217011e9eae4SChaoyong He 					version.major);
217111e9eae4SChaoyong He 			return false;
217211e9eae4SChaoyong He 		}
217311e9eae4SChaoyong He 
217411e9eae4SChaoyong He 		return true;
217511e9eae4SChaoyong He 	}
217611e9eae4SChaoyong He 
217711e9eae4SChaoyong He 	return false;
217811e9eae4SChaoyong He }
2179c4de52ecSChaoyong He 
2180c4de52ecSChaoyong He /* Disable rx and tx functions to allow for reconfiguring. */
2181c4de52ecSChaoyong He int
2182c4de52ecSChaoyong He nfp_net_stop(struct rte_eth_dev *dev)
2183c4de52ecSChaoyong He {
2184acb6bebfSChaoyong He 	struct nfp_cpp *cpp;
2185c4de52ecSChaoyong He 	struct nfp_net_hw *hw;
2186c4de52ecSChaoyong He 
2187c4de52ecSChaoyong He 	hw = nfp_net_get_hw(dev);
2188c4de52ecSChaoyong He 
2189c4de52ecSChaoyong He 	nfp_net_disable_queues(dev);
2190c4de52ecSChaoyong He 
2191c4de52ecSChaoyong He 	/* Clear queues */
2192c4de52ecSChaoyong He 	nfp_net_stop_tx_queue(dev);
2193c4de52ecSChaoyong He 	nfp_net_stop_rx_queue(dev);
2194c4de52ecSChaoyong He 
2195c4de52ecSChaoyong He 	if (rte_eal_process_type() == RTE_PROC_PRIMARY)
2196acb6bebfSChaoyong He 		cpp = hw->cpp;
2197c4de52ecSChaoyong He 	else
2198acb6bebfSChaoyong He 		cpp = ((struct nfp_pf_dev *)(dev->process_private))->cpp;
2199acb6bebfSChaoyong He 
2200acb6bebfSChaoyong He 	nfp_eth_set_configured(cpp, hw->nfp_idx, 0);
2201c4de52ecSChaoyong He 
2202c4de52ecSChaoyong He 	return 0;
2203c4de52ecSChaoyong He }
220451d15e82SZerun Fu 
220551d15e82SZerun Fu static enum rte_eth_fc_mode
220651d15e82SZerun Fu nfp_net_get_pause_mode(struct nfp_eth_table_port *eth_port)
220751d15e82SZerun Fu {
220851d15e82SZerun Fu 	enum rte_eth_fc_mode mode;
220951d15e82SZerun Fu 
221051d15e82SZerun Fu 	if (eth_port->rx_pause_enabled) {
221151d15e82SZerun Fu 		if (eth_port->tx_pause_enabled)
221251d15e82SZerun Fu 			mode = RTE_ETH_FC_FULL;
221351d15e82SZerun Fu 		else
221451d15e82SZerun Fu 			mode = RTE_ETH_FC_RX_PAUSE;
221551d15e82SZerun Fu 	} else {
221651d15e82SZerun Fu 		if (eth_port->tx_pause_enabled)
221751d15e82SZerun Fu 			mode = RTE_ETH_FC_TX_PAUSE;
221851d15e82SZerun Fu 		else
221951d15e82SZerun Fu 			mode = RTE_ETH_FC_NONE;
222051d15e82SZerun Fu 	}
222151d15e82SZerun Fu 
222251d15e82SZerun Fu 	return mode;
222351d15e82SZerun Fu }
222451d15e82SZerun Fu 
222551d15e82SZerun Fu int
222651d15e82SZerun Fu nfp_net_flow_ctrl_get(struct rte_eth_dev *dev,
222751d15e82SZerun Fu 		struct rte_eth_fc_conf *fc_conf)
222851d15e82SZerun Fu {
222951d15e82SZerun Fu 	struct nfp_net_hw *net_hw;
223051d15e82SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
223151d15e82SZerun Fu 	struct nfp_eth_table_port *eth_port;
223251d15e82SZerun Fu 
223351d15e82SZerun Fu 	net_hw = nfp_net_get_hw(dev);
223451d15e82SZerun Fu 	if (net_hw->pf_dev == NULL)
223551d15e82SZerun Fu 		return -EINVAL;
223651d15e82SZerun Fu 
223751d15e82SZerun Fu 	nfp_eth_table = net_hw->pf_dev->nfp_eth_table;
223851d15e82SZerun Fu 	eth_port = &nfp_eth_table->ports[dev->data->port_id];
223951d15e82SZerun Fu 
224051d15e82SZerun Fu 	/* Currently only RX/TX switch are supported */
224151d15e82SZerun Fu 	fc_conf->mode = nfp_net_get_pause_mode(eth_port);
224251d15e82SZerun Fu 
224351d15e82SZerun Fu 	return 0;
224451d15e82SZerun Fu }
224568aa3537SZerun Fu 
224668aa3537SZerun Fu static int
224768aa3537SZerun Fu nfp_net_pause_frame_set(struct nfp_net_hw *net_hw,
224868aa3537SZerun Fu 		struct nfp_eth_table_port *eth_port,
224968aa3537SZerun Fu 		enum rte_eth_fc_mode mode)
225068aa3537SZerun Fu {
225168aa3537SZerun Fu 	int err;
225268aa3537SZerun Fu 	bool flag;
225368aa3537SZerun Fu 	struct nfp_nsp *nsp;
225468aa3537SZerun Fu 
225568aa3537SZerun Fu 	nsp = nfp_eth_config_start(net_hw->cpp, eth_port->index);
225668aa3537SZerun Fu 	if (nsp == NULL) {
225768aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle.");
225868aa3537SZerun Fu 		return -EIO;
225968aa3537SZerun Fu 	}
226068aa3537SZerun Fu 
226168aa3537SZerun Fu 	flag = (mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true;
226268aa3537SZerun Fu 	err = nfp_eth_set_tx_pause(nsp, flag);
226368aa3537SZerun Fu 	if (err != 0) {
226468aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to configure TX pause frame.");
226568aa3537SZerun Fu 		nfp_eth_config_cleanup_end(nsp);
226668aa3537SZerun Fu 		return err;
226768aa3537SZerun Fu 	}
226868aa3537SZerun Fu 
226968aa3537SZerun Fu 	flag = (mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true;
227068aa3537SZerun Fu 	err = nfp_eth_set_rx_pause(nsp, flag);
227168aa3537SZerun Fu 	if (err != 0) {
227268aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to configure RX pause frame.");
227368aa3537SZerun Fu 		nfp_eth_config_cleanup_end(nsp);
227468aa3537SZerun Fu 		return err;
227568aa3537SZerun Fu 	}
227668aa3537SZerun Fu 
227768aa3537SZerun Fu 	err = nfp_eth_config_commit_end(nsp);
227868aa3537SZerun Fu 	if (err != 0) {
227968aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to configure pause frame.");
228068aa3537SZerun Fu 		return err;
228168aa3537SZerun Fu 	}
228268aa3537SZerun Fu 
228368aa3537SZerun Fu 	return 0;
228468aa3537SZerun Fu }
228568aa3537SZerun Fu 
228668aa3537SZerun Fu int
228768aa3537SZerun Fu nfp_net_flow_ctrl_set(struct rte_eth_dev *dev,
228868aa3537SZerun Fu 		struct rte_eth_fc_conf *fc_conf)
228968aa3537SZerun Fu {
229068aa3537SZerun Fu 	int ret;
229168aa3537SZerun Fu 	struct nfp_net_hw *net_hw;
229268aa3537SZerun Fu 	enum rte_eth_fc_mode set_mode;
229368aa3537SZerun Fu 	enum rte_eth_fc_mode original_mode;
229468aa3537SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
229568aa3537SZerun Fu 	struct nfp_eth_table_port *eth_port;
229668aa3537SZerun Fu 
229768aa3537SZerun Fu 	net_hw = nfp_net_get_hw(dev);
229868aa3537SZerun Fu 	if (net_hw->pf_dev == NULL)
229968aa3537SZerun Fu 		return -EINVAL;
230068aa3537SZerun Fu 
230168aa3537SZerun Fu 	nfp_eth_table = net_hw->pf_dev->nfp_eth_table;
230268aa3537SZerun Fu 	eth_port = &nfp_eth_table->ports[net_hw->idx];
230368aa3537SZerun Fu 
230468aa3537SZerun Fu 	original_mode = nfp_net_get_pause_mode(eth_port);
230568aa3537SZerun Fu 	set_mode = fc_conf->mode;
230668aa3537SZerun Fu 
230768aa3537SZerun Fu 	if (set_mode == original_mode)
230868aa3537SZerun Fu 		return 0;
230968aa3537SZerun Fu 
231068aa3537SZerun Fu 	ret = nfp_net_pause_frame_set(net_hw, eth_port, set_mode);
231168aa3537SZerun Fu 	if (ret != 0)
231268aa3537SZerun Fu 		return ret;
231368aa3537SZerun Fu 
231468aa3537SZerun Fu 	/* Update eth_table after modifying RX/TX pause frame mode. */
231568aa3537SZerun Fu 	eth_port->tx_pause_enabled = (set_mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true;
231668aa3537SZerun Fu 	eth_port->rx_pause_enabled = (set_mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true;
231768aa3537SZerun Fu 
231868aa3537SZerun Fu 	return 0;
231968aa3537SZerun Fu }
23200786add9SZerun Fu 
23210786add9SZerun Fu int
23220786add9SZerun Fu nfp_net_fec_get_capability(struct rte_eth_dev *dev,
23230786add9SZerun Fu 		struct rte_eth_fec_capa *speed_fec_capa,
23240786add9SZerun Fu 		__rte_unused unsigned int num)
23250786add9SZerun Fu {
23260786add9SZerun Fu 	uint16_t speed;
23270786add9SZerun Fu 	struct nfp_net_hw *hw;
23280786add9SZerun Fu 	uint32_t supported_fec;
23290786add9SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
23300786add9SZerun Fu 	struct nfp_eth_table_port *eth_port;
23310786add9SZerun Fu 
23320786add9SZerun Fu 	hw = nfp_net_get_hw(dev);
23330786add9SZerun Fu 	if (hw->pf_dev == NULL)
23340786add9SZerun Fu 		return -EINVAL;
23350786add9SZerun Fu 
23360786add9SZerun Fu 	nfp_eth_table = hw->pf_dev->nfp_eth_table;
23370786add9SZerun Fu 	eth_port = &nfp_eth_table->ports[hw->idx];
23380786add9SZerun Fu 
23390786add9SZerun Fu 	speed = eth_port->speed;
23400786add9SZerun Fu 	supported_fec = nfp_eth_supported_fec_modes(eth_port);
23410786add9SZerun Fu 	if (speed == 0 || supported_fec == 0) {
23420786add9SZerun Fu 		PMD_DRV_LOG(ERR, "FEC modes supported or Speed is invalid.");
23430786add9SZerun Fu 		return -EINVAL;
23440786add9SZerun Fu 	}
23450786add9SZerun Fu 
23460786add9SZerun Fu 	if (speed_fec_capa == NULL)
23470786add9SZerun Fu 		return NFP_FEC_CAPA_ENTRY_NUM;
23480786add9SZerun Fu 
23490786add9SZerun Fu 	speed_fec_capa->speed = speed;
23500786add9SZerun Fu 
23510786add9SZerun Fu 	if ((supported_fec & NFP_FEC_AUTO) != 0)
23520786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
23530786add9SZerun Fu 	if ((supported_fec & NFP_FEC_BASER) != 0)
23540786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
23550786add9SZerun Fu 	if ((supported_fec & NFP_FEC_REED_SOLOMON) != 0)
23560786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(RS);
23570786add9SZerun Fu 	if ((supported_fec & NFP_FEC_DISABLED) != 0)
23580786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
23590786add9SZerun Fu 
23600786add9SZerun Fu 	return NFP_FEC_CAPA_ENTRY_NUM;
23610786add9SZerun Fu }
2362c6835a32SZerun Fu 
2363c6835a32SZerun Fu static uint32_t
2364c6835a32SZerun Fu nfp_net_fec_nfp_to_rte(enum nfp_eth_fec fec)
2365c6835a32SZerun Fu {
2366c6835a32SZerun Fu 	switch (fec) {
2367c6835a32SZerun Fu 	case NFP_FEC_AUTO_BIT:
2368c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
2369c6835a32SZerun Fu 	case NFP_FEC_BASER_BIT:
2370c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
2371c6835a32SZerun Fu 	case NFP_FEC_REED_SOLOMON_BIT:
2372c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(RS);
2373c6835a32SZerun Fu 	case NFP_FEC_DISABLED_BIT:
2374c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
2375c6835a32SZerun Fu 	default:
2376c6835a32SZerun Fu 		PMD_DRV_LOG(ERR, "FEC mode is invalid.");
2377c6835a32SZerun Fu 		return 0;
2378c6835a32SZerun Fu 	}
2379c6835a32SZerun Fu }
2380c6835a32SZerun Fu 
2381c6835a32SZerun Fu int
2382c6835a32SZerun Fu nfp_net_fec_get(struct rte_eth_dev *dev,
2383c6835a32SZerun Fu 		uint32_t *fec_capa)
2384c6835a32SZerun Fu {
2385c6835a32SZerun Fu 	struct nfp_net_hw *hw;
2386c6835a32SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
2387c6835a32SZerun Fu 	struct nfp_eth_table_port *eth_port;
2388c6835a32SZerun Fu 
2389c6835a32SZerun Fu 	hw = nfp_net_get_hw(dev);
2390c6835a32SZerun Fu 	if (hw->pf_dev == NULL)
2391c6835a32SZerun Fu 		return -EINVAL;
2392c6835a32SZerun Fu 
2393c6835a32SZerun Fu 	if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN) {
2394c6835a32SZerun Fu 		nfp_eth_table = nfp_eth_read_ports(hw->cpp);
2395c6835a32SZerun Fu 		hw->pf_dev->nfp_eth_table->ports[hw->idx] = nfp_eth_table->ports[hw->idx];
2396c6835a32SZerun Fu 		free(nfp_eth_table);
2397c6835a32SZerun Fu 	}
2398c6835a32SZerun Fu 
2399c6835a32SZerun Fu 	nfp_eth_table = hw->pf_dev->nfp_eth_table;
2400c6835a32SZerun Fu 	eth_port = &nfp_eth_table->ports[hw->idx];
2401c6835a32SZerun Fu 
2402c6835a32SZerun Fu 	if (!nfp_eth_can_support_fec(eth_port)) {
2403c6835a32SZerun Fu 		PMD_DRV_LOG(ERR, "NFP can not support FEC.");
2404c6835a32SZerun Fu 		return -ENOTSUP;
2405c6835a32SZerun Fu 	}
2406c6835a32SZerun Fu 
2407c6835a32SZerun Fu 	/*
2408c6835a32SZerun Fu 	 * If link is down and AUTO is enabled, AUTO is returned, otherwise,
2409c6835a32SZerun Fu 	 * configured FEC mode is returned.
2410c6835a32SZerun Fu 	 * If link is up, current FEC mode is returned.
2411c6835a32SZerun Fu 	 */
2412c6835a32SZerun Fu 	if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN)
2413c6835a32SZerun Fu 		*fec_capa = nfp_net_fec_nfp_to_rte(eth_port->fec);
2414c6835a32SZerun Fu 	else
2415c6835a32SZerun Fu 		*fec_capa = nfp_net_fec_nfp_to_rte(eth_port->act_fec);
2416c6835a32SZerun Fu 
2417c6835a32SZerun Fu 	if (*fec_capa == 0)
2418c6835a32SZerun Fu 		return -EINVAL;
2419c6835a32SZerun Fu 
2420c6835a32SZerun Fu 	return 0;
2421c6835a32SZerun Fu }
242237bd1b84SZerun Fu 
242337bd1b84SZerun Fu static enum nfp_eth_fec
242437bd1b84SZerun Fu nfp_net_fec_rte_to_nfp(uint32_t fec)
242537bd1b84SZerun Fu {
242637bd1b84SZerun Fu 	switch (fec) {
242737bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_AUTO):
242837bd1b84SZerun Fu 		return NFP_FEC_AUTO_BIT;
242937bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_NOFEC):
243037bd1b84SZerun Fu 		return NFP_FEC_DISABLED_BIT;
243137bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_RS):
243237bd1b84SZerun Fu 		return NFP_FEC_REED_SOLOMON_BIT;
243337bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_BASER):
243437bd1b84SZerun Fu 		return NFP_FEC_BASER_BIT;
243537bd1b84SZerun Fu 	default:
243637bd1b84SZerun Fu 		return NFP_FEC_INVALID_BIT;
243737bd1b84SZerun Fu 	}
243837bd1b84SZerun Fu }
243937bd1b84SZerun Fu 
244037bd1b84SZerun Fu int
244137bd1b84SZerun Fu nfp_net_fec_set(struct rte_eth_dev *dev,
244237bd1b84SZerun Fu 		uint32_t fec_capa)
244337bd1b84SZerun Fu {
244437bd1b84SZerun Fu 	enum nfp_eth_fec fec;
244537bd1b84SZerun Fu 	struct nfp_net_hw *hw;
244637bd1b84SZerun Fu 	uint32_t supported_fec;
244737bd1b84SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
244837bd1b84SZerun Fu 	struct nfp_eth_table_port *eth_port;
244937bd1b84SZerun Fu 
245037bd1b84SZerun Fu 	hw = nfp_net_get_hw(dev);
245137bd1b84SZerun Fu 	if (hw->pf_dev == NULL)
245237bd1b84SZerun Fu 		return -EINVAL;
245337bd1b84SZerun Fu 
245437bd1b84SZerun Fu 	nfp_eth_table = hw->pf_dev->nfp_eth_table;
245537bd1b84SZerun Fu 	eth_port = &nfp_eth_table->ports[hw->idx];
245637bd1b84SZerun Fu 
245737bd1b84SZerun Fu 	supported_fec = nfp_eth_supported_fec_modes(eth_port);
245837bd1b84SZerun Fu 	if (supported_fec == 0) {
245937bd1b84SZerun Fu 		PMD_DRV_LOG(ERR, "NFP can not support FEC.");
246037bd1b84SZerun Fu 		return -ENOTSUP;
246137bd1b84SZerun Fu 	}
246237bd1b84SZerun Fu 
246337bd1b84SZerun Fu 	fec = nfp_net_fec_rte_to_nfp(fec_capa);
246437bd1b84SZerun Fu 	if (fec == NFP_FEC_INVALID_BIT) {
246537bd1b84SZerun Fu 		PMD_DRV_LOG(ERR, "FEC modes is invalid.");
246637bd1b84SZerun Fu 		return -EINVAL;
246737bd1b84SZerun Fu 	}
246837bd1b84SZerun Fu 
246937bd1b84SZerun Fu 	if ((RTE_BIT32(fec) & supported_fec) == 0) {
247037bd1b84SZerun Fu 		PMD_DRV_LOG(ERR, "Unsupported FEC mode is set.");
247137bd1b84SZerun Fu 		return -EIO;
247237bd1b84SZerun Fu 	}
247337bd1b84SZerun Fu 
247437bd1b84SZerun Fu 	return nfp_eth_set_fec(hw->cpp, eth_port->index, fec);
247537bd1b84SZerun Fu }
2476