xref: /dpdk/drivers/net/nfp/nfp_net_common.c (revision c43d2aab426bdc6e22142b4c5667d6d1634248de)
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 
12636e133eSPeng Zhang #include "flower/nfp_flower_cmsg.h"
1311e9eae4SChaoyong He #include "flower/nfp_flower_representor.h"
1411e9eae4SChaoyong He #include "nfd3/nfp_nfd3.h"
1511e9eae4SChaoyong He #include "nfdk/nfp_nfdk.h"
1611e9eae4SChaoyong He #include "nfpcore/nfp_mip.h"
1711e9eae4SChaoyong He #include "nfpcore/nfp_nsp.h"
18eac7eda4SChaoyong He #include "nfpcore/nfp_rtsym.h"
1911e9eae4SChaoyong He #include "nfp_logs.h"
20ddcd598fSLong Wu #include "nfp_net_meta.h"
2111e9eae4SChaoyong He 
2211e9eae4SChaoyong He #define NFP_TX_MAX_SEG       UINT8_MAX
2311e9eae4SChaoyong He #define NFP_TX_MAX_MTU_SEG   8
2411e9eae4SChaoyong He 
2511e9eae4SChaoyong He #define NFP_NET_LINK_DOWN_CHECK_TIMEOUT 4000 /* ms */
2611e9eae4SChaoyong He #define NFP_NET_LINK_UP_CHECK_TIMEOUT   1000 /* ms */
2711e9eae4SChaoyong He 
2811e9eae4SChaoyong He #define DEFAULT_FLBUF_SIZE        9216
292f1bfbf4SJames Hershaw #define NFP_ETH_OVERHEAD \
302f1bfbf4SJames Hershaw 	(RTE_ETHER_HDR_LEN + RTE_ETHER_CRC_LEN + RTE_VLAN_HLEN * 2)
3111e9eae4SChaoyong He 
320786add9SZerun Fu /* Only show FEC capability supported by the current speed. */
330786add9SZerun Fu #define NFP_FEC_CAPA_ENTRY_NUM  1
340786add9SZerun Fu 
3511e9eae4SChaoyong He enum nfp_xstat_group {
3611e9eae4SChaoyong He 	NFP_XSTAT_GROUP_NET,
3711e9eae4SChaoyong He 	NFP_XSTAT_GROUP_MAC
3811e9eae4SChaoyong He };
3911e9eae4SChaoyong He 
4011e9eae4SChaoyong He struct nfp_xstat {
4111e9eae4SChaoyong He 	char name[RTE_ETH_XSTATS_NAME_SIZE];
4211e9eae4SChaoyong He 	int offset;
4311e9eae4SChaoyong He 	enum nfp_xstat_group group;
4411e9eae4SChaoyong He };
4511e9eae4SChaoyong He 
4611e9eae4SChaoyong He #define NFP_XSTAT_NET(_name, _offset) {                 \
4711e9eae4SChaoyong He 	.name = _name,                                  \
4811e9eae4SChaoyong He 	.offset = NFP_NET_CFG_STATS_##_offset,          \
4911e9eae4SChaoyong He 	.group = NFP_XSTAT_GROUP_NET,                   \
5011e9eae4SChaoyong He }
5111e9eae4SChaoyong He 
5211e9eae4SChaoyong He #define NFP_XSTAT_MAC(_name, _offset) {                 \
5311e9eae4SChaoyong He 	.name = _name,                                  \
5411e9eae4SChaoyong He 	.offset = NFP_MAC_STATS_##_offset,              \
5511e9eae4SChaoyong He 	.group = NFP_XSTAT_GROUP_MAC,                   \
5611e9eae4SChaoyong He }
5711e9eae4SChaoyong He 
5811e9eae4SChaoyong He static const struct nfp_xstat nfp_net_xstats[] = {
5911e9eae4SChaoyong He 	/*
6011e9eae4SChaoyong He 	 * Basic xstats available on both VF and PF.
6111e9eae4SChaoyong He 	 * Note that in case new statistics of group NFP_XSTAT_GROUP_NET
6211e9eae4SChaoyong He 	 * are added to this array, they must appear before any statistics
6311e9eae4SChaoyong He 	 * of group NFP_XSTAT_GROUP_MAC.
6411e9eae4SChaoyong He 	 */
6511e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_packets_mc", RX_MC_FRAMES),
6611e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_packets_mc", TX_MC_FRAMES),
6711e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_packets_bc", RX_BC_FRAMES),
6811e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_packets_bc", TX_BC_FRAMES),
6911e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_uc", RX_UC_OCTETS),
7011e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_uc", TX_UC_OCTETS),
7111e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_mc", RX_MC_OCTETS),
7211e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_mc", TX_MC_OCTETS),
7311e9eae4SChaoyong He 	NFP_XSTAT_NET("rx_good_bytes_bc", RX_BC_OCTETS),
7411e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_good_bytes_bc", TX_BC_OCTETS),
7511e9eae4SChaoyong He 	NFP_XSTAT_NET("tx_missed_erros", TX_DISCARDS),
7611e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_pass_pkts", APP0_FRAMES),
7711e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_pass_bytes", APP0_BYTES),
7811e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app1_pkts", APP1_FRAMES),
7911e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app1_bytes", APP1_BYTES),
8011e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app2_pkts", APP2_FRAMES),
8111e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app2_bytes", APP2_BYTES),
8211e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app3_pkts", APP3_FRAMES),
8311e9eae4SChaoyong He 	NFP_XSTAT_NET("bpf_app3_bytes", APP3_BYTES),
8411e9eae4SChaoyong He 	/*
8511e9eae4SChaoyong He 	 * MAC xstats available only on PF. These statistics are not available for VFs as the
8611e9eae4SChaoyong He 	 * PF is not initialized when the VF is initialized as it is still bound to the kernel
8711e9eae4SChaoyong He 	 * driver. As such, the PMD cannot obtain a CPP handle and access the rtsym_table in order
8811e9eae4SChaoyong He 	 * to get the pointer to the start of the MAC statistics counters.
8911e9eae4SChaoyong He 	 */
9011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_octets", RX_IN_OCTS),
9111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frame_too_long_errors", RX_FRAME_TOO_LONG_ERRORS),
9211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_range_length_errors", RX_RANGE_LENGTH_ERRORS),
9311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_vlan_received_ok", RX_VLAN_RECEIVED_OK),
9411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_errors", RX_IN_ERRORS),
9511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_broadcast_pkts", RX_IN_BROADCAST_PKTS),
9611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_drop_events", RX_DROP_EVENTS),
9711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_alignment_errors", RX_ALIGNMENT_ERRORS),
9811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_mac_ctrl_frames", RX_PAUSE_MAC_CTRL_FRAMES),
9911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frames_received_ok", RX_FRAMES_RECEIVED_OK),
10011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_frame_check_sequence_errors", RX_FRAME_CHECK_SEQ_ERRORS),
10111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_unicast_pkts", RX_UNICAST_PKTS),
10211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_multicast_pkts", RX_MULTICAST_PKTS),
10311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts", RX_PKTS),
10411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_undersize_pkts", RX_UNDERSIZE_PKTS),
10511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_64_octets", RX_PKTS_64_OCTS),
10611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_65_to_127_octets", RX_PKTS_65_TO_127_OCTS),
10711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_128_to_255_octets", RX_PKTS_128_TO_255_OCTS),
10811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_256_to_511_octets", RX_PKTS_256_TO_511_OCTS),
10911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_512_to_1023_octets", RX_PKTS_512_TO_1023_OCTS),
11011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_1024_to_1518_octets", RX_PKTS_1024_TO_1518_OCTS),
11111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pkts_1519_to_max_octets", RX_PKTS_1519_TO_MAX_OCTS),
11211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_jabbers", RX_JABBERS),
11311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_fragments", RX_FRAGMENTS),
11411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_oversize_pkts", RX_OVERSIZE_PKTS),
11511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class0", RX_PAUSE_FRAMES_CLASS0),
11611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class1", RX_PAUSE_FRAMES_CLASS1),
11711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class2", RX_PAUSE_FRAMES_CLASS2),
11811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class3", RX_PAUSE_FRAMES_CLASS3),
11911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class4", RX_PAUSE_FRAMES_CLASS4),
12011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class5", RX_PAUSE_FRAMES_CLASS5),
12111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class6", RX_PAUSE_FRAMES_CLASS6),
12211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_pause_frames_class7", RX_PAUSE_FRAMES_CLASS7),
12311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_mac_ctrl_frames_received", RX_MAC_CTRL_FRAMES_REC),
12411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.rx_mac_head_drop", RX_MAC_HEAD_DROP),
12511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_queue_drop", TX_QUEUE_DROP),
12611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_octets", TX_OUT_OCTS),
12711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_vlan_transmitted_ok", TX_VLAN_TRANSMITTED_OK),
12811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_errors", TX_OUT_ERRORS),
12911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_broadcast_pkts", TX_BROADCAST_PKTS),
13011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_mac_ctrl_frames", TX_PAUSE_MAC_CTRL_FRAMES),
13111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_frames_transmitted_ok", TX_FRAMES_TRANSMITTED_OK),
13211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_unicast_pkts", TX_UNICAST_PKTS),
13311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_multicast_pkts", TX_MULTICAST_PKTS),
13411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_64_octets", TX_PKTS_64_OCTS),
13511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_65_to_127_octets", TX_PKTS_65_TO_127_OCTS),
13611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_128_to_255_octets", TX_PKTS_128_TO_255_OCTS),
13711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_256_to_511_octets", TX_PKTS_256_TO_511_OCTS),
13811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_512_to_1023_octets", TX_PKTS_512_TO_1023_OCTS),
13911e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_1024_to_1518_octets", TX_PKTS_1024_TO_1518_OCTS),
14011e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pkts_1519_to_max_octets", TX_PKTS_1519_TO_MAX_OCTS),
14111e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class0", TX_PAUSE_FRAMES_CLASS0),
14211e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class1", TX_PAUSE_FRAMES_CLASS1),
14311e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class2", TX_PAUSE_FRAMES_CLASS2),
14411e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class3", TX_PAUSE_FRAMES_CLASS3),
14511e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class4", TX_PAUSE_FRAMES_CLASS4),
14611e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class5", TX_PAUSE_FRAMES_CLASS5),
14711e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class6", TX_PAUSE_FRAMES_CLASS6),
14811e9eae4SChaoyong He 	NFP_XSTAT_MAC("mac.tx_pause_frames_class7", TX_PAUSE_FRAMES_CLASS7),
14911e9eae4SChaoyong He };
15011e9eae4SChaoyong He 
15111e9eae4SChaoyong He static const uint32_t nfp_net_link_speed_nfp2rte[] = {
15211e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_UNSUPPORTED] = RTE_ETH_SPEED_NUM_NONE,
15311e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_UNKNOWN]     = RTE_ETH_SPEED_NUM_NONE,
15411e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_1G]          = RTE_ETH_SPEED_NUM_1G,
15511e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_10G]         = RTE_ETH_SPEED_NUM_10G,
15611e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_25G]         = RTE_ETH_SPEED_NUM_25G,
15711e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_40G]         = RTE_ETH_SPEED_NUM_40G,
15811e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_50G]         = RTE_ETH_SPEED_NUM_50G,
15911e9eae4SChaoyong He 	[NFP_NET_CFG_STS_LINK_RATE_100G]        = RTE_ETH_SPEED_NUM_100G,
16011e9eae4SChaoyong He };
16111e9eae4SChaoyong He 
162*c43d2aabSLong Wu static bool
163*c43d2aabSLong Wu nfp_net_is_pf(struct rte_eth_dev *dev)
164*c43d2aabSLong Wu {
165*c43d2aabSLong Wu 	if (rte_eth_dev_is_repr(dev))
166*c43d2aabSLong Wu 		return nfp_flower_repr_is_pf(dev);
167*c43d2aabSLong Wu 
168*c43d2aabSLong Wu 	return ((struct nfp_net_hw_priv *)dev->process_private)->is_pf;
169*c43d2aabSLong Wu }
170*c43d2aabSLong Wu 
17193ebb1e5SQin Ke static size_t
17293ebb1e5SQin Ke nfp_net_link_speed_rte2nfp(uint32_t speed)
17311e9eae4SChaoyong He {
17493ebb1e5SQin Ke 	size_t i;
17511e9eae4SChaoyong He 
17611e9eae4SChaoyong He 	for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) {
17711e9eae4SChaoyong He 		if (speed == nfp_net_link_speed_nfp2rte[i])
17811e9eae4SChaoyong He 			return i;
17911e9eae4SChaoyong He 	}
18011e9eae4SChaoyong He 
18111e9eae4SChaoyong He 	return NFP_NET_CFG_STS_LINK_RATE_UNKNOWN;
18211e9eae4SChaoyong He }
18311e9eae4SChaoyong He 
18448de6254SQin Ke static uint32_t
18548de6254SQin Ke nfp_net_link_speed_nfp2rte_check(uint32_t speed)
18648de6254SQin Ke {
18748de6254SQin Ke 	size_t i;
18848de6254SQin Ke 
18948de6254SQin Ke 	for (i = 0; i < RTE_DIM(nfp_net_link_speed_nfp2rte); i++) {
19048de6254SQin Ke 		if (speed == nfp_net_link_speed_nfp2rte[i])
19148de6254SQin Ke 			return nfp_net_link_speed_nfp2rte[i];
19248de6254SQin Ke 	}
19348de6254SQin Ke 
19448de6254SQin Ke 	return RTE_ETH_SPEED_NUM_NONE;
19548de6254SQin Ke }
19648de6254SQin Ke 
19722548137SZerun Fu void
19811e9eae4SChaoyong He nfp_net_notify_port_speed(struct nfp_net_hw *hw,
19911e9eae4SChaoyong He 		struct rte_eth_link *link)
20011e9eae4SChaoyong He {
20111e9eae4SChaoyong He 	/*
20211e9eae4SChaoyong He 	 * Read the link status from NFP_NET_CFG_STS. If the link is down
20311e9eae4SChaoyong He 	 * then write the link speed NFP_NET_CFG_STS_LINK_RATE_UNKNOWN to
20411e9eae4SChaoyong He 	 * NFP_NET_CFG_STS_NSP_LINK_RATE.
20511e9eae4SChaoyong He 	 */
20611e9eae4SChaoyong He 	if (link->link_status == RTE_ETH_LINK_DOWN) {
207f58bde00SChaoyong He 		nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE,
208f58bde00SChaoyong He 				NFP_NET_CFG_STS_LINK_RATE_UNKNOWN);
20911e9eae4SChaoyong He 		return;
21011e9eae4SChaoyong He 	}
21111e9eae4SChaoyong He 
21211e9eae4SChaoyong He 	/*
21311e9eae4SChaoyong He 	 * Link is up so write the link speed from the eth_table to
21411e9eae4SChaoyong He 	 * NFP_NET_CFG_STS_NSP_LINK_RATE.
21511e9eae4SChaoyong He 	 */
216f58bde00SChaoyong He 	nn_cfg_writew(&hw->super, NFP_NET_CFG_STS_NSP_LINK_RATE,
21711e9eae4SChaoyong He 			nfp_net_link_speed_rte2nfp(link->link_speed));
21811e9eae4SChaoyong He }
21911e9eae4SChaoyong He 
22011e9eae4SChaoyong He /**
22187abbaf9SPeng Zhang  * Reconfigure the firmware of VF configure
22287abbaf9SPeng Zhang  *
22387abbaf9SPeng Zhang  * @param net_hw
22487abbaf9SPeng Zhang  *   Device to reconfigure
22587abbaf9SPeng Zhang  * @param pf_dev
22687abbaf9SPeng Zhang  *   Get the Device info
22787abbaf9SPeng Zhang  * @param update
22887abbaf9SPeng Zhang  *   The value for the mailbox VF command
22987abbaf9SPeng Zhang  * @param value
23087abbaf9SPeng Zhang  *   The value of update
23187abbaf9SPeng Zhang  * @param offset
23287abbaf9SPeng Zhang  *   The offset in the VF configure table
23387abbaf9SPeng Zhang  *
23487abbaf9SPeng Zhang  * @return
23587abbaf9SPeng Zhang  *   - (0) if OK to reconfigure vf configure.
23687abbaf9SPeng Zhang  *   - (-EIO) if I/O err and fail to configure the vf configure
23787abbaf9SPeng Zhang  */
23887abbaf9SPeng Zhang static int
23987abbaf9SPeng Zhang nfp_net_vf_reconfig(struct nfp_net_hw *net_hw,
24087abbaf9SPeng Zhang 		struct nfp_pf_dev *pf_dev,
24187abbaf9SPeng Zhang 		uint16_t update,
24287abbaf9SPeng Zhang 		uint8_t value,
24387abbaf9SPeng Zhang 		uint32_t offset)
24487abbaf9SPeng Zhang {
24587abbaf9SPeng Zhang 	int ret;
24687abbaf9SPeng Zhang 	struct nfp_hw *hw;
24787abbaf9SPeng Zhang 
24887abbaf9SPeng Zhang 	hw = &net_hw->super;
24987abbaf9SPeng Zhang 	rte_spinlock_lock(&hw->reconfig_lock);
25087abbaf9SPeng Zhang 
25187abbaf9SPeng Zhang 	/* Write update info to mailbox in VF config symbol */
25287abbaf9SPeng Zhang 	nn_writeb(value, pf_dev->vf_cfg_tbl_bar + offset);
25387abbaf9SPeng Zhang 	nn_writew(update, pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_UPD);
25487abbaf9SPeng Zhang 	nn_cfg_writel(hw, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_VF);
25587abbaf9SPeng Zhang 
25687abbaf9SPeng Zhang 	rte_wmb();
25787abbaf9SPeng Zhang 
25887abbaf9SPeng Zhang 	ret = nfp_reconfig_real(hw, NFP_NET_CFG_UPDATE_VF);
25987abbaf9SPeng Zhang 
26087abbaf9SPeng Zhang 	rte_spinlock_unlock(&hw->reconfig_lock);
26187abbaf9SPeng Zhang 
26287abbaf9SPeng Zhang 	if (ret != 0)
26387abbaf9SPeng Zhang 		return -EIO;
26487abbaf9SPeng Zhang 
26587abbaf9SPeng Zhang 	return nn_readw(pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_RET);
26687abbaf9SPeng Zhang }
26787abbaf9SPeng Zhang 
26887abbaf9SPeng Zhang /**
26911e9eae4SChaoyong He  * Reconfigure the firmware via the mailbox
27011e9eae4SChaoyong He  *
2714a9bb682SChaoyong He  * @param net_hw
27211e9eae4SChaoyong He  *   Device to reconfigure
27311e9eae4SChaoyong He  * @param mbox_cmd
27411e9eae4SChaoyong He  *   The value for the mailbox command
27511e9eae4SChaoyong He  *
27611e9eae4SChaoyong He  * @return
27711e9eae4SChaoyong He  *   - (0) if OK to reconfigure by the mailbox.
27811e9eae4SChaoyong He  *   - (-EIO) if I/O err and fail to reconfigure by the mailbox
27911e9eae4SChaoyong He  */
28011e9eae4SChaoyong He int
2814a9bb682SChaoyong He nfp_net_mbox_reconfig(struct nfp_net_hw *net_hw,
28211e9eae4SChaoyong He 		uint32_t mbox_cmd)
28311e9eae4SChaoyong He {
28411e9eae4SChaoyong He 	int ret;
28511e9eae4SChaoyong He 	uint32_t mbox;
28611e9eae4SChaoyong He 
2874a9bb682SChaoyong He 	mbox = net_hw->tlv_caps.mbox_off;
28811e9eae4SChaoyong He 
2894a9bb682SChaoyong He 	rte_spinlock_lock(&net_hw->super.reconfig_lock);
29011e9eae4SChaoyong He 
2914a9bb682SChaoyong He 	nn_cfg_writeq(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_CMD, mbox_cmd);
2924a9bb682SChaoyong He 	nn_cfg_writel(&net_hw->super, NFP_NET_CFG_UPDATE, NFP_NET_CFG_UPDATE_MBOX);
29311e9eae4SChaoyong He 
29411e9eae4SChaoyong He 	rte_wmb();
29511e9eae4SChaoyong He 
2964a9bb682SChaoyong He 	ret = nfp_reconfig_real(&net_hw->super, NFP_NET_CFG_UPDATE_MBOX);
29711e9eae4SChaoyong He 
2984a9bb682SChaoyong He 	rte_spinlock_unlock(&net_hw->super.reconfig_lock);
29911e9eae4SChaoyong He 
30011e9eae4SChaoyong He 	if (ret != 0) {
301b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Error nft net mailbox reconfig: mbox=%#08x update=%#08x.",
30211e9eae4SChaoyong He 				mbox_cmd, NFP_NET_CFG_UPDATE_MBOX);
30311e9eae4SChaoyong He 		return -EIO;
30411e9eae4SChaoyong He 	}
30511e9eae4SChaoyong He 
3064a9bb682SChaoyong He 	return nn_cfg_readl(&net_hw->super, mbox + NFP_NET_CFG_MBOX_SIMPLE_RET);
30711e9eae4SChaoyong He }
30811e9eae4SChaoyong He 
309b12d2b2eSChaoyong He struct nfp_net_hw *
310b12d2b2eSChaoyong He nfp_net_get_hw(const struct rte_eth_dev *dev)
311b12d2b2eSChaoyong He {
312b12d2b2eSChaoyong He 	struct nfp_net_hw *hw;
313b12d2b2eSChaoyong He 
314c99e1db8SLong Wu 	if (rte_eth_dev_is_repr(dev)) {
315b12d2b2eSChaoyong He 		struct nfp_flower_representor *repr;
316b12d2b2eSChaoyong He 		repr = dev->data->dev_private;
317b12d2b2eSChaoyong He 		hw = repr->app_fw_flower->pf_hw;
318b12d2b2eSChaoyong He 	} else {
319b12d2b2eSChaoyong He 		hw = dev->data->dev_private;
320b12d2b2eSChaoyong He 	}
321b12d2b2eSChaoyong He 
322b12d2b2eSChaoyong He 	return hw;
323b12d2b2eSChaoyong He }
324b12d2b2eSChaoyong He 
325441839f1SQin Ke uint8_t
326441839f1SQin Ke nfp_net_get_idx(const struct rte_eth_dev *dev)
327441839f1SQin Ke {
328441839f1SQin Ke 	uint8_t idx;
329441839f1SQin Ke 
330441839f1SQin Ke 	if (rte_eth_dev_is_repr(dev)) {
331441839f1SQin Ke 		struct nfp_flower_representor *repr;
332441839f1SQin Ke 		repr = dev->data->dev_private;
333441839f1SQin Ke 		idx = repr->idx;
334441839f1SQin Ke 	} else {
335441839f1SQin Ke 		struct nfp_net_hw *hw;
336441839f1SQin Ke 		hw = dev->data->dev_private;
337441839f1SQin Ke 		idx = hw->idx;
338441839f1SQin Ke 	}
339441839f1SQin Ke 
340441839f1SQin Ke 	return idx;
341441839f1SQin Ke }
342441839f1SQin Ke 
34311e9eae4SChaoyong He /*
34411e9eae4SChaoyong He  * Configure an Ethernet device.
34511e9eae4SChaoyong He  *
34611e9eae4SChaoyong He  * This function must be invoked first before any other function in the Ethernet API.
34711e9eae4SChaoyong He  * This function can also be re-invoked when a device is in the stopped state.
34811e9eae4SChaoyong He  *
34911e9eae4SChaoyong He  * A DPDK app sends info about how many queues to use and how  those queues
35011e9eae4SChaoyong He  * need to be configured. This is used by the DPDK core and it makes sure no
35111e9eae4SChaoyong He  * more queues than those advertised by the driver are requested.
35211e9eae4SChaoyong He  * This function is called after that internal process.
35311e9eae4SChaoyong He  */
35411e9eae4SChaoyong He int
35511e9eae4SChaoyong He nfp_net_configure(struct rte_eth_dev *dev)
35611e9eae4SChaoyong He {
35711e9eae4SChaoyong He 	struct nfp_net_hw *hw;
35811e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
35911e9eae4SChaoyong He 	struct rte_eth_rxmode *rxmode;
36011e9eae4SChaoyong He 	struct rte_eth_txmode *txmode;
36111e9eae4SChaoyong He 
362b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
36311e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
36411e9eae4SChaoyong He 	rxmode = &dev_conf->rxmode;
36511e9eae4SChaoyong He 	txmode = &dev_conf->txmode;
36611e9eae4SChaoyong He 
36711e9eae4SChaoyong He 	if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0)
36811e9eae4SChaoyong He 		rxmode->offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
36911e9eae4SChaoyong He 
37011e9eae4SChaoyong He 	/* Checking TX mode */
37111e9eae4SChaoyong He 	if (txmode->mq_mode != RTE_ETH_MQ_TX_NONE) {
372b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "TX mq_mode DCB and VMDq not supported.");
37311e9eae4SChaoyong He 		return -EINVAL;
37411e9eae4SChaoyong He 	}
37511e9eae4SChaoyong He 
37611e9eae4SChaoyong He 	/* Checking RX mode */
37711e9eae4SChaoyong He 	if ((rxmode->mq_mode & RTE_ETH_MQ_RX_RSS_FLAG) != 0 &&
37875a76c73SChaoyong He 			(hw->super.cap & NFP_NET_CFG_CTRL_RSS_ANY) == 0) {
379b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "RSS not supported.");
38011e9eae4SChaoyong He 		return -EINVAL;
38111e9eae4SChaoyong He 	}
38211e9eae4SChaoyong He 
38311e9eae4SChaoyong He 	/* Checking MTU set */
3842f1bfbf4SJames Hershaw 	if (rxmode->mtu > hw->max_mtu + NFP_ETH_OVERHEAD) {
385b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "MTU (%u) larger than the maximum possible frame size (%u).",
3862f1bfbf4SJames Hershaw 				rxmode->mtu, hw->max_mtu + NFP_ETH_OVERHEAD);
38711e9eae4SChaoyong He 		return -ERANGE;
38811e9eae4SChaoyong He 	}
38911e9eae4SChaoyong He 
39011e9eae4SChaoyong He 	return 0;
39111e9eae4SChaoyong He }
39211e9eae4SChaoyong He 
39311e9eae4SChaoyong He void
394000feb4cSChaoyong He nfp_net_log_device_information(const struct nfp_net_hw *hw,
395000feb4cSChaoyong He 		struct nfp_pf_dev *pf_dev)
39611e9eae4SChaoyong He {
39775a76c73SChaoyong He 	uint32_t cap = hw->super.cap;
398cbf062e9SChaoyong He 	uint32_t cap_ext = hw->super.cap_ext;
39975a76c73SChaoyong He 
400b6de4353SZerun Fu 	PMD_INIT_LOG(INFO, "VER: %u.%u, Maximum supported MTU: %d.",
401000feb4cSChaoyong He 			pf_dev->ver.major, pf_dev->ver.minor, hw->max_mtu);
40211e9eae4SChaoyong He 
403b6de4353SZerun Fu 	PMD_INIT_LOG(INFO, "CAP: %#x.", cap);
404df77f704SChaoyong 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",
405cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_ENABLE        ? "ENABLE "      : "",
40675a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_PROMISC       ? "PROMISC "     : "",
40775a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2BC          ? "L2BCFILT "    : "",
40875a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2MC          ? "L2MCFILT "    : "",
40975a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXCSUM        ? "RXCSUM "      : "",
41075a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXCSUM        ? "TXCSUM "      : "",
41175a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXVLAN        ? "RXVLAN "      : "",
41275a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXVLAN        ? "TXVLAN "      : "",
41375a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_SCATTER       ? "SCATTER "     : "",
41475a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_GATHER        ? "GATHER "      : "",
41575a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_LSO           ? "TSO "         : "",
416cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXQINQ        ? "RXQINQ "      : "",
417cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RXVLAN_V2     ? "RXVLANv2 "    : "",
418cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RINGCFG       ? "RINGCFG "     : "",
41975a76c73SChaoyong He 			cap & NFP_NET_CFG_CTRL_RSS           ? "RSS "         : "",
420cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_IRQMOD        ? "IRQMOD "      : "",
421cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RINGPRIO      ? "RINGPRIO "    : "",
422cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_MSIXAUTO      ? "MSIXAUTO "    : "",
423cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXRWB         ? "TXRWB "       : "",
424cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_L2SWITCH      ? "L2SWITCH "    : "",
425cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_TXVLAN_V2     ? "TXVLANv2 "    : "",
426cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_VXLAN         ? "VXLAN "       : "",
427cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_NVGRE         ? "NVGRE "       : "",
428cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_MSIX_TX_OFF   ? "MSIX_TX_OFF " : "",
429cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_LSO2          ? "TSOv2 "       : "",
430cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_RSS2          ? "RSSv2 "       : "",
431cbf062e9SChaoyong He 			cap & NFP_NET_CFG_CTRL_CSUM_COMPLETE ? "CSUM "        : "",
432df77f704SChaoyong He 			cap & NFP_NET_CFG_CTRL_LIVE_ADDR     ? "LIVE_ADDR "   : "",
433df77f704SChaoyong He 			cap & NFP_NET_CFG_CTRL_USO           ? "USO"          : "");
434cbf062e9SChaoyong He 
435b6de4353SZerun Fu 	PMD_INIT_LOG(INFO, "CAP_WORD1: %#x.", cap_ext);
436cbf062e9SChaoyong He 	PMD_INIT_LOG(INFO, "%s%s%s%s%s%s%s",
437cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE        ? "PKT_TYPE "        : "",
438cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IPSEC           ? "IPSEC "           : "",
439cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IPSEC_SM_LOOKUP ? "IPSEC_SM "        : "",
440cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IPSEC_LM_LOOKUP ? "IPSEC_LM "        : "",
441cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_MULTI_PF        ? "MULTI_PF "        : "",
442cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_FLOW_STEER      ? "FLOW_STEER "      : "",
443cbf062e9SChaoyong He 			cap_ext & NFP_NET_CFG_CTRL_IN_ORDER        ? "VIRTIO_IN_ORDER " : "");
44411e9eae4SChaoyong He 
445b6de4353SZerun Fu 	PMD_INIT_LOG(INFO, "The max_rx_queues: %u, max_tx_queues: %u.",
44611e9eae4SChaoyong He 			hw->max_rx_queues, hw->max_tx_queues);
44711e9eae4SChaoyong He }
44811e9eae4SChaoyong He 
44911e9eae4SChaoyong He static inline void
45011e9eae4SChaoyong He nfp_net_enable_rxvlan_cap(struct nfp_net_hw *hw,
45111e9eae4SChaoyong He 		uint32_t *ctrl)
45211e9eae4SChaoyong He {
45375a76c73SChaoyong He 	if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN_V2) != 0)
45411e9eae4SChaoyong He 		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN_V2;
45575a76c73SChaoyong He 	else if ((hw->super.cap & NFP_NET_CFG_CTRL_RXVLAN) != 0)
45611e9eae4SChaoyong He 		*ctrl |= NFP_NET_CFG_CTRL_RXVLAN;
45711e9eae4SChaoyong He }
45811e9eae4SChaoyong He 
45911e9eae4SChaoyong He void
46011e9eae4SChaoyong He nfp_net_enable_queues(struct rte_eth_dev *dev)
46111e9eae4SChaoyong He {
46211e9eae4SChaoyong He 	struct nfp_net_hw *hw;
46311e9eae4SChaoyong He 
464b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
46511e9eae4SChaoyong He 
46687f5b35bSChaoyong He 	nfp_enable_queues(&hw->super, dev->data->nb_rx_queues,
46787f5b35bSChaoyong He 			dev->data->nb_tx_queues);
46811e9eae4SChaoyong He }
46911e9eae4SChaoyong He 
47011e9eae4SChaoyong He void
47111e9eae4SChaoyong He nfp_net_disable_queues(struct rte_eth_dev *dev)
47211e9eae4SChaoyong He {
47372d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
47411e9eae4SChaoyong He 
475b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
47611e9eae4SChaoyong He 
47787f5b35bSChaoyong He 	nfp_disable_queues(&net_hw->super);
47811e9eae4SChaoyong He }
47911e9eae4SChaoyong He 
48011e9eae4SChaoyong He void
48111e9eae4SChaoyong He nfp_net_params_setup(struct nfp_net_hw *hw)
48211e9eae4SChaoyong He {
483f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, hw->mtu);
484f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_FLBUFSZ, hw->flbufsz);
48511e9eae4SChaoyong He }
48611e9eae4SChaoyong He 
48711e9eae4SChaoyong He void
48811e9eae4SChaoyong He nfp_net_cfg_queue_setup(struct nfp_net_hw *hw)
48911e9eae4SChaoyong He {
490464a535bSChaoyong He 	hw->super.qcp_cfg = hw->tx_bar + NFP_QCP_QUEUE_ADDR_SZ;
49111e9eae4SChaoyong He }
49211e9eae4SChaoyong He 
49311e9eae4SChaoyong He int
49411e9eae4SChaoyong He nfp_net_set_mac_addr(struct rte_eth_dev *dev,
49511e9eae4SChaoyong He 		struct rte_ether_addr *mac_addr)
49611e9eae4SChaoyong He {
49711e9eae4SChaoyong He 	uint32_t update;
498d6702227SChaoyong He 	uint32_t new_ctrl;
49972d1dea6SChaoyong He 	struct nfp_hw *hw;
50072d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
50111e9eae4SChaoyong He 
502b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
50372d1dea6SChaoyong He 	hw = &net_hw->super;
50472d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 &&
50572d1dea6SChaoyong He 			(hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) == 0) {
506b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "MAC address unable to change when port enabled.");
50711e9eae4SChaoyong He 		return -EBUSY;
50811e9eae4SChaoyong He 	}
50911e9eae4SChaoyong He 
510edbb4e1cSChaoyong He 	if (rte_is_valid_assigned_ether_addr(mac_addr) == 0) {
511b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Invalid MAC address.");
512edbb4e1cSChaoyong He 		return -EINVAL;
513edbb4e1cSChaoyong He 	}
514edbb4e1cSChaoyong He 
51511e9eae4SChaoyong He 	/* Writing new MAC to the specific port BAR address */
516503ac807SChaoyong He 	nfp_write_mac(hw, (uint8_t *)mac_addr);
51711e9eae4SChaoyong He 
51811e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_MACADDR;
519d6702227SChaoyong He 	new_ctrl = hw->ctrl;
52072d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_ENABLE) != 0 &&
52172d1dea6SChaoyong He 			(hw->cap & NFP_NET_CFG_CTRL_LIVE_ADDR) != 0)
522d6702227SChaoyong He 		new_ctrl |= NFP_NET_CFG_CTRL_LIVE_ADDR;
52311e9eae4SChaoyong He 
52411e9eae4SChaoyong He 	/* Signal the NIC about the change */
525d6702227SChaoyong He 	if (nfp_reconfig(hw, new_ctrl, update) != 0) {
526b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "MAC address update failed.");
52711e9eae4SChaoyong He 		return -EIO;
52811e9eae4SChaoyong He 	}
52911e9eae4SChaoyong He 
530d6702227SChaoyong He 	hw->ctrl = new_ctrl;
531d6702227SChaoyong He 
53211e9eae4SChaoyong He 	return 0;
53311e9eae4SChaoyong He }
53411e9eae4SChaoyong He 
53511e9eae4SChaoyong He int
53611e9eae4SChaoyong He nfp_configure_rx_interrupt(struct rte_eth_dev *dev,
53711e9eae4SChaoyong He 		struct rte_intr_handle *intr_handle)
53811e9eae4SChaoyong He {
53911e9eae4SChaoyong He 	uint16_t i;
54011e9eae4SChaoyong He 	struct nfp_net_hw *hw;
54111e9eae4SChaoyong He 
54211e9eae4SChaoyong He 	if (rte_intr_vec_list_alloc(intr_handle, "intr_vec",
54311e9eae4SChaoyong He 				dev->data->nb_rx_queues) != 0) {
544b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to allocate %d rx_queues intr_vec.",
54511e9eae4SChaoyong He 				dev->data->nb_rx_queues);
54611e9eae4SChaoyong He 		return -ENOMEM;
54711e9eae4SChaoyong He 	}
54811e9eae4SChaoyong He 
549b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
55011e9eae4SChaoyong He 
55111e9eae4SChaoyong He 	if (rte_intr_type_get(intr_handle) == RTE_INTR_HANDLE_UIO) {
552b6de4353SZerun Fu 		PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with UIO.");
55311e9eae4SChaoyong He 		/* UIO just supports one queue and no LSC */
554f58bde00SChaoyong He 		nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(0), 0);
55511e9eae4SChaoyong He 		if (rte_intr_vec_list_index_set(intr_handle, 0, 0) != 0)
55611e9eae4SChaoyong He 			return -1;
55711e9eae4SChaoyong He 	} else {
558b6de4353SZerun Fu 		PMD_DRV_LOG(INFO, "VF: enabling RX interrupt with VFIO.");
55911e9eae4SChaoyong He 		for (i = 0; i < dev->data->nb_rx_queues; i++) {
56011e9eae4SChaoyong He 			/*
56111e9eae4SChaoyong He 			 * The first msix vector is reserved for non
56211e9eae4SChaoyong He 			 * efd interrupts.
56311e9eae4SChaoyong He 			 */
564f58bde00SChaoyong He 			nn_cfg_writeb(&hw->super, NFP_NET_CFG_RXR_VEC(i), i + 1);
56511e9eae4SChaoyong He 			if (rte_intr_vec_list_index_set(intr_handle, i, i + 1) != 0)
56611e9eae4SChaoyong He 				return -1;
56711e9eae4SChaoyong He 		}
56811e9eae4SChaoyong He 	}
56911e9eae4SChaoyong He 
57011e9eae4SChaoyong He 	/* Avoiding TX interrupts */
571b4b6988aSChaoyong He 	hw->super.ctrl |= NFP_NET_CFG_CTRL_MSIX_TX_OFF;
57211e9eae4SChaoyong He 	return 0;
57311e9eae4SChaoyong He }
57411e9eae4SChaoyong He 
57511e9eae4SChaoyong He uint32_t
57611e9eae4SChaoyong He nfp_check_offloads(struct rte_eth_dev *dev)
57711e9eae4SChaoyong He {
5784a9bb682SChaoyong He 	uint32_t cap;
57911e9eae4SChaoyong He 	uint32_t ctrl = 0;
58011e9eae4SChaoyong He 	uint64_t rx_offload;
58111e9eae4SChaoyong He 	uint64_t tx_offload;
58211e9eae4SChaoyong He 	struct nfp_net_hw *hw;
58311e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
58411e9eae4SChaoyong He 
585b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
5864a9bb682SChaoyong He 	cap = hw->super.cap;
58711e9eae4SChaoyong He 
58811e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
58911e9eae4SChaoyong He 	rx_offload = dev_conf->rxmode.offloads;
59011e9eae4SChaoyong He 	tx_offload = dev_conf->txmode.offloads;
59111e9eae4SChaoyong He 
59211e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_IPV4_CKSUM) != 0) {
5934a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0)
59411e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_RXCSUM;
59511e9eae4SChaoyong He 	}
59611e9eae4SChaoyong He 
59711e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0)
59811e9eae4SChaoyong He 		nfp_net_enable_rxvlan_cap(hw, &ctrl);
59911e9eae4SChaoyong He 
60011e9eae4SChaoyong He 	if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0) {
6014a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0)
60211e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
60311e9eae4SChaoyong He 	}
60411e9eae4SChaoyong He 
60511e9eae4SChaoyong He 	hw->mtu = dev->data->mtu;
60611e9eae4SChaoyong He 
60711e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_VLAN_INSERT) != 0) {
6084a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_TXVLAN_V2) != 0)
60911e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_TXVLAN_V2;
6104a9bb682SChaoyong He 		else if ((cap & NFP_NET_CFG_CTRL_TXVLAN) != 0)
61111e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_TXVLAN;
61211e9eae4SChaoyong He 	}
61311e9eae4SChaoyong He 
61411e9eae4SChaoyong He 	/* L2 broadcast */
6154a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_L2BC) != 0)
61611e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_L2BC;
61711e9eae4SChaoyong He 
61811e9eae4SChaoyong He 	/* L2 multicast */
6194a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_L2MC) != 0)
62011e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_L2MC;
62111e9eae4SChaoyong He 
62211e9eae4SChaoyong He 	/* TX checksum offload */
62311e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_IPV4_CKSUM) != 0 ||
62411e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_UDP_CKSUM) != 0 ||
62511e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_TCP_CKSUM) != 0)
62611e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_TXCSUM;
62711e9eae4SChaoyong He 
62811e9eae4SChaoyong He 	/* LSO offload */
62911e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_TCP_TSO) != 0 ||
630df77f704SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_UDP_TSO) != 0 ||
63111e9eae4SChaoyong He 			(tx_offload & RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO) != 0) {
6324a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_LSO) != 0)
63311e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_LSO;
634afa83796SChaoyong He 		else if ((cap & NFP_NET_CFG_CTRL_LSO2) != 0)
63511e9eae4SChaoyong He 			ctrl |= NFP_NET_CFG_CTRL_LSO2;
63611e9eae4SChaoyong He 	}
63711e9eae4SChaoyong He 
63811e9eae4SChaoyong He 	/* RX gather */
63911e9eae4SChaoyong He 	if ((tx_offload & RTE_ETH_TX_OFFLOAD_MULTI_SEGS) != 0)
64011e9eae4SChaoyong He 		ctrl |= NFP_NET_CFG_CTRL_GATHER;
64111e9eae4SChaoyong He 
64211e9eae4SChaoyong He 	return ctrl;
64311e9eae4SChaoyong He }
64411e9eae4SChaoyong He 
64511e9eae4SChaoyong He int
64611e9eae4SChaoyong He nfp_net_promisc_enable(struct rte_eth_dev *dev)
64711e9eae4SChaoyong He {
64811e9eae4SChaoyong He 	int ret;
64972d1dea6SChaoyong He 	uint32_t update;
65011e9eae4SChaoyong He 	uint32_t new_ctrl;
65172d1dea6SChaoyong He 	struct nfp_hw *hw;
65272d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
65311e9eae4SChaoyong He 
654b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
65511e9eae4SChaoyong He 
65672d1dea6SChaoyong He 	hw = &net_hw->super;
65772d1dea6SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) {
658b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Promiscuous mode not supported.");
65911e9eae4SChaoyong He 		return -ENOTSUP;
66011e9eae4SChaoyong He 	}
66111e9eae4SChaoyong He 
66272d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) != 0) {
663b6de4353SZerun Fu 		PMD_DRV_LOG(INFO, "Promiscuous mode already enabled.");
66411e9eae4SChaoyong He 		return 0;
66511e9eae4SChaoyong He 	}
66611e9eae4SChaoyong He 
66772d1dea6SChaoyong He 	new_ctrl = hw->ctrl | NFP_NET_CFG_CTRL_PROMISC;
66811e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
66911e9eae4SChaoyong He 
67072d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
67111e9eae4SChaoyong He 	if (ret != 0)
67211e9eae4SChaoyong He 		return ret;
67311e9eae4SChaoyong He 
67472d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
67511e9eae4SChaoyong He 
67611e9eae4SChaoyong He 	return 0;
67711e9eae4SChaoyong He }
67811e9eae4SChaoyong He 
67911e9eae4SChaoyong He int
68011e9eae4SChaoyong He nfp_net_promisc_disable(struct rte_eth_dev *dev)
68111e9eae4SChaoyong He {
68211e9eae4SChaoyong He 	int ret;
68372d1dea6SChaoyong He 	uint32_t update;
68411e9eae4SChaoyong He 	uint32_t new_ctrl;
68572d1dea6SChaoyong He 	struct nfp_hw *hw;
68672d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
68711e9eae4SChaoyong He 
688b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
68972d1dea6SChaoyong He 	hw = &net_hw->super;
69011e9eae4SChaoyong He 
6915ff76867SChaoyong He 	if ((hw->cap & NFP_NET_CFG_CTRL_PROMISC) == 0) {
692b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Promiscuous mode not supported.");
6935ff76867SChaoyong He 		return -ENOTSUP;
6945ff76867SChaoyong He 	}
6955ff76867SChaoyong He 
69672d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_PROMISC) == 0) {
697b6de4353SZerun Fu 		PMD_DRV_LOG(INFO, "Promiscuous mode already disabled.");
69811e9eae4SChaoyong He 		return 0;
69911e9eae4SChaoyong He 	}
70011e9eae4SChaoyong He 
70172d1dea6SChaoyong He 	new_ctrl = hw->ctrl & ~NFP_NET_CFG_CTRL_PROMISC;
70211e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
70311e9eae4SChaoyong He 
70472d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
70511e9eae4SChaoyong He 	if (ret != 0)
70611e9eae4SChaoyong He 		return ret;
70711e9eae4SChaoyong He 
70872d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
70911e9eae4SChaoyong He 
71011e9eae4SChaoyong He 	return 0;
71111e9eae4SChaoyong He }
71211e9eae4SChaoyong He 
7134a86c36bSQin Ke static int
7144a86c36bSQin Ke nfp_net_set_allmulticast_mode(struct rte_eth_dev *dev,
7154a86c36bSQin Ke 		bool enable)
7164a86c36bSQin Ke {
7174a86c36bSQin Ke 	int ret;
7184a86c36bSQin Ke 	uint32_t update;
7194a86c36bSQin Ke 	struct nfp_hw *hw;
7204a86c36bSQin Ke 	uint32_t cap_extend;
7214a86c36bSQin Ke 	uint32_t ctrl_extend;
7224a86c36bSQin Ke 	uint32_t new_ctrl_extend;
7234a86c36bSQin Ke 	struct nfp_net_hw *net_hw;
7244a86c36bSQin Ke 
7254a86c36bSQin Ke 	net_hw = nfp_net_get_hw(dev);
7264a86c36bSQin Ke 	hw = &net_hw->super;
7274a86c36bSQin Ke 
7284a86c36bSQin Ke 	cap_extend = hw->cap_ext;
7294a86c36bSQin Ke 	if ((cap_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0) {
730b6de4353SZerun Fu 		PMD_DRV_LOG(DEBUG, "Allmulticast mode not supported.");
7314a86c36bSQin Ke 		return -ENOTSUP;
7324a86c36bSQin Ke 	}
7334a86c36bSQin Ke 
7344a86c36bSQin Ke 	/*
7354a86c36bSQin Ke 	 * Allmulticast mode enabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 0.
7364a86c36bSQin Ke 	 * Allmulticast mode disabled when NFP_NET_CFG_CTRL_MCAST_FILTER bit is 1.
7374a86c36bSQin Ke 	 */
7384a86c36bSQin Ke 	ctrl_extend = hw->ctrl_ext;
7394a86c36bSQin Ke 	if (enable) {
7404a86c36bSQin Ke 		if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) == 0)
7414a86c36bSQin Ke 			return 0;
7424a86c36bSQin Ke 
7434a86c36bSQin Ke 		new_ctrl_extend = ctrl_extend & ~NFP_NET_CFG_CTRL_MCAST_FILTER;
7444a86c36bSQin Ke 	} else {
7454a86c36bSQin Ke 		if ((ctrl_extend & NFP_NET_CFG_CTRL_MCAST_FILTER) != 0)
7464a86c36bSQin Ke 			return 0;
7474a86c36bSQin Ke 
7484a86c36bSQin Ke 		new_ctrl_extend = ctrl_extend | NFP_NET_CFG_CTRL_MCAST_FILTER;
7494a86c36bSQin Ke 	}
7504a86c36bSQin Ke 
7514a86c36bSQin Ke 	update = NFP_NET_CFG_UPDATE_GEN;
7524a86c36bSQin Ke 
7534a86c36bSQin Ke 	ret = nfp_ext_reconfig(hw, new_ctrl_extend, update);
7544a86c36bSQin Ke 	if (ret != 0)
7554a86c36bSQin Ke 		return ret;
7564a86c36bSQin Ke 
7574a86c36bSQin Ke 	hw->ctrl_ext = new_ctrl_extend;
7584a86c36bSQin Ke 	return 0;
7594a86c36bSQin Ke }
7604a86c36bSQin Ke 
7614a86c36bSQin Ke int
7624a86c36bSQin Ke nfp_net_allmulticast_enable(struct rte_eth_dev *dev)
7634a86c36bSQin Ke {
7644a86c36bSQin Ke 	return nfp_net_set_allmulticast_mode(dev, true);
7654a86c36bSQin Ke }
7664a86c36bSQin Ke 
7674a86c36bSQin Ke int
7684a86c36bSQin Ke nfp_net_allmulticast_disable(struct rte_eth_dev *dev)
7694a86c36bSQin Ke {
7704a86c36bSQin Ke 	return nfp_net_set_allmulticast_mode(dev, false);
7714a86c36bSQin Ke }
7724a86c36bSQin Ke 
773a476ccaeSZerun Fu static void
7741b3b12c4SQin Ke nfp_net_pf_speed_update(struct rte_eth_dev *dev,
775ff9f5a56SChaoyong He 		struct nfp_net_hw_priv *hw_priv,
7768412feedSZerun Fu 		struct rte_eth_link *link)
7778412feedSZerun Fu {
778441839f1SQin Ke 	uint8_t idx;
779aaa57548SZerun Fu 	enum nfp_eth_aneg aneg;
780aaa57548SZerun Fu 	struct nfp_pf_dev *pf_dev;
7818412feedSZerun Fu 	struct nfp_eth_table *nfp_eth_table;
7828412feedSZerun Fu 	struct nfp_eth_table_port *eth_port;
7838412feedSZerun Fu 
784aaa57548SZerun Fu 	pf_dev = hw_priv->pf_dev;
785441839f1SQin Ke 	idx = nfp_net_get_idx(dev);
786441839f1SQin Ke 	aneg = pf_dev->nfp_eth_table->ports[idx].aneg;
787aaa57548SZerun Fu 
7888412feedSZerun Fu 	/* Compare whether the current status has changed. */
789aaa57548SZerun Fu 	if (pf_dev->speed_updated || aneg == NFP_ANEG_AUTO) {
790aaa57548SZerun Fu 		nfp_eth_table = nfp_eth_read_ports(pf_dev->cpp);
7918412feedSZerun Fu 		if (nfp_eth_table == NULL) {
79217d6720eSZerun Fu 			PMD_DRV_LOG(DEBUG, "Failed to get nfp_eth_table.");
793aaa57548SZerun Fu 		} else {
794441839f1SQin Ke 			pf_dev->nfp_eth_table->ports[idx] = nfp_eth_table->ports[idx];
7958412feedSZerun Fu 			free(nfp_eth_table);
796aaa57548SZerun Fu 			pf_dev->speed_updated = false;
797aaa57548SZerun Fu 		}
7988412feedSZerun Fu 	}
7998412feedSZerun Fu 
800aaa57548SZerun Fu 	nfp_eth_table = pf_dev->nfp_eth_table;
801441839f1SQin Ke 	eth_port = &nfp_eth_table->ports[idx];
8028412feedSZerun Fu 
80348de6254SQin Ke 	link->link_speed = nfp_net_link_speed_nfp2rte_check(eth_port->speed);
8048412feedSZerun Fu 
8058412feedSZerun Fu 	if (dev->data->dev_conf.link_speeds == RTE_ETH_LINK_SPEED_AUTONEG &&
8068412feedSZerun Fu 			eth_port->supp_aneg)
8078412feedSZerun Fu 		link->link_autoneg = RTE_ETH_LINK_AUTONEG;
8088412feedSZerun Fu }
8098412feedSZerun Fu 
8102e3ad187SQin Ke static void
8112e3ad187SQin Ke nfp_net_vf_speed_update(struct rte_eth_link *link,
8122e3ad187SQin Ke 		uint32_t link_status)
8132e3ad187SQin Ke {
8142e3ad187SQin Ke 	size_t link_rate_index;
8152e3ad187SQin Ke 
8162e3ad187SQin Ke 	/*
8172e3ad187SQin Ke 	 * Shift and mask link_status so that it is effectively the value
8182e3ad187SQin Ke 	 * at offset NFP_NET_CFG_STS_NSP_LINK_RATE.
8192e3ad187SQin Ke 	 */
8202e3ad187SQin Ke 	link_rate_index = (link_status >> NFP_NET_CFG_STS_LINK_RATE_SHIFT) &
8212e3ad187SQin Ke 			NFP_NET_CFG_STS_LINK_RATE_MASK;
8222e3ad187SQin Ke 	if (link_rate_index < RTE_DIM(nfp_net_link_speed_nfp2rte))
8232e3ad187SQin Ke 		link->link_speed = nfp_net_link_speed_nfp2rte[link_rate_index];
8242e3ad187SQin Ke 	else
8252e3ad187SQin Ke 		link->link_speed = RTE_ETH_SPEED_NUM_NONE;
8262e3ad187SQin Ke }
8272e3ad187SQin Ke 
828c4de52ecSChaoyong He int
829c4de52ecSChaoyong He nfp_net_link_update_common(struct rte_eth_dev *dev,
830c4de52ecSChaoyong He 		struct rte_eth_link *link,
831c4de52ecSChaoyong He 		uint32_t link_status)
832c4de52ecSChaoyong He {
833c4de52ecSChaoyong He 	int ret;
834ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
835c4de52ecSChaoyong He 
836ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
837c4de52ecSChaoyong He 	if (link->link_status == RTE_ETH_LINK_UP) {
838*c43d2aabSLong Wu 		if (nfp_net_is_pf(dev))
839441839f1SQin Ke 			nfp_net_pf_speed_update(dev, hw_priv, link);
8402e3ad187SQin Ke 		else
8412e3ad187SQin Ke 			nfp_net_vf_speed_update(link, link_status);
842c4de52ecSChaoyong He 	}
843c4de52ecSChaoyong He 
844c4de52ecSChaoyong He 	ret = rte_eth_linkstatus_set(dev, link);
845c4de52ecSChaoyong He 	if (ret == 0) {
8461b3b12c4SQin Ke 		if (link->link_status == RTE_ETH_LINK_UP)
847b6de4353SZerun Fu 			PMD_DRV_LOG(INFO, "NIC Link is Up.");
848c4de52ecSChaoyong He 		else
849b6de4353SZerun Fu 			PMD_DRV_LOG(INFO, "NIC Link is Down.");
850c4de52ecSChaoyong He 	}
851c4de52ecSChaoyong He 
852c4de52ecSChaoyong He 	return ret;
853c4de52ecSChaoyong He }
854c4de52ecSChaoyong He 
85511e9eae4SChaoyong He /*
85611e9eae4SChaoyong He  * Return 0 means link status changed, -1 means not changed
85711e9eae4SChaoyong He  *
85811e9eae4SChaoyong He  * Wait to complete is needed as it can take up to 9 seconds to get the Link
85911e9eae4SChaoyong He  * status.
86011e9eae4SChaoyong He  */
86111e9eae4SChaoyong He int
86211e9eae4SChaoyong He nfp_net_link_update(struct rte_eth_dev *dev,
86311e9eae4SChaoyong He 		__rte_unused int wait_to_complete)
86411e9eae4SChaoyong He {
86511e9eae4SChaoyong He 	int ret;
86611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
86711e9eae4SChaoyong He 	uint32_t nn_link_status;
86811e9eae4SChaoyong He 	struct rte_eth_link link;
869ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
87011e9eae4SChaoyong He 
871b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
872ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
87311e9eae4SChaoyong He 
87411e9eae4SChaoyong He 	memset(&link, 0, sizeof(struct rte_eth_link));
87511e9eae4SChaoyong He 
87611e9eae4SChaoyong He 	/* Read link status */
877f58bde00SChaoyong He 	nn_link_status = nn_cfg_readw(&hw->super, NFP_NET_CFG_STS);
87811e9eae4SChaoyong He 	if ((nn_link_status & NFP_NET_CFG_STS_LINK) != 0)
87911e9eae4SChaoyong He 		link.link_status = RTE_ETH_LINK_UP;
88011e9eae4SChaoyong He 
88111e9eae4SChaoyong He 	link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
88211e9eae4SChaoyong He 
883441839f1SQin Ke 	ret = nfp_net_link_update_common(dev, &link, nn_link_status);
8848412feedSZerun Fu 	if (ret == -EIO)
8858412feedSZerun Fu 		return ret;
88611e9eae4SChaoyong He 
88711e9eae4SChaoyong He 	/*
88811e9eae4SChaoyong He 	 * Notify the port to update the speed value in the CTRL BAR from NSP.
88911e9eae4SChaoyong He 	 * Not applicable for VFs as the associated PF is still attached to the
89011e9eae4SChaoyong He 	 * kernel driver.
89111e9eae4SChaoyong He 	 */
892c2b4f0d5SChaoyong He 	if (hw_priv != NULL && hw_priv->is_pf)
89311e9eae4SChaoyong He 		nfp_net_notify_port_speed(hw, &link);
89411e9eae4SChaoyong He 
89511e9eae4SChaoyong He 	return ret;
89611e9eae4SChaoyong He }
89711e9eae4SChaoyong He 
89811e9eae4SChaoyong He int
89911e9eae4SChaoyong He nfp_net_stats_get(struct rte_eth_dev *dev,
90011e9eae4SChaoyong He 		struct rte_eth_stats *stats)
90111e9eae4SChaoyong He {
90211e9eae4SChaoyong He 	uint16_t i;
90311e9eae4SChaoyong He 	struct nfp_net_hw *hw;
90411e9eae4SChaoyong He 	struct rte_eth_stats nfp_dev_stats;
90511e9eae4SChaoyong He 
90611e9eae4SChaoyong He 	if (stats == NULL)
90711e9eae4SChaoyong He 		return -EINVAL;
90811e9eae4SChaoyong He 
909b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
91011e9eae4SChaoyong He 
91111e9eae4SChaoyong He 	memset(&nfp_dev_stats, 0, sizeof(nfp_dev_stats));
91211e9eae4SChaoyong He 
91311e9eae4SChaoyong He 	/* Reading per RX ring stats */
91411e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
91511e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
91611e9eae4SChaoyong He 			break;
91711e9eae4SChaoyong He 
91811e9eae4SChaoyong He 		nfp_dev_stats.q_ipackets[i] =
919f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i));
92011e9eae4SChaoyong He 		nfp_dev_stats.q_ipackets[i] -=
92111e9eae4SChaoyong He 				hw->eth_stats_base.q_ipackets[i];
92211e9eae4SChaoyong He 
92311e9eae4SChaoyong He 		nfp_dev_stats.q_ibytes[i] =
924f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8);
92511e9eae4SChaoyong He 		nfp_dev_stats.q_ibytes[i] -=
92611e9eae4SChaoyong He 				hw->eth_stats_base.q_ibytes[i];
92711e9eae4SChaoyong He 	}
92811e9eae4SChaoyong He 
92911e9eae4SChaoyong He 	/* Reading per TX ring stats */
93011e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
93111e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
93211e9eae4SChaoyong He 			break;
93311e9eae4SChaoyong He 
93411e9eae4SChaoyong He 		nfp_dev_stats.q_opackets[i] =
935f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i));
93611e9eae4SChaoyong He 		nfp_dev_stats.q_opackets[i] -= hw->eth_stats_base.q_opackets[i];
93711e9eae4SChaoyong He 
93811e9eae4SChaoyong He 		nfp_dev_stats.q_obytes[i] =
939f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8);
94011e9eae4SChaoyong He 		nfp_dev_stats.q_obytes[i] -= hw->eth_stats_base.q_obytes[i];
94111e9eae4SChaoyong He 	}
94211e9eae4SChaoyong He 
943f58bde00SChaoyong He 	nfp_dev_stats.ipackets = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES);
94411e9eae4SChaoyong He 	nfp_dev_stats.ipackets -= hw->eth_stats_base.ipackets;
94511e9eae4SChaoyong He 
946f58bde00SChaoyong He 	nfp_dev_stats.ibytes = nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS);
94711e9eae4SChaoyong He 	nfp_dev_stats.ibytes -= hw->eth_stats_base.ibytes;
94811e9eae4SChaoyong He 
94911e9eae4SChaoyong He 	nfp_dev_stats.opackets =
950f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES);
95111e9eae4SChaoyong He 	nfp_dev_stats.opackets -= hw->eth_stats_base.opackets;
95211e9eae4SChaoyong He 
95311e9eae4SChaoyong He 	nfp_dev_stats.obytes =
954f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS);
95511e9eae4SChaoyong He 	nfp_dev_stats.obytes -= hw->eth_stats_base.obytes;
95611e9eae4SChaoyong He 
95711e9eae4SChaoyong He 	/* Reading general device stats */
95811e9eae4SChaoyong He 	nfp_dev_stats.ierrors =
959f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS);
96011e9eae4SChaoyong He 	nfp_dev_stats.ierrors -= hw->eth_stats_base.ierrors;
96111e9eae4SChaoyong He 
96211e9eae4SChaoyong He 	nfp_dev_stats.oerrors =
963f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS);
96411e9eae4SChaoyong He 	nfp_dev_stats.oerrors -= hw->eth_stats_base.oerrors;
96511e9eae4SChaoyong He 
96611e9eae4SChaoyong He 	/* RX ring mbuf allocation failures */
96711e9eae4SChaoyong He 	nfp_dev_stats.rx_nombuf = dev->data->rx_mbuf_alloc_failed;
96811e9eae4SChaoyong He 
96911e9eae4SChaoyong He 	nfp_dev_stats.imissed =
970f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS);
97111e9eae4SChaoyong He 	nfp_dev_stats.imissed -= hw->eth_stats_base.imissed;
97211e9eae4SChaoyong He 
97311e9eae4SChaoyong He 	memcpy(stats, &nfp_dev_stats, sizeof(*stats));
97411e9eae4SChaoyong He 	return 0;
97511e9eae4SChaoyong He }
97611e9eae4SChaoyong He 
97711e9eae4SChaoyong He /*
97811e9eae4SChaoyong He  * hw->eth_stats_base records the per counter starting point.
97911e9eae4SChaoyong He  * Lets update it now.
98011e9eae4SChaoyong He  */
98111e9eae4SChaoyong He int
98211e9eae4SChaoyong He nfp_net_stats_reset(struct rte_eth_dev *dev)
98311e9eae4SChaoyong He {
98411e9eae4SChaoyong He 	uint16_t i;
98511e9eae4SChaoyong He 	struct nfp_net_hw *hw;
98611e9eae4SChaoyong He 
987b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
98811e9eae4SChaoyong He 
98911e9eae4SChaoyong He 	/* Reading per RX ring stats */
99011e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
99111e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
99211e9eae4SChaoyong He 			break;
99311e9eae4SChaoyong He 
99411e9eae4SChaoyong He 		hw->eth_stats_base.q_ipackets[i] =
995f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i));
99611e9eae4SChaoyong He 
99711e9eae4SChaoyong He 		hw->eth_stats_base.q_ibytes[i] =
998f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_RXR_STATS(i) + 0x8);
99911e9eae4SChaoyong He 	}
100011e9eae4SChaoyong He 
100111e9eae4SChaoyong He 	/* Reading per TX ring stats */
100211e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
100311e9eae4SChaoyong He 		if (i == RTE_ETHDEV_QUEUE_STAT_CNTRS)
100411e9eae4SChaoyong He 			break;
100511e9eae4SChaoyong He 
100611e9eae4SChaoyong He 		hw->eth_stats_base.q_opackets[i] =
1007f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i));
100811e9eae4SChaoyong He 
100911e9eae4SChaoyong He 		hw->eth_stats_base.q_obytes[i] =
1010f58bde00SChaoyong He 				nn_cfg_readq(&hw->super, NFP_NET_CFG_TXR_STATS(i) + 0x8);
101111e9eae4SChaoyong He 	}
101211e9eae4SChaoyong He 
101311e9eae4SChaoyong He 	hw->eth_stats_base.ipackets =
1014f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_FRAMES);
101511e9eae4SChaoyong He 
101611e9eae4SChaoyong He 	hw->eth_stats_base.ibytes =
1017f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_OCTETS);
101811e9eae4SChaoyong He 
101911e9eae4SChaoyong He 	hw->eth_stats_base.opackets =
1020f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_FRAMES);
102111e9eae4SChaoyong He 
102211e9eae4SChaoyong He 	hw->eth_stats_base.obytes =
1023f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_OCTETS);
102411e9eae4SChaoyong He 
102511e9eae4SChaoyong He 	/* Reading general device stats */
102611e9eae4SChaoyong He 	hw->eth_stats_base.ierrors =
1027f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_ERRORS);
102811e9eae4SChaoyong He 
102911e9eae4SChaoyong He 	hw->eth_stats_base.oerrors =
1030f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_TX_ERRORS);
103111e9eae4SChaoyong He 
103211e9eae4SChaoyong He 	/* RX ring mbuf allocation failures */
103311e9eae4SChaoyong He 	dev->data->rx_mbuf_alloc_failed = 0;
103411e9eae4SChaoyong He 
103511e9eae4SChaoyong He 	hw->eth_stats_base.imissed =
1036f58bde00SChaoyong He 			nn_cfg_readq(&hw->super, NFP_NET_CFG_STATS_RX_DISCARDS);
103711e9eae4SChaoyong He 
103811e9eae4SChaoyong He 	return 0;
103911e9eae4SChaoyong He }
104011e9eae4SChaoyong He 
104111e9eae4SChaoyong He uint32_t
104211e9eae4SChaoyong He nfp_net_xstats_size(const struct rte_eth_dev *dev)
104311e9eae4SChaoyong He {
104411e9eae4SChaoyong He 	uint32_t count;
104582a2c286SChaoyong He 	bool vf_flag = false;
104611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
104782a2c286SChaoyong He 	struct nfp_flower_representor *repr;
104811e9eae4SChaoyong He 	const uint32_t size = RTE_DIM(nfp_net_xstats);
104911e9eae4SChaoyong He 
105082a2c286SChaoyong He 	if (rte_eth_dev_is_repr(dev)) {
105182a2c286SChaoyong He 		repr = dev->data->dev_private;
1052608bc946SPeng Zhang 		if (nfp_flower_repr_is_vf(repr))
105382a2c286SChaoyong He 			vf_flag = true;
105482a2c286SChaoyong He 	} else {
105582a2c286SChaoyong He 		hw = dev->data->dev_private;
105682a2c286SChaoyong He 		if (hw->mac_stats == NULL)
105782a2c286SChaoyong He 			vf_flag = true;
105882a2c286SChaoyong He 	}
105982a2c286SChaoyong He 
106082a2c286SChaoyong He 	/* If the device is a VF or VF-repr, then there will be no MAC stats */
106182a2c286SChaoyong He 	if (vf_flag) {
106211e9eae4SChaoyong He 		for (count = 0; count < size; count++) {
106311e9eae4SChaoyong He 			if (nfp_net_xstats[count].group == NFP_XSTAT_GROUP_MAC)
106411e9eae4SChaoyong He 				break;
106511e9eae4SChaoyong He 		}
106611e9eae4SChaoyong He 
106711e9eae4SChaoyong He 		return count;
106811e9eae4SChaoyong He 	}
106911e9eae4SChaoyong He 
107011e9eae4SChaoyong He 	return size;
107111e9eae4SChaoyong He }
107211e9eae4SChaoyong He 
107311e9eae4SChaoyong He static const struct nfp_xstat *
107411e9eae4SChaoyong He nfp_net_xstats_info(const struct rte_eth_dev *dev,
107511e9eae4SChaoyong He 		uint32_t index)
107611e9eae4SChaoyong He {
107711e9eae4SChaoyong He 	if (index >= nfp_net_xstats_size(dev)) {
1078b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "The xstat index out of bounds.");
107911e9eae4SChaoyong He 		return NULL;
108011e9eae4SChaoyong He 	}
108111e9eae4SChaoyong He 
108211e9eae4SChaoyong He 	return &nfp_net_xstats[index];
108311e9eae4SChaoyong He }
108411e9eae4SChaoyong He 
108511e9eae4SChaoyong He static uint64_t
108611e9eae4SChaoyong He nfp_net_xstats_value(const struct rte_eth_dev *dev,
108711e9eae4SChaoyong He 		uint32_t index,
108811e9eae4SChaoyong He 		bool raw)
108911e9eae4SChaoyong He {
109011e9eae4SChaoyong He 	uint64_t value;
109182a2c286SChaoyong He 	uint8_t *mac_stats;
109211e9eae4SChaoyong He 	struct nfp_net_hw *hw;
109311e9eae4SChaoyong He 	struct nfp_xstat xstat;
109482a2c286SChaoyong He 	struct rte_eth_xstat *xstats_base;
109582a2c286SChaoyong He 	struct nfp_flower_representor *repr;
109611e9eae4SChaoyong He 
109782a2c286SChaoyong He 	if (rte_eth_dev_is_repr(dev)) {
109882a2c286SChaoyong He 		repr = dev->data->dev_private;
109982a2c286SChaoyong He 		hw = repr->app_fw_flower->pf_hw;
110082a2c286SChaoyong He 
110182a2c286SChaoyong He 		mac_stats = repr->mac_stats;
110282a2c286SChaoyong He 		xstats_base = repr->repr_xstats_base;
110382a2c286SChaoyong He 	} else {
110482a2c286SChaoyong He 		hw = dev->data->dev_private;
110582a2c286SChaoyong He 
110682a2c286SChaoyong He 		mac_stats = hw->mac_stats;
110782a2c286SChaoyong He 		xstats_base = hw->eth_xstats_base;
110882a2c286SChaoyong He 	}
110982a2c286SChaoyong He 
111011e9eae4SChaoyong He 	xstat = nfp_net_xstats[index];
111111e9eae4SChaoyong He 
111211e9eae4SChaoyong He 	if (xstat.group == NFP_XSTAT_GROUP_MAC)
111382a2c286SChaoyong He 		value = nn_readq(mac_stats + xstat.offset);
111411e9eae4SChaoyong He 	else
1115f58bde00SChaoyong He 		value = nn_cfg_readq(&hw->super, xstat.offset);
111611e9eae4SChaoyong He 
111711e9eae4SChaoyong He 	if (raw)
111811e9eae4SChaoyong He 		return value;
111911e9eae4SChaoyong He 
112011e9eae4SChaoyong He 	/*
112111e9eae4SChaoyong He 	 * A baseline value of each statistic counter is recorded when stats are "reset".
112211e9eae4SChaoyong He 	 * Thus, the value returned by this function need to be decremented by this
112311e9eae4SChaoyong He 	 * baseline value. The result is the count of this statistic since the last time
112411e9eae4SChaoyong He 	 * it was "reset".
112511e9eae4SChaoyong He 	 */
112682a2c286SChaoyong He 	return value - xstats_base[index].value;
112711e9eae4SChaoyong He }
112811e9eae4SChaoyong He 
112911e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */
113011e9eae4SChaoyong He int
113111e9eae4SChaoyong He nfp_net_xstats_get_names(struct rte_eth_dev *dev,
113211e9eae4SChaoyong He 		struct rte_eth_xstat_name *xstats_names,
113311e9eae4SChaoyong He 		unsigned int size)
113411e9eae4SChaoyong He {
113511e9eae4SChaoyong He 	uint32_t id;
113611e9eae4SChaoyong He 	uint32_t nfp_size;
113711e9eae4SChaoyong He 	uint32_t read_size;
113811e9eae4SChaoyong He 
113911e9eae4SChaoyong He 	nfp_size = nfp_net_xstats_size(dev);
114011e9eae4SChaoyong He 
114111e9eae4SChaoyong He 	if (xstats_names == NULL)
114211e9eae4SChaoyong He 		return nfp_size;
114311e9eae4SChaoyong He 
114411e9eae4SChaoyong He 	/* Read at most NFP xstats number of names. */
114511e9eae4SChaoyong He 	read_size = RTE_MIN(size, nfp_size);
114611e9eae4SChaoyong He 
114711e9eae4SChaoyong He 	for (id = 0; id < read_size; id++)
114811e9eae4SChaoyong He 		rte_strlcpy(xstats_names[id].name, nfp_net_xstats[id].name,
114911e9eae4SChaoyong He 				RTE_ETH_XSTATS_NAME_SIZE);
115011e9eae4SChaoyong He 
115111e9eae4SChaoyong He 	return read_size;
115211e9eae4SChaoyong He }
115311e9eae4SChaoyong He 
115411e9eae4SChaoyong He /* NOTE: All callers ensure dev is always set. */
115511e9eae4SChaoyong He int
115611e9eae4SChaoyong He nfp_net_xstats_get(struct rte_eth_dev *dev,
115711e9eae4SChaoyong He 		struct rte_eth_xstat *xstats,
115811e9eae4SChaoyong He 		unsigned int n)
115911e9eae4SChaoyong He {
116011e9eae4SChaoyong He 	uint32_t id;
116111e9eae4SChaoyong He 	uint32_t nfp_size;
116211e9eae4SChaoyong He 	uint32_t read_size;
116311e9eae4SChaoyong He 
116411e9eae4SChaoyong He 	nfp_size = nfp_net_xstats_size(dev);
116511e9eae4SChaoyong He 
116611e9eae4SChaoyong He 	if (xstats == NULL)
116711e9eae4SChaoyong He 		return nfp_size;
116811e9eae4SChaoyong He 
116911e9eae4SChaoyong He 	/* Read at most NFP xstats number of values. */
117011e9eae4SChaoyong He 	read_size = RTE_MIN(n, nfp_size);
117111e9eae4SChaoyong He 
117211e9eae4SChaoyong He 	for (id = 0; id < read_size; id++) {
117311e9eae4SChaoyong He 		xstats[id].id = id;
117411e9eae4SChaoyong He 		xstats[id].value = nfp_net_xstats_value(dev, id, false);
117511e9eae4SChaoyong He 	}
117611e9eae4SChaoyong He 
117711e9eae4SChaoyong He 	return read_size;
117811e9eae4SChaoyong He }
117911e9eae4SChaoyong He 
118011e9eae4SChaoyong He /*
118111e9eae4SChaoyong He  * NOTE: The only caller rte_eth_xstats_get_names_by_id() ensures dev,
118211e9eae4SChaoyong He  * ids, xstats_names and size are valid, and non-NULL.
118311e9eae4SChaoyong He  */
118411e9eae4SChaoyong He int
118511e9eae4SChaoyong He nfp_net_xstats_get_names_by_id(struct rte_eth_dev *dev,
118611e9eae4SChaoyong He 		const uint64_t *ids,
118711e9eae4SChaoyong He 		struct rte_eth_xstat_name *xstats_names,
118811e9eae4SChaoyong He 		unsigned int size)
118911e9eae4SChaoyong He {
119011e9eae4SChaoyong He 	uint32_t i;
119111e9eae4SChaoyong He 	uint32_t read_size;
119211e9eae4SChaoyong He 
119311e9eae4SChaoyong He 	/* Read at most NFP xstats number of names. */
119411e9eae4SChaoyong He 	read_size = RTE_MIN(size, nfp_net_xstats_size(dev));
119511e9eae4SChaoyong He 
119611e9eae4SChaoyong He 	for (i = 0; i < read_size; i++) {
119711e9eae4SChaoyong He 		const struct nfp_xstat *xstat;
119811e9eae4SChaoyong He 
119911e9eae4SChaoyong He 		/* Make sure ID is valid for device. */
120011e9eae4SChaoyong He 		xstat = nfp_net_xstats_info(dev, ids[i]);
120111e9eae4SChaoyong He 		if (xstat == NULL)
120211e9eae4SChaoyong He 			return -EINVAL;
120311e9eae4SChaoyong He 
120411e9eae4SChaoyong He 		rte_strlcpy(xstats_names[i].name, xstat->name,
120511e9eae4SChaoyong He 				RTE_ETH_XSTATS_NAME_SIZE);
120611e9eae4SChaoyong He 	}
120711e9eae4SChaoyong He 
120811e9eae4SChaoyong He 	return read_size;
120911e9eae4SChaoyong He }
121011e9eae4SChaoyong He 
121111e9eae4SChaoyong He /*
121211e9eae4SChaoyong He  * NOTE: The only caller rte_eth_xstats_get_by_id() ensures dev,
121311e9eae4SChaoyong He  * ids, values and n are valid, and non-NULL.
121411e9eae4SChaoyong He  */
121511e9eae4SChaoyong He int
121611e9eae4SChaoyong He nfp_net_xstats_get_by_id(struct rte_eth_dev *dev,
121711e9eae4SChaoyong He 		const uint64_t *ids,
121811e9eae4SChaoyong He 		uint64_t *values,
121911e9eae4SChaoyong He 		unsigned int n)
122011e9eae4SChaoyong He {
122111e9eae4SChaoyong He 	uint32_t i;
122211e9eae4SChaoyong He 	uint32_t read_size;
122311e9eae4SChaoyong He 
122411e9eae4SChaoyong He 	/* Read at most NFP xstats number of values. */
122511e9eae4SChaoyong He 	read_size = RTE_MIN(n, nfp_net_xstats_size(dev));
122611e9eae4SChaoyong He 
122711e9eae4SChaoyong He 	for (i = 0; i < read_size; i++) {
122811e9eae4SChaoyong He 		const struct nfp_xstat *xstat;
122911e9eae4SChaoyong He 
123011e9eae4SChaoyong He 		/* Make sure index is valid for device. */
123111e9eae4SChaoyong He 		xstat = nfp_net_xstats_info(dev, ids[i]);
123211e9eae4SChaoyong He 		if (xstat == NULL)
123311e9eae4SChaoyong He 			return -EINVAL;
123411e9eae4SChaoyong He 
123511e9eae4SChaoyong He 		values[i] = nfp_net_xstats_value(dev, ids[i], false);
123611e9eae4SChaoyong He 	}
123711e9eae4SChaoyong He 
123811e9eae4SChaoyong He 	return read_size;
123911e9eae4SChaoyong He }
124011e9eae4SChaoyong He 
124111e9eae4SChaoyong He int
124211e9eae4SChaoyong He nfp_net_xstats_reset(struct rte_eth_dev *dev)
124311e9eae4SChaoyong He {
124411e9eae4SChaoyong He 	uint32_t id;
124511e9eae4SChaoyong He 	uint32_t read_size;
124611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
124782a2c286SChaoyong He 	struct rte_eth_xstat *xstats_base;
124882a2c286SChaoyong He 	struct nfp_flower_representor *repr;
124911e9eae4SChaoyong He 
125011e9eae4SChaoyong He 	read_size = nfp_net_xstats_size(dev);
125111e9eae4SChaoyong He 
125282a2c286SChaoyong He 	if (rte_eth_dev_is_repr(dev)) {
125382a2c286SChaoyong He 		repr = dev->data->dev_private;
125482a2c286SChaoyong He 		xstats_base = repr->repr_xstats_base;
125582a2c286SChaoyong He 	} else {
125682a2c286SChaoyong He 		hw = dev->data->dev_private;
125782a2c286SChaoyong He 		xstats_base = hw->eth_xstats_base;
125882a2c286SChaoyong He 	}
125982a2c286SChaoyong He 
126011e9eae4SChaoyong He 	for (id = 0; id < read_size; id++) {
126182a2c286SChaoyong He 		xstats_base[id].id = id;
126282a2c286SChaoyong He 		xstats_base[id].value = nfp_net_xstats_value(dev, id, true);
126311e9eae4SChaoyong He 	}
126411e9eae4SChaoyong He 
126511e9eae4SChaoyong He 	/* Successfully reset xstats, now call function to reset basic stats. */
126682a2c286SChaoyong He 	if (rte_eth_dev_is_repr(dev))
126782a2c286SChaoyong He 		return nfp_flower_repr_stats_reset(dev);
126882a2c286SChaoyong He 	else
126911e9eae4SChaoyong He 		return nfp_net_stats_reset(dev);
127011e9eae4SChaoyong He }
127111e9eae4SChaoyong He 
127211e9eae4SChaoyong He void
1273d81e2b51SChaoyong He nfp_net_rx_desc_limits(struct nfp_net_hw_priv *hw_priv,
127411e9eae4SChaoyong He 		uint16_t *min_rx_desc,
127511e9eae4SChaoyong He 		uint16_t *max_rx_desc)
127611e9eae4SChaoyong He {
1277d81e2b51SChaoyong He 	*max_rx_desc = hw_priv->dev_info->max_qc_size;
1278d81e2b51SChaoyong He 	*min_rx_desc = hw_priv->dev_info->min_qc_size;
127911e9eae4SChaoyong He }
128011e9eae4SChaoyong He 
128111e9eae4SChaoyong He void
1282000feb4cSChaoyong He nfp_net_tx_desc_limits(struct nfp_net_hw_priv *hw_priv,
128311e9eae4SChaoyong He 		uint16_t *min_tx_desc,
128411e9eae4SChaoyong He 		uint16_t *max_tx_desc)
128511e9eae4SChaoyong He {
128611e9eae4SChaoyong He 	uint16_t tx_dpp;
128711e9eae4SChaoyong He 
1288000feb4cSChaoyong He 	if (hw_priv->pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3)
128911e9eae4SChaoyong He 		tx_dpp = NFD3_TX_DESC_PER_PKT;
129011e9eae4SChaoyong He 	else
129111e9eae4SChaoyong He 		tx_dpp = NFDK_TX_DESC_PER_SIMPLE_PKT;
129211e9eae4SChaoyong He 
1293d81e2b51SChaoyong He 	*max_tx_desc = hw_priv->dev_info->max_qc_size / tx_dpp;
1294d81e2b51SChaoyong He 	*min_tx_desc = hw_priv->dev_info->min_qc_size / tx_dpp;
129511e9eae4SChaoyong He }
129611e9eae4SChaoyong He 
129711e9eae4SChaoyong He int
129811e9eae4SChaoyong He nfp_net_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *dev_info)
129911e9eae4SChaoyong He {
13004a9bb682SChaoyong He 	uint32_t cap;
130111e9eae4SChaoyong He 	uint32_t cap_extend;
130211e9eae4SChaoyong He 	uint16_t min_rx_desc;
130311e9eae4SChaoyong He 	uint16_t max_rx_desc;
130411e9eae4SChaoyong He 	uint16_t min_tx_desc;
130511e9eae4SChaoyong He 	uint16_t max_tx_desc;
130611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
1307ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
130811e9eae4SChaoyong He 
1309b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
1310ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
1311bcdf9151SChaoyong He 	if (hw_priv == NULL)
1312bcdf9151SChaoyong He 		return -EINVAL;
131311e9eae4SChaoyong He 
1314d81e2b51SChaoyong He 	nfp_net_rx_desc_limits(hw_priv, &min_rx_desc, &max_rx_desc);
1315000feb4cSChaoyong He 	nfp_net_tx_desc_limits(hw_priv, &min_tx_desc, &max_tx_desc);
131611e9eae4SChaoyong He 
131711e9eae4SChaoyong He 	dev_info->max_rx_queues = (uint16_t)hw->max_rx_queues;
131811e9eae4SChaoyong He 	dev_info->max_tx_queues = (uint16_t)hw->max_tx_queues;
131911e9eae4SChaoyong He 	dev_info->min_rx_bufsize = RTE_ETHER_MIN_MTU;
13202f1bfbf4SJames Hershaw 	/*
13212f1bfbf4SJames Hershaw 	 * The maximum rx packet length is set to the maximum layer 3 MTU,
13222f1bfbf4SJames Hershaw 	 * plus layer 2, CRC and VLAN headers.
132311e9eae4SChaoyong He 	 * The maximum layer 3 MTU (max_mtu) is read from hardware,
132411e9eae4SChaoyong He 	 * which was set by the firmware loaded onto the card.
132511e9eae4SChaoyong He 	 */
13262f1bfbf4SJames Hershaw 	dev_info->max_rx_pktlen = hw->max_mtu + NFP_ETH_OVERHEAD;
132711e9eae4SChaoyong He 	dev_info->max_mtu = hw->max_mtu;
132811e9eae4SChaoyong He 	dev_info->min_mtu = RTE_ETHER_MIN_MTU;
132911e9eae4SChaoyong He 	/* Next should change when PF support is implemented */
133011e9eae4SChaoyong He 	dev_info->max_mac_addrs = 1;
133111e9eae4SChaoyong He 
13324a9bb682SChaoyong He 	cap = hw->super.cap;
13334a9bb682SChaoyong He 
13344a9bb682SChaoyong He 	if ((cap & (NFP_NET_CFG_CTRL_RXVLAN | NFP_NET_CFG_CTRL_RXVLAN_V2)) != 0)
133511e9eae4SChaoyong He 		dev_info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP;
133611e9eae4SChaoyong He 
13374a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_RXQINQ) != 0)
133811e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_QINQ_STRIP;
133911e9eae4SChaoyong He 
13404a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_RXCSUM) != 0)
134111e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
134211e9eae4SChaoyong He 				RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
134311e9eae4SChaoyong He 				RTE_ETH_RX_OFFLOAD_TCP_CKSUM;
134411e9eae4SChaoyong He 
13454a9bb682SChaoyong He 	if ((cap & (NFP_NET_CFG_CTRL_TXVLAN | NFP_NET_CFG_CTRL_TXVLAN_V2)) != 0)
134611e9eae4SChaoyong He 		dev_info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT;
134711e9eae4SChaoyong He 
13484a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_TXCSUM) != 0)
134911e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
135011e9eae4SChaoyong He 				RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
135111e9eae4SChaoyong He 				RTE_ETH_TX_OFFLOAD_TCP_CKSUM;
135211e9eae4SChaoyong He 
13534a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_LSO_ANY) != 0) {
135411e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_TCP_TSO;
1355df77f704SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_USO) != 0)
1356df77f704SChaoyong He 			dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_UDP_TSO;
13574a9bb682SChaoyong He 		if ((cap & NFP_NET_CFG_CTRL_VXLAN) != 0)
135811e9eae4SChaoyong He 			dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_VXLAN_TNL_TSO;
135911e9eae4SChaoyong He 	}
136011e9eae4SChaoyong He 
13614a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_GATHER) != 0)
136211e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
136311e9eae4SChaoyong He 
136475a76c73SChaoyong He 	cap_extend = hw->super.cap_ext;
136511e9eae4SChaoyong He 	if ((cap_extend & NFP_NET_CFG_CTRL_IPSEC) != 0) {
136611e9eae4SChaoyong He 		dev_info->tx_offload_capa |= RTE_ETH_TX_OFFLOAD_SECURITY;
136711e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_SECURITY;
136811e9eae4SChaoyong He 	}
136911e9eae4SChaoyong He 
137011e9eae4SChaoyong He 	dev_info->default_rxconf = (struct rte_eth_rxconf) {
137111e9eae4SChaoyong He 		.rx_thresh = {
137211e9eae4SChaoyong He 			.pthresh = DEFAULT_RX_PTHRESH,
137311e9eae4SChaoyong He 			.hthresh = DEFAULT_RX_HTHRESH,
137411e9eae4SChaoyong He 			.wthresh = DEFAULT_RX_WTHRESH,
137511e9eae4SChaoyong He 		},
137611e9eae4SChaoyong He 		.rx_free_thresh = DEFAULT_RX_FREE_THRESH,
137711e9eae4SChaoyong He 		.rx_drop_en = 0,
137811e9eae4SChaoyong He 	};
137911e9eae4SChaoyong He 
138011e9eae4SChaoyong He 	dev_info->default_txconf = (struct rte_eth_txconf) {
138111e9eae4SChaoyong He 		.tx_thresh = {
138211e9eae4SChaoyong He 			.pthresh = DEFAULT_TX_PTHRESH,
138311e9eae4SChaoyong He 			.hthresh = DEFAULT_TX_HTHRESH,
138411e9eae4SChaoyong He 			.wthresh = DEFAULT_TX_WTHRESH,
138511e9eae4SChaoyong He 		},
138611e9eae4SChaoyong He 		.tx_free_thresh = DEFAULT_TX_FREE_THRESH,
138711e9eae4SChaoyong He 		.tx_rs_thresh = DEFAULT_TX_RSBIT_THRESH,
138811e9eae4SChaoyong He 	};
138911e9eae4SChaoyong He 
139011e9eae4SChaoyong He 	dev_info->rx_desc_lim = (struct rte_eth_desc_lim) {
139111e9eae4SChaoyong He 		.nb_max = max_rx_desc,
139211e9eae4SChaoyong He 		.nb_min = min_rx_desc,
139311e9eae4SChaoyong He 		.nb_align = NFP_ALIGN_RING_DESC,
139411e9eae4SChaoyong He 	};
139511e9eae4SChaoyong He 
139611e9eae4SChaoyong He 	dev_info->tx_desc_lim = (struct rte_eth_desc_lim) {
139711e9eae4SChaoyong He 		.nb_max = max_tx_desc,
139811e9eae4SChaoyong He 		.nb_min = min_tx_desc,
139911e9eae4SChaoyong He 		.nb_align = NFP_ALIGN_RING_DESC,
140011e9eae4SChaoyong He 		.nb_seg_max = NFP_TX_MAX_SEG,
140111e9eae4SChaoyong He 		.nb_mtu_seg_max = NFP_TX_MAX_MTU_SEG,
140211e9eae4SChaoyong He 	};
140311e9eae4SChaoyong He 
14044a9bb682SChaoyong He 	if ((cap & NFP_NET_CFG_CTRL_RSS_ANY) != 0) {
140511e9eae4SChaoyong He 		dev_info->rx_offload_capa |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
1406b458a2a0SLong Wu 		dev_info->flow_type_rss_offloads = NFP_NET_RSS_CAP;
140711e9eae4SChaoyong He 		dev_info->reta_size = NFP_NET_CFG_RSS_ITBL_SZ;
140811e9eae4SChaoyong He 		dev_info->hash_key_size = NFP_NET_CFG_RSS_KEY_SZ;
140911e9eae4SChaoyong He 	}
141011e9eae4SChaoyong He 
14113110ab73SZerun Fu 	/* Only PF supports getting speed capability. */
1412c2b4f0d5SChaoyong He 	if (hw_priv->is_pf)
1413ff9f5a56SChaoyong He 		dev_info->speed_capa = hw_priv->pf_dev->speed_capa;
141411e9eae4SChaoyong He 
141511e9eae4SChaoyong He 	return 0;
141611e9eae4SChaoyong He }
141711e9eae4SChaoyong He 
141811e9eae4SChaoyong He int
1419000feb4cSChaoyong He nfp_net_common_init(struct nfp_pf_dev *pf_dev,
142011e9eae4SChaoyong He 		struct nfp_net_hw *hw)
142111e9eae4SChaoyong He {
142211e9eae4SChaoyong He 	const int stride = 4;
1423000feb4cSChaoyong He 	struct rte_pci_device *pci_dev;
142411e9eae4SChaoyong He 
1425000feb4cSChaoyong He 	pci_dev = pf_dev->pci_dev;
142611e9eae4SChaoyong He 	hw->device_id = pci_dev->id.device_id;
142711e9eae4SChaoyong He 	hw->vendor_id = pci_dev->id.vendor_id;
142811e9eae4SChaoyong He 	hw->subsystem_device_id = pci_dev->id.subsystem_device_id;
142911e9eae4SChaoyong He 	hw->subsystem_vendor_id = pci_dev->id.subsystem_vendor_id;
143011e9eae4SChaoyong He 
1431f58bde00SChaoyong He 	hw->max_rx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_RXRINGS);
1432f58bde00SChaoyong He 	hw->max_tx_queues = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_TXRINGS);
143311e9eae4SChaoyong He 	if (hw->max_rx_queues == 0 || hw->max_tx_queues == 0) {
143411e9eae4SChaoyong He 		PMD_INIT_LOG(ERR, "Device %s can not be used, there are no valid queue "
1435b6de4353SZerun Fu 				"pairs for use.", pci_dev->name);
143611e9eae4SChaoyong He 		return -ENODEV;
143711e9eae4SChaoyong He 	}
143811e9eae4SChaoyong He 
1439000feb4cSChaoyong He 	if (nfp_net_check_dma_mask(pf_dev, pci_dev->name) != 0)
144011e9eae4SChaoyong He 		return -ENODEV;
144111e9eae4SChaoyong He 
144211e9eae4SChaoyong He 	/* Get some of the read-only fields from the config BAR */
1443f58bde00SChaoyong He 	hw->super.cap = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP);
1444f58bde00SChaoyong He 	hw->super.cap_ext = nn_cfg_readl(&hw->super, NFP_NET_CFG_CAP_WORD1);
1445f58bde00SChaoyong He 	hw->max_mtu = nn_cfg_readl(&hw->super, NFP_NET_CFG_MAX_MTU);
144611e9eae4SChaoyong He 	hw->flbufsz = DEFAULT_FLBUF_SIZE;
144711e9eae4SChaoyong He 
1448000feb4cSChaoyong He 	nfp_net_meta_init_format(hw, pf_dev);
144911e9eae4SChaoyong He 
145011e9eae4SChaoyong He 	/* Read the Rx offset configured from firmware */
1451000feb4cSChaoyong He 	if (pf_dev->ver.major < 2)
145211e9eae4SChaoyong He 		hw->rx_offset = NFP_NET_RX_OFFSET;
145311e9eae4SChaoyong He 	else
145465f6915dSChaoyong He 		hw->rx_offset = nn_cfg_readl(&hw->super, NFP_NET_CFG_RX_OFFSET);
145511e9eae4SChaoyong He 
1456b4b6988aSChaoyong He 	hw->super.ctrl = 0;
145711e9eae4SChaoyong He 	hw->stride_rx = stride;
145811e9eae4SChaoyong He 	hw->stride_tx = stride;
145911e9eae4SChaoyong He 
146011e9eae4SChaoyong He 	return 0;
146111e9eae4SChaoyong He }
146211e9eae4SChaoyong He 
146311e9eae4SChaoyong He const uint32_t *
1464ba6a168aSSivaramakrishnan Venkat nfp_net_supported_ptypes_get(struct rte_eth_dev *dev, size_t *no_of_elements)
146511e9eae4SChaoyong He {
146611e9eae4SChaoyong He 	struct nfp_net_hw *net_hw;
146711e9eae4SChaoyong He 	static const uint32_t ptypes[] = {
146811e9eae4SChaoyong He 		RTE_PTYPE_L2_ETHER,
146911e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4,
147011e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4_EXT,
147111e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6,
147211e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6_EXT,
147311e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV4_EXT_UNKNOWN,
147411e9eae4SChaoyong He 		RTE_PTYPE_L3_IPV6_EXT_UNKNOWN,
147511e9eae4SChaoyong He 		RTE_PTYPE_L4_TCP,
147611e9eae4SChaoyong He 		RTE_PTYPE_L4_UDP,
147711e9eae4SChaoyong He 		RTE_PTYPE_L4_FRAG,
147811e9eae4SChaoyong He 		RTE_PTYPE_L4_NONFRAG,
147911e9eae4SChaoyong He 		RTE_PTYPE_L4_ICMP,
148011e9eae4SChaoyong He 		RTE_PTYPE_L4_SCTP,
148111e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_VXLAN,
148211e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_NVGRE,
148311e9eae4SChaoyong He 		RTE_PTYPE_TUNNEL_GENEVE,
148411e9eae4SChaoyong He 		RTE_PTYPE_INNER_L2_ETHER,
148511e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4,
148611e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4_EXT,
148711e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6,
148811e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6_EXT,
148911e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV4_EXT_UNKNOWN,
149011e9eae4SChaoyong He 		RTE_PTYPE_INNER_L3_IPV6_EXT_UNKNOWN,
149111e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_TCP,
149211e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_UDP,
149311e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_FRAG,
149411e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_NONFRAG,
149511e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_ICMP,
149611e9eae4SChaoyong He 		RTE_PTYPE_INNER_L4_SCTP,
149711e9eae4SChaoyong He 	};
149811e9eae4SChaoyong He 
149962edcfd6SLong Wu 	if (dev->rx_pkt_burst == NULL)
150011e9eae4SChaoyong He 		return NULL;
150111e9eae4SChaoyong He 
15029d723baaSChaoyong He 	net_hw = dev->data->dev_private;
1503a498019dSLong Wu 	if ((net_hw->super.cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
150411e9eae4SChaoyong He 		return NULL;
150511e9eae4SChaoyong He 
1506ba6a168aSSivaramakrishnan Venkat 	*no_of_elements = RTE_DIM(ptypes);
150711e9eae4SChaoyong He 	return ptypes;
150811e9eae4SChaoyong He }
150911e9eae4SChaoyong He 
151011e9eae4SChaoyong He int
1511a498019dSLong Wu nfp_net_ptypes_set(struct rte_eth_dev *dev,
1512a498019dSLong Wu 		uint32_t ptype_mask)
1513a498019dSLong Wu {
1514a498019dSLong Wu 	int ret;
1515a498019dSLong Wu 	uint32_t update;
1516a498019dSLong Wu 	uint32_t ctrl_ext;
1517a498019dSLong Wu 	struct nfp_hw *hw;
1518a498019dSLong Wu 	struct nfp_net_hw *net_hw;
1519a498019dSLong Wu 
1520a498019dSLong Wu 	net_hw = dev->data->dev_private;
1521a498019dSLong Wu 	hw = &net_hw->super;
1522a498019dSLong Wu 
1523a498019dSLong Wu 	if ((hw->cap_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
1524a498019dSLong Wu 		return -ENOTSUP;
1525a498019dSLong Wu 
1526a498019dSLong Wu 	ctrl_ext = hw->ctrl_ext;
1527a498019dSLong Wu 	if (ptype_mask == 0) {
1528a498019dSLong Wu 		if ((ctrl_ext & NFP_NET_CFG_CTRL_PKT_TYPE) == 0)
1529a498019dSLong Wu 			return 0;
1530a498019dSLong Wu 
1531a498019dSLong Wu 		ctrl_ext &= ~NFP_NET_CFG_CTRL_PKT_TYPE;
1532a498019dSLong Wu 	} else {
1533a498019dSLong Wu 		if ((ctrl_ext & NFP_NET_CFG_CTRL_PKT_TYPE) != 0)
1534a498019dSLong Wu 			return 0;
1535a498019dSLong Wu 
1536a498019dSLong Wu 		ctrl_ext |= NFP_NET_CFG_CTRL_PKT_TYPE;
1537a498019dSLong Wu 	}
1538a498019dSLong Wu 
1539a498019dSLong Wu 	update = NFP_NET_CFG_UPDATE_GEN;
1540a498019dSLong Wu 
1541a498019dSLong Wu 	ret = nfp_ext_reconfig(hw, ctrl_ext, update);
1542a498019dSLong Wu 	if (ret != 0)
1543a498019dSLong Wu 		return ret;
1544a498019dSLong Wu 
1545a498019dSLong Wu 	hw->ctrl_ext = ctrl_ext;
1546a498019dSLong Wu 
1547a498019dSLong Wu 	return 0;
1548a498019dSLong Wu }
1549a498019dSLong Wu 
1550a498019dSLong Wu int
155111e9eae4SChaoyong He nfp_rx_queue_intr_enable(struct rte_eth_dev *dev,
155211e9eae4SChaoyong He 		uint16_t queue_id)
155311e9eae4SChaoyong He {
155411e9eae4SChaoyong He 	uint16_t base = 0;
155511e9eae4SChaoyong He 	struct nfp_net_hw *hw;
155611e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
155711e9eae4SChaoyong He 
155811e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
155911e9eae4SChaoyong He 	if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO)
156011e9eae4SChaoyong He 		base = 1;
156111e9eae4SChaoyong He 
156211e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
156311e9eae4SChaoyong He 	rte_wmb();
156411e9eae4SChaoyong He 
1565b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
1566f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id),
156711e9eae4SChaoyong He 			NFP_NET_CFG_ICR_UNMASKED);
156811e9eae4SChaoyong He 	return 0;
156911e9eae4SChaoyong He }
157011e9eae4SChaoyong He 
157111e9eae4SChaoyong He int
157211e9eae4SChaoyong He nfp_rx_queue_intr_disable(struct rte_eth_dev *dev,
157311e9eae4SChaoyong He 		uint16_t queue_id)
157411e9eae4SChaoyong He {
157511e9eae4SChaoyong He 	uint16_t base = 0;
157611e9eae4SChaoyong He 	struct nfp_net_hw *hw;
157711e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
157811e9eae4SChaoyong He 
157911e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
158011e9eae4SChaoyong He 	if (rte_intr_type_get(pci_dev->intr_handle) != RTE_INTR_HANDLE_UIO)
158111e9eae4SChaoyong He 		base = 1;
158211e9eae4SChaoyong He 
158311e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
158411e9eae4SChaoyong He 	rte_wmb();
158511e9eae4SChaoyong He 
1586b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
1587f58bde00SChaoyong He 	nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(base + queue_id), NFP_NET_CFG_ICR_RXTX);
158811e9eae4SChaoyong He 
158911e9eae4SChaoyong He 	return 0;
159011e9eae4SChaoyong He }
159111e9eae4SChaoyong He 
159211e9eae4SChaoyong He static void
159311e9eae4SChaoyong He nfp_net_dev_link_status_print(struct rte_eth_dev *dev)
159411e9eae4SChaoyong He {
159511e9eae4SChaoyong He 	struct rte_eth_link link;
159611e9eae4SChaoyong He 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
159711e9eae4SChaoyong He 
159811e9eae4SChaoyong He 	rte_eth_linkstatus_get(dev, &link);
159911e9eae4SChaoyong He 	if (link.link_status != 0)
1600b6de4353SZerun Fu 		PMD_DRV_LOG(INFO, "Port %d: Link Up - speed %u Mbps - %s.",
160111e9eae4SChaoyong He 				dev->data->port_id, link.link_speed,
160211e9eae4SChaoyong He 				link.link_duplex == RTE_ETH_LINK_FULL_DUPLEX ?
160311e9eae4SChaoyong He 				"full-duplex" : "half-duplex");
160411e9eae4SChaoyong He 	else
1605b6de4353SZerun Fu 		PMD_DRV_LOG(INFO, " Port %d: Link Down.", dev->data->port_id);
160611e9eae4SChaoyong He 
160711e9eae4SChaoyong He 	PMD_DRV_LOG(INFO, "PCI Address: " PCI_PRI_FMT,
160811e9eae4SChaoyong He 			pci_dev->addr.domain, pci_dev->addr.bus,
160911e9eae4SChaoyong He 			pci_dev->addr.devid, pci_dev->addr.function);
161011e9eae4SChaoyong He }
161111e9eae4SChaoyong He 
161211e9eae4SChaoyong He /*
161311e9eae4SChaoyong He  * Unmask an interrupt
161411e9eae4SChaoyong He  *
161511e9eae4SChaoyong He  * If MSI-X auto-masking is enabled clear the mask bit, otherwise
161611e9eae4SChaoyong He  * clear the ICR for the entry.
161711e9eae4SChaoyong He  */
161894d0631aSPeng Zhang void
161911e9eae4SChaoyong He nfp_net_irq_unmask(struct rte_eth_dev *dev)
162011e9eae4SChaoyong He {
162111e9eae4SChaoyong He 	struct nfp_net_hw *hw;
162211e9eae4SChaoyong He 	struct rte_pci_device *pci_dev;
162311e9eae4SChaoyong He 
1624b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
162511e9eae4SChaoyong He 	pci_dev = RTE_ETH_DEV_TO_PCI(dev);
162611e9eae4SChaoyong He 
162711e9eae4SChaoyong He 	/* Make sure all updates are written before un-masking */
162811e9eae4SChaoyong He 	rte_wmb();
162911e9eae4SChaoyong He 
1630b4b6988aSChaoyong He 	if ((hw->super.ctrl & NFP_NET_CFG_CTRL_MSIXAUTO) != 0) {
163111e9eae4SChaoyong He 		/* If MSI-X auto-masking is used, clear the entry */
163211e9eae4SChaoyong He 		rte_intr_ack(pci_dev->intr_handle);
163311e9eae4SChaoyong He 	} else {
1634f58bde00SChaoyong He 		nn_cfg_writeb(&hw->super, NFP_NET_CFG_ICR(NFP_NET_IRQ_LSC_IDX),
163511e9eae4SChaoyong He 				NFP_NET_CFG_ICR_UNMASKED);
163611e9eae4SChaoyong He 	}
163711e9eae4SChaoyong He }
163811e9eae4SChaoyong He 
163911e9eae4SChaoyong He /**
164011e9eae4SChaoyong He  * Interrupt handler which shall be registered for alarm callback for delayed
164111e9eae4SChaoyong He  * handling specific interrupt to wait for the stable nic state. As the NIC
164211e9eae4SChaoyong He  * interrupt state is not stable for nfp after link is just down, it needs
164311e9eae4SChaoyong He  * to wait 4 seconds to get the stable status.
164411e9eae4SChaoyong He  *
164511e9eae4SChaoyong He  * @param param
164611e9eae4SChaoyong He  *   The address of parameter (struct rte_eth_dev *)
164711e9eae4SChaoyong He  */
164811e9eae4SChaoyong He void
164911e9eae4SChaoyong He nfp_net_dev_interrupt_delayed_handler(void *param)
165011e9eae4SChaoyong He {
165111e9eae4SChaoyong He 	struct rte_eth_dev *dev = param;
165211e9eae4SChaoyong He 
165311e9eae4SChaoyong He 	nfp_net_link_update(dev, 0);
165411e9eae4SChaoyong He 	rte_eth_dev_callback_process(dev, RTE_ETH_EVENT_INTR_LSC, NULL);
165511e9eae4SChaoyong He 
165611e9eae4SChaoyong He 	nfp_net_dev_link_status_print(dev);
165711e9eae4SChaoyong He 
165811e9eae4SChaoyong He 	/* Unmasking */
165911e9eae4SChaoyong He 	nfp_net_irq_unmask(dev);
166011e9eae4SChaoyong He }
166111e9eae4SChaoyong He 
166211e9eae4SChaoyong He void
166311e9eae4SChaoyong He nfp_net_dev_interrupt_handler(void *param)
166411e9eae4SChaoyong He {
166511e9eae4SChaoyong He 	int64_t timeout;
166611e9eae4SChaoyong He 	struct rte_eth_link link;
166711e9eae4SChaoyong He 	struct rte_eth_dev *dev = param;
166811e9eae4SChaoyong He 
166911e9eae4SChaoyong He 	PMD_DRV_LOG(DEBUG, "We got a LSC interrupt!!!");
167011e9eae4SChaoyong He 
167111e9eae4SChaoyong He 	rte_eth_linkstatus_get(dev, &link);
167211e9eae4SChaoyong He 
167311e9eae4SChaoyong He 	nfp_net_link_update(dev, 0);
167411e9eae4SChaoyong He 
167511e9eae4SChaoyong He 	/* Likely to up */
167611e9eae4SChaoyong He 	if (link.link_status == 0) {
167711e9eae4SChaoyong He 		/* Handle it 1 sec later, wait it being stable */
167811e9eae4SChaoyong He 		timeout = NFP_NET_LINK_UP_CHECK_TIMEOUT;
167911e9eae4SChaoyong He 	} else {  /* Likely to down */
168011e9eae4SChaoyong He 		/* Handle it 4 sec later, wait it being stable */
168111e9eae4SChaoyong He 		timeout = NFP_NET_LINK_DOWN_CHECK_TIMEOUT;
168211e9eae4SChaoyong He 	}
168311e9eae4SChaoyong He 
168411e9eae4SChaoyong He 	if (rte_eal_alarm_set(timeout * 1000,
168511e9eae4SChaoyong He 			nfp_net_dev_interrupt_delayed_handler,
168611e9eae4SChaoyong He 			(void *)dev) != 0) {
1687b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "Error setting alarm.");
168811e9eae4SChaoyong He 		/* Unmasking */
168911e9eae4SChaoyong He 		nfp_net_irq_unmask(dev);
169011e9eae4SChaoyong He 	}
169111e9eae4SChaoyong He }
169211e9eae4SChaoyong He 
169311e9eae4SChaoyong He int
169411e9eae4SChaoyong He nfp_net_dev_mtu_set(struct rte_eth_dev *dev,
169511e9eae4SChaoyong He 		uint16_t mtu)
169611e9eae4SChaoyong He {
169711e9eae4SChaoyong He 	struct nfp_net_hw *hw;
169811e9eae4SChaoyong He 
1699b12d2b2eSChaoyong He 	hw = nfp_net_get_hw(dev);
170011e9eae4SChaoyong He 
170111e9eae4SChaoyong He 	/* MTU setting is forbidden if port is started */
170211e9eae4SChaoyong He 	if (dev->data->dev_started) {
1703b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Port %d must be stopped before configuration.",
170411e9eae4SChaoyong He 				dev->data->port_id);
170511e9eae4SChaoyong He 		return -EBUSY;
170611e9eae4SChaoyong He 	}
170711e9eae4SChaoyong He 
170811e9eae4SChaoyong He 	/* MTU larger than current mbufsize not supported */
170911e9eae4SChaoyong He 	if (mtu > hw->flbufsz) {
1710b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "MTU (%u) larger than current mbufsize (%u) not supported.",
171111e9eae4SChaoyong He 				mtu, hw->flbufsz);
171211e9eae4SChaoyong He 		return -ERANGE;
171311e9eae4SChaoyong He 	}
171411e9eae4SChaoyong He 
171511e9eae4SChaoyong He 	/* Writing to configuration space */
1716f58bde00SChaoyong He 	nn_cfg_writel(&hw->super, NFP_NET_CFG_MTU, mtu);
171711e9eae4SChaoyong He 
171811e9eae4SChaoyong He 	hw->mtu = mtu;
171911e9eae4SChaoyong He 
172011e9eae4SChaoyong He 	return 0;
172111e9eae4SChaoyong He }
172211e9eae4SChaoyong He 
172311e9eae4SChaoyong He int
172411e9eae4SChaoyong He nfp_net_vlan_offload_set(struct rte_eth_dev *dev,
172511e9eae4SChaoyong He 		int mask)
172611e9eae4SChaoyong He {
172711e9eae4SChaoyong He 	int ret;
172811e9eae4SChaoyong He 	uint32_t update;
172911e9eae4SChaoyong He 	uint32_t new_ctrl;
173072d1dea6SChaoyong He 	struct nfp_hw *hw;
173111e9eae4SChaoyong He 	uint64_t rx_offload;
173272d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
173311e9eae4SChaoyong He 	uint32_t rxvlan_ctrl = 0;
173411e9eae4SChaoyong He 
1735b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
173672d1dea6SChaoyong He 	hw = &net_hw->super;
173711e9eae4SChaoyong He 	rx_offload = dev->data->dev_conf.rxmode.offloads;
173872d1dea6SChaoyong He 	new_ctrl = hw->ctrl;
173911e9eae4SChaoyong He 
174011e9eae4SChaoyong He 	/* VLAN stripping setting */
174111e9eae4SChaoyong He 	if ((mask & RTE_ETH_VLAN_STRIP_MASK) != 0) {
174272d1dea6SChaoyong He 		nfp_net_enable_rxvlan_cap(net_hw, &rxvlan_ctrl);
174311e9eae4SChaoyong He 		if ((rx_offload & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) != 0)
174411e9eae4SChaoyong He 			new_ctrl |= rxvlan_ctrl;
174511e9eae4SChaoyong He 		else
174611e9eae4SChaoyong He 			new_ctrl &= ~rxvlan_ctrl;
174711e9eae4SChaoyong He 	}
174811e9eae4SChaoyong He 
174911e9eae4SChaoyong He 	/* QinQ stripping setting */
175011e9eae4SChaoyong He 	if ((mask & RTE_ETH_QINQ_STRIP_MASK) != 0) {
175111e9eae4SChaoyong He 		if ((rx_offload & RTE_ETH_RX_OFFLOAD_QINQ_STRIP) != 0)
175211e9eae4SChaoyong He 			new_ctrl |= NFP_NET_CFG_CTRL_RXQINQ;
175311e9eae4SChaoyong He 		else
175411e9eae4SChaoyong He 			new_ctrl &= ~NFP_NET_CFG_CTRL_RXQINQ;
175511e9eae4SChaoyong He 	}
175611e9eae4SChaoyong He 
175772d1dea6SChaoyong He 	if (new_ctrl == hw->ctrl)
175811e9eae4SChaoyong He 		return 0;
175911e9eae4SChaoyong He 
176011e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_GEN;
176111e9eae4SChaoyong He 
176272d1dea6SChaoyong He 	ret = nfp_reconfig(hw, new_ctrl, update);
176311e9eae4SChaoyong He 	if (ret != 0)
176411e9eae4SChaoyong He 		return ret;
176511e9eae4SChaoyong He 
176672d1dea6SChaoyong He 	hw->ctrl = new_ctrl;
176711e9eae4SChaoyong He 
176811e9eae4SChaoyong He 	return 0;
176911e9eae4SChaoyong He }
177011e9eae4SChaoyong He 
177111e9eae4SChaoyong He static int
177211e9eae4SChaoyong He nfp_net_rss_reta_write(struct rte_eth_dev *dev,
177311e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
177411e9eae4SChaoyong He 		uint16_t reta_size)
177511e9eae4SChaoyong He {
177611e9eae4SChaoyong He 	uint16_t i;
177711e9eae4SChaoyong He 	uint16_t j;
177811e9eae4SChaoyong He 	uint16_t idx;
177911e9eae4SChaoyong He 	uint8_t mask;
178011e9eae4SChaoyong He 	uint32_t reta;
178111e9eae4SChaoyong He 	uint16_t shift;
17824a9bb682SChaoyong He 	struct nfp_hw *hw;
17834a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
178411e9eae4SChaoyong He 
1785b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
17864a9bb682SChaoyong He 	hw = &net_hw->super;
178711e9eae4SChaoyong He 
178811e9eae4SChaoyong He 	if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) {
178911e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%hu)"
1790b6de4353SZerun Fu 				" does not match hardware can supported (%d).",
179111e9eae4SChaoyong He 				reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
179211e9eae4SChaoyong He 		return -EINVAL;
179311e9eae4SChaoyong He 	}
179411e9eae4SChaoyong He 
179511e9eae4SChaoyong He 	/*
179611e9eae4SChaoyong He 	 * Update Redirection Table. There are 128 8bit-entries which can be
179711e9eae4SChaoyong He 	 * manage as 32 32bit-entries.
179811e9eae4SChaoyong He 	 */
179911e9eae4SChaoyong He 	for (i = 0; i < reta_size; i += 4) {
180011e9eae4SChaoyong He 		/* Handling 4 RSS entries per loop */
180111e9eae4SChaoyong He 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
180211e9eae4SChaoyong He 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
180311e9eae4SChaoyong He 		mask = (uint8_t)((reta_conf[idx].mask >> shift) & 0xF);
180411e9eae4SChaoyong He 		if (mask == 0)
180511e9eae4SChaoyong He 			continue;
180611e9eae4SChaoyong He 
180711e9eae4SChaoyong He 		reta = 0;
180811e9eae4SChaoyong He 
180911e9eae4SChaoyong He 		/* If all 4 entries were set, don't need read RETA register */
181011e9eae4SChaoyong He 		if (mask != 0xF)
18114a9bb682SChaoyong He 			reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + i);
181211e9eae4SChaoyong He 
181311e9eae4SChaoyong He 		for (j = 0; j < 4; j++) {
181411e9eae4SChaoyong He 			if ((mask & (0x1 << j)) == 0)
181511e9eae4SChaoyong He 				continue;
181611e9eae4SChaoyong He 
181711e9eae4SChaoyong He 			/* Clearing the entry bits */
181811e9eae4SChaoyong He 			if (mask != 0xF)
181911e9eae4SChaoyong He 				reta &= ~(0xFF << (8 * j));
182011e9eae4SChaoyong He 
182111e9eae4SChaoyong He 			reta |= reta_conf[idx].reta[shift + j] << (8 * j);
182211e9eae4SChaoyong He 		}
182311e9eae4SChaoyong He 
18244a9bb682SChaoyong He 		nn_cfg_writel(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift, reta);
182511e9eae4SChaoyong He 	}
182611e9eae4SChaoyong He 
182711e9eae4SChaoyong He 	return 0;
182811e9eae4SChaoyong He }
182911e9eae4SChaoyong He 
183011e9eae4SChaoyong He /* Update Redirection Table(RETA) of Receive Side Scaling of Ethernet device */
183111e9eae4SChaoyong He int
183211e9eae4SChaoyong He nfp_net_reta_update(struct rte_eth_dev *dev,
183311e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
183411e9eae4SChaoyong He 		uint16_t reta_size)
183511e9eae4SChaoyong He {
183611e9eae4SChaoyong He 	int ret;
183711e9eae4SChaoyong He 	uint32_t update;
183872d1dea6SChaoyong He 	struct nfp_hw *hw;
183972d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
184011e9eae4SChaoyong He 
1841b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
184272d1dea6SChaoyong He 	hw = &net_hw->super;
184372d1dea6SChaoyong He 
184472d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
184511e9eae4SChaoyong He 		return -EINVAL;
184611e9eae4SChaoyong He 
184711e9eae4SChaoyong He 	ret = nfp_net_rss_reta_write(dev, reta_conf, reta_size);
184811e9eae4SChaoyong He 	if (ret != 0)
184911e9eae4SChaoyong He 		return ret;
185011e9eae4SChaoyong He 
185111e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_RSS;
185211e9eae4SChaoyong He 
185372d1dea6SChaoyong He 	if (nfp_reconfig(hw, hw->ctrl, update) != 0)
185411e9eae4SChaoyong He 		return -EIO;
185511e9eae4SChaoyong He 
185611e9eae4SChaoyong He 	return 0;
185711e9eae4SChaoyong He }
185811e9eae4SChaoyong He 
185911e9eae4SChaoyong He /* Query Redirection Table(RETA) of Receive Side Scaling of Ethernet device. */
186011e9eae4SChaoyong He int
186111e9eae4SChaoyong He nfp_net_reta_query(struct rte_eth_dev *dev,
186211e9eae4SChaoyong He 		struct rte_eth_rss_reta_entry64 *reta_conf,
186311e9eae4SChaoyong He 		uint16_t reta_size)
186411e9eae4SChaoyong He {
186511e9eae4SChaoyong He 	uint16_t i;
186611e9eae4SChaoyong He 	uint16_t j;
186711e9eae4SChaoyong He 	uint16_t idx;
186811e9eae4SChaoyong He 	uint8_t mask;
186911e9eae4SChaoyong He 	uint32_t reta;
187011e9eae4SChaoyong He 	uint16_t shift;
18714a9bb682SChaoyong He 	struct nfp_hw *hw;
18724a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
187311e9eae4SChaoyong He 
1874b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
18754a9bb682SChaoyong He 	hw = &net_hw->super;
18764a9bb682SChaoyong He 
18774a9bb682SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
187811e9eae4SChaoyong He 		return -EINVAL;
187911e9eae4SChaoyong He 
188011e9eae4SChaoyong He 	if (reta_size != NFP_NET_CFG_RSS_ITBL_SZ) {
188111e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The size of hash lookup table configured (%d)"
1882b6de4353SZerun Fu 				" does not match hardware can supported (%d).",
188311e9eae4SChaoyong He 				reta_size, NFP_NET_CFG_RSS_ITBL_SZ);
188411e9eae4SChaoyong He 		return -EINVAL;
188511e9eae4SChaoyong He 	}
188611e9eae4SChaoyong He 
188711e9eae4SChaoyong He 	/*
188811e9eae4SChaoyong He 	 * Reading Redirection Table. There are 128 8bit-entries which can be
188911e9eae4SChaoyong He 	 * manage as 32 32bit-entries.
189011e9eae4SChaoyong He 	 */
189111e9eae4SChaoyong He 	for (i = 0; i < reta_size; i += 4) {
189211e9eae4SChaoyong He 		/* Handling 4 RSS entries per loop */
189311e9eae4SChaoyong He 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
189411e9eae4SChaoyong He 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
189511e9eae4SChaoyong He 		mask = (reta_conf[idx].mask >> shift) & 0xF;
189611e9eae4SChaoyong He 
189711e9eae4SChaoyong He 		if (mask == 0)
189811e9eae4SChaoyong He 			continue;
189911e9eae4SChaoyong He 
19004a9bb682SChaoyong He 		reta = nn_cfg_readl(hw, NFP_NET_CFG_RSS_ITBL + (idx * 64) + shift);
190111e9eae4SChaoyong He 		for (j = 0; j < 4; j++) {
190211e9eae4SChaoyong He 			if ((mask & (0x1 << j)) == 0)
190311e9eae4SChaoyong He 				continue;
190411e9eae4SChaoyong He 
190511e9eae4SChaoyong He 			reta_conf[idx].reta[shift + j] =
190611e9eae4SChaoyong He 					(uint8_t)((reta >> (8 * j)) & 0xF);
190711e9eae4SChaoyong He 		}
190811e9eae4SChaoyong He 	}
190911e9eae4SChaoyong He 
191011e9eae4SChaoyong He 	return 0;
191111e9eae4SChaoyong He }
191211e9eae4SChaoyong He 
191311e9eae4SChaoyong He static int
191411e9eae4SChaoyong He nfp_net_rss_hash_write(struct rte_eth_dev *dev,
191511e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
191611e9eae4SChaoyong He {
191711e9eae4SChaoyong He 	uint8_t i;
191811e9eae4SChaoyong He 	uint8_t key;
191911e9eae4SChaoyong He 	uint64_t rss_hf;
19204a9bb682SChaoyong He 	struct nfp_hw *hw;
19214a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
192211e9eae4SChaoyong He 	uint32_t cfg_rss_ctrl = 0;
192311e9eae4SChaoyong He 
1924b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
19254a9bb682SChaoyong He 	hw = &net_hw->super;
192611e9eae4SChaoyong He 
192711e9eae4SChaoyong He 	/* Writing the key byte by byte */
192811e9eae4SChaoyong He 	for (i = 0; i < rss_conf->rss_key_len; i++) {
192911e9eae4SChaoyong He 		memcpy(&key, &rss_conf->rss_key[i], 1);
19304a9bb682SChaoyong He 		nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY + i, key);
193111e9eae4SChaoyong He 	}
193211e9eae4SChaoyong He 
193311e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
193411e9eae4SChaoyong He 
193511e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_IPV4) != 0)
193611e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4;
193711e9eae4SChaoyong He 
193811e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) != 0)
193911e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_TCP;
194011e9eae4SChaoyong He 
194111e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) != 0)
194211e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_UDP;
194311e9eae4SChaoyong He 
194411e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_SCTP) != 0)
194511e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV4_SCTP;
194611e9eae4SChaoyong He 
194711e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_IPV6) != 0)
194811e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6;
194911e9eae4SChaoyong He 
195011e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) != 0)
195111e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_TCP;
195211e9eae4SChaoyong He 
195311e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) != 0)
195411e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_UDP;
195511e9eae4SChaoyong He 
195611e9eae4SChaoyong He 	if ((rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_SCTP) != 0)
195711e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_IPV6_SCTP;
195811e9eae4SChaoyong He 
195911e9eae4SChaoyong He 	cfg_rss_ctrl |= NFP_NET_CFG_RSS_MASK;
1960b458a2a0SLong Wu 
1961b458a2a0SLong Wu 	if (rte_eth_dev_is_repr(dev))
1962b458a2a0SLong Wu 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_CRC32;
1963b458a2a0SLong Wu 	else
196411e9eae4SChaoyong He 		cfg_rss_ctrl |= NFP_NET_CFG_RSS_TOEPLITZ;
196511e9eae4SChaoyong He 
196611e9eae4SChaoyong He 	/* Configuring where to apply the RSS hash */
19674a9bb682SChaoyong He 	nn_cfg_writel(hw, NFP_NET_CFG_RSS_CTRL, cfg_rss_ctrl);
196811e9eae4SChaoyong He 
196911e9eae4SChaoyong He 	/* Writing the key size */
19704a9bb682SChaoyong He 	nn_cfg_writeb(hw, NFP_NET_CFG_RSS_KEY_SZ, rss_conf->rss_key_len);
197111e9eae4SChaoyong He 
197211e9eae4SChaoyong He 	return 0;
197311e9eae4SChaoyong He }
197411e9eae4SChaoyong He 
197511e9eae4SChaoyong He int
197611e9eae4SChaoyong He nfp_net_rss_hash_update(struct rte_eth_dev *dev,
197711e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
197811e9eae4SChaoyong He {
197911e9eae4SChaoyong He 	uint32_t update;
198011e9eae4SChaoyong He 	uint64_t rss_hf;
198172d1dea6SChaoyong He 	struct nfp_hw *hw;
198272d1dea6SChaoyong He 	struct nfp_net_hw *net_hw;
198311e9eae4SChaoyong He 
1984b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
198572d1dea6SChaoyong He 	hw = &net_hw->super;
198611e9eae4SChaoyong He 
198711e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
198811e9eae4SChaoyong He 
198911e9eae4SChaoyong He 	/* Checking if RSS is enabled */
199072d1dea6SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0) {
199111e9eae4SChaoyong He 		if (rss_hf != 0) {
1992b6de4353SZerun Fu 			PMD_DRV_LOG(ERR, "RSS unsupported.");
199311e9eae4SChaoyong He 			return -EINVAL;
199411e9eae4SChaoyong He 		}
199511e9eae4SChaoyong He 
199611e9eae4SChaoyong He 		return 0; /* Nothing to do */
199711e9eae4SChaoyong He 	}
199811e9eae4SChaoyong He 
199911e9eae4SChaoyong He 	if (rss_conf->rss_key_len > NFP_NET_CFG_RSS_KEY_SZ) {
2000b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "RSS hash key too long.");
200111e9eae4SChaoyong He 		return -EINVAL;
200211e9eae4SChaoyong He 	}
200311e9eae4SChaoyong He 
200411e9eae4SChaoyong He 	nfp_net_rss_hash_write(dev, rss_conf);
200511e9eae4SChaoyong He 
200611e9eae4SChaoyong He 	update = NFP_NET_CFG_UPDATE_RSS;
200711e9eae4SChaoyong He 
200872d1dea6SChaoyong He 	if (nfp_reconfig(hw, hw->ctrl, update) != 0)
200911e9eae4SChaoyong He 		return -EIO;
201011e9eae4SChaoyong He 
201111e9eae4SChaoyong He 	return 0;
201211e9eae4SChaoyong He }
201311e9eae4SChaoyong He 
201411e9eae4SChaoyong He int
201511e9eae4SChaoyong He nfp_net_rss_hash_conf_get(struct rte_eth_dev *dev,
201611e9eae4SChaoyong He 		struct rte_eth_rss_conf *rss_conf)
201711e9eae4SChaoyong He {
201811e9eae4SChaoyong He 	uint8_t i;
201911e9eae4SChaoyong He 	uint8_t key;
202011e9eae4SChaoyong He 	uint64_t rss_hf;
20214a9bb682SChaoyong He 	struct nfp_hw *hw;
202211e9eae4SChaoyong He 	uint32_t cfg_rss_ctrl;
20234a9bb682SChaoyong He 	struct nfp_net_hw *net_hw;
202411e9eae4SChaoyong He 
2025b12d2b2eSChaoyong He 	net_hw = nfp_net_get_hw(dev);
20264a9bb682SChaoyong He 	hw = &net_hw->super;
202711e9eae4SChaoyong He 
20284a9bb682SChaoyong He 	if ((hw->ctrl & NFP_NET_CFG_CTRL_RSS_ANY) == 0)
202911e9eae4SChaoyong He 		return -EINVAL;
203011e9eae4SChaoyong He 
203111e9eae4SChaoyong He 	rss_hf = rss_conf->rss_hf;
20324a9bb682SChaoyong He 	cfg_rss_ctrl = nn_cfg_readl(hw, NFP_NET_CFG_RSS_CTRL);
203311e9eae4SChaoyong He 
203411e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4) != 0)
203511e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_IPV4;
203611e9eae4SChaoyong He 
203711e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_TCP) != 0)
203811e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_TCP;
203911e9eae4SChaoyong He 
204011e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_TCP) != 0)
204111e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_TCP;
204211e9eae4SChaoyong He 
204311e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_UDP) != 0)
204411e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_UDP;
204511e9eae4SChaoyong He 
204611e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_UDP) != 0)
204711e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_UDP;
204811e9eae4SChaoyong He 
204911e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6) != 0)
205011e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_IPV6;
205111e9eae4SChaoyong He 
205211e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV4_SCTP) != 0)
205311e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV4_SCTP;
205411e9eae4SChaoyong He 
205511e9eae4SChaoyong He 	if ((cfg_rss_ctrl & NFP_NET_CFG_RSS_IPV6_SCTP) != 0)
205611e9eae4SChaoyong He 		rss_hf |= RTE_ETH_RSS_NONFRAG_IPV6_SCTP;
205711e9eae4SChaoyong He 
205811e9eae4SChaoyong He 	/* Propagate current RSS hash functions to caller */
205911e9eae4SChaoyong He 	rss_conf->rss_hf = rss_hf;
206011e9eae4SChaoyong He 
206111e9eae4SChaoyong He 	/* Reading the key size */
20624a9bb682SChaoyong He 	rss_conf->rss_key_len = nn_cfg_readl(hw, NFP_NET_CFG_RSS_KEY_SZ);
206311e9eae4SChaoyong He 
206411e9eae4SChaoyong He 	/* Reading the key byte a byte */
206511e9eae4SChaoyong He 	for (i = 0; i < rss_conf->rss_key_len; i++) {
20664a9bb682SChaoyong He 		key = nn_cfg_readb(hw, NFP_NET_CFG_RSS_KEY + i);
206711e9eae4SChaoyong He 		memcpy(&rss_conf->rss_key[i], &key, 1);
206811e9eae4SChaoyong He 	}
206911e9eae4SChaoyong He 
207011e9eae4SChaoyong He 	return 0;
207111e9eae4SChaoyong He }
207211e9eae4SChaoyong He 
207311e9eae4SChaoyong He int
207411e9eae4SChaoyong He nfp_net_rss_config_default(struct rte_eth_dev *dev)
207511e9eae4SChaoyong He {
207611e9eae4SChaoyong He 	int ret;
207711e9eae4SChaoyong He 	uint8_t i;
207811e9eae4SChaoyong He 	uint8_t j;
207911e9eae4SChaoyong He 	uint16_t queue = 0;
208011e9eae4SChaoyong He 	struct rte_eth_conf *dev_conf;
208111e9eae4SChaoyong He 	struct rte_eth_rss_conf rss_conf;
208211e9eae4SChaoyong He 	uint16_t rx_queues = dev->data->nb_rx_queues;
208311e9eae4SChaoyong He 	struct rte_eth_rss_reta_entry64 nfp_reta_conf[2];
208411e9eae4SChaoyong He 
208511e9eae4SChaoyong He 	nfp_reta_conf[0].mask = ~0x0;
208611e9eae4SChaoyong He 	nfp_reta_conf[1].mask = ~0x0;
208711e9eae4SChaoyong He 
208811e9eae4SChaoyong He 	for (i = 0; i < 0x40; i += 8) {
208911e9eae4SChaoyong He 		for (j = i; j < (i + 8); j++) {
209011e9eae4SChaoyong He 			nfp_reta_conf[0].reta[j] = queue;
209111e9eae4SChaoyong He 			nfp_reta_conf[1].reta[j] = queue++;
209211e9eae4SChaoyong He 			queue %= rx_queues;
209311e9eae4SChaoyong He 		}
209411e9eae4SChaoyong He 	}
209511e9eae4SChaoyong He 
209611e9eae4SChaoyong He 	ret = nfp_net_rss_reta_write(dev, nfp_reta_conf, 0x80);
209711e9eae4SChaoyong He 	if (ret != 0)
209811e9eae4SChaoyong He 		return ret;
209911e9eae4SChaoyong He 
210011e9eae4SChaoyong He 	dev_conf = &dev->data->dev_conf;
210111e9eae4SChaoyong He 	if (dev_conf == NULL) {
2102b6de4353SZerun Fu 		PMD_DRV_LOG(ERR, "Wrong rss conf.");
210311e9eae4SChaoyong He 		return -EINVAL;
210411e9eae4SChaoyong He 	}
210511e9eae4SChaoyong He 
210611e9eae4SChaoyong He 	rss_conf = dev_conf->rx_adv_conf.rss_conf;
210711e9eae4SChaoyong He 	ret = nfp_net_rss_hash_write(dev, &rss_conf);
210811e9eae4SChaoyong He 
210911e9eae4SChaoyong He 	return ret;
211011e9eae4SChaoyong He }
211111e9eae4SChaoyong He 
211211e9eae4SChaoyong He void
211311e9eae4SChaoyong He nfp_net_stop_rx_queue(struct rte_eth_dev *dev)
211411e9eae4SChaoyong He {
211511e9eae4SChaoyong He 	uint16_t i;
211611e9eae4SChaoyong He 	struct nfp_net_rxq *this_rx_q;
211711e9eae4SChaoyong He 
211811e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
211911e9eae4SChaoyong He 		this_rx_q = dev->data->rx_queues[i];
212011e9eae4SChaoyong He 		nfp_net_reset_rx_queue(this_rx_q);
212111e9eae4SChaoyong He 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
212211e9eae4SChaoyong He 	}
212311e9eae4SChaoyong He }
212411e9eae4SChaoyong He 
212511e9eae4SChaoyong He void
212611e9eae4SChaoyong He nfp_net_close_rx_queue(struct rte_eth_dev *dev)
212711e9eae4SChaoyong He {
212811e9eae4SChaoyong He 	uint16_t i;
212911e9eae4SChaoyong He 	struct nfp_net_rxq *this_rx_q;
213011e9eae4SChaoyong He 
213111e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_rx_queues; i++) {
213211e9eae4SChaoyong He 		this_rx_q = dev->data->rx_queues[i];
213311e9eae4SChaoyong He 		nfp_net_reset_rx_queue(this_rx_q);
213411e9eae4SChaoyong He 		nfp_net_rx_queue_release(dev, i);
213511e9eae4SChaoyong He 	}
213611e9eae4SChaoyong He }
213711e9eae4SChaoyong He 
213811e9eae4SChaoyong He void
213911e9eae4SChaoyong He nfp_net_stop_tx_queue(struct rte_eth_dev *dev)
214011e9eae4SChaoyong He {
214111e9eae4SChaoyong He 	uint16_t i;
214211e9eae4SChaoyong He 	struct nfp_net_txq *this_tx_q;
214311e9eae4SChaoyong He 
214411e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
214511e9eae4SChaoyong He 		this_tx_q = dev->data->tx_queues[i];
214611e9eae4SChaoyong He 		nfp_net_reset_tx_queue(this_tx_q);
214711e9eae4SChaoyong He 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
214811e9eae4SChaoyong He 	}
214911e9eae4SChaoyong He }
215011e9eae4SChaoyong He 
215111e9eae4SChaoyong He void
215211e9eae4SChaoyong He nfp_net_close_tx_queue(struct rte_eth_dev *dev)
215311e9eae4SChaoyong He {
215411e9eae4SChaoyong He 	uint16_t i;
215511e9eae4SChaoyong He 	struct nfp_net_txq *this_tx_q;
215611e9eae4SChaoyong He 
215711e9eae4SChaoyong He 	for (i = 0; i < dev->data->nb_tx_queues; i++) {
215811e9eae4SChaoyong He 		this_tx_q = dev->data->tx_queues[i];
215911e9eae4SChaoyong He 		nfp_net_reset_tx_queue(this_tx_q);
216011e9eae4SChaoyong He 		nfp_net_tx_queue_release(dev, i);
216111e9eae4SChaoyong He 	}
216211e9eae4SChaoyong He }
216311e9eae4SChaoyong He 
216411e9eae4SChaoyong He int
216572d1dea6SChaoyong He nfp_net_set_vxlan_port(struct nfp_net_hw *net_hw,
216611e9eae4SChaoyong He 		size_t idx,
21675b81c1e2SLong Wu 		uint16_t port,
21685b81c1e2SLong Wu 		uint32_t ctrl)
216911e9eae4SChaoyong He {
217011e9eae4SChaoyong He 	uint32_t i;
217172d1dea6SChaoyong He 	struct nfp_hw *hw = &net_hw->super;
217211e9eae4SChaoyong He 
217311e9eae4SChaoyong He 	if (idx >= NFP_NET_N_VXLAN_PORTS) {
217411e9eae4SChaoyong He 		PMD_DRV_LOG(ERR, "The idx value is out of range.");
217511e9eae4SChaoyong He 		return -ERANGE;
217611e9eae4SChaoyong He 	}
217711e9eae4SChaoyong He 
217872d1dea6SChaoyong He 	net_hw->vxlan_ports[idx] = port;
217911e9eae4SChaoyong He 
218011e9eae4SChaoyong He 	for (i = 0; i < NFP_NET_N_VXLAN_PORTS; i += 2) {
218172d1dea6SChaoyong He 		nn_cfg_writel(hw, NFP_NET_CFG_VXLAN_PORT + i * sizeof(port),
218272d1dea6SChaoyong He 				(net_hw->vxlan_ports[i + 1] << 16) | net_hw->vxlan_ports[i]);
218311e9eae4SChaoyong He 	}
218411e9eae4SChaoyong He 
21855b81c1e2SLong Wu 	return nfp_reconfig(hw, ctrl, NFP_NET_CFG_UPDATE_VXLAN);
218611e9eae4SChaoyong He }
218711e9eae4SChaoyong He 
218811e9eae4SChaoyong He /*
218911e9eae4SChaoyong He  * The firmware with NFD3 can not handle DMA address requiring more
219011e9eae4SChaoyong He  * than 40 bits.
219111e9eae4SChaoyong He  */
219211e9eae4SChaoyong He int
2193000feb4cSChaoyong He nfp_net_check_dma_mask(struct nfp_pf_dev *pf_dev,
219411e9eae4SChaoyong He 		char *name)
219511e9eae4SChaoyong He {
2196000feb4cSChaoyong He 	if (pf_dev->ver.extend == NFP_NET_CFG_VERSION_DP_NFD3 &&
219711e9eae4SChaoyong He 			rte_mem_check_dma_mask(40) != 0) {
2198fb86136dSZerun Fu 		PMD_DRV_LOG(ERR, "Device %s can not be used: restricted dma mask to 40 bits!",
219911e9eae4SChaoyong He 				name);
220011e9eae4SChaoyong He 		return -ENODEV;
220111e9eae4SChaoyong He 	}
220211e9eae4SChaoyong He 
220311e9eae4SChaoyong He 	return 0;
220411e9eae4SChaoyong He }
220511e9eae4SChaoyong He 
2206ff9da649SLong Wu int
2207ff9da649SLong Wu nfp_net_txrwb_alloc(struct rte_eth_dev *eth_dev)
2208ff9da649SLong Wu {
2209ff9da649SLong Wu 	struct nfp_net_hw *net_hw;
2210ff9da649SLong Wu 	char mz_name[RTE_MEMZONE_NAMESIZE];
2211ff9da649SLong Wu 
2212ff9da649SLong Wu 	net_hw = nfp_net_get_hw(eth_dev);
2213ff9da649SLong Wu 	snprintf(mz_name, sizeof(mz_name), "%s_TXRWB", eth_dev->data->name);
2214ff9da649SLong Wu 	net_hw->txrwb_mz = rte_memzone_reserve_aligned(mz_name,
2215ff9da649SLong Wu 			net_hw->max_tx_queues * sizeof(uint64_t),
2216ff9da649SLong Wu 			rte_socket_id(),
2217ff9da649SLong Wu 			RTE_MEMZONE_IOVA_CONTIG, RTE_CACHE_LINE_SIZE);
2218ff9da649SLong Wu 	if (net_hw->txrwb_mz == NULL) {
2219b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "Failed to alloc %s for TX ring write back.",
2220ff9da649SLong Wu 				mz_name);
2221ff9da649SLong Wu 		return -ENOMEM;
2222ff9da649SLong Wu 	}
2223ff9da649SLong Wu 
2224ff9da649SLong Wu 	return 0;
2225ff9da649SLong Wu }
2226ff9da649SLong Wu 
2227ff9da649SLong Wu void
2228ff9da649SLong Wu nfp_net_txrwb_free(struct rte_eth_dev *eth_dev)
2229ff9da649SLong Wu {
2230ff9da649SLong Wu 	struct nfp_net_hw *net_hw;
2231ff9da649SLong Wu 
2232ff9da649SLong Wu 	net_hw = nfp_net_get_hw(eth_dev);
2233ff9da649SLong Wu 	if (net_hw->txrwb_mz == NULL)
2234ff9da649SLong Wu 		return;
2235ff9da649SLong Wu 
2236ff9da649SLong Wu 	rte_memzone_free(net_hw->txrwb_mz);
2237ff9da649SLong Wu 	net_hw->txrwb_mz = NULL;
2238ff9da649SLong Wu }
2239ff9da649SLong Wu 
2240000feb4cSChaoyong He static void
2241000feb4cSChaoyong He nfp_net_cfg_read_version(struct nfp_hw *hw,
2242000feb4cSChaoyong He 		struct nfp_pf_dev *pf_dev)
224311e9eae4SChaoyong He {
224411e9eae4SChaoyong He 	union {
224511e9eae4SChaoyong He 		uint32_t whole;
224611e9eae4SChaoyong He 		struct nfp_net_fw_ver split;
224711e9eae4SChaoyong He 	} version;
224811e9eae4SChaoyong He 
2249000feb4cSChaoyong He 	version.whole = nn_cfg_readl(hw, NFP_NET_CFG_VERSION);
2250000feb4cSChaoyong He 	pf_dev->ver = version.split;
2251000feb4cSChaoyong He }
2252000feb4cSChaoyong He 
2253000feb4cSChaoyong He bool
2254000feb4cSChaoyong He nfp_net_version_check(struct nfp_hw *hw,
2255000feb4cSChaoyong He 		struct nfp_pf_dev *pf_dev)
2256000feb4cSChaoyong He {
2257000feb4cSChaoyong He 	nfp_net_cfg_read_version(hw, pf_dev);
2258000feb4cSChaoyong He 	if (!nfp_net_is_valid_nfd_version(pf_dev->ver))
2259000feb4cSChaoyong He 		return false;
2260000feb4cSChaoyong He 
226119bd7cceSChaoyong He 	if (!nfp_net_is_valid_version_class(pf_dev->ver))
226219bd7cceSChaoyong He 		return false;
226319bd7cceSChaoyong He 
2264000feb4cSChaoyong He 	return true;
226511e9eae4SChaoyong He }
226611e9eae4SChaoyong He 
226711e9eae4SChaoyong He static void
2268b3c21344SChaoyong He nfp_net_get_nsp_info(struct nfp_net_hw_priv *hw_priv,
226911e9eae4SChaoyong He 		char *nsp_version)
227011e9eae4SChaoyong He {
227111e9eae4SChaoyong He 	struct nfp_nsp *nsp;
227211e9eae4SChaoyong He 
2273b3c21344SChaoyong He 	nsp = nfp_nsp_open(hw_priv->pf_dev->cpp);
227411e9eae4SChaoyong He 	if (nsp == NULL)
227511e9eae4SChaoyong He 		return;
227611e9eae4SChaoyong He 
227711e9eae4SChaoyong He 	snprintf(nsp_version, FW_VER_LEN, "%hu.%hu",
227811e9eae4SChaoyong He 			nfp_nsp_get_abi_ver_major(nsp),
227911e9eae4SChaoyong He 			nfp_nsp_get_abi_ver_minor(nsp));
228011e9eae4SChaoyong He 
228111e9eae4SChaoyong He 	nfp_nsp_close(nsp);
228211e9eae4SChaoyong He }
228311e9eae4SChaoyong He 
2284a2bc299dSPeng Zhang void
2285b3c21344SChaoyong He nfp_net_get_fw_version(struct nfp_cpp *cpp,
2286a2bc299dSPeng Zhang 		uint32_t *mip_version)
2287a2bc299dSPeng Zhang {
2288a2bc299dSPeng Zhang 	struct nfp_mip *mip;
2289a2bc299dSPeng Zhang 
2290b3c21344SChaoyong He 	mip = nfp_mip_open(cpp);
2291a2bc299dSPeng Zhang 	if (mip == NULL) {
2292a2bc299dSPeng Zhang 		*mip_version = 0;
2293a2bc299dSPeng Zhang 		return;
2294a2bc299dSPeng Zhang 	}
2295a2bc299dSPeng Zhang 
2296a2bc299dSPeng Zhang 	*mip_version = nfp_mip_fw_version(mip);
2297a2bc299dSPeng Zhang 
2298a2bc299dSPeng Zhang 	nfp_mip_close(mip);
2299a2bc299dSPeng Zhang }
2300a2bc299dSPeng Zhang 
230111e9eae4SChaoyong He static void
2302b3c21344SChaoyong He nfp_net_get_mip_name(struct nfp_net_hw_priv *hw_priv,
230311e9eae4SChaoyong He 		char *mip_name)
230411e9eae4SChaoyong He {
230511e9eae4SChaoyong He 	struct nfp_mip *mip;
230611e9eae4SChaoyong He 
2307b3c21344SChaoyong He 	mip = nfp_mip_open(hw_priv->pf_dev->cpp);
230811e9eae4SChaoyong He 	if (mip == NULL)
230911e9eae4SChaoyong He 		return;
231011e9eae4SChaoyong He 
2311cda9123eSChaoyong He 	strlcpy(mip_name, nfp_mip_name(mip), FW_VER_LEN);
231211e9eae4SChaoyong He 
231311e9eae4SChaoyong He 	nfp_mip_close(mip);
231411e9eae4SChaoyong He }
231511e9eae4SChaoyong He 
231611e9eae4SChaoyong He static void
2317ff9f5a56SChaoyong He nfp_net_get_app_name(struct nfp_net_hw_priv *hw_priv,
231811e9eae4SChaoyong He 		char *app_name)
231911e9eae4SChaoyong He {
2320ff9f5a56SChaoyong He 	switch (hw_priv->pf_dev->app_fw_id) {
232111e9eae4SChaoyong He 	case NFP_APP_FW_CORE_NIC:
2322cda9123eSChaoyong He 		strlcpy(app_name, "nic", FW_VER_LEN);
232311e9eae4SChaoyong He 		break;
232411e9eae4SChaoyong He 	case NFP_APP_FW_FLOWER_NIC:
2325cda9123eSChaoyong He 		strlcpy(app_name, "flower", FW_VER_LEN);
232611e9eae4SChaoyong He 		break;
232711e9eae4SChaoyong He 	default:
2328cda9123eSChaoyong He 		strlcpy(app_name, "unknown", FW_VER_LEN);
232911e9eae4SChaoyong He 		break;
233011e9eae4SChaoyong He 	}
233111e9eae4SChaoyong He }
233211e9eae4SChaoyong He 
233311e9eae4SChaoyong He int
233411e9eae4SChaoyong He nfp_net_firmware_version_get(struct rte_eth_dev *dev,
233511e9eae4SChaoyong He 		char *fw_version,
233611e9eae4SChaoyong He 		size_t fw_size)
233711e9eae4SChaoyong He {
233811e9eae4SChaoyong He 	struct nfp_net_hw *hw;
2339000feb4cSChaoyong He 	struct nfp_pf_dev *pf_dev;
2340ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
2341b7adbb2eSZerun Fu 	char app_name[FW_VER_LEN] = {0};
2342b7adbb2eSZerun Fu 	char mip_name[FW_VER_LEN] = {0};
2343b7adbb2eSZerun Fu 	char nsp_version[FW_VER_LEN] = {0};
2344b7adbb2eSZerun Fu 	char vnic_version[FW_VER_LEN] = {0};
234511e9eae4SChaoyong He 
234611e9eae4SChaoyong He 	if (fw_size < FW_VER_LEN)
234711e9eae4SChaoyong He 		return FW_VER_LEN;
234811e9eae4SChaoyong He 
2349c4de52ecSChaoyong He 	hw = nfp_net_get_hw(dev);
2350ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
2351000feb4cSChaoyong He 	pf_dev = hw_priv->pf_dev;
235211e9eae4SChaoyong He 
2353b7adbb2eSZerun Fu 	if (hw->fw_version[0] != 0) {
2354b7adbb2eSZerun Fu 		snprintf(fw_version, FW_VER_LEN, "%s", hw->fw_version);
2355b7adbb2eSZerun Fu 		return 0;
2356b7adbb2eSZerun Fu 	}
2357b7adbb2eSZerun Fu 
2358e72d6053SQin Ke 	if (!rte_eth_dev_is_repr(dev)) {
235911e9eae4SChaoyong He 		snprintf(vnic_version, FW_VER_LEN, "%d.%d.%d.%d",
2360000feb4cSChaoyong He 			pf_dev->ver.extend, pf_dev->ver.class,
2361000feb4cSChaoyong He 			pf_dev->ver.major, pf_dev->ver.minor);
2362c4de52ecSChaoyong He 	} else {
2363c4de52ecSChaoyong He 		snprintf(vnic_version, FW_VER_LEN, "*");
2364c4de52ecSChaoyong He 	}
236511e9eae4SChaoyong He 
2366b3c21344SChaoyong He 	nfp_net_get_nsp_info(hw_priv, nsp_version);
2367b3c21344SChaoyong He 	nfp_net_get_mip_name(hw_priv, mip_name);
2368ff9f5a56SChaoyong He 	nfp_net_get_app_name(hw_priv, app_name);
236911e9eae4SChaoyong He 
2370b7adbb2eSZerun Fu 	if (nsp_version[0] == 0 || mip_name[0] == 0) {
237111e9eae4SChaoyong He 		snprintf(fw_version, FW_VER_LEN, "%s %s %s %s",
237211e9eae4SChaoyong He 			vnic_version, nsp_version, mip_name, app_name);
2373b7adbb2eSZerun Fu 		return 0;
2374b7adbb2eSZerun Fu 	}
2375b7adbb2eSZerun Fu 
2376b7adbb2eSZerun Fu 	snprintf(hw->fw_version, FW_VER_LEN, "%s %s %s %s",
2377b7adbb2eSZerun Fu 			vnic_version, nsp_version, mip_name, app_name);
2378b7adbb2eSZerun Fu 
2379b7adbb2eSZerun Fu 	snprintf(fw_version, FW_VER_LEN, "%s", hw->fw_version);
238011e9eae4SChaoyong He 
238111e9eae4SChaoyong He 	return 0;
238211e9eae4SChaoyong He }
238311e9eae4SChaoyong He 
238411e9eae4SChaoyong He bool
238511e9eae4SChaoyong He nfp_net_is_valid_nfd_version(struct nfp_net_fw_ver version)
238611e9eae4SChaoyong He {
238711e9eae4SChaoyong He 	uint8_t nfd_version = version.extend;
238811e9eae4SChaoyong He 
238911e9eae4SChaoyong He 	if (nfd_version == NFP_NET_CFG_VERSION_DP_NFD3)
239011e9eae4SChaoyong He 		return true;
239111e9eae4SChaoyong He 
239211e9eae4SChaoyong He 	if (nfd_version == NFP_NET_CFG_VERSION_DP_NFDK) {
239311e9eae4SChaoyong He 		if (version.major < 5) {
2394b6de4353SZerun Fu 			PMD_INIT_LOG(ERR, "NFDK must use ABI 5 or newer, found: %d.",
239511e9eae4SChaoyong He 					version.major);
239611e9eae4SChaoyong He 			return false;
239711e9eae4SChaoyong He 		}
239811e9eae4SChaoyong He 
239911e9eae4SChaoyong He 		return true;
240011e9eae4SChaoyong He 	}
240111e9eae4SChaoyong He 
240211e9eae4SChaoyong He 	return false;
240311e9eae4SChaoyong He }
2404c4de52ecSChaoyong He 
240519bd7cceSChaoyong He bool
240619bd7cceSChaoyong He nfp_net_is_valid_version_class(struct nfp_net_fw_ver version)
240719bd7cceSChaoyong He {
240819bd7cceSChaoyong He 	switch (version.class) {
240919bd7cceSChaoyong He 	case NFP_NET_CFG_VERSION_CLASS_GENERIC:
241019bd7cceSChaoyong He 		return true;
241119bd7cceSChaoyong He 	case NFP_NET_CFG_VERSION_CLASS_NO_EMEM:
241219bd7cceSChaoyong He 		return true;
241319bd7cceSChaoyong He 	default:
241419bd7cceSChaoyong He 		return false;
241519bd7cceSChaoyong He 	}
241619bd7cceSChaoyong He }
241719bd7cceSChaoyong He 
241819bd7cceSChaoyong He void
241919bd7cceSChaoyong He nfp_net_ctrl_bar_size_set(struct nfp_pf_dev *pf_dev)
242019bd7cceSChaoyong He {
242119bd7cceSChaoyong He 	if (pf_dev->ver.class == NFP_NET_CFG_VERSION_CLASS_GENERIC)
242219bd7cceSChaoyong He 		pf_dev->ctrl_bar_size = NFP_NET_CFG_BAR_SZ_32K;
242319bd7cceSChaoyong He 	else
242419bd7cceSChaoyong He 		pf_dev->ctrl_bar_size = NFP_NET_CFG_BAR_SZ_8K;
242519bd7cceSChaoyong He }
242619bd7cceSChaoyong He 
2427c4de52ecSChaoyong He /* Disable rx and tx functions to allow for reconfiguring. */
2428c4de52ecSChaoyong He int
2429c4de52ecSChaoyong He nfp_net_stop(struct rte_eth_dev *dev)
2430c4de52ecSChaoyong He {
24311580387eSChaoyong He 	int ret;
2432c4de52ecSChaoyong He 	struct nfp_net_hw *hw;
2433ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
2434c4de52ecSChaoyong He 
2435c4de52ecSChaoyong He 	hw = nfp_net_get_hw(dev);
2436ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
2437c4de52ecSChaoyong He 
2438c4de52ecSChaoyong He 	nfp_net_disable_queues(dev);
2439c4de52ecSChaoyong He 
2440c4de52ecSChaoyong He 	/* Clear queues */
2441c4de52ecSChaoyong He 	nfp_net_stop_tx_queue(dev);
2442c4de52ecSChaoyong He 	nfp_net_stop_rx_queue(dev);
2443c4de52ecSChaoyong He 
24441580387eSChaoyong He 	ret = nfp_eth_set_configured(hw_priv->pf_dev->cpp, hw->nfp_idx, 0);
24451580387eSChaoyong He 	if (ret < 0)
24461580387eSChaoyong He 		return ret;
2447c4de52ecSChaoyong He 
2448c4de52ecSChaoyong He 	return 0;
2449c4de52ecSChaoyong He }
245051d15e82SZerun Fu 
245151d15e82SZerun Fu static enum rte_eth_fc_mode
245251d15e82SZerun Fu nfp_net_get_pause_mode(struct nfp_eth_table_port *eth_port)
245351d15e82SZerun Fu {
245451d15e82SZerun Fu 	enum rte_eth_fc_mode mode;
245551d15e82SZerun Fu 
245651d15e82SZerun Fu 	if (eth_port->rx_pause_enabled) {
245751d15e82SZerun Fu 		if (eth_port->tx_pause_enabled)
245851d15e82SZerun Fu 			mode = RTE_ETH_FC_FULL;
245951d15e82SZerun Fu 		else
246051d15e82SZerun Fu 			mode = RTE_ETH_FC_RX_PAUSE;
246151d15e82SZerun Fu 	} else {
246251d15e82SZerun Fu 		if (eth_port->tx_pause_enabled)
246351d15e82SZerun Fu 			mode = RTE_ETH_FC_TX_PAUSE;
246451d15e82SZerun Fu 		else
246551d15e82SZerun Fu 			mode = RTE_ETH_FC_NONE;
246651d15e82SZerun Fu 	}
246751d15e82SZerun Fu 
246851d15e82SZerun Fu 	return mode;
246951d15e82SZerun Fu }
247051d15e82SZerun Fu 
247151d15e82SZerun Fu int
247251d15e82SZerun Fu nfp_net_flow_ctrl_get(struct rte_eth_dev *dev,
247351d15e82SZerun Fu 		struct rte_eth_fc_conf *fc_conf)
247451d15e82SZerun Fu {
2475ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
247651d15e82SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
247751d15e82SZerun Fu 	struct nfp_eth_table_port *eth_port;
247851d15e82SZerun Fu 
2479ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
2480ff9f5a56SChaoyong He 	if (hw_priv == NULL || hw_priv->pf_dev == NULL)
248151d15e82SZerun Fu 		return -EINVAL;
248251d15e82SZerun Fu 
2483ff9f5a56SChaoyong He 	nfp_eth_table = hw_priv->pf_dev->nfp_eth_table;
248451d15e82SZerun Fu 	eth_port = &nfp_eth_table->ports[dev->data->port_id];
248551d15e82SZerun Fu 
248651d15e82SZerun Fu 	/* Currently only RX/TX switch are supported */
248751d15e82SZerun Fu 	fc_conf->mode = nfp_net_get_pause_mode(eth_port);
248851d15e82SZerun Fu 
248951d15e82SZerun Fu 	return 0;
249051d15e82SZerun Fu }
249168aa3537SZerun Fu 
249268aa3537SZerun Fu static int
2493b3c21344SChaoyong He nfp_net_pause_frame_set(struct nfp_net_hw_priv *hw_priv,
249468aa3537SZerun Fu 		struct nfp_eth_table_port *eth_port,
249568aa3537SZerun Fu 		enum rte_eth_fc_mode mode)
249668aa3537SZerun Fu {
249768aa3537SZerun Fu 	int err;
249868aa3537SZerun Fu 	bool flag;
249968aa3537SZerun Fu 	struct nfp_nsp *nsp;
250068aa3537SZerun Fu 
2501b3c21344SChaoyong He 	nsp = nfp_eth_config_start(hw_priv->pf_dev->cpp, eth_port->index);
250268aa3537SZerun Fu 	if (nsp == NULL) {
250368aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "NFP error when obtaining NSP handle.");
250468aa3537SZerun Fu 		return -EIO;
250568aa3537SZerun Fu 	}
250668aa3537SZerun Fu 
250768aa3537SZerun Fu 	flag = (mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true;
250868aa3537SZerun Fu 	err = nfp_eth_set_tx_pause(nsp, flag);
250968aa3537SZerun Fu 	if (err != 0) {
251068aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to configure TX pause frame.");
251168aa3537SZerun Fu 		nfp_eth_config_cleanup_end(nsp);
251268aa3537SZerun Fu 		return err;
251368aa3537SZerun Fu 	}
251468aa3537SZerun Fu 
251568aa3537SZerun Fu 	flag = (mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true;
251668aa3537SZerun Fu 	err = nfp_eth_set_rx_pause(nsp, flag);
251768aa3537SZerun Fu 	if (err != 0) {
251868aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to configure RX pause frame.");
251968aa3537SZerun Fu 		nfp_eth_config_cleanup_end(nsp);
252068aa3537SZerun Fu 		return err;
252168aa3537SZerun Fu 	}
252268aa3537SZerun Fu 
252368aa3537SZerun Fu 	err = nfp_eth_config_commit_end(nsp);
25244bb6de51SChaoyong He 	if (err < 0) {
252568aa3537SZerun Fu 		PMD_DRV_LOG(ERR, "Failed to configure pause frame.");
252668aa3537SZerun Fu 		return err;
252768aa3537SZerun Fu 	}
252868aa3537SZerun Fu 
252968aa3537SZerun Fu 	return 0;
253068aa3537SZerun Fu }
253168aa3537SZerun Fu 
253268aa3537SZerun Fu int
253368aa3537SZerun Fu nfp_net_flow_ctrl_set(struct rte_eth_dev *dev,
253468aa3537SZerun Fu 		struct rte_eth_fc_conf *fc_conf)
253568aa3537SZerun Fu {
253668aa3537SZerun Fu 	int ret;
2537c33504deSQin Ke 	uint8_t idx;
253868aa3537SZerun Fu 	enum rte_eth_fc_mode set_mode;
2539ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
254068aa3537SZerun Fu 	enum rte_eth_fc_mode original_mode;
254168aa3537SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
254268aa3537SZerun Fu 	struct nfp_eth_table_port *eth_port;
254368aa3537SZerun Fu 
2544c33504deSQin Ke 	idx = nfp_net_get_idx(dev);
2545ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
2546ff9f5a56SChaoyong He 	if (hw_priv == NULL || hw_priv->pf_dev == NULL)
254768aa3537SZerun Fu 		return -EINVAL;
254868aa3537SZerun Fu 
2549ff9f5a56SChaoyong He 	nfp_eth_table = hw_priv->pf_dev->nfp_eth_table;
2550c33504deSQin Ke 	eth_port = &nfp_eth_table->ports[idx];
255168aa3537SZerun Fu 
255268aa3537SZerun Fu 	original_mode = nfp_net_get_pause_mode(eth_port);
255368aa3537SZerun Fu 	set_mode = fc_conf->mode;
255468aa3537SZerun Fu 
255568aa3537SZerun Fu 	if (set_mode == original_mode)
255668aa3537SZerun Fu 		return 0;
255768aa3537SZerun Fu 
2558b3c21344SChaoyong He 	ret = nfp_net_pause_frame_set(hw_priv, eth_port, set_mode);
255968aa3537SZerun Fu 	if (ret != 0)
256068aa3537SZerun Fu 		return ret;
256168aa3537SZerun Fu 
256268aa3537SZerun Fu 	/* Update eth_table after modifying RX/TX pause frame mode. */
256368aa3537SZerun Fu 	eth_port->tx_pause_enabled = (set_mode & RTE_ETH_FC_TX_PAUSE) == 0 ? false : true;
256468aa3537SZerun Fu 	eth_port->rx_pause_enabled = (set_mode & RTE_ETH_FC_RX_PAUSE) == 0 ? false : true;
256568aa3537SZerun Fu 
256668aa3537SZerun Fu 	return 0;
256768aa3537SZerun Fu }
25680786add9SZerun Fu 
25690786add9SZerun Fu int
25700786add9SZerun Fu nfp_net_fec_get_capability(struct rte_eth_dev *dev,
25710786add9SZerun Fu 		struct rte_eth_fec_capa *speed_fec_capa,
25720786add9SZerun Fu 		__rte_unused unsigned int num)
25730786add9SZerun Fu {
2574c33504deSQin Ke 	uint8_t idx;
25750786add9SZerun Fu 	uint16_t speed;
25760786add9SZerun Fu 	uint32_t supported_fec;
2577ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
25780786add9SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
25790786add9SZerun Fu 	struct nfp_eth_table_port *eth_port;
25800786add9SZerun Fu 
2581c33504deSQin Ke 	idx = nfp_net_get_idx(dev);
2582ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
2583ff9f5a56SChaoyong He 	if (hw_priv == NULL || hw_priv->pf_dev == NULL)
25840786add9SZerun Fu 		return -EINVAL;
25850786add9SZerun Fu 
2586ff9f5a56SChaoyong He 	nfp_eth_table = hw_priv->pf_dev->nfp_eth_table;
2587c33504deSQin Ke 	eth_port = &nfp_eth_table->ports[idx];
25880786add9SZerun Fu 
25890786add9SZerun Fu 	speed = eth_port->speed;
25900786add9SZerun Fu 	supported_fec = nfp_eth_supported_fec_modes(eth_port);
25910786add9SZerun Fu 	if (speed == 0 || supported_fec == 0) {
25920786add9SZerun Fu 		PMD_DRV_LOG(ERR, "FEC modes supported or Speed is invalid.");
25930786add9SZerun Fu 		return -EINVAL;
25940786add9SZerun Fu 	}
25950786add9SZerun Fu 
25960786add9SZerun Fu 	if (speed_fec_capa == NULL)
25970786add9SZerun Fu 		return NFP_FEC_CAPA_ENTRY_NUM;
25980786add9SZerun Fu 
25990786add9SZerun Fu 	speed_fec_capa->speed = speed;
26000786add9SZerun Fu 
26010786add9SZerun Fu 	if ((supported_fec & NFP_FEC_AUTO) != 0)
26020786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
26030786add9SZerun Fu 	if ((supported_fec & NFP_FEC_BASER) != 0)
26040786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
26050786add9SZerun Fu 	if ((supported_fec & NFP_FEC_REED_SOLOMON) != 0)
26060786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(RS);
26070786add9SZerun Fu 	if ((supported_fec & NFP_FEC_DISABLED) != 0)
26080786add9SZerun Fu 		speed_fec_capa->capa |= RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
26090786add9SZerun Fu 
26100786add9SZerun Fu 	return NFP_FEC_CAPA_ENTRY_NUM;
26110786add9SZerun Fu }
2612c6835a32SZerun Fu 
2613c6835a32SZerun Fu static uint32_t
2614c6835a32SZerun Fu nfp_net_fec_nfp_to_rte(enum nfp_eth_fec fec)
2615c6835a32SZerun Fu {
2616c6835a32SZerun Fu 	switch (fec) {
2617c6835a32SZerun Fu 	case NFP_FEC_AUTO_BIT:
2618c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(AUTO);
2619c6835a32SZerun Fu 	case NFP_FEC_BASER_BIT:
2620c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(BASER);
2621c6835a32SZerun Fu 	case NFP_FEC_REED_SOLOMON_BIT:
2622c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(RS);
2623c6835a32SZerun Fu 	case NFP_FEC_DISABLED_BIT:
2624c6835a32SZerun Fu 		return RTE_ETH_FEC_MODE_CAPA_MASK(NOFEC);
2625c6835a32SZerun Fu 	default:
2626c6835a32SZerun Fu 		PMD_DRV_LOG(ERR, "FEC mode is invalid.");
2627c6835a32SZerun Fu 		return 0;
2628c6835a32SZerun Fu 	}
2629c6835a32SZerun Fu }
2630c6835a32SZerun Fu 
2631c6835a32SZerun Fu int
2632c6835a32SZerun Fu nfp_net_fec_get(struct rte_eth_dev *dev,
2633c6835a32SZerun Fu 		uint32_t *fec_capa)
2634c6835a32SZerun Fu {
2635c33504deSQin Ke 	uint8_t idx;
2636ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
2637c6835a32SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
2638c6835a32SZerun Fu 	struct nfp_eth_table_port *eth_port;
2639c6835a32SZerun Fu 
2640c33504deSQin Ke 	idx = nfp_net_get_idx(dev);
2641ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
2642ff9f5a56SChaoyong He 	if (hw_priv == NULL || hw_priv->pf_dev == NULL)
2643c6835a32SZerun Fu 		return -EINVAL;
2644c6835a32SZerun Fu 
2645c6835a32SZerun Fu 	if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN) {
2646b3c21344SChaoyong He 		nfp_eth_table = nfp_eth_read_ports(hw_priv->pf_dev->cpp);
2647c33504deSQin Ke 		hw_priv->pf_dev->nfp_eth_table->ports[idx] = nfp_eth_table->ports[idx];
2648c6835a32SZerun Fu 		free(nfp_eth_table);
2649c6835a32SZerun Fu 	}
2650c6835a32SZerun Fu 
2651ff9f5a56SChaoyong He 	nfp_eth_table = hw_priv->pf_dev->nfp_eth_table;
2652c33504deSQin Ke 	eth_port = &nfp_eth_table->ports[idx];
2653c6835a32SZerun Fu 
2654c6835a32SZerun Fu 	if (!nfp_eth_can_support_fec(eth_port)) {
2655c6835a32SZerun Fu 		PMD_DRV_LOG(ERR, "NFP can not support FEC.");
2656c6835a32SZerun Fu 		return -ENOTSUP;
2657c6835a32SZerun Fu 	}
2658c6835a32SZerun Fu 
2659c6835a32SZerun Fu 	/*
2660c6835a32SZerun Fu 	 * If link is down and AUTO is enabled, AUTO is returned, otherwise,
2661c6835a32SZerun Fu 	 * configured FEC mode is returned.
2662c6835a32SZerun Fu 	 * If link is up, current FEC mode is returned.
2663c6835a32SZerun Fu 	 */
2664c6835a32SZerun Fu 	if (dev->data->dev_link.link_status == RTE_ETH_LINK_DOWN)
2665c6835a32SZerun Fu 		*fec_capa = nfp_net_fec_nfp_to_rte(eth_port->fec);
2666c6835a32SZerun Fu 	else
2667c6835a32SZerun Fu 		*fec_capa = nfp_net_fec_nfp_to_rte(eth_port->act_fec);
2668c6835a32SZerun Fu 
2669c6835a32SZerun Fu 	if (*fec_capa == 0)
2670c6835a32SZerun Fu 		return -EINVAL;
2671c6835a32SZerun Fu 
2672c6835a32SZerun Fu 	return 0;
2673c6835a32SZerun Fu }
267437bd1b84SZerun Fu 
267537bd1b84SZerun Fu static enum nfp_eth_fec
267637bd1b84SZerun Fu nfp_net_fec_rte_to_nfp(uint32_t fec)
267737bd1b84SZerun Fu {
267837bd1b84SZerun Fu 	switch (fec) {
267937bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_AUTO):
268037bd1b84SZerun Fu 		return NFP_FEC_AUTO_BIT;
268137bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_NOFEC):
268237bd1b84SZerun Fu 		return NFP_FEC_DISABLED_BIT;
268337bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_RS):
268437bd1b84SZerun Fu 		return NFP_FEC_REED_SOLOMON_BIT;
268537bd1b84SZerun Fu 	case RTE_BIT32(RTE_ETH_FEC_BASER):
268637bd1b84SZerun Fu 		return NFP_FEC_BASER_BIT;
268737bd1b84SZerun Fu 	default:
268837bd1b84SZerun Fu 		return NFP_FEC_INVALID_BIT;
268937bd1b84SZerun Fu 	}
269037bd1b84SZerun Fu }
269137bd1b84SZerun Fu 
269237bd1b84SZerun Fu int
269337bd1b84SZerun Fu nfp_net_fec_set(struct rte_eth_dev *dev,
269437bd1b84SZerun Fu 		uint32_t fec_capa)
269537bd1b84SZerun Fu {
269647fc5e4eSChaoyong He 	int ret;
2697c33504deSQin Ke 	uint8_t idx;
269837bd1b84SZerun Fu 	enum nfp_eth_fec fec;
269937bd1b84SZerun Fu 	uint32_t supported_fec;
2700ff9f5a56SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
270137bd1b84SZerun Fu 	struct nfp_eth_table *nfp_eth_table;
270237bd1b84SZerun Fu 	struct nfp_eth_table_port *eth_port;
270337bd1b84SZerun Fu 
2704c33504deSQin Ke 	idx = nfp_net_get_idx(dev);
2705ff9f5a56SChaoyong He 	hw_priv = dev->process_private;
2706ff9f5a56SChaoyong He 	if (hw_priv == NULL || hw_priv->pf_dev == NULL)
270737bd1b84SZerun Fu 		return -EINVAL;
270837bd1b84SZerun Fu 
2709ff9f5a56SChaoyong He 	nfp_eth_table = hw_priv->pf_dev->nfp_eth_table;
2710c33504deSQin Ke 	eth_port = &nfp_eth_table->ports[idx];
271137bd1b84SZerun Fu 
271237bd1b84SZerun Fu 	supported_fec = nfp_eth_supported_fec_modes(eth_port);
271337bd1b84SZerun Fu 	if (supported_fec == 0) {
271437bd1b84SZerun Fu 		PMD_DRV_LOG(ERR, "NFP can not support FEC.");
271537bd1b84SZerun Fu 		return -ENOTSUP;
271637bd1b84SZerun Fu 	}
271737bd1b84SZerun Fu 
271837bd1b84SZerun Fu 	fec = nfp_net_fec_rte_to_nfp(fec_capa);
271937bd1b84SZerun Fu 	if (fec == NFP_FEC_INVALID_BIT) {
272037bd1b84SZerun Fu 		PMD_DRV_LOG(ERR, "FEC modes is invalid.");
272137bd1b84SZerun Fu 		return -EINVAL;
272237bd1b84SZerun Fu 	}
272337bd1b84SZerun Fu 
272437bd1b84SZerun Fu 	if ((RTE_BIT32(fec) & supported_fec) == 0) {
272537bd1b84SZerun Fu 		PMD_DRV_LOG(ERR, "Unsupported FEC mode is set.");
272637bd1b84SZerun Fu 		return -EIO;
272737bd1b84SZerun Fu 	}
272837bd1b84SZerun Fu 
272947fc5e4eSChaoyong He 	ret = nfp_eth_set_fec(hw_priv->pf_dev->cpp, eth_port->index, fec);
273047fc5e4eSChaoyong He 	if (ret < 0) {
273147fc5e4eSChaoyong He 		PMD_DRV_LOG(ERR, "NFP set FEC mode failed.");
273247fc5e4eSChaoyong He 		return ret;
273347fc5e4eSChaoyong He 	}
273447fc5e4eSChaoyong He 
273547fc5e4eSChaoyong He 	return 0;
273637bd1b84SZerun Fu }
2737bd4969abSPeng Zhang 
2738bd4969abSPeng Zhang uint32_t
2739eac7eda4SChaoyong He nfp_net_get_phyports_from_nsp(struct nfp_pf_dev *pf_dev)
2740bd4969abSPeng Zhang {
2741bd4969abSPeng Zhang 	if (pf_dev->multi_pf.enabled)
2742bd4969abSPeng Zhang 		return 1;
2743bd4969abSPeng Zhang 	else
27446f708e52SChaoyong He 		return pf_dev->nfp_eth_table->count;
2745bd4969abSPeng Zhang }
2746a807bcebSPeng Zhang 
2747eac7eda4SChaoyong He uint32_t
2748eac7eda4SChaoyong He nfp_net_get_phyports_from_fw(struct nfp_pf_dev *pf_dev)
2749eac7eda4SChaoyong He {
2750eac7eda4SChaoyong He 	int ret = 0;
2751eac7eda4SChaoyong He 	uint8_t total_phyports;
2752eac7eda4SChaoyong He 	char pf_name[RTE_ETH_NAME_MAX_LEN];
2753eac7eda4SChaoyong He 
2754eac7eda4SChaoyong He 	/* Read the number of vNIC's created for the PF */
2755eac7eda4SChaoyong He 	snprintf(pf_name, sizeof(pf_name), "nfd_cfg_pf%u_num_ports",
2756eac7eda4SChaoyong He 			pf_dev->multi_pf.function_id);
2757eac7eda4SChaoyong He 	total_phyports = nfp_rtsym_read_le(pf_dev->sym_tbl, pf_name, &ret);
2758eac7eda4SChaoyong He 	if (ret != 0 || total_phyports == 0 || total_phyports > 8) {
2759eac7eda4SChaoyong He 		PMD_INIT_LOG(ERR, "%s symbol with wrong value", pf_name);
2760eac7eda4SChaoyong He 		return 0;
2761eac7eda4SChaoyong He 	}
2762eac7eda4SChaoyong He 
2763eac7eda4SChaoyong He 	return total_phyports;
2764eac7eda4SChaoyong He }
2765eac7eda4SChaoyong He 
2766a807bcebSPeng Zhang uint8_t
2767a807bcebSPeng Zhang nfp_function_id_get(const struct nfp_pf_dev *pf_dev,
2768a807bcebSPeng Zhang 		uint8_t port_id)
2769a807bcebSPeng Zhang {
2770a807bcebSPeng Zhang 	if (pf_dev->multi_pf.enabled)
2771a807bcebSPeng Zhang 		return pf_dev->multi_pf.function_id;
2772a807bcebSPeng Zhang 
2773a807bcebSPeng Zhang 	return port_id;
2774a807bcebSPeng Zhang }
277587abbaf9SPeng Zhang 
277687abbaf9SPeng Zhang static int
277787abbaf9SPeng Zhang nfp_net_sriov_check(struct nfp_pf_dev *pf_dev,
277887abbaf9SPeng Zhang 		uint16_t cap)
277987abbaf9SPeng Zhang {
278087abbaf9SPeng Zhang 	uint16_t cap_vf;
278187abbaf9SPeng Zhang 
278287abbaf9SPeng Zhang 	cap_vf = nn_readw(pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_CAP);
278387abbaf9SPeng Zhang 	if ((cap_vf & cap) != cap)
278487abbaf9SPeng Zhang 		return -ENOTSUP;
278587abbaf9SPeng Zhang 
278687abbaf9SPeng Zhang 	return 0;
278787abbaf9SPeng Zhang }
278887abbaf9SPeng Zhang 
278987abbaf9SPeng Zhang static int
279087abbaf9SPeng Zhang nfp_net_sriov_update(struct nfp_net_hw *net_hw,
279187abbaf9SPeng Zhang 		struct nfp_pf_dev *pf_dev,
279287abbaf9SPeng Zhang 		uint16_t update)
279387abbaf9SPeng Zhang {
279487abbaf9SPeng Zhang 	int ret;
279587abbaf9SPeng Zhang 
279687abbaf9SPeng Zhang 	/* Reuse NFP_NET_VF_CFG_MB_VF_NUM to pass vf_base_id to FW. */
279787abbaf9SPeng Zhang 	ret = nfp_net_vf_reconfig(net_hw, pf_dev, update, pf_dev->vf_base_id,
279887abbaf9SPeng Zhang 			NFP_NET_VF_CFG_MB_VF_NUM);
279987abbaf9SPeng Zhang 	if (ret != 0) {
2800b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "Error nfp VF reconfig.");
280187abbaf9SPeng Zhang 		return ret;
280287abbaf9SPeng Zhang 	}
280387abbaf9SPeng Zhang 
280487abbaf9SPeng Zhang 	return 0;
280587abbaf9SPeng Zhang }
280687abbaf9SPeng Zhang 
280787abbaf9SPeng Zhang static int
2808bb24eb38SPeng Zhang nfp_net_vf_queues_config(struct nfp_net_hw *net_hw,
2809bb24eb38SPeng Zhang 		struct nfp_pf_dev *pf_dev)
2810bb24eb38SPeng Zhang {
2811bb24eb38SPeng Zhang 	int ret;
2812bb24eb38SPeng Zhang 	uint32_t i;
2813bb24eb38SPeng Zhang 	uint32_t offset;
2814bb24eb38SPeng Zhang 
2815bb24eb38SPeng Zhang 	ret = nfp_net_sriov_check(pf_dev, NFP_NET_VF_CFG_MB_CAP_QUEUE_CONFIG);
2816bb24eb38SPeng Zhang 	if (ret != 0) {
2817bb24eb38SPeng Zhang 		if (ret == -ENOTSUP) {
2818b6de4353SZerun Fu 			PMD_INIT_LOG(DEBUG, "Set VF max queue not supported.");
2819bb24eb38SPeng Zhang 			return 0;
2820bb24eb38SPeng Zhang 		}
2821bb24eb38SPeng Zhang 
2822b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "Set VF max queue failed.");
2823bb24eb38SPeng Zhang 		return ret;
2824bb24eb38SPeng Zhang 	}
2825bb24eb38SPeng Zhang 
2826bb24eb38SPeng Zhang 	offset = NFP_NET_VF_CFG_MB_SZ + pf_dev->max_vfs * NFP_NET_VF_CFG_SZ;
2827bb24eb38SPeng Zhang 	for (i = 0; i < pf_dev->sriov_vf; i++) {
2828bb24eb38SPeng Zhang 		ret = nfp_net_vf_reconfig(net_hw, pf_dev, NFP_NET_VF_CFG_MB_UPD_QUEUE_CONFIG,
2829bb24eb38SPeng Zhang 				pf_dev->queue_per_vf, pf_dev->vf_base_id + offset + i);
2830bb24eb38SPeng Zhang 		if (ret != 0) {
2831b6de4353SZerun Fu 			PMD_INIT_LOG(ERR, "Set VF max_queue failed.");
2832bb24eb38SPeng Zhang 			return ret;
2833bb24eb38SPeng Zhang 		}
2834bb24eb38SPeng Zhang 	}
2835bb24eb38SPeng Zhang 
2836bb24eb38SPeng Zhang 	return 0;
2837bb24eb38SPeng Zhang }
2838bb24eb38SPeng Zhang 
2839bb24eb38SPeng Zhang static int
284087abbaf9SPeng Zhang nfp_net_sriov_init(struct nfp_net_hw *net_hw,
284187abbaf9SPeng Zhang 		struct nfp_pf_dev *pf_dev)
284287abbaf9SPeng Zhang {
284387abbaf9SPeng Zhang 	int ret;
284487abbaf9SPeng Zhang 
284587abbaf9SPeng Zhang 	ret = nfp_net_sriov_check(pf_dev, NFP_NET_VF_CFG_MB_CAP_SPLIT);
284687abbaf9SPeng Zhang 	if (ret != 0) {
284787abbaf9SPeng Zhang 		if (ret == -ENOTSUP) {
2848b6de4353SZerun Fu 			PMD_INIT_LOG(DEBUG, "Set VF split not supported.");
284987abbaf9SPeng Zhang 			return 0;
285087abbaf9SPeng Zhang 		}
285187abbaf9SPeng Zhang 
2852b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "Set VF split failed.");
285387abbaf9SPeng Zhang 		return ret;
285487abbaf9SPeng Zhang 	}
285587abbaf9SPeng Zhang 
285687abbaf9SPeng Zhang 	nn_writeb(pf_dev->sriov_vf, pf_dev->vf_cfg_tbl_bar + NFP_NET_VF_CFG_MB_VF_CNT);
285787abbaf9SPeng Zhang 
285887abbaf9SPeng Zhang 	ret = nfp_net_sriov_update(net_hw, pf_dev, NFP_NET_VF_CFG_MB_UPD_SPLIT);
285987abbaf9SPeng Zhang 	if (ret != 0) {
2860b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "The nfp sriov update spilt failed.");
286187abbaf9SPeng Zhang 		return ret;
286287abbaf9SPeng Zhang 	}
286387abbaf9SPeng Zhang 
286487abbaf9SPeng Zhang 	return 0;
286587abbaf9SPeng Zhang }
286687abbaf9SPeng Zhang 
286787abbaf9SPeng Zhang int
286887abbaf9SPeng Zhang nfp_net_vf_config_app_init(struct nfp_net_hw *net_hw,
286987abbaf9SPeng Zhang 		struct nfp_pf_dev *pf_dev)
287087abbaf9SPeng Zhang {
287187abbaf9SPeng Zhang 	int ret;
287287abbaf9SPeng Zhang 
287387abbaf9SPeng Zhang 	if (pf_dev->sriov_vf == 0)
287487abbaf9SPeng Zhang 		return 0;
287587abbaf9SPeng Zhang 
287687abbaf9SPeng Zhang 	ret = nfp_net_sriov_init(net_hw, pf_dev);
287787abbaf9SPeng Zhang 	if (ret != 0) {
2878b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "Failed to init sriov module.");
287987abbaf9SPeng Zhang 		return ret;
288087abbaf9SPeng Zhang 	}
288187abbaf9SPeng Zhang 
2882bb24eb38SPeng Zhang 	ret = nfp_net_vf_queues_config(net_hw, pf_dev);
2883bb24eb38SPeng Zhang 	if (ret != 0) {
2884b6de4353SZerun Fu 		PMD_INIT_LOG(ERR, "Failed to config vf queue.");
2885bb24eb38SPeng Zhang 		return ret;
2886bb24eb38SPeng Zhang 	}
2887bb24eb38SPeng Zhang 
288887abbaf9SPeng Zhang 	return 0;
288987abbaf9SPeng Zhang }
2890636e133eSPeng Zhang 
2891636e133eSPeng Zhang static inline bool
2892636e133eSPeng Zhang nfp_net_meta_has_no_port_type(__rte_unused struct nfp_net_meta_parsed *meta)
2893636e133eSPeng Zhang {
2894636e133eSPeng Zhang 	return true;
2895636e133eSPeng Zhang }
2896636e133eSPeng Zhang 
2897636e133eSPeng Zhang static inline bool
2898636e133eSPeng Zhang nfp_net_meta_is_not_pf_port(__rte_unused struct nfp_net_meta_parsed *meta)
2899636e133eSPeng Zhang {
2900636e133eSPeng Zhang 	return false;
2901636e133eSPeng Zhang }
2902636e133eSPeng Zhang 
2903636e133eSPeng Zhang static inline bool
2904636e133eSPeng Zhang nfp_net_meta_is_pf_port(struct nfp_net_meta_parsed *meta)
2905636e133eSPeng Zhang {
2906636e133eSPeng Zhang 	return nfp_flower_port_is_phy_port(meta->port_id);
2907636e133eSPeng Zhang }
2908636e133eSPeng Zhang 
2909636e133eSPeng Zhang bool
2910636e133eSPeng Zhang nfp_net_recv_pkt_meta_check_register(struct nfp_net_hw_priv *hw_priv)
2911636e133eSPeng Zhang {
2912636e133eSPeng Zhang 	struct nfp_pf_dev *pf_dev;
2913636e133eSPeng Zhang 
2914636e133eSPeng Zhang 	pf_dev = hw_priv->pf_dev;
2915636e133eSPeng Zhang 	if (!hw_priv->is_pf) {
2916636e133eSPeng Zhang 		pf_dev->recv_pkt_meta_check_t = nfp_net_meta_has_no_port_type;
2917636e133eSPeng Zhang 		return true;
2918636e133eSPeng Zhang 	}
2919636e133eSPeng Zhang 
2920636e133eSPeng Zhang 	switch (pf_dev->app_fw_id) {
2921636e133eSPeng Zhang 	case NFP_APP_FW_CORE_NIC:
2922636e133eSPeng Zhang 		pf_dev->recv_pkt_meta_check_t = nfp_net_meta_has_no_port_type;
2923636e133eSPeng Zhang 		break;
2924636e133eSPeng Zhang 	case NFP_APP_FW_FLOWER_NIC:
2925636e133eSPeng Zhang 		if (pf_dev->multi_pf.enabled)
2926636e133eSPeng Zhang 			pf_dev->recv_pkt_meta_check_t = nfp_net_meta_is_pf_port;
2927636e133eSPeng Zhang 		else
2928636e133eSPeng Zhang 			pf_dev->recv_pkt_meta_check_t = nfp_net_meta_is_not_pf_port;
2929636e133eSPeng Zhang 		break;
2930636e133eSPeng Zhang 	default:
2931636e133eSPeng Zhang 		PMD_INIT_LOG(ERR, "Unsupported Firmware loaded.");
2932636e133eSPeng Zhang 		return false;
2933636e133eSPeng Zhang 	}
2934636e133eSPeng Zhang 
2935636e133eSPeng Zhang 	return true;
2936636e133eSPeng Zhang }
29377f693813SChaoyong He 
29387f693813SChaoyong He static int
29397f693813SChaoyong He nfp_net_get_nfp_index(struct rte_eth_dev *dev)
29407f693813SChaoyong He {
29417f693813SChaoyong He 	int nfp_idx;
29427f693813SChaoyong He 
29437f693813SChaoyong He 	if (rte_eth_dev_is_repr(dev)) {
29447f693813SChaoyong He 		struct nfp_flower_representor *repr;
29457f693813SChaoyong He 		repr = dev->data->dev_private;
29467f693813SChaoyong He 		nfp_idx = repr->nfp_idx;
29477f693813SChaoyong He 	} else {
29487f693813SChaoyong He 		struct nfp_net_hw *net_hw;
29497f693813SChaoyong He 		net_hw = dev->data->dev_private;
29507f693813SChaoyong He 		nfp_idx = net_hw->nfp_idx;
29517f693813SChaoyong He 	}
29527f693813SChaoyong He 
29537f693813SChaoyong He 	return nfp_idx;
29547f693813SChaoyong He }
29557f693813SChaoyong He 
29567f693813SChaoyong He int
29577f693813SChaoyong He nfp_net_get_eeprom_len(__rte_unused struct rte_eth_dev *dev)
29587f693813SChaoyong He {
29597f693813SChaoyong He 	return RTE_ETHER_ADDR_LEN;
29607f693813SChaoyong He }
29617f693813SChaoyong He 
29627f693813SChaoyong He static int
29637f693813SChaoyong He nfp_net_get_port_mac_hwinfo(struct nfp_net_hw_priv *hw_priv,
29647f693813SChaoyong He 		uint32_t index,
29657f693813SChaoyong He 		struct rte_ether_addr *mac_addr)
29667f693813SChaoyong He {
29677f693813SChaoyong He 	int ret;
29687f693813SChaoyong He 	char hwinfo[32];
29697f693813SChaoyong He 	struct nfp_nsp *nsp;
29707f693813SChaoyong He 
29717f693813SChaoyong He 	snprintf(hwinfo, sizeof(hwinfo), "eth%u.mac", index);
29727f693813SChaoyong He 
29737f693813SChaoyong He 	nsp = nfp_nsp_open(hw_priv->pf_dev->cpp);
29747f693813SChaoyong He 	if (nsp == NULL)
29757f693813SChaoyong He 		return -EOPNOTSUPP;
29767f693813SChaoyong He 
29777f693813SChaoyong He 	ret = nfp_nsp_hwinfo_lookup(nsp, hwinfo, sizeof(hwinfo));
29787f693813SChaoyong He 	nfp_nsp_close(nsp);
29797f693813SChaoyong He 
29807f693813SChaoyong He 	if (ret != 0) {
29817f693813SChaoyong He 		PMD_DRV_LOG(ERR, "Read persistent MAC address failed for eth_index %u.", index);
29827f693813SChaoyong He 		return ret;
29837f693813SChaoyong He 	}
29847f693813SChaoyong He 
29857f693813SChaoyong He 	ret = rte_ether_unformat_addr(hwinfo, mac_addr);
29867f693813SChaoyong He 	if (ret != 0) {
29877f693813SChaoyong He 		PMD_DRV_LOG(ERR, "Can not parse persistent MAC address.");
29887f693813SChaoyong He 		return -EOPNOTSUPP;
29897f693813SChaoyong He 	}
29907f693813SChaoyong He 
29917f693813SChaoyong He 	return 0;
29927f693813SChaoyong He }
29937f693813SChaoyong He 
29947f693813SChaoyong He static int
29957f693813SChaoyong He nfp_net_set_port_mac_hwinfo(struct nfp_net_hw_priv *hw_priv,
29967f693813SChaoyong He 		uint32_t index,
29977f693813SChaoyong He 		struct rte_ether_addr *mac_addr)
29987f693813SChaoyong He {
29997f693813SChaoyong He 	int ret;
30007f693813SChaoyong He 	char hwinfo_mac[32];
30017f693813SChaoyong He 	struct nfp_nsp *nsp;
30027f693813SChaoyong He 	char buf[RTE_ETHER_ADDR_FMT_SIZE];
30037f693813SChaoyong He 
30047f693813SChaoyong He 	rte_ether_format_addr(buf, RTE_ETHER_ADDR_FMT_SIZE, mac_addr);
30057f693813SChaoyong He 	snprintf(hwinfo_mac, sizeof(hwinfo_mac), "eth%u.mac=%s", index, buf);
30067f693813SChaoyong He 
30077f693813SChaoyong He 	nsp = nfp_nsp_open(hw_priv->pf_dev->cpp);
30087f693813SChaoyong He 	if (nsp == NULL)
30097f693813SChaoyong He 		return -EOPNOTSUPP;
30107f693813SChaoyong He 
30117f693813SChaoyong He 	ret = nfp_nsp_hwinfo_set(nsp, hwinfo_mac, sizeof(hwinfo_mac));
30127f693813SChaoyong He 	nfp_nsp_close(nsp);
30137f693813SChaoyong He 
30147f693813SChaoyong He 	if (ret != 0) {
30157f693813SChaoyong He 		PMD_DRV_LOG(ERR, "HWinfo set failed: %d.", ret);
30167f693813SChaoyong He 		return ret;
30177f693813SChaoyong He 	}
30187f693813SChaoyong He 
30197f693813SChaoyong He 	return 0;
30207f693813SChaoyong He }
30217f693813SChaoyong He 
30227f693813SChaoyong He int
30237f693813SChaoyong He nfp_net_get_eeprom(struct rte_eth_dev *dev,
30247f693813SChaoyong He 		struct rte_dev_eeprom_info *eeprom)
30257f693813SChaoyong He {
30267f693813SChaoyong He 	int ret;
30277f693813SChaoyong He 	uint32_t nfp_idx;
30287f693813SChaoyong He 	struct nfp_net_hw *net_hw;
30297f693813SChaoyong He 	struct rte_ether_addr mac_addr;
30307f693813SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
30317f693813SChaoyong He 
30327f693813SChaoyong He 	if (eeprom->length == 0)
30337f693813SChaoyong He 		return -EINVAL;
30347f693813SChaoyong He 
30357f693813SChaoyong He 	hw_priv = dev->process_private;
30367f693813SChaoyong He 	nfp_idx = nfp_net_get_nfp_index(dev);
30377f693813SChaoyong He 
30387f693813SChaoyong He 	ret = nfp_net_get_port_mac_hwinfo(hw_priv, nfp_idx, &mac_addr);
30397f693813SChaoyong He 	if (ret != 0)
30407f693813SChaoyong He 		return -EOPNOTSUPP;
30417f693813SChaoyong He 
30427f693813SChaoyong He 	net_hw = nfp_net_get_hw(dev);
30437f693813SChaoyong He 	eeprom->magic = net_hw->vendor_id | (net_hw->device_id << 16);
30447f693813SChaoyong He 	memcpy(eeprom->data, mac_addr.addr_bytes + eeprom->offset, eeprom->length);
30457f693813SChaoyong He 
30467f693813SChaoyong He 	return 0;
30477f693813SChaoyong He }
30487f693813SChaoyong He 
30497f693813SChaoyong He int
30507f693813SChaoyong He nfp_net_set_eeprom(struct rte_eth_dev *dev,
30517f693813SChaoyong He 		struct rte_dev_eeprom_info *eeprom)
30527f693813SChaoyong He {
30537f693813SChaoyong He 	int ret;
30547f693813SChaoyong He 	uint32_t nfp_idx;
30557f693813SChaoyong He 	struct nfp_net_hw *net_hw;
30567f693813SChaoyong He 	struct rte_ether_addr mac_addr;
30577f693813SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
30587f693813SChaoyong He 
30597f693813SChaoyong He 	if (eeprom->length == 0)
30607f693813SChaoyong He 		return -EINVAL;
30617f693813SChaoyong He 
30627f693813SChaoyong He 	net_hw = nfp_net_get_hw(dev);
30637f693813SChaoyong He 	if (eeprom->magic != (uint32_t)(net_hw->vendor_id | (net_hw->device_id << 16)))
30647f693813SChaoyong He 		return -EINVAL;
30657f693813SChaoyong He 
30667f693813SChaoyong He 	hw_priv = dev->process_private;
30677f693813SChaoyong He 	nfp_idx = nfp_net_get_nfp_index(dev);
30687f693813SChaoyong He 	ret = nfp_net_get_port_mac_hwinfo(hw_priv, nfp_idx, &mac_addr);
30697f693813SChaoyong He 	if (ret != 0)
30707f693813SChaoyong He 		return -EOPNOTSUPP;
30717f693813SChaoyong He 
30727f693813SChaoyong He 	memcpy(mac_addr.addr_bytes + eeprom->offset, eeprom->data, eeprom->length);
30737f693813SChaoyong He 	ret = nfp_net_set_port_mac_hwinfo(hw_priv, nfp_idx, &mac_addr);
30747f693813SChaoyong He 	if (ret != 0)
30757f693813SChaoyong He 		return -EOPNOTSUPP;
30767f693813SChaoyong He 
30777f693813SChaoyong He 	return 0;
30787f693813SChaoyong He }
30797f693813SChaoyong He 
30807f693813SChaoyong He int
30817f693813SChaoyong He nfp_net_get_module_info(struct rte_eth_dev *dev,
30827f693813SChaoyong He 		struct rte_eth_dev_module_info *info)
30837f693813SChaoyong He {
30847f693813SChaoyong He 	int ret = 0;
30857f693813SChaoyong He 	uint8_t data;
30867f693813SChaoyong He 	uint32_t idx;
30877f693813SChaoyong He 	uint32_t read_len;
30887f693813SChaoyong He 	struct nfp_nsp *nsp;
30897f693813SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
30907f693813SChaoyong He 	struct nfp_eth_table_port *eth_port;
30917f693813SChaoyong He 
30927f693813SChaoyong He 	hw_priv = dev->process_private;
30937f693813SChaoyong He 	nsp = nfp_nsp_open(hw_priv->pf_dev->cpp);
30947f693813SChaoyong He 	if (nsp == NULL) {
30957f693813SChaoyong He 		PMD_DRV_LOG(ERR, "Unable to open NSP.");
30967f693813SChaoyong He 		return -EIO;
30977f693813SChaoyong He 	}
30987f693813SChaoyong He 
30997f693813SChaoyong He 	if (!nfp_nsp_has_read_module_eeprom(nsp)) {
31007f693813SChaoyong He 		PMD_DRV_LOG(ERR, "Read module eeprom not supported. Please update flash.");
31017f693813SChaoyong He 		ret = -EOPNOTSUPP;
31027f693813SChaoyong He 		goto exit_close_nsp;
31037f693813SChaoyong He 	}
31047f693813SChaoyong He 
31057f693813SChaoyong He 	idx = nfp_net_get_idx(dev);
31067f693813SChaoyong He 	eth_port = &hw_priv->pf_dev->nfp_eth_table->ports[idx];
31077f693813SChaoyong He 	switch (eth_port->interface) {
31087f693813SChaoyong He 	case NFP_INTERFACE_SFP:
31097f693813SChaoyong He 		/* FALLTHROUGH */
31107f693813SChaoyong He 	case NFP_INTERFACE_SFP28:
31117f693813SChaoyong He 		/* Read which revision the transceiver compiles with */
31127f693813SChaoyong He 		ret = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index,
31137f693813SChaoyong He 				SFP_SFF8472_COMPLIANCE, &data, 1, &read_len);
31147f693813SChaoyong He 		if (ret != 0)
31157f693813SChaoyong He 			goto exit_close_nsp;
31167f693813SChaoyong He 
31177f693813SChaoyong He 		if (data == 0) {
31187f693813SChaoyong He 			info->type = RTE_ETH_MODULE_SFF_8079;
31197f693813SChaoyong He 			info->eeprom_len = RTE_ETH_MODULE_SFF_8079_LEN;
31207f693813SChaoyong He 		} else {
31217f693813SChaoyong He 			info->type = RTE_ETH_MODULE_SFF_8472;
31227f693813SChaoyong He 			info->eeprom_len = RTE_ETH_MODULE_SFF_8472_LEN;
31237f693813SChaoyong He 		}
31247f693813SChaoyong He 		break;
31257f693813SChaoyong He 	case NFP_INTERFACE_QSFP:
31267f693813SChaoyong He 		/* Read which revision the transceiver compiles with */
31277f693813SChaoyong He 		ret = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index,
31287f693813SChaoyong He 				SFP_SFF_REV_COMPLIANCE, &data, 1, &read_len);
31297f693813SChaoyong He 		if (ret != 0)
31307f693813SChaoyong He 			goto exit_close_nsp;
31317f693813SChaoyong He 
31327f693813SChaoyong He 		if (data == 0) {
31337f693813SChaoyong He 			info->type = RTE_ETH_MODULE_SFF_8436;
31347f693813SChaoyong He 			info->eeprom_len = RTE_ETH_MODULE_SFF_8436_MAX_LEN;
31357f693813SChaoyong He 		} else {
31367f693813SChaoyong He 			info->type = RTE_ETH_MODULE_SFF_8636;
31377f693813SChaoyong He 			info->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN;
31387f693813SChaoyong He 		}
31397f693813SChaoyong He 		break;
31407f693813SChaoyong He 	case NFP_INTERFACE_QSFP28:
31417f693813SChaoyong He 		info->type = RTE_ETH_MODULE_SFF_8636;
31427f693813SChaoyong He 		info->eeprom_len = RTE_ETH_MODULE_SFF_8636_MAX_LEN;
31437f693813SChaoyong He 		break;
31447f693813SChaoyong He 	default:
31457f693813SChaoyong He 		PMD_DRV_LOG(ERR, "Unsupported module %#x detected.",
31467f693813SChaoyong He 				eth_port->interface);
31477f693813SChaoyong He 		ret = -EINVAL;
31487f693813SChaoyong He 	}
31497f693813SChaoyong He 
31507f693813SChaoyong He exit_close_nsp:
31517f693813SChaoyong He 	nfp_nsp_close(nsp);
31527f693813SChaoyong He 	return ret;
31537f693813SChaoyong He }
31547f693813SChaoyong He 
31557f693813SChaoyong He int
31567f693813SChaoyong He nfp_net_get_module_eeprom(struct rte_eth_dev *dev,
31577f693813SChaoyong He 		struct rte_dev_eeprom_info *info)
31587f693813SChaoyong He {
31597f693813SChaoyong He 	int ret = 0;
31607f693813SChaoyong He 	uint32_t idx;
31617f693813SChaoyong He 	struct nfp_nsp *nsp;
31627f693813SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
31637f693813SChaoyong He 	struct nfp_eth_table_port *eth_port;
31647f693813SChaoyong He 
31657f693813SChaoyong He 	hw_priv = dev->process_private;
31667f693813SChaoyong He 	nsp = nfp_nsp_open(hw_priv->pf_dev->cpp);
31677f693813SChaoyong He 	if (nsp == NULL) {
31687f693813SChaoyong He 		PMD_DRV_LOG(ERR, "Unable to open NSP.");
31697f693813SChaoyong He 		return -EIO;
31707f693813SChaoyong He 	}
31717f693813SChaoyong He 
31727f693813SChaoyong He 	if (!nfp_nsp_has_read_module_eeprom(nsp)) {
31737f693813SChaoyong He 		PMD_DRV_LOG(ERR, "Read module eeprom not supported. Please update flash.");
31747f693813SChaoyong He 		ret = -EOPNOTSUPP;
31757f693813SChaoyong He 		goto exit_close_nsp;
31767f693813SChaoyong He 	}
31777f693813SChaoyong He 
31787f693813SChaoyong He 	idx = nfp_net_get_idx(dev);
31797f693813SChaoyong He 	eth_port = &hw_priv->pf_dev->nfp_eth_table->ports[idx];
31807f693813SChaoyong He 	ret = nfp_nsp_read_module_eeprom(nsp, eth_port->eth_index, info->offset,
31817f693813SChaoyong He 			info->data, info->length, &info->length);
31827f693813SChaoyong He 	if (ret != 0) {
31837f693813SChaoyong He 		if (info->length)
31847f693813SChaoyong He 			PMD_DRV_LOG(ERR, "Incomplete read from module EEPROM: %d.", ret);
31857f693813SChaoyong He 		else
31867f693813SChaoyong He 			PMD_DRV_LOG(ERR, "Read from module EEPROM failed: %d.", ret);
31877f693813SChaoyong He 	}
31887f693813SChaoyong He 
31897f693813SChaoyong He exit_close_nsp:
31907f693813SChaoyong He 	nfp_nsp_close(nsp);
31917f693813SChaoyong He 	return ret;
31927f693813SChaoyong He }
31938bd6f540SChaoyong He 
31948bd6f540SChaoyong He static int
31958bd6f540SChaoyong He nfp_net_led_control(struct rte_eth_dev *dev,
31968bd6f540SChaoyong He 		bool is_on)
31978bd6f540SChaoyong He {
31988bd6f540SChaoyong He 	int ret;
31998bd6f540SChaoyong He 	uint32_t nfp_idx;
32008bd6f540SChaoyong He 	struct nfp_net_hw_priv *hw_priv;
32018bd6f540SChaoyong He 
32028bd6f540SChaoyong He 	hw_priv = dev->process_private;
32038bd6f540SChaoyong He 	nfp_idx = nfp_net_get_nfp_index(dev);
32048bd6f540SChaoyong He 
32058bd6f540SChaoyong He 	ret = nfp_eth_set_idmode(hw_priv->pf_dev->cpp, nfp_idx, is_on);
32068bd6f540SChaoyong He 	if (ret < 0) {
32078bd6f540SChaoyong He 		PMD_DRV_LOG(ERR, "Set nfp idmode failed.");
32088bd6f540SChaoyong He 		return ret;
32098bd6f540SChaoyong He 	}
32108bd6f540SChaoyong He 
32118bd6f540SChaoyong He 	return 0;
32128bd6f540SChaoyong He }
32138bd6f540SChaoyong He 
32148bd6f540SChaoyong He int
32158bd6f540SChaoyong He nfp_net_led_on(struct rte_eth_dev *dev)
32168bd6f540SChaoyong He {
32178bd6f540SChaoyong He 	return nfp_net_led_control(dev, true);
32188bd6f540SChaoyong He }
32198bd6f540SChaoyong He 
32208bd6f540SChaoyong He int
32218bd6f540SChaoyong He nfp_net_led_off(struct rte_eth_dev *dev)
32228bd6f540SChaoyong He {
32238bd6f540SChaoyong He 	return nfp_net_led_control(dev, false);
32248bd6f540SChaoyong He }
3225