xref: /dpdk/drivers/net/hinic/hinic_pmd_ethdev.c (revision 2cfd68ec407609becd75661787043e7cae35f15c)
11d09792aSZiyang Xuan /* SPDX-License-Identifier: BSD-3-Clause
21d09792aSZiyang Xuan  * Copyright(c) 2017 Huawei Technologies Co., Ltd
31d09792aSZiyang Xuan  */
41d09792aSZiyang Xuan 
51d09792aSZiyang Xuan #include <rte_pci.h>
61d09792aSZiyang Xuan #include <rte_bus_pci.h>
7df96fd0dSBruce Richardson #include <ethdev_pci.h>
864727024SZiyang Xuan #include <rte_mbuf.h>
91d09792aSZiyang Xuan #include <rte_malloc.h>
101d09792aSZiyang Xuan #include <rte_memcpy.h>
1164727024SZiyang Xuan #include <rte_mempool.h>
1264727024SZiyang Xuan #include <rte_errno.h>
13fdba3bf1SXiaoyun Wang #include <rte_ether.h>
141d09792aSZiyang Xuan 
151d09792aSZiyang Xuan #include "base/hinic_compat.h"
161d09792aSZiyang Xuan #include "base/hinic_pmd_hwdev.h"
1764727024SZiyang Xuan #include "base/hinic_pmd_hwif.h"
1864727024SZiyang Xuan #include "base/hinic_pmd_wq.h"
1964727024SZiyang Xuan #include "base/hinic_pmd_cfg.h"
2064727024SZiyang Xuan #include "base/hinic_pmd_mgmt.h"
2164727024SZiyang Xuan #include "base/hinic_pmd_cmdq.h"
221d09792aSZiyang Xuan #include "base/hinic_pmd_niccfg.h"
2364727024SZiyang Xuan #include "base/hinic_pmd_nicio.h"
246691acefSXiaoyun Wang #include "base/hinic_pmd_mbox.h"
251d09792aSZiyang Xuan #include "hinic_pmd_ethdev.h"
2664727024SZiyang Xuan #include "hinic_pmd_tx.h"
2764727024SZiyang Xuan #include "hinic_pmd_rx.h"
281d09792aSZiyang Xuan 
291d09792aSZiyang Xuan /* Vendor ID used by Huawei devices */
301d09792aSZiyang Xuan #define HINIC_HUAWEI_VENDOR_ID		0x19E5
311d09792aSZiyang Xuan 
321d09792aSZiyang Xuan /* Hinic devices */
331d09792aSZiyang Xuan #define HINIC_DEV_ID_PRD		0x1822
346691acefSXiaoyun Wang #define HINIC_DEV_ID_VF			0x375E
356691acefSXiaoyun Wang #define HINIC_DEV_ID_VF_HV		0x379E
366691acefSXiaoyun Wang 
376691acefSXiaoyun Wang /* Mezz card for Blade Server */
381d09792aSZiyang Xuan #define HINIC_DEV_ID_MEZZ_25GE		0x0210
391d09792aSZiyang Xuan #define HINIC_DEV_ID_MEZZ_100GE		0x0205
401d09792aSZiyang Xuan 
416691acefSXiaoyun Wang /* 2*25G and 2*100G card */
426691acefSXiaoyun Wang #define HINIC_DEV_ID_1822_DUAL_25GE	0x0206
436691acefSXiaoyun Wang #define HINIC_DEV_ID_1822_100GE		0x0200
446691acefSXiaoyun Wang 
4564727024SZiyang Xuan #define HINIC_SERVICE_MODE_NIC		2
4664727024SZiyang Xuan 
4764727024SZiyang Xuan #define HINIC_INTR_CB_UNREG_MAX_RETRIES	10
4864727024SZiyang Xuan 
4964727024SZiyang Xuan #define DEFAULT_BASE_COS		4
5064727024SZiyang Xuan #define NR_MAX_COS			8
5164727024SZiyang Xuan 
521d09792aSZiyang Xuan #define HINIC_MIN_RX_BUF_SIZE		1024
5300499a22SXiaoyun Wang #define HINIC_MAX_UC_MAC_ADDRS		128
5400499a22SXiaoyun Wang #define HINIC_MAX_MC_MAC_ADDRS		2048
55483b4817SXiaoyun Wang 
56483b4817SXiaoyun Wang #define HINIC_DEFAULT_BURST_SIZE	32
57483b4817SXiaoyun Wang #define HINIC_DEFAULT_NB_QUEUES		1
58483b4817SXiaoyun Wang #define HINIC_DEFAULT_RING_SIZE		1024
591b7b9f17SXiaoyun Wang #define HINIC_MAX_LRO_SIZE		65536
60483b4817SXiaoyun Wang 
61fdba3bf1SXiaoyun Wang /*
62fdba3bf1SXiaoyun Wang  * vlan_id is a 12 bit number.
63fdba3bf1SXiaoyun Wang  * The VFTA array is actually a 4096 bit array, 128 of 32bit elements.
64fdba3bf1SXiaoyun Wang  * 2^5 = 32. The val of lower 5 bits specifies the bit in the 32bit element.
65fdba3bf1SXiaoyun Wang  * The higher 7 bit val specifies VFTA array index.
66fdba3bf1SXiaoyun Wang  */
67fdba3bf1SXiaoyun Wang #define HINIC_VFTA_BIT(vlan_id)    (1 << ((vlan_id) & 0x1F))
68fdba3bf1SXiaoyun Wang #define HINIC_VFTA_IDX(vlan_id)    ((vlan_id) >> 5)
69fdba3bf1SXiaoyun Wang 
70fdba3bf1SXiaoyun Wang #define HINIC_VLAN_FILTER_EN		(1U << 0)
71fdba3bf1SXiaoyun Wang 
728260eba6SXiaoyun Wang #define HINIC_MTU_TO_PKTLEN(mtu)	\
738260eba6SXiaoyun Wang 	((mtu) + ETH_HLEN + ETH_CRC_LEN)
748260eba6SXiaoyun Wang 
758260eba6SXiaoyun Wang #define HINIC_PKTLEN_TO_MTU(pktlen)	\
768260eba6SXiaoyun Wang 	((pktlen) - (ETH_HLEN + ETH_CRC_LEN))
778260eba6SXiaoyun Wang 
78e542ab51SSteve Yang /* The max frame size with default MTU */
79e542ab51SSteve Yang #define HINIC_ETH_MAX_LEN (RTE_ETHER_MTU + ETH_HLEN + ETH_CRC_LEN)
80e542ab51SSteve Yang 
819d4878efSXiaoyun Wang /* lro numer limit for one packet */
829d4878efSXiaoyun Wang #define HINIC_LRO_WQE_NUM_DEFAULT	8
839d4878efSXiaoyun Wang 
84cb7b6606SZiyang Xuan struct hinic_xstats_name_off {
85cb7b6606SZiyang Xuan 	char name[RTE_ETH_XSTATS_NAME_SIZE];
86cb7b6606SZiyang Xuan 	u32  offset;
87cb7b6606SZiyang Xuan };
88cb7b6606SZiyang Xuan 
89cb7b6606SZiyang Xuan #define HINIC_FUNC_STAT(_stat_item) {	\
90cb7b6606SZiyang Xuan 	.name = #_stat_item, \
91cb7b6606SZiyang Xuan 	.offset = offsetof(struct hinic_vport_stats, _stat_item) \
92cb7b6606SZiyang Xuan }
93cb7b6606SZiyang Xuan 
94cb7b6606SZiyang Xuan #define HINIC_PORT_STAT(_stat_item) { \
95cb7b6606SZiyang Xuan 	.name = #_stat_item, \
96cb7b6606SZiyang Xuan 	.offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
97cb7b6606SZiyang Xuan }
98cb7b6606SZiyang Xuan 
99cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_vport_stats_strings[] = {
100cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_unicast_pkts_vport),
101cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_unicast_bytes_vport),
102cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_multicast_pkts_vport),
103cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_multicast_bytes_vport),
104cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_broadcast_pkts_vport),
105cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_broadcast_bytes_vport),
106cb7b6606SZiyang Xuan 
107cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_unicast_pkts_vport),
108cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_unicast_bytes_vport),
109cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_multicast_pkts_vport),
110cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_multicast_bytes_vport),
111cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_broadcast_pkts_vport),
112cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_broadcast_bytes_vport),
113cb7b6606SZiyang Xuan 
114cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_discard_vport),
115cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_discard_vport),
116cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_err_vport),
117cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_err_vport),
118cb7b6606SZiyang Xuan };
119cb7b6606SZiyang Xuan 
120cb7b6606SZiyang Xuan #define HINIC_VPORT_XSTATS_NUM (sizeof(hinic_vport_stats_strings) / \
121cb7b6606SZiyang Xuan 		sizeof(hinic_vport_stats_strings[0]))
122cb7b6606SZiyang Xuan 
123cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_phyport_stats_strings[] = {
124cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_total_pkt_num),
125cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_total_oct_num),
126cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_bad_pkt_num),
127cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_bad_oct_num),
128cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_good_pkt_num),
129cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_good_oct_num),
130cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_uni_pkt_num),
131cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_multi_pkt_num),
132cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_broad_pkt_num),
133cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_total_pkt_num),
134cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_total_oct_num),
135cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_bad_pkt_num),
136cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_bad_oct_num),
137cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_good_pkt_num),
138cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_good_oct_num),
139cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_uni_pkt_num),
140cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_multi_pkt_num),
141cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_broad_pkt_num),
142cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_fragment_pkt_num),
143cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_undersize_pkt_num),
144cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_undermin_pkt_num),
145cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_64_oct_pkt_num),
146cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),
147cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),
148cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),
149cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),
150cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),
151cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),
152cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),
153cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),
154cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),
155cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),
156cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),
157cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),
158cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),
159cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_oversize_pkt_num),
160cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_jabber_pkt_num),
161cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_mac_pause_num),
162cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pkt_num),
163cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),
164cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),
165cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),
166cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),
167cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),
168cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),
169cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),
170cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),
171cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_mac_control_pkt_num),
172cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_sym_err_pkt_num),
173cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num),
174cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num),
175cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),
176cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_fragment_pkt_num),
177cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_undersize_pkt_num),
178cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_undermin_pkt_num),
179cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_64_oct_pkt_num),
180cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),
181cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),
182cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),
183cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),
184cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),
185cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),
186cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),
187cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),
188cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),
189cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),
190cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),
191cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),
192cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),
193cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_oversize_pkt_num),
194cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_trans_jabber_pkt_num),
195cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_mac_pause_num),
196cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pkt_num),
197cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),
198cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),
199cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),
200cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),
201cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),
202cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),
203cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),
204cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),
205cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_mac_control_pkt_num),
206cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_err_all_pkt_num),
207cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num),
208cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),
209cb7b6606SZiyang Xuan };
210cb7b6606SZiyang Xuan 
211cb7b6606SZiyang Xuan #define HINIC_PHYPORT_XSTATS_NUM (sizeof(hinic_phyport_stats_strings) / \
212cb7b6606SZiyang Xuan 		sizeof(hinic_phyport_stats_strings[0]))
213cb7b6606SZiyang Xuan 
214cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_rxq_stats_strings[] = {
215cb7b6606SZiyang Xuan 	{"rx_nombuf", offsetof(struct hinic_rxq_stats, rx_nombuf)},
216cb7b6606SZiyang Xuan 	{"burst_pkt", offsetof(struct hinic_rxq_stats, burst_pkts)},
217cb7b6606SZiyang Xuan };
218cb7b6606SZiyang Xuan 
219cb7b6606SZiyang Xuan #define HINIC_RXQ_XSTATS_NUM (sizeof(hinic_rxq_stats_strings) / \
220cb7b6606SZiyang Xuan 		sizeof(hinic_rxq_stats_strings[0]))
221cb7b6606SZiyang Xuan 
222cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_txq_stats_strings[] = {
223cb7b6606SZiyang Xuan 	{"tx_busy", offsetof(struct hinic_txq_stats, tx_busy)},
224cb7b6606SZiyang Xuan 	{"offload_errors", offsetof(struct hinic_txq_stats, off_errs)},
225cb7b6606SZiyang Xuan 	{"copy_pkts", offsetof(struct hinic_txq_stats, cpy_pkts)},
226cb7b6606SZiyang Xuan 	{"rl_drop", offsetof(struct hinic_txq_stats, rl_drop)},
227cb7b6606SZiyang Xuan 	{"burst_pkts", offsetof(struct hinic_txq_stats, burst_pkts)},
22854faba22SXiaoyun Wang 	{"sge_len0", offsetof(struct hinic_txq_stats, sge_len0)},
22954faba22SXiaoyun Wang 	{"mbuf_null", offsetof(struct hinic_txq_stats, mbuf_null)},
230cb7b6606SZiyang Xuan };
231cb7b6606SZiyang Xuan 
232cb7b6606SZiyang Xuan #define HINIC_TXQ_XSTATS_NUM (sizeof(hinic_txq_stats_strings) / \
233cb7b6606SZiyang Xuan 		sizeof(hinic_txq_stats_strings[0]))
234cb7b6606SZiyang Xuan 
235cb7b6606SZiyang Xuan static int hinic_xstats_calc_num(struct hinic_nic_dev *nic_dev)
236cb7b6606SZiyang Xuan {
2376691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev)) {
2386691acefSXiaoyun Wang 		return (HINIC_VPORT_XSTATS_NUM +
2396691acefSXiaoyun Wang 			HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq +
2406691acefSXiaoyun Wang 			HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq);
2416691acefSXiaoyun Wang 	} else {
242cb7b6606SZiyang Xuan 		return (HINIC_VPORT_XSTATS_NUM +
243cb7b6606SZiyang Xuan 			HINIC_PHYPORT_XSTATS_NUM +
244cb7b6606SZiyang Xuan 			HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq +
245cb7b6606SZiyang Xuan 			HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq);
246cb7b6606SZiyang Xuan 	}
2476691acefSXiaoyun Wang }
248cb7b6606SZiyang Xuan 
2491d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_rx_desc_lim = {
2501d09792aSZiyang Xuan 	.nb_max = HINIC_MAX_QUEUE_DEPTH,
2511d09792aSZiyang Xuan 	.nb_min = HINIC_MIN_QUEUE_DEPTH,
2521d09792aSZiyang Xuan 	.nb_align = HINIC_RXD_ALIGN,
2531d09792aSZiyang Xuan };
2541d09792aSZiyang Xuan 
2551d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_tx_desc_lim = {
2561d09792aSZiyang Xuan 	.nb_max = HINIC_MAX_QUEUE_DEPTH,
2571d09792aSZiyang Xuan 	.nb_min = HINIC_MIN_QUEUE_DEPTH,
2581d09792aSZiyang Xuan 	.nb_align = HINIC_TXD_ALIGN,
2591d09792aSZiyang Xuan };
2601d09792aSZiyang Xuan 
261fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask);
2622c473729SZiyang Xuan 
2631d09792aSZiyang Xuan /**
26464727024SZiyang Xuan  * Interrupt handler triggered by NIC  for handling
26564727024SZiyang Xuan  * specific event.
26664727024SZiyang Xuan  *
26764727024SZiyang Xuan  * @param: The address of parameter (struct rte_eth_dev *) regsitered before.
268c3ba1f0fSXiaoyun Wang  */
26964727024SZiyang Xuan static void hinic_dev_interrupt_handler(void *param)
27064727024SZiyang Xuan {
27164727024SZiyang Xuan 	struct rte_eth_dev *dev = param;
27264727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
27364727024SZiyang Xuan 
2740371535dSJoyce Kong 	if (!rte_bit_relaxed_get32(HINIC_DEV_INTR_EN, &nic_dev->dev_status)) {
27564727024SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Device's interrupt is disabled, ignore interrupt event, dev_name: %s, port_id: %d",
27664727024SZiyang Xuan 			    nic_dev->proc_dev_name, dev->data->port_id);
27764727024SZiyang Xuan 		return;
27864727024SZiyang Xuan 	}
27964727024SZiyang Xuan 
28064727024SZiyang Xuan 	/* aeq0 msg handler */
28164727024SZiyang Xuan 	hinic_dev_handle_aeq_event(nic_dev->hwdev, param);
28264727024SZiyang Xuan }
28364727024SZiyang Xuan 
28464727024SZiyang Xuan /**
28564727024SZiyang Xuan  * Ethernet device configuration.
28664727024SZiyang Xuan  *
28764727024SZiyang Xuan  * Prepare the driver for a given number of TX and RX queues, mtu size
28864727024SZiyang Xuan  * and configure RSS.
28964727024SZiyang Xuan  *
29064727024SZiyang Xuan  * @param dev
29164727024SZiyang Xuan  *   Pointer to Ethernet device structure.
29264727024SZiyang Xuan  *
29364727024SZiyang Xuan  * @return
29464727024SZiyang Xuan  *   0 on success, negative error value otherwise.
29564727024SZiyang Xuan  */
29664727024SZiyang Xuan static int hinic_dev_configure(struct rte_eth_dev *dev)
29764727024SZiyang Xuan {
29864727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
29964727024SZiyang Xuan 	struct hinic_nic_io *nic_io;
30064727024SZiyang Xuan 	int err;
30164727024SZiyang Xuan 
30264727024SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
30364727024SZiyang Xuan 	nic_io = nic_dev->hwdev->nic_io;
30464727024SZiyang Xuan 
30564727024SZiyang Xuan 	nic_dev->num_sq =  dev->data->nb_tx_queues;
30664727024SZiyang Xuan 	nic_dev->num_rq = dev->data->nb_rx_queues;
30764727024SZiyang Xuan 
30864727024SZiyang Xuan 	nic_io->num_sqs =  dev->data->nb_tx_queues;
30964727024SZiyang Xuan 	nic_io->num_rqs = dev->data->nb_rx_queues;
31064727024SZiyang Xuan 
31164727024SZiyang Xuan 	/* queue pair is max_num(sq, rq) */
31264727024SZiyang Xuan 	nic_dev->num_qps = (nic_dev->num_sq > nic_dev->num_rq) ?
31364727024SZiyang Xuan 			nic_dev->num_sq : nic_dev->num_rq;
31464727024SZiyang Xuan 	nic_io->num_qps = nic_dev->num_qps;
31564727024SZiyang Xuan 
31664727024SZiyang Xuan 	if (nic_dev->num_qps > nic_io->max_qps) {
31764727024SZiyang Xuan 		PMD_DRV_LOG(ERR,
31864727024SZiyang Xuan 			"Queue number out of range, get queue_num:%d, max_queue_num:%d",
31964727024SZiyang Xuan 			nic_dev->num_qps, nic_io->max_qps);
32064727024SZiyang Xuan 		return -EINVAL;
32164727024SZiyang Xuan 	}
32264727024SZiyang Xuan 
32373fb89ddSAndrew Rybchenko 	if (dev->data->dev_conf.rxmode.mq_mode & ETH_MQ_RX_RSS_FLAG)
3248b945a7fSPavan Nikhilesh 		dev->data->dev_conf.rxmode.offloads |= DEV_RX_OFFLOAD_RSS_HASH;
3258b945a7fSPavan Nikhilesh 
32664727024SZiyang Xuan 	/* mtu size is 256~9600 */
32764727024SZiyang Xuan 	if (dev->data->dev_conf.rxmode.max_rx_pkt_len < HINIC_MIN_FRAME_SIZE ||
32864727024SZiyang Xuan 	    dev->data->dev_conf.rxmode.max_rx_pkt_len >
32964727024SZiyang Xuan 	    HINIC_MAX_JUMBO_FRAME_SIZE) {
33064727024SZiyang Xuan 		PMD_DRV_LOG(ERR,
33164727024SZiyang Xuan 			"Max rx pkt len out of range, get max_rx_pkt_len:%d, "
33264727024SZiyang Xuan 			"expect between %d and %d",
33364727024SZiyang Xuan 			dev->data->dev_conf.rxmode.max_rx_pkt_len,
33464727024SZiyang Xuan 			HINIC_MIN_FRAME_SIZE, HINIC_MAX_JUMBO_FRAME_SIZE);
33564727024SZiyang Xuan 		return -EINVAL;
33664727024SZiyang Xuan 	}
33764727024SZiyang Xuan 
33864727024SZiyang Xuan 	nic_dev->mtu_size =
33964727024SZiyang Xuan 		HINIC_PKTLEN_TO_MTU(dev->data->dev_conf.rxmode.max_rx_pkt_len);
34064727024SZiyang Xuan 
34164727024SZiyang Xuan 	/* rss template */
34264727024SZiyang Xuan 	err = hinic_config_mq_mode(dev, TRUE);
34364727024SZiyang Xuan 	if (err) {
34464727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Config multi-queue failed");
34564727024SZiyang Xuan 		return err;
34664727024SZiyang Xuan 	}
34764727024SZiyang Xuan 
348fdba3bf1SXiaoyun Wang 	/* init vlan offoad */
349fdba3bf1SXiaoyun Wang 	err = hinic_vlan_offload_set(dev,
350fdba3bf1SXiaoyun Wang 				ETH_VLAN_STRIP_MASK | ETH_VLAN_FILTER_MASK);
351fdba3bf1SXiaoyun Wang 	if (err) {
3524f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Initialize vlan filter and strip failed");
353fdba3bf1SXiaoyun Wang 		(void)hinic_config_mq_mode(dev, FALSE);
354fdba3bf1SXiaoyun Wang 		return err;
355fdba3bf1SXiaoyun Wang 	}
356fdba3bf1SXiaoyun Wang 
3571742421bSXiaoyun Wang 	/* clear fdir filter flag in function table */
3581742421bSXiaoyun Wang 	hinic_free_fdir_filter(nic_dev);
3591742421bSXiaoyun Wang 
36064727024SZiyang Xuan 	return HINIC_OK;
36164727024SZiyang Xuan }
36264727024SZiyang Xuan 
36364727024SZiyang Xuan /**
3642c473729SZiyang Xuan  * DPDK callback to create the receive queue.
3652c473729SZiyang Xuan  *
3662c473729SZiyang Xuan  * @param dev
3672c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
3682c473729SZiyang Xuan  * @param queue_idx
3692c473729SZiyang Xuan  *   RX queue index.
3702c473729SZiyang Xuan  * @param nb_desc
3712c473729SZiyang Xuan  *   Number of descriptors for receive queue.
3722c473729SZiyang Xuan  * @param socket_id
3732c473729SZiyang Xuan  *   NUMA socket on which memory must be allocated.
3742c473729SZiyang Xuan  * @param rx_conf
3752c473729SZiyang Xuan  *   Thresholds parameters (unused_).
3762c473729SZiyang Xuan  * @param mp
3772c473729SZiyang Xuan  *   Memory pool for buffer allocations.
3782c473729SZiyang Xuan  *
3792c473729SZiyang Xuan  * @return
3802c473729SZiyang Xuan  *   0 on success, negative error value otherwise.
3812c473729SZiyang Xuan  */
3822c473729SZiyang Xuan static int hinic_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
3832c473729SZiyang Xuan 			 uint16_t nb_desc, unsigned int socket_id,
3842c473729SZiyang Xuan 			 __rte_unused const struct rte_eth_rxconf *rx_conf,
3852c473729SZiyang Xuan 			 struct rte_mempool *mp)
3862c473729SZiyang Xuan {
3872c473729SZiyang Xuan 	int rc;
3882c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
3892c473729SZiyang Xuan 	struct hinic_hwdev *hwdev;
3902c473729SZiyang Xuan 	struct hinic_rxq *rxq;
3912c473729SZiyang Xuan 	u16 rq_depth, rx_free_thresh;
3922c473729SZiyang Xuan 	u32 buf_size;
3932c473729SZiyang Xuan 
3942c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
3952c473729SZiyang Xuan 	hwdev = nic_dev->hwdev;
3962c473729SZiyang Xuan 
3972c473729SZiyang Xuan 	/* queue depth must be power of 2, otherwise will be aligned up */
3982c473729SZiyang Xuan 	rq_depth = (nb_desc & (nb_desc - 1)) ?
3992c473729SZiyang Xuan 		((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc;
4002c473729SZiyang Xuan 
4012c473729SZiyang Xuan 	/*
4022c473729SZiyang Xuan 	 * Validate number of receive descriptors.
4032c473729SZiyang Xuan 	 * It must not exceed hardware maximum and minimum.
4042c473729SZiyang Xuan 	 */
4052c473729SZiyang Xuan 	if (rq_depth > HINIC_MAX_QUEUE_DEPTH ||
4062c473729SZiyang Xuan 		rq_depth < HINIC_MIN_QUEUE_DEPTH) {
4072c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "RX queue depth is out of range from %d to %d, (nb_desc=%d, q_depth=%d, port=%d queue=%d)",
4082c473729SZiyang Xuan 			    HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH,
4092c473729SZiyang Xuan 			    (int)nb_desc, (int)rq_depth,
4102c473729SZiyang Xuan 			    (int)dev->data->port_id, (int)queue_idx);
4112c473729SZiyang Xuan 		return -EINVAL;
4122c473729SZiyang Xuan 	}
4132c473729SZiyang Xuan 
4142c473729SZiyang Xuan 	/*
4152c473729SZiyang Xuan 	 * The RX descriptor ring will be cleaned after rxq->rx_free_thresh
4162c473729SZiyang Xuan 	 * descriptors are used or if the number of descriptors required
4172c473729SZiyang Xuan 	 * to transmit a packet is greater than the number of free RX
4182c473729SZiyang Xuan 	 * descriptors.
4192c473729SZiyang Xuan 	 * The following constraints must be satisfied:
4202c473729SZiyang Xuan 	 *  rx_free_thresh must be greater than 0.
4212c473729SZiyang Xuan 	 *  rx_free_thresh must be less than the size of the ring minus 1.
4222c473729SZiyang Xuan 	 * When set to zero use default values.
4232c473729SZiyang Xuan 	 */
4242c473729SZiyang Xuan 	rx_free_thresh = (u16)((rx_conf->rx_free_thresh) ?
4252c473729SZiyang Xuan 			rx_conf->rx_free_thresh : HINIC_DEFAULT_RX_FREE_THRESH);
4262c473729SZiyang Xuan 	if (rx_free_thresh >= (rq_depth - 1)) {
4272c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "rx_free_thresh must be less than the number of RX descriptors minus 1. (rx_free_thresh=%u port=%d queue=%d)",
4282c473729SZiyang Xuan 			    (unsigned int)rx_free_thresh,
4292c473729SZiyang Xuan 			    (int)dev->data->port_id,
4302c473729SZiyang Xuan 			    (int)queue_idx);
4312c473729SZiyang Xuan 		return -EINVAL;
4322c473729SZiyang Xuan 	}
4332c473729SZiyang Xuan 
4342c473729SZiyang Xuan 	rxq = rte_zmalloc_socket("hinic_rx_queue", sizeof(struct hinic_rxq),
4352c473729SZiyang Xuan 				 RTE_CACHE_LINE_SIZE, socket_id);
4362c473729SZiyang Xuan 	if (!rxq) {
4372c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate rxq[%d] failed, dev_name: %s",
4382c473729SZiyang Xuan 			    queue_idx, dev->data->name);
4392c473729SZiyang Xuan 		return -ENOMEM;
4402c473729SZiyang Xuan 	}
4412c473729SZiyang Xuan 	nic_dev->rxqs[queue_idx] = rxq;
4422c473729SZiyang Xuan 
4432c473729SZiyang Xuan 	/* alloc rx sq hw wqe page */
4441b7b9f17SXiaoyun Wang 	rc = hinic_create_rq(hwdev, queue_idx, rq_depth, socket_id);
4452c473729SZiyang Xuan 	if (rc) {
4462c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Create rxq[%d] failed, dev_name: %s, rq_depth: %d",
4472c473729SZiyang Xuan 			    queue_idx, dev->data->name, rq_depth);
4482c473729SZiyang Xuan 		goto ceate_rq_fail;
4492c473729SZiyang Xuan 	}
4502c473729SZiyang Xuan 
4512c473729SZiyang Xuan 	/* mbuf pool must be assigned before setup rx resources */
4522c473729SZiyang Xuan 	rxq->mb_pool = mp;
4532c473729SZiyang Xuan 
4542c473729SZiyang Xuan 	rc =
4552c473729SZiyang Xuan 	hinic_convert_rx_buf_size(rte_pktmbuf_data_room_size(rxq->mb_pool) -
4562c473729SZiyang Xuan 				  RTE_PKTMBUF_HEADROOM, &buf_size);
4572c473729SZiyang Xuan 	if (rc) {
4582c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Adjust buf size failed, dev_name: %s",
4592c473729SZiyang Xuan 			    dev->data->name);
4602c473729SZiyang Xuan 		goto adjust_bufsize_fail;
4612c473729SZiyang Xuan 	}
4622c473729SZiyang Xuan 
4632c473729SZiyang Xuan 	/* rx queue info, rearm control */
4642c473729SZiyang Xuan 	rxq->wq = &hwdev->nic_io->rq_wq[queue_idx];
4652c473729SZiyang Xuan 	rxq->pi_virt_addr = hwdev->nic_io->qps[queue_idx].rq.pi_virt_addr;
4662c473729SZiyang Xuan 	rxq->nic_dev = nic_dev;
4672c473729SZiyang Xuan 	rxq->q_id = queue_idx;
4682c473729SZiyang Xuan 	rxq->q_depth = rq_depth;
4692c473729SZiyang Xuan 	rxq->buf_len = (u16)buf_size;
4702c473729SZiyang Xuan 	rxq->rx_free_thresh = rx_free_thresh;
4711b7b9f17SXiaoyun Wang 	rxq->socket_id = socket_id;
4722c473729SZiyang Xuan 
4732c473729SZiyang Xuan 	/* the last point cant do mbuf rearm in bulk */
4742c473729SZiyang Xuan 	rxq->rxinfo_align_end = rxq->q_depth - rxq->rx_free_thresh;
4752c473729SZiyang Xuan 
4762c473729SZiyang Xuan 	/* device port identifier */
4772c473729SZiyang Xuan 	rxq->port_id = dev->data->port_id;
4782c473729SZiyang Xuan 
4792c473729SZiyang Xuan 	/* alloc rx_cqe and prepare rq_wqe */
4802c473729SZiyang Xuan 	rc = hinic_setup_rx_resources(rxq);
4812c473729SZiyang Xuan 	if (rc) {
4822c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Setup rxq[%d] rx_resources failed, dev_name: %s",
4832c473729SZiyang Xuan 			    queue_idx, dev->data->name);
4842c473729SZiyang Xuan 		goto setup_rx_res_err;
4852c473729SZiyang Xuan 	}
4862c473729SZiyang Xuan 
4872c473729SZiyang Xuan 	/* record nic_dev rxq in rte_eth rx_queues */
4882c473729SZiyang Xuan 	dev->data->rx_queues[queue_idx] = rxq;
4892c473729SZiyang Xuan 
4902c473729SZiyang Xuan 	return 0;
4912c473729SZiyang Xuan 
4922c473729SZiyang Xuan setup_rx_res_err:
4932c473729SZiyang Xuan adjust_bufsize_fail:
4942c473729SZiyang Xuan 	hinic_destroy_rq(hwdev, queue_idx);
4952c473729SZiyang Xuan 
4962c473729SZiyang Xuan ceate_rq_fail:
4972c473729SZiyang Xuan 	rte_free(rxq);
4982c473729SZiyang Xuan 
4992c473729SZiyang Xuan 	return rc;
5002c473729SZiyang Xuan }
5012c473729SZiyang Xuan 
5022c473729SZiyang Xuan static void hinic_reset_rx_queue(struct rte_eth_dev *dev)
5032c473729SZiyang Xuan {
5042c473729SZiyang Xuan 	struct hinic_rxq *rxq;
5052c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
5062c473729SZiyang Xuan 	int q_id = 0;
5072c473729SZiyang Xuan 
5082c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
5092c473729SZiyang Xuan 
5102c473729SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
5112c473729SZiyang Xuan 		rxq = dev->data->rx_queues[q_id];
5122c473729SZiyang Xuan 
5132c473729SZiyang Xuan 		rxq->wq->cons_idx = 0;
5142c473729SZiyang Xuan 		rxq->wq->prod_idx = 0;
5152c473729SZiyang Xuan 		rxq->wq->delta = rxq->q_depth;
5162c473729SZiyang Xuan 		rxq->wq->mask = rxq->q_depth - 1;
5172c473729SZiyang Xuan 
5182c473729SZiyang Xuan 		/* alloc mbuf to rq */
5192c473729SZiyang Xuan 		hinic_rx_alloc_pkts(rxq);
5202c473729SZiyang Xuan 	}
5212c473729SZiyang Xuan }
5222c473729SZiyang Xuan 
5232c473729SZiyang Xuan /**
5242c473729SZiyang Xuan  * DPDK callback to configure the transmit queue.
5252c473729SZiyang Xuan  *
5262c473729SZiyang Xuan  * @param dev
5272c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
5282c473729SZiyang Xuan  * @param queue_idx
5292c473729SZiyang Xuan  *   Transmit queue index.
5302c473729SZiyang Xuan  * @param nb_desc
5312c473729SZiyang Xuan  *   Number of descriptors for transmit queue.
5322c473729SZiyang Xuan  * @param socket_id
5332c473729SZiyang Xuan  *   NUMA socket on which memory must be allocated.
5342c473729SZiyang Xuan  * @param tx_conf
5352c473729SZiyang Xuan  *   Tx queue configuration parameters.
5362c473729SZiyang Xuan  *
5372c473729SZiyang Xuan  * @return
5382c473729SZiyang Xuan  *   0 on success, negative error value otherwise.
5392c473729SZiyang Xuan  */
5402c473729SZiyang Xuan static int hinic_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
5412c473729SZiyang Xuan 			 uint16_t nb_desc, unsigned int socket_id,
5422c473729SZiyang Xuan 			 __rte_unused const struct rte_eth_txconf *tx_conf)
5432c473729SZiyang Xuan {
5442c473729SZiyang Xuan 	int rc;
5452c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
5462c473729SZiyang Xuan 	struct hinic_hwdev *hwdev;
5472c473729SZiyang Xuan 	struct hinic_txq *txq;
5482c473729SZiyang Xuan 	u16 sq_depth, tx_free_thresh;
5492c473729SZiyang Xuan 
5502c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
5512c473729SZiyang Xuan 	hwdev = nic_dev->hwdev;
5522c473729SZiyang Xuan 
5532c473729SZiyang Xuan 	/* queue depth must be power of 2, otherwise will be aligned up */
5542c473729SZiyang Xuan 	sq_depth = (nb_desc & (nb_desc - 1)) ?
5552c473729SZiyang Xuan 			((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc;
5562c473729SZiyang Xuan 
5572c473729SZiyang Xuan 	/*
5582c473729SZiyang Xuan 	 * Validate number of transmit descriptors.
5592c473729SZiyang Xuan 	 * It must not exceed hardware maximum and minimum.
5602c473729SZiyang Xuan 	 */
5612c473729SZiyang Xuan 	if (sq_depth > HINIC_MAX_QUEUE_DEPTH ||
5622c473729SZiyang Xuan 		sq_depth < HINIC_MIN_QUEUE_DEPTH) {
5632c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "TX queue depth is out of range from %d to %d, (nb_desc=%d, q_depth=%d, port=%d queue=%d)",
5642c473729SZiyang Xuan 			  HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH,
5652c473729SZiyang Xuan 			  (int)nb_desc, (int)sq_depth,
5662c473729SZiyang Xuan 			  (int)dev->data->port_id, (int)queue_idx);
5672c473729SZiyang Xuan 		return -EINVAL;
5682c473729SZiyang Xuan 	}
5692c473729SZiyang Xuan 
5702c473729SZiyang Xuan 	/*
5712c473729SZiyang Xuan 	 * The TX descriptor ring will be cleaned after txq->tx_free_thresh
5722c473729SZiyang Xuan 	 * descriptors are used or if the number of descriptors required
5732c473729SZiyang Xuan 	 * to transmit a packet is greater than the number of free TX
5742c473729SZiyang Xuan 	 * descriptors.
5752c473729SZiyang Xuan 	 * The following constraints must be satisfied:
5762c473729SZiyang Xuan 	 *  tx_free_thresh must be greater than 0.
5772c473729SZiyang Xuan 	 *  tx_free_thresh must be less than the size of the ring minus 1.
5782c473729SZiyang Xuan 	 * When set to zero use default values.
5792c473729SZiyang Xuan 	 */
5802c473729SZiyang Xuan 	tx_free_thresh = (u16)((tx_conf->tx_free_thresh) ?
5812c473729SZiyang Xuan 			tx_conf->tx_free_thresh : HINIC_DEFAULT_TX_FREE_THRESH);
5822c473729SZiyang Xuan 	if (tx_free_thresh >= (sq_depth - 1)) {
5832c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "tx_free_thresh must be less than the number of TX descriptors minus 1. (tx_free_thresh=%u port=%d queue=%d)",
5842c473729SZiyang Xuan 			(unsigned int)tx_free_thresh, (int)dev->data->port_id,
5852c473729SZiyang Xuan 			(int)queue_idx);
5862c473729SZiyang Xuan 		return -EINVAL;
5872c473729SZiyang Xuan 	}
5882c473729SZiyang Xuan 
5892c473729SZiyang Xuan 	txq = rte_zmalloc_socket("hinic_tx_queue", sizeof(struct hinic_txq),
5902c473729SZiyang Xuan 				 RTE_CACHE_LINE_SIZE, socket_id);
5912c473729SZiyang Xuan 	if (!txq) {
5922c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate txq[%d] failed, dev_name: %s",
5932c473729SZiyang Xuan 			    queue_idx, dev->data->name);
5942c473729SZiyang Xuan 		return -ENOMEM;
5952c473729SZiyang Xuan 	}
5962c473729SZiyang Xuan 	nic_dev->txqs[queue_idx] = txq;
5972c473729SZiyang Xuan 
5982c473729SZiyang Xuan 	/* alloc tx sq hw wqepage */
5991b7b9f17SXiaoyun Wang 	rc = hinic_create_sq(hwdev, queue_idx, sq_depth, socket_id);
6002c473729SZiyang Xuan 	if (rc) {
6012c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Create txq[%d] failed, dev_name: %s, sq_depth: %d",
6022c473729SZiyang Xuan 			    queue_idx, dev->data->name, sq_depth);
6032c473729SZiyang Xuan 		goto create_sq_fail;
6042c473729SZiyang Xuan 	}
6052c473729SZiyang Xuan 
6062c473729SZiyang Xuan 	txq->q_id = queue_idx;
6072c473729SZiyang Xuan 	txq->q_depth = sq_depth;
6082c473729SZiyang Xuan 	txq->port_id = dev->data->port_id;
6092c473729SZiyang Xuan 	txq->tx_free_thresh = tx_free_thresh;
6102c473729SZiyang Xuan 	txq->nic_dev = nic_dev;
6112c473729SZiyang Xuan 	txq->wq = &hwdev->nic_io->sq_wq[queue_idx];
6122c473729SZiyang Xuan 	txq->sq = &hwdev->nic_io->qps[queue_idx].sq;
6132c473729SZiyang Xuan 	txq->cons_idx_addr = hwdev->nic_io->qps[queue_idx].sq.cons_idx_addr;
6142c473729SZiyang Xuan 	txq->sq_head_addr = HINIC_GET_WQ_HEAD(txq);
6152c473729SZiyang Xuan 	txq->sq_bot_sge_addr = HINIC_GET_WQ_TAIL(txq) -
6162c473729SZiyang Xuan 					sizeof(struct hinic_sq_bufdesc);
6172c473729SZiyang Xuan 	txq->cos = nic_dev->default_cos;
6181b7b9f17SXiaoyun Wang 	txq->socket_id = socket_id;
6192c473729SZiyang Xuan 
6202c473729SZiyang Xuan 	/* alloc software txinfo */
6212c473729SZiyang Xuan 	rc = hinic_setup_tx_resources(txq);
6222c473729SZiyang Xuan 	if (rc) {
6232c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Setup txq[%d] tx_resources failed, dev_name: %s",
6242c473729SZiyang Xuan 			    queue_idx, dev->data->name);
6252c473729SZiyang Xuan 		goto setup_tx_res_fail;
6262c473729SZiyang Xuan 	}
6272c473729SZiyang Xuan 
6282c473729SZiyang Xuan 	/* record nic_dev txq in rte_eth tx_queues */
6292c473729SZiyang Xuan 	dev->data->tx_queues[queue_idx] = txq;
6302c473729SZiyang Xuan 
6312c473729SZiyang Xuan 	return HINIC_OK;
6322c473729SZiyang Xuan 
6332c473729SZiyang Xuan setup_tx_res_fail:
6342c473729SZiyang Xuan 	hinic_destroy_sq(hwdev, queue_idx);
6352c473729SZiyang Xuan 
6362c473729SZiyang Xuan create_sq_fail:
6372c473729SZiyang Xuan 	rte_free(txq);
6382c473729SZiyang Xuan 
6392c473729SZiyang Xuan 	return rc;
6402c473729SZiyang Xuan }
6412c473729SZiyang Xuan 
6422c473729SZiyang Xuan static void hinic_reset_tx_queue(struct rte_eth_dev *dev)
6432c473729SZiyang Xuan {
6442c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
6452c473729SZiyang Xuan 	struct hinic_txq *txq;
6462c473729SZiyang Xuan 	struct hinic_nic_io *nic_io;
6472c473729SZiyang Xuan 	struct hinic_hwdev *hwdev;
6482c473729SZiyang Xuan 	volatile u32 *ci_addr;
6492c473729SZiyang Xuan 	int q_id = 0;
6502c473729SZiyang Xuan 
6512c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
6522c473729SZiyang Xuan 	hwdev = nic_dev->hwdev;
6532c473729SZiyang Xuan 	nic_io = hwdev->nic_io;
6542c473729SZiyang Xuan 
6552c473729SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_sq; q_id++) {
6562c473729SZiyang Xuan 		txq = dev->data->tx_queues[q_id];
6572c473729SZiyang Xuan 
6582c473729SZiyang Xuan 		txq->wq->cons_idx = 0;
6592c473729SZiyang Xuan 		txq->wq->prod_idx = 0;
6602c473729SZiyang Xuan 		txq->wq->delta = txq->q_depth;
6612c473729SZiyang Xuan 		txq->wq->mask  = txq->q_depth - 1;
6622c473729SZiyang Xuan 
6632c473729SZiyang Xuan 		/* clear hardware ci */
6642c473729SZiyang Xuan 		ci_addr = (volatile u32 *)HINIC_CI_VADDR(nic_io->ci_vaddr_base,
6652c473729SZiyang Xuan 							q_id);
6662c473729SZiyang Xuan 		*ci_addr = 0;
6672c473729SZiyang Xuan 	}
6682c473729SZiyang Xuan }
6692c473729SZiyang Xuan 
6702c473729SZiyang Xuan /**
6711d09792aSZiyang Xuan  * Get link speed from NIC.
6721d09792aSZiyang Xuan  *
6731d09792aSZiyang Xuan  * @param dev
6741d09792aSZiyang Xuan  *   Pointer to Ethernet device structure.
6751d09792aSZiyang Xuan  * @param speed_capa
6761d09792aSZiyang Xuan  *   Pointer to link speed structure.
6771d09792aSZiyang Xuan  */
6781d09792aSZiyang Xuan static void hinic_get_speed_capa(struct rte_eth_dev *dev, uint32_t *speed_capa)
6791d09792aSZiyang Xuan {
6801d09792aSZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
6811d09792aSZiyang Xuan 	u32 supported_link, advertised_link;
6821d09792aSZiyang Xuan 	int err;
6831d09792aSZiyang Xuan 
6841d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_1G	(1U << HINIC_GE_BASE_KX)
6851d09792aSZiyang Xuan 
6861d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_10G	(1U << HINIC_10GE_BASE_KR)
6871d09792aSZiyang Xuan 
6881d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_25G	((1U << HINIC_25GE_BASE_KR_S) | \
6891d09792aSZiyang Xuan 					(1U << HINIC_25GE_BASE_CR_S) | \
6901d09792aSZiyang Xuan 					(1U << HINIC_25GE_BASE_KR) | \
6911d09792aSZiyang Xuan 					(1U << HINIC_25GE_BASE_CR))
6921d09792aSZiyang Xuan 
6931d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_40G	((1U << HINIC_40GE_BASE_KR4) | \
6941d09792aSZiyang Xuan 					(1U << HINIC_40GE_BASE_CR4))
6951d09792aSZiyang Xuan 
6961d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_100G	((1U << HINIC_100GE_BASE_KR4) | \
6971d09792aSZiyang Xuan 					(1U << HINIC_100GE_BASE_CR4))
6981d09792aSZiyang Xuan 
6991d09792aSZiyang Xuan 	err = hinic_get_link_mode(nic_dev->hwdev,
7001d09792aSZiyang Xuan 				  &supported_link, &advertised_link);
7011d09792aSZiyang Xuan 	if (err || supported_link == HINIC_SUPPORTED_UNKNOWN ||
7021d09792aSZiyang Xuan 	    advertised_link == HINIC_SUPPORTED_UNKNOWN) {
7031d09792aSZiyang Xuan 		PMD_DRV_LOG(WARNING, "Get speed capability info failed, device: %s, port_id: %u",
7041d09792aSZiyang Xuan 			  nic_dev->proc_dev_name, dev->data->port_id);
7051d09792aSZiyang Xuan 	} else {
7061d09792aSZiyang Xuan 		*speed_capa = 0;
7071d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_1G))
7081d09792aSZiyang Xuan 			*speed_capa |= ETH_LINK_SPEED_1G;
7091d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_10G))
7101d09792aSZiyang Xuan 			*speed_capa |= ETH_LINK_SPEED_10G;
7111d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_25G))
7121d09792aSZiyang Xuan 			*speed_capa |= ETH_LINK_SPEED_25G;
7131d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_40G))
7141d09792aSZiyang Xuan 			*speed_capa |= ETH_LINK_SPEED_40G;
7151d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_100G))
7161d09792aSZiyang Xuan 			*speed_capa |= ETH_LINK_SPEED_100G;
7171d09792aSZiyang Xuan 	}
7181d09792aSZiyang Xuan }
7191d09792aSZiyang Xuan 
7201d09792aSZiyang Xuan /**
7211d09792aSZiyang Xuan  * DPDK callback to get information about the device.
7221d09792aSZiyang Xuan  *
7231d09792aSZiyang Xuan  * @param dev
7241d09792aSZiyang Xuan  *   Pointer to Ethernet device structure.
7251d09792aSZiyang Xuan  * @param info
7261d09792aSZiyang Xuan  *   Pointer to Info structure output buffer.
7271d09792aSZiyang Xuan  */
728bdad90d1SIvan Ilchenko static int
7291d09792aSZiyang Xuan hinic_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
7301d09792aSZiyang Xuan {
7311d09792aSZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
7321d09792aSZiyang Xuan 
7331d09792aSZiyang Xuan 	info->max_rx_queues  = nic_dev->nic_cap.max_rqs;
7341d09792aSZiyang Xuan 	info->max_tx_queues  = nic_dev->nic_cap.max_sqs;
7351d09792aSZiyang Xuan 	info->min_rx_bufsize = HINIC_MIN_RX_BUF_SIZE;
7361d09792aSZiyang Xuan 	info->max_rx_pktlen  = HINIC_MAX_JUMBO_FRAME_SIZE;
73700499a22SXiaoyun Wang 	info->max_mac_addrs  = HINIC_MAX_UC_MAC_ADDRS;
7388260eba6SXiaoyun Wang 	info->min_mtu = HINIC_MIN_MTU_SIZE;
7398260eba6SXiaoyun Wang 	info->max_mtu = HINIC_MAX_MTU_SIZE;
7409d02f40dSXiaoyun Wang 	info->max_lro_pkt_size = HINIC_MAX_LRO_SIZE;
7411d09792aSZiyang Xuan 
7421d09792aSZiyang Xuan 	hinic_get_speed_capa(dev, &info->speed_capa);
7431d09792aSZiyang Xuan 	info->rx_queue_offload_capa = 0;
7441d09792aSZiyang Xuan 	info->rx_offload_capa = DEV_RX_OFFLOAD_VLAN_STRIP |
7451d09792aSZiyang Xuan 				DEV_RX_OFFLOAD_IPV4_CKSUM |
7461d09792aSZiyang Xuan 				DEV_RX_OFFLOAD_UDP_CKSUM |
747fdba3bf1SXiaoyun Wang 				DEV_RX_OFFLOAD_TCP_CKSUM |
7488260eba6SXiaoyun Wang 				DEV_RX_OFFLOAD_VLAN_FILTER |
7498260eba6SXiaoyun Wang 				DEV_RX_OFFLOAD_SCATTER |
7509d4878efSXiaoyun Wang 				DEV_RX_OFFLOAD_JUMBO_FRAME |
7518b945a7fSPavan Nikhilesh 				DEV_RX_OFFLOAD_TCP_LRO |
7528b945a7fSPavan Nikhilesh 				DEV_RX_OFFLOAD_RSS_HASH;
7531d09792aSZiyang Xuan 
7541d09792aSZiyang Xuan 	info->tx_queue_offload_capa = 0;
7551d09792aSZiyang Xuan 	info->tx_offload_capa = DEV_TX_OFFLOAD_VLAN_INSERT |
7561d09792aSZiyang Xuan 				DEV_TX_OFFLOAD_IPV4_CKSUM |
7571d09792aSZiyang Xuan 				DEV_TX_OFFLOAD_UDP_CKSUM |
7581d09792aSZiyang Xuan 				DEV_TX_OFFLOAD_TCP_CKSUM |
7591d09792aSZiyang Xuan 				DEV_TX_OFFLOAD_SCTP_CKSUM |
7601d09792aSZiyang Xuan 				DEV_TX_OFFLOAD_OUTER_IPV4_CKSUM |
7611d09792aSZiyang Xuan 				DEV_TX_OFFLOAD_TCP_TSO |
7621d09792aSZiyang Xuan 				DEV_TX_OFFLOAD_MULTI_SEGS;
7631d09792aSZiyang Xuan 
7641d09792aSZiyang Xuan 	info->hash_key_size = HINIC_RSS_KEY_SIZE;
7651d09792aSZiyang Xuan 	info->reta_size = HINIC_RSS_INDIR_SIZE;
76664727024SZiyang Xuan 	info->flow_type_rss_offloads = HINIC_RSS_OFFLOAD_ALL;
7671d09792aSZiyang Xuan 	info->rx_desc_lim = hinic_rx_desc_lim;
7681d09792aSZiyang Xuan 	info->tx_desc_lim = hinic_tx_desc_lim;
769bdad90d1SIvan Ilchenko 
770483b4817SXiaoyun Wang 	/* Driver-preferred Rx/Tx parameters */
771483b4817SXiaoyun Wang 	info->default_rxportconf.burst_size = HINIC_DEFAULT_BURST_SIZE;
772483b4817SXiaoyun Wang 	info->default_txportconf.burst_size = HINIC_DEFAULT_BURST_SIZE;
773483b4817SXiaoyun Wang 	info->default_rxportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES;
774483b4817SXiaoyun Wang 	info->default_txportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES;
775483b4817SXiaoyun Wang 	info->default_rxportconf.ring_size = HINIC_DEFAULT_RING_SIZE;
776483b4817SXiaoyun Wang 	info->default_txportconf.ring_size = HINIC_DEFAULT_RING_SIZE;
777483b4817SXiaoyun Wang 
778bdad90d1SIvan Ilchenko 	return 0;
7791d09792aSZiyang Xuan }
7801d09792aSZiyang Xuan 
781dbf524abSXiaoyun Wang static int hinic_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
782dbf524abSXiaoyun Wang 				size_t fw_size)
783dbf524abSXiaoyun Wang {
784dbf524abSXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
785dbf524abSXiaoyun Wang 	char fw_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0};
786dbf524abSXiaoyun Wang 	int err;
787dbf524abSXiaoyun Wang 
788dbf524abSXiaoyun Wang 	err = hinic_get_mgmt_version(nic_dev->hwdev, fw_ver);
789dbf524abSXiaoyun Wang 	if (err) {
7904f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Failed to get fw version");
791dbf524abSXiaoyun Wang 		return -EINVAL;
792dbf524abSXiaoyun Wang 	}
793dbf524abSXiaoyun Wang 
794dbf524abSXiaoyun Wang 	if (fw_size < strlen(fw_ver) + 1)
795dbf524abSXiaoyun Wang 		return (strlen(fw_ver) + 1);
796dbf524abSXiaoyun Wang 
797dbf524abSXiaoyun Wang 	snprintf(fw_version, fw_size, "%s", fw_ver);
798dbf524abSXiaoyun Wang 
799dbf524abSXiaoyun Wang 	return 0;
800dbf524abSXiaoyun Wang }
801dbf524abSXiaoyun Wang 
8022c473729SZiyang Xuan static int hinic_config_rx_mode(struct hinic_nic_dev *nic_dev, u32 rx_mode_ctrl)
8032c473729SZiyang Xuan {
8042c473729SZiyang Xuan 	int err;
8052c473729SZiyang Xuan 
8062c473729SZiyang Xuan 	err = hinic_set_rx_mode(nic_dev->hwdev, rx_mode_ctrl);
8072c473729SZiyang Xuan 	if (err) {
8082c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set rx mode");
8092c473729SZiyang Xuan 		return -EINVAL;
8102c473729SZiyang Xuan 	}
8112c473729SZiyang Xuan 	nic_dev->rx_mode_status = rx_mode_ctrl;
8122c473729SZiyang Xuan 
8132c473729SZiyang Xuan 	return 0;
8142c473729SZiyang Xuan }
8152c473729SZiyang Xuan 
8162c473729SZiyang Xuan static int hinic_rxtx_configure(struct rte_eth_dev *dev)
8172c473729SZiyang Xuan {
8182c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
8199d02f40dSXiaoyun Wang 	int err;
8202c473729SZiyang Xuan 
8212c473729SZiyang Xuan 	/* rx configure, if rss enable, need to init default configuration */
8222c473729SZiyang Xuan 	err = hinic_rx_configure(dev);
8232c473729SZiyang Xuan 	if (err) {
8242c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure rss failed");
8252c473729SZiyang Xuan 		return err;
8262c473729SZiyang Xuan 	}
8272c473729SZiyang Xuan 
8282c473729SZiyang Xuan 	/* rx mode init */
8292c473729SZiyang Xuan 	err = hinic_config_rx_mode(nic_dev, HINIC_DEFAULT_RX_MODE);
8302c473729SZiyang Xuan 	if (err) {
8312c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure rx_mode:0x%x failed",
8322c473729SZiyang Xuan 			HINIC_DEFAULT_RX_MODE);
8332c473729SZiyang Xuan 		goto set_rx_mode_fail;
8342c473729SZiyang Xuan 	}
8352c473729SZiyang Xuan 
8362c473729SZiyang Xuan 	return HINIC_OK;
8372c473729SZiyang Xuan 
8382c473729SZiyang Xuan set_rx_mode_fail:
8392c473729SZiyang Xuan 	hinic_rx_remove_configure(dev);
8402c473729SZiyang Xuan 
8412c473729SZiyang Xuan 	return err;
8422c473729SZiyang Xuan }
8432c473729SZiyang Xuan 
8442c473729SZiyang Xuan static void hinic_remove_rxtx_configure(struct rte_eth_dev *dev)
8452c473729SZiyang Xuan {
8462c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
8472c473729SZiyang Xuan 
8482c473729SZiyang Xuan 	(void)hinic_config_rx_mode(nic_dev, 0);
8492c473729SZiyang Xuan 	hinic_rx_remove_configure(dev);
8502c473729SZiyang Xuan }
8512c473729SZiyang Xuan 
8522c473729SZiyang Xuan static int hinic_priv_get_dev_link_status(struct hinic_nic_dev *nic_dev,
8532c473729SZiyang Xuan 					  struct rte_eth_link *link)
8542c473729SZiyang Xuan {
8552c473729SZiyang Xuan 	int rc;
8562c473729SZiyang Xuan 	u8 port_link_status = 0;
8572c473729SZiyang Xuan 	struct nic_port_info port_link_info;
8582c473729SZiyang Xuan 	struct hinic_hwdev *nic_hwdev = nic_dev->hwdev;
8592c473729SZiyang Xuan 	uint32_t port_speed[LINK_SPEED_MAX] = {ETH_SPEED_NUM_10M,
8602c473729SZiyang Xuan 					ETH_SPEED_NUM_100M, ETH_SPEED_NUM_1G,
8612c473729SZiyang Xuan 					ETH_SPEED_NUM_10G, ETH_SPEED_NUM_25G,
8622c473729SZiyang Xuan 					ETH_SPEED_NUM_40G, ETH_SPEED_NUM_100G};
8632c473729SZiyang Xuan 
8642c473729SZiyang Xuan 	rc = hinic_get_link_status(nic_hwdev, &port_link_status);
8652c473729SZiyang Xuan 	if (rc)
8662c473729SZiyang Xuan 		return rc;
8672c473729SZiyang Xuan 
8682c473729SZiyang Xuan 	if (!port_link_status) {
8692c473729SZiyang Xuan 		link->link_status = ETH_LINK_DOWN;
8702c473729SZiyang Xuan 		link->link_speed = 0;
8712c473729SZiyang Xuan 		link->link_duplex = ETH_LINK_HALF_DUPLEX;
8722c473729SZiyang Xuan 		link->link_autoneg = ETH_LINK_FIXED;
8732c473729SZiyang Xuan 		return HINIC_OK;
8742c473729SZiyang Xuan 	}
8752c473729SZiyang Xuan 
8762c473729SZiyang Xuan 	memset(&port_link_info, 0, sizeof(port_link_info));
8772c473729SZiyang Xuan 	rc = hinic_get_port_info(nic_hwdev, &port_link_info);
8782c473729SZiyang Xuan 	if (rc)
8792c473729SZiyang Xuan 		return rc;
8802c473729SZiyang Xuan 
8812c473729SZiyang Xuan 	link->link_speed = port_speed[port_link_info.speed % LINK_SPEED_MAX];
8822c473729SZiyang Xuan 	link->link_duplex = port_link_info.duplex;
8832c473729SZiyang Xuan 	link->link_autoneg = port_link_info.autoneg_state;
8842c473729SZiyang Xuan 	link->link_status = port_link_status;
8852c473729SZiyang Xuan 
8862c473729SZiyang Xuan 	return HINIC_OK;
8872c473729SZiyang Xuan }
8882c473729SZiyang Xuan 
8892c473729SZiyang Xuan /**
8902c473729SZiyang Xuan  * DPDK callback to retrieve physical link information.
8912c473729SZiyang Xuan  *
8922c473729SZiyang Xuan  * @param dev
8932c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
8942c473729SZiyang Xuan  * @param wait_to_complete
8952c473729SZiyang Xuan  *   Wait for request completion.
8962c473729SZiyang Xuan  *
8972c473729SZiyang Xuan  * @return
8982c473729SZiyang Xuan  *   0 link status changed, -1 link status not changed
8992c473729SZiyang Xuan  */
9002c473729SZiyang Xuan static int hinic_link_update(struct rte_eth_dev *dev, int wait_to_complete)
9012c473729SZiyang Xuan {
9022c473729SZiyang Xuan #define CHECK_INTERVAL 10  /* 10ms */
9032c473729SZiyang Xuan #define MAX_REPEAT_TIME 100  /* 1s (100 * 10ms) in total */
9042c473729SZiyang Xuan 	int rc = HINIC_OK;
9052c473729SZiyang Xuan 	struct rte_eth_link link;
9062c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
9072c473729SZiyang Xuan 	unsigned int rep_cnt = MAX_REPEAT_TIME;
9082c473729SZiyang Xuan 
9092c473729SZiyang Xuan 	memset(&link, 0, sizeof(link));
9102c473729SZiyang Xuan 	do {
9112c473729SZiyang Xuan 		/* Get link status information from hardware */
9122c473729SZiyang Xuan 		rc = hinic_priv_get_dev_link_status(nic_dev, &link);
9132c473729SZiyang Xuan 		if (rc != HINIC_OK) {
9142c473729SZiyang Xuan 			link.link_speed = ETH_SPEED_NUM_NONE;
9152c473729SZiyang Xuan 			link.link_duplex = ETH_LINK_FULL_DUPLEX;
9162c473729SZiyang Xuan 			PMD_DRV_LOG(ERR, "Get link status failed");
9172c473729SZiyang Xuan 			goto out;
9182c473729SZiyang Xuan 		}
9192c473729SZiyang Xuan 
9202c473729SZiyang Xuan 		if (!wait_to_complete || link.link_status)
9212c473729SZiyang Xuan 			break;
9222c473729SZiyang Xuan 
9232c473729SZiyang Xuan 		rte_delay_ms(CHECK_INTERVAL);
9242c473729SZiyang Xuan 	} while (rep_cnt--);
9252c473729SZiyang Xuan 
9262c473729SZiyang Xuan out:
9272c473729SZiyang Xuan 	rc = rte_eth_linkstatus_set(dev, &link);
9282c473729SZiyang Xuan 	return rc;
9292c473729SZiyang Xuan }
9302c473729SZiyang Xuan 
9312c473729SZiyang Xuan /**
93254ac3386SXiaoyun Wang  * DPDK callback to bring the link UP.
93354ac3386SXiaoyun Wang  *
93454ac3386SXiaoyun Wang  * @param dev
93554ac3386SXiaoyun Wang  *   Pointer to Ethernet device structure.
93654ac3386SXiaoyun Wang  *
93754ac3386SXiaoyun Wang  * @return
93854ac3386SXiaoyun Wang  *   0 on success, negative errno value on failure.
93954ac3386SXiaoyun Wang  */
94054ac3386SXiaoyun Wang static int hinic_dev_set_link_up(struct rte_eth_dev *dev)
94154ac3386SXiaoyun Wang {
94254ac3386SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
94354ac3386SXiaoyun Wang 	int ret;
94454ac3386SXiaoyun Wang 
94554ac3386SXiaoyun Wang 	/* link status follow phy port status, up will open pma */
94654ac3386SXiaoyun Wang 	ret = hinic_set_port_enable(nic_dev->hwdev, true);
94754ac3386SXiaoyun Wang 	if (ret)
94854ac3386SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set mac link up failed, dev_name: %s, port_id: %d",
94954ac3386SXiaoyun Wang 			    nic_dev->proc_dev_name, dev->data->port_id);
95054ac3386SXiaoyun Wang 
95154ac3386SXiaoyun Wang 	return ret;
95254ac3386SXiaoyun Wang }
95354ac3386SXiaoyun Wang 
95454ac3386SXiaoyun Wang /**
95554ac3386SXiaoyun Wang  * DPDK callback to bring the link DOWN.
95654ac3386SXiaoyun Wang  *
95754ac3386SXiaoyun Wang  * @param dev
95854ac3386SXiaoyun Wang  *   Pointer to Ethernet device structure.
95954ac3386SXiaoyun Wang  *
96054ac3386SXiaoyun Wang  * @return
96154ac3386SXiaoyun Wang  *   0 on success, negative errno value on failure.
96254ac3386SXiaoyun Wang  */
96354ac3386SXiaoyun Wang static int hinic_dev_set_link_down(struct rte_eth_dev *dev)
96454ac3386SXiaoyun Wang {
96554ac3386SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
96654ac3386SXiaoyun Wang 	int ret;
96754ac3386SXiaoyun Wang 
96854ac3386SXiaoyun Wang 	/* link status follow phy port status, up will close pma */
96954ac3386SXiaoyun Wang 	ret = hinic_set_port_enable(nic_dev->hwdev, false);
97054ac3386SXiaoyun Wang 	if (ret)
97154ac3386SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set mac link down failed, dev_name: %s, port_id: %d",
97254ac3386SXiaoyun Wang 			    nic_dev->proc_dev_name, dev->data->port_id);
97354ac3386SXiaoyun Wang 
97454ac3386SXiaoyun Wang 	return ret;
97554ac3386SXiaoyun Wang }
97654ac3386SXiaoyun Wang 
97754ac3386SXiaoyun Wang /**
9782c473729SZiyang Xuan  * DPDK callback to start the device.
9792c473729SZiyang Xuan  *
9802c473729SZiyang Xuan  * @param dev
9812c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
9822c473729SZiyang Xuan  *
9832c473729SZiyang Xuan  * @return
9842c473729SZiyang Xuan  *   0 on success, negative errno value on failure.
9852c473729SZiyang Xuan  */
9862c473729SZiyang Xuan static int hinic_dev_start(struct rte_eth_dev *dev)
9872c473729SZiyang Xuan {
9882c473729SZiyang Xuan 	int rc;
9892c473729SZiyang Xuan 	char *name;
9902c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
9912c473729SZiyang Xuan 
9922c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
9932c473729SZiyang Xuan 	name = dev->data->name;
9942c473729SZiyang Xuan 
9952c473729SZiyang Xuan 	/* reset rx and tx queue */
9962c473729SZiyang Xuan 	hinic_reset_rx_queue(dev);
9972c473729SZiyang Xuan 	hinic_reset_tx_queue(dev);
9982c473729SZiyang Xuan 
9992c473729SZiyang Xuan 	/* get func rx buf size */
10002c473729SZiyang Xuan 	hinic_get_func_rx_buf_size(nic_dev);
10012c473729SZiyang Xuan 
10022c473729SZiyang Xuan 	/* init txq and rxq context */
10032c473729SZiyang Xuan 	rc = hinic_init_qp_ctxts(nic_dev->hwdev);
10042c473729SZiyang Xuan 	if (rc) {
10052c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize qp context failed, dev_name: %s",
10062c473729SZiyang Xuan 			    name);
10072c473729SZiyang Xuan 		goto init_qp_fail;
10082c473729SZiyang Xuan 	}
10092c473729SZiyang Xuan 
10102c473729SZiyang Xuan 	/* rss template */
10112c473729SZiyang Xuan 	rc = hinic_config_mq_mode(dev, TRUE);
10122c473729SZiyang Xuan 	if (rc) {
10132c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure mq mode failed, dev_name: %s",
10142c473729SZiyang Xuan 			    name);
10152c473729SZiyang Xuan 		goto cfg_mq_mode_fail;
10162c473729SZiyang Xuan 	}
10172c473729SZiyang Xuan 
10182c473729SZiyang Xuan 	/* set default mtu */
10192c473729SZiyang Xuan 	rc = hinic_set_port_mtu(nic_dev->hwdev, nic_dev->mtu_size);
10202c473729SZiyang Xuan 	if (rc) {
10212c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Set mtu_size[%d] failed, dev_name: %s",
10222c473729SZiyang Xuan 			    nic_dev->mtu_size, name);
10232c473729SZiyang Xuan 		goto set_mtu_fail;
10242c473729SZiyang Xuan 	}
10252c473729SZiyang Xuan 
10262c473729SZiyang Xuan 	/* configure rss rx_mode and other rx or tx default feature */
10272c473729SZiyang Xuan 	rc = hinic_rxtx_configure(dev);
10282c473729SZiyang Xuan 	if (rc) {
10292c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure tx and rx failed, dev_name: %s",
10302c473729SZiyang Xuan 			    name);
10312c473729SZiyang Xuan 		goto cfg_rxtx_fail;
10322c473729SZiyang Xuan 	}
10332c473729SZiyang Xuan 
10346691acefSXiaoyun Wang 	/* reactive pf status, so that uP report asyn event */
10356691acefSXiaoyun Wang 	hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_ACTIVE_FLAG);
10366691acefSXiaoyun Wang 
10372c473729SZiyang Xuan 	/* open virtual port and ready to start packet receiving */
10382c473729SZiyang Xuan 	rc = hinic_set_vport_enable(nic_dev->hwdev, true);
10392c473729SZiyang Xuan 	if (rc) {
10402c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Enable vport failed, dev_name:%s", name);
10412c473729SZiyang Xuan 		goto en_vport_fail;
10422c473729SZiyang Xuan 	}
10432c473729SZiyang Xuan 
10442c473729SZiyang Xuan 	/* open physical port and start packet receiving */
10452c473729SZiyang Xuan 	rc = hinic_set_port_enable(nic_dev->hwdev, true);
10462c473729SZiyang Xuan 	if (rc) {
10472c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Enable physical port failed, dev_name: %s",
10482c473729SZiyang Xuan 			    name);
10492c473729SZiyang Xuan 		goto en_port_fail;
10502c473729SZiyang Xuan 	}
10512c473729SZiyang Xuan 
10522c473729SZiyang Xuan 	/* update eth_dev link status */
10532c473729SZiyang Xuan 	if (dev->data->dev_conf.intr_conf.lsc != 0)
10542c473729SZiyang Xuan 		(void)hinic_link_update(dev, 0);
10552c473729SZiyang Xuan 
10560371535dSJoyce Kong 	rte_bit_relaxed_set32(HINIC_DEV_START, &nic_dev->dev_status);
10572c473729SZiyang Xuan 
10582c473729SZiyang Xuan 	return 0;
10592c473729SZiyang Xuan 
10602c473729SZiyang Xuan en_port_fail:
10612c473729SZiyang Xuan 	(void)hinic_set_vport_enable(nic_dev->hwdev, false);
10622c473729SZiyang Xuan 
10632c473729SZiyang Xuan en_vport_fail:
10646691acefSXiaoyun Wang 	hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_INIT);
10656691acefSXiaoyun Wang 
10662c473729SZiyang Xuan 	/* Flush tx && rx chip resources in case of set vport fake fail */
10672c473729SZiyang Xuan 	(void)hinic_flush_qp_res(nic_dev->hwdev);
10682c473729SZiyang Xuan 	rte_delay_ms(100);
10692c473729SZiyang Xuan 
10702c473729SZiyang Xuan 	hinic_remove_rxtx_configure(dev);
10712c473729SZiyang Xuan 
10722c473729SZiyang Xuan cfg_rxtx_fail:
10732c473729SZiyang Xuan set_mtu_fail:
10742c473729SZiyang Xuan cfg_mq_mode_fail:
10752c473729SZiyang Xuan 	hinic_free_qp_ctxts(nic_dev->hwdev);
10762c473729SZiyang Xuan 
10772c473729SZiyang Xuan init_qp_fail:
10782c473729SZiyang Xuan 	hinic_free_all_rx_mbuf(dev);
10792c473729SZiyang Xuan 	hinic_free_all_tx_mbuf(dev);
10802c473729SZiyang Xuan 
10812c473729SZiyang Xuan 	return rc;
10822c473729SZiyang Xuan }
10832c473729SZiyang Xuan 
10842c473729SZiyang Xuan /**
10852c473729SZiyang Xuan  * DPDK callback to release the receive queue.
10862c473729SZiyang Xuan  *
10872c473729SZiyang Xuan  * @param queue
10882c473729SZiyang Xuan  *   Generic receive queue pointer.
10892c473729SZiyang Xuan  */
10902c473729SZiyang Xuan static void hinic_rx_queue_release(void *queue)
10912c473729SZiyang Xuan {
10922c473729SZiyang Xuan 	struct hinic_rxq *rxq = queue;
10932c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
10942c473729SZiyang Xuan 
10952c473729SZiyang Xuan 	if (!rxq) {
10962c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Rxq is null when release");
10972c473729SZiyang Xuan 		return;
10982c473729SZiyang Xuan 	}
10992c473729SZiyang Xuan 	nic_dev = rxq->nic_dev;
11002c473729SZiyang Xuan 
11012c473729SZiyang Xuan 	/* free rxq_pkt mbuf */
1102c3ba1f0fSXiaoyun Wang 	hinic_free_all_rx_mbufs(rxq);
11032c473729SZiyang Xuan 
11042c473729SZiyang Xuan 	/* free rxq_cqe, rxq_info */
11052c473729SZiyang Xuan 	hinic_free_rx_resources(rxq);
11062c473729SZiyang Xuan 
11072c473729SZiyang Xuan 	/* free root rq wq */
11082c473729SZiyang Xuan 	hinic_destroy_rq(nic_dev->hwdev, rxq->q_id);
11092c473729SZiyang Xuan 
11102c473729SZiyang Xuan 	nic_dev->rxqs[rxq->q_id] = NULL;
11112c473729SZiyang Xuan 
11122c473729SZiyang Xuan 	/* free rxq */
11132c473729SZiyang Xuan 	rte_free(rxq);
11142c473729SZiyang Xuan }
11152c473729SZiyang Xuan 
11162c473729SZiyang Xuan /**
11172c473729SZiyang Xuan  * DPDK callback to release the transmit queue.
11182c473729SZiyang Xuan  *
11192c473729SZiyang Xuan  * @param queue
11202c473729SZiyang Xuan  *   Generic transmit queue pointer.
11212c473729SZiyang Xuan  */
11222c473729SZiyang Xuan static void hinic_tx_queue_release(void *queue)
11232c473729SZiyang Xuan {
11242c473729SZiyang Xuan 	struct hinic_txq *txq = queue;
11252c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
11262c473729SZiyang Xuan 
11272c473729SZiyang Xuan 	if (!txq) {
11282c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Txq is null when release");
11292c473729SZiyang Xuan 		return;
11302c473729SZiyang Xuan 	}
11312c473729SZiyang Xuan 	nic_dev = txq->nic_dev;
11322c473729SZiyang Xuan 
11332c473729SZiyang Xuan 	/* free txq_pkt mbuf */
1134c3ba1f0fSXiaoyun Wang 	hinic_free_all_tx_mbufs(txq);
11352c473729SZiyang Xuan 
11362c473729SZiyang Xuan 	/* free txq_info */
11372c473729SZiyang Xuan 	hinic_free_tx_resources(txq);
11382c473729SZiyang Xuan 
11392c473729SZiyang Xuan 	/* free root sq wq */
11402c473729SZiyang Xuan 	hinic_destroy_sq(nic_dev->hwdev, txq->q_id);
11412c473729SZiyang Xuan 	nic_dev->txqs[txq->q_id] = NULL;
11422c473729SZiyang Xuan 
11432c473729SZiyang Xuan 	/* free txq */
11442c473729SZiyang Xuan 	rte_free(txq);
11452c473729SZiyang Xuan }
11462c473729SZiyang Xuan 
114764727024SZiyang Xuan static void hinic_free_all_rq(struct hinic_nic_dev *nic_dev)
11481d09792aSZiyang Xuan {
114964727024SZiyang Xuan 	u16 q_id;
115064727024SZiyang Xuan 
115164727024SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_rq; q_id++)
115264727024SZiyang Xuan 		hinic_destroy_rq(nic_dev->hwdev, q_id);
115364727024SZiyang Xuan }
115464727024SZiyang Xuan 
115564727024SZiyang Xuan static void hinic_free_all_sq(struct hinic_nic_dev *nic_dev)
115664727024SZiyang Xuan {
115764727024SZiyang Xuan 	u16 q_id;
115864727024SZiyang Xuan 
115964727024SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_sq; q_id++)
116064727024SZiyang Xuan 		hinic_destroy_sq(nic_dev->hwdev, q_id);
116164727024SZiyang Xuan }
116264727024SZiyang Xuan 
11632c473729SZiyang Xuan /**
11642c473729SZiyang Xuan  * DPDK callback to stop the device.
11652c473729SZiyang Xuan  *
11662c473729SZiyang Xuan  * @param dev
11672c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
11682c473729SZiyang Xuan  */
116962024eb8SIvan Ilchenko static int hinic_dev_stop(struct rte_eth_dev *dev)
11702c473729SZiyang Xuan {
11712c473729SZiyang Xuan 	int rc;
11722c473729SZiyang Xuan 	char *name;
11732c473729SZiyang Xuan 	uint16_t port_id;
11742c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
11752c473729SZiyang Xuan 	struct rte_eth_link link;
11762c473729SZiyang Xuan 
11772c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
11782c473729SZiyang Xuan 	name = dev->data->name;
11792c473729SZiyang Xuan 	port_id = dev->data->port_id;
11802c473729SZiyang Xuan 
1181b8f5d2aeSThomas Monjalon 	dev->data->dev_started = 0;
1182b8f5d2aeSThomas Monjalon 
11830371535dSJoyce Kong 	if (!rte_bit_relaxed_test_and_clear32(HINIC_DEV_START,
11840371535dSJoyce Kong 					      &nic_dev->dev_status)) {
11852c473729SZiyang Xuan 		PMD_DRV_LOG(INFO, "Device %s already stopped", name);
118662024eb8SIvan Ilchenko 		return 0;
11872c473729SZiyang Xuan 	}
11882c473729SZiyang Xuan 
11892c473729SZiyang Xuan 	/* just stop phy port and vport */
11902c473729SZiyang Xuan 	rc = hinic_set_port_enable(nic_dev->hwdev, false);
11912c473729SZiyang Xuan 	if (rc)
11922c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Disable phy port failed, error: %d, dev_name: %s, port_id: %d",
11932c473729SZiyang Xuan 			  rc, name, port_id);
11942c473729SZiyang Xuan 
11952c473729SZiyang Xuan 	rc = hinic_set_vport_enable(nic_dev->hwdev, false);
11962c473729SZiyang Xuan 	if (rc)
11972c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Disable vport failed, error: %d, dev_name: %s, port_id: %d",
11982c473729SZiyang Xuan 			  rc, name, port_id);
11992c473729SZiyang Xuan 
12002c473729SZiyang Xuan 	/* Clear recorded link status */
12012c473729SZiyang Xuan 	memset(&link, 0, sizeof(link));
12022c473729SZiyang Xuan 	(void)rte_eth_linkstatus_set(dev, &link);
12032c473729SZiyang Xuan 
12042c473729SZiyang Xuan 	/* flush pending io request */
12052c473729SZiyang Xuan 	rc = hinic_rx_tx_flush(nic_dev->hwdev);
12062c473729SZiyang Xuan 	if (rc)
12072c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Flush pending io failed, error: %d, dev_name: %s, port_id: %d",
12082c473729SZiyang Xuan 			    rc, name, port_id);
12092c473729SZiyang Xuan 
12102c473729SZiyang Xuan 	/* clean rss table and rx_mode */
12112c473729SZiyang Xuan 	hinic_remove_rxtx_configure(dev);
12122c473729SZiyang Xuan 
12132c473729SZiyang Xuan 	/* clean root context */
12142c473729SZiyang Xuan 	hinic_free_qp_ctxts(nic_dev->hwdev);
12152c473729SZiyang Xuan 
12161fe89aa3SXiaoyun Wang 	hinic_destroy_fdir_filter(dev);
12171742421bSXiaoyun Wang 
12182c473729SZiyang Xuan 	/* free mbuf */
12192c473729SZiyang Xuan 	hinic_free_all_rx_mbuf(dev);
12202c473729SZiyang Xuan 	hinic_free_all_tx_mbuf(dev);
122162024eb8SIvan Ilchenko 
122262024eb8SIvan Ilchenko 	return 0;
12232c473729SZiyang Xuan }
12242c473729SZiyang Xuan 
122564727024SZiyang Xuan static void hinic_disable_interrupt(struct rte_eth_dev *dev)
122664727024SZiyang Xuan {
122764727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
122864727024SZiyang Xuan 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
122964727024SZiyang Xuan 	int ret, retries = 0;
123064727024SZiyang Xuan 
12310371535dSJoyce Kong 	rte_bit_relaxed_clear32(HINIC_DEV_INTR_EN, &nic_dev->dev_status);
123264727024SZiyang Xuan 
123364727024SZiyang Xuan 	/* disable msix interrupt in hardware */
123464727024SZiyang Xuan 	hinic_set_msix_state(nic_dev->hwdev, 0, HINIC_MSIX_DISABLE);
123564727024SZiyang Xuan 
123664727024SZiyang Xuan 	/* disable rte interrupt */
123764727024SZiyang Xuan 	ret = rte_intr_disable(&pci_dev->intr_handle);
123864727024SZiyang Xuan 	if (ret)
123964727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Disable intr failed: %d", ret);
124064727024SZiyang Xuan 
124164727024SZiyang Xuan 	do {
124264727024SZiyang Xuan 		ret =
124364727024SZiyang Xuan 		rte_intr_callback_unregister(&pci_dev->intr_handle,
124464727024SZiyang Xuan 					     hinic_dev_interrupt_handler, dev);
124564727024SZiyang Xuan 		if (ret >= 0) {
124664727024SZiyang Xuan 			break;
124764727024SZiyang Xuan 		} else if (ret == -EAGAIN) {
124864727024SZiyang Xuan 			rte_delay_ms(100);
124964727024SZiyang Xuan 			retries++;
125064727024SZiyang Xuan 		} else {
125164727024SZiyang Xuan 			PMD_DRV_LOG(ERR, "intr callback unregister failed: %d",
125264727024SZiyang Xuan 				    ret);
125364727024SZiyang Xuan 			break;
125464727024SZiyang Xuan 		}
125564727024SZiyang Xuan 	} while (retries < HINIC_INTR_CB_UNREG_MAX_RETRIES);
125664727024SZiyang Xuan 
125764727024SZiyang Xuan 	if (retries == HINIC_INTR_CB_UNREG_MAX_RETRIES)
125864727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Unregister intr callback failed after %d retries",
125964727024SZiyang Xuan 			    retries);
1260511b7371SGuoyang Zhou 
1261511b7371SGuoyang Zhou 	rte_bit_relaxed_clear32(HINIC_DEV_INIT, &nic_dev->dev_status);
126264727024SZiyang Xuan }
126364727024SZiyang Xuan 
1264cb7b6606SZiyang Xuan static int hinic_set_dev_promiscuous(struct hinic_nic_dev *nic_dev, bool enable)
1265cb7b6606SZiyang Xuan {
1266224cff4bSXiaoyun Wang 	u32 rx_mode_ctrl;
1267224cff4bSXiaoyun Wang 	int err;
1268224cff4bSXiaoyun Wang 
1269224cff4bSXiaoyun Wang 	err = hinic_mutex_lock(&nic_dev->rx_mode_mutex);
1270224cff4bSXiaoyun Wang 	if (err)
1271224cff4bSXiaoyun Wang 		return err;
1272224cff4bSXiaoyun Wang 
1273224cff4bSXiaoyun Wang 	rx_mode_ctrl = nic_dev->rx_mode_status;
1274cb7b6606SZiyang Xuan 
1275cb7b6606SZiyang Xuan 	if (enable)
1276cb7b6606SZiyang Xuan 		rx_mode_ctrl |= HINIC_RX_MODE_PROMISC;
1277cb7b6606SZiyang Xuan 	else
1278cb7b6606SZiyang Xuan 		rx_mode_ctrl &= (~HINIC_RX_MODE_PROMISC);
1279cb7b6606SZiyang Xuan 
1280224cff4bSXiaoyun Wang 	err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
1281224cff4bSXiaoyun Wang 
1282224cff4bSXiaoyun Wang 	(void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex);
1283224cff4bSXiaoyun Wang 
1284224cff4bSXiaoyun Wang 	return err;
1285cb7b6606SZiyang Xuan }
1286cb7b6606SZiyang Xuan 
1287cb7b6606SZiyang Xuan /**
1288cb7b6606SZiyang Xuan  * DPDK callback to get device statistics.
1289cb7b6606SZiyang Xuan  *
1290cb7b6606SZiyang Xuan  * @param dev
1291cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
1292cb7b6606SZiyang Xuan  * @param stats
1293cb7b6606SZiyang Xuan  *   Stats structure output buffer.
1294cb7b6606SZiyang Xuan  *
1295cb7b6606SZiyang Xuan  * @return
1296cb7b6606SZiyang Xuan  *   0 on success and stats is filled,
1297cb7b6606SZiyang Xuan  *   negative error value otherwise.
1298cb7b6606SZiyang Xuan  */
1299cb7b6606SZiyang Xuan static int
1300cb7b6606SZiyang Xuan hinic_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
1301cb7b6606SZiyang Xuan {
1302cb7b6606SZiyang Xuan 	int i, err, q_num;
1303cb7b6606SZiyang Xuan 	u64 rx_discards_pmd = 0;
1304cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1305cb7b6606SZiyang Xuan 	struct hinic_vport_stats vport_stats;
1306cb7b6606SZiyang Xuan 	struct hinic_rxq	*rxq = NULL;
1307cb7b6606SZiyang Xuan 	struct hinic_rxq_stats rxq_stats;
1308cb7b6606SZiyang Xuan 	struct hinic_txq	*txq = NULL;
1309cb7b6606SZiyang Xuan 	struct hinic_txq_stats txq_stats;
1310cb7b6606SZiyang Xuan 
1311cb7b6606SZiyang Xuan 	err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats);
1312cb7b6606SZiyang Xuan 	if (err) {
1313cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Get vport stats from fw failed, nic_dev: %s",
1314cb7b6606SZiyang Xuan 			nic_dev->proc_dev_name);
1315cb7b6606SZiyang Xuan 		return err;
1316cb7b6606SZiyang Xuan 	}
1317cb7b6606SZiyang Xuan 
13183930d9ceSXiaoyun Wang 	dev->data->rx_mbuf_alloc_failed = 0;
13193930d9ceSXiaoyun Wang 
1320cb7b6606SZiyang Xuan 	/* rx queue stats */
1321cb7b6606SZiyang Xuan 	q_num = (nic_dev->num_rq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
1322cb7b6606SZiyang Xuan 			nic_dev->num_rq : RTE_ETHDEV_QUEUE_STAT_CNTRS;
1323cb7b6606SZiyang Xuan 	for (i = 0; i < q_num; i++) {
1324cb7b6606SZiyang Xuan 		rxq = nic_dev->rxqs[i];
1325cb7b6606SZiyang Xuan 		hinic_rxq_get_stats(rxq, &rxq_stats);
1326cb7b6606SZiyang Xuan 		stats->q_ipackets[i] = rxq_stats.packets;
1327cb7b6606SZiyang Xuan 		stats->q_ibytes[i] = rxq_stats.bytes;
1328cb7b6606SZiyang Xuan 		stats->q_errors[i] = rxq_stats.rx_discards;
1329cb7b6606SZiyang Xuan 
1330cb7b6606SZiyang Xuan 		stats->ierrors += rxq_stats.errors;
1331cb7b6606SZiyang Xuan 		rx_discards_pmd += rxq_stats.rx_discards;
1332cb7b6606SZiyang Xuan 		dev->data->rx_mbuf_alloc_failed += rxq_stats.rx_nombuf;
1333cb7b6606SZiyang Xuan 	}
1334cb7b6606SZiyang Xuan 
1335cb7b6606SZiyang Xuan 	/* tx queue stats */
1336cb7b6606SZiyang Xuan 	q_num = (nic_dev->num_sq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
1337cb7b6606SZiyang Xuan 		nic_dev->num_sq : RTE_ETHDEV_QUEUE_STAT_CNTRS;
1338cb7b6606SZiyang Xuan 	for (i = 0; i < q_num; i++) {
1339cb7b6606SZiyang Xuan 		txq = nic_dev->txqs[i];
1340cb7b6606SZiyang Xuan 		hinic_txq_get_stats(txq, &txq_stats);
1341cb7b6606SZiyang Xuan 		stats->q_opackets[i] = txq_stats.packets;
1342cb7b6606SZiyang Xuan 		stats->q_obytes[i] = txq_stats.bytes;
1343cb7b6606SZiyang Xuan 		stats->oerrors += (txq_stats.tx_busy + txq_stats.off_errs);
1344cb7b6606SZiyang Xuan 	}
1345cb7b6606SZiyang Xuan 
1346cb7b6606SZiyang Xuan 	/* vport stats */
1347cb7b6606SZiyang Xuan 	stats->oerrors += vport_stats.tx_discard_vport;
1348cb7b6606SZiyang Xuan 
1349cb7b6606SZiyang Xuan 	stats->imissed = vport_stats.rx_discard_vport + rx_discards_pmd;
1350cb7b6606SZiyang Xuan 
1351cb7b6606SZiyang Xuan 	stats->ipackets = (vport_stats.rx_unicast_pkts_vport +
1352cb7b6606SZiyang Xuan 			vport_stats.rx_multicast_pkts_vport +
1353cb7b6606SZiyang Xuan 			vport_stats.rx_broadcast_pkts_vport -
1354cb7b6606SZiyang Xuan 			rx_discards_pmd);
1355cb7b6606SZiyang Xuan 
1356cb7b6606SZiyang Xuan 	stats->opackets = (vport_stats.tx_unicast_pkts_vport +
1357cb7b6606SZiyang Xuan 			vport_stats.tx_multicast_pkts_vport +
1358cb7b6606SZiyang Xuan 			vport_stats.tx_broadcast_pkts_vport);
1359cb7b6606SZiyang Xuan 
1360cb7b6606SZiyang Xuan 	stats->ibytes = (vport_stats.rx_unicast_bytes_vport +
1361cb7b6606SZiyang Xuan 			vport_stats.rx_multicast_bytes_vport +
1362cb7b6606SZiyang Xuan 			vport_stats.rx_broadcast_bytes_vport);
1363cb7b6606SZiyang Xuan 
1364cb7b6606SZiyang Xuan 	stats->obytes = (vport_stats.tx_unicast_bytes_vport +
1365cb7b6606SZiyang Xuan 			vport_stats.tx_multicast_bytes_vport +
1366cb7b6606SZiyang Xuan 			vport_stats.tx_broadcast_bytes_vport);
1367cb7b6606SZiyang Xuan 	return 0;
1368cb7b6606SZiyang Xuan }
1369cb7b6606SZiyang Xuan 
1370cb7b6606SZiyang Xuan /**
1371cb7b6606SZiyang Xuan  * DPDK callback to clear device statistics.
1372cb7b6606SZiyang Xuan  *
1373cb7b6606SZiyang Xuan  * @param dev
1374cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
1375cb7b6606SZiyang Xuan  */
13769970a9adSIgor Romanov static int hinic_dev_stats_reset(struct rte_eth_dev *dev)
1377cb7b6606SZiyang Xuan {
1378cb7b6606SZiyang Xuan 	int qid;
1379cb7b6606SZiyang Xuan 	struct hinic_rxq	*rxq = NULL;
1380cb7b6606SZiyang Xuan 	struct hinic_txq	*txq = NULL;
1381cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
13829970a9adSIgor Romanov 	int ret;
1383cb7b6606SZiyang Xuan 
13849970a9adSIgor Romanov 	ret = hinic_clear_vport_stats(nic_dev->hwdev);
13859970a9adSIgor Romanov 	if (ret != 0)
13869970a9adSIgor Romanov 		return ret;
1387cb7b6606SZiyang Xuan 
1388cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_rq; qid++) {
1389cb7b6606SZiyang Xuan 		rxq = nic_dev->rxqs[qid];
1390cb7b6606SZiyang Xuan 		hinic_rxq_stats_reset(rxq);
1391cb7b6606SZiyang Xuan 	}
1392cb7b6606SZiyang Xuan 
1393cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_sq; qid++) {
1394cb7b6606SZiyang Xuan 		txq = nic_dev->txqs[qid];
1395cb7b6606SZiyang Xuan 		hinic_txq_stats_reset(txq);
1396cb7b6606SZiyang Xuan 	}
13979970a9adSIgor Romanov 
13989970a9adSIgor Romanov 	return 0;
1399cb7b6606SZiyang Xuan }
1400cb7b6606SZiyang Xuan 
1401cb7b6606SZiyang Xuan /**
1402cb7b6606SZiyang Xuan  * DPDK callback to clear device extended statistics.
1403cb7b6606SZiyang Xuan  *
1404cb7b6606SZiyang Xuan  * @param dev
1405cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
14066691acefSXiaoyun Wang  */
14079970a9adSIgor Romanov static int hinic_dev_xstats_reset(struct rte_eth_dev *dev)
1408cb7b6606SZiyang Xuan {
1409cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
14109970a9adSIgor Romanov 	int ret;
1411cb7b6606SZiyang Xuan 
14129970a9adSIgor Romanov 	ret = hinic_dev_stats_reset(dev);
14139970a9adSIgor Romanov 	if (ret != 0)
14149970a9adSIgor Romanov 		return ret;
1415cb7b6606SZiyang Xuan 
14169970a9adSIgor Romanov 	if (hinic_func_type(nic_dev->hwdev) != TYPE_VF) {
14179970a9adSIgor Romanov 		ret = hinic_clear_phy_port_stats(nic_dev->hwdev);
14189970a9adSIgor Romanov 		if (ret != 0)
14199970a9adSIgor Romanov 			return ret;
14209970a9adSIgor Romanov 	}
14219970a9adSIgor Romanov 
14229970a9adSIgor Romanov 	return 0;
1423cb7b6606SZiyang Xuan }
1424cb7b6606SZiyang Xuan 
14252c473729SZiyang Xuan static void hinic_gen_random_mac_addr(struct rte_ether_addr *mac_addr)
14262c473729SZiyang Xuan {
14272c473729SZiyang Xuan 	uint64_t random_value;
14282c473729SZiyang Xuan 
14292c473729SZiyang Xuan 	/* Set Organizationally Unique Identifier (OUI) prefix */
14302c473729SZiyang Xuan 	mac_addr->addr_bytes[0] = 0x00;
14312c473729SZiyang Xuan 	mac_addr->addr_bytes[1] = 0x09;
14322c473729SZiyang Xuan 	mac_addr->addr_bytes[2] = 0xC0;
14332c473729SZiyang Xuan 	/* Force indication of locally assigned MAC address. */
14342c473729SZiyang Xuan 	mac_addr->addr_bytes[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR;
14352c473729SZiyang Xuan 	/* Generate the last 3 bytes of the MAC address with a random number. */
14362c473729SZiyang Xuan 	random_value = rte_rand();
14372c473729SZiyang Xuan 	memcpy(&mac_addr->addr_bytes[3], &random_value, 3);
14382c473729SZiyang Xuan }
14392c473729SZiyang Xuan 
144064727024SZiyang Xuan /**
144164727024SZiyang Xuan  * Init mac_vlan table in NIC.
144264727024SZiyang Xuan  *
144364727024SZiyang Xuan  * @param dev
144464727024SZiyang Xuan  *   Pointer to Ethernet device structure.
144564727024SZiyang Xuan  *
144664727024SZiyang Xuan  * @return
144764727024SZiyang Xuan  *   0 on success and stats is filled,
144864727024SZiyang Xuan  *   negative error value otherwise.
144964727024SZiyang Xuan  */
145064727024SZiyang Xuan static int hinic_init_mac_addr(struct rte_eth_dev *eth_dev)
145164727024SZiyang Xuan {
145264727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
145364727024SZiyang Xuan 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
145464727024SZiyang Xuan 	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN];
145564727024SZiyang Xuan 	u16 func_id = 0;
145664727024SZiyang Xuan 	int rc = 0;
145764727024SZiyang Xuan 
145864727024SZiyang Xuan 	rc = hinic_get_default_mac(nic_dev->hwdev, addr_bytes);
145964727024SZiyang Xuan 	if (rc)
146064727024SZiyang Xuan 		return rc;
146164727024SZiyang Xuan 
146200499a22SXiaoyun Wang 	rte_ether_addr_copy((struct rte_ether_addr *)addr_bytes,
146300499a22SXiaoyun Wang 		&eth_dev->data->mac_addrs[0]);
146400499a22SXiaoyun Wang 	if (rte_is_zero_ether_addr(&eth_dev->data->mac_addrs[0]))
146500499a22SXiaoyun Wang 		hinic_gen_random_mac_addr(&eth_dev->data->mac_addrs[0]);
14662c473729SZiyang Xuan 
146764727024SZiyang Xuan 	func_id = hinic_global_func_id(nic_dev->hwdev);
146800499a22SXiaoyun Wang 	rc = hinic_set_mac(nic_dev->hwdev,
146900499a22SXiaoyun Wang 			eth_dev->data->mac_addrs[0].addr_bytes,
147064727024SZiyang Xuan 			0, func_id);
147164727024SZiyang Xuan 	if (rc && rc != HINIC_PF_SET_VF_ALREADY)
147264727024SZiyang Xuan 		return rc;
147364727024SZiyang Xuan 
147400499a22SXiaoyun Wang 	rte_ether_addr_copy(&eth_dev->data->mac_addrs[0],
147500499a22SXiaoyun Wang 			&nic_dev->default_addr);
147600499a22SXiaoyun Wang 
14771d09792aSZiyang Xuan 	return 0;
14781d09792aSZiyang Xuan }
14791d09792aSZiyang Xuan 
148000499a22SXiaoyun Wang static void hinic_delete_mc_addr_list(struct hinic_nic_dev *nic_dev)
148100499a22SXiaoyun Wang {
148200499a22SXiaoyun Wang 	u16 func_id;
148300499a22SXiaoyun Wang 	u32 i;
148400499a22SXiaoyun Wang 
148500499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
148600499a22SXiaoyun Wang 
148700499a22SXiaoyun Wang 	for (i = 0; i < HINIC_MAX_MC_MAC_ADDRS; i++) {
148800499a22SXiaoyun Wang 		if (rte_is_zero_ether_addr(&nic_dev->mc_list[i]))
148900499a22SXiaoyun Wang 			break;
149000499a22SXiaoyun Wang 
149100499a22SXiaoyun Wang 		hinic_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes,
149200499a22SXiaoyun Wang 			      0, func_id);
149300499a22SXiaoyun Wang 		memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr));
149400499a22SXiaoyun Wang 	}
149500499a22SXiaoyun Wang }
149600499a22SXiaoyun Wang 
14971d09792aSZiyang Xuan /**
149864727024SZiyang Xuan  * Deinit mac_vlan table in NIC.
149964727024SZiyang Xuan  *
150064727024SZiyang Xuan  * @param dev
150164727024SZiyang Xuan  *   Pointer to Ethernet device structure.
150264727024SZiyang Xuan  *
150364727024SZiyang Xuan  * @return
150464727024SZiyang Xuan  *   0 on success and stats is filled,
150564727024SZiyang Xuan  *   negative error value otherwise.
150664727024SZiyang Xuan  */
150764727024SZiyang Xuan static void hinic_deinit_mac_addr(struct rte_eth_dev *eth_dev)
150864727024SZiyang Xuan {
150964727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
151064727024SZiyang Xuan 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
151164727024SZiyang Xuan 	u16 func_id = 0;
151200499a22SXiaoyun Wang 	int rc;
151300499a22SXiaoyun Wang 	int i;
151464727024SZiyang Xuan 
151564727024SZiyang Xuan 	func_id = hinic_global_func_id(nic_dev->hwdev);
151600499a22SXiaoyun Wang 
151700499a22SXiaoyun Wang 	for (i = 0; i < HINIC_MAX_UC_MAC_ADDRS; i++) {
151800499a22SXiaoyun Wang 		if (rte_is_zero_ether_addr(&eth_dev->data->mac_addrs[i]))
151900499a22SXiaoyun Wang 			continue;
152000499a22SXiaoyun Wang 
152164727024SZiyang Xuan 		rc = hinic_del_mac(nic_dev->hwdev,
152200499a22SXiaoyun Wang 				   eth_dev->data->mac_addrs[i].addr_bytes,
152364727024SZiyang Xuan 				   0, func_id);
152464727024SZiyang Xuan 		if (rc && rc != HINIC_PF_SET_VF_ALREADY)
152564727024SZiyang Xuan 			PMD_DRV_LOG(ERR, "Delete mac table failed, dev_name: %s",
152664727024SZiyang Xuan 				    eth_dev->data->name);
152700499a22SXiaoyun Wang 
152800499a22SXiaoyun Wang 		memset(&eth_dev->data->mac_addrs[i], 0,
152900499a22SXiaoyun Wang 		       sizeof(struct rte_ether_addr));
153000499a22SXiaoyun Wang 	}
153100499a22SXiaoyun Wang 
153200499a22SXiaoyun Wang 	/* delete multicast mac addrs */
153300499a22SXiaoyun Wang 	hinic_delete_mc_addr_list(nic_dev);
1534511b7371SGuoyang Zhou 
1535511b7371SGuoyang Zhou 	rte_free(nic_dev->mc_list);
1536511b7371SGuoyang Zhou 
153764727024SZiyang Xuan }
153864727024SZiyang Xuan 
15398260eba6SXiaoyun Wang static int hinic_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
15408260eba6SXiaoyun Wang {
15418260eba6SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1542254bd849SXiaoyun Wang 	uint32_t frame_size;
1543254bd849SXiaoyun Wang 	int ret = 0;
15448260eba6SXiaoyun Wang 
15458260eba6SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Set port mtu, port_id: %d, mtu: %d, max_pkt_len: %d",
15468260eba6SXiaoyun Wang 			dev->data->port_id, mtu, HINIC_MTU_TO_PKTLEN(mtu));
15478260eba6SXiaoyun Wang 
15488260eba6SXiaoyun Wang 	if (mtu < HINIC_MIN_MTU_SIZE || mtu > HINIC_MAX_MTU_SIZE) {
15498260eba6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Invalid mtu: %d, must between %d and %d",
15508260eba6SXiaoyun Wang 				mtu, HINIC_MIN_MTU_SIZE, HINIC_MAX_MTU_SIZE);
15518260eba6SXiaoyun Wang 		return -EINVAL;
15528260eba6SXiaoyun Wang 	}
15538260eba6SXiaoyun Wang 
15548260eba6SXiaoyun Wang 	ret = hinic_set_port_mtu(nic_dev->hwdev, mtu);
15558260eba6SXiaoyun Wang 	if (ret) {
15568260eba6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set port mtu failed, ret: %d", ret);
15578260eba6SXiaoyun Wang 		return ret;
15588260eba6SXiaoyun Wang 	}
15598260eba6SXiaoyun Wang 
15608260eba6SXiaoyun Wang 	/* update max frame size */
1561254bd849SXiaoyun Wang 	frame_size = HINIC_MTU_TO_PKTLEN(mtu);
1562e542ab51SSteve Yang 	if (frame_size > HINIC_ETH_MAX_LEN)
1563254bd849SXiaoyun Wang 		dev->data->dev_conf.rxmode.offloads |=
1564254bd849SXiaoyun Wang 			DEV_RX_OFFLOAD_JUMBO_FRAME;
1565254bd849SXiaoyun Wang 	else
1566254bd849SXiaoyun Wang 		dev->data->dev_conf.rxmode.offloads &=
1567254bd849SXiaoyun Wang 			~DEV_RX_OFFLOAD_JUMBO_FRAME;
1568254bd849SXiaoyun Wang 
1569254bd849SXiaoyun Wang 	dev->data->dev_conf.rxmode.max_rx_pkt_len = frame_size;
15708260eba6SXiaoyun Wang 	nic_dev->mtu_size = mtu;
15718260eba6SXiaoyun Wang 
15728260eba6SXiaoyun Wang 	return ret;
15738260eba6SXiaoyun Wang }
15748260eba6SXiaoyun Wang 
1575fdba3bf1SXiaoyun Wang static void hinic_store_vlan_filter(struct hinic_nic_dev *nic_dev,
1576fdba3bf1SXiaoyun Wang 					u16 vlan_id, bool on)
1577fdba3bf1SXiaoyun Wang {
1578fdba3bf1SXiaoyun Wang 	u32 vid_idx, vid_bit;
1579fdba3bf1SXiaoyun Wang 
1580fdba3bf1SXiaoyun Wang 	vid_idx = HINIC_VFTA_IDX(vlan_id);
1581fdba3bf1SXiaoyun Wang 	vid_bit = HINIC_VFTA_BIT(vlan_id);
1582fdba3bf1SXiaoyun Wang 
1583fdba3bf1SXiaoyun Wang 	if (on)
1584fdba3bf1SXiaoyun Wang 		nic_dev->vfta[vid_idx] |= vid_bit;
1585fdba3bf1SXiaoyun Wang 	else
1586fdba3bf1SXiaoyun Wang 		nic_dev->vfta[vid_idx] &= ~vid_bit;
1587fdba3bf1SXiaoyun Wang }
1588fdba3bf1SXiaoyun Wang 
1589fdba3bf1SXiaoyun Wang static bool hinic_find_vlan_filter(struct hinic_nic_dev *nic_dev,
1590fdba3bf1SXiaoyun Wang 				uint16_t vlan_id)
1591fdba3bf1SXiaoyun Wang {
1592fdba3bf1SXiaoyun Wang 	u32 vid_idx, vid_bit;
1593fdba3bf1SXiaoyun Wang 
1594fdba3bf1SXiaoyun Wang 	vid_idx = HINIC_VFTA_IDX(vlan_id);
1595fdba3bf1SXiaoyun Wang 	vid_bit = HINIC_VFTA_BIT(vlan_id);
1596fdba3bf1SXiaoyun Wang 
1597fdba3bf1SXiaoyun Wang 	return (nic_dev->vfta[vid_idx] & vid_bit) ? TRUE : FALSE;
1598fdba3bf1SXiaoyun Wang }
1599fdba3bf1SXiaoyun Wang 
1600fdba3bf1SXiaoyun Wang /**
1601fdba3bf1SXiaoyun Wang  * DPDK callback to set vlan filter.
1602fdba3bf1SXiaoyun Wang  *
1603fdba3bf1SXiaoyun Wang  * @param dev
1604fdba3bf1SXiaoyun Wang  *   Pointer to Ethernet device structure.
1605fdba3bf1SXiaoyun Wang  * @param vlan_id
1606fdba3bf1SXiaoyun Wang  *   vlan id is used to filter vlan packets
1607fdba3bf1SXiaoyun Wang  * @param enable
1608fdba3bf1SXiaoyun Wang  *   enable disable or enable vlan filter function
1609fdba3bf1SXiaoyun Wang  */
1610fdba3bf1SXiaoyun Wang static int hinic_vlan_filter_set(struct rte_eth_dev *dev,
1611fdba3bf1SXiaoyun Wang 				uint16_t vlan_id, int enable)
1612fdba3bf1SXiaoyun Wang {
1613fdba3bf1SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1614fdba3bf1SXiaoyun Wang 	int err = 0;
1615fdba3bf1SXiaoyun Wang 	u16 func_id;
1616fdba3bf1SXiaoyun Wang 
1617fdba3bf1SXiaoyun Wang 	if (vlan_id > RTE_ETHER_MAX_VLAN_ID)
1618fdba3bf1SXiaoyun Wang 		return -EINVAL;
1619fdba3bf1SXiaoyun Wang 
1620*2cfd68ecSGuoyang Zhou 	if (vlan_id == 0)
1621*2cfd68ecSGuoyang Zhou 		return 0;
1622*2cfd68ecSGuoyang Zhou 
1623fdba3bf1SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
1624fdba3bf1SXiaoyun Wang 
1625fdba3bf1SXiaoyun Wang 	if (enable) {
1626fdba3bf1SXiaoyun Wang 		/* If vlanid is already set, just return */
1627fdba3bf1SXiaoyun Wang 		if (hinic_find_vlan_filter(nic_dev, vlan_id)) {
1628fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(INFO, "Vlan %u has been added, device: %s",
1629fdba3bf1SXiaoyun Wang 				  vlan_id, nic_dev->proc_dev_name);
1630fdba3bf1SXiaoyun Wang 			return 0;
1631fdba3bf1SXiaoyun Wang 		}
1632fdba3bf1SXiaoyun Wang 
1633fdba3bf1SXiaoyun Wang 		err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id,
1634fdba3bf1SXiaoyun Wang 					    func_id, TRUE);
1635fdba3bf1SXiaoyun Wang 	} else {
1636fdba3bf1SXiaoyun Wang 		/* If vlanid can't be found, just return */
1637fdba3bf1SXiaoyun Wang 		if (!hinic_find_vlan_filter(nic_dev, vlan_id)) {
1638fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(INFO, "Vlan %u is not in the vlan filter list, device: %s",
1639fdba3bf1SXiaoyun Wang 				  vlan_id, nic_dev->proc_dev_name);
1640fdba3bf1SXiaoyun Wang 			return 0;
1641fdba3bf1SXiaoyun Wang 		}
1642fdba3bf1SXiaoyun Wang 
1643fdba3bf1SXiaoyun Wang 		err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id,
1644fdba3bf1SXiaoyun Wang 					    func_id, FALSE);
1645fdba3bf1SXiaoyun Wang 	}
1646fdba3bf1SXiaoyun Wang 
1647fdba3bf1SXiaoyun Wang 	if (err) {
1648fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(ERR, "%s vlan failed, func_id: %d, vlan_id: %d, err: %d",
1649fdba3bf1SXiaoyun Wang 		      enable ? "Add" : "Remove", func_id, vlan_id, err);
1650fdba3bf1SXiaoyun Wang 		return err;
1651fdba3bf1SXiaoyun Wang 	}
1652fdba3bf1SXiaoyun Wang 
1653fdba3bf1SXiaoyun Wang 	hinic_store_vlan_filter(nic_dev, vlan_id, enable);
1654fdba3bf1SXiaoyun Wang 
1655fdba3bf1SXiaoyun Wang 	PMD_DRV_LOG(INFO, "%s vlan %u succeed, device: %s",
1656fdba3bf1SXiaoyun Wang 		  enable ? "Add" : "Remove", vlan_id, nic_dev->proc_dev_name);
1657fdba3bf1SXiaoyun Wang 	return 0;
1658fdba3bf1SXiaoyun Wang }
1659fdba3bf1SXiaoyun Wang 
1660fdba3bf1SXiaoyun Wang /**
1661fdba3bf1SXiaoyun Wang  * DPDK callback to enable or disable vlan offload.
1662fdba3bf1SXiaoyun Wang  *
1663fdba3bf1SXiaoyun Wang  * @param dev
1664fdba3bf1SXiaoyun Wang  *   Pointer to Ethernet device structure.
1665fdba3bf1SXiaoyun Wang  * @param mask
1666fdba3bf1SXiaoyun Wang  *   Definitions used for VLAN setting
1667fdba3bf1SXiaoyun Wang  */
1668fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask)
1669fdba3bf1SXiaoyun Wang {
1670fdba3bf1SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1671fdba3bf1SXiaoyun Wang 	struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
1672fdba3bf1SXiaoyun Wang 	bool on;
1673fdba3bf1SXiaoyun Wang 	int err;
1674fdba3bf1SXiaoyun Wang 
1675fdba3bf1SXiaoyun Wang 	/* Enable or disable VLAN filter */
1676fdba3bf1SXiaoyun Wang 	if (mask & ETH_VLAN_FILTER_MASK) {
1677fdba3bf1SXiaoyun Wang 		on = (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_FILTER) ?
1678fdba3bf1SXiaoyun Wang 			TRUE : FALSE;
1679fdba3bf1SXiaoyun Wang 		err = hinic_config_vlan_filter(nic_dev->hwdev, on);
1680fdba3bf1SXiaoyun Wang 		if (err == HINIC_MGMT_CMD_UNSUPPORTED) {
1681fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(WARNING,
1682fdba3bf1SXiaoyun Wang 				"Current matching version does not support vlan filter configuration, device: %s, port_id: %d",
1683fdba3bf1SXiaoyun Wang 				  nic_dev->proc_dev_name, dev->data->port_id);
1684fdba3bf1SXiaoyun Wang 		} else if (err) {
1685fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Failed to %s vlan filter, device: %s, port_id: %d, err: %d",
1686fdba3bf1SXiaoyun Wang 				  on ? "enable" : "disable",
1687fdba3bf1SXiaoyun Wang 				  nic_dev->proc_dev_name,
1688fdba3bf1SXiaoyun Wang 				  dev->data->port_id, err);
1689fdba3bf1SXiaoyun Wang 			return err;
1690fdba3bf1SXiaoyun Wang 		}
1691fdba3bf1SXiaoyun Wang 
1692fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(INFO, "%s vlan filter succeed, device: %s, port_id: %d",
1693fdba3bf1SXiaoyun Wang 			  on ? "Enable" : "Disable",
1694fdba3bf1SXiaoyun Wang 			  nic_dev->proc_dev_name, dev->data->port_id);
1695fdba3bf1SXiaoyun Wang 	}
1696fdba3bf1SXiaoyun Wang 
1697fdba3bf1SXiaoyun Wang 	/* Enable or disable VLAN stripping */
1698fdba3bf1SXiaoyun Wang 	if (mask & ETH_VLAN_STRIP_MASK) {
1699fdba3bf1SXiaoyun Wang 		on = (rxmode->offloads & DEV_RX_OFFLOAD_VLAN_STRIP) ?
1700fdba3bf1SXiaoyun Wang 			TRUE : FALSE;
1701fdba3bf1SXiaoyun Wang 		err = hinic_set_rx_vlan_offload(nic_dev->hwdev, on);
1702fdba3bf1SXiaoyun Wang 		if (err) {
1703fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Failed to %s vlan strip, device: %s, port_id: %d, err: %d",
1704fdba3bf1SXiaoyun Wang 				  on ? "enable" : "disable",
1705fdba3bf1SXiaoyun Wang 				  nic_dev->proc_dev_name,
1706fdba3bf1SXiaoyun Wang 				  dev->data->port_id, err);
1707fdba3bf1SXiaoyun Wang 			return err;
1708fdba3bf1SXiaoyun Wang 		}
1709fdba3bf1SXiaoyun Wang 
1710fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(INFO, "%s vlan strip succeed, device: %s, port_id: %d",
1711fdba3bf1SXiaoyun Wang 			  on ? "Enable" : "Disable",
1712fdba3bf1SXiaoyun Wang 			  nic_dev->proc_dev_name, dev->data->port_id);
1713fdba3bf1SXiaoyun Wang 	}
1714fdba3bf1SXiaoyun Wang 
1715fdba3bf1SXiaoyun Wang 	return 0;
1716fdba3bf1SXiaoyun Wang }
1717fdba3bf1SXiaoyun Wang 
1718fdba3bf1SXiaoyun Wang static void hinic_remove_all_vlanid(struct rte_eth_dev *eth_dev)
1719fdba3bf1SXiaoyun Wang {
1720fdba3bf1SXiaoyun Wang 	struct hinic_nic_dev *nic_dev =
1721fdba3bf1SXiaoyun Wang 		HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
1722fdba3bf1SXiaoyun Wang 	u16 func_id;
1723fdba3bf1SXiaoyun Wang 	int i;
1724fdba3bf1SXiaoyun Wang 
1725fdba3bf1SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
1726fdba3bf1SXiaoyun Wang 	for (i = 0; i <= RTE_ETHER_MAX_VLAN_ID; i++) {
1727fdba3bf1SXiaoyun Wang 		/* If can't find it, continue */
1728fdba3bf1SXiaoyun Wang 		if (!hinic_find_vlan_filter(nic_dev, i))
1729fdba3bf1SXiaoyun Wang 			continue;
1730fdba3bf1SXiaoyun Wang 
1731fdba3bf1SXiaoyun Wang 		(void)hinic_add_remove_vlan(nic_dev->hwdev, i, func_id, FALSE);
1732fdba3bf1SXiaoyun Wang 		hinic_store_vlan_filter(nic_dev, i, false);
1733fdba3bf1SXiaoyun Wang 	}
1734fdba3bf1SXiaoyun Wang }
1735fdba3bf1SXiaoyun Wang 
17368260eba6SXiaoyun Wang static int hinic_set_dev_allmulticast(struct hinic_nic_dev *nic_dev,
17378260eba6SXiaoyun Wang 				bool enable)
17388260eba6SXiaoyun Wang {
1739224cff4bSXiaoyun Wang 	u32 rx_mode_ctrl;
1740224cff4bSXiaoyun Wang 	int err;
1741224cff4bSXiaoyun Wang 
1742224cff4bSXiaoyun Wang 	err = hinic_mutex_lock(&nic_dev->rx_mode_mutex);
1743224cff4bSXiaoyun Wang 	if (err)
1744224cff4bSXiaoyun Wang 		return err;
1745224cff4bSXiaoyun Wang 
1746224cff4bSXiaoyun Wang 	rx_mode_ctrl = nic_dev->rx_mode_status;
17478260eba6SXiaoyun Wang 
17488260eba6SXiaoyun Wang 	if (enable)
17498260eba6SXiaoyun Wang 		rx_mode_ctrl |= HINIC_RX_MODE_MC_ALL;
17508260eba6SXiaoyun Wang 	else
17518260eba6SXiaoyun Wang 		rx_mode_ctrl &= (~HINIC_RX_MODE_MC_ALL);
17528260eba6SXiaoyun Wang 
1753224cff4bSXiaoyun Wang 	err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
1754224cff4bSXiaoyun Wang 
1755224cff4bSXiaoyun Wang 	(void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex);
1756224cff4bSXiaoyun Wang 
1757224cff4bSXiaoyun Wang 	return err;
17588260eba6SXiaoyun Wang }
17598260eba6SXiaoyun Wang 
17608260eba6SXiaoyun Wang /**
17618260eba6SXiaoyun Wang  * DPDK callback to enable allmulticast mode.
17628260eba6SXiaoyun Wang  *
17638260eba6SXiaoyun Wang  * @param dev
17648260eba6SXiaoyun Wang  *   Pointer to Ethernet device structure.
17658260eba6SXiaoyun Wang  *
17668260eba6SXiaoyun Wang  * @return
17678260eba6SXiaoyun Wang  *   0 on success,
17688260eba6SXiaoyun Wang  *   negative error value otherwise.
17698260eba6SXiaoyun Wang  */
17708260eba6SXiaoyun Wang static int hinic_dev_allmulticast_enable(struct rte_eth_dev *dev)
17718260eba6SXiaoyun Wang {
17728260eba6SXiaoyun Wang 	int ret = HINIC_OK;
17738260eba6SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
17748260eba6SXiaoyun Wang 
17758260eba6SXiaoyun Wang 	ret = hinic_set_dev_allmulticast(nic_dev, true);
17768260eba6SXiaoyun Wang 	if (ret) {
17778260eba6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Enable allmulticast failed, error: %d", ret);
17788260eba6SXiaoyun Wang 		return ret;
17798260eba6SXiaoyun Wang 	}
17808260eba6SXiaoyun Wang 
17818260eba6SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Enable allmulticast succeed, nic_dev: %s, port_id: %d",
17828260eba6SXiaoyun Wang 		nic_dev->proc_dev_name, dev->data->port_id);
17838260eba6SXiaoyun Wang 	return 0;
17848260eba6SXiaoyun Wang }
17858260eba6SXiaoyun Wang 
17868260eba6SXiaoyun Wang /**
17878260eba6SXiaoyun Wang  * DPDK callback to disable allmulticast mode.
17888260eba6SXiaoyun Wang  *
17898260eba6SXiaoyun Wang  * @param dev
17908260eba6SXiaoyun Wang  *   Pointer to Ethernet device structure.
17918260eba6SXiaoyun Wang  *
17928260eba6SXiaoyun Wang  * @return
17938260eba6SXiaoyun Wang  *   0 on success,
17948260eba6SXiaoyun Wang  *   negative error value otherwise.
17958260eba6SXiaoyun Wang  */
17968260eba6SXiaoyun Wang static int hinic_dev_allmulticast_disable(struct rte_eth_dev *dev)
17978260eba6SXiaoyun Wang {
17988260eba6SXiaoyun Wang 	int ret = HINIC_OK;
17998260eba6SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
18008260eba6SXiaoyun Wang 
18018260eba6SXiaoyun Wang 	ret = hinic_set_dev_allmulticast(nic_dev, false);
18028260eba6SXiaoyun Wang 	if (ret) {
18038260eba6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Disable allmulticast failed, error: %d", ret);
18048260eba6SXiaoyun Wang 		return ret;
18058260eba6SXiaoyun Wang 	}
18068260eba6SXiaoyun Wang 
18078260eba6SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Disable allmulticast succeed, nic_dev: %s, port_id: %d",
18088260eba6SXiaoyun Wang 		nic_dev->proc_dev_name, dev->data->port_id);
18098260eba6SXiaoyun Wang 	return 0;
18108260eba6SXiaoyun Wang }
18118260eba6SXiaoyun Wang 
1812cb7b6606SZiyang Xuan /**
1813cb7b6606SZiyang Xuan  * DPDK callback to enable promiscuous mode.
1814cb7b6606SZiyang Xuan  *
1815cb7b6606SZiyang Xuan  * @param dev
1816cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
18179039c812SAndrew Rybchenko  *
18189039c812SAndrew Rybchenko  * @return
18199039c812SAndrew Rybchenko  *   0 on success,
18209039c812SAndrew Rybchenko  *   negative error value otherwise.
1821cb7b6606SZiyang Xuan  */
18229039c812SAndrew Rybchenko static int hinic_dev_promiscuous_enable(struct rte_eth_dev *dev)
1823cb7b6606SZiyang Xuan {
1824cb7b6606SZiyang Xuan 	int rc = HINIC_OK;
1825cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1826cb7b6606SZiyang Xuan 
1827cb7b6606SZiyang Xuan 	PMD_DRV_LOG(INFO, "Enable promiscuous, nic_dev: %s, port_id: %d, promisc: %d",
1828cb7b6606SZiyang Xuan 		    nic_dev->proc_dev_name, dev->data->port_id,
1829cb7b6606SZiyang Xuan 		    dev->data->promiscuous);
1830cb7b6606SZiyang Xuan 
1831cb7b6606SZiyang Xuan 	rc = hinic_set_dev_promiscuous(nic_dev, true);
1832cb7b6606SZiyang Xuan 	if (rc)
1833cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Enable promiscuous failed");
18349039c812SAndrew Rybchenko 
18359039c812SAndrew Rybchenko 	return rc;
1836cb7b6606SZiyang Xuan }
1837cb7b6606SZiyang Xuan 
1838cb7b6606SZiyang Xuan /**
1839cb7b6606SZiyang Xuan  * DPDK callback to disable promiscuous mode.
1840cb7b6606SZiyang Xuan  *
1841cb7b6606SZiyang Xuan  * @param dev
1842cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
18439039c812SAndrew Rybchenko  *
18449039c812SAndrew Rybchenko  * @return
18459039c812SAndrew Rybchenko  *   0 on success,
18469039c812SAndrew Rybchenko  *   negative error value otherwise.
1847cb7b6606SZiyang Xuan  */
18489039c812SAndrew Rybchenko static int hinic_dev_promiscuous_disable(struct rte_eth_dev *dev)
1849cb7b6606SZiyang Xuan {
1850cb7b6606SZiyang Xuan 	int rc = HINIC_OK;
1851cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1852cb7b6606SZiyang Xuan 
1853cb7b6606SZiyang Xuan 	PMD_DRV_LOG(INFO, "Disable promiscuous, nic_dev: %s, port_id: %d, promisc: %d",
1854cb7b6606SZiyang Xuan 		    nic_dev->proc_dev_name, dev->data->port_id,
1855cb7b6606SZiyang Xuan 		    dev->data->promiscuous);
1856cb7b6606SZiyang Xuan 
1857cb7b6606SZiyang Xuan 	rc = hinic_set_dev_promiscuous(nic_dev, false);
1858cb7b6606SZiyang Xuan 	if (rc)
1859cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Disable promiscuous failed");
18609039c812SAndrew Rybchenko 
18619039c812SAndrew Rybchenko 	return rc;
1862cb7b6606SZiyang Xuan }
1863cb7b6606SZiyang Xuan 
1864ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_get(struct rte_eth_dev *dev,
1865ef6f2f5cSXiaoyun Wang 			struct rte_eth_fc_conf *fc_conf)
1866ef6f2f5cSXiaoyun Wang {
1867ef6f2f5cSXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1868ef6f2f5cSXiaoyun Wang 	struct nic_pause_config nic_pause;
1869ef6f2f5cSXiaoyun Wang 	int err;
1870ef6f2f5cSXiaoyun Wang 
1871ef6f2f5cSXiaoyun Wang 	memset(&nic_pause, 0, sizeof(nic_pause));
1872ef6f2f5cSXiaoyun Wang 
1873ef6f2f5cSXiaoyun Wang 	err = hinic_get_pause_info(nic_dev->hwdev, &nic_pause);
1874ef6f2f5cSXiaoyun Wang 	if (err)
1875ef6f2f5cSXiaoyun Wang 		return err;
1876ef6f2f5cSXiaoyun Wang 
1877ef6f2f5cSXiaoyun Wang 	if (nic_dev->pause_set || !nic_pause.auto_neg) {
1878ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause = nic_dev->nic_pause.rx_pause;
1879ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause = nic_dev->nic_pause.tx_pause;
1880ef6f2f5cSXiaoyun Wang 	}
1881ef6f2f5cSXiaoyun Wang 
1882ef6f2f5cSXiaoyun Wang 	fc_conf->autoneg = nic_pause.auto_neg;
1883ef6f2f5cSXiaoyun Wang 
1884ef6f2f5cSXiaoyun Wang 	if (nic_pause.tx_pause && nic_pause.rx_pause)
1885ef6f2f5cSXiaoyun Wang 		fc_conf->mode = RTE_FC_FULL;
1886ef6f2f5cSXiaoyun Wang 	else if (nic_pause.tx_pause)
1887ef6f2f5cSXiaoyun Wang 		fc_conf->mode = RTE_FC_TX_PAUSE;
1888ef6f2f5cSXiaoyun Wang 	else if (nic_pause.rx_pause)
1889ef6f2f5cSXiaoyun Wang 		fc_conf->mode = RTE_FC_RX_PAUSE;
1890ef6f2f5cSXiaoyun Wang 	else
1891ef6f2f5cSXiaoyun Wang 		fc_conf->mode = RTE_FC_NONE;
1892ef6f2f5cSXiaoyun Wang 
1893ef6f2f5cSXiaoyun Wang 	return 0;
1894ef6f2f5cSXiaoyun Wang }
1895ef6f2f5cSXiaoyun Wang 
1896ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_set(struct rte_eth_dev *dev,
1897ef6f2f5cSXiaoyun Wang 			struct rte_eth_fc_conf *fc_conf)
1898ef6f2f5cSXiaoyun Wang {
1899ef6f2f5cSXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1900ef6f2f5cSXiaoyun Wang 	struct nic_pause_config nic_pause;
1901ef6f2f5cSXiaoyun Wang 	int err;
1902ef6f2f5cSXiaoyun Wang 
1903ef6f2f5cSXiaoyun Wang 	nic_pause.auto_neg = fc_conf->autoneg;
1904ef6f2f5cSXiaoyun Wang 
1905ef6f2f5cSXiaoyun Wang 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
1906ef6f2f5cSXiaoyun Wang 		(fc_conf->mode & RTE_FC_TX_PAUSE))
1907ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause = true;
1908ef6f2f5cSXiaoyun Wang 	else
1909ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause = false;
1910ef6f2f5cSXiaoyun Wang 
1911ef6f2f5cSXiaoyun Wang 	if (((fc_conf->mode & RTE_FC_FULL) == RTE_FC_FULL) ||
1912ef6f2f5cSXiaoyun Wang 		(fc_conf->mode & RTE_FC_RX_PAUSE))
1913ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause = true;
1914ef6f2f5cSXiaoyun Wang 	else
1915ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause = false;
1916ef6f2f5cSXiaoyun Wang 
1917ef6f2f5cSXiaoyun Wang 	err = hinic_set_pause_config(nic_dev->hwdev, nic_pause);
1918ef6f2f5cSXiaoyun Wang 	if (err)
1919ef6f2f5cSXiaoyun Wang 		return err;
1920ef6f2f5cSXiaoyun Wang 
1921ef6f2f5cSXiaoyun Wang 	nic_dev->pause_set = true;
1922ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.auto_neg = nic_pause.auto_neg;
1923ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.rx_pause = nic_pause.rx_pause;
1924ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.tx_pause = nic_pause.tx_pause;
1925ef6f2f5cSXiaoyun Wang 
1926036b61d8SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Set pause options, tx: %s, rx: %s, auto: %s\n",
1927ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause ? "on" : "off",
1928ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause ? "on" : "off",
1929ef6f2f5cSXiaoyun Wang 		nic_pause.auto_neg ? "on" : "off");
1930ef6f2f5cSXiaoyun Wang 
1931ef6f2f5cSXiaoyun Wang 	return 0;
1932ef6f2f5cSXiaoyun Wang }
1933ef6f2f5cSXiaoyun Wang 
1934cb7b6606SZiyang Xuan /**
1935cb7b6606SZiyang Xuan  * DPDK callback to update the RSS hash key and RSS hash type.
1936cb7b6606SZiyang Xuan  *
1937cb7b6606SZiyang Xuan  * @param dev
1938cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
1939cb7b6606SZiyang Xuan  * @param rss_conf
1940cb7b6606SZiyang Xuan  *   RSS configuration data.
1941cb7b6606SZiyang Xuan  *
1942cb7b6606SZiyang Xuan  * @return
1943cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
1944cb7b6606SZiyang Xuan  */
1945cb7b6606SZiyang Xuan static int hinic_rss_hash_update(struct rte_eth_dev *dev,
1946cb7b6606SZiyang Xuan 			  struct rte_eth_rss_conf *rss_conf)
1947cb7b6606SZiyang Xuan {
1948cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1949cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
1950cb7b6606SZiyang Xuan 	u8 hashkey[HINIC_RSS_KEY_SIZE] = {0};
1951cb7b6606SZiyang Xuan 	u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
1952cb7b6606SZiyang Xuan 	u64 rss_hf = rss_conf->rss_hf;
1953cb7b6606SZiyang Xuan 	struct nic_rss_type rss_type = {0};
1954cb7b6606SZiyang Xuan 	int err = 0;
1955cb7b6606SZiyang Xuan 
1956cb7b6606SZiyang Xuan 	if (!(nic_dev->flags & ETH_MQ_RX_RSS_FLAG)) {
1957cb7b6606SZiyang Xuan 		PMD_DRV_LOG(WARNING, "RSS is not enabled");
1958cb7b6606SZiyang Xuan 		return HINIC_OK;
1959cb7b6606SZiyang Xuan 	}
1960cb7b6606SZiyang Xuan 
1961cb7b6606SZiyang Xuan 	if (rss_conf->rss_key_len > HINIC_RSS_KEY_SIZE) {
1962cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid rss key, rss_key_len: %d",
1963cb7b6606SZiyang Xuan 			    rss_conf->rss_key_len);
1964cb7b6606SZiyang Xuan 		return HINIC_ERROR;
1965cb7b6606SZiyang Xuan 	}
1966cb7b6606SZiyang Xuan 
1967cb7b6606SZiyang Xuan 	if (rss_conf->rss_key) {
1968cb7b6606SZiyang Xuan 		memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len);
1969cb7b6606SZiyang Xuan 		err = hinic_rss_set_template_tbl(nic_dev->hwdev, tmpl_idx,
1970cb7b6606SZiyang Xuan 						 hashkey);
1971cb7b6606SZiyang Xuan 		if (err) {
1972cb7b6606SZiyang Xuan 			PMD_DRV_LOG(ERR, "Set rss template table failed");
1973cb7b6606SZiyang Xuan 			goto disable_rss;
1974cb7b6606SZiyang Xuan 		}
1975cb7b6606SZiyang Xuan 	}
1976cb7b6606SZiyang Xuan 
1977cb7b6606SZiyang Xuan 	rss_type.ipv4 = (rss_hf & (ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4)) ? 1 : 0;
1978cb7b6606SZiyang Xuan 	rss_type.tcp_ipv4 = (rss_hf & ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0;
1979cb7b6606SZiyang Xuan 	rss_type.ipv6 = (rss_hf & (ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6)) ? 1 : 0;
1980cb7b6606SZiyang Xuan 	rss_type.ipv6_ext = (rss_hf & ETH_RSS_IPV6_EX) ? 1 : 0;
1981cb7b6606SZiyang Xuan 	rss_type.tcp_ipv6 = (rss_hf & ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0;
1982cb7b6606SZiyang Xuan 	rss_type.tcp_ipv6_ext = (rss_hf & ETH_RSS_IPV6_TCP_EX) ? 1 : 0;
1983cb7b6606SZiyang Xuan 	rss_type.udp_ipv4 = (rss_hf & ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0;
1984cb7b6606SZiyang Xuan 	rss_type.udp_ipv6 = (rss_hf & ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0;
1985cb7b6606SZiyang Xuan 
1986cb7b6606SZiyang Xuan 	err = hinic_set_rss_type(nic_dev->hwdev, tmpl_idx, rss_type);
1987cb7b6606SZiyang Xuan 	if (err) {
1988cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Set rss type table failed");
1989cb7b6606SZiyang Xuan 		goto disable_rss;
1990cb7b6606SZiyang Xuan 	}
1991cb7b6606SZiyang Xuan 
1992cb7b6606SZiyang Xuan 	return 0;
1993cb7b6606SZiyang Xuan 
1994cb7b6606SZiyang Xuan disable_rss:
1995cb7b6606SZiyang Xuan 	memset(prio_tc, 0, sizeof(prio_tc));
1996cb7b6606SZiyang Xuan 	(void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc);
1997cb7b6606SZiyang Xuan 	return err;
1998cb7b6606SZiyang Xuan }
1999cb7b6606SZiyang Xuan 
2000cb7b6606SZiyang Xuan /**
2001cb7b6606SZiyang Xuan  * DPDK callback to get the RSS hash configuration.
2002cb7b6606SZiyang Xuan  *
2003cb7b6606SZiyang Xuan  * @param dev
2004cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
2005cb7b6606SZiyang Xuan  * @param rss_conf
2006cb7b6606SZiyang Xuan  *   RSS configuration data.
2007cb7b6606SZiyang Xuan  *
2008cb7b6606SZiyang Xuan  * @return
2009cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
2010cb7b6606SZiyang Xuan  */
2011cb7b6606SZiyang Xuan static int hinic_rss_conf_get(struct rte_eth_dev *dev,
2012cb7b6606SZiyang Xuan 		       struct rte_eth_rss_conf *rss_conf)
2013cb7b6606SZiyang Xuan {
2014cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2015cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
2016cb7b6606SZiyang Xuan 	u8 hashkey[HINIC_RSS_KEY_SIZE] = {0};
2017cb7b6606SZiyang Xuan 	struct nic_rss_type rss_type = {0};
2018cb7b6606SZiyang Xuan 	int err;
2019cb7b6606SZiyang Xuan 
2020cb7b6606SZiyang Xuan 	if (!(nic_dev->flags & ETH_MQ_RX_RSS_FLAG)) {
2021cb7b6606SZiyang Xuan 		PMD_DRV_LOG(WARNING, "RSS is not enabled");
2022cb7b6606SZiyang Xuan 		return HINIC_ERROR;
2023cb7b6606SZiyang Xuan 	}
2024cb7b6606SZiyang Xuan 
2025cb7b6606SZiyang Xuan 	err = hinic_rss_get_template_tbl(nic_dev->hwdev, tmpl_idx, hashkey);
2026cb7b6606SZiyang Xuan 	if (err)
2027cb7b6606SZiyang Xuan 		return err;
2028cb7b6606SZiyang Xuan 
2029cb7b6606SZiyang Xuan 	if (rss_conf->rss_key &&
2030cb7b6606SZiyang Xuan 	    rss_conf->rss_key_len >= HINIC_RSS_KEY_SIZE) {
2031cb7b6606SZiyang Xuan 		memcpy(rss_conf->rss_key, hashkey, sizeof(hashkey));
2032cb7b6606SZiyang Xuan 		rss_conf->rss_key_len = sizeof(hashkey);
2033cb7b6606SZiyang Xuan 	}
2034cb7b6606SZiyang Xuan 
2035cb7b6606SZiyang Xuan 	err = hinic_get_rss_type(nic_dev->hwdev, tmpl_idx, &rss_type);
2036cb7b6606SZiyang Xuan 	if (err)
2037cb7b6606SZiyang Xuan 		return err;
2038cb7b6606SZiyang Xuan 
2039cb7b6606SZiyang Xuan 	rss_conf->rss_hf = 0;
2040cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.ipv4 ?
2041cb7b6606SZiyang Xuan 		(ETH_RSS_IPV4 | ETH_RSS_FRAG_IPV4) : 0;
2042cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.tcp_ipv4 ? ETH_RSS_NONFRAG_IPV4_TCP : 0;
2043cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.ipv6 ?
2044cb7b6606SZiyang Xuan 		(ETH_RSS_IPV6 | ETH_RSS_FRAG_IPV6) : 0;
2045cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.ipv6_ext ? ETH_RSS_IPV6_EX : 0;
2046cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.tcp_ipv6 ? ETH_RSS_NONFRAG_IPV6_TCP : 0;
2047cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.tcp_ipv6_ext ? ETH_RSS_IPV6_TCP_EX : 0;
2048cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.udp_ipv4 ? ETH_RSS_NONFRAG_IPV4_UDP : 0;
2049cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.udp_ipv6 ? ETH_RSS_NONFRAG_IPV6_UDP : 0;
2050cb7b6606SZiyang Xuan 
2051cb7b6606SZiyang Xuan 	return HINIC_OK;
2052cb7b6606SZiyang Xuan }
2053cb7b6606SZiyang Xuan 
2054cb7b6606SZiyang Xuan /**
2055f372a65fSXiaoyun Wang  * DPDK callback to update the RSS redirection table.
2056cb7b6606SZiyang Xuan  *
2057cb7b6606SZiyang Xuan  * @param dev
2058cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
2059cb7b6606SZiyang Xuan  * @param reta_conf
2060f372a65fSXiaoyun Wang  *   Pointer to RSS reta configuration data.
2061cb7b6606SZiyang Xuan  * @param reta_size
2062cb7b6606SZiyang Xuan  *   Size of the RETA table.
2063cb7b6606SZiyang Xuan  *
2064cb7b6606SZiyang Xuan  * @return
2065cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
2066cb7b6606SZiyang Xuan  */
2067cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_update(struct rte_eth_dev *dev,
2068cb7b6606SZiyang Xuan 			      struct rte_eth_rss_reta_entry64 *reta_conf,
2069cb7b6606SZiyang Xuan 			      uint16_t reta_size)
2070cb7b6606SZiyang Xuan {
2071cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2072cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
2073cb7b6606SZiyang Xuan 	u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
2074cb7b6606SZiyang Xuan 	u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0};
2075cb7b6606SZiyang Xuan 	int err = 0;
2076cb7b6606SZiyang Xuan 	u16 i = 0;
2077cb7b6606SZiyang Xuan 	u16 idx, shift;
2078cb7b6606SZiyang Xuan 
2079cb7b6606SZiyang Xuan 	if (!(nic_dev->flags & ETH_MQ_RX_RSS_FLAG))
2080cb7b6606SZiyang Xuan 		return HINIC_OK;
2081cb7b6606SZiyang Xuan 
2082cb7b6606SZiyang Xuan 	if (reta_size != NIC_RSS_INDIR_SIZE) {
2083cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size);
2084cb7b6606SZiyang Xuan 		return HINIC_ERROR;
2085cb7b6606SZiyang Xuan 	}
2086cb7b6606SZiyang Xuan 
2087cb7b6606SZiyang Xuan 	err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl);
2088cb7b6606SZiyang Xuan 	if (err)
2089cb7b6606SZiyang Xuan 		return err;
2090cb7b6606SZiyang Xuan 
2091cb7b6606SZiyang Xuan 	/* update rss indir_tbl */
2092cb7b6606SZiyang Xuan 	for (i = 0; i < reta_size; i++) {
2093cb7b6606SZiyang Xuan 		idx = i / RTE_RETA_GROUP_SIZE;
2094cb7b6606SZiyang Xuan 		shift = i % RTE_RETA_GROUP_SIZE;
209572babbc0SXiaoyun Wang 
209672babbc0SXiaoyun Wang 		if (reta_conf[idx].reta[shift] >= nic_dev->num_rq) {
209772babbc0SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Invalid reta entry, indirtbl[%d]: %d "
209872babbc0SXiaoyun Wang 				"exceeds the maximum rxq num: %d", i,
209972babbc0SXiaoyun Wang 				reta_conf[idx].reta[shift], nic_dev->num_rq);
210072babbc0SXiaoyun Wang 			return -EINVAL;
2101cb7b6606SZiyang Xuan 		}
2102cb7b6606SZiyang Xuan 
210372babbc0SXiaoyun Wang 		if (reta_conf[idx].mask & (1ULL << shift))
210472babbc0SXiaoyun Wang 			indirtbl[i] = reta_conf[idx].reta[shift];
2105cb7b6606SZiyang Xuan 	}
2106cb7b6606SZiyang Xuan 
2107cb7b6606SZiyang Xuan 	err = hinic_rss_set_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl);
2108cb7b6606SZiyang Xuan 	if (err)
2109cb7b6606SZiyang Xuan 		goto disable_rss;
2110cb7b6606SZiyang Xuan 
2111cb7b6606SZiyang Xuan 	nic_dev->rss_indir_flag = true;
2112cb7b6606SZiyang Xuan 
2113cb7b6606SZiyang Xuan 	return 0;
2114cb7b6606SZiyang Xuan 
2115cb7b6606SZiyang Xuan disable_rss:
2116cb7b6606SZiyang Xuan 	memset(prio_tc, 0, sizeof(prio_tc));
2117cb7b6606SZiyang Xuan 	(void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc);
2118cb7b6606SZiyang Xuan 
2119cb7b6606SZiyang Xuan 	return HINIC_ERROR;
2120cb7b6606SZiyang Xuan }
2121cb7b6606SZiyang Xuan 
2122cb7b6606SZiyang Xuan /**
2123f372a65fSXiaoyun Wang  * DPDK callback to get the RSS indirection table.
2124cb7b6606SZiyang Xuan  *
2125cb7b6606SZiyang Xuan  * @param dev
2126cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
2127cb7b6606SZiyang Xuan  * @param reta_conf
2128f372a65fSXiaoyun Wang  *   Pointer to RSS reta configuration data.
2129cb7b6606SZiyang Xuan  * @param reta_size
2130cb7b6606SZiyang Xuan  *   Size of the RETA table.
2131cb7b6606SZiyang Xuan  *
2132cb7b6606SZiyang Xuan  * @return
2133cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
2134cb7b6606SZiyang Xuan  */
2135cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_query(struct rte_eth_dev *dev,
2136cb7b6606SZiyang Xuan 			     struct rte_eth_rss_reta_entry64 *reta_conf,
2137cb7b6606SZiyang Xuan 			     uint16_t reta_size)
2138cb7b6606SZiyang Xuan {
2139cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2140cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
2141cb7b6606SZiyang Xuan 	int err = 0;
2142cb7b6606SZiyang Xuan 	u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0};
2143cb7b6606SZiyang Xuan 	u16 idx, shift;
2144cb7b6606SZiyang Xuan 	u16 i = 0;
2145cb7b6606SZiyang Xuan 
2146cb7b6606SZiyang Xuan 	if (reta_size != NIC_RSS_INDIR_SIZE) {
2147cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size);
2148cb7b6606SZiyang Xuan 		return HINIC_ERROR;
2149cb7b6606SZiyang Xuan 	}
2150cb7b6606SZiyang Xuan 
2151cb7b6606SZiyang Xuan 	err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl);
2152cb7b6606SZiyang Xuan 	if (err) {
2153cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Get rss indirect table failed, error: %d",
2154cb7b6606SZiyang Xuan 			    err);
2155cb7b6606SZiyang Xuan 		return err;
2156cb7b6606SZiyang Xuan 	}
2157cb7b6606SZiyang Xuan 
2158cb7b6606SZiyang Xuan 	for (i = 0; i < reta_size; i++) {
2159cb7b6606SZiyang Xuan 		idx = i / RTE_RETA_GROUP_SIZE;
2160cb7b6606SZiyang Xuan 		shift = i % RTE_RETA_GROUP_SIZE;
2161cb7b6606SZiyang Xuan 		if (reta_conf[idx].mask & (1ULL << shift))
2162cb7b6606SZiyang Xuan 			reta_conf[idx].reta[shift] = (uint16_t)indirtbl[i];
2163cb7b6606SZiyang Xuan 	}
2164cb7b6606SZiyang Xuan 
2165cb7b6606SZiyang Xuan 	return HINIC_OK;
2166cb7b6606SZiyang Xuan }
2167cb7b6606SZiyang Xuan 
2168cb7b6606SZiyang Xuan /**
2169cb7b6606SZiyang Xuan  * DPDK callback to get extended device statistics.
2170cb7b6606SZiyang Xuan  *
2171cb7b6606SZiyang Xuan  * @param dev
2172cb7b6606SZiyang Xuan  *   Pointer to Ethernet device.
2173cb7b6606SZiyang Xuan  * @param xstats
2174cb7b6606SZiyang Xuan  *   Pointer to rte extended stats table.
2175cb7b6606SZiyang Xuan  * @param n
2176cb7b6606SZiyang Xuan  *   The size of the stats table.
2177cb7b6606SZiyang Xuan  *
2178cb7b6606SZiyang Xuan  * @return
2179cb7b6606SZiyang Xuan  *   Number of extended stats on success and stats is filled,
2180cb7b6606SZiyang Xuan  *   negative error value otherwise.
2181cb7b6606SZiyang Xuan  */
2182cb7b6606SZiyang Xuan static int hinic_dev_xstats_get(struct rte_eth_dev *dev,
2183cb7b6606SZiyang Xuan 			 struct rte_eth_xstat *xstats,
2184cb7b6606SZiyang Xuan 			 unsigned int n)
2185cb7b6606SZiyang Xuan {
2186cb7b6606SZiyang Xuan 	u16 qid = 0;
2187cb7b6606SZiyang Xuan 	u32 i;
2188cb7b6606SZiyang Xuan 	int err, count;
2189cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
2190cb7b6606SZiyang Xuan 	struct hinic_phy_port_stats port_stats;
2191cb7b6606SZiyang Xuan 	struct hinic_vport_stats vport_stats;
2192cb7b6606SZiyang Xuan 	struct hinic_rxq	*rxq = NULL;
2193cb7b6606SZiyang Xuan 	struct hinic_rxq_stats rxq_stats;
2194cb7b6606SZiyang Xuan 	struct hinic_txq	*txq = NULL;
2195cb7b6606SZiyang Xuan 	struct hinic_txq_stats txq_stats;
2196cb7b6606SZiyang Xuan 
2197cb7b6606SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2198cb7b6606SZiyang Xuan 	count = hinic_xstats_calc_num(nic_dev);
2199cb7b6606SZiyang Xuan 	if ((int)n < count)
2200cb7b6606SZiyang Xuan 		return count;
2201cb7b6606SZiyang Xuan 
2202cb7b6606SZiyang Xuan 	count = 0;
2203cb7b6606SZiyang Xuan 
2204cb7b6606SZiyang Xuan 	/* Get stats from hinic_rxq_stats */
2205cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_rq; qid++) {
2206cb7b6606SZiyang Xuan 		rxq = nic_dev->rxqs[qid];
2207cb7b6606SZiyang Xuan 		hinic_rxq_get_stats(rxq, &rxq_stats);
2208cb7b6606SZiyang Xuan 
2209cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) {
2210cb7b6606SZiyang Xuan 			xstats[count].value =
2211cb7b6606SZiyang Xuan 				*(uint64_t *)(((char *)&rxq_stats) +
2212cb7b6606SZiyang Xuan 				hinic_rxq_stats_strings[i].offset);
2213cb7b6606SZiyang Xuan 			xstats[count].id = count;
2214cb7b6606SZiyang Xuan 			count++;
2215cb7b6606SZiyang Xuan 		}
2216cb7b6606SZiyang Xuan 	}
2217cb7b6606SZiyang Xuan 
2218cb7b6606SZiyang Xuan 	/* Get stats from hinic_txq_stats */
2219cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_sq; qid++) {
2220cb7b6606SZiyang Xuan 		txq = nic_dev->txqs[qid];
2221cb7b6606SZiyang Xuan 		hinic_txq_get_stats(txq, &txq_stats);
2222cb7b6606SZiyang Xuan 
2223cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) {
2224cb7b6606SZiyang Xuan 			xstats[count].value =
2225cb7b6606SZiyang Xuan 				*(uint64_t *)(((char *)&txq_stats) +
2226cb7b6606SZiyang Xuan 				hinic_txq_stats_strings[i].offset);
2227cb7b6606SZiyang Xuan 			xstats[count].id = count;
2228cb7b6606SZiyang Xuan 			count++;
2229cb7b6606SZiyang Xuan 		}
2230cb7b6606SZiyang Xuan 	}
2231cb7b6606SZiyang Xuan 
2232cb7b6606SZiyang Xuan 	/* Get stats from hinic_vport_stats */
2233cb7b6606SZiyang Xuan 	err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats);
2234cb7b6606SZiyang Xuan 	if (err)
2235cb7b6606SZiyang Xuan 		return err;
2236cb7b6606SZiyang Xuan 
2237cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) {
2238cb7b6606SZiyang Xuan 		xstats[count].value =
2239cb7b6606SZiyang Xuan 			*(uint64_t *)(((char *)&vport_stats) +
2240cb7b6606SZiyang Xuan 			hinic_vport_stats_strings[i].offset);
2241cb7b6606SZiyang Xuan 		xstats[count].id = count;
2242cb7b6606SZiyang Xuan 		count++;
2243cb7b6606SZiyang Xuan 	}
2244cb7b6606SZiyang Xuan 
22456691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev))
22466691acefSXiaoyun Wang 		return count;
22476691acefSXiaoyun Wang 
2248cb7b6606SZiyang Xuan 	/* Get stats from hinic_phy_port_stats */
2249cb7b6606SZiyang Xuan 	err = hinic_get_phy_port_stats(nic_dev->hwdev, &port_stats);
2250cb7b6606SZiyang Xuan 	if (err)
2251cb7b6606SZiyang Xuan 		return err;
2252cb7b6606SZiyang Xuan 
2253cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) {
2254cb7b6606SZiyang Xuan 		xstats[count].value = *(uint64_t *)(((char *)&port_stats) +
2255cb7b6606SZiyang Xuan 				hinic_phyport_stats_strings[i].offset);
2256cb7b6606SZiyang Xuan 		xstats[count].id = count;
2257cb7b6606SZiyang Xuan 		count++;
2258cb7b6606SZiyang Xuan 	}
2259cb7b6606SZiyang Xuan 
2260cb7b6606SZiyang Xuan 	return count;
2261cb7b6606SZiyang Xuan }
2262cb7b6606SZiyang Xuan 
2263483b4817SXiaoyun Wang static void hinic_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
2264483b4817SXiaoyun Wang 				struct rte_eth_rxq_info *qinfo)
2265483b4817SXiaoyun Wang {
2266483b4817SXiaoyun Wang 	struct hinic_rxq  *rxq = dev->data->rx_queues[queue_id];
2267483b4817SXiaoyun Wang 
2268483b4817SXiaoyun Wang 	qinfo->mp = rxq->mb_pool;
2269483b4817SXiaoyun Wang 	qinfo->nb_desc = rxq->q_depth;
2270483b4817SXiaoyun Wang }
2271483b4817SXiaoyun Wang 
2272483b4817SXiaoyun Wang static void hinic_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
2273483b4817SXiaoyun Wang 				struct rte_eth_txq_info *qinfo)
2274483b4817SXiaoyun Wang {
2275483b4817SXiaoyun Wang 	struct hinic_txq  *txq = dev->data->tx_queues[queue_id];
2276483b4817SXiaoyun Wang 
2277483b4817SXiaoyun Wang 	qinfo->nb_desc = txq->q_depth;
2278483b4817SXiaoyun Wang }
2279483b4817SXiaoyun Wang 
2280cb7b6606SZiyang Xuan /**
2281cb7b6606SZiyang Xuan  * DPDK callback to retrieve names of extended device statistics
2282cb7b6606SZiyang Xuan  *
2283cb7b6606SZiyang Xuan  * @param dev
2284cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
2285cb7b6606SZiyang Xuan  * @param xstats_names
2286cb7b6606SZiyang Xuan  *   Buffer to insert names into.
2287cb7b6606SZiyang Xuan  *
2288cb7b6606SZiyang Xuan  * @return
2289cb7b6606SZiyang Xuan  *   Number of xstats names.
2290cb7b6606SZiyang Xuan  */
2291cb7b6606SZiyang Xuan static int hinic_dev_xstats_get_names(struct rte_eth_dev *dev,
2292cb7b6606SZiyang Xuan 			       struct rte_eth_xstat_name *xstats_names,
2293cb7b6606SZiyang Xuan 			       __rte_unused unsigned int limit)
2294cb7b6606SZiyang Xuan {
2295cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2296cb7b6606SZiyang Xuan 	int count = 0;
2297cb7b6606SZiyang Xuan 	u16 i = 0, q_num;
2298cb7b6606SZiyang Xuan 
2299cb7b6606SZiyang Xuan 	if (xstats_names == NULL)
2300cb7b6606SZiyang Xuan 		return hinic_xstats_calc_num(nic_dev);
2301cb7b6606SZiyang Xuan 
2302cb7b6606SZiyang Xuan 	/* get pmd rxq stats */
2303cb7b6606SZiyang Xuan 	for (q_num = 0; q_num < nic_dev->num_rq; q_num++) {
2304cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) {
2305cb7b6606SZiyang Xuan 			snprintf(xstats_names[count].name,
2306cb7b6606SZiyang Xuan 				 sizeof(xstats_names[count].name),
2307cb7b6606SZiyang Xuan 				 "rxq%d_%s_pmd",
2308cb7b6606SZiyang Xuan 				 q_num, hinic_rxq_stats_strings[i].name);
2309cb7b6606SZiyang Xuan 			count++;
2310cb7b6606SZiyang Xuan 		}
2311cb7b6606SZiyang Xuan 	}
2312cb7b6606SZiyang Xuan 
2313cb7b6606SZiyang Xuan 	/* get pmd txq stats */
2314cb7b6606SZiyang Xuan 	for (q_num = 0; q_num < nic_dev->num_sq; q_num++) {
2315cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) {
2316cb7b6606SZiyang Xuan 			snprintf(xstats_names[count].name,
2317cb7b6606SZiyang Xuan 				 sizeof(xstats_names[count].name),
2318cb7b6606SZiyang Xuan 				 "txq%d_%s_pmd",
2319cb7b6606SZiyang Xuan 				 q_num, hinic_txq_stats_strings[i].name);
2320cb7b6606SZiyang Xuan 			count++;
2321cb7b6606SZiyang Xuan 		}
2322cb7b6606SZiyang Xuan 	}
2323cb7b6606SZiyang Xuan 
2324cb7b6606SZiyang Xuan 	/* get vport stats */
2325cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) {
2326cb7b6606SZiyang Xuan 		snprintf(xstats_names[count].name,
2327cb7b6606SZiyang Xuan 			 sizeof(xstats_names[count].name),
2328f372a65fSXiaoyun Wang 			 "%s", hinic_vport_stats_strings[i].name);
2329cb7b6606SZiyang Xuan 		count++;
2330cb7b6606SZiyang Xuan 	}
2331cb7b6606SZiyang Xuan 
23326691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev))
23336691acefSXiaoyun Wang 		return count;
23346691acefSXiaoyun Wang 
2335cb7b6606SZiyang Xuan 	/* get phy port stats */
2336cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) {
2337cb7b6606SZiyang Xuan 		snprintf(xstats_names[count].name,
2338cb7b6606SZiyang Xuan 			 sizeof(xstats_names[count].name),
2339f372a65fSXiaoyun Wang 			 "%s", hinic_phyport_stats_strings[i].name);
2340cb7b6606SZiyang Xuan 		count++;
2341cb7b6606SZiyang Xuan 	}
2342cb7b6606SZiyang Xuan 
2343cb7b6606SZiyang Xuan 	return count;
2344cb7b6606SZiyang Xuan }
2345f372a65fSXiaoyun Wang 
234600499a22SXiaoyun Wang /**
234700499a22SXiaoyun Wang  *  DPDK callback to set mac address
234800499a22SXiaoyun Wang  *
234900499a22SXiaoyun Wang  * @param dev
235000499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
235100499a22SXiaoyun Wang  * @param addr
235200499a22SXiaoyun Wang  *   Pointer to mac address
235300499a22SXiaoyun Wang  * @return
235400499a22SXiaoyun Wang  *   0 on success, negative error value otherwise.
235500499a22SXiaoyun Wang  */
235600499a22SXiaoyun Wang static int hinic_set_mac_addr(struct rte_eth_dev *dev,
235700499a22SXiaoyun Wang 			      struct rte_ether_addr *addr)
235800499a22SXiaoyun Wang {
235900499a22SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
236000499a22SXiaoyun Wang 	u16 func_id;
236100499a22SXiaoyun Wang 	int err;
236200499a22SXiaoyun Wang 
236300499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
236400499a22SXiaoyun Wang 	err = hinic_update_mac(nic_dev->hwdev, nic_dev->default_addr.addr_bytes,
236500499a22SXiaoyun Wang 			       addr->addr_bytes, 0, func_id);
236600499a22SXiaoyun Wang 	if (err)
236700499a22SXiaoyun Wang 		return err;
236800499a22SXiaoyun Wang 
236900499a22SXiaoyun Wang 	rte_ether_addr_copy(addr, &nic_dev->default_addr);
237000499a22SXiaoyun Wang 
23714f1af3cbSXiaoyun Wang 	PMD_DRV_LOG(INFO, "Set new mac address %02x:%02x:%02x:%02x:%02x:%02x",
237200499a22SXiaoyun Wang 		    addr->addr_bytes[0], addr->addr_bytes[1],
237300499a22SXiaoyun Wang 		    addr->addr_bytes[2], addr->addr_bytes[3],
237400499a22SXiaoyun Wang 		    addr->addr_bytes[4], addr->addr_bytes[5]);
237500499a22SXiaoyun Wang 
237600499a22SXiaoyun Wang 	return 0;
237700499a22SXiaoyun Wang }
237800499a22SXiaoyun Wang 
237900499a22SXiaoyun Wang /**
238000499a22SXiaoyun Wang  * DPDK callback to remove a MAC address.
238100499a22SXiaoyun Wang  *
238200499a22SXiaoyun Wang  * @param dev
238300499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
238400499a22SXiaoyun Wang  * @param index
23854f1af3cbSXiaoyun Wang  *   MAC address index, should less than 128.
238600499a22SXiaoyun Wang  */
238700499a22SXiaoyun Wang static void hinic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
238800499a22SXiaoyun Wang {
238900499a22SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
239000499a22SXiaoyun Wang 	u16 func_id;
239100499a22SXiaoyun Wang 	int ret;
239200499a22SXiaoyun Wang 
239300499a22SXiaoyun Wang 	if (index >= HINIC_MAX_UC_MAC_ADDRS) {
239400499a22SXiaoyun Wang 		PMD_DRV_LOG(INFO, "Remove mac index(%u) is out of range",
239500499a22SXiaoyun Wang 			    index);
239600499a22SXiaoyun Wang 		return;
239700499a22SXiaoyun Wang 	}
239800499a22SXiaoyun Wang 
239900499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
240000499a22SXiaoyun Wang 	ret = hinic_del_mac(nic_dev->hwdev,
240100499a22SXiaoyun Wang 			    dev->data->mac_addrs[index].addr_bytes, 0, func_id);
240200499a22SXiaoyun Wang 	if (ret)
240300499a22SXiaoyun Wang 		return;
240400499a22SXiaoyun Wang 
240500499a22SXiaoyun Wang 	memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr));
240600499a22SXiaoyun Wang }
240700499a22SXiaoyun Wang 
240800499a22SXiaoyun Wang /**
240900499a22SXiaoyun Wang  * DPDK callback to add a MAC address.
241000499a22SXiaoyun Wang  *
241100499a22SXiaoyun Wang  * @param dev
241200499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
241300499a22SXiaoyun Wang  * @param mac_addr
24144f1af3cbSXiaoyun Wang  *   Pointer to MAC address
241500499a22SXiaoyun Wang  * @param index
24164f1af3cbSXiaoyun Wang  *   MAC address index, should less than 128.
241700499a22SXiaoyun Wang  * @param vmdq
24184f1af3cbSXiaoyun Wang  *   VMDq pool index(not used).
241900499a22SXiaoyun Wang  *
242000499a22SXiaoyun Wang  * @return
24214f1af3cbSXiaoyun Wang  *   0 on success, negative error value otherwise.
242200499a22SXiaoyun Wang  */
242300499a22SXiaoyun Wang static int hinic_mac_addr_add(struct rte_eth_dev *dev,
242400499a22SXiaoyun Wang 			      struct rte_ether_addr *mac_addr, uint32_t index,
242500499a22SXiaoyun Wang 			      __rte_unused uint32_t vmdq)
242600499a22SXiaoyun Wang {
242700499a22SXiaoyun Wang 	struct hinic_nic_dev  *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
242800499a22SXiaoyun Wang 	unsigned int i;
242900499a22SXiaoyun Wang 	u16 func_id;
243000499a22SXiaoyun Wang 	int ret;
243100499a22SXiaoyun Wang 
243200499a22SXiaoyun Wang 	if (index >= HINIC_MAX_UC_MAC_ADDRS) {
24334f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(INFO, "Add mac index(%u) is out of range", index);
243400499a22SXiaoyun Wang 		return -EINVAL;
243500499a22SXiaoyun Wang 	}
243600499a22SXiaoyun Wang 
243700499a22SXiaoyun Wang 	/* First, make sure this address isn't already configured. */
243800499a22SXiaoyun Wang 	for (i = 0; (i != HINIC_MAX_UC_MAC_ADDRS); ++i) {
243900499a22SXiaoyun Wang 		/* Skip this index, it's going to be reconfigured. */
244000499a22SXiaoyun Wang 		if (i == index)
244100499a22SXiaoyun Wang 			continue;
244200499a22SXiaoyun Wang 
244300499a22SXiaoyun Wang 		if (memcmp(&dev->data->mac_addrs[i],
244400499a22SXiaoyun Wang 			mac_addr, sizeof(*mac_addr)))
244500499a22SXiaoyun Wang 			continue;
244600499a22SXiaoyun Wang 
244700499a22SXiaoyun Wang 		PMD_DRV_LOG(INFO, "MAC address already configured");
244800499a22SXiaoyun Wang 		return -EADDRINUSE;
244900499a22SXiaoyun Wang 	}
245000499a22SXiaoyun Wang 
245100499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
245200499a22SXiaoyun Wang 	ret = hinic_set_mac(nic_dev->hwdev, mac_addr->addr_bytes, 0, func_id);
245300499a22SXiaoyun Wang 	if (ret)
245400499a22SXiaoyun Wang 		return ret;
245500499a22SXiaoyun Wang 
245600499a22SXiaoyun Wang 	dev->data->mac_addrs[index] = *mac_addr;
245700499a22SXiaoyun Wang 	return 0;
245800499a22SXiaoyun Wang }
245900499a22SXiaoyun Wang 
246000499a22SXiaoyun Wang /**
246100499a22SXiaoyun Wang  *  DPDK callback to set multicast mac address
246200499a22SXiaoyun Wang  *
246300499a22SXiaoyun Wang  * @param dev
246400499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
246500499a22SXiaoyun Wang  * @param mc_addr_set
246600499a22SXiaoyun Wang  *   Pointer to multicast mac address
246700499a22SXiaoyun Wang  * @param nb_mc_addr
246800499a22SXiaoyun Wang  *   mc addr count
246900499a22SXiaoyun Wang  * @return
247000499a22SXiaoyun Wang  *   0 on success, negative error value otherwise.
247100499a22SXiaoyun Wang  */
247200499a22SXiaoyun Wang static int hinic_set_mc_addr_list(struct rte_eth_dev *dev,
247300499a22SXiaoyun Wang 				  struct rte_ether_addr *mc_addr_set,
247400499a22SXiaoyun Wang 				  uint32_t nb_mc_addr)
247500499a22SXiaoyun Wang {
247600499a22SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
247700499a22SXiaoyun Wang 	u16 func_id;
247800499a22SXiaoyun Wang 	int ret;
247900499a22SXiaoyun Wang 	u32 i;
248000499a22SXiaoyun Wang 
248100499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
248200499a22SXiaoyun Wang 
248300499a22SXiaoyun Wang 	/* delete old multi_cast addrs firstly */
248400499a22SXiaoyun Wang 	hinic_delete_mc_addr_list(nic_dev);
248500499a22SXiaoyun Wang 
248600499a22SXiaoyun Wang 	if (nb_mc_addr > HINIC_MAX_MC_MAC_ADDRS)
248700499a22SXiaoyun Wang 		goto allmulti;
248800499a22SXiaoyun Wang 
248900499a22SXiaoyun Wang 	for (i = 0; i < nb_mc_addr; i++) {
249000499a22SXiaoyun Wang 		ret = hinic_set_mac(nic_dev->hwdev, mc_addr_set[i].addr_bytes,
249100499a22SXiaoyun Wang 				    0, func_id);
249200499a22SXiaoyun Wang 		/* if add mc addr failed, set all multi_cast */
249300499a22SXiaoyun Wang 		if (ret) {
249400499a22SXiaoyun Wang 			hinic_delete_mc_addr_list(nic_dev);
249500499a22SXiaoyun Wang 			goto allmulti;
249600499a22SXiaoyun Wang 		}
249700499a22SXiaoyun Wang 
249800499a22SXiaoyun Wang 		rte_ether_addr_copy(&mc_addr_set[i], &nic_dev->mc_list[i]);
249900499a22SXiaoyun Wang 	}
250000499a22SXiaoyun Wang 
250100499a22SXiaoyun Wang 	return 0;
250200499a22SXiaoyun Wang 
250300499a22SXiaoyun Wang allmulti:
250400499a22SXiaoyun Wang 	hinic_dev_allmulticast_enable(dev);
250500499a22SXiaoyun Wang 
250600499a22SXiaoyun Wang 	return 0;
250700499a22SXiaoyun Wang }
2508cb7b6606SZiyang Xuan 
250973122b52SXiaoyun Wang /**
2510fb7ad441SThomas Monjalon  * DPDK callback to get flow operations
251173122b52SXiaoyun Wang  *
251273122b52SXiaoyun Wang  * @param dev
251373122b52SXiaoyun Wang  *   Pointer to Ethernet device structure.
2514fb7ad441SThomas Monjalon  * @param ops
251573122b52SXiaoyun Wang  *   Pointer to operation-specific structure.
251673122b52SXiaoyun Wang  *
251773122b52SXiaoyun Wang  * @return
2518f372a65fSXiaoyun Wang  *   0 on success, negative error value otherwise.
251973122b52SXiaoyun Wang  */
2520fb7ad441SThomas Monjalon static int hinic_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
2521fb7ad441SThomas Monjalon 				  const struct rte_flow_ops **ops)
252273122b52SXiaoyun Wang {
2523fb7ad441SThomas Monjalon 	*ops = &hinic_flow_ops;
252473122b52SXiaoyun Wang 	return 0;
252573122b52SXiaoyun Wang }
252673122b52SXiaoyun Wang 
252764727024SZiyang Xuan static int hinic_set_default_pause_feature(struct hinic_nic_dev *nic_dev)
252864727024SZiyang Xuan {
252964727024SZiyang Xuan 	struct nic_pause_config pause_config = {0};
2530ef6f2f5cSXiaoyun Wang 	int err;
253164727024SZiyang Xuan 
253264727024SZiyang Xuan 	pause_config.auto_neg = 0;
253364727024SZiyang Xuan 	pause_config.rx_pause = HINIC_DEFAUT_PAUSE_CONFIG;
253464727024SZiyang Xuan 	pause_config.tx_pause = HINIC_DEFAUT_PAUSE_CONFIG;
253564727024SZiyang Xuan 
2536ef6f2f5cSXiaoyun Wang 	err = hinic_set_pause_config(nic_dev->hwdev, pause_config);
2537ef6f2f5cSXiaoyun Wang 	if (err)
2538ef6f2f5cSXiaoyun Wang 		return err;
2539ef6f2f5cSXiaoyun Wang 
2540ef6f2f5cSXiaoyun Wang 	nic_dev->pause_set = true;
2541ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.auto_neg = pause_config.auto_neg;
2542ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.rx_pause = pause_config.rx_pause;
2543ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.tx_pause = pause_config.tx_pause;
2544ef6f2f5cSXiaoyun Wang 
2545ef6f2f5cSXiaoyun Wang 	return 0;
254664727024SZiyang Xuan }
254764727024SZiyang Xuan 
254864727024SZiyang Xuan static int hinic_set_default_dcb_feature(struct hinic_nic_dev *nic_dev)
254964727024SZiyang Xuan {
255064727024SZiyang Xuan 	u8 up_tc[HINIC_DCB_UP_MAX] = {0};
255164727024SZiyang Xuan 	u8 up_pgid[HINIC_DCB_UP_MAX] = {0};
255264727024SZiyang Xuan 	u8 up_bw[HINIC_DCB_UP_MAX] = {0};
255364727024SZiyang Xuan 	u8 pg_bw[HINIC_DCB_UP_MAX] = {0};
255464727024SZiyang Xuan 	u8 up_strict[HINIC_DCB_UP_MAX] = {0};
255564727024SZiyang Xuan 	int i = 0;
255664727024SZiyang Xuan 
255764727024SZiyang Xuan 	pg_bw[0] = 100;
255864727024SZiyang Xuan 	for (i = 0; i < HINIC_DCB_UP_MAX; i++)
255964727024SZiyang Xuan 		up_bw[i] = 100;
256064727024SZiyang Xuan 
256164727024SZiyang Xuan 	return hinic_dcb_set_ets(nic_dev->hwdev, up_tc, pg_bw,
256264727024SZiyang Xuan 					up_pgid, up_bw, up_strict);
256364727024SZiyang Xuan }
256464727024SZiyang Xuan 
2565d4002360SXiaoyun Wang static int hinic_pf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
2566d4002360SXiaoyun Wang {
2567d4002360SXiaoyun Wang 	u8 default_cos = 0;
2568d4002360SXiaoyun Wang 	u8 valid_cos_bitmap;
2569d4002360SXiaoyun Wang 	u8 i;
2570d4002360SXiaoyun Wang 
2571d4002360SXiaoyun Wang 	valid_cos_bitmap = hwdev->cfg_mgmt->svc_cap.valid_cos_bitmap;
2572d4002360SXiaoyun Wang 	if (!valid_cos_bitmap) {
2573d4002360SXiaoyun Wang 		PMD_DRV_LOG(ERR, "PF has none cos to support\n");
2574d4002360SXiaoyun Wang 		return -EFAULT;
2575d4002360SXiaoyun Wang 	}
2576d4002360SXiaoyun Wang 
2577d4002360SXiaoyun Wang 	for (i = 0; i < NR_MAX_COS; i++) {
2578d4002360SXiaoyun Wang 		if (valid_cos_bitmap & BIT(i))
2579d4002360SXiaoyun Wang 			default_cos = i; /* Find max cos id as default cos */
2580d4002360SXiaoyun Wang 	}
2581d4002360SXiaoyun Wang 
2582d4002360SXiaoyun Wang 	*cos_id = default_cos;
2583d4002360SXiaoyun Wang 
2584d4002360SXiaoyun Wang 	return 0;
2585d4002360SXiaoyun Wang }
2586d4002360SXiaoyun Wang 
25876691acefSXiaoyun Wang static int hinic_init_default_cos(struct hinic_nic_dev *nic_dev)
258864727024SZiyang Xuan {
25896691acefSXiaoyun Wang 	u8 cos_id = 0;
25906691acefSXiaoyun Wang 	int err;
25916691acefSXiaoyun Wang 
25926691acefSXiaoyun Wang 	if (!HINIC_IS_VF(nic_dev->hwdev)) {
2593d4002360SXiaoyun Wang 		err = hinic_pf_get_default_cos(nic_dev->hwdev, &cos_id);
2594d4002360SXiaoyun Wang 		if (err) {
2595d4002360SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Get PF default cos failed, err: %d",
2596d4002360SXiaoyun Wang 				    err);
2597d4002360SXiaoyun Wang 			return HINIC_ERROR;
2598d4002360SXiaoyun Wang 		}
25996691acefSXiaoyun Wang 	} else {
26006691acefSXiaoyun Wang 		err = hinic_vf_get_default_cos(nic_dev->hwdev, &cos_id);
26016691acefSXiaoyun Wang 		if (err) {
26026691acefSXiaoyun Wang 			PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d",
26036691acefSXiaoyun Wang 				    err);
26046691acefSXiaoyun Wang 			return HINIC_ERROR;
26056691acefSXiaoyun Wang 		}
2606d4002360SXiaoyun Wang 	}
26076691acefSXiaoyun Wang 
26086691acefSXiaoyun Wang 	nic_dev->default_cos = cos_id;
2609d4002360SXiaoyun Wang 
2610d4002360SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Default cos %d", nic_dev->default_cos);
26116691acefSXiaoyun Wang 
26126691acefSXiaoyun Wang 	return 0;
261364727024SZiyang Xuan }
261464727024SZiyang Xuan 
261564727024SZiyang Xuan static int hinic_set_default_hw_feature(struct hinic_nic_dev *nic_dev)
261664727024SZiyang Xuan {
261764727024SZiyang Xuan 	int err;
261864727024SZiyang Xuan 
26196691acefSXiaoyun Wang 	err = hinic_init_default_cos(nic_dev);
26206691acefSXiaoyun Wang 	if (err)
26216691acefSXiaoyun Wang 		return err;
26226691acefSXiaoyun Wang 
26236691acefSXiaoyun Wang 	if (hinic_func_type(nic_dev->hwdev) == TYPE_VF)
26246691acefSXiaoyun Wang 		return 0;
262564727024SZiyang Xuan 
262664727024SZiyang Xuan 	/* Restore DCB configure to default status */
262764727024SZiyang Xuan 	err = hinic_set_default_dcb_feature(nic_dev);
262864727024SZiyang Xuan 	if (err)
262964727024SZiyang Xuan 		return err;
263064727024SZiyang Xuan 
263164727024SZiyang Xuan 	/* Set pause enable, and up will disable pfc. */
263264727024SZiyang Xuan 	err = hinic_set_default_pause_feature(nic_dev);
263364727024SZiyang Xuan 	if (err)
263464727024SZiyang Xuan 		return err;
263564727024SZiyang Xuan 
263664727024SZiyang Xuan 	err = hinic_reset_port_link_cfg(nic_dev->hwdev);
263764727024SZiyang Xuan 	if (err)
263864727024SZiyang Xuan 		return err;
263964727024SZiyang Xuan 
264064727024SZiyang Xuan 	err = hinic_set_link_status_follow(nic_dev->hwdev,
264164727024SZiyang Xuan 					   HINIC_LINK_FOLLOW_PORT);
264264727024SZiyang Xuan 	if (err == HINIC_MGMT_CMD_UNSUPPORTED)
264364727024SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Don't support to set link status follow phy port status");
264464727024SZiyang Xuan 	else if (err)
264564727024SZiyang Xuan 		return err;
264664727024SZiyang Xuan 
264764727024SZiyang Xuan 	return hinic_set_anti_attack(nic_dev->hwdev, true);
264864727024SZiyang Xuan }
264964727024SZiyang Xuan 
265064727024SZiyang Xuan static int32_t hinic_card_workmode_check(struct hinic_nic_dev *nic_dev)
265164727024SZiyang Xuan {
265264727024SZiyang Xuan 	struct hinic_board_info info = { 0 };
265364727024SZiyang Xuan 	int rc;
265464727024SZiyang Xuan 
26556691acefSXiaoyun Wang 	if (hinic_func_type(nic_dev->hwdev) == TYPE_VF)
26566691acefSXiaoyun Wang 		return 0;
26576691acefSXiaoyun Wang 
265864727024SZiyang Xuan 	rc = hinic_get_board_info(nic_dev->hwdev, &info);
265964727024SZiyang Xuan 	if (rc)
266064727024SZiyang Xuan 		return rc;
266164727024SZiyang Xuan 
266264727024SZiyang Xuan 	return (info.service_mode == HINIC_SERVICE_MODE_NIC ? HINIC_OK :
266364727024SZiyang Xuan 						HINIC_ERROR);
266464727024SZiyang Xuan }
266564727024SZiyang Xuan 
266664727024SZiyang Xuan static int hinic_copy_mempool_init(struct hinic_nic_dev *nic_dev)
266764727024SZiyang Xuan {
266864727024SZiyang Xuan 	nic_dev->cpy_mpool = rte_mempool_lookup(nic_dev->proc_dev_name);
266964727024SZiyang Xuan 	if (nic_dev->cpy_mpool == NULL) {
267064727024SZiyang Xuan 		nic_dev->cpy_mpool =
267164727024SZiyang Xuan 		rte_pktmbuf_pool_create(nic_dev->proc_dev_name,
267264727024SZiyang Xuan 					HINIC_COPY_MEMPOOL_DEPTH,
26736691acefSXiaoyun Wang 					0, 0,
267464727024SZiyang Xuan 					HINIC_COPY_MBUF_SIZE,
267564727024SZiyang Xuan 					rte_socket_id());
267664727024SZiyang Xuan 		if (!nic_dev->cpy_mpool) {
267764727024SZiyang Xuan 			PMD_DRV_LOG(ERR, "Create copy mempool failed, errno: %d, dev_name: %s",
267864727024SZiyang Xuan 				    rte_errno, nic_dev->proc_dev_name);
267964727024SZiyang Xuan 			return -ENOMEM;
268064727024SZiyang Xuan 		}
268164727024SZiyang Xuan 	}
268264727024SZiyang Xuan 
268364727024SZiyang Xuan 	return 0;
268464727024SZiyang Xuan }
268564727024SZiyang Xuan 
268664727024SZiyang Xuan static void hinic_copy_mempool_uninit(struct hinic_nic_dev *nic_dev)
268764727024SZiyang Xuan {
268864727024SZiyang Xuan 	if (nic_dev->cpy_mpool != NULL)
268964727024SZiyang Xuan 		rte_mempool_free(nic_dev->cpy_mpool);
269064727024SZiyang Xuan }
269164727024SZiyang Xuan 
269264727024SZiyang Xuan static int hinic_init_sw_rxtxqs(struct hinic_nic_dev *nic_dev)
269364727024SZiyang Xuan {
269464727024SZiyang Xuan 	u32 txq_size;
269564727024SZiyang Xuan 	u32 rxq_size;
269664727024SZiyang Xuan 
269764727024SZiyang Xuan 	/* allocate software txq array */
269864727024SZiyang Xuan 	txq_size = nic_dev->nic_cap.max_sqs * sizeof(*nic_dev->txqs);
269964727024SZiyang Xuan 	nic_dev->txqs = kzalloc_aligned(txq_size, GFP_KERNEL);
270064727024SZiyang Xuan 	if (!nic_dev->txqs) {
270164727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate txqs failed");
270264727024SZiyang Xuan 		return -ENOMEM;
270364727024SZiyang Xuan 	}
270464727024SZiyang Xuan 
270564727024SZiyang Xuan 	/* allocate software rxq array */
270664727024SZiyang Xuan 	rxq_size = nic_dev->nic_cap.max_rqs * sizeof(*nic_dev->rxqs);
270764727024SZiyang Xuan 	nic_dev->rxqs = kzalloc_aligned(rxq_size, GFP_KERNEL);
270864727024SZiyang Xuan 	if (!nic_dev->rxqs) {
270964727024SZiyang Xuan 		/* free txqs */
271064727024SZiyang Xuan 		kfree(nic_dev->txqs);
271164727024SZiyang Xuan 		nic_dev->txqs = NULL;
271264727024SZiyang Xuan 
271364727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate rxqs failed");
271464727024SZiyang Xuan 		return -ENOMEM;
271564727024SZiyang Xuan 	}
271664727024SZiyang Xuan 
271764727024SZiyang Xuan 	return HINIC_OK;
271864727024SZiyang Xuan }
271964727024SZiyang Xuan 
272064727024SZiyang Xuan static void hinic_deinit_sw_rxtxqs(struct hinic_nic_dev *nic_dev)
272164727024SZiyang Xuan {
272264727024SZiyang Xuan 	kfree(nic_dev->txqs);
272364727024SZiyang Xuan 	nic_dev->txqs = NULL;
272464727024SZiyang Xuan 
272564727024SZiyang Xuan 	kfree(nic_dev->rxqs);
272664727024SZiyang Xuan 	nic_dev->rxqs = NULL;
272764727024SZiyang Xuan }
272864727024SZiyang Xuan 
272964727024SZiyang Xuan static int hinic_nic_dev_create(struct rte_eth_dev *eth_dev)
273064727024SZiyang Xuan {
273164727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
273264727024SZiyang Xuan 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
273364727024SZiyang Xuan 	int rc;
273464727024SZiyang Xuan 
273564727024SZiyang Xuan 	nic_dev->hwdev = rte_zmalloc("hinic_hwdev", sizeof(*nic_dev->hwdev),
273664727024SZiyang Xuan 				     RTE_CACHE_LINE_SIZE);
273764727024SZiyang Xuan 	if (!nic_dev->hwdev) {
273864727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate hinic hwdev memory failed, dev_name: %s",
273964727024SZiyang Xuan 			    eth_dev->data->name);
274064727024SZiyang Xuan 		return -ENOMEM;
274164727024SZiyang Xuan 	}
274264727024SZiyang Xuan 	nic_dev->hwdev->pcidev_hdl = RTE_ETH_DEV_TO_PCI(eth_dev);
274364727024SZiyang Xuan 
274464727024SZiyang Xuan 	/* init osdep*/
274564727024SZiyang Xuan 	rc = hinic_osdep_init(nic_dev->hwdev);
274664727024SZiyang Xuan 	if (rc) {
274764727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize os_dep failed, dev_name: %s",
274864727024SZiyang Xuan 			    eth_dev->data->name);
274964727024SZiyang Xuan 		goto init_osdep_fail;
275064727024SZiyang Xuan 	}
275164727024SZiyang Xuan 
275264727024SZiyang Xuan 	/* init_hwif */
275364727024SZiyang Xuan 	rc = hinic_hwif_res_init(nic_dev->hwdev);
275464727024SZiyang Xuan 	if (rc) {
275564727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize hwif failed, dev_name: %s",
275664727024SZiyang Xuan 			    eth_dev->data->name);
275764727024SZiyang Xuan 		goto init_hwif_fail;
275864727024SZiyang Xuan 	}
275964727024SZiyang Xuan 
276064727024SZiyang Xuan 	/* init_cfg_mgmt */
276164727024SZiyang Xuan 	rc = init_cfg_mgmt(nic_dev->hwdev);
276264727024SZiyang Xuan 	if (rc) {
276364727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize cfg_mgmt failed, dev_name: %s",
276464727024SZiyang Xuan 			    eth_dev->data->name);
276564727024SZiyang Xuan 		goto init_cfgmgnt_fail;
276664727024SZiyang Xuan 	}
276764727024SZiyang Xuan 
276864727024SZiyang Xuan 	/* init_aeqs */
276964727024SZiyang Xuan 	rc = hinic_comm_aeqs_init(nic_dev->hwdev);
277064727024SZiyang Xuan 	if (rc) {
277164727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize aeqs failed, dev_name: %s",
277264727024SZiyang Xuan 			    eth_dev->data->name);
277364727024SZiyang Xuan 		goto init_aeqs_fail;
277464727024SZiyang Xuan 	}
277564727024SZiyang Xuan 
277664727024SZiyang Xuan 	/* init_pf_to_mgnt */
277764727024SZiyang Xuan 	rc = hinic_comm_pf_to_mgmt_init(nic_dev->hwdev);
277864727024SZiyang Xuan 	if (rc) {
277964727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize pf_to_mgmt failed, dev_name: %s",
278064727024SZiyang Xuan 			    eth_dev->data->name);
278164727024SZiyang Xuan 		goto init_pf_to_mgmt_fail;
278264727024SZiyang Xuan 	}
278364727024SZiyang Xuan 
27846691acefSXiaoyun Wang 	/* init mailbox */
27856691acefSXiaoyun Wang 	rc = hinic_comm_func_to_func_init(nic_dev->hwdev);
27866691acefSXiaoyun Wang 	if (rc) {
27876691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Initialize func_to_func failed, dev_name: %s",
27886691acefSXiaoyun Wang 			    eth_dev->data->name);
27896691acefSXiaoyun Wang 		goto init_func_to_func_fail;
27906691acefSXiaoyun Wang 	}
27916691acefSXiaoyun Wang 
279264727024SZiyang Xuan 	rc = hinic_card_workmode_check(nic_dev);
279364727024SZiyang Xuan 	if (rc) {
279464727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Check card workmode failed, dev_name: %s",
279564727024SZiyang Xuan 			    eth_dev->data->name);
279664727024SZiyang Xuan 		goto workmode_check_fail;
279764727024SZiyang Xuan 	}
279864727024SZiyang Xuan 
279964727024SZiyang Xuan 	/* do l2nic reset to make chip clear */
280064727024SZiyang Xuan 	rc = hinic_l2nic_reset(nic_dev->hwdev);
280164727024SZiyang Xuan 	if (rc) {
280264727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Do l2nic reset failed, dev_name: %s",
280364727024SZiyang Xuan 			    eth_dev->data->name);
280464727024SZiyang Xuan 		goto l2nic_reset_fail;
280564727024SZiyang Xuan 	}
280664727024SZiyang Xuan 
280764727024SZiyang Xuan 	/* init dma and aeq msix attribute table */
280864727024SZiyang Xuan 	(void)hinic_init_attr_table(nic_dev->hwdev);
280964727024SZiyang Xuan 
281064727024SZiyang Xuan 	/* init_cmdqs */
281164727024SZiyang Xuan 	rc = hinic_comm_cmdqs_init(nic_dev->hwdev);
281264727024SZiyang Xuan 	if (rc) {
281364727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize cmdq failed, dev_name: %s",
281464727024SZiyang Xuan 			    eth_dev->data->name);
281564727024SZiyang Xuan 		goto init_cmdq_fail;
281664727024SZiyang Xuan 	}
281764727024SZiyang Xuan 
281864727024SZiyang Xuan 	/* set hardware state active */
281964727024SZiyang Xuan 	rc = hinic_activate_hwdev_state(nic_dev->hwdev);
282064727024SZiyang Xuan 	if (rc) {
282164727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize resources state failed, dev_name: %s",
282264727024SZiyang Xuan 			    eth_dev->data->name);
282364727024SZiyang Xuan 		goto init_resources_state_fail;
282464727024SZiyang Xuan 	}
282564727024SZiyang Xuan 
282664727024SZiyang Xuan 	/* init_capability */
282764727024SZiyang Xuan 	rc = hinic_init_capability(nic_dev->hwdev);
282864727024SZiyang Xuan 	if (rc) {
282964727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize capability failed, dev_name: %s",
283064727024SZiyang Xuan 			    eth_dev->data->name);
283164727024SZiyang Xuan 		goto init_cap_fail;
283264727024SZiyang Xuan 	}
283364727024SZiyang Xuan 
283464727024SZiyang Xuan 	/* get nic capability */
283513850e88SXiaoyun Wang 	if (!hinic_support_nic(nic_dev->hwdev, &nic_dev->nic_cap)) {
283613850e88SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hw doesn't support nic, dev_name: %s",
283713850e88SXiaoyun Wang 			    eth_dev->data->name);
283813850e88SXiaoyun Wang 		rc = -EINVAL;
283964727024SZiyang Xuan 		goto nic_check_fail;
284013850e88SXiaoyun Wang 	}
284164727024SZiyang Xuan 
284264727024SZiyang Xuan 	/* init root cla and function table */
284364727024SZiyang Xuan 	rc = hinic_init_nicio(nic_dev->hwdev);
284464727024SZiyang Xuan 	if (rc) {
284564727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize nic_io failed, dev_name: %s",
284664727024SZiyang Xuan 			    eth_dev->data->name);
284764727024SZiyang Xuan 		goto init_nicio_fail;
284864727024SZiyang Xuan 	}
284964727024SZiyang Xuan 
285064727024SZiyang Xuan 	/* init_software_txrxq */
285164727024SZiyang Xuan 	rc = hinic_init_sw_rxtxqs(nic_dev);
285264727024SZiyang Xuan 	if (rc) {
285364727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize sw_rxtxqs failed, dev_name: %s",
285464727024SZiyang Xuan 			    eth_dev->data->name);
285564727024SZiyang Xuan 		goto init_sw_rxtxqs_fail;
285664727024SZiyang Xuan 	}
285764727024SZiyang Xuan 
285864727024SZiyang Xuan 	rc = hinic_copy_mempool_init(nic_dev);
285964727024SZiyang Xuan 	if (rc) {
286064727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Create copy mempool failed, dev_name: %s",
286164727024SZiyang Xuan 			 eth_dev->data->name);
286264727024SZiyang Xuan 		goto init_mpool_fail;
286364727024SZiyang Xuan 	}
286464727024SZiyang Xuan 
286564727024SZiyang Xuan 	/* set hardware feature to default status */
286664727024SZiyang Xuan 	rc = hinic_set_default_hw_feature(nic_dev);
286764727024SZiyang Xuan 	if (rc) {
286864727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize hardware default features failed, dev_name: %s",
286964727024SZiyang Xuan 			    eth_dev->data->name);
287064727024SZiyang Xuan 		goto set_default_hw_feature_fail;
287164727024SZiyang Xuan 	}
287264727024SZiyang Xuan 
287364727024SZiyang Xuan 	return 0;
287464727024SZiyang Xuan 
287564727024SZiyang Xuan set_default_hw_feature_fail:
287664727024SZiyang Xuan 	hinic_copy_mempool_uninit(nic_dev);
287764727024SZiyang Xuan 
287864727024SZiyang Xuan init_mpool_fail:
287964727024SZiyang Xuan 	hinic_deinit_sw_rxtxqs(nic_dev);
288064727024SZiyang Xuan 
288164727024SZiyang Xuan init_sw_rxtxqs_fail:
288264727024SZiyang Xuan 	hinic_deinit_nicio(nic_dev->hwdev);
288364727024SZiyang Xuan 
288464727024SZiyang Xuan nic_check_fail:
288564727024SZiyang Xuan init_nicio_fail:
288664727024SZiyang Xuan init_cap_fail:
288764727024SZiyang Xuan 	hinic_deactivate_hwdev_state(nic_dev->hwdev);
288864727024SZiyang Xuan 
288964727024SZiyang Xuan init_resources_state_fail:
289064727024SZiyang Xuan 	hinic_comm_cmdqs_free(nic_dev->hwdev);
289164727024SZiyang Xuan 
289264727024SZiyang Xuan init_cmdq_fail:
289364727024SZiyang Xuan l2nic_reset_fail:
289464727024SZiyang Xuan workmode_check_fail:
28956691acefSXiaoyun Wang 	hinic_comm_func_to_func_free(nic_dev->hwdev);
28966691acefSXiaoyun Wang 
28976691acefSXiaoyun Wang init_func_to_func_fail:
289864727024SZiyang Xuan 	hinic_comm_pf_to_mgmt_free(nic_dev->hwdev);
289964727024SZiyang Xuan 
290064727024SZiyang Xuan init_pf_to_mgmt_fail:
290164727024SZiyang Xuan 	hinic_comm_aeqs_free(nic_dev->hwdev);
290264727024SZiyang Xuan 
290364727024SZiyang Xuan init_aeqs_fail:
290464727024SZiyang Xuan 	free_cfg_mgmt(nic_dev->hwdev);
290564727024SZiyang Xuan 
290664727024SZiyang Xuan init_cfgmgnt_fail:
290764727024SZiyang Xuan 	hinic_hwif_res_free(nic_dev->hwdev);
290864727024SZiyang Xuan 
290964727024SZiyang Xuan init_hwif_fail:
291064727024SZiyang Xuan 	hinic_osdep_deinit(nic_dev->hwdev);
291164727024SZiyang Xuan 
291264727024SZiyang Xuan init_osdep_fail:
291364727024SZiyang Xuan 	rte_free(nic_dev->hwdev);
291464727024SZiyang Xuan 	nic_dev->hwdev = NULL;
291564727024SZiyang Xuan 
291664727024SZiyang Xuan 	return rc;
291764727024SZiyang Xuan }
291864727024SZiyang Xuan 
291964727024SZiyang Xuan static void hinic_nic_dev_destroy(struct rte_eth_dev *eth_dev)
292064727024SZiyang Xuan {
292164727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
292264727024SZiyang Xuan 			HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
292364727024SZiyang Xuan 
292464727024SZiyang Xuan 	(void)hinic_set_link_status_follow(nic_dev->hwdev,
292564727024SZiyang Xuan 					   HINIC_LINK_FOLLOW_DEFAULT);
292664727024SZiyang Xuan 	hinic_copy_mempool_uninit(nic_dev);
292764727024SZiyang Xuan 	hinic_deinit_sw_rxtxqs(nic_dev);
292864727024SZiyang Xuan 	hinic_deinit_nicio(nic_dev->hwdev);
292964727024SZiyang Xuan 	hinic_deactivate_hwdev_state(nic_dev->hwdev);
293064727024SZiyang Xuan 	hinic_comm_cmdqs_free(nic_dev->hwdev);
29316691acefSXiaoyun Wang 	hinic_comm_func_to_func_free(nic_dev->hwdev);
293264727024SZiyang Xuan 	hinic_comm_pf_to_mgmt_free(nic_dev->hwdev);
293364727024SZiyang Xuan 	hinic_comm_aeqs_free(nic_dev->hwdev);
293464727024SZiyang Xuan 	free_cfg_mgmt(nic_dev->hwdev);
293564727024SZiyang Xuan 	hinic_hwif_res_free(nic_dev->hwdev);
293664727024SZiyang Xuan 	hinic_osdep_deinit(nic_dev->hwdev);
293764727024SZiyang Xuan 	rte_free(nic_dev->hwdev);
293864727024SZiyang Xuan 	nic_dev->hwdev = NULL;
293964727024SZiyang Xuan }
294064727024SZiyang Xuan 
294164727024SZiyang Xuan /**
29421d09792aSZiyang Xuan  * DPDK callback to close the device.
29431d09792aSZiyang Xuan  *
29441d09792aSZiyang Xuan  * @param dev
29451d09792aSZiyang Xuan  *   Pointer to Ethernet device structure.
29461d09792aSZiyang Xuan  */
2947b142387bSThomas Monjalon static int hinic_dev_close(struct rte_eth_dev *dev)
29481d09792aSZiyang Xuan {
294964727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
295062024eb8SIvan Ilchenko 	int ret;
295164727024SZiyang Xuan 
295230410493SThomas Monjalon 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
295330410493SThomas Monjalon 		return 0;
295430410493SThomas Monjalon 
29550371535dSJoyce Kong 	if (rte_bit_relaxed_test_and_set32(HINIC_DEV_CLOSE,
29560371535dSJoyce Kong 					   &nic_dev->dev_status)) {
295764727024SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Device %s already closed",
295864727024SZiyang Xuan 			    dev->data->name);
2959b142387bSThomas Monjalon 		return 0;
296064727024SZiyang Xuan 	}
296164727024SZiyang Xuan 
29622c473729SZiyang Xuan 	/* stop device first */
296362024eb8SIvan Ilchenko 	ret = hinic_dev_stop(dev);
29642c473729SZiyang Xuan 
296564727024SZiyang Xuan 	/* rx_cqe, rx_info */
296664727024SZiyang Xuan 	hinic_free_all_rx_resources(dev);
296764727024SZiyang Xuan 
296864727024SZiyang Xuan 	/* tx_info */
296964727024SZiyang Xuan 	hinic_free_all_tx_resources(dev);
297064727024SZiyang Xuan 
297164727024SZiyang Xuan 	/* free wq, pi_dma_addr */
297264727024SZiyang Xuan 	hinic_free_all_rq(nic_dev);
297364727024SZiyang Xuan 
297464727024SZiyang Xuan 	/* free wq, db_addr */
297564727024SZiyang Xuan 	hinic_free_all_sq(nic_dev);
297664727024SZiyang Xuan 
297764727024SZiyang Xuan 	/* deinit mac vlan tbl */
297864727024SZiyang Xuan 	hinic_deinit_mac_addr(dev);
2979fdba3bf1SXiaoyun Wang 	hinic_remove_all_vlanid(dev);
298064727024SZiyang Xuan 
298164727024SZiyang Xuan 	/* disable hardware and uio interrupt */
298264727024SZiyang Xuan 	hinic_disable_interrupt(dev);
298364727024SZiyang Xuan 
2984511b7371SGuoyang Zhou 	/* destroy rx mode mutex */
2985511b7371SGuoyang Zhou 	hinic_mutex_destroy(&nic_dev->rx_mode_mutex);
2986511b7371SGuoyang Zhou 
298764727024SZiyang Xuan 	/* deinit nic hardware device */
298864727024SZiyang Xuan 	hinic_nic_dev_destroy(dev);
2989b142387bSThomas Monjalon 
299062024eb8SIvan Ilchenko 	return ret;
29911d09792aSZiyang Xuan }
29921d09792aSZiyang Xuan 
29931d09792aSZiyang Xuan static const struct eth_dev_ops hinic_pmd_ops = {
299464727024SZiyang Xuan 	.dev_configure                 = hinic_dev_configure,
29951d09792aSZiyang Xuan 	.dev_infos_get                 = hinic_dev_infos_get,
2996dbf524abSXiaoyun Wang 	.fw_version_get                = hinic_fw_version_get,
29972c473729SZiyang Xuan 	.rx_queue_setup                = hinic_rx_queue_setup,
29982c473729SZiyang Xuan 	.tx_queue_setup                = hinic_tx_queue_setup,
29992c473729SZiyang Xuan 	.dev_start                     = hinic_dev_start,
300054ac3386SXiaoyun Wang 	.dev_set_link_up               = hinic_dev_set_link_up,
300154ac3386SXiaoyun Wang 	.dev_set_link_down             = hinic_dev_set_link_down,
30022c473729SZiyang Xuan 	.link_update                   = hinic_link_update,
30032c473729SZiyang Xuan 	.rx_queue_release              = hinic_rx_queue_release,
30042c473729SZiyang Xuan 	.tx_queue_release              = hinic_tx_queue_release,
30052c473729SZiyang Xuan 	.dev_stop                      = hinic_dev_stop,
300664727024SZiyang Xuan 	.dev_close                     = hinic_dev_close,
30078260eba6SXiaoyun Wang 	.mtu_set                       = hinic_dev_set_mtu,
3008fdba3bf1SXiaoyun Wang 	.vlan_filter_set               = hinic_vlan_filter_set,
3009fdba3bf1SXiaoyun Wang 	.vlan_offload_set              = hinic_vlan_offload_set,
30108260eba6SXiaoyun Wang 	.allmulticast_enable           = hinic_dev_allmulticast_enable,
30118260eba6SXiaoyun Wang 	.allmulticast_disable          = hinic_dev_allmulticast_disable,
3012cb7b6606SZiyang Xuan 	.promiscuous_enable            = hinic_dev_promiscuous_enable,
3013cb7b6606SZiyang Xuan 	.promiscuous_disable           = hinic_dev_promiscuous_disable,
3014ef6f2f5cSXiaoyun Wang 	.flow_ctrl_get                 = hinic_flow_ctrl_get,
3015ef6f2f5cSXiaoyun Wang 	.flow_ctrl_set                 = hinic_flow_ctrl_set,
3016cb7b6606SZiyang Xuan 	.rss_hash_update               = hinic_rss_hash_update,
3017cb7b6606SZiyang Xuan 	.rss_hash_conf_get             = hinic_rss_conf_get,
3018cb7b6606SZiyang Xuan 	.reta_update                   = hinic_rss_indirtbl_update,
3019cb7b6606SZiyang Xuan 	.reta_query                    = hinic_rss_indirtbl_query,
3020cb7b6606SZiyang Xuan 	.stats_get                     = hinic_dev_stats_get,
3021cb7b6606SZiyang Xuan 	.stats_reset                   = hinic_dev_stats_reset,
3022cb7b6606SZiyang Xuan 	.xstats_get                    = hinic_dev_xstats_get,
3023cb7b6606SZiyang Xuan 	.xstats_reset                  = hinic_dev_xstats_reset,
3024cb7b6606SZiyang Xuan 	.xstats_get_names              = hinic_dev_xstats_get_names,
3025483b4817SXiaoyun Wang 	.rxq_info_get                  = hinic_rxq_info_get,
3026483b4817SXiaoyun Wang 	.txq_info_get                  = hinic_txq_info_get,
302700499a22SXiaoyun Wang 	.mac_addr_set                  = hinic_set_mac_addr,
302800499a22SXiaoyun Wang 	.mac_addr_remove               = hinic_mac_addr_remove,
302900499a22SXiaoyun Wang 	.mac_addr_add                  = hinic_mac_addr_add,
303000499a22SXiaoyun Wang 	.set_mc_addr_list              = hinic_set_mc_addr_list,
3031fb7ad441SThomas Monjalon 	.flow_ops_get                  = hinic_dev_flow_ops_get,
30321d09792aSZiyang Xuan };
30331d09792aSZiyang Xuan 
30346691acefSXiaoyun Wang static const struct eth_dev_ops hinic_pmd_vf_ops = {
30356691acefSXiaoyun Wang 	.dev_configure                 = hinic_dev_configure,
30366691acefSXiaoyun Wang 	.dev_infos_get                 = hinic_dev_infos_get,
3037dbf524abSXiaoyun Wang 	.fw_version_get                = hinic_fw_version_get,
30386691acefSXiaoyun Wang 	.rx_queue_setup                = hinic_rx_queue_setup,
30396691acefSXiaoyun Wang 	.tx_queue_setup                = hinic_tx_queue_setup,
30406691acefSXiaoyun Wang 	.dev_start                     = hinic_dev_start,
30416691acefSXiaoyun Wang 	.link_update                   = hinic_link_update,
30426691acefSXiaoyun Wang 	.rx_queue_release              = hinic_rx_queue_release,
30436691acefSXiaoyun Wang 	.tx_queue_release              = hinic_tx_queue_release,
30446691acefSXiaoyun Wang 	.dev_stop                      = hinic_dev_stop,
30456691acefSXiaoyun Wang 	.dev_close                     = hinic_dev_close,
30468260eba6SXiaoyun Wang 	.mtu_set                       = hinic_dev_set_mtu,
3047fdba3bf1SXiaoyun Wang 	.vlan_filter_set               = hinic_vlan_filter_set,
3048fdba3bf1SXiaoyun Wang 	.vlan_offload_set              = hinic_vlan_offload_set,
30498260eba6SXiaoyun Wang 	.allmulticast_enable           = hinic_dev_allmulticast_enable,
30508260eba6SXiaoyun Wang 	.allmulticast_disable          = hinic_dev_allmulticast_disable,
30516691acefSXiaoyun Wang 	.rss_hash_update               = hinic_rss_hash_update,
30526691acefSXiaoyun Wang 	.rss_hash_conf_get             = hinic_rss_conf_get,
30536691acefSXiaoyun Wang 	.reta_update                   = hinic_rss_indirtbl_update,
30546691acefSXiaoyun Wang 	.reta_query                    = hinic_rss_indirtbl_query,
30556691acefSXiaoyun Wang 	.stats_get                     = hinic_dev_stats_get,
30566691acefSXiaoyun Wang 	.stats_reset                   = hinic_dev_stats_reset,
30576691acefSXiaoyun Wang 	.xstats_get                    = hinic_dev_xstats_get,
30586691acefSXiaoyun Wang 	.xstats_reset                  = hinic_dev_xstats_reset,
30596691acefSXiaoyun Wang 	.xstats_get_names              = hinic_dev_xstats_get_names,
3060483b4817SXiaoyun Wang 	.rxq_info_get                  = hinic_rxq_info_get,
3061483b4817SXiaoyun Wang 	.txq_info_get                  = hinic_txq_info_get,
306200499a22SXiaoyun Wang 	.mac_addr_set                  = hinic_set_mac_addr,
306300499a22SXiaoyun Wang 	.mac_addr_remove               = hinic_mac_addr_remove,
306400499a22SXiaoyun Wang 	.mac_addr_add                  = hinic_mac_addr_add,
306500499a22SXiaoyun Wang 	.set_mc_addr_list              = hinic_set_mc_addr_list,
3066fb7ad441SThomas Monjalon 	.flow_ops_get                  = hinic_dev_flow_ops_get,
30676691acefSXiaoyun Wang };
30686691acefSXiaoyun Wang 
30694c670dfaSGuoyang Zhou static const struct eth_dev_ops hinic_dev_sec_ops = {
30704c670dfaSGuoyang Zhou 	.dev_infos_get                 = hinic_dev_infos_get,
30714c670dfaSGuoyang Zhou };
30724c670dfaSGuoyang Zhou 
30736691acefSXiaoyun Wang static int hinic_func_init(struct rte_eth_dev *eth_dev)
30746691acefSXiaoyun Wang {
30756691acefSXiaoyun Wang 	struct rte_pci_device *pci_dev;
30766691acefSXiaoyun Wang 	struct rte_ether_addr *eth_addr;
30776691acefSXiaoyun Wang 	struct hinic_nic_dev *nic_dev;
30781742421bSXiaoyun Wang 	struct hinic_filter_info *filter_info;
30791fe89aa3SXiaoyun Wang 	struct hinic_tcam_info *tcam_info;
308000499a22SXiaoyun Wang 	u32 mac_size;
30816691acefSXiaoyun Wang 	int rc;
30826691acefSXiaoyun Wang 
30836691acefSXiaoyun Wang 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
30846691acefSXiaoyun Wang 
30856691acefSXiaoyun Wang 	/* EAL is SECONDARY and eth_dev is already created */
30866691acefSXiaoyun Wang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
30874c670dfaSGuoyang Zhou 		eth_dev->dev_ops = &hinic_dev_sec_ops;
308866f64dd6SXiaoyun Wang 		PMD_DRV_LOG(INFO, "Initialize %s in secondary process",
30896691acefSXiaoyun Wang 			    eth_dev->data->name);
30906691acefSXiaoyun Wang 
309166f64dd6SXiaoyun Wang 		return 0;
30926691acefSXiaoyun Wang 	}
30936691acefSXiaoyun Wang 
3094f30e69b4SFerruh Yigit 	eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
3095f30e69b4SFerruh Yigit 
30966691acefSXiaoyun Wang 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
30976691acefSXiaoyun Wang 	memset(nic_dev, 0, sizeof(*nic_dev));
30986691acefSXiaoyun Wang 
30996691acefSXiaoyun Wang 	snprintf(nic_dev->proc_dev_name,
31006691acefSXiaoyun Wang 		 sizeof(nic_dev->proc_dev_name),
31016691acefSXiaoyun Wang 		 "hinic-%.4x:%.2x:%.2x.%x",
31026691acefSXiaoyun Wang 		 pci_dev->addr.domain, pci_dev->addr.bus,
31036691acefSXiaoyun Wang 		 pci_dev->addr.devid, pci_dev->addr.function);
31046691acefSXiaoyun Wang 
31056691acefSXiaoyun Wang 	/* alloc mac_addrs */
310600499a22SXiaoyun Wang 	mac_size = HINIC_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr);
310700499a22SXiaoyun Wang 	eth_addr = rte_zmalloc("hinic_mac", mac_size, 0);
31086691acefSXiaoyun Wang 	if (!eth_addr) {
31096691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Allocate ethernet addresses' memory failed, dev_name: %s",
31106691acefSXiaoyun Wang 			    eth_dev->data->name);
31116691acefSXiaoyun Wang 		rc = -ENOMEM;
31126691acefSXiaoyun Wang 		goto eth_addr_fail;
31136691acefSXiaoyun Wang 	}
31146691acefSXiaoyun Wang 	eth_dev->data->mac_addrs = eth_addr;
31156691acefSXiaoyun Wang 
311600499a22SXiaoyun Wang 	mac_size = HINIC_MAX_MC_MAC_ADDRS * sizeof(struct rte_ether_addr);
311700499a22SXiaoyun Wang 	nic_dev->mc_list = rte_zmalloc("hinic_mc", mac_size, 0);
311800499a22SXiaoyun Wang 	if (!nic_dev->mc_list) {
311900499a22SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Allocate mcast address' memory failed, dev_name: %s",
312000499a22SXiaoyun Wang 			    eth_dev->data->name);
312100499a22SXiaoyun Wang 		rc = -ENOMEM;
312200499a22SXiaoyun Wang 		goto mc_addr_fail;
312300499a22SXiaoyun Wang 	}
312400499a22SXiaoyun Wang 
31256691acefSXiaoyun Wang 	/* create hardware nic_device */
31266691acefSXiaoyun Wang 	rc = hinic_nic_dev_create(eth_dev);
31276691acefSXiaoyun Wang 	if (rc) {
31286691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Create nic device failed, dev_name: %s",
31296691acefSXiaoyun Wang 			    eth_dev->data->name);
31306691acefSXiaoyun Wang 		goto create_nic_dev_fail;
31316691acefSXiaoyun Wang 	}
31326691acefSXiaoyun Wang 
31336691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev))
31346691acefSXiaoyun Wang 		eth_dev->dev_ops = &hinic_pmd_vf_ops;
31356691acefSXiaoyun Wang 	else
31366691acefSXiaoyun Wang 		eth_dev->dev_ops = &hinic_pmd_ops;
31376691acefSXiaoyun Wang 
31386691acefSXiaoyun Wang 	rc = hinic_init_mac_addr(eth_dev);
31396691acefSXiaoyun Wang 	if (rc) {
31406691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Initialize mac table failed, dev_name: %s",
31416691acefSXiaoyun Wang 			    eth_dev->data->name);
31426691acefSXiaoyun Wang 		goto init_mac_fail;
31436691acefSXiaoyun Wang 	}
31446691acefSXiaoyun Wang 
31456691acefSXiaoyun Wang 	/* register callback func to eal lib */
31466691acefSXiaoyun Wang 	rc = rte_intr_callback_register(&pci_dev->intr_handle,
31476691acefSXiaoyun Wang 					hinic_dev_interrupt_handler,
31486691acefSXiaoyun Wang 					(void *)eth_dev);
31496691acefSXiaoyun Wang 	if (rc) {
31506691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Register rte interrupt callback failed, dev_name: %s",
31516691acefSXiaoyun Wang 			    eth_dev->data->name);
31526691acefSXiaoyun Wang 		goto reg_intr_cb_fail;
31536691acefSXiaoyun Wang 	}
31546691acefSXiaoyun Wang 
31556691acefSXiaoyun Wang 	/* enable uio/vfio intr/eventfd mapping */
31566691acefSXiaoyun Wang 	rc = rte_intr_enable(&pci_dev->intr_handle);
31576691acefSXiaoyun Wang 	if (rc) {
31586691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Enable rte interrupt failed, dev_name: %s",
31596691acefSXiaoyun Wang 			    eth_dev->data->name);
31606691acefSXiaoyun Wang 		goto enable_intr_fail;
31616691acefSXiaoyun Wang 	}
31620371535dSJoyce Kong 	rte_bit_relaxed_set32(HINIC_DEV_INTR_EN, &nic_dev->dev_status);
31636691acefSXiaoyun Wang 
3164224cff4bSXiaoyun Wang 	hinic_mutex_init(&nic_dev->rx_mode_mutex, NULL);
3165224cff4bSXiaoyun Wang 
31661742421bSXiaoyun Wang 	/* initialize filter info */
31671742421bSXiaoyun Wang 	filter_info = &nic_dev->filter;
31681fe89aa3SXiaoyun Wang 	tcam_info = &nic_dev->tcam;
31691742421bSXiaoyun Wang 	memset(filter_info, 0, sizeof(struct hinic_filter_info));
31701fe89aa3SXiaoyun Wang 	memset(tcam_info, 0, sizeof(struct hinic_tcam_info));
31711742421bSXiaoyun Wang 	/* initialize 5tuple filter list */
31721742421bSXiaoyun Wang 	TAILQ_INIT(&filter_info->fivetuple_list);
31731fe89aa3SXiaoyun Wang 	TAILQ_INIT(&tcam_info->tcam_list);
31741742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->filter_ntuple_list);
31751742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->filter_ethertype_list);
31761742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->filter_fdir_rule_list);
31771742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->hinic_flow_list);
31781742421bSXiaoyun Wang 
31790371535dSJoyce Kong 	rte_bit_relaxed_set32(HINIC_DEV_INIT, &nic_dev->dev_status);
31806691acefSXiaoyun Wang 	PMD_DRV_LOG(INFO, "Initialize %s in primary successfully",
31816691acefSXiaoyun Wang 		    eth_dev->data->name);
31826691acefSXiaoyun Wang 
31836691acefSXiaoyun Wang 	return 0;
31846691acefSXiaoyun Wang 
31856691acefSXiaoyun Wang enable_intr_fail:
31866691acefSXiaoyun Wang 	(void)rte_intr_callback_unregister(&pci_dev->intr_handle,
31876691acefSXiaoyun Wang 					   hinic_dev_interrupt_handler,
31886691acefSXiaoyun Wang 					   (void *)eth_dev);
31896691acefSXiaoyun Wang 
31906691acefSXiaoyun Wang reg_intr_cb_fail:
31916691acefSXiaoyun Wang 	hinic_deinit_mac_addr(eth_dev);
31926691acefSXiaoyun Wang 
31936691acefSXiaoyun Wang init_mac_fail:
31946691acefSXiaoyun Wang 	eth_dev->dev_ops = NULL;
31956691acefSXiaoyun Wang 	hinic_nic_dev_destroy(eth_dev);
31966691acefSXiaoyun Wang 
31976691acefSXiaoyun Wang create_nic_dev_fail:
319800499a22SXiaoyun Wang 	rte_free(nic_dev->mc_list);
319900499a22SXiaoyun Wang 	nic_dev->mc_list = NULL;
320000499a22SXiaoyun Wang 
320100499a22SXiaoyun Wang mc_addr_fail:
32026691acefSXiaoyun Wang 	rte_free(eth_addr);
32036691acefSXiaoyun Wang 	eth_dev->data->mac_addrs = NULL;
32046691acefSXiaoyun Wang 
32056691acefSXiaoyun Wang eth_addr_fail:
32066691acefSXiaoyun Wang 	PMD_DRV_LOG(ERR, "Initialize %s in primary failed",
32076691acefSXiaoyun Wang 		    eth_dev->data->name);
32086691acefSXiaoyun Wang 	return rc;
32096691acefSXiaoyun Wang }
32106691acefSXiaoyun Wang 
32111d09792aSZiyang Xuan static int hinic_dev_init(struct rte_eth_dev *eth_dev)
32121d09792aSZiyang Xuan {
32131d09792aSZiyang Xuan 	struct rte_pci_device *pci_dev;
32141d09792aSZiyang Xuan 
32151d09792aSZiyang Xuan 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
32161d09792aSZiyang Xuan 
32171d09792aSZiyang Xuan 	PMD_DRV_LOG(INFO, "Initializing pf hinic-%.4x:%.2x:%.2x.%x in %s process",
32181d09792aSZiyang Xuan 		    pci_dev->addr.domain, pci_dev->addr.bus,
32191d09792aSZiyang Xuan 		    pci_dev->addr.devid, pci_dev->addr.function,
32201d09792aSZiyang Xuan 		    (rte_eal_process_type() == RTE_PROC_PRIMARY) ?
32211d09792aSZiyang Xuan 		    "primary" : "secondary");
32221d09792aSZiyang Xuan 
32236691acefSXiaoyun Wang 	/* rte_eth_dev rx_burst and tx_burst */
3224076221c8SZiyang Xuan 	eth_dev->rx_pkt_burst = hinic_recv_pkts;
3225076221c8SZiyang Xuan 	eth_dev->tx_pkt_burst = hinic_xmit_pkts;
32261d09792aSZiyang Xuan 
32271d09792aSZiyang Xuan 	return hinic_func_init(eth_dev);
32281d09792aSZiyang Xuan }
32291d09792aSZiyang Xuan 
32301d09792aSZiyang Xuan static int hinic_dev_uninit(struct rte_eth_dev *dev)
32311d09792aSZiyang Xuan {
32321d09792aSZiyang Xuan 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
32331d09792aSZiyang Xuan 		return 0;
32341d09792aSZiyang Xuan 
32351d09792aSZiyang Xuan 	hinic_dev_close(dev);
32361d09792aSZiyang Xuan 
32371d09792aSZiyang Xuan 	return HINIC_OK;
32381d09792aSZiyang Xuan }
32391d09792aSZiyang Xuan 
32401d09792aSZiyang Xuan static struct rte_pci_id pci_id_hinic_map[] = {
32411d09792aSZiyang Xuan 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_PRD) },
32421d09792aSZiyang Xuan 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_25GE) },
32431d09792aSZiyang Xuan 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_100GE) },
32446691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF) },
32456691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF_HV) },
32466691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_DUAL_25GE) },
32476691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_100GE) },
32481d09792aSZiyang Xuan 	{.vendor_id = 0},
32491d09792aSZiyang Xuan };
32501d09792aSZiyang Xuan 
32511d09792aSZiyang Xuan static int hinic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
32521d09792aSZiyang Xuan 			   struct rte_pci_device *pci_dev)
32531d09792aSZiyang Xuan {
32541d09792aSZiyang Xuan 	return rte_eth_dev_pci_generic_probe(pci_dev,
32551d09792aSZiyang Xuan 		sizeof(struct hinic_nic_dev), hinic_dev_init);
32561d09792aSZiyang Xuan }
32571d09792aSZiyang Xuan 
32581d09792aSZiyang Xuan static int hinic_pci_remove(struct rte_pci_device *pci_dev)
32591d09792aSZiyang Xuan {
32601d09792aSZiyang Xuan 	return rte_eth_dev_pci_generic_remove(pci_dev, hinic_dev_uninit);
32611d09792aSZiyang Xuan }
32621d09792aSZiyang Xuan 
32631d09792aSZiyang Xuan static struct rte_pci_driver rte_hinic_pmd = {
32641d09792aSZiyang Xuan 	.id_table = pci_id_hinic_map,
32651d09792aSZiyang Xuan 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
32661d09792aSZiyang Xuan 	.probe = hinic_pci_probe,
32671d09792aSZiyang Xuan 	.remove = hinic_pci_remove,
32681d09792aSZiyang Xuan };
32691d09792aSZiyang Xuan 
32701d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI(net_hinic, rte_hinic_pmd);
32711d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI_TABLE(net_hinic, pci_id_hinic_map);
3272eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(hinic_logtype, INFO);
3273