xref: /dpdk/drivers/net/hinic/hinic_pmd_ethdev.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
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>
61f37cb2bSDavid Marchand #include <bus_pci_driver.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 
729d4878efSXiaoyun Wang /* lro numer limit for one packet */
739d4878efSXiaoyun Wang #define HINIC_LRO_WQE_NUM_DEFAULT	8
749d4878efSXiaoyun Wang 
75cb7b6606SZiyang Xuan struct hinic_xstats_name_off {
76cb7b6606SZiyang Xuan 	char name[RTE_ETH_XSTATS_NAME_SIZE];
77cb7b6606SZiyang Xuan 	u32  offset;
78cb7b6606SZiyang Xuan };
79cb7b6606SZiyang Xuan 
80cb7b6606SZiyang Xuan #define HINIC_FUNC_STAT(_stat_item) {	\
81cb7b6606SZiyang Xuan 	.name = #_stat_item, \
82cb7b6606SZiyang Xuan 	.offset = offsetof(struct hinic_vport_stats, _stat_item) \
83cb7b6606SZiyang Xuan }
84cb7b6606SZiyang Xuan 
85cb7b6606SZiyang Xuan #define HINIC_PORT_STAT(_stat_item) { \
86cb7b6606SZiyang Xuan 	.name = #_stat_item, \
87cb7b6606SZiyang Xuan 	.offset = offsetof(struct hinic_phy_port_stats, _stat_item) \
88cb7b6606SZiyang Xuan }
89cb7b6606SZiyang Xuan 
90cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_vport_stats_strings[] = {
91cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_unicast_pkts_vport),
92cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_unicast_bytes_vport),
93cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_multicast_pkts_vport),
94cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_multicast_bytes_vport),
95cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_broadcast_pkts_vport),
96cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_broadcast_bytes_vport),
97cb7b6606SZiyang Xuan 
98cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_unicast_pkts_vport),
99cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_unicast_bytes_vport),
100cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_multicast_pkts_vport),
101cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_multicast_bytes_vport),
102cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_broadcast_pkts_vport),
103cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_broadcast_bytes_vport),
104cb7b6606SZiyang Xuan 
105cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_discard_vport),
106cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_discard_vport),
107cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(tx_err_vport),
108cb7b6606SZiyang Xuan 	HINIC_FUNC_STAT(rx_err_vport),
109cb7b6606SZiyang Xuan };
110cb7b6606SZiyang Xuan 
111cb7b6606SZiyang Xuan #define HINIC_VPORT_XSTATS_NUM (sizeof(hinic_vport_stats_strings) / \
112cb7b6606SZiyang Xuan 		sizeof(hinic_vport_stats_strings[0]))
113cb7b6606SZiyang Xuan 
114cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_phyport_stats_strings[] = {
115cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_total_pkt_num),
116cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_total_oct_num),
117cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_bad_pkt_num),
118cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_bad_oct_num),
119cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_good_pkt_num),
120cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_good_oct_num),
121cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_uni_pkt_num),
122cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_multi_pkt_num),
123cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_broad_pkt_num),
124cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_total_pkt_num),
125cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_total_oct_num),
126cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_bad_pkt_num),
127cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_bad_oct_num),
128cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_good_pkt_num),
129cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_good_oct_num),
130cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_uni_pkt_num),
131cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_multi_pkt_num),
132cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_broad_pkt_num),
133cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_fragment_pkt_num),
134cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_undersize_pkt_num),
135cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_undermin_pkt_num),
136cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_64_oct_pkt_num),
137cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_65_127_oct_pkt_num),
138cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_128_255_oct_pkt_num),
139cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_256_511_oct_pkt_num),
140cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_512_1023_oct_pkt_num),
141cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1024_1518_oct_pkt_num),
142cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1519_2047_oct_pkt_num),
143cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_2048_4095_oct_pkt_num),
144cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_4096_8191_oct_pkt_num),
145cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_8192_9216_oct_pkt_num),
146cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_9217_12287_oct_pkt_num),
147cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_12288_16383_oct_pkt_num),
148cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1519_max_bad_pkt_num),
149cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_1519_max_good_pkt_num),
150cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_oversize_pkt_num),
151cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_jabber_pkt_num),
152cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_mac_pause_num),
153cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pkt_num),
154cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri0_pkt_num),
155cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri1_pkt_num),
156cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri2_pkt_num),
157cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri3_pkt_num),
158cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri4_pkt_num),
159cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri5_pkt_num),
160cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri6_pkt_num),
161cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_pfc_pri7_pkt_num),
162cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_mac_control_pkt_num),
163cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_sym_err_pkt_num),
164cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_fcs_err_pkt_num),
165cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_send_app_good_pkt_num),
166cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_rx_send_app_bad_pkt_num),
167cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_fragment_pkt_num),
168cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_undersize_pkt_num),
169cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_undermin_pkt_num),
170cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_64_oct_pkt_num),
171cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_65_127_oct_pkt_num),
172cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_128_255_oct_pkt_num),
173cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_256_511_oct_pkt_num),
174cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_512_1023_oct_pkt_num),
175cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1024_1518_oct_pkt_num),
176cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1519_2047_oct_pkt_num),
177cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_2048_4095_oct_pkt_num),
178cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_4096_8191_oct_pkt_num),
179cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_8192_9216_oct_pkt_num),
180cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_9217_12287_oct_pkt_num),
181cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_12288_16383_oct_pkt_num),
182cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1519_max_bad_pkt_num),
183cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_1519_max_good_pkt_num),
184cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_oversize_pkt_num),
185cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_trans_jabber_pkt_num),
186cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_mac_pause_num),
187cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pkt_num),
188cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri0_pkt_num),
189cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri1_pkt_num),
190cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri2_pkt_num),
191cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri3_pkt_num),
192cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri4_pkt_num),
193cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri5_pkt_num),
194cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri6_pkt_num),
195cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_pfc_pri7_pkt_num),
196cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_mac_control_pkt_num),
197cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_err_all_pkt_num),
198cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_from_app_good_pkt_num),
199cb7b6606SZiyang Xuan 	HINIC_PORT_STAT(mac_tx_from_app_bad_pkt_num),
200cb7b6606SZiyang Xuan };
201cb7b6606SZiyang Xuan 
202cb7b6606SZiyang Xuan #define HINIC_PHYPORT_XSTATS_NUM (sizeof(hinic_phyport_stats_strings) / \
203cb7b6606SZiyang Xuan 		sizeof(hinic_phyport_stats_strings[0]))
204cb7b6606SZiyang Xuan 
205cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_rxq_stats_strings[] = {
206cb7b6606SZiyang Xuan 	{"rx_nombuf", offsetof(struct hinic_rxq_stats, rx_nombuf)},
207cb7b6606SZiyang Xuan 	{"burst_pkt", offsetof(struct hinic_rxq_stats, burst_pkts)},
208cb7b6606SZiyang Xuan };
209cb7b6606SZiyang Xuan 
210cb7b6606SZiyang Xuan #define HINIC_RXQ_XSTATS_NUM (sizeof(hinic_rxq_stats_strings) / \
211cb7b6606SZiyang Xuan 		sizeof(hinic_rxq_stats_strings[0]))
212cb7b6606SZiyang Xuan 
213cb7b6606SZiyang Xuan static const struct hinic_xstats_name_off hinic_txq_stats_strings[] = {
214cb7b6606SZiyang Xuan 	{"tx_busy", offsetof(struct hinic_txq_stats, tx_busy)},
215cb7b6606SZiyang Xuan 	{"offload_errors", offsetof(struct hinic_txq_stats, off_errs)},
216cb7b6606SZiyang Xuan 	{"copy_pkts", offsetof(struct hinic_txq_stats, cpy_pkts)},
217cb7b6606SZiyang Xuan 	{"rl_drop", offsetof(struct hinic_txq_stats, rl_drop)},
218cb7b6606SZiyang Xuan 	{"burst_pkts", offsetof(struct hinic_txq_stats, burst_pkts)},
21954faba22SXiaoyun Wang 	{"sge_len0", offsetof(struct hinic_txq_stats, sge_len0)},
22054faba22SXiaoyun Wang 	{"mbuf_null", offsetof(struct hinic_txq_stats, mbuf_null)},
221cb7b6606SZiyang Xuan };
222cb7b6606SZiyang Xuan 
223cb7b6606SZiyang Xuan #define HINIC_TXQ_XSTATS_NUM (sizeof(hinic_txq_stats_strings) / \
224cb7b6606SZiyang Xuan 		sizeof(hinic_txq_stats_strings[0]))
225cb7b6606SZiyang Xuan 
226cb7b6606SZiyang Xuan static int hinic_xstats_calc_num(struct hinic_nic_dev *nic_dev)
227cb7b6606SZiyang Xuan {
2286691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev)) {
2296691acefSXiaoyun Wang 		return (HINIC_VPORT_XSTATS_NUM +
2306691acefSXiaoyun Wang 			HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq +
2316691acefSXiaoyun Wang 			HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq);
2326691acefSXiaoyun Wang 	} else {
233cb7b6606SZiyang Xuan 		return (HINIC_VPORT_XSTATS_NUM +
234cb7b6606SZiyang Xuan 			HINIC_PHYPORT_XSTATS_NUM +
235cb7b6606SZiyang Xuan 			HINIC_RXQ_XSTATS_NUM * nic_dev->num_rq +
236cb7b6606SZiyang Xuan 			HINIC_TXQ_XSTATS_NUM * nic_dev->num_sq);
237cb7b6606SZiyang Xuan 	}
2386691acefSXiaoyun Wang }
239cb7b6606SZiyang Xuan 
2401d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_rx_desc_lim = {
2411d09792aSZiyang Xuan 	.nb_max = HINIC_MAX_QUEUE_DEPTH,
2421d09792aSZiyang Xuan 	.nb_min = HINIC_MIN_QUEUE_DEPTH,
2431d09792aSZiyang Xuan 	.nb_align = HINIC_RXD_ALIGN,
2441d09792aSZiyang Xuan };
2451d09792aSZiyang Xuan 
2461d09792aSZiyang Xuan static const struct rte_eth_desc_lim hinic_tx_desc_lim = {
2471d09792aSZiyang Xuan 	.nb_max = HINIC_MAX_QUEUE_DEPTH,
2481d09792aSZiyang Xuan 	.nb_min = HINIC_MIN_QUEUE_DEPTH,
2491d09792aSZiyang Xuan 	.nb_align = HINIC_TXD_ALIGN,
2501d09792aSZiyang Xuan };
2511d09792aSZiyang Xuan 
252fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask);
2532c473729SZiyang Xuan 
2541d09792aSZiyang Xuan /**
25564727024SZiyang Xuan  * Interrupt handler triggered by NIC  for handling
25664727024SZiyang Xuan  * specific event.
25764727024SZiyang Xuan  *
2587be78d02SJosh Soref  * @param: The address of parameter (struct rte_eth_dev *) registered before.
259c3ba1f0fSXiaoyun Wang  */
26064727024SZiyang Xuan static void hinic_dev_interrupt_handler(void *param)
26164727024SZiyang Xuan {
26264727024SZiyang Xuan 	struct rte_eth_dev *dev = param;
26364727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
26464727024SZiyang Xuan 
2650371535dSJoyce Kong 	if (!rte_bit_relaxed_get32(HINIC_DEV_INTR_EN, &nic_dev->dev_status)) {
26664727024SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Device's interrupt is disabled, ignore interrupt event, dev_name: %s, port_id: %d",
26764727024SZiyang Xuan 			    nic_dev->proc_dev_name, dev->data->port_id);
26864727024SZiyang Xuan 		return;
26964727024SZiyang Xuan 	}
27064727024SZiyang Xuan 
27164727024SZiyang Xuan 	/* aeq0 msg handler */
27264727024SZiyang Xuan 	hinic_dev_handle_aeq_event(nic_dev->hwdev, param);
27364727024SZiyang Xuan }
27464727024SZiyang Xuan 
27564727024SZiyang Xuan /**
27664727024SZiyang Xuan  * Ethernet device configuration.
27764727024SZiyang Xuan  *
27864727024SZiyang Xuan  * Prepare the driver for a given number of TX and RX queues, mtu size
27964727024SZiyang Xuan  * and configure RSS.
28064727024SZiyang Xuan  *
28164727024SZiyang Xuan  * @param dev
28264727024SZiyang Xuan  *   Pointer to Ethernet device structure.
28364727024SZiyang Xuan  *
28464727024SZiyang Xuan  * @return
28564727024SZiyang Xuan  *   0 on success, negative error value otherwise.
28664727024SZiyang Xuan  */
28764727024SZiyang Xuan static int hinic_dev_configure(struct rte_eth_dev *dev)
28864727024SZiyang Xuan {
28964727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
29064727024SZiyang Xuan 	struct hinic_nic_io *nic_io;
29164727024SZiyang Xuan 	int err;
29264727024SZiyang Xuan 
29364727024SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
29464727024SZiyang Xuan 	nic_io = nic_dev->hwdev->nic_io;
29564727024SZiyang Xuan 
29664727024SZiyang Xuan 	nic_dev->num_sq =  dev->data->nb_tx_queues;
29764727024SZiyang Xuan 	nic_dev->num_rq = dev->data->nb_rx_queues;
29864727024SZiyang Xuan 
29964727024SZiyang Xuan 	nic_io->num_sqs =  dev->data->nb_tx_queues;
30064727024SZiyang Xuan 	nic_io->num_rqs = dev->data->nb_rx_queues;
30164727024SZiyang Xuan 
30264727024SZiyang Xuan 	/* queue pair is max_num(sq, rq) */
30364727024SZiyang Xuan 	nic_dev->num_qps = (nic_dev->num_sq > nic_dev->num_rq) ?
30464727024SZiyang Xuan 			nic_dev->num_sq : nic_dev->num_rq;
30564727024SZiyang Xuan 	nic_io->num_qps = nic_dev->num_qps;
30664727024SZiyang Xuan 
30764727024SZiyang Xuan 	if (nic_dev->num_qps > nic_io->max_qps) {
30864727024SZiyang Xuan 		PMD_DRV_LOG(ERR,
30964727024SZiyang Xuan 			"Queue number out of range, get queue_num:%d, max_queue_num:%d",
31064727024SZiyang Xuan 			nic_dev->num_qps, nic_io->max_qps);
31164727024SZiyang Xuan 		return -EINVAL;
31264727024SZiyang Xuan 	}
31364727024SZiyang Xuan 
314295968d1SFerruh Yigit 	if (dev->data->dev_conf.rxmode.mq_mode & RTE_ETH_MQ_RX_RSS_FLAG)
315295968d1SFerruh Yigit 		dev->data->dev_conf.rxmode.offloads |= RTE_ETH_RX_OFFLOAD_RSS_HASH;
3168b945a7fSPavan Nikhilesh 
31764727024SZiyang Xuan 	/* mtu size is 256~9600 */
3181bb4a528SFerruh Yigit 	if (HINIC_MTU_TO_PKTLEN(dev->data->dev_conf.rxmode.mtu) <
3191bb4a528SFerruh Yigit 			HINIC_MIN_FRAME_SIZE ||
3201bb4a528SFerruh Yigit 	    HINIC_MTU_TO_PKTLEN(dev->data->dev_conf.rxmode.mtu) >
32164727024SZiyang Xuan 			HINIC_MAX_JUMBO_FRAME_SIZE) {
32264727024SZiyang Xuan 		PMD_DRV_LOG(ERR,
3231bb4a528SFerruh Yigit 			"Packet length out of range, get packet length:%d, "
32464727024SZiyang Xuan 			"expect between %d and %d",
3251bb4a528SFerruh Yigit 			HINIC_MTU_TO_PKTLEN(dev->data->dev_conf.rxmode.mtu),
32664727024SZiyang Xuan 			HINIC_MIN_FRAME_SIZE, HINIC_MAX_JUMBO_FRAME_SIZE);
32764727024SZiyang Xuan 		return -EINVAL;
32864727024SZiyang Xuan 	}
32964727024SZiyang Xuan 
3301bb4a528SFerruh Yigit 	nic_dev->mtu_size = dev->data->dev_conf.rxmode.mtu;
33164727024SZiyang Xuan 
33264727024SZiyang Xuan 	/* rss template */
33364727024SZiyang Xuan 	err = hinic_config_mq_mode(dev, TRUE);
33464727024SZiyang Xuan 	if (err) {
33564727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Config multi-queue failed");
33664727024SZiyang Xuan 		return err;
33764727024SZiyang Xuan 	}
33864727024SZiyang Xuan 
3397be78d02SJosh Soref 	/* init VLAN offload */
340fdba3bf1SXiaoyun Wang 	err = hinic_vlan_offload_set(dev,
341295968d1SFerruh Yigit 				RTE_ETH_VLAN_STRIP_MASK | RTE_ETH_VLAN_FILTER_MASK);
342fdba3bf1SXiaoyun Wang 	if (err) {
3434f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Initialize vlan filter and strip failed");
344fdba3bf1SXiaoyun Wang 		(void)hinic_config_mq_mode(dev, FALSE);
345fdba3bf1SXiaoyun Wang 		return err;
346fdba3bf1SXiaoyun Wang 	}
347fdba3bf1SXiaoyun Wang 
3481742421bSXiaoyun Wang 	/* clear fdir filter flag in function table */
3491742421bSXiaoyun Wang 	hinic_free_fdir_filter(nic_dev);
3501742421bSXiaoyun Wang 
35164727024SZiyang Xuan 	return HINIC_OK;
35264727024SZiyang Xuan }
35364727024SZiyang Xuan 
35464727024SZiyang Xuan /**
3552c473729SZiyang Xuan  * DPDK callback to create the receive queue.
3562c473729SZiyang Xuan  *
3572c473729SZiyang Xuan  * @param dev
3582c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
3592c473729SZiyang Xuan  * @param queue_idx
3602c473729SZiyang Xuan  *   RX queue index.
3612c473729SZiyang Xuan  * @param nb_desc
3622c473729SZiyang Xuan  *   Number of descriptors for receive queue.
3632c473729SZiyang Xuan  * @param socket_id
3642c473729SZiyang Xuan  *   NUMA socket on which memory must be allocated.
3652c473729SZiyang Xuan  * @param rx_conf
3662c473729SZiyang Xuan  *   Thresholds parameters (unused_).
3672c473729SZiyang Xuan  * @param mp
3682c473729SZiyang Xuan  *   Memory pool for buffer allocations.
3692c473729SZiyang Xuan  *
3702c473729SZiyang Xuan  * @return
3712c473729SZiyang Xuan  *   0 on success, negative error value otherwise.
3722c473729SZiyang Xuan  */
3732c473729SZiyang Xuan static int hinic_rx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
3742c473729SZiyang Xuan 			 uint16_t nb_desc, unsigned int socket_id,
3752c473729SZiyang Xuan 			 __rte_unused const struct rte_eth_rxconf *rx_conf,
3762c473729SZiyang Xuan 			 struct rte_mempool *mp)
3772c473729SZiyang Xuan {
3782c473729SZiyang Xuan 	int rc;
3792c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
3802c473729SZiyang Xuan 	struct hinic_hwdev *hwdev;
3812c473729SZiyang Xuan 	struct hinic_rxq *rxq;
3822c473729SZiyang Xuan 	u16 rq_depth, rx_free_thresh;
3832c473729SZiyang Xuan 	u32 buf_size;
3842c473729SZiyang Xuan 
3852c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
3862c473729SZiyang Xuan 	hwdev = nic_dev->hwdev;
3872c473729SZiyang Xuan 
3882c473729SZiyang Xuan 	/* queue depth must be power of 2, otherwise will be aligned up */
3892c473729SZiyang Xuan 	rq_depth = (nb_desc & (nb_desc - 1)) ?
3902c473729SZiyang Xuan 		((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc;
3912c473729SZiyang Xuan 
3922c473729SZiyang Xuan 	/*
3932c473729SZiyang Xuan 	 * Validate number of receive descriptors.
3942c473729SZiyang Xuan 	 * It must not exceed hardware maximum and minimum.
3952c473729SZiyang Xuan 	 */
3962c473729SZiyang Xuan 	if (rq_depth > HINIC_MAX_QUEUE_DEPTH ||
3972c473729SZiyang Xuan 		rq_depth < HINIC_MIN_QUEUE_DEPTH) {
3982c473729SZiyang 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)",
3992c473729SZiyang Xuan 			    HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH,
4002c473729SZiyang Xuan 			    (int)nb_desc, (int)rq_depth,
4012c473729SZiyang Xuan 			    (int)dev->data->port_id, (int)queue_idx);
4022c473729SZiyang Xuan 		return -EINVAL;
4032c473729SZiyang Xuan 	}
4042c473729SZiyang Xuan 
4052c473729SZiyang Xuan 	/*
4062c473729SZiyang Xuan 	 * The RX descriptor ring will be cleaned after rxq->rx_free_thresh
4072c473729SZiyang Xuan 	 * descriptors are used or if the number of descriptors required
4082c473729SZiyang Xuan 	 * to transmit a packet is greater than the number of free RX
4092c473729SZiyang Xuan 	 * descriptors.
4102c473729SZiyang Xuan 	 * The following constraints must be satisfied:
4112c473729SZiyang Xuan 	 *  rx_free_thresh must be greater than 0.
4122c473729SZiyang Xuan 	 *  rx_free_thresh must be less than the size of the ring minus 1.
4132c473729SZiyang Xuan 	 * When set to zero use default values.
4142c473729SZiyang Xuan 	 */
4152c473729SZiyang Xuan 	rx_free_thresh = (u16)((rx_conf->rx_free_thresh) ?
4162c473729SZiyang Xuan 			rx_conf->rx_free_thresh : HINIC_DEFAULT_RX_FREE_THRESH);
4172c473729SZiyang Xuan 	if (rx_free_thresh >= (rq_depth - 1)) {
4182c473729SZiyang 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)",
4192c473729SZiyang Xuan 			    (unsigned int)rx_free_thresh,
4202c473729SZiyang Xuan 			    (int)dev->data->port_id,
4212c473729SZiyang Xuan 			    (int)queue_idx);
4222c473729SZiyang Xuan 		return -EINVAL;
4232c473729SZiyang Xuan 	}
4242c473729SZiyang Xuan 
4252c473729SZiyang Xuan 	rxq = rte_zmalloc_socket("hinic_rx_queue", sizeof(struct hinic_rxq),
4262c473729SZiyang Xuan 				 RTE_CACHE_LINE_SIZE, socket_id);
4272c473729SZiyang Xuan 	if (!rxq) {
4282c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate rxq[%d] failed, dev_name: %s",
4292c473729SZiyang Xuan 			    queue_idx, dev->data->name);
4302c473729SZiyang Xuan 		return -ENOMEM;
4312c473729SZiyang Xuan 	}
4322c473729SZiyang Xuan 	nic_dev->rxqs[queue_idx] = rxq;
4332c473729SZiyang Xuan 
4342c473729SZiyang Xuan 	/* alloc rx sq hw wqe page */
4351b7b9f17SXiaoyun Wang 	rc = hinic_create_rq(hwdev, queue_idx, rq_depth, socket_id);
4362c473729SZiyang Xuan 	if (rc) {
4372c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Create rxq[%d] failed, dev_name: %s, rq_depth: %d",
4382c473729SZiyang Xuan 			    queue_idx, dev->data->name, rq_depth);
4392c473729SZiyang Xuan 		goto ceate_rq_fail;
4402c473729SZiyang Xuan 	}
4412c473729SZiyang Xuan 
4422c473729SZiyang Xuan 	/* mbuf pool must be assigned before setup rx resources */
4432c473729SZiyang Xuan 	rxq->mb_pool = mp;
4442c473729SZiyang Xuan 
4452c473729SZiyang Xuan 	rc =
4462c473729SZiyang Xuan 	hinic_convert_rx_buf_size(rte_pktmbuf_data_room_size(rxq->mb_pool) -
4472c473729SZiyang Xuan 				  RTE_PKTMBUF_HEADROOM, &buf_size);
4482c473729SZiyang Xuan 	if (rc) {
4492c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Adjust buf size failed, dev_name: %s",
4502c473729SZiyang Xuan 			    dev->data->name);
4512c473729SZiyang Xuan 		goto adjust_bufsize_fail;
4522c473729SZiyang Xuan 	}
4532c473729SZiyang Xuan 
4542c473729SZiyang Xuan 	/* rx queue info, rearm control */
4552c473729SZiyang Xuan 	rxq->wq = &hwdev->nic_io->rq_wq[queue_idx];
4562c473729SZiyang Xuan 	rxq->pi_virt_addr = hwdev->nic_io->qps[queue_idx].rq.pi_virt_addr;
4572c473729SZiyang Xuan 	rxq->nic_dev = nic_dev;
4582c473729SZiyang Xuan 	rxq->q_id = queue_idx;
4592c473729SZiyang Xuan 	rxq->q_depth = rq_depth;
4602c473729SZiyang Xuan 	rxq->buf_len = (u16)buf_size;
4612c473729SZiyang Xuan 	rxq->rx_free_thresh = rx_free_thresh;
4621b7b9f17SXiaoyun Wang 	rxq->socket_id = socket_id;
4632c473729SZiyang Xuan 
4642c473729SZiyang Xuan 	/* the last point cant do mbuf rearm in bulk */
4652c473729SZiyang Xuan 	rxq->rxinfo_align_end = rxq->q_depth - rxq->rx_free_thresh;
4662c473729SZiyang Xuan 
4672c473729SZiyang Xuan 	/* device port identifier */
4682c473729SZiyang Xuan 	rxq->port_id = dev->data->port_id;
4692c473729SZiyang Xuan 
4702c473729SZiyang Xuan 	/* alloc rx_cqe and prepare rq_wqe */
4712c473729SZiyang Xuan 	rc = hinic_setup_rx_resources(rxq);
4722c473729SZiyang Xuan 	if (rc) {
4732c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Setup rxq[%d] rx_resources failed, dev_name: %s",
4742c473729SZiyang Xuan 			    queue_idx, dev->data->name);
4752c473729SZiyang Xuan 		goto setup_rx_res_err;
4762c473729SZiyang Xuan 	}
4772c473729SZiyang Xuan 
4782c473729SZiyang Xuan 	/* record nic_dev rxq in rte_eth rx_queues */
4792c473729SZiyang Xuan 	dev->data->rx_queues[queue_idx] = rxq;
4802c473729SZiyang Xuan 
4812c473729SZiyang Xuan 	return 0;
4822c473729SZiyang Xuan 
4832c473729SZiyang Xuan setup_rx_res_err:
4842c473729SZiyang Xuan adjust_bufsize_fail:
4852c473729SZiyang Xuan 	hinic_destroy_rq(hwdev, queue_idx);
4862c473729SZiyang Xuan 
4872c473729SZiyang Xuan ceate_rq_fail:
4882c473729SZiyang Xuan 	rte_free(rxq);
4892c473729SZiyang Xuan 
4902c473729SZiyang Xuan 	return rc;
4912c473729SZiyang Xuan }
4922c473729SZiyang Xuan 
4932c473729SZiyang Xuan static void hinic_reset_rx_queue(struct rte_eth_dev *dev)
4942c473729SZiyang Xuan {
4952c473729SZiyang Xuan 	struct hinic_rxq *rxq;
4962c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
4972c473729SZiyang Xuan 	int q_id = 0;
4982c473729SZiyang Xuan 
4992c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
5002c473729SZiyang Xuan 
5012c473729SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_rq; q_id++) {
5022c473729SZiyang Xuan 		rxq = dev->data->rx_queues[q_id];
5032c473729SZiyang Xuan 
5042c473729SZiyang Xuan 		rxq->wq->cons_idx = 0;
5052c473729SZiyang Xuan 		rxq->wq->prod_idx = 0;
5062c473729SZiyang Xuan 		rxq->wq->delta = rxq->q_depth;
5072c473729SZiyang Xuan 		rxq->wq->mask = rxq->q_depth - 1;
5082c473729SZiyang Xuan 
5092c473729SZiyang Xuan 		/* alloc mbuf to rq */
5102c473729SZiyang Xuan 		hinic_rx_alloc_pkts(rxq);
5112c473729SZiyang Xuan 	}
5122c473729SZiyang Xuan }
5132c473729SZiyang Xuan 
5142c473729SZiyang Xuan /**
5152c473729SZiyang Xuan  * DPDK callback to configure the transmit queue.
5162c473729SZiyang Xuan  *
5172c473729SZiyang Xuan  * @param dev
5182c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
5192c473729SZiyang Xuan  * @param queue_idx
5202c473729SZiyang Xuan  *   Transmit queue index.
5212c473729SZiyang Xuan  * @param nb_desc
5222c473729SZiyang Xuan  *   Number of descriptors for transmit queue.
5232c473729SZiyang Xuan  * @param socket_id
5242c473729SZiyang Xuan  *   NUMA socket on which memory must be allocated.
5252c473729SZiyang Xuan  * @param tx_conf
5262c473729SZiyang Xuan  *   Tx queue configuration parameters.
5272c473729SZiyang Xuan  *
5282c473729SZiyang Xuan  * @return
5292c473729SZiyang Xuan  *   0 on success, negative error value otherwise.
5302c473729SZiyang Xuan  */
5312c473729SZiyang Xuan static int hinic_tx_queue_setup(struct rte_eth_dev *dev, uint16_t queue_idx,
5322c473729SZiyang Xuan 			 uint16_t nb_desc, unsigned int socket_id,
5332c473729SZiyang Xuan 			 __rte_unused const struct rte_eth_txconf *tx_conf)
5342c473729SZiyang Xuan {
5352c473729SZiyang Xuan 	int rc;
5362c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
5372c473729SZiyang Xuan 	struct hinic_hwdev *hwdev;
5382c473729SZiyang Xuan 	struct hinic_txq *txq;
5392c473729SZiyang Xuan 	u16 sq_depth, tx_free_thresh;
5402c473729SZiyang Xuan 
5412c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
5422c473729SZiyang Xuan 	hwdev = nic_dev->hwdev;
5432c473729SZiyang Xuan 
5442c473729SZiyang Xuan 	/* queue depth must be power of 2, otherwise will be aligned up */
5452c473729SZiyang Xuan 	sq_depth = (nb_desc & (nb_desc - 1)) ?
5462c473729SZiyang Xuan 			((u16)(1U << (ilog2(nb_desc) + 1))) : nb_desc;
5472c473729SZiyang Xuan 
5482c473729SZiyang Xuan 	/*
5492c473729SZiyang Xuan 	 * Validate number of transmit descriptors.
5502c473729SZiyang Xuan 	 * It must not exceed hardware maximum and minimum.
5512c473729SZiyang Xuan 	 */
5522c473729SZiyang Xuan 	if (sq_depth > HINIC_MAX_QUEUE_DEPTH ||
5532c473729SZiyang Xuan 		sq_depth < HINIC_MIN_QUEUE_DEPTH) {
5542c473729SZiyang 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)",
5552c473729SZiyang Xuan 			  HINIC_MIN_QUEUE_DEPTH, HINIC_MAX_QUEUE_DEPTH,
5562c473729SZiyang Xuan 			  (int)nb_desc, (int)sq_depth,
5572c473729SZiyang Xuan 			  (int)dev->data->port_id, (int)queue_idx);
5582c473729SZiyang Xuan 		return -EINVAL;
5592c473729SZiyang Xuan 	}
5602c473729SZiyang Xuan 
5612c473729SZiyang Xuan 	/*
5622c473729SZiyang Xuan 	 * The TX descriptor ring will be cleaned after txq->tx_free_thresh
5632c473729SZiyang Xuan 	 * descriptors are used or if the number of descriptors required
5642c473729SZiyang Xuan 	 * to transmit a packet is greater than the number of free TX
5652c473729SZiyang Xuan 	 * descriptors.
5662c473729SZiyang Xuan 	 * The following constraints must be satisfied:
5672c473729SZiyang Xuan 	 *  tx_free_thresh must be greater than 0.
5682c473729SZiyang Xuan 	 *  tx_free_thresh must be less than the size of the ring minus 1.
5692c473729SZiyang Xuan 	 * When set to zero use default values.
5702c473729SZiyang Xuan 	 */
5712c473729SZiyang Xuan 	tx_free_thresh = (u16)((tx_conf->tx_free_thresh) ?
5722c473729SZiyang Xuan 			tx_conf->tx_free_thresh : HINIC_DEFAULT_TX_FREE_THRESH);
5732c473729SZiyang Xuan 	if (tx_free_thresh >= (sq_depth - 1)) {
5742c473729SZiyang 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)",
5752c473729SZiyang Xuan 			(unsigned int)tx_free_thresh, (int)dev->data->port_id,
5762c473729SZiyang Xuan 			(int)queue_idx);
5772c473729SZiyang Xuan 		return -EINVAL;
5782c473729SZiyang Xuan 	}
5792c473729SZiyang Xuan 
5802c473729SZiyang Xuan 	txq = rte_zmalloc_socket("hinic_tx_queue", sizeof(struct hinic_txq),
5812c473729SZiyang Xuan 				 RTE_CACHE_LINE_SIZE, socket_id);
5822c473729SZiyang Xuan 	if (!txq) {
5832c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate txq[%d] failed, dev_name: %s",
5842c473729SZiyang Xuan 			    queue_idx, dev->data->name);
5852c473729SZiyang Xuan 		return -ENOMEM;
5862c473729SZiyang Xuan 	}
5872c473729SZiyang Xuan 	nic_dev->txqs[queue_idx] = txq;
5882c473729SZiyang Xuan 
5892c473729SZiyang Xuan 	/* alloc tx sq hw wqepage */
5901b7b9f17SXiaoyun Wang 	rc = hinic_create_sq(hwdev, queue_idx, sq_depth, socket_id);
5912c473729SZiyang Xuan 	if (rc) {
5922c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Create txq[%d] failed, dev_name: %s, sq_depth: %d",
5932c473729SZiyang Xuan 			    queue_idx, dev->data->name, sq_depth);
5942c473729SZiyang Xuan 		goto create_sq_fail;
5952c473729SZiyang Xuan 	}
5962c473729SZiyang Xuan 
5972c473729SZiyang Xuan 	txq->q_id = queue_idx;
5982c473729SZiyang Xuan 	txq->q_depth = sq_depth;
5992c473729SZiyang Xuan 	txq->port_id = dev->data->port_id;
6002c473729SZiyang Xuan 	txq->tx_free_thresh = tx_free_thresh;
6012c473729SZiyang Xuan 	txq->nic_dev = nic_dev;
6022c473729SZiyang Xuan 	txq->wq = &hwdev->nic_io->sq_wq[queue_idx];
6032c473729SZiyang Xuan 	txq->sq = &hwdev->nic_io->qps[queue_idx].sq;
6042c473729SZiyang Xuan 	txq->cons_idx_addr = hwdev->nic_io->qps[queue_idx].sq.cons_idx_addr;
6052c473729SZiyang Xuan 	txq->sq_head_addr = HINIC_GET_WQ_HEAD(txq);
6062c473729SZiyang Xuan 	txq->sq_bot_sge_addr = HINIC_GET_WQ_TAIL(txq) -
6072c473729SZiyang Xuan 					sizeof(struct hinic_sq_bufdesc);
6082c473729SZiyang Xuan 	txq->cos = nic_dev->default_cos;
6091b7b9f17SXiaoyun Wang 	txq->socket_id = socket_id;
6102c473729SZiyang Xuan 
6112c473729SZiyang Xuan 	/* alloc software txinfo */
6122c473729SZiyang Xuan 	rc = hinic_setup_tx_resources(txq);
6132c473729SZiyang Xuan 	if (rc) {
6142c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Setup txq[%d] tx_resources failed, dev_name: %s",
6152c473729SZiyang Xuan 			    queue_idx, dev->data->name);
6162c473729SZiyang Xuan 		goto setup_tx_res_fail;
6172c473729SZiyang Xuan 	}
6182c473729SZiyang Xuan 
6192c473729SZiyang Xuan 	/* record nic_dev txq in rte_eth tx_queues */
6202c473729SZiyang Xuan 	dev->data->tx_queues[queue_idx] = txq;
6212c473729SZiyang Xuan 
6222c473729SZiyang Xuan 	return HINIC_OK;
6232c473729SZiyang Xuan 
6242c473729SZiyang Xuan setup_tx_res_fail:
6252c473729SZiyang Xuan 	hinic_destroy_sq(hwdev, queue_idx);
6262c473729SZiyang Xuan 
6272c473729SZiyang Xuan create_sq_fail:
6282c473729SZiyang Xuan 	rte_free(txq);
6292c473729SZiyang Xuan 
6302c473729SZiyang Xuan 	return rc;
6312c473729SZiyang Xuan }
6322c473729SZiyang Xuan 
6332c473729SZiyang Xuan static void hinic_reset_tx_queue(struct rte_eth_dev *dev)
6342c473729SZiyang Xuan {
6352c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
6362c473729SZiyang Xuan 	struct hinic_txq *txq;
6372c473729SZiyang Xuan 	struct hinic_nic_io *nic_io;
6382c473729SZiyang Xuan 	struct hinic_hwdev *hwdev;
6392c473729SZiyang Xuan 	volatile u32 *ci_addr;
6402c473729SZiyang Xuan 	int q_id = 0;
6412c473729SZiyang Xuan 
6422c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
6432c473729SZiyang Xuan 	hwdev = nic_dev->hwdev;
6442c473729SZiyang Xuan 	nic_io = hwdev->nic_io;
6452c473729SZiyang Xuan 
6462c473729SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_sq; q_id++) {
6472c473729SZiyang Xuan 		txq = dev->data->tx_queues[q_id];
6482c473729SZiyang Xuan 
6492c473729SZiyang Xuan 		txq->wq->cons_idx = 0;
6502c473729SZiyang Xuan 		txq->wq->prod_idx = 0;
6512c473729SZiyang Xuan 		txq->wq->delta = txq->q_depth;
6522c473729SZiyang Xuan 		txq->wq->mask  = txq->q_depth - 1;
6532c473729SZiyang Xuan 
6542c473729SZiyang Xuan 		/* clear hardware ci */
6552c473729SZiyang Xuan 		ci_addr = (volatile u32 *)HINIC_CI_VADDR(nic_io->ci_vaddr_base,
6562c473729SZiyang Xuan 							q_id);
6572c473729SZiyang Xuan 		*ci_addr = 0;
6582c473729SZiyang Xuan 	}
6592c473729SZiyang Xuan }
6602c473729SZiyang Xuan 
6612c473729SZiyang Xuan /**
6621d09792aSZiyang Xuan  * Get link speed from NIC.
6631d09792aSZiyang Xuan  *
6641d09792aSZiyang Xuan  * @param dev
6651d09792aSZiyang Xuan  *   Pointer to Ethernet device structure.
6661d09792aSZiyang Xuan  * @param speed_capa
6671d09792aSZiyang Xuan  *   Pointer to link speed structure.
6681d09792aSZiyang Xuan  */
6691d09792aSZiyang Xuan static void hinic_get_speed_capa(struct rte_eth_dev *dev, uint32_t *speed_capa)
6701d09792aSZiyang Xuan {
6711d09792aSZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
6721d09792aSZiyang Xuan 	u32 supported_link, advertised_link;
6731d09792aSZiyang Xuan 	int err;
6741d09792aSZiyang Xuan 
6751d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_1G	(1U << HINIC_GE_BASE_KX)
6761d09792aSZiyang Xuan 
6771d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_10G	(1U << HINIC_10GE_BASE_KR)
6781d09792aSZiyang Xuan 
6791d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_25G	((1U << HINIC_25GE_BASE_KR_S) | \
6801d09792aSZiyang Xuan 					(1U << HINIC_25GE_BASE_CR_S) | \
6811d09792aSZiyang Xuan 					(1U << HINIC_25GE_BASE_KR) | \
6821d09792aSZiyang Xuan 					(1U << HINIC_25GE_BASE_CR))
6831d09792aSZiyang Xuan 
6841d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_40G	((1U << HINIC_40GE_BASE_KR4) | \
6851d09792aSZiyang Xuan 					(1U << HINIC_40GE_BASE_CR4))
6861d09792aSZiyang Xuan 
6871d09792aSZiyang Xuan #define HINIC_LINK_MODE_SUPPORT_100G	((1U << HINIC_100GE_BASE_KR4) | \
6881d09792aSZiyang Xuan 					(1U << HINIC_100GE_BASE_CR4))
6891d09792aSZiyang Xuan 
6901d09792aSZiyang Xuan 	err = hinic_get_link_mode(nic_dev->hwdev,
6911d09792aSZiyang Xuan 				  &supported_link, &advertised_link);
6921d09792aSZiyang Xuan 	if (err || supported_link == HINIC_SUPPORTED_UNKNOWN ||
6931d09792aSZiyang Xuan 	    advertised_link == HINIC_SUPPORTED_UNKNOWN) {
6941d09792aSZiyang Xuan 		PMD_DRV_LOG(WARNING, "Get speed capability info failed, device: %s, port_id: %u",
6951d09792aSZiyang Xuan 			  nic_dev->proc_dev_name, dev->data->port_id);
6961d09792aSZiyang Xuan 	} else {
6971d09792aSZiyang Xuan 		*speed_capa = 0;
6981d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_1G))
699295968d1SFerruh Yigit 			*speed_capa |= RTE_ETH_LINK_SPEED_1G;
7001d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_10G))
701295968d1SFerruh Yigit 			*speed_capa |= RTE_ETH_LINK_SPEED_10G;
7021d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_25G))
703295968d1SFerruh Yigit 			*speed_capa |= RTE_ETH_LINK_SPEED_25G;
7041d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_40G))
705295968d1SFerruh Yigit 			*speed_capa |= RTE_ETH_LINK_SPEED_40G;
7061d09792aSZiyang Xuan 		if (!!(supported_link & HINIC_LINK_MODE_SUPPORT_100G))
707295968d1SFerruh Yigit 			*speed_capa |= RTE_ETH_LINK_SPEED_100G;
7081d09792aSZiyang Xuan 	}
7091d09792aSZiyang Xuan }
7101d09792aSZiyang Xuan 
7111d09792aSZiyang Xuan /**
7121d09792aSZiyang Xuan  * DPDK callback to get information about the device.
7131d09792aSZiyang Xuan  *
7141d09792aSZiyang Xuan  * @param dev
7151d09792aSZiyang Xuan  *   Pointer to Ethernet device structure.
7161d09792aSZiyang Xuan  * @param info
7171d09792aSZiyang Xuan  *   Pointer to Info structure output buffer.
7181d09792aSZiyang Xuan  */
719bdad90d1SIvan Ilchenko static int
7201d09792aSZiyang Xuan hinic_dev_infos_get(struct rte_eth_dev *dev, struct rte_eth_dev_info *info)
7211d09792aSZiyang Xuan {
7221d09792aSZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
7231d09792aSZiyang Xuan 
7241d09792aSZiyang Xuan 	info->max_rx_queues  = nic_dev->nic_cap.max_rqs;
7251d09792aSZiyang Xuan 	info->max_tx_queues  = nic_dev->nic_cap.max_sqs;
7261d09792aSZiyang Xuan 	info->min_rx_bufsize = HINIC_MIN_RX_BUF_SIZE;
7271d09792aSZiyang Xuan 	info->max_rx_pktlen  = HINIC_MAX_JUMBO_FRAME_SIZE;
72800499a22SXiaoyun Wang 	info->max_mac_addrs  = HINIC_MAX_UC_MAC_ADDRS;
7298260eba6SXiaoyun Wang 	info->min_mtu = HINIC_MIN_MTU_SIZE;
7308260eba6SXiaoyun Wang 	info->max_mtu = HINIC_MAX_MTU_SIZE;
7319d02f40dSXiaoyun Wang 	info->max_lro_pkt_size = HINIC_MAX_LRO_SIZE;
7321d09792aSZiyang Xuan 
7331d09792aSZiyang Xuan 	hinic_get_speed_capa(dev, &info->speed_capa);
7341d09792aSZiyang Xuan 	info->rx_queue_offload_capa = 0;
735295968d1SFerruh Yigit 	info->rx_offload_capa = RTE_ETH_RX_OFFLOAD_VLAN_STRIP |
736295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_IPV4_CKSUM |
737295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_UDP_CKSUM |
738295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_TCP_CKSUM |
739295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_VLAN_FILTER |
740295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_SCATTER |
741295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_TCP_LRO |
742295968d1SFerruh Yigit 				RTE_ETH_RX_OFFLOAD_RSS_HASH;
7431d09792aSZiyang Xuan 
7441d09792aSZiyang Xuan 	info->tx_queue_offload_capa = 0;
745295968d1SFerruh Yigit 	info->tx_offload_capa = RTE_ETH_TX_OFFLOAD_VLAN_INSERT |
746295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_IPV4_CKSUM |
747295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_UDP_CKSUM |
748295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_TCP_CKSUM |
749295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_SCTP_CKSUM |
750295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_OUTER_IPV4_CKSUM |
751295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_TCP_TSO |
752295968d1SFerruh Yigit 				RTE_ETH_TX_OFFLOAD_MULTI_SEGS;
7531d09792aSZiyang Xuan 
7542fe6f1b7SDmitry Kozlyuk 	info->dev_capa &= ~RTE_ETH_DEV_CAPA_FLOW_RULE_KEEP;
7552fe6f1b7SDmitry Kozlyuk 
7561d09792aSZiyang Xuan 	info->hash_key_size = HINIC_RSS_KEY_SIZE;
7571d09792aSZiyang Xuan 	info->reta_size = HINIC_RSS_INDIR_SIZE;
75864727024SZiyang Xuan 	info->flow_type_rss_offloads = HINIC_RSS_OFFLOAD_ALL;
7591d09792aSZiyang Xuan 	info->rx_desc_lim = hinic_rx_desc_lim;
7601d09792aSZiyang Xuan 	info->tx_desc_lim = hinic_tx_desc_lim;
761bdad90d1SIvan Ilchenko 
762483b4817SXiaoyun Wang 	/* Driver-preferred Rx/Tx parameters */
763483b4817SXiaoyun Wang 	info->default_rxportconf.burst_size = HINIC_DEFAULT_BURST_SIZE;
764483b4817SXiaoyun Wang 	info->default_txportconf.burst_size = HINIC_DEFAULT_BURST_SIZE;
765483b4817SXiaoyun Wang 	info->default_rxportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES;
766483b4817SXiaoyun Wang 	info->default_txportconf.nb_queues = HINIC_DEFAULT_NB_QUEUES;
767483b4817SXiaoyun Wang 	info->default_rxportconf.ring_size = HINIC_DEFAULT_RING_SIZE;
768483b4817SXiaoyun Wang 	info->default_txportconf.ring_size = HINIC_DEFAULT_RING_SIZE;
769483b4817SXiaoyun Wang 
770bdad90d1SIvan Ilchenko 	return 0;
7711d09792aSZiyang Xuan }
7721d09792aSZiyang Xuan 
773dbf524abSXiaoyun Wang static int hinic_fw_version_get(struct rte_eth_dev *dev, char *fw_version,
774dbf524abSXiaoyun Wang 				size_t fw_size)
775dbf524abSXiaoyun Wang {
776dbf524abSXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
777dbf524abSXiaoyun Wang 	char fw_ver[HINIC_MGMT_VERSION_MAX_LEN] = {0};
778dbf524abSXiaoyun Wang 	int err;
779dbf524abSXiaoyun Wang 
780dbf524abSXiaoyun Wang 	err = hinic_get_mgmt_version(nic_dev->hwdev, fw_ver);
781dbf524abSXiaoyun Wang 	if (err) {
7824f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Failed to get fw version");
783dbf524abSXiaoyun Wang 		return -EINVAL;
784dbf524abSXiaoyun Wang 	}
785dbf524abSXiaoyun Wang 
786dbf524abSXiaoyun Wang 	if (fw_size < strlen(fw_ver) + 1)
787dbf524abSXiaoyun Wang 		return (strlen(fw_ver) + 1);
788dbf524abSXiaoyun Wang 
789dbf524abSXiaoyun Wang 	snprintf(fw_version, fw_size, "%s", fw_ver);
790dbf524abSXiaoyun Wang 
791dbf524abSXiaoyun Wang 	return 0;
792dbf524abSXiaoyun Wang }
793dbf524abSXiaoyun Wang 
7942c473729SZiyang Xuan static int hinic_config_rx_mode(struct hinic_nic_dev *nic_dev, u32 rx_mode_ctrl)
7952c473729SZiyang Xuan {
7962c473729SZiyang Xuan 	int err;
7972c473729SZiyang Xuan 
7982c473729SZiyang Xuan 	err = hinic_set_rx_mode(nic_dev->hwdev, rx_mode_ctrl);
7992c473729SZiyang Xuan 	if (err) {
8002c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set rx mode");
8012c473729SZiyang Xuan 		return -EINVAL;
8022c473729SZiyang Xuan 	}
8032c473729SZiyang Xuan 	nic_dev->rx_mode_status = rx_mode_ctrl;
8042c473729SZiyang Xuan 
8052c473729SZiyang Xuan 	return 0;
8062c473729SZiyang Xuan }
8072c473729SZiyang Xuan 
8082c473729SZiyang Xuan static int hinic_rxtx_configure(struct rte_eth_dev *dev)
8092c473729SZiyang Xuan {
8102c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
8119d02f40dSXiaoyun Wang 	int err;
8122c473729SZiyang Xuan 
8132c473729SZiyang Xuan 	/* rx configure, if rss enable, need to init default configuration */
8142c473729SZiyang Xuan 	err = hinic_rx_configure(dev);
8152c473729SZiyang Xuan 	if (err) {
8162c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure rss failed");
8172c473729SZiyang Xuan 		return err;
8182c473729SZiyang Xuan 	}
8192c473729SZiyang Xuan 
8202c473729SZiyang Xuan 	/* rx mode init */
8212c473729SZiyang Xuan 	err = hinic_config_rx_mode(nic_dev, HINIC_DEFAULT_RX_MODE);
8222c473729SZiyang Xuan 	if (err) {
8232c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure rx_mode:0x%x failed",
8242c473729SZiyang Xuan 			HINIC_DEFAULT_RX_MODE);
8252c473729SZiyang Xuan 		goto set_rx_mode_fail;
8262c473729SZiyang Xuan 	}
8272c473729SZiyang Xuan 
8282c473729SZiyang Xuan 	return HINIC_OK;
8292c473729SZiyang Xuan 
8302c473729SZiyang Xuan set_rx_mode_fail:
8312c473729SZiyang Xuan 	hinic_rx_remove_configure(dev);
8322c473729SZiyang Xuan 
8332c473729SZiyang Xuan 	return err;
8342c473729SZiyang Xuan }
8352c473729SZiyang Xuan 
8362c473729SZiyang Xuan static void hinic_remove_rxtx_configure(struct rte_eth_dev *dev)
8372c473729SZiyang Xuan {
8382c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
8392c473729SZiyang Xuan 
8402c473729SZiyang Xuan 	(void)hinic_config_rx_mode(nic_dev, 0);
8412c473729SZiyang Xuan 	hinic_rx_remove_configure(dev);
8422c473729SZiyang Xuan }
8432c473729SZiyang Xuan 
8442c473729SZiyang Xuan static int hinic_priv_get_dev_link_status(struct hinic_nic_dev *nic_dev,
8452c473729SZiyang Xuan 					  struct rte_eth_link *link)
8462c473729SZiyang Xuan {
8472c473729SZiyang Xuan 	int rc;
8482c473729SZiyang Xuan 	u8 port_link_status = 0;
8492c473729SZiyang Xuan 	struct nic_port_info port_link_info;
8502c473729SZiyang Xuan 	struct hinic_hwdev *nic_hwdev = nic_dev->hwdev;
851295968d1SFerruh Yigit 	uint32_t port_speed[LINK_SPEED_MAX] = {RTE_ETH_SPEED_NUM_10M,
852295968d1SFerruh Yigit 					RTE_ETH_SPEED_NUM_100M, RTE_ETH_SPEED_NUM_1G,
853295968d1SFerruh Yigit 					RTE_ETH_SPEED_NUM_10G, RTE_ETH_SPEED_NUM_25G,
854295968d1SFerruh Yigit 					RTE_ETH_SPEED_NUM_40G, RTE_ETH_SPEED_NUM_100G};
8552c473729SZiyang Xuan 
8562c473729SZiyang Xuan 	rc = hinic_get_link_status(nic_hwdev, &port_link_status);
8572c473729SZiyang Xuan 	if (rc)
8582c473729SZiyang Xuan 		return rc;
8592c473729SZiyang Xuan 
8602c473729SZiyang Xuan 	if (!port_link_status) {
861295968d1SFerruh Yigit 		link->link_status = RTE_ETH_LINK_DOWN;
8622c473729SZiyang Xuan 		link->link_speed = 0;
863295968d1SFerruh Yigit 		link->link_duplex = RTE_ETH_LINK_HALF_DUPLEX;
864295968d1SFerruh Yigit 		link->link_autoneg = RTE_ETH_LINK_FIXED;
8652c473729SZiyang Xuan 		return HINIC_OK;
8662c473729SZiyang Xuan 	}
8672c473729SZiyang Xuan 
8682c473729SZiyang Xuan 	memset(&port_link_info, 0, sizeof(port_link_info));
8692c473729SZiyang Xuan 	rc = hinic_get_port_info(nic_hwdev, &port_link_info);
8702c473729SZiyang Xuan 	if (rc)
8712c473729SZiyang Xuan 		return rc;
8722c473729SZiyang Xuan 
8732c473729SZiyang Xuan 	link->link_speed = port_speed[port_link_info.speed % LINK_SPEED_MAX];
8742c473729SZiyang Xuan 	link->link_duplex = port_link_info.duplex;
8752c473729SZiyang Xuan 	link->link_autoneg = port_link_info.autoneg_state;
8762c473729SZiyang Xuan 	link->link_status = port_link_status;
8772c473729SZiyang Xuan 
8782c473729SZiyang Xuan 	return HINIC_OK;
8792c473729SZiyang Xuan }
8802c473729SZiyang Xuan 
8812c473729SZiyang Xuan /**
8822c473729SZiyang Xuan  * DPDK callback to retrieve physical link information.
8832c473729SZiyang Xuan  *
8842c473729SZiyang Xuan  * @param dev
8852c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
8862c473729SZiyang Xuan  * @param wait_to_complete
8872c473729SZiyang Xuan  *   Wait for request completion.
8882c473729SZiyang Xuan  *
8892c473729SZiyang Xuan  * @return
8902c473729SZiyang Xuan  *   0 link status changed, -1 link status not changed
8912c473729SZiyang Xuan  */
8922c473729SZiyang Xuan static int hinic_link_update(struct rte_eth_dev *dev, int wait_to_complete)
8932c473729SZiyang Xuan {
8942c473729SZiyang Xuan #define CHECK_INTERVAL 10  /* 10ms */
8952c473729SZiyang Xuan #define MAX_REPEAT_TIME 100  /* 1s (100 * 10ms) in total */
8962c473729SZiyang Xuan 	int rc = HINIC_OK;
8972c473729SZiyang Xuan 	struct rte_eth_link link;
8982c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
8992c473729SZiyang Xuan 	unsigned int rep_cnt = MAX_REPEAT_TIME;
9002c473729SZiyang Xuan 
9012c473729SZiyang Xuan 	memset(&link, 0, sizeof(link));
9022c473729SZiyang Xuan 	do {
9032c473729SZiyang Xuan 		/* Get link status information from hardware */
9042c473729SZiyang Xuan 		rc = hinic_priv_get_dev_link_status(nic_dev, &link);
9052c473729SZiyang Xuan 		if (rc != HINIC_OK) {
906295968d1SFerruh Yigit 			link.link_speed = RTE_ETH_SPEED_NUM_NONE;
907295968d1SFerruh Yigit 			link.link_duplex = RTE_ETH_LINK_FULL_DUPLEX;
9082c473729SZiyang Xuan 			PMD_DRV_LOG(ERR, "Get link status failed");
9092c473729SZiyang Xuan 			goto out;
9102c473729SZiyang Xuan 		}
9112c473729SZiyang Xuan 
9122c473729SZiyang Xuan 		if (!wait_to_complete || link.link_status)
9132c473729SZiyang Xuan 			break;
9142c473729SZiyang Xuan 
9152c473729SZiyang Xuan 		rte_delay_ms(CHECK_INTERVAL);
9162c473729SZiyang Xuan 	} while (rep_cnt--);
9172c473729SZiyang Xuan 
9182c473729SZiyang Xuan out:
9192c473729SZiyang Xuan 	rc = rte_eth_linkstatus_set(dev, &link);
9202c473729SZiyang Xuan 	return rc;
9212c473729SZiyang Xuan }
9222c473729SZiyang Xuan 
9232c473729SZiyang Xuan /**
92454ac3386SXiaoyun Wang  * DPDK callback to bring the link UP.
92554ac3386SXiaoyun Wang  *
92654ac3386SXiaoyun Wang  * @param dev
92754ac3386SXiaoyun Wang  *   Pointer to Ethernet device structure.
92854ac3386SXiaoyun Wang  *
92954ac3386SXiaoyun Wang  * @return
93054ac3386SXiaoyun Wang  *   0 on success, negative errno value on failure.
93154ac3386SXiaoyun Wang  */
93254ac3386SXiaoyun Wang static int hinic_dev_set_link_up(struct rte_eth_dev *dev)
93354ac3386SXiaoyun Wang {
93454ac3386SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
93554ac3386SXiaoyun Wang 	int ret;
93654ac3386SXiaoyun Wang 
93754ac3386SXiaoyun Wang 	/* link status follow phy port status, up will open pma */
93854ac3386SXiaoyun Wang 	ret = hinic_set_port_enable(nic_dev->hwdev, true);
93954ac3386SXiaoyun Wang 	if (ret)
94054ac3386SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set mac link up failed, dev_name: %s, port_id: %d",
94154ac3386SXiaoyun Wang 			    nic_dev->proc_dev_name, dev->data->port_id);
94254ac3386SXiaoyun Wang 
94354ac3386SXiaoyun Wang 	return ret;
94454ac3386SXiaoyun Wang }
94554ac3386SXiaoyun Wang 
94654ac3386SXiaoyun Wang /**
94754ac3386SXiaoyun Wang  * DPDK callback to bring the link DOWN.
94854ac3386SXiaoyun Wang  *
94954ac3386SXiaoyun Wang  * @param dev
95054ac3386SXiaoyun Wang  *   Pointer to Ethernet device structure.
95154ac3386SXiaoyun Wang  *
95254ac3386SXiaoyun Wang  * @return
95354ac3386SXiaoyun Wang  *   0 on success, negative errno value on failure.
95454ac3386SXiaoyun Wang  */
95554ac3386SXiaoyun Wang static int hinic_dev_set_link_down(struct rte_eth_dev *dev)
95654ac3386SXiaoyun Wang {
95754ac3386SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
95854ac3386SXiaoyun Wang 	int ret;
95954ac3386SXiaoyun Wang 
96054ac3386SXiaoyun Wang 	/* link status follow phy port status, up will close pma */
96154ac3386SXiaoyun Wang 	ret = hinic_set_port_enable(nic_dev->hwdev, false);
96254ac3386SXiaoyun Wang 	if (ret)
96354ac3386SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set mac link down failed, dev_name: %s, port_id: %d",
96454ac3386SXiaoyun Wang 			    nic_dev->proc_dev_name, dev->data->port_id);
96554ac3386SXiaoyun Wang 
96654ac3386SXiaoyun Wang 	return ret;
96754ac3386SXiaoyun Wang }
96854ac3386SXiaoyun Wang 
96954ac3386SXiaoyun Wang /**
9702c473729SZiyang Xuan  * DPDK callback to start the device.
9712c473729SZiyang Xuan  *
9722c473729SZiyang Xuan  * @param dev
9732c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
9742c473729SZiyang Xuan  *
9752c473729SZiyang Xuan  * @return
9762c473729SZiyang Xuan  *   0 on success, negative errno value on failure.
9772c473729SZiyang Xuan  */
9782c473729SZiyang Xuan static int hinic_dev_start(struct rte_eth_dev *dev)
9792c473729SZiyang Xuan {
9802c473729SZiyang Xuan 	int rc;
9812c473729SZiyang Xuan 	char *name;
9822c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
983b0f9c8e2SJie Hai 	uint16_t i;
9842c473729SZiyang Xuan 
9852c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
9862c473729SZiyang Xuan 	name = dev->data->name;
9872c473729SZiyang Xuan 
9882c473729SZiyang Xuan 	/* reset rx and tx queue */
9892c473729SZiyang Xuan 	hinic_reset_rx_queue(dev);
9902c473729SZiyang Xuan 	hinic_reset_tx_queue(dev);
9912c473729SZiyang Xuan 
9922c473729SZiyang Xuan 	/* get func rx buf size */
9932c473729SZiyang Xuan 	hinic_get_func_rx_buf_size(nic_dev);
9942c473729SZiyang Xuan 
9952c473729SZiyang Xuan 	/* init txq and rxq context */
9962c473729SZiyang Xuan 	rc = hinic_init_qp_ctxts(nic_dev->hwdev);
9972c473729SZiyang Xuan 	if (rc) {
9982c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize qp context failed, dev_name: %s",
9992c473729SZiyang Xuan 			    name);
10002c473729SZiyang Xuan 		goto init_qp_fail;
10012c473729SZiyang Xuan 	}
10022c473729SZiyang Xuan 
10032c473729SZiyang Xuan 	/* rss template */
10042c473729SZiyang Xuan 	rc = hinic_config_mq_mode(dev, TRUE);
10052c473729SZiyang Xuan 	if (rc) {
10062c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure mq mode failed, dev_name: %s",
10072c473729SZiyang Xuan 			    name);
10082c473729SZiyang Xuan 		goto cfg_mq_mode_fail;
10092c473729SZiyang Xuan 	}
10102c473729SZiyang Xuan 
10112c473729SZiyang Xuan 	/* set default mtu */
10122c473729SZiyang Xuan 	rc = hinic_set_port_mtu(nic_dev->hwdev, nic_dev->mtu_size);
10132c473729SZiyang Xuan 	if (rc) {
10142c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Set mtu_size[%d] failed, dev_name: %s",
10152c473729SZiyang Xuan 			    nic_dev->mtu_size, name);
10162c473729SZiyang Xuan 		goto set_mtu_fail;
10172c473729SZiyang Xuan 	}
10182c473729SZiyang Xuan 
10192c473729SZiyang Xuan 	/* configure rss rx_mode and other rx or tx default feature */
10202c473729SZiyang Xuan 	rc = hinic_rxtx_configure(dev);
10212c473729SZiyang Xuan 	if (rc) {
10222c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Configure tx and rx failed, dev_name: %s",
10232c473729SZiyang Xuan 			    name);
10242c473729SZiyang Xuan 		goto cfg_rxtx_fail;
10252c473729SZiyang Xuan 	}
10262c473729SZiyang Xuan 
10276691acefSXiaoyun Wang 	/* reactive pf status, so that uP report asyn event */
10286691acefSXiaoyun Wang 	hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_ACTIVE_FLAG);
10296691acefSXiaoyun Wang 
10302c473729SZiyang Xuan 	/* open virtual port and ready to start packet receiving */
10312c473729SZiyang Xuan 	rc = hinic_set_vport_enable(nic_dev->hwdev, true);
10322c473729SZiyang Xuan 	if (rc) {
10332c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Enable vport failed, dev_name:%s", name);
10342c473729SZiyang Xuan 		goto en_vport_fail;
10352c473729SZiyang Xuan 	}
10362c473729SZiyang Xuan 
10372c473729SZiyang Xuan 	/* open physical port and start packet receiving */
10382c473729SZiyang Xuan 	rc = hinic_set_port_enable(nic_dev->hwdev, true);
10392c473729SZiyang Xuan 	if (rc) {
10402c473729SZiyang Xuan 		PMD_DRV_LOG(ERR, "Enable physical port failed, dev_name: %s",
10412c473729SZiyang Xuan 			    name);
10422c473729SZiyang Xuan 		goto en_port_fail;
10432c473729SZiyang Xuan 	}
10442c473729SZiyang Xuan 
10452c473729SZiyang Xuan 	/* update eth_dev link status */
10462c473729SZiyang Xuan 	if (dev->data->dev_conf.intr_conf.lsc != 0)
10472c473729SZiyang Xuan 		(void)hinic_link_update(dev, 0);
10482c473729SZiyang Xuan 
10490371535dSJoyce Kong 	rte_bit_relaxed_set32(HINIC_DEV_START, &nic_dev->dev_status);
10502c473729SZiyang Xuan 
1051b0f9c8e2SJie Hai 	for (i = 0; i < dev->data->nb_rx_queues; i++)
1052b0f9c8e2SJie Hai 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
1053b0f9c8e2SJie Hai 	for (i = 0; i < dev->data->nb_tx_queues; i++)
1054b0f9c8e2SJie Hai 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STARTED;
1055b0f9c8e2SJie Hai 
10562c473729SZiyang Xuan 	return 0;
10572c473729SZiyang Xuan 
10582c473729SZiyang Xuan en_port_fail:
10592c473729SZiyang Xuan 	(void)hinic_set_vport_enable(nic_dev->hwdev, false);
10602c473729SZiyang Xuan 
10612c473729SZiyang Xuan en_vport_fail:
10626691acefSXiaoyun Wang 	hinic_set_pf_status(nic_dev->hwdev->hwif, HINIC_PF_STATUS_INIT);
10636691acefSXiaoyun Wang 
10642c473729SZiyang Xuan 	/* Flush tx && rx chip resources in case of set vport fake fail */
10652c473729SZiyang Xuan 	(void)hinic_flush_qp_res(nic_dev->hwdev);
10662c473729SZiyang Xuan 	rte_delay_ms(100);
10672c473729SZiyang Xuan 
10682c473729SZiyang Xuan 	hinic_remove_rxtx_configure(dev);
10692c473729SZiyang Xuan 
10702c473729SZiyang Xuan cfg_rxtx_fail:
10712c473729SZiyang Xuan set_mtu_fail:
10722c473729SZiyang Xuan cfg_mq_mode_fail:
10732c473729SZiyang Xuan 	hinic_free_qp_ctxts(nic_dev->hwdev);
10742c473729SZiyang Xuan 
10752c473729SZiyang Xuan init_qp_fail:
10762c473729SZiyang Xuan 	hinic_free_all_rx_mbuf(dev);
10772c473729SZiyang Xuan 	hinic_free_all_tx_mbuf(dev);
10782c473729SZiyang Xuan 
10792c473729SZiyang Xuan 	return rc;
10802c473729SZiyang Xuan }
10812c473729SZiyang Xuan 
10822c473729SZiyang Xuan /**
10832c473729SZiyang Xuan  * DPDK callback to release the receive queue.
10842c473729SZiyang Xuan  *
10857483341aSXueming Li  * @param dev
10867483341aSXueming Li  *   Pointer to Ethernet device structure.
10877483341aSXueming Li  * @param qid
10887483341aSXueming Li  *   Receive queue index.
10892c473729SZiyang Xuan  */
10907483341aSXueming Li static void hinic_rx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
10912c473729SZiyang Xuan {
10927483341aSXueming Li 	struct hinic_rxq *rxq = dev->data->rx_queues[qid];
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  *
11197483341aSXueming Li  * @param dev
11207483341aSXueming Li  *   Pointer to Ethernet device structure.
11217483341aSXueming Li  * @param qid
11227483341aSXueming Li  *   Transmit queue index.
11232c473729SZiyang Xuan  */
11247483341aSXueming Li static void hinic_tx_queue_release(struct rte_eth_dev *dev, uint16_t qid)
11252c473729SZiyang Xuan {
11267483341aSXueming Li 	struct hinic_txq *txq = dev->data->tx_queues[qid];
11272c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
11282c473729SZiyang Xuan 
11292c473729SZiyang Xuan 	if (!txq) {
11302c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Txq is null when release");
11312c473729SZiyang Xuan 		return;
11322c473729SZiyang Xuan 	}
11332c473729SZiyang Xuan 	nic_dev = txq->nic_dev;
11342c473729SZiyang Xuan 
11352c473729SZiyang Xuan 	/* free txq_pkt mbuf */
1136c3ba1f0fSXiaoyun Wang 	hinic_free_all_tx_mbufs(txq);
11372c473729SZiyang Xuan 
11382c473729SZiyang Xuan 	/* free txq_info */
11392c473729SZiyang Xuan 	hinic_free_tx_resources(txq);
11402c473729SZiyang Xuan 
11412c473729SZiyang Xuan 	/* free root sq wq */
11422c473729SZiyang Xuan 	hinic_destroy_sq(nic_dev->hwdev, txq->q_id);
11432c473729SZiyang Xuan 	nic_dev->txqs[txq->q_id] = NULL;
11442c473729SZiyang Xuan 
11452c473729SZiyang Xuan 	/* free txq */
11462c473729SZiyang Xuan 	rte_free(txq);
11472c473729SZiyang Xuan }
11482c473729SZiyang Xuan 
114964727024SZiyang Xuan static void hinic_free_all_rq(struct hinic_nic_dev *nic_dev)
11501d09792aSZiyang Xuan {
115164727024SZiyang Xuan 	u16 q_id;
115264727024SZiyang Xuan 
115364727024SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_rq; q_id++)
115464727024SZiyang Xuan 		hinic_destroy_rq(nic_dev->hwdev, q_id);
115564727024SZiyang Xuan }
115664727024SZiyang Xuan 
115764727024SZiyang Xuan static void hinic_free_all_sq(struct hinic_nic_dev *nic_dev)
115864727024SZiyang Xuan {
115964727024SZiyang Xuan 	u16 q_id;
116064727024SZiyang Xuan 
116164727024SZiyang Xuan 	for (q_id = 0; q_id < nic_dev->num_sq; q_id++)
116264727024SZiyang Xuan 		hinic_destroy_sq(nic_dev->hwdev, q_id);
116364727024SZiyang Xuan }
116464727024SZiyang Xuan 
11652c473729SZiyang Xuan /**
11662c473729SZiyang Xuan  * DPDK callback to stop the device.
11672c473729SZiyang Xuan  *
11682c473729SZiyang Xuan  * @param dev
11692c473729SZiyang Xuan  *   Pointer to Ethernet device structure.
11702c473729SZiyang Xuan  */
117162024eb8SIvan Ilchenko static int hinic_dev_stop(struct rte_eth_dev *dev)
11722c473729SZiyang Xuan {
11732c473729SZiyang Xuan 	int rc;
11742c473729SZiyang Xuan 	char *name;
11752c473729SZiyang Xuan 	uint16_t port_id;
11762c473729SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
11772c473729SZiyang Xuan 	struct rte_eth_link link;
1178b0f9c8e2SJie Hai 	uint16_t i;
11792c473729SZiyang Xuan 
11802c473729SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
11812c473729SZiyang Xuan 	name = dev->data->name;
11822c473729SZiyang Xuan 	port_id = dev->data->port_id;
11832c473729SZiyang Xuan 
1184b8f5d2aeSThomas Monjalon 	dev->data->dev_started = 0;
1185b8f5d2aeSThomas Monjalon 
11860371535dSJoyce Kong 	if (!rte_bit_relaxed_test_and_clear32(HINIC_DEV_START,
11870371535dSJoyce Kong 					      &nic_dev->dev_status)) {
11882c473729SZiyang Xuan 		PMD_DRV_LOG(INFO, "Device %s already stopped", name);
118962024eb8SIvan Ilchenko 		return 0;
11902c473729SZiyang Xuan 	}
11912c473729SZiyang Xuan 
11922c473729SZiyang Xuan 	/* just stop phy port and vport */
11932c473729SZiyang Xuan 	rc = hinic_set_port_enable(nic_dev->hwdev, false);
11942c473729SZiyang Xuan 	if (rc)
11952c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Disable phy port failed, error: %d, dev_name: %s, port_id: %d",
11962c473729SZiyang Xuan 			  rc, name, port_id);
11972c473729SZiyang Xuan 
11982c473729SZiyang Xuan 	rc = hinic_set_vport_enable(nic_dev->hwdev, false);
11992c473729SZiyang Xuan 	if (rc)
12002c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Disable vport failed, error: %d, dev_name: %s, port_id: %d",
12012c473729SZiyang Xuan 			  rc, name, port_id);
12022c473729SZiyang Xuan 
12032c473729SZiyang Xuan 	/* Clear recorded link status */
12042c473729SZiyang Xuan 	memset(&link, 0, sizeof(link));
12052c473729SZiyang Xuan 	(void)rte_eth_linkstatus_set(dev, &link);
12062c473729SZiyang Xuan 
12072c473729SZiyang Xuan 	/* flush pending io request */
12082c473729SZiyang Xuan 	rc = hinic_rx_tx_flush(nic_dev->hwdev);
12092c473729SZiyang Xuan 	if (rc)
12102c473729SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Flush pending io failed, error: %d, dev_name: %s, port_id: %d",
12112c473729SZiyang Xuan 			    rc, name, port_id);
12122c473729SZiyang Xuan 
12132c473729SZiyang Xuan 	/* clean rss table and rx_mode */
12142c473729SZiyang Xuan 	hinic_remove_rxtx_configure(dev);
12152c473729SZiyang Xuan 
12162c473729SZiyang Xuan 	/* clean root context */
12172c473729SZiyang Xuan 	hinic_free_qp_ctxts(nic_dev->hwdev);
12182c473729SZiyang Xuan 
12191fe89aa3SXiaoyun Wang 	hinic_destroy_fdir_filter(dev);
12201742421bSXiaoyun Wang 
12212c473729SZiyang Xuan 	/* free mbuf */
12222c473729SZiyang Xuan 	hinic_free_all_rx_mbuf(dev);
12232c473729SZiyang Xuan 	hinic_free_all_tx_mbuf(dev);
122462024eb8SIvan Ilchenko 
1225b0f9c8e2SJie Hai 	for (i = 0; i < dev->data->nb_rx_queues; i++)
1226b0f9c8e2SJie Hai 		dev->data->rx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1227b0f9c8e2SJie Hai 	for (i = 0; i < dev->data->nb_tx_queues; i++)
1228b0f9c8e2SJie Hai 		dev->data->tx_queue_state[i] = RTE_ETH_QUEUE_STATE_STOPPED;
1229b0f9c8e2SJie Hai 
123062024eb8SIvan Ilchenko 	return 0;
12312c473729SZiyang Xuan }
12322c473729SZiyang Xuan 
123364727024SZiyang Xuan static void hinic_disable_interrupt(struct rte_eth_dev *dev)
123464727024SZiyang Xuan {
123564727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
123664727024SZiyang Xuan 	struct rte_pci_device *pci_dev = RTE_ETH_DEV_TO_PCI(dev);
123764727024SZiyang Xuan 	int ret, retries = 0;
123864727024SZiyang Xuan 
12390371535dSJoyce Kong 	rte_bit_relaxed_clear32(HINIC_DEV_INTR_EN, &nic_dev->dev_status);
124064727024SZiyang Xuan 
124164727024SZiyang Xuan 	/* disable msix interrupt in hardware */
124264727024SZiyang Xuan 	hinic_set_msix_state(nic_dev->hwdev, 0, HINIC_MSIX_DISABLE);
124364727024SZiyang Xuan 
124464727024SZiyang Xuan 	/* disable rte interrupt */
1245d61138d4SHarman Kalra 	ret = rte_intr_disable(pci_dev->intr_handle);
124664727024SZiyang Xuan 	if (ret)
124764727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Disable intr failed: %d", ret);
124864727024SZiyang Xuan 
124964727024SZiyang Xuan 	do {
125064727024SZiyang Xuan 		ret =
1251d61138d4SHarman Kalra 		rte_intr_callback_unregister(pci_dev->intr_handle,
125264727024SZiyang Xuan 					     hinic_dev_interrupt_handler, dev);
125364727024SZiyang Xuan 		if (ret >= 0) {
125464727024SZiyang Xuan 			break;
125564727024SZiyang Xuan 		} else if (ret == -EAGAIN) {
125664727024SZiyang Xuan 			rte_delay_ms(100);
125764727024SZiyang Xuan 			retries++;
125864727024SZiyang Xuan 		} else {
125964727024SZiyang Xuan 			PMD_DRV_LOG(ERR, "intr callback unregister failed: %d",
126064727024SZiyang Xuan 				    ret);
126164727024SZiyang Xuan 			break;
126264727024SZiyang Xuan 		}
126364727024SZiyang Xuan 	} while (retries < HINIC_INTR_CB_UNREG_MAX_RETRIES);
126464727024SZiyang Xuan 
126564727024SZiyang Xuan 	if (retries == HINIC_INTR_CB_UNREG_MAX_RETRIES)
126664727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Unregister intr callback failed after %d retries",
126764727024SZiyang Xuan 			    retries);
1268511b7371SGuoyang Zhou 
1269511b7371SGuoyang Zhou 	rte_bit_relaxed_clear32(HINIC_DEV_INIT, &nic_dev->dev_status);
127064727024SZiyang Xuan }
127164727024SZiyang Xuan 
1272cb7b6606SZiyang Xuan static int hinic_set_dev_promiscuous(struct hinic_nic_dev *nic_dev, bool enable)
1273cb7b6606SZiyang Xuan {
1274224cff4bSXiaoyun Wang 	u32 rx_mode_ctrl;
1275224cff4bSXiaoyun Wang 	int err;
1276224cff4bSXiaoyun Wang 
1277224cff4bSXiaoyun Wang 	err = hinic_mutex_lock(&nic_dev->rx_mode_mutex);
1278224cff4bSXiaoyun Wang 	if (err)
1279224cff4bSXiaoyun Wang 		return err;
1280224cff4bSXiaoyun Wang 
1281224cff4bSXiaoyun Wang 	rx_mode_ctrl = nic_dev->rx_mode_status;
1282cb7b6606SZiyang Xuan 
1283cb7b6606SZiyang Xuan 	if (enable)
1284cb7b6606SZiyang Xuan 		rx_mode_ctrl |= HINIC_RX_MODE_PROMISC;
1285cb7b6606SZiyang Xuan 	else
1286cb7b6606SZiyang Xuan 		rx_mode_ctrl &= (~HINIC_RX_MODE_PROMISC);
1287cb7b6606SZiyang Xuan 
1288224cff4bSXiaoyun Wang 	err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
1289224cff4bSXiaoyun Wang 
1290224cff4bSXiaoyun Wang 	(void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex);
1291224cff4bSXiaoyun Wang 
1292224cff4bSXiaoyun Wang 	return err;
1293cb7b6606SZiyang Xuan }
1294cb7b6606SZiyang Xuan 
1295cb7b6606SZiyang Xuan /**
1296cb7b6606SZiyang Xuan  * DPDK callback to get device statistics.
1297cb7b6606SZiyang Xuan  *
1298cb7b6606SZiyang Xuan  * @param dev
1299cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
1300cb7b6606SZiyang Xuan  * @param stats
1301cb7b6606SZiyang Xuan  *   Stats structure output buffer.
1302cb7b6606SZiyang Xuan  *
1303cb7b6606SZiyang Xuan  * @return
1304cb7b6606SZiyang Xuan  *   0 on success and stats is filled,
1305cb7b6606SZiyang Xuan  *   negative error value otherwise.
1306cb7b6606SZiyang Xuan  */
1307cb7b6606SZiyang Xuan static int
1308cb7b6606SZiyang Xuan hinic_dev_stats_get(struct rte_eth_dev *dev, struct rte_eth_stats *stats)
1309cb7b6606SZiyang Xuan {
1310cb7b6606SZiyang Xuan 	int i, err, q_num;
1311cb7b6606SZiyang Xuan 	u64 rx_discards_pmd = 0;
1312cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1313cb7b6606SZiyang Xuan 	struct hinic_vport_stats vport_stats;
1314cb7b6606SZiyang Xuan 	struct hinic_rxq	*rxq = NULL;
1315cb7b6606SZiyang Xuan 	struct hinic_rxq_stats rxq_stats;
1316cb7b6606SZiyang Xuan 	struct hinic_txq	*txq = NULL;
1317cb7b6606SZiyang Xuan 	struct hinic_txq_stats txq_stats;
1318cb7b6606SZiyang Xuan 
1319cb7b6606SZiyang Xuan 	err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats);
1320cb7b6606SZiyang Xuan 	if (err) {
1321cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Get vport stats from fw failed, nic_dev: %s",
1322cb7b6606SZiyang Xuan 			nic_dev->proc_dev_name);
1323cb7b6606SZiyang Xuan 		return err;
1324cb7b6606SZiyang Xuan 	}
1325cb7b6606SZiyang Xuan 
13263930d9ceSXiaoyun Wang 	dev->data->rx_mbuf_alloc_failed = 0;
13273930d9ceSXiaoyun Wang 
1328cb7b6606SZiyang Xuan 	/* rx queue stats */
1329cb7b6606SZiyang Xuan 	q_num = (nic_dev->num_rq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
1330cb7b6606SZiyang Xuan 			nic_dev->num_rq : RTE_ETHDEV_QUEUE_STAT_CNTRS;
1331cb7b6606SZiyang Xuan 	for (i = 0; i < q_num; i++) {
1332cb7b6606SZiyang Xuan 		rxq = nic_dev->rxqs[i];
1333cb7b6606SZiyang Xuan 		hinic_rxq_get_stats(rxq, &rxq_stats);
1334cb7b6606SZiyang Xuan 		stats->q_ipackets[i] = rxq_stats.packets;
1335cb7b6606SZiyang Xuan 		stats->q_ibytes[i] = rxq_stats.bytes;
1336cb7b6606SZiyang Xuan 		stats->q_errors[i] = rxq_stats.rx_discards;
1337cb7b6606SZiyang Xuan 
1338cb7b6606SZiyang Xuan 		stats->ierrors += rxq_stats.errors;
1339cb7b6606SZiyang Xuan 		rx_discards_pmd += rxq_stats.rx_discards;
1340cb7b6606SZiyang Xuan 		dev->data->rx_mbuf_alloc_failed += rxq_stats.rx_nombuf;
1341cb7b6606SZiyang Xuan 	}
1342cb7b6606SZiyang Xuan 
1343cb7b6606SZiyang Xuan 	/* tx queue stats */
1344cb7b6606SZiyang Xuan 	q_num = (nic_dev->num_sq < RTE_ETHDEV_QUEUE_STAT_CNTRS) ?
1345cb7b6606SZiyang Xuan 		nic_dev->num_sq : RTE_ETHDEV_QUEUE_STAT_CNTRS;
1346cb7b6606SZiyang Xuan 	for (i = 0; i < q_num; i++) {
1347cb7b6606SZiyang Xuan 		txq = nic_dev->txqs[i];
1348cb7b6606SZiyang Xuan 		hinic_txq_get_stats(txq, &txq_stats);
1349cb7b6606SZiyang Xuan 		stats->q_opackets[i] = txq_stats.packets;
1350cb7b6606SZiyang Xuan 		stats->q_obytes[i] = txq_stats.bytes;
1351cb7b6606SZiyang Xuan 		stats->oerrors += (txq_stats.tx_busy + txq_stats.off_errs);
1352cb7b6606SZiyang Xuan 	}
1353cb7b6606SZiyang Xuan 
1354cb7b6606SZiyang Xuan 	/* vport stats */
1355cb7b6606SZiyang Xuan 	stats->oerrors += vport_stats.tx_discard_vport;
1356cb7b6606SZiyang Xuan 
1357cb7b6606SZiyang Xuan 	stats->imissed = vport_stats.rx_discard_vport + rx_discards_pmd;
1358cb7b6606SZiyang Xuan 
1359cb7b6606SZiyang Xuan 	stats->ipackets = (vport_stats.rx_unicast_pkts_vport +
1360cb7b6606SZiyang Xuan 			vport_stats.rx_multicast_pkts_vport +
1361cb7b6606SZiyang Xuan 			vport_stats.rx_broadcast_pkts_vport -
1362cb7b6606SZiyang Xuan 			rx_discards_pmd);
1363cb7b6606SZiyang Xuan 
1364cb7b6606SZiyang Xuan 	stats->opackets = (vport_stats.tx_unicast_pkts_vport +
1365cb7b6606SZiyang Xuan 			vport_stats.tx_multicast_pkts_vport +
1366cb7b6606SZiyang Xuan 			vport_stats.tx_broadcast_pkts_vport);
1367cb7b6606SZiyang Xuan 
1368cb7b6606SZiyang Xuan 	stats->ibytes = (vport_stats.rx_unicast_bytes_vport +
1369cb7b6606SZiyang Xuan 			vport_stats.rx_multicast_bytes_vport +
1370cb7b6606SZiyang Xuan 			vport_stats.rx_broadcast_bytes_vport);
1371cb7b6606SZiyang Xuan 
1372cb7b6606SZiyang Xuan 	stats->obytes = (vport_stats.tx_unicast_bytes_vport +
1373cb7b6606SZiyang Xuan 			vport_stats.tx_multicast_bytes_vport +
1374cb7b6606SZiyang Xuan 			vport_stats.tx_broadcast_bytes_vport);
1375cb7b6606SZiyang Xuan 	return 0;
1376cb7b6606SZiyang Xuan }
1377cb7b6606SZiyang Xuan 
1378cb7b6606SZiyang Xuan /**
1379cb7b6606SZiyang Xuan  * DPDK callback to clear device statistics.
1380cb7b6606SZiyang Xuan  *
1381cb7b6606SZiyang Xuan  * @param dev
1382cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
1383cb7b6606SZiyang Xuan  */
13849970a9adSIgor Romanov static int hinic_dev_stats_reset(struct rte_eth_dev *dev)
1385cb7b6606SZiyang Xuan {
1386cb7b6606SZiyang Xuan 	int qid;
1387cb7b6606SZiyang Xuan 	struct hinic_rxq	*rxq = NULL;
1388cb7b6606SZiyang Xuan 	struct hinic_txq	*txq = NULL;
1389cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
13909970a9adSIgor Romanov 	int ret;
1391cb7b6606SZiyang Xuan 
13929970a9adSIgor Romanov 	ret = hinic_clear_vport_stats(nic_dev->hwdev);
13939970a9adSIgor Romanov 	if (ret != 0)
13949970a9adSIgor Romanov 		return ret;
1395cb7b6606SZiyang Xuan 
1396cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_rq; qid++) {
1397cb7b6606SZiyang Xuan 		rxq = nic_dev->rxqs[qid];
1398cb7b6606SZiyang Xuan 		hinic_rxq_stats_reset(rxq);
1399cb7b6606SZiyang Xuan 	}
1400cb7b6606SZiyang Xuan 
1401cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_sq; qid++) {
1402cb7b6606SZiyang Xuan 		txq = nic_dev->txqs[qid];
1403cb7b6606SZiyang Xuan 		hinic_txq_stats_reset(txq);
1404cb7b6606SZiyang Xuan 	}
14059970a9adSIgor Romanov 
14069970a9adSIgor Romanov 	return 0;
1407cb7b6606SZiyang Xuan }
1408cb7b6606SZiyang Xuan 
1409cb7b6606SZiyang Xuan /**
1410cb7b6606SZiyang Xuan  * DPDK callback to clear device extended statistics.
1411cb7b6606SZiyang Xuan  *
1412cb7b6606SZiyang Xuan  * @param dev
1413cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
14146691acefSXiaoyun Wang  */
14159970a9adSIgor Romanov static int hinic_dev_xstats_reset(struct rte_eth_dev *dev)
1416cb7b6606SZiyang Xuan {
1417cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
14189970a9adSIgor Romanov 	int ret;
1419cb7b6606SZiyang Xuan 
14209970a9adSIgor Romanov 	ret = hinic_dev_stats_reset(dev);
14219970a9adSIgor Romanov 	if (ret != 0)
14229970a9adSIgor Romanov 		return ret;
1423cb7b6606SZiyang Xuan 
14249970a9adSIgor Romanov 	if (hinic_func_type(nic_dev->hwdev) != TYPE_VF) {
14259970a9adSIgor Romanov 		ret = hinic_clear_phy_port_stats(nic_dev->hwdev);
14269970a9adSIgor Romanov 		if (ret != 0)
14279970a9adSIgor Romanov 			return ret;
14289970a9adSIgor Romanov 	}
14299970a9adSIgor Romanov 
14309970a9adSIgor Romanov 	return 0;
1431cb7b6606SZiyang Xuan }
1432cb7b6606SZiyang Xuan 
14332c473729SZiyang Xuan static void hinic_gen_random_mac_addr(struct rte_ether_addr *mac_addr)
14342c473729SZiyang Xuan {
14352c473729SZiyang Xuan 	uint64_t random_value;
14362c473729SZiyang Xuan 
14372c473729SZiyang Xuan 	/* Set Organizationally Unique Identifier (OUI) prefix */
14382c473729SZiyang Xuan 	mac_addr->addr_bytes[0] = 0x00;
14392c473729SZiyang Xuan 	mac_addr->addr_bytes[1] = 0x09;
14402c473729SZiyang Xuan 	mac_addr->addr_bytes[2] = 0xC0;
14412c473729SZiyang Xuan 	/* Force indication of locally assigned MAC address. */
14422c473729SZiyang Xuan 	mac_addr->addr_bytes[0] |= RTE_ETHER_LOCAL_ADMIN_ADDR;
14432c473729SZiyang Xuan 	/* Generate the last 3 bytes of the MAC address with a random number. */
14442c473729SZiyang Xuan 	random_value = rte_rand();
14452c473729SZiyang Xuan 	memcpy(&mac_addr->addr_bytes[3], &random_value, 3);
14462c473729SZiyang Xuan }
14472c473729SZiyang Xuan 
144864727024SZiyang Xuan /**
144964727024SZiyang Xuan  * Init mac_vlan table in NIC.
145064727024SZiyang Xuan  *
145164727024SZiyang Xuan  * @param dev
145264727024SZiyang Xuan  *   Pointer to Ethernet device structure.
145364727024SZiyang Xuan  *
145464727024SZiyang Xuan  * @return
145564727024SZiyang Xuan  *   0 on success and stats is filled,
145664727024SZiyang Xuan  *   negative error value otherwise.
145764727024SZiyang Xuan  */
145864727024SZiyang Xuan static int hinic_init_mac_addr(struct rte_eth_dev *eth_dev)
145964727024SZiyang Xuan {
146064727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
146164727024SZiyang Xuan 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
146264727024SZiyang Xuan 	uint8_t addr_bytes[RTE_ETHER_ADDR_LEN];
146364727024SZiyang Xuan 	u16 func_id = 0;
146464727024SZiyang Xuan 	int rc = 0;
146564727024SZiyang Xuan 
146664727024SZiyang Xuan 	rc = hinic_get_default_mac(nic_dev->hwdev, addr_bytes);
146764727024SZiyang Xuan 	if (rc)
146864727024SZiyang Xuan 		return rc;
146964727024SZiyang Xuan 
147000499a22SXiaoyun Wang 	rte_ether_addr_copy((struct rte_ether_addr *)addr_bytes,
147100499a22SXiaoyun Wang 		&eth_dev->data->mac_addrs[0]);
147200499a22SXiaoyun Wang 	if (rte_is_zero_ether_addr(&eth_dev->data->mac_addrs[0]))
147300499a22SXiaoyun Wang 		hinic_gen_random_mac_addr(&eth_dev->data->mac_addrs[0]);
14742c473729SZiyang Xuan 
147564727024SZiyang Xuan 	func_id = hinic_global_func_id(nic_dev->hwdev);
147600499a22SXiaoyun Wang 	rc = hinic_set_mac(nic_dev->hwdev,
147700499a22SXiaoyun Wang 			eth_dev->data->mac_addrs[0].addr_bytes,
147864727024SZiyang Xuan 			0, func_id);
147964727024SZiyang Xuan 	if (rc && rc != HINIC_PF_SET_VF_ALREADY)
148064727024SZiyang Xuan 		return rc;
148164727024SZiyang Xuan 
148200499a22SXiaoyun Wang 	rte_ether_addr_copy(&eth_dev->data->mac_addrs[0],
148300499a22SXiaoyun Wang 			&nic_dev->default_addr);
148400499a22SXiaoyun Wang 
14851d09792aSZiyang Xuan 	return 0;
14861d09792aSZiyang Xuan }
14871d09792aSZiyang Xuan 
148800499a22SXiaoyun Wang static void hinic_delete_mc_addr_list(struct hinic_nic_dev *nic_dev)
148900499a22SXiaoyun Wang {
149000499a22SXiaoyun Wang 	u16 func_id;
149100499a22SXiaoyun Wang 	u32 i;
149200499a22SXiaoyun Wang 
149300499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
149400499a22SXiaoyun Wang 
149500499a22SXiaoyun Wang 	for (i = 0; i < HINIC_MAX_MC_MAC_ADDRS; i++) {
149600499a22SXiaoyun Wang 		if (rte_is_zero_ether_addr(&nic_dev->mc_list[i]))
149700499a22SXiaoyun Wang 			break;
149800499a22SXiaoyun Wang 
149900499a22SXiaoyun Wang 		hinic_del_mac(nic_dev->hwdev, nic_dev->mc_list[i].addr_bytes,
150000499a22SXiaoyun Wang 			      0, func_id);
150100499a22SXiaoyun Wang 		memset(&nic_dev->mc_list[i], 0, sizeof(struct rte_ether_addr));
150200499a22SXiaoyun Wang 	}
150300499a22SXiaoyun Wang }
150400499a22SXiaoyun Wang 
15051d09792aSZiyang Xuan /**
150664727024SZiyang Xuan  * Deinit mac_vlan table in NIC.
150764727024SZiyang Xuan  *
150864727024SZiyang Xuan  * @param dev
150964727024SZiyang Xuan  *   Pointer to Ethernet device structure.
151064727024SZiyang Xuan  *
151164727024SZiyang Xuan  * @return
151264727024SZiyang Xuan  *   0 on success and stats is filled,
151364727024SZiyang Xuan  *   negative error value otherwise.
151464727024SZiyang Xuan  */
151564727024SZiyang Xuan static void hinic_deinit_mac_addr(struct rte_eth_dev *eth_dev)
151664727024SZiyang Xuan {
151764727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
151864727024SZiyang Xuan 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
151964727024SZiyang Xuan 	u16 func_id = 0;
152000499a22SXiaoyun Wang 	int rc;
152100499a22SXiaoyun Wang 	int i;
152264727024SZiyang Xuan 
152364727024SZiyang Xuan 	func_id = hinic_global_func_id(nic_dev->hwdev);
152400499a22SXiaoyun Wang 
152500499a22SXiaoyun Wang 	for (i = 0; i < HINIC_MAX_UC_MAC_ADDRS; i++) {
152600499a22SXiaoyun Wang 		if (rte_is_zero_ether_addr(&eth_dev->data->mac_addrs[i]))
152700499a22SXiaoyun Wang 			continue;
152800499a22SXiaoyun Wang 
152964727024SZiyang Xuan 		rc = hinic_del_mac(nic_dev->hwdev,
153000499a22SXiaoyun Wang 				   eth_dev->data->mac_addrs[i].addr_bytes,
153164727024SZiyang Xuan 				   0, func_id);
153264727024SZiyang Xuan 		if (rc && rc != HINIC_PF_SET_VF_ALREADY)
153364727024SZiyang Xuan 			PMD_DRV_LOG(ERR, "Delete mac table failed, dev_name: %s",
153464727024SZiyang Xuan 				    eth_dev->data->name);
153500499a22SXiaoyun Wang 
153600499a22SXiaoyun Wang 		memset(&eth_dev->data->mac_addrs[i], 0,
153700499a22SXiaoyun Wang 		       sizeof(struct rte_ether_addr));
153800499a22SXiaoyun Wang 	}
153900499a22SXiaoyun Wang 
154000499a22SXiaoyun Wang 	/* delete multicast mac addrs */
154100499a22SXiaoyun Wang 	hinic_delete_mc_addr_list(nic_dev);
1542511b7371SGuoyang Zhou 
1543511b7371SGuoyang Zhou 	rte_free(nic_dev->mc_list);
1544511b7371SGuoyang Zhou 
154564727024SZiyang Xuan }
154664727024SZiyang Xuan 
15478260eba6SXiaoyun Wang static int hinic_dev_set_mtu(struct rte_eth_dev *dev, uint16_t mtu)
15488260eba6SXiaoyun Wang {
15498260eba6SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1550f7e04f57SFerruh Yigit 	int ret;
15518260eba6SXiaoyun Wang 
15528260eba6SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Set port mtu, port_id: %d, mtu: %d, max_pkt_len: %d",
15538260eba6SXiaoyun Wang 			dev->data->port_id, mtu, HINIC_MTU_TO_PKTLEN(mtu));
15548260eba6SXiaoyun Wang 
15558260eba6SXiaoyun Wang 	ret = hinic_set_port_mtu(nic_dev->hwdev, mtu);
15568260eba6SXiaoyun Wang 	if (ret) {
15578260eba6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set port mtu failed, ret: %d", ret);
15588260eba6SXiaoyun Wang 		return ret;
15598260eba6SXiaoyun Wang 	}
15608260eba6SXiaoyun Wang 
15618260eba6SXiaoyun Wang 	nic_dev->mtu_size = mtu;
15628260eba6SXiaoyun Wang 
15638260eba6SXiaoyun Wang 	return ret;
15648260eba6SXiaoyun Wang }
15658260eba6SXiaoyun Wang 
1566fdba3bf1SXiaoyun Wang static void hinic_store_vlan_filter(struct hinic_nic_dev *nic_dev,
1567fdba3bf1SXiaoyun Wang 					u16 vlan_id, bool on)
1568fdba3bf1SXiaoyun Wang {
1569fdba3bf1SXiaoyun Wang 	u32 vid_idx, vid_bit;
1570fdba3bf1SXiaoyun Wang 
1571fdba3bf1SXiaoyun Wang 	vid_idx = HINIC_VFTA_IDX(vlan_id);
1572fdba3bf1SXiaoyun Wang 	vid_bit = HINIC_VFTA_BIT(vlan_id);
1573fdba3bf1SXiaoyun Wang 
1574fdba3bf1SXiaoyun Wang 	if (on)
1575fdba3bf1SXiaoyun Wang 		nic_dev->vfta[vid_idx] |= vid_bit;
1576fdba3bf1SXiaoyun Wang 	else
1577fdba3bf1SXiaoyun Wang 		nic_dev->vfta[vid_idx] &= ~vid_bit;
1578fdba3bf1SXiaoyun Wang }
1579fdba3bf1SXiaoyun Wang 
1580fdba3bf1SXiaoyun Wang static bool hinic_find_vlan_filter(struct hinic_nic_dev *nic_dev,
1581fdba3bf1SXiaoyun Wang 				uint16_t vlan_id)
1582fdba3bf1SXiaoyun Wang {
1583fdba3bf1SXiaoyun Wang 	u32 vid_idx, vid_bit;
1584fdba3bf1SXiaoyun Wang 
1585fdba3bf1SXiaoyun Wang 	vid_idx = HINIC_VFTA_IDX(vlan_id);
1586fdba3bf1SXiaoyun Wang 	vid_bit = HINIC_VFTA_BIT(vlan_id);
1587fdba3bf1SXiaoyun Wang 
1588fdba3bf1SXiaoyun Wang 	return (nic_dev->vfta[vid_idx] & vid_bit) ? TRUE : FALSE;
1589fdba3bf1SXiaoyun Wang }
1590fdba3bf1SXiaoyun Wang 
1591fdba3bf1SXiaoyun Wang /**
1592fdba3bf1SXiaoyun Wang  * DPDK callback to set vlan filter.
1593fdba3bf1SXiaoyun Wang  *
1594fdba3bf1SXiaoyun Wang  * @param dev
1595fdba3bf1SXiaoyun Wang  *   Pointer to Ethernet device structure.
1596fdba3bf1SXiaoyun Wang  * @param vlan_id
1597fdba3bf1SXiaoyun Wang  *   vlan id is used to filter vlan packets
1598fdba3bf1SXiaoyun Wang  * @param enable
1599fdba3bf1SXiaoyun Wang  *   enable disable or enable vlan filter function
1600fdba3bf1SXiaoyun Wang  */
1601fdba3bf1SXiaoyun Wang static int hinic_vlan_filter_set(struct rte_eth_dev *dev,
1602fdba3bf1SXiaoyun Wang 				uint16_t vlan_id, int enable)
1603fdba3bf1SXiaoyun Wang {
1604fdba3bf1SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1605fdba3bf1SXiaoyun Wang 	int err = 0;
1606fdba3bf1SXiaoyun Wang 	u16 func_id;
1607fdba3bf1SXiaoyun Wang 
1608fdba3bf1SXiaoyun Wang 	if (vlan_id > RTE_ETHER_MAX_VLAN_ID)
1609fdba3bf1SXiaoyun Wang 		return -EINVAL;
1610fdba3bf1SXiaoyun Wang 
16112cfd68ecSGuoyang Zhou 	if (vlan_id == 0)
16122cfd68ecSGuoyang Zhou 		return 0;
16132cfd68ecSGuoyang Zhou 
1614fdba3bf1SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
1615fdba3bf1SXiaoyun Wang 
1616fdba3bf1SXiaoyun Wang 	if (enable) {
1617fdba3bf1SXiaoyun Wang 		/* If vlanid is already set, just return */
1618fdba3bf1SXiaoyun Wang 		if (hinic_find_vlan_filter(nic_dev, vlan_id)) {
1619fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(INFO, "Vlan %u has been added, device: %s",
1620fdba3bf1SXiaoyun Wang 				  vlan_id, nic_dev->proc_dev_name);
1621fdba3bf1SXiaoyun Wang 			return 0;
1622fdba3bf1SXiaoyun Wang 		}
1623fdba3bf1SXiaoyun Wang 
1624fdba3bf1SXiaoyun Wang 		err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id,
1625fdba3bf1SXiaoyun Wang 					    func_id, TRUE);
1626fdba3bf1SXiaoyun Wang 	} else {
1627fdba3bf1SXiaoyun Wang 		/* If vlanid can't be found, just return */
1628fdba3bf1SXiaoyun Wang 		if (!hinic_find_vlan_filter(nic_dev, vlan_id)) {
1629fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(INFO, "Vlan %u is not in the vlan filter list, device: %s",
1630fdba3bf1SXiaoyun Wang 				  vlan_id, nic_dev->proc_dev_name);
1631fdba3bf1SXiaoyun Wang 			return 0;
1632fdba3bf1SXiaoyun Wang 		}
1633fdba3bf1SXiaoyun Wang 
1634fdba3bf1SXiaoyun Wang 		err = hinic_add_remove_vlan(nic_dev->hwdev, vlan_id,
1635fdba3bf1SXiaoyun Wang 					    func_id, FALSE);
1636fdba3bf1SXiaoyun Wang 	}
1637fdba3bf1SXiaoyun Wang 
1638fdba3bf1SXiaoyun Wang 	if (err) {
1639fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(ERR, "%s vlan failed, func_id: %d, vlan_id: %d, err: %d",
1640fdba3bf1SXiaoyun Wang 		      enable ? "Add" : "Remove", func_id, vlan_id, err);
1641fdba3bf1SXiaoyun Wang 		return err;
1642fdba3bf1SXiaoyun Wang 	}
1643fdba3bf1SXiaoyun Wang 
1644fdba3bf1SXiaoyun Wang 	hinic_store_vlan_filter(nic_dev, vlan_id, enable);
1645fdba3bf1SXiaoyun Wang 
1646fdba3bf1SXiaoyun Wang 	PMD_DRV_LOG(INFO, "%s vlan %u succeed, device: %s",
1647fdba3bf1SXiaoyun Wang 		  enable ? "Add" : "Remove", vlan_id, nic_dev->proc_dev_name);
1648fdba3bf1SXiaoyun Wang 	return 0;
1649fdba3bf1SXiaoyun Wang }
1650fdba3bf1SXiaoyun Wang 
1651fdba3bf1SXiaoyun Wang /**
1652fdba3bf1SXiaoyun Wang  * DPDK callback to enable or disable vlan offload.
1653fdba3bf1SXiaoyun Wang  *
1654fdba3bf1SXiaoyun Wang  * @param dev
1655fdba3bf1SXiaoyun Wang  *   Pointer to Ethernet device structure.
1656fdba3bf1SXiaoyun Wang  * @param mask
1657fdba3bf1SXiaoyun Wang  *   Definitions used for VLAN setting
1658fdba3bf1SXiaoyun Wang  */
1659fdba3bf1SXiaoyun Wang static int hinic_vlan_offload_set(struct rte_eth_dev *dev, int mask)
1660fdba3bf1SXiaoyun Wang {
1661fdba3bf1SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1662fdba3bf1SXiaoyun Wang 	struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode;
1663fdba3bf1SXiaoyun Wang 	bool on;
1664fdba3bf1SXiaoyun Wang 	int err;
1665fdba3bf1SXiaoyun Wang 
1666fdba3bf1SXiaoyun Wang 	/* Enable or disable VLAN filter */
1667295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_FILTER_MASK) {
1668295968d1SFerruh Yigit 		on = (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_FILTER) ?
1669fdba3bf1SXiaoyun Wang 			TRUE : FALSE;
1670fdba3bf1SXiaoyun Wang 		err = hinic_config_vlan_filter(nic_dev->hwdev, on);
1671fdba3bf1SXiaoyun Wang 		if (err == HINIC_MGMT_CMD_UNSUPPORTED) {
1672fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(WARNING,
1673fdba3bf1SXiaoyun Wang 				"Current matching version does not support vlan filter configuration, device: %s, port_id: %d",
1674fdba3bf1SXiaoyun Wang 				  nic_dev->proc_dev_name, dev->data->port_id);
1675fdba3bf1SXiaoyun Wang 		} else if (err) {
1676fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Failed to %s vlan filter, device: %s, port_id: %d, err: %d",
1677fdba3bf1SXiaoyun Wang 				  on ? "enable" : "disable",
1678fdba3bf1SXiaoyun Wang 				  nic_dev->proc_dev_name,
1679fdba3bf1SXiaoyun Wang 				  dev->data->port_id, err);
1680fdba3bf1SXiaoyun Wang 			return err;
1681fdba3bf1SXiaoyun Wang 		}
1682fdba3bf1SXiaoyun Wang 
1683fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(INFO, "%s vlan filter succeed, device: %s, port_id: %d",
1684fdba3bf1SXiaoyun Wang 			  on ? "Enable" : "Disable",
1685fdba3bf1SXiaoyun Wang 			  nic_dev->proc_dev_name, dev->data->port_id);
1686fdba3bf1SXiaoyun Wang 	}
1687fdba3bf1SXiaoyun Wang 
1688fdba3bf1SXiaoyun Wang 	/* Enable or disable VLAN stripping */
1689295968d1SFerruh Yigit 	if (mask & RTE_ETH_VLAN_STRIP_MASK) {
1690295968d1SFerruh Yigit 		on = (rxmode->offloads & RTE_ETH_RX_OFFLOAD_VLAN_STRIP) ?
1691fdba3bf1SXiaoyun Wang 			TRUE : FALSE;
1692fdba3bf1SXiaoyun Wang 		err = hinic_set_rx_vlan_offload(nic_dev->hwdev, on);
1693fdba3bf1SXiaoyun Wang 		if (err) {
1694fdba3bf1SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Failed to %s vlan strip, device: %s, port_id: %d, err: %d",
1695fdba3bf1SXiaoyun Wang 				  on ? "enable" : "disable",
1696fdba3bf1SXiaoyun Wang 				  nic_dev->proc_dev_name,
1697fdba3bf1SXiaoyun Wang 				  dev->data->port_id, err);
1698fdba3bf1SXiaoyun Wang 			return err;
1699fdba3bf1SXiaoyun Wang 		}
1700fdba3bf1SXiaoyun Wang 
1701fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(INFO, "%s vlan strip succeed, device: %s, port_id: %d",
1702fdba3bf1SXiaoyun Wang 			  on ? "Enable" : "Disable",
1703fdba3bf1SXiaoyun Wang 			  nic_dev->proc_dev_name, dev->data->port_id);
1704fdba3bf1SXiaoyun Wang 	}
1705fdba3bf1SXiaoyun Wang 
1706fdba3bf1SXiaoyun Wang 	return 0;
1707fdba3bf1SXiaoyun Wang }
1708fdba3bf1SXiaoyun Wang 
1709fdba3bf1SXiaoyun Wang static void hinic_remove_all_vlanid(struct rte_eth_dev *eth_dev)
1710fdba3bf1SXiaoyun Wang {
1711fdba3bf1SXiaoyun Wang 	struct hinic_nic_dev *nic_dev =
1712fdba3bf1SXiaoyun Wang 		HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
1713fdba3bf1SXiaoyun Wang 	u16 func_id;
1714fdba3bf1SXiaoyun Wang 	int i;
1715fdba3bf1SXiaoyun Wang 
1716fdba3bf1SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
1717fdba3bf1SXiaoyun Wang 	for (i = 0; i <= RTE_ETHER_MAX_VLAN_ID; i++) {
1718fdba3bf1SXiaoyun Wang 		/* If can't find it, continue */
1719fdba3bf1SXiaoyun Wang 		if (!hinic_find_vlan_filter(nic_dev, i))
1720fdba3bf1SXiaoyun Wang 			continue;
1721fdba3bf1SXiaoyun Wang 
1722fdba3bf1SXiaoyun Wang 		(void)hinic_add_remove_vlan(nic_dev->hwdev, i, func_id, FALSE);
1723fdba3bf1SXiaoyun Wang 		hinic_store_vlan_filter(nic_dev, i, false);
1724fdba3bf1SXiaoyun Wang 	}
1725fdba3bf1SXiaoyun Wang }
1726fdba3bf1SXiaoyun Wang 
17278260eba6SXiaoyun Wang static int hinic_set_dev_allmulticast(struct hinic_nic_dev *nic_dev,
17288260eba6SXiaoyun Wang 				bool enable)
17298260eba6SXiaoyun Wang {
1730224cff4bSXiaoyun Wang 	u32 rx_mode_ctrl;
1731224cff4bSXiaoyun Wang 	int err;
1732224cff4bSXiaoyun Wang 
1733224cff4bSXiaoyun Wang 	err = hinic_mutex_lock(&nic_dev->rx_mode_mutex);
1734224cff4bSXiaoyun Wang 	if (err)
1735224cff4bSXiaoyun Wang 		return err;
1736224cff4bSXiaoyun Wang 
1737224cff4bSXiaoyun Wang 	rx_mode_ctrl = nic_dev->rx_mode_status;
17388260eba6SXiaoyun Wang 
17398260eba6SXiaoyun Wang 	if (enable)
17408260eba6SXiaoyun Wang 		rx_mode_ctrl |= HINIC_RX_MODE_MC_ALL;
17418260eba6SXiaoyun Wang 	else
17428260eba6SXiaoyun Wang 		rx_mode_ctrl &= (~HINIC_RX_MODE_MC_ALL);
17438260eba6SXiaoyun Wang 
1744224cff4bSXiaoyun Wang 	err = hinic_config_rx_mode(nic_dev, rx_mode_ctrl);
1745224cff4bSXiaoyun Wang 
1746224cff4bSXiaoyun Wang 	(void)hinic_mutex_unlock(&nic_dev->rx_mode_mutex);
1747224cff4bSXiaoyun Wang 
1748224cff4bSXiaoyun Wang 	return err;
17498260eba6SXiaoyun Wang }
17508260eba6SXiaoyun Wang 
17518260eba6SXiaoyun Wang /**
17528260eba6SXiaoyun Wang  * DPDK callback to enable allmulticast mode.
17538260eba6SXiaoyun Wang  *
17548260eba6SXiaoyun Wang  * @param dev
17558260eba6SXiaoyun Wang  *   Pointer to Ethernet device structure.
17568260eba6SXiaoyun Wang  *
17578260eba6SXiaoyun Wang  * @return
17588260eba6SXiaoyun Wang  *   0 on success,
17598260eba6SXiaoyun Wang  *   negative error value otherwise.
17608260eba6SXiaoyun Wang  */
17618260eba6SXiaoyun Wang static int hinic_dev_allmulticast_enable(struct rte_eth_dev *dev)
17628260eba6SXiaoyun Wang {
17638260eba6SXiaoyun Wang 	int ret = HINIC_OK;
17648260eba6SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
17658260eba6SXiaoyun Wang 
17668260eba6SXiaoyun Wang 	ret = hinic_set_dev_allmulticast(nic_dev, true);
17678260eba6SXiaoyun Wang 	if (ret) {
17688260eba6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Enable allmulticast failed, error: %d", ret);
17698260eba6SXiaoyun Wang 		return ret;
17708260eba6SXiaoyun Wang 	}
17718260eba6SXiaoyun Wang 
17728260eba6SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Enable allmulticast succeed, nic_dev: %s, port_id: %d",
17738260eba6SXiaoyun Wang 		nic_dev->proc_dev_name, dev->data->port_id);
17748260eba6SXiaoyun Wang 	return 0;
17758260eba6SXiaoyun Wang }
17768260eba6SXiaoyun Wang 
17778260eba6SXiaoyun Wang /**
17788260eba6SXiaoyun Wang  * DPDK callback to disable allmulticast mode.
17798260eba6SXiaoyun Wang  *
17808260eba6SXiaoyun Wang  * @param dev
17818260eba6SXiaoyun Wang  *   Pointer to Ethernet device structure.
17828260eba6SXiaoyun Wang  *
17838260eba6SXiaoyun Wang  * @return
17848260eba6SXiaoyun Wang  *   0 on success,
17858260eba6SXiaoyun Wang  *   negative error value otherwise.
17868260eba6SXiaoyun Wang  */
17878260eba6SXiaoyun Wang static int hinic_dev_allmulticast_disable(struct rte_eth_dev *dev)
17888260eba6SXiaoyun Wang {
17898260eba6SXiaoyun Wang 	int ret = HINIC_OK;
17908260eba6SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
17918260eba6SXiaoyun Wang 
17928260eba6SXiaoyun Wang 	ret = hinic_set_dev_allmulticast(nic_dev, false);
17938260eba6SXiaoyun Wang 	if (ret) {
17948260eba6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Disable allmulticast failed, error: %d", ret);
17958260eba6SXiaoyun Wang 		return ret;
17968260eba6SXiaoyun Wang 	}
17978260eba6SXiaoyun Wang 
17988260eba6SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Disable allmulticast succeed, nic_dev: %s, port_id: %d",
17998260eba6SXiaoyun Wang 		nic_dev->proc_dev_name, dev->data->port_id);
18008260eba6SXiaoyun Wang 	return 0;
18018260eba6SXiaoyun Wang }
18028260eba6SXiaoyun Wang 
1803cb7b6606SZiyang Xuan /**
1804cb7b6606SZiyang Xuan  * DPDK callback to enable promiscuous mode.
1805cb7b6606SZiyang Xuan  *
1806cb7b6606SZiyang Xuan  * @param dev
1807cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
18089039c812SAndrew Rybchenko  *
18099039c812SAndrew Rybchenko  * @return
18109039c812SAndrew Rybchenko  *   0 on success,
18119039c812SAndrew Rybchenko  *   negative error value otherwise.
1812cb7b6606SZiyang Xuan  */
18139039c812SAndrew Rybchenko static int hinic_dev_promiscuous_enable(struct rte_eth_dev *dev)
1814cb7b6606SZiyang Xuan {
1815cb7b6606SZiyang Xuan 	int rc = HINIC_OK;
1816cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1817cb7b6606SZiyang Xuan 
1818cb7b6606SZiyang Xuan 	PMD_DRV_LOG(INFO, "Enable promiscuous, nic_dev: %s, port_id: %d, promisc: %d",
1819cb7b6606SZiyang Xuan 		    nic_dev->proc_dev_name, dev->data->port_id,
1820cb7b6606SZiyang Xuan 		    dev->data->promiscuous);
1821cb7b6606SZiyang Xuan 
1822cb7b6606SZiyang Xuan 	rc = hinic_set_dev_promiscuous(nic_dev, true);
1823cb7b6606SZiyang Xuan 	if (rc)
1824cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Enable promiscuous failed");
18259039c812SAndrew Rybchenko 
18269039c812SAndrew Rybchenko 	return rc;
1827cb7b6606SZiyang Xuan }
1828cb7b6606SZiyang Xuan 
1829cb7b6606SZiyang Xuan /**
1830cb7b6606SZiyang Xuan  * DPDK callback to disable promiscuous mode.
1831cb7b6606SZiyang Xuan  *
1832cb7b6606SZiyang Xuan  * @param dev
1833cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
18349039c812SAndrew Rybchenko  *
18359039c812SAndrew Rybchenko  * @return
18369039c812SAndrew Rybchenko  *   0 on success,
18379039c812SAndrew Rybchenko  *   negative error value otherwise.
1838cb7b6606SZiyang Xuan  */
18399039c812SAndrew Rybchenko static int hinic_dev_promiscuous_disable(struct rte_eth_dev *dev)
1840cb7b6606SZiyang Xuan {
1841cb7b6606SZiyang Xuan 	int rc = HINIC_OK;
1842cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1843cb7b6606SZiyang Xuan 
1844cb7b6606SZiyang Xuan 	PMD_DRV_LOG(INFO, "Disable promiscuous, nic_dev: %s, port_id: %d, promisc: %d",
1845cb7b6606SZiyang Xuan 		    nic_dev->proc_dev_name, dev->data->port_id,
1846cb7b6606SZiyang Xuan 		    dev->data->promiscuous);
1847cb7b6606SZiyang Xuan 
1848cb7b6606SZiyang Xuan 	rc = hinic_set_dev_promiscuous(nic_dev, false);
1849cb7b6606SZiyang Xuan 	if (rc)
1850cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Disable promiscuous failed");
18519039c812SAndrew Rybchenko 
18529039c812SAndrew Rybchenko 	return rc;
1853cb7b6606SZiyang Xuan }
1854cb7b6606SZiyang Xuan 
1855ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_get(struct rte_eth_dev *dev,
1856ef6f2f5cSXiaoyun Wang 			struct rte_eth_fc_conf *fc_conf)
1857ef6f2f5cSXiaoyun Wang {
1858ef6f2f5cSXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1859ef6f2f5cSXiaoyun Wang 	struct nic_pause_config nic_pause;
1860ef6f2f5cSXiaoyun Wang 	int err;
1861ef6f2f5cSXiaoyun Wang 
1862ef6f2f5cSXiaoyun Wang 	memset(&nic_pause, 0, sizeof(nic_pause));
1863ef6f2f5cSXiaoyun Wang 
1864ef6f2f5cSXiaoyun Wang 	err = hinic_get_pause_info(nic_dev->hwdev, &nic_pause);
1865ef6f2f5cSXiaoyun Wang 	if (err)
1866ef6f2f5cSXiaoyun Wang 		return err;
1867ef6f2f5cSXiaoyun Wang 
1868ef6f2f5cSXiaoyun Wang 	if (nic_dev->pause_set || !nic_pause.auto_neg) {
1869ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause = nic_dev->nic_pause.rx_pause;
1870ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause = nic_dev->nic_pause.tx_pause;
1871ef6f2f5cSXiaoyun Wang 	}
1872ef6f2f5cSXiaoyun Wang 
1873ef6f2f5cSXiaoyun Wang 	fc_conf->autoneg = nic_pause.auto_neg;
1874ef6f2f5cSXiaoyun Wang 
1875ef6f2f5cSXiaoyun Wang 	if (nic_pause.tx_pause && nic_pause.rx_pause)
1876295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_FULL;
1877ef6f2f5cSXiaoyun Wang 	else if (nic_pause.tx_pause)
1878295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_TX_PAUSE;
1879ef6f2f5cSXiaoyun Wang 	else if (nic_pause.rx_pause)
1880295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_RX_PAUSE;
1881ef6f2f5cSXiaoyun Wang 	else
1882295968d1SFerruh Yigit 		fc_conf->mode = RTE_ETH_FC_NONE;
1883ef6f2f5cSXiaoyun Wang 
1884ef6f2f5cSXiaoyun Wang 	return 0;
1885ef6f2f5cSXiaoyun Wang }
1886ef6f2f5cSXiaoyun Wang 
1887ef6f2f5cSXiaoyun Wang static int hinic_flow_ctrl_set(struct rte_eth_dev *dev,
1888ef6f2f5cSXiaoyun Wang 			struct rte_eth_fc_conf *fc_conf)
1889ef6f2f5cSXiaoyun Wang {
1890ef6f2f5cSXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1891ef6f2f5cSXiaoyun Wang 	struct nic_pause_config nic_pause;
1892ef6f2f5cSXiaoyun Wang 	int err;
1893ef6f2f5cSXiaoyun Wang 
1894ef6f2f5cSXiaoyun Wang 	nic_pause.auto_neg = fc_conf->autoneg;
1895ef6f2f5cSXiaoyun Wang 
1896295968d1SFerruh Yigit 	if (((fc_conf->mode & RTE_ETH_FC_FULL) == RTE_ETH_FC_FULL) ||
1897295968d1SFerruh Yigit 		(fc_conf->mode & RTE_ETH_FC_TX_PAUSE))
1898ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause = true;
1899ef6f2f5cSXiaoyun Wang 	else
1900ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause = false;
1901ef6f2f5cSXiaoyun Wang 
1902295968d1SFerruh Yigit 	if (((fc_conf->mode & RTE_ETH_FC_FULL) == RTE_ETH_FC_FULL) ||
1903295968d1SFerruh Yigit 		(fc_conf->mode & RTE_ETH_FC_RX_PAUSE))
1904ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause = true;
1905ef6f2f5cSXiaoyun Wang 	else
1906ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause = false;
1907ef6f2f5cSXiaoyun Wang 
1908ef6f2f5cSXiaoyun Wang 	err = hinic_set_pause_config(nic_dev->hwdev, nic_pause);
1909ef6f2f5cSXiaoyun Wang 	if (err)
1910ef6f2f5cSXiaoyun Wang 		return err;
1911ef6f2f5cSXiaoyun Wang 
1912ef6f2f5cSXiaoyun Wang 	nic_dev->pause_set = true;
1913ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.auto_neg = nic_pause.auto_neg;
1914ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.rx_pause = nic_pause.rx_pause;
1915ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.tx_pause = nic_pause.tx_pause;
1916ef6f2f5cSXiaoyun Wang 
1917*f665790aSDavid Marchand 	PMD_DRV_LOG(INFO, "Set pause options, tx: %s, rx: %s, auto: %s",
1918ef6f2f5cSXiaoyun Wang 		nic_pause.tx_pause ? "on" : "off",
1919ef6f2f5cSXiaoyun Wang 		nic_pause.rx_pause ? "on" : "off",
1920ef6f2f5cSXiaoyun Wang 		nic_pause.auto_neg ? "on" : "off");
1921ef6f2f5cSXiaoyun Wang 
1922ef6f2f5cSXiaoyun Wang 	return 0;
1923ef6f2f5cSXiaoyun Wang }
1924ef6f2f5cSXiaoyun Wang 
1925cb7b6606SZiyang Xuan /**
1926cb7b6606SZiyang Xuan  * DPDK callback to update the RSS hash key and RSS hash type.
1927cb7b6606SZiyang Xuan  *
1928cb7b6606SZiyang Xuan  * @param dev
1929cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
1930cb7b6606SZiyang Xuan  * @param rss_conf
1931cb7b6606SZiyang Xuan  *   RSS configuration data.
1932cb7b6606SZiyang Xuan  *
1933cb7b6606SZiyang Xuan  * @return
1934cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
1935cb7b6606SZiyang Xuan  */
1936cb7b6606SZiyang Xuan static int hinic_rss_hash_update(struct rte_eth_dev *dev,
1937cb7b6606SZiyang Xuan 			  struct rte_eth_rss_conf *rss_conf)
1938cb7b6606SZiyang Xuan {
1939cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
1940cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
1941cb7b6606SZiyang Xuan 	u8 hashkey[HINIC_RSS_KEY_SIZE] = {0};
1942cb7b6606SZiyang Xuan 	u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
1943cb7b6606SZiyang Xuan 	u64 rss_hf = rss_conf->rss_hf;
1944cb7b6606SZiyang Xuan 	struct nic_rss_type rss_type = {0};
1945cb7b6606SZiyang Xuan 	int err = 0;
1946cb7b6606SZiyang Xuan 
1947295968d1SFerruh Yigit 	if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG)) {
1948cb7b6606SZiyang Xuan 		PMD_DRV_LOG(WARNING, "RSS is not enabled");
1949cb7b6606SZiyang Xuan 		return HINIC_OK;
1950cb7b6606SZiyang Xuan 	}
1951cb7b6606SZiyang Xuan 
1952cb7b6606SZiyang Xuan 	if (rss_conf->rss_key_len > HINIC_RSS_KEY_SIZE) {
1953cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid rss key, rss_key_len: %d",
1954cb7b6606SZiyang Xuan 			    rss_conf->rss_key_len);
1955cb7b6606SZiyang Xuan 		return HINIC_ERROR;
1956cb7b6606SZiyang Xuan 	}
1957cb7b6606SZiyang Xuan 
1958cb7b6606SZiyang Xuan 	if (rss_conf->rss_key) {
1959cb7b6606SZiyang Xuan 		memcpy(hashkey, rss_conf->rss_key, rss_conf->rss_key_len);
1960cb7b6606SZiyang Xuan 		err = hinic_rss_set_template_tbl(nic_dev->hwdev, tmpl_idx,
1961cb7b6606SZiyang Xuan 						 hashkey);
1962cb7b6606SZiyang Xuan 		if (err) {
1963cb7b6606SZiyang Xuan 			PMD_DRV_LOG(ERR, "Set rss template table failed");
1964cb7b6606SZiyang Xuan 			goto disable_rss;
1965cb7b6606SZiyang Xuan 		}
1966cb7b6606SZiyang Xuan 	}
1967cb7b6606SZiyang Xuan 
1968295968d1SFerruh Yigit 	rss_type.ipv4 = (rss_hf & (RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4)) ? 1 : 0;
1969295968d1SFerruh Yigit 	rss_type.tcp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_TCP) ? 1 : 0;
1970295968d1SFerruh Yigit 	rss_type.ipv6 = (rss_hf & (RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6)) ? 1 : 0;
1971295968d1SFerruh Yigit 	rss_type.ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_EX) ? 1 : 0;
1972295968d1SFerruh Yigit 	rss_type.tcp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_TCP) ? 1 : 0;
1973295968d1SFerruh Yigit 	rss_type.tcp_ipv6_ext = (rss_hf & RTE_ETH_RSS_IPV6_TCP_EX) ? 1 : 0;
1974295968d1SFerruh Yigit 	rss_type.udp_ipv4 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV4_UDP) ? 1 : 0;
1975295968d1SFerruh Yigit 	rss_type.udp_ipv6 = (rss_hf & RTE_ETH_RSS_NONFRAG_IPV6_UDP) ? 1 : 0;
1976cb7b6606SZiyang Xuan 
1977cb7b6606SZiyang Xuan 	err = hinic_set_rss_type(nic_dev->hwdev, tmpl_idx, rss_type);
1978cb7b6606SZiyang Xuan 	if (err) {
1979cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Set rss type table failed");
1980cb7b6606SZiyang Xuan 		goto disable_rss;
1981cb7b6606SZiyang Xuan 	}
1982cb7b6606SZiyang Xuan 
1983cb7b6606SZiyang Xuan 	return 0;
1984cb7b6606SZiyang Xuan 
1985cb7b6606SZiyang Xuan disable_rss:
1986cb7b6606SZiyang Xuan 	memset(prio_tc, 0, sizeof(prio_tc));
1987cb7b6606SZiyang Xuan 	(void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc);
1988cb7b6606SZiyang Xuan 	return err;
1989cb7b6606SZiyang Xuan }
1990cb7b6606SZiyang Xuan 
1991cb7b6606SZiyang Xuan /**
1992cb7b6606SZiyang Xuan  * DPDK callback to get the RSS hash configuration.
1993cb7b6606SZiyang Xuan  *
1994cb7b6606SZiyang Xuan  * @param dev
1995cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
1996cb7b6606SZiyang Xuan  * @param rss_conf
1997cb7b6606SZiyang Xuan  *   RSS configuration data.
1998cb7b6606SZiyang Xuan  *
1999cb7b6606SZiyang Xuan  * @return
2000cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
2001cb7b6606SZiyang Xuan  */
2002cb7b6606SZiyang Xuan static int hinic_rss_conf_get(struct rte_eth_dev *dev,
2003cb7b6606SZiyang Xuan 		       struct rte_eth_rss_conf *rss_conf)
2004cb7b6606SZiyang Xuan {
2005cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2006cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
2007cb7b6606SZiyang Xuan 	u8 hashkey[HINIC_RSS_KEY_SIZE] = {0};
2008cb7b6606SZiyang Xuan 	struct nic_rss_type rss_type = {0};
2009cb7b6606SZiyang Xuan 	int err;
2010cb7b6606SZiyang Xuan 
2011295968d1SFerruh Yigit 	if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG)) {
2012cb7b6606SZiyang Xuan 		PMD_DRV_LOG(WARNING, "RSS is not enabled");
2013cb7b6606SZiyang Xuan 		return HINIC_ERROR;
2014cb7b6606SZiyang Xuan 	}
2015cb7b6606SZiyang Xuan 
2016cb7b6606SZiyang Xuan 	err = hinic_rss_get_template_tbl(nic_dev->hwdev, tmpl_idx, hashkey);
2017cb7b6606SZiyang Xuan 	if (err)
2018cb7b6606SZiyang Xuan 		return err;
2019cb7b6606SZiyang Xuan 
2020cb7b6606SZiyang Xuan 	if (rss_conf->rss_key &&
2021cb7b6606SZiyang Xuan 	    rss_conf->rss_key_len >= HINIC_RSS_KEY_SIZE) {
2022cb7b6606SZiyang Xuan 		memcpy(rss_conf->rss_key, hashkey, sizeof(hashkey));
2023cb7b6606SZiyang Xuan 		rss_conf->rss_key_len = sizeof(hashkey);
2024cb7b6606SZiyang Xuan 	}
2025cb7b6606SZiyang Xuan 
2026cb7b6606SZiyang Xuan 	err = hinic_get_rss_type(nic_dev->hwdev, tmpl_idx, &rss_type);
2027cb7b6606SZiyang Xuan 	if (err)
2028cb7b6606SZiyang Xuan 		return err;
2029cb7b6606SZiyang Xuan 
2030cb7b6606SZiyang Xuan 	rss_conf->rss_hf = 0;
2031cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.ipv4 ?
2032295968d1SFerruh Yigit 		(RTE_ETH_RSS_IPV4 | RTE_ETH_RSS_FRAG_IPV4) : 0;
2033295968d1SFerruh Yigit 	rss_conf->rss_hf |=  rss_type.tcp_ipv4 ? RTE_ETH_RSS_NONFRAG_IPV4_TCP : 0;
2034cb7b6606SZiyang Xuan 	rss_conf->rss_hf |=  rss_type.ipv6 ?
2035295968d1SFerruh Yigit 		(RTE_ETH_RSS_IPV6 | RTE_ETH_RSS_FRAG_IPV6) : 0;
2036295968d1SFerruh Yigit 	rss_conf->rss_hf |=  rss_type.ipv6_ext ? RTE_ETH_RSS_IPV6_EX : 0;
2037295968d1SFerruh Yigit 	rss_conf->rss_hf |=  rss_type.tcp_ipv6 ? RTE_ETH_RSS_NONFRAG_IPV6_TCP : 0;
2038295968d1SFerruh Yigit 	rss_conf->rss_hf |=  rss_type.tcp_ipv6_ext ? RTE_ETH_RSS_IPV6_TCP_EX : 0;
2039295968d1SFerruh Yigit 	rss_conf->rss_hf |=  rss_type.udp_ipv4 ? RTE_ETH_RSS_NONFRAG_IPV4_UDP : 0;
2040295968d1SFerruh Yigit 	rss_conf->rss_hf |=  rss_type.udp_ipv6 ? RTE_ETH_RSS_NONFRAG_IPV6_UDP : 0;
2041cb7b6606SZiyang Xuan 
2042cb7b6606SZiyang Xuan 	return HINIC_OK;
2043cb7b6606SZiyang Xuan }
2044cb7b6606SZiyang Xuan 
2045cb7b6606SZiyang Xuan /**
2046f372a65fSXiaoyun Wang  * DPDK callback to update the RSS redirection table.
2047cb7b6606SZiyang Xuan  *
2048cb7b6606SZiyang Xuan  * @param dev
2049cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
2050cb7b6606SZiyang Xuan  * @param reta_conf
2051f372a65fSXiaoyun Wang  *   Pointer to RSS reta configuration data.
2052cb7b6606SZiyang Xuan  * @param reta_size
2053cb7b6606SZiyang Xuan  *   Size of the RETA table.
2054cb7b6606SZiyang Xuan  *
2055cb7b6606SZiyang Xuan  * @return
2056cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
2057cb7b6606SZiyang Xuan  */
2058cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_update(struct rte_eth_dev *dev,
2059cb7b6606SZiyang Xuan 			      struct rte_eth_rss_reta_entry64 *reta_conf,
2060cb7b6606SZiyang Xuan 			      uint16_t reta_size)
2061cb7b6606SZiyang Xuan {
2062cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2063cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
2064cb7b6606SZiyang Xuan 	u8 prio_tc[HINIC_DCB_UP_MAX] = {0};
2065cb7b6606SZiyang Xuan 	u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0};
2066cb7b6606SZiyang Xuan 	int err = 0;
2067cb7b6606SZiyang Xuan 	u16 i = 0;
2068cb7b6606SZiyang Xuan 	u16 idx, shift;
2069cb7b6606SZiyang Xuan 
2070295968d1SFerruh Yigit 	if (!(nic_dev->flags & RTE_ETH_MQ_RX_RSS_FLAG))
2071cb7b6606SZiyang Xuan 		return HINIC_OK;
2072cb7b6606SZiyang Xuan 
2073cb7b6606SZiyang Xuan 	if (reta_size != NIC_RSS_INDIR_SIZE) {
2074cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size);
2075cb7b6606SZiyang Xuan 		return HINIC_ERROR;
2076cb7b6606SZiyang Xuan 	}
2077cb7b6606SZiyang Xuan 
2078cb7b6606SZiyang Xuan 	err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl);
2079cb7b6606SZiyang Xuan 	if (err)
2080cb7b6606SZiyang Xuan 		return err;
2081cb7b6606SZiyang Xuan 
2082cb7b6606SZiyang Xuan 	/* update rss indir_tbl */
2083cb7b6606SZiyang Xuan 	for (i = 0; i < reta_size; i++) {
2084295968d1SFerruh Yigit 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
2085295968d1SFerruh Yigit 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
208672babbc0SXiaoyun Wang 
208772babbc0SXiaoyun Wang 		if (reta_conf[idx].reta[shift] >= nic_dev->num_rq) {
208872babbc0SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Invalid reta entry, indirtbl[%d]: %d "
208972babbc0SXiaoyun Wang 				"exceeds the maximum rxq num: %d", i,
209072babbc0SXiaoyun Wang 				reta_conf[idx].reta[shift], nic_dev->num_rq);
209172babbc0SXiaoyun Wang 			return -EINVAL;
2092cb7b6606SZiyang Xuan 		}
2093cb7b6606SZiyang Xuan 
209472babbc0SXiaoyun Wang 		if (reta_conf[idx].mask & (1ULL << shift))
209572babbc0SXiaoyun Wang 			indirtbl[i] = reta_conf[idx].reta[shift];
2096cb7b6606SZiyang Xuan 	}
2097cb7b6606SZiyang Xuan 
2098cb7b6606SZiyang Xuan 	err = hinic_rss_set_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl);
2099cb7b6606SZiyang Xuan 	if (err)
2100cb7b6606SZiyang Xuan 		goto disable_rss;
2101cb7b6606SZiyang Xuan 
2102cb7b6606SZiyang Xuan 	nic_dev->rss_indir_flag = true;
2103cb7b6606SZiyang Xuan 
2104cb7b6606SZiyang Xuan 	return 0;
2105cb7b6606SZiyang Xuan 
2106cb7b6606SZiyang Xuan disable_rss:
2107cb7b6606SZiyang Xuan 	memset(prio_tc, 0, sizeof(prio_tc));
2108cb7b6606SZiyang Xuan 	(void)hinic_rss_cfg(nic_dev->hwdev, 0, tmpl_idx, 0, prio_tc);
2109cb7b6606SZiyang Xuan 
2110cb7b6606SZiyang Xuan 	return HINIC_ERROR;
2111cb7b6606SZiyang Xuan }
2112cb7b6606SZiyang Xuan 
2113cb7b6606SZiyang Xuan /**
2114f372a65fSXiaoyun Wang  * DPDK callback to get the RSS indirection table.
2115cb7b6606SZiyang Xuan  *
2116cb7b6606SZiyang Xuan  * @param dev
2117cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
2118cb7b6606SZiyang Xuan  * @param reta_conf
2119f372a65fSXiaoyun Wang  *   Pointer to RSS reta configuration data.
2120cb7b6606SZiyang Xuan  * @param reta_size
2121cb7b6606SZiyang Xuan  *   Size of the RETA table.
2122cb7b6606SZiyang Xuan  *
2123cb7b6606SZiyang Xuan  * @return
2124cb7b6606SZiyang Xuan  *   0 on success, negative error value otherwise.
2125cb7b6606SZiyang Xuan  */
2126cb7b6606SZiyang Xuan static int hinic_rss_indirtbl_query(struct rte_eth_dev *dev,
2127cb7b6606SZiyang Xuan 			     struct rte_eth_rss_reta_entry64 *reta_conf,
2128cb7b6606SZiyang Xuan 			     uint16_t reta_size)
2129cb7b6606SZiyang Xuan {
2130cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2131cb7b6606SZiyang Xuan 	u8 tmpl_idx = nic_dev->rss_tmpl_idx;
2132cb7b6606SZiyang Xuan 	int err = 0;
2133cb7b6606SZiyang Xuan 	u32 indirtbl[NIC_RSS_INDIR_SIZE] = {0};
2134cb7b6606SZiyang Xuan 	u16 idx, shift;
2135cb7b6606SZiyang Xuan 	u16 i = 0;
2136cb7b6606SZiyang Xuan 
2137cb7b6606SZiyang Xuan 	if (reta_size != NIC_RSS_INDIR_SIZE) {
2138cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid reta size, reta_size: %d", reta_size);
2139cb7b6606SZiyang Xuan 		return HINIC_ERROR;
2140cb7b6606SZiyang Xuan 	}
2141cb7b6606SZiyang Xuan 
2142cb7b6606SZiyang Xuan 	err = hinic_rss_get_indir_tbl(nic_dev->hwdev, tmpl_idx, indirtbl);
2143cb7b6606SZiyang Xuan 	if (err) {
2144cb7b6606SZiyang Xuan 		PMD_DRV_LOG(ERR, "Get rss indirect table failed, error: %d",
2145cb7b6606SZiyang Xuan 			    err);
2146cb7b6606SZiyang Xuan 		return err;
2147cb7b6606SZiyang Xuan 	}
2148cb7b6606SZiyang Xuan 
2149cb7b6606SZiyang Xuan 	for (i = 0; i < reta_size; i++) {
2150295968d1SFerruh Yigit 		idx = i / RTE_ETH_RETA_GROUP_SIZE;
2151295968d1SFerruh Yigit 		shift = i % RTE_ETH_RETA_GROUP_SIZE;
2152cb7b6606SZiyang Xuan 		if (reta_conf[idx].mask & (1ULL << shift))
2153cb7b6606SZiyang Xuan 			reta_conf[idx].reta[shift] = (uint16_t)indirtbl[i];
2154cb7b6606SZiyang Xuan 	}
2155cb7b6606SZiyang Xuan 
2156cb7b6606SZiyang Xuan 	return HINIC_OK;
2157cb7b6606SZiyang Xuan }
2158cb7b6606SZiyang Xuan 
2159cb7b6606SZiyang Xuan /**
2160cb7b6606SZiyang Xuan  * DPDK callback to get extended device statistics.
2161cb7b6606SZiyang Xuan  *
2162cb7b6606SZiyang Xuan  * @param dev
2163cb7b6606SZiyang Xuan  *   Pointer to Ethernet device.
2164cb7b6606SZiyang Xuan  * @param xstats
2165cb7b6606SZiyang Xuan  *   Pointer to rte extended stats table.
2166cb7b6606SZiyang Xuan  * @param n
2167cb7b6606SZiyang Xuan  *   The size of the stats table.
2168cb7b6606SZiyang Xuan  *
2169cb7b6606SZiyang Xuan  * @return
2170cb7b6606SZiyang Xuan  *   Number of extended stats on success and stats is filled,
2171cb7b6606SZiyang Xuan  *   negative error value otherwise.
2172cb7b6606SZiyang Xuan  */
2173cb7b6606SZiyang Xuan static int hinic_dev_xstats_get(struct rte_eth_dev *dev,
2174cb7b6606SZiyang Xuan 			 struct rte_eth_xstat *xstats,
2175cb7b6606SZiyang Xuan 			 unsigned int n)
2176cb7b6606SZiyang Xuan {
2177cb7b6606SZiyang Xuan 	u16 qid = 0;
2178cb7b6606SZiyang Xuan 	u32 i;
2179cb7b6606SZiyang Xuan 	int err, count;
2180cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev;
2181cb7b6606SZiyang Xuan 	struct hinic_phy_port_stats port_stats;
2182cb7b6606SZiyang Xuan 	struct hinic_vport_stats vport_stats;
2183cb7b6606SZiyang Xuan 	struct hinic_rxq	*rxq = NULL;
2184cb7b6606SZiyang Xuan 	struct hinic_rxq_stats rxq_stats;
2185cb7b6606SZiyang Xuan 	struct hinic_txq	*txq = NULL;
2186cb7b6606SZiyang Xuan 	struct hinic_txq_stats txq_stats;
2187cb7b6606SZiyang Xuan 
2188cb7b6606SZiyang Xuan 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2189cb7b6606SZiyang Xuan 	count = hinic_xstats_calc_num(nic_dev);
2190cb7b6606SZiyang Xuan 	if ((int)n < count)
2191cb7b6606SZiyang Xuan 		return count;
2192cb7b6606SZiyang Xuan 
2193cb7b6606SZiyang Xuan 	count = 0;
2194cb7b6606SZiyang Xuan 
2195cb7b6606SZiyang Xuan 	/* Get stats from hinic_rxq_stats */
2196cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_rq; qid++) {
2197cb7b6606SZiyang Xuan 		rxq = nic_dev->rxqs[qid];
2198cb7b6606SZiyang Xuan 		hinic_rxq_get_stats(rxq, &rxq_stats);
2199cb7b6606SZiyang Xuan 
2200cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) {
2201cb7b6606SZiyang Xuan 			xstats[count].value =
2202cb7b6606SZiyang Xuan 				*(uint64_t *)(((char *)&rxq_stats) +
2203cb7b6606SZiyang Xuan 				hinic_rxq_stats_strings[i].offset);
2204cb7b6606SZiyang Xuan 			xstats[count].id = count;
2205cb7b6606SZiyang Xuan 			count++;
2206cb7b6606SZiyang Xuan 		}
2207cb7b6606SZiyang Xuan 	}
2208cb7b6606SZiyang Xuan 
2209cb7b6606SZiyang Xuan 	/* Get stats from hinic_txq_stats */
2210cb7b6606SZiyang Xuan 	for (qid = 0; qid < nic_dev->num_sq; qid++) {
2211cb7b6606SZiyang Xuan 		txq = nic_dev->txqs[qid];
2212cb7b6606SZiyang Xuan 		hinic_txq_get_stats(txq, &txq_stats);
2213cb7b6606SZiyang Xuan 
2214cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) {
2215cb7b6606SZiyang Xuan 			xstats[count].value =
2216cb7b6606SZiyang Xuan 				*(uint64_t *)(((char *)&txq_stats) +
2217cb7b6606SZiyang Xuan 				hinic_txq_stats_strings[i].offset);
2218cb7b6606SZiyang Xuan 			xstats[count].id = count;
2219cb7b6606SZiyang Xuan 			count++;
2220cb7b6606SZiyang Xuan 		}
2221cb7b6606SZiyang Xuan 	}
2222cb7b6606SZiyang Xuan 
2223cb7b6606SZiyang Xuan 	/* Get stats from hinic_vport_stats */
2224cb7b6606SZiyang Xuan 	err = hinic_get_vport_stats(nic_dev->hwdev, &vport_stats);
2225cb7b6606SZiyang Xuan 	if (err)
2226cb7b6606SZiyang Xuan 		return err;
2227cb7b6606SZiyang Xuan 
2228cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) {
2229cb7b6606SZiyang Xuan 		xstats[count].value =
2230cb7b6606SZiyang Xuan 			*(uint64_t *)(((char *)&vport_stats) +
2231cb7b6606SZiyang Xuan 			hinic_vport_stats_strings[i].offset);
2232cb7b6606SZiyang Xuan 		xstats[count].id = count;
2233cb7b6606SZiyang Xuan 		count++;
2234cb7b6606SZiyang Xuan 	}
2235cb7b6606SZiyang Xuan 
22366691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev))
22376691acefSXiaoyun Wang 		return count;
22386691acefSXiaoyun Wang 
2239cb7b6606SZiyang Xuan 	/* Get stats from hinic_phy_port_stats */
2240cb7b6606SZiyang Xuan 	err = hinic_get_phy_port_stats(nic_dev->hwdev, &port_stats);
2241cb7b6606SZiyang Xuan 	if (err)
2242cb7b6606SZiyang Xuan 		return err;
2243cb7b6606SZiyang Xuan 
2244cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) {
2245cb7b6606SZiyang Xuan 		xstats[count].value = *(uint64_t *)(((char *)&port_stats) +
2246cb7b6606SZiyang Xuan 				hinic_phyport_stats_strings[i].offset);
2247cb7b6606SZiyang Xuan 		xstats[count].id = count;
2248cb7b6606SZiyang Xuan 		count++;
2249cb7b6606SZiyang Xuan 	}
2250cb7b6606SZiyang Xuan 
2251cb7b6606SZiyang Xuan 	return count;
2252cb7b6606SZiyang Xuan }
2253cb7b6606SZiyang Xuan 
2254483b4817SXiaoyun Wang static void hinic_rxq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
2255483b4817SXiaoyun Wang 				struct rte_eth_rxq_info *qinfo)
2256483b4817SXiaoyun Wang {
2257483b4817SXiaoyun Wang 	struct hinic_rxq  *rxq = dev->data->rx_queues[queue_id];
2258483b4817SXiaoyun Wang 
2259483b4817SXiaoyun Wang 	qinfo->mp = rxq->mb_pool;
2260483b4817SXiaoyun Wang 	qinfo->nb_desc = rxq->q_depth;
2261483b4817SXiaoyun Wang }
2262483b4817SXiaoyun Wang 
2263483b4817SXiaoyun Wang static void hinic_txq_info_get(struct rte_eth_dev *dev, uint16_t queue_id,
2264483b4817SXiaoyun Wang 				struct rte_eth_txq_info *qinfo)
2265483b4817SXiaoyun Wang {
2266483b4817SXiaoyun Wang 	struct hinic_txq  *txq = dev->data->tx_queues[queue_id];
2267483b4817SXiaoyun Wang 
2268483b4817SXiaoyun Wang 	qinfo->nb_desc = txq->q_depth;
2269483b4817SXiaoyun Wang }
2270483b4817SXiaoyun Wang 
2271cb7b6606SZiyang Xuan /**
2272cb7b6606SZiyang Xuan  * DPDK callback to retrieve names of extended device statistics
2273cb7b6606SZiyang Xuan  *
2274cb7b6606SZiyang Xuan  * @param dev
2275cb7b6606SZiyang Xuan  *   Pointer to Ethernet device structure.
2276cb7b6606SZiyang Xuan  * @param xstats_names
2277cb7b6606SZiyang Xuan  *   Buffer to insert names into.
2278cb7b6606SZiyang Xuan  *
2279cb7b6606SZiyang Xuan  * @return
2280cb7b6606SZiyang Xuan  *   Number of xstats names.
2281cb7b6606SZiyang Xuan  */
2282cb7b6606SZiyang Xuan static int hinic_dev_xstats_get_names(struct rte_eth_dev *dev,
2283cb7b6606SZiyang Xuan 			       struct rte_eth_xstat_name *xstats_names,
2284cb7b6606SZiyang Xuan 			       __rte_unused unsigned int limit)
2285cb7b6606SZiyang Xuan {
2286cb7b6606SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
2287cb7b6606SZiyang Xuan 	int count = 0;
2288cb7b6606SZiyang Xuan 	u16 i = 0, q_num;
2289cb7b6606SZiyang Xuan 
2290cb7b6606SZiyang Xuan 	if (xstats_names == NULL)
2291cb7b6606SZiyang Xuan 		return hinic_xstats_calc_num(nic_dev);
2292cb7b6606SZiyang Xuan 
2293cb7b6606SZiyang Xuan 	/* get pmd rxq stats */
2294cb7b6606SZiyang Xuan 	for (q_num = 0; q_num < nic_dev->num_rq; q_num++) {
2295cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_RXQ_XSTATS_NUM; i++) {
2296cb7b6606SZiyang Xuan 			snprintf(xstats_names[count].name,
2297cb7b6606SZiyang Xuan 				 sizeof(xstats_names[count].name),
2298cb7b6606SZiyang Xuan 				 "rxq%d_%s_pmd",
2299cb7b6606SZiyang Xuan 				 q_num, hinic_rxq_stats_strings[i].name);
2300cb7b6606SZiyang Xuan 			count++;
2301cb7b6606SZiyang Xuan 		}
2302cb7b6606SZiyang Xuan 	}
2303cb7b6606SZiyang Xuan 
2304cb7b6606SZiyang Xuan 	/* get pmd txq stats */
2305cb7b6606SZiyang Xuan 	for (q_num = 0; q_num < nic_dev->num_sq; q_num++) {
2306cb7b6606SZiyang Xuan 		for (i = 0; i < HINIC_TXQ_XSTATS_NUM; i++) {
2307cb7b6606SZiyang Xuan 			snprintf(xstats_names[count].name,
2308cb7b6606SZiyang Xuan 				 sizeof(xstats_names[count].name),
2309cb7b6606SZiyang Xuan 				 "txq%d_%s_pmd",
2310cb7b6606SZiyang Xuan 				 q_num, hinic_txq_stats_strings[i].name);
2311cb7b6606SZiyang Xuan 			count++;
2312cb7b6606SZiyang Xuan 		}
2313cb7b6606SZiyang Xuan 	}
2314cb7b6606SZiyang Xuan 
2315cb7b6606SZiyang Xuan 	/* get vport stats */
2316cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_VPORT_XSTATS_NUM; i++) {
2317cb7b6606SZiyang Xuan 		snprintf(xstats_names[count].name,
2318cb7b6606SZiyang Xuan 			 sizeof(xstats_names[count].name),
2319f372a65fSXiaoyun Wang 			 "%s", hinic_vport_stats_strings[i].name);
2320cb7b6606SZiyang Xuan 		count++;
2321cb7b6606SZiyang Xuan 	}
2322cb7b6606SZiyang Xuan 
23236691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev))
23246691acefSXiaoyun Wang 		return count;
23256691acefSXiaoyun Wang 
2326cb7b6606SZiyang Xuan 	/* get phy port stats */
2327cb7b6606SZiyang Xuan 	for (i = 0; i < HINIC_PHYPORT_XSTATS_NUM; i++) {
2328cb7b6606SZiyang Xuan 		snprintf(xstats_names[count].name,
2329cb7b6606SZiyang Xuan 			 sizeof(xstats_names[count].name),
2330f372a65fSXiaoyun Wang 			 "%s", hinic_phyport_stats_strings[i].name);
2331cb7b6606SZiyang Xuan 		count++;
2332cb7b6606SZiyang Xuan 	}
2333cb7b6606SZiyang Xuan 
2334cb7b6606SZiyang Xuan 	return count;
2335cb7b6606SZiyang Xuan }
2336f372a65fSXiaoyun Wang 
233700499a22SXiaoyun Wang /**
233800499a22SXiaoyun Wang  *  DPDK callback to set mac address
233900499a22SXiaoyun Wang  *
234000499a22SXiaoyun Wang  * @param dev
234100499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
234200499a22SXiaoyun Wang  * @param addr
234300499a22SXiaoyun Wang  *   Pointer to mac address
234400499a22SXiaoyun Wang  * @return
234500499a22SXiaoyun Wang  *   0 on success, negative error value otherwise.
234600499a22SXiaoyun Wang  */
234700499a22SXiaoyun Wang static int hinic_set_mac_addr(struct rte_eth_dev *dev,
234800499a22SXiaoyun Wang 			      struct rte_ether_addr *addr)
234900499a22SXiaoyun Wang {
235000499a22SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
235100499a22SXiaoyun Wang 	u16 func_id;
235200499a22SXiaoyun Wang 	int err;
235300499a22SXiaoyun Wang 
235400499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
235500499a22SXiaoyun Wang 	err = hinic_update_mac(nic_dev->hwdev, nic_dev->default_addr.addr_bytes,
235600499a22SXiaoyun Wang 			       addr->addr_bytes, 0, func_id);
235700499a22SXiaoyun Wang 	if (err)
235800499a22SXiaoyun Wang 		return err;
235900499a22SXiaoyun Wang 
236000499a22SXiaoyun Wang 	rte_ether_addr_copy(addr, &nic_dev->default_addr);
236100499a22SXiaoyun Wang 
2362c2c4f87bSAman Deep Singh 	PMD_DRV_LOG(INFO, "Set new mac address " RTE_ETHER_ADDR_PRT_FMT,
2363a7db3afcSAman Deep Singh 		    RTE_ETHER_ADDR_BYTES(addr));
236400499a22SXiaoyun Wang 
236500499a22SXiaoyun Wang 	return 0;
236600499a22SXiaoyun Wang }
236700499a22SXiaoyun Wang 
236800499a22SXiaoyun Wang /**
236900499a22SXiaoyun Wang  * DPDK callback to remove a MAC address.
237000499a22SXiaoyun Wang  *
237100499a22SXiaoyun Wang  * @param dev
237200499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
237300499a22SXiaoyun Wang  * @param index
23744f1af3cbSXiaoyun Wang  *   MAC address index, should less than 128.
237500499a22SXiaoyun Wang  */
237600499a22SXiaoyun Wang static void hinic_mac_addr_remove(struct rte_eth_dev *dev, uint32_t index)
237700499a22SXiaoyun Wang {
237800499a22SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
237900499a22SXiaoyun Wang 	u16 func_id;
238000499a22SXiaoyun Wang 	int ret;
238100499a22SXiaoyun Wang 
238200499a22SXiaoyun Wang 	if (index >= HINIC_MAX_UC_MAC_ADDRS) {
238300499a22SXiaoyun Wang 		PMD_DRV_LOG(INFO, "Remove mac index(%u) is out of range",
238400499a22SXiaoyun Wang 			    index);
238500499a22SXiaoyun Wang 		return;
238600499a22SXiaoyun Wang 	}
238700499a22SXiaoyun Wang 
238800499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
238900499a22SXiaoyun Wang 	ret = hinic_del_mac(nic_dev->hwdev,
239000499a22SXiaoyun Wang 			    dev->data->mac_addrs[index].addr_bytes, 0, func_id);
239100499a22SXiaoyun Wang 	if (ret)
239200499a22SXiaoyun Wang 		return;
239300499a22SXiaoyun Wang 
239400499a22SXiaoyun Wang 	memset(&dev->data->mac_addrs[index], 0, sizeof(struct rte_ether_addr));
239500499a22SXiaoyun Wang }
239600499a22SXiaoyun Wang 
239700499a22SXiaoyun Wang /**
239800499a22SXiaoyun Wang  * DPDK callback to add a MAC address.
239900499a22SXiaoyun Wang  *
240000499a22SXiaoyun Wang  * @param dev
240100499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
240200499a22SXiaoyun Wang  * @param mac_addr
24034f1af3cbSXiaoyun Wang  *   Pointer to MAC address
240400499a22SXiaoyun Wang  * @param index
24054f1af3cbSXiaoyun Wang  *   MAC address index, should less than 128.
240600499a22SXiaoyun Wang  * @param vmdq
24074f1af3cbSXiaoyun Wang  *   VMDq pool index(not used).
240800499a22SXiaoyun Wang  *
240900499a22SXiaoyun Wang  * @return
24104f1af3cbSXiaoyun Wang  *   0 on success, negative error value otherwise.
241100499a22SXiaoyun Wang  */
241200499a22SXiaoyun Wang static int hinic_mac_addr_add(struct rte_eth_dev *dev,
241300499a22SXiaoyun Wang 			      struct rte_ether_addr *mac_addr, uint32_t index,
241400499a22SXiaoyun Wang 			      __rte_unused uint32_t vmdq)
241500499a22SXiaoyun Wang {
241600499a22SXiaoyun Wang 	struct hinic_nic_dev  *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
241700499a22SXiaoyun Wang 	unsigned int i;
241800499a22SXiaoyun Wang 	u16 func_id;
241900499a22SXiaoyun Wang 	int ret;
242000499a22SXiaoyun Wang 
242100499a22SXiaoyun Wang 	if (index >= HINIC_MAX_UC_MAC_ADDRS) {
24224f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(INFO, "Add mac index(%u) is out of range", index);
242300499a22SXiaoyun Wang 		return -EINVAL;
242400499a22SXiaoyun Wang 	}
242500499a22SXiaoyun Wang 
242600499a22SXiaoyun Wang 	/* First, make sure this address isn't already configured. */
242700499a22SXiaoyun Wang 	for (i = 0; (i != HINIC_MAX_UC_MAC_ADDRS); ++i) {
242800499a22SXiaoyun Wang 		/* Skip this index, it's going to be reconfigured. */
242900499a22SXiaoyun Wang 		if (i == index)
243000499a22SXiaoyun Wang 			continue;
243100499a22SXiaoyun Wang 
243200499a22SXiaoyun Wang 		if (memcmp(&dev->data->mac_addrs[i],
243300499a22SXiaoyun Wang 			mac_addr, sizeof(*mac_addr)))
243400499a22SXiaoyun Wang 			continue;
243500499a22SXiaoyun Wang 
243600499a22SXiaoyun Wang 		PMD_DRV_LOG(INFO, "MAC address already configured");
243700499a22SXiaoyun Wang 		return -EADDRINUSE;
243800499a22SXiaoyun Wang 	}
243900499a22SXiaoyun Wang 
244000499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
244100499a22SXiaoyun Wang 	ret = hinic_set_mac(nic_dev->hwdev, mac_addr->addr_bytes, 0, func_id);
244200499a22SXiaoyun Wang 	if (ret)
244300499a22SXiaoyun Wang 		return ret;
244400499a22SXiaoyun Wang 
244500499a22SXiaoyun Wang 	dev->data->mac_addrs[index] = *mac_addr;
244600499a22SXiaoyun Wang 	return 0;
244700499a22SXiaoyun Wang }
244800499a22SXiaoyun Wang 
244900499a22SXiaoyun Wang /**
245000499a22SXiaoyun Wang  *  DPDK callback to set multicast mac address
245100499a22SXiaoyun Wang  *
245200499a22SXiaoyun Wang  * @param dev
245300499a22SXiaoyun Wang  *   Pointer to Ethernet device structure.
245400499a22SXiaoyun Wang  * @param mc_addr_set
245500499a22SXiaoyun Wang  *   Pointer to multicast mac address
245600499a22SXiaoyun Wang  * @param nb_mc_addr
245700499a22SXiaoyun Wang  *   mc addr count
245800499a22SXiaoyun Wang  * @return
245900499a22SXiaoyun Wang  *   0 on success, negative error value otherwise.
246000499a22SXiaoyun Wang  */
246100499a22SXiaoyun Wang static int hinic_set_mc_addr_list(struct rte_eth_dev *dev,
246200499a22SXiaoyun Wang 				  struct rte_ether_addr *mc_addr_set,
246300499a22SXiaoyun Wang 				  uint32_t nb_mc_addr)
246400499a22SXiaoyun Wang {
246500499a22SXiaoyun Wang 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
246600499a22SXiaoyun Wang 	u16 func_id;
246700499a22SXiaoyun Wang 	int ret;
246800499a22SXiaoyun Wang 	u32 i;
246900499a22SXiaoyun Wang 
247000499a22SXiaoyun Wang 	func_id = hinic_global_func_id(nic_dev->hwdev);
247100499a22SXiaoyun Wang 
247200499a22SXiaoyun Wang 	/* delete old multi_cast addrs firstly */
247300499a22SXiaoyun Wang 	hinic_delete_mc_addr_list(nic_dev);
247400499a22SXiaoyun Wang 
247500499a22SXiaoyun Wang 	if (nb_mc_addr > HINIC_MAX_MC_MAC_ADDRS)
247600499a22SXiaoyun Wang 		goto allmulti;
247700499a22SXiaoyun Wang 
247800499a22SXiaoyun Wang 	for (i = 0; i < nb_mc_addr; i++) {
247900499a22SXiaoyun Wang 		ret = hinic_set_mac(nic_dev->hwdev, mc_addr_set[i].addr_bytes,
248000499a22SXiaoyun Wang 				    0, func_id);
248100499a22SXiaoyun Wang 		/* if add mc addr failed, set all multi_cast */
248200499a22SXiaoyun Wang 		if (ret) {
248300499a22SXiaoyun Wang 			hinic_delete_mc_addr_list(nic_dev);
248400499a22SXiaoyun Wang 			goto allmulti;
248500499a22SXiaoyun Wang 		}
248600499a22SXiaoyun Wang 
248700499a22SXiaoyun Wang 		rte_ether_addr_copy(&mc_addr_set[i], &nic_dev->mc_list[i]);
248800499a22SXiaoyun Wang 	}
248900499a22SXiaoyun Wang 
249000499a22SXiaoyun Wang 	return 0;
249100499a22SXiaoyun Wang 
249200499a22SXiaoyun Wang allmulti:
249300499a22SXiaoyun Wang 	hinic_dev_allmulticast_enable(dev);
249400499a22SXiaoyun Wang 
249500499a22SXiaoyun Wang 	return 0;
249600499a22SXiaoyun Wang }
2497cb7b6606SZiyang Xuan 
249873122b52SXiaoyun Wang /**
2499fb7ad441SThomas Monjalon  * DPDK callback to get flow operations
250073122b52SXiaoyun Wang  *
250173122b52SXiaoyun Wang  * @param dev
250273122b52SXiaoyun Wang  *   Pointer to Ethernet device structure.
2503fb7ad441SThomas Monjalon  * @param ops
250473122b52SXiaoyun Wang  *   Pointer to operation-specific structure.
250573122b52SXiaoyun Wang  *
250673122b52SXiaoyun Wang  * @return
2507f372a65fSXiaoyun Wang  *   0 on success, negative error value otherwise.
250873122b52SXiaoyun Wang  */
2509fb7ad441SThomas Monjalon static int hinic_dev_flow_ops_get(struct rte_eth_dev *dev __rte_unused,
2510fb7ad441SThomas Monjalon 				  const struct rte_flow_ops **ops)
251173122b52SXiaoyun Wang {
2512fb7ad441SThomas Monjalon 	*ops = &hinic_flow_ops;
251373122b52SXiaoyun Wang 	return 0;
251473122b52SXiaoyun Wang }
251573122b52SXiaoyun Wang 
251664727024SZiyang Xuan static int hinic_set_default_pause_feature(struct hinic_nic_dev *nic_dev)
251764727024SZiyang Xuan {
251864727024SZiyang Xuan 	struct nic_pause_config pause_config = {0};
2519ef6f2f5cSXiaoyun Wang 	int err;
252064727024SZiyang Xuan 
252164727024SZiyang Xuan 	pause_config.auto_neg = 0;
252264727024SZiyang Xuan 	pause_config.rx_pause = HINIC_DEFAUT_PAUSE_CONFIG;
252364727024SZiyang Xuan 	pause_config.tx_pause = HINIC_DEFAUT_PAUSE_CONFIG;
252464727024SZiyang Xuan 
2525ef6f2f5cSXiaoyun Wang 	err = hinic_set_pause_config(nic_dev->hwdev, pause_config);
2526ef6f2f5cSXiaoyun Wang 	if (err)
2527ef6f2f5cSXiaoyun Wang 		return err;
2528ef6f2f5cSXiaoyun Wang 
2529ef6f2f5cSXiaoyun Wang 	nic_dev->pause_set = true;
2530ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.auto_neg = pause_config.auto_neg;
2531ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.rx_pause = pause_config.rx_pause;
2532ef6f2f5cSXiaoyun Wang 	nic_dev->nic_pause.tx_pause = pause_config.tx_pause;
2533ef6f2f5cSXiaoyun Wang 
2534ef6f2f5cSXiaoyun Wang 	return 0;
253564727024SZiyang Xuan }
253664727024SZiyang Xuan 
253764727024SZiyang Xuan static int hinic_set_default_dcb_feature(struct hinic_nic_dev *nic_dev)
253864727024SZiyang Xuan {
253964727024SZiyang Xuan 	u8 up_tc[HINIC_DCB_UP_MAX] = {0};
254064727024SZiyang Xuan 	u8 up_pgid[HINIC_DCB_UP_MAX] = {0};
254164727024SZiyang Xuan 	u8 up_bw[HINIC_DCB_UP_MAX] = {0};
254264727024SZiyang Xuan 	u8 pg_bw[HINIC_DCB_UP_MAX] = {0};
254364727024SZiyang Xuan 	u8 up_strict[HINIC_DCB_UP_MAX] = {0};
254464727024SZiyang Xuan 	int i = 0;
254564727024SZiyang Xuan 
254664727024SZiyang Xuan 	pg_bw[0] = 100;
254764727024SZiyang Xuan 	for (i = 0; i < HINIC_DCB_UP_MAX; i++)
254864727024SZiyang Xuan 		up_bw[i] = 100;
254964727024SZiyang Xuan 
255064727024SZiyang Xuan 	return hinic_dcb_set_ets(nic_dev->hwdev, up_tc, pg_bw,
255164727024SZiyang Xuan 					up_pgid, up_bw, up_strict);
255264727024SZiyang Xuan }
255364727024SZiyang Xuan 
2554d4002360SXiaoyun Wang static int hinic_pf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
2555d4002360SXiaoyun Wang {
2556d4002360SXiaoyun Wang 	u8 default_cos = 0;
2557d4002360SXiaoyun Wang 	u8 valid_cos_bitmap;
2558d4002360SXiaoyun Wang 	u8 i;
2559d4002360SXiaoyun Wang 
2560d4002360SXiaoyun Wang 	valid_cos_bitmap = hwdev->cfg_mgmt->svc_cap.valid_cos_bitmap;
2561d4002360SXiaoyun Wang 	if (!valid_cos_bitmap) {
2562*f665790aSDavid Marchand 		PMD_DRV_LOG(ERR, "PF has none cos to support");
2563d4002360SXiaoyun Wang 		return -EFAULT;
2564d4002360SXiaoyun Wang 	}
2565d4002360SXiaoyun Wang 
2566d4002360SXiaoyun Wang 	for (i = 0; i < NR_MAX_COS; i++) {
2567d4002360SXiaoyun Wang 		if (valid_cos_bitmap & BIT(i))
2568d4002360SXiaoyun Wang 			default_cos = i; /* Find max cos id as default cos */
2569d4002360SXiaoyun Wang 	}
2570d4002360SXiaoyun Wang 
2571d4002360SXiaoyun Wang 	*cos_id = default_cos;
2572d4002360SXiaoyun Wang 
2573d4002360SXiaoyun Wang 	return 0;
2574d4002360SXiaoyun Wang }
2575d4002360SXiaoyun Wang 
25766691acefSXiaoyun Wang static int hinic_init_default_cos(struct hinic_nic_dev *nic_dev)
257764727024SZiyang Xuan {
25786691acefSXiaoyun Wang 	u8 cos_id = 0;
25796691acefSXiaoyun Wang 	int err;
25806691acefSXiaoyun Wang 
25816691acefSXiaoyun Wang 	if (!HINIC_IS_VF(nic_dev->hwdev)) {
2582d4002360SXiaoyun Wang 		err = hinic_pf_get_default_cos(nic_dev->hwdev, &cos_id);
2583d4002360SXiaoyun Wang 		if (err) {
2584d4002360SXiaoyun Wang 			PMD_DRV_LOG(ERR, "Get PF default cos failed, err: %d",
2585d4002360SXiaoyun Wang 				    err);
2586d4002360SXiaoyun Wang 			return HINIC_ERROR;
2587d4002360SXiaoyun Wang 		}
25886691acefSXiaoyun Wang 	} else {
25896691acefSXiaoyun Wang 		err = hinic_vf_get_default_cos(nic_dev->hwdev, &cos_id);
25906691acefSXiaoyun Wang 		if (err) {
25916691acefSXiaoyun Wang 			PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d",
25926691acefSXiaoyun Wang 				    err);
25936691acefSXiaoyun Wang 			return HINIC_ERROR;
25946691acefSXiaoyun Wang 		}
2595d4002360SXiaoyun Wang 	}
25966691acefSXiaoyun Wang 
25976691acefSXiaoyun Wang 	nic_dev->default_cos = cos_id;
2598d4002360SXiaoyun Wang 
2599d4002360SXiaoyun Wang 	PMD_DRV_LOG(INFO, "Default cos %d", nic_dev->default_cos);
26006691acefSXiaoyun Wang 
26016691acefSXiaoyun Wang 	return 0;
260264727024SZiyang Xuan }
260364727024SZiyang Xuan 
260464727024SZiyang Xuan static int hinic_set_default_hw_feature(struct hinic_nic_dev *nic_dev)
260564727024SZiyang Xuan {
260664727024SZiyang Xuan 	int err;
260764727024SZiyang Xuan 
26086691acefSXiaoyun Wang 	err = hinic_init_default_cos(nic_dev);
26096691acefSXiaoyun Wang 	if (err)
26106691acefSXiaoyun Wang 		return err;
26116691acefSXiaoyun Wang 
26126691acefSXiaoyun Wang 	if (hinic_func_type(nic_dev->hwdev) == TYPE_VF)
26136691acefSXiaoyun Wang 		return 0;
261464727024SZiyang Xuan 
261564727024SZiyang Xuan 	/* Restore DCB configure to default status */
261664727024SZiyang Xuan 	err = hinic_set_default_dcb_feature(nic_dev);
261764727024SZiyang Xuan 	if (err)
261864727024SZiyang Xuan 		return err;
261964727024SZiyang Xuan 
262064727024SZiyang Xuan 	/* Set pause enable, and up will disable pfc. */
262164727024SZiyang Xuan 	err = hinic_set_default_pause_feature(nic_dev);
262264727024SZiyang Xuan 	if (err)
262364727024SZiyang Xuan 		return err;
262464727024SZiyang Xuan 
262564727024SZiyang Xuan 	err = hinic_reset_port_link_cfg(nic_dev->hwdev);
262664727024SZiyang Xuan 	if (err)
262764727024SZiyang Xuan 		return err;
262864727024SZiyang Xuan 
262964727024SZiyang Xuan 	err = hinic_set_link_status_follow(nic_dev->hwdev,
263064727024SZiyang Xuan 					   HINIC_LINK_FOLLOW_PORT);
263164727024SZiyang Xuan 	if (err == HINIC_MGMT_CMD_UNSUPPORTED)
263264727024SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Don't support to set link status follow phy port status");
263364727024SZiyang Xuan 	else if (err)
263464727024SZiyang Xuan 		return err;
263564727024SZiyang Xuan 
263664727024SZiyang Xuan 	return hinic_set_anti_attack(nic_dev->hwdev, true);
263764727024SZiyang Xuan }
263864727024SZiyang Xuan 
263964727024SZiyang Xuan static int32_t hinic_card_workmode_check(struct hinic_nic_dev *nic_dev)
264064727024SZiyang Xuan {
264164727024SZiyang Xuan 	struct hinic_board_info info = { 0 };
264264727024SZiyang Xuan 	int rc;
264364727024SZiyang Xuan 
26446691acefSXiaoyun Wang 	if (hinic_func_type(nic_dev->hwdev) == TYPE_VF)
26456691acefSXiaoyun Wang 		return 0;
26466691acefSXiaoyun Wang 
264764727024SZiyang Xuan 	rc = hinic_get_board_info(nic_dev->hwdev, &info);
264864727024SZiyang Xuan 	if (rc)
264964727024SZiyang Xuan 		return rc;
265064727024SZiyang Xuan 
265164727024SZiyang Xuan 	return (info.service_mode == HINIC_SERVICE_MODE_NIC ? HINIC_OK :
265264727024SZiyang Xuan 						HINIC_ERROR);
265364727024SZiyang Xuan }
265464727024SZiyang Xuan 
265564727024SZiyang Xuan static int hinic_copy_mempool_init(struct hinic_nic_dev *nic_dev)
265664727024SZiyang Xuan {
265764727024SZiyang Xuan 	nic_dev->cpy_mpool = rte_mempool_lookup(nic_dev->proc_dev_name);
265864727024SZiyang Xuan 	if (nic_dev->cpy_mpool == NULL) {
265964727024SZiyang Xuan 		nic_dev->cpy_mpool =
266064727024SZiyang Xuan 		rte_pktmbuf_pool_create(nic_dev->proc_dev_name,
266164727024SZiyang Xuan 					HINIC_COPY_MEMPOOL_DEPTH,
26626691acefSXiaoyun Wang 					0, 0,
266364727024SZiyang Xuan 					HINIC_COPY_MBUF_SIZE,
266464727024SZiyang Xuan 					rte_socket_id());
266564727024SZiyang Xuan 		if (!nic_dev->cpy_mpool) {
266664727024SZiyang Xuan 			PMD_DRV_LOG(ERR, "Create copy mempool failed, errno: %d, dev_name: %s",
266764727024SZiyang Xuan 				    rte_errno, nic_dev->proc_dev_name);
266864727024SZiyang Xuan 			return -ENOMEM;
266964727024SZiyang Xuan 		}
267064727024SZiyang Xuan 	}
267164727024SZiyang Xuan 
267264727024SZiyang Xuan 	return 0;
267364727024SZiyang Xuan }
267464727024SZiyang Xuan 
267564727024SZiyang Xuan static void hinic_copy_mempool_uninit(struct hinic_nic_dev *nic_dev)
267664727024SZiyang Xuan {
267764727024SZiyang Xuan 	rte_mempool_free(nic_dev->cpy_mpool);
267864727024SZiyang Xuan }
267964727024SZiyang Xuan 
268064727024SZiyang Xuan static int hinic_init_sw_rxtxqs(struct hinic_nic_dev *nic_dev)
268164727024SZiyang Xuan {
268264727024SZiyang Xuan 	u32 txq_size;
268364727024SZiyang Xuan 	u32 rxq_size;
268464727024SZiyang Xuan 
268564727024SZiyang Xuan 	/* allocate software txq array */
268664727024SZiyang Xuan 	txq_size = nic_dev->nic_cap.max_sqs * sizeof(*nic_dev->txqs);
268764727024SZiyang Xuan 	nic_dev->txqs = kzalloc_aligned(txq_size, GFP_KERNEL);
268864727024SZiyang Xuan 	if (!nic_dev->txqs) {
268964727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate txqs failed");
269064727024SZiyang Xuan 		return -ENOMEM;
269164727024SZiyang Xuan 	}
269264727024SZiyang Xuan 
269364727024SZiyang Xuan 	/* allocate software rxq array */
269464727024SZiyang Xuan 	rxq_size = nic_dev->nic_cap.max_rqs * sizeof(*nic_dev->rxqs);
269564727024SZiyang Xuan 	nic_dev->rxqs = kzalloc_aligned(rxq_size, GFP_KERNEL);
269664727024SZiyang Xuan 	if (!nic_dev->rxqs) {
269764727024SZiyang Xuan 		/* free txqs */
269864727024SZiyang Xuan 		kfree(nic_dev->txqs);
269964727024SZiyang Xuan 		nic_dev->txqs = NULL;
270064727024SZiyang Xuan 
270164727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate rxqs failed");
270264727024SZiyang Xuan 		return -ENOMEM;
270364727024SZiyang Xuan 	}
270464727024SZiyang Xuan 
270564727024SZiyang Xuan 	return HINIC_OK;
270664727024SZiyang Xuan }
270764727024SZiyang Xuan 
270864727024SZiyang Xuan static void hinic_deinit_sw_rxtxqs(struct hinic_nic_dev *nic_dev)
270964727024SZiyang Xuan {
271064727024SZiyang Xuan 	kfree(nic_dev->txqs);
271164727024SZiyang Xuan 	nic_dev->txqs = NULL;
271264727024SZiyang Xuan 
271364727024SZiyang Xuan 	kfree(nic_dev->rxqs);
271464727024SZiyang Xuan 	nic_dev->rxqs = NULL;
271564727024SZiyang Xuan }
271664727024SZiyang Xuan 
271764727024SZiyang Xuan static int hinic_nic_dev_create(struct rte_eth_dev *eth_dev)
271864727024SZiyang Xuan {
271964727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
272064727024SZiyang Xuan 				HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
272164727024SZiyang Xuan 	int rc;
272264727024SZiyang Xuan 
272364727024SZiyang Xuan 	nic_dev->hwdev = rte_zmalloc("hinic_hwdev", sizeof(*nic_dev->hwdev),
272464727024SZiyang Xuan 				     RTE_CACHE_LINE_SIZE);
272564727024SZiyang Xuan 	if (!nic_dev->hwdev) {
272664727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Allocate hinic hwdev memory failed, dev_name: %s",
272764727024SZiyang Xuan 			    eth_dev->data->name);
272864727024SZiyang Xuan 		return -ENOMEM;
272964727024SZiyang Xuan 	}
273064727024SZiyang Xuan 	nic_dev->hwdev->pcidev_hdl = RTE_ETH_DEV_TO_PCI(eth_dev);
273164727024SZiyang Xuan 
273264727024SZiyang Xuan 	/* init osdep*/
273364727024SZiyang Xuan 	rc = hinic_osdep_init(nic_dev->hwdev);
273464727024SZiyang Xuan 	if (rc) {
273564727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize os_dep failed, dev_name: %s",
273664727024SZiyang Xuan 			    eth_dev->data->name);
273764727024SZiyang Xuan 		goto init_osdep_fail;
273864727024SZiyang Xuan 	}
273964727024SZiyang Xuan 
274064727024SZiyang Xuan 	/* init_hwif */
274164727024SZiyang Xuan 	rc = hinic_hwif_res_init(nic_dev->hwdev);
274264727024SZiyang Xuan 	if (rc) {
274364727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize hwif failed, dev_name: %s",
274464727024SZiyang Xuan 			    eth_dev->data->name);
274564727024SZiyang Xuan 		goto init_hwif_fail;
274664727024SZiyang Xuan 	}
274764727024SZiyang Xuan 
274864727024SZiyang Xuan 	/* init_cfg_mgmt */
274964727024SZiyang Xuan 	rc = init_cfg_mgmt(nic_dev->hwdev);
275064727024SZiyang Xuan 	if (rc) {
275164727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize cfg_mgmt failed, dev_name: %s",
275264727024SZiyang Xuan 			    eth_dev->data->name);
275364727024SZiyang Xuan 		goto init_cfgmgnt_fail;
275464727024SZiyang Xuan 	}
275564727024SZiyang Xuan 
275664727024SZiyang Xuan 	/* init_aeqs */
275764727024SZiyang Xuan 	rc = hinic_comm_aeqs_init(nic_dev->hwdev);
275864727024SZiyang Xuan 	if (rc) {
275964727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize aeqs failed, dev_name: %s",
276064727024SZiyang Xuan 			    eth_dev->data->name);
276164727024SZiyang Xuan 		goto init_aeqs_fail;
276264727024SZiyang Xuan 	}
276364727024SZiyang Xuan 
276464727024SZiyang Xuan 	/* init_pf_to_mgnt */
276564727024SZiyang Xuan 	rc = hinic_comm_pf_to_mgmt_init(nic_dev->hwdev);
276664727024SZiyang Xuan 	if (rc) {
276764727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize pf_to_mgmt failed, dev_name: %s",
276864727024SZiyang Xuan 			    eth_dev->data->name);
276964727024SZiyang Xuan 		goto init_pf_to_mgmt_fail;
277064727024SZiyang Xuan 	}
277164727024SZiyang Xuan 
27726691acefSXiaoyun Wang 	/* init mailbox */
27736691acefSXiaoyun Wang 	rc = hinic_comm_func_to_func_init(nic_dev->hwdev);
27746691acefSXiaoyun Wang 	if (rc) {
27756691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Initialize func_to_func failed, dev_name: %s",
27766691acefSXiaoyun Wang 			    eth_dev->data->name);
27776691acefSXiaoyun Wang 		goto init_func_to_func_fail;
27786691acefSXiaoyun Wang 	}
27796691acefSXiaoyun Wang 
278064727024SZiyang Xuan 	rc = hinic_card_workmode_check(nic_dev);
278164727024SZiyang Xuan 	if (rc) {
278264727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Check card workmode failed, dev_name: %s",
278364727024SZiyang Xuan 			    eth_dev->data->name);
278464727024SZiyang Xuan 		goto workmode_check_fail;
278564727024SZiyang Xuan 	}
278664727024SZiyang Xuan 
278764727024SZiyang Xuan 	/* do l2nic reset to make chip clear */
278864727024SZiyang Xuan 	rc = hinic_l2nic_reset(nic_dev->hwdev);
278964727024SZiyang Xuan 	if (rc) {
279064727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Do l2nic reset failed, dev_name: %s",
279164727024SZiyang Xuan 			    eth_dev->data->name);
279264727024SZiyang Xuan 		goto l2nic_reset_fail;
279364727024SZiyang Xuan 	}
279464727024SZiyang Xuan 
279564727024SZiyang Xuan 	/* init dma and aeq msix attribute table */
279664727024SZiyang Xuan 	(void)hinic_init_attr_table(nic_dev->hwdev);
279764727024SZiyang Xuan 
279864727024SZiyang Xuan 	/* init_cmdqs */
279964727024SZiyang Xuan 	rc = hinic_comm_cmdqs_init(nic_dev->hwdev);
280064727024SZiyang Xuan 	if (rc) {
280164727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize cmdq failed, dev_name: %s",
280264727024SZiyang Xuan 			    eth_dev->data->name);
280364727024SZiyang Xuan 		goto init_cmdq_fail;
280464727024SZiyang Xuan 	}
280564727024SZiyang Xuan 
280664727024SZiyang Xuan 	/* set hardware state active */
280764727024SZiyang Xuan 	rc = hinic_activate_hwdev_state(nic_dev->hwdev);
280864727024SZiyang Xuan 	if (rc) {
280964727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize resources state failed, dev_name: %s",
281064727024SZiyang Xuan 			    eth_dev->data->name);
281164727024SZiyang Xuan 		goto init_resources_state_fail;
281264727024SZiyang Xuan 	}
281364727024SZiyang Xuan 
281464727024SZiyang Xuan 	/* init_capability */
281564727024SZiyang Xuan 	rc = hinic_init_capability(nic_dev->hwdev);
281664727024SZiyang Xuan 	if (rc) {
281764727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize capability failed, dev_name: %s",
281864727024SZiyang Xuan 			    eth_dev->data->name);
281964727024SZiyang Xuan 		goto init_cap_fail;
282064727024SZiyang Xuan 	}
282164727024SZiyang Xuan 
282264727024SZiyang Xuan 	/* get nic capability */
282313850e88SXiaoyun Wang 	if (!hinic_support_nic(nic_dev->hwdev, &nic_dev->nic_cap)) {
282413850e88SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hw doesn't support nic, dev_name: %s",
282513850e88SXiaoyun Wang 			    eth_dev->data->name);
282613850e88SXiaoyun Wang 		rc = -EINVAL;
282764727024SZiyang Xuan 		goto nic_check_fail;
282813850e88SXiaoyun Wang 	}
282964727024SZiyang Xuan 
283064727024SZiyang Xuan 	/* init root cla and function table */
283164727024SZiyang Xuan 	rc = hinic_init_nicio(nic_dev->hwdev);
283264727024SZiyang Xuan 	if (rc) {
283364727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize nic_io failed, dev_name: %s",
283464727024SZiyang Xuan 			    eth_dev->data->name);
283564727024SZiyang Xuan 		goto init_nicio_fail;
283664727024SZiyang Xuan 	}
283764727024SZiyang Xuan 
283864727024SZiyang Xuan 	/* init_software_txrxq */
283964727024SZiyang Xuan 	rc = hinic_init_sw_rxtxqs(nic_dev);
284064727024SZiyang Xuan 	if (rc) {
284164727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize sw_rxtxqs failed, dev_name: %s",
284264727024SZiyang Xuan 			    eth_dev->data->name);
284364727024SZiyang Xuan 		goto init_sw_rxtxqs_fail;
284464727024SZiyang Xuan 	}
284564727024SZiyang Xuan 
284664727024SZiyang Xuan 	rc = hinic_copy_mempool_init(nic_dev);
284764727024SZiyang Xuan 	if (rc) {
284864727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Create copy mempool failed, dev_name: %s",
284964727024SZiyang Xuan 			 eth_dev->data->name);
285064727024SZiyang Xuan 		goto init_mpool_fail;
285164727024SZiyang Xuan 	}
285264727024SZiyang Xuan 
285364727024SZiyang Xuan 	/* set hardware feature to default status */
285464727024SZiyang Xuan 	rc = hinic_set_default_hw_feature(nic_dev);
285564727024SZiyang Xuan 	if (rc) {
285664727024SZiyang Xuan 		PMD_DRV_LOG(ERR, "Initialize hardware default features failed, dev_name: %s",
285764727024SZiyang Xuan 			    eth_dev->data->name);
285864727024SZiyang Xuan 		goto set_default_hw_feature_fail;
285964727024SZiyang Xuan 	}
286064727024SZiyang Xuan 
286164727024SZiyang Xuan 	return 0;
286264727024SZiyang Xuan 
286364727024SZiyang Xuan set_default_hw_feature_fail:
286464727024SZiyang Xuan 	hinic_copy_mempool_uninit(nic_dev);
286564727024SZiyang Xuan 
286664727024SZiyang Xuan init_mpool_fail:
286764727024SZiyang Xuan 	hinic_deinit_sw_rxtxqs(nic_dev);
286864727024SZiyang Xuan 
286964727024SZiyang Xuan init_sw_rxtxqs_fail:
287064727024SZiyang Xuan 	hinic_deinit_nicio(nic_dev->hwdev);
287164727024SZiyang Xuan 
287264727024SZiyang Xuan nic_check_fail:
287364727024SZiyang Xuan init_nicio_fail:
287464727024SZiyang Xuan init_cap_fail:
287564727024SZiyang Xuan 	hinic_deactivate_hwdev_state(nic_dev->hwdev);
287664727024SZiyang Xuan 
287764727024SZiyang Xuan init_resources_state_fail:
287864727024SZiyang Xuan 	hinic_comm_cmdqs_free(nic_dev->hwdev);
287964727024SZiyang Xuan 
288064727024SZiyang Xuan init_cmdq_fail:
288164727024SZiyang Xuan l2nic_reset_fail:
288264727024SZiyang Xuan workmode_check_fail:
28836691acefSXiaoyun Wang 	hinic_comm_func_to_func_free(nic_dev->hwdev);
28846691acefSXiaoyun Wang 
28856691acefSXiaoyun Wang init_func_to_func_fail:
288664727024SZiyang Xuan 	hinic_comm_pf_to_mgmt_free(nic_dev->hwdev);
288764727024SZiyang Xuan 
288864727024SZiyang Xuan init_pf_to_mgmt_fail:
288964727024SZiyang Xuan 	hinic_comm_aeqs_free(nic_dev->hwdev);
289064727024SZiyang Xuan 
289164727024SZiyang Xuan init_aeqs_fail:
289264727024SZiyang Xuan 	free_cfg_mgmt(nic_dev->hwdev);
289364727024SZiyang Xuan 
289464727024SZiyang Xuan init_cfgmgnt_fail:
289564727024SZiyang Xuan 	hinic_hwif_res_free(nic_dev->hwdev);
289664727024SZiyang Xuan 
289764727024SZiyang Xuan init_hwif_fail:
289864727024SZiyang Xuan 	hinic_osdep_deinit(nic_dev->hwdev);
289964727024SZiyang Xuan 
290064727024SZiyang Xuan init_osdep_fail:
290164727024SZiyang Xuan 	rte_free(nic_dev->hwdev);
290264727024SZiyang Xuan 	nic_dev->hwdev = NULL;
290364727024SZiyang Xuan 
290464727024SZiyang Xuan 	return rc;
290564727024SZiyang Xuan }
290664727024SZiyang Xuan 
290764727024SZiyang Xuan static void hinic_nic_dev_destroy(struct rte_eth_dev *eth_dev)
290864727024SZiyang Xuan {
290964727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev =
291064727024SZiyang Xuan 			HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
291164727024SZiyang Xuan 
291264727024SZiyang Xuan 	(void)hinic_set_link_status_follow(nic_dev->hwdev,
291364727024SZiyang Xuan 					   HINIC_LINK_FOLLOW_DEFAULT);
291464727024SZiyang Xuan 	hinic_copy_mempool_uninit(nic_dev);
291564727024SZiyang Xuan 	hinic_deinit_sw_rxtxqs(nic_dev);
291664727024SZiyang Xuan 	hinic_deinit_nicio(nic_dev->hwdev);
291764727024SZiyang Xuan 	hinic_deactivate_hwdev_state(nic_dev->hwdev);
291864727024SZiyang Xuan 	hinic_comm_cmdqs_free(nic_dev->hwdev);
29196691acefSXiaoyun Wang 	hinic_comm_func_to_func_free(nic_dev->hwdev);
292064727024SZiyang Xuan 	hinic_comm_pf_to_mgmt_free(nic_dev->hwdev);
292164727024SZiyang Xuan 	hinic_comm_aeqs_free(nic_dev->hwdev);
292264727024SZiyang Xuan 	free_cfg_mgmt(nic_dev->hwdev);
292364727024SZiyang Xuan 	hinic_hwif_res_free(nic_dev->hwdev);
292464727024SZiyang Xuan 	hinic_osdep_deinit(nic_dev->hwdev);
292564727024SZiyang Xuan 	rte_free(nic_dev->hwdev);
292664727024SZiyang Xuan 	nic_dev->hwdev = NULL;
292764727024SZiyang Xuan }
292864727024SZiyang Xuan 
292964727024SZiyang Xuan /**
29301d09792aSZiyang Xuan  * DPDK callback to close the device.
29311d09792aSZiyang Xuan  *
29321d09792aSZiyang Xuan  * @param dev
29331d09792aSZiyang Xuan  *   Pointer to Ethernet device structure.
29341d09792aSZiyang Xuan  */
2935b142387bSThomas Monjalon static int hinic_dev_close(struct rte_eth_dev *dev)
29361d09792aSZiyang Xuan {
293764727024SZiyang Xuan 	struct hinic_nic_dev *nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(dev);
293862024eb8SIvan Ilchenko 	int ret;
293964727024SZiyang Xuan 
294030410493SThomas Monjalon 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
294130410493SThomas Monjalon 		return 0;
294230410493SThomas Monjalon 
29430371535dSJoyce Kong 	if (rte_bit_relaxed_test_and_set32(HINIC_DEV_CLOSE,
29440371535dSJoyce Kong 					   &nic_dev->dev_status)) {
294564727024SZiyang Xuan 		PMD_DRV_LOG(WARNING, "Device %s already closed",
294664727024SZiyang Xuan 			    dev->data->name);
2947b142387bSThomas Monjalon 		return 0;
294864727024SZiyang Xuan 	}
294964727024SZiyang Xuan 
29502c473729SZiyang Xuan 	/* stop device first */
295162024eb8SIvan Ilchenko 	ret = hinic_dev_stop(dev);
29522c473729SZiyang Xuan 
295364727024SZiyang Xuan 	/* rx_cqe, rx_info */
295464727024SZiyang Xuan 	hinic_free_all_rx_resources(dev);
295564727024SZiyang Xuan 
295664727024SZiyang Xuan 	/* tx_info */
295764727024SZiyang Xuan 	hinic_free_all_tx_resources(dev);
295864727024SZiyang Xuan 
295964727024SZiyang Xuan 	/* free wq, pi_dma_addr */
296064727024SZiyang Xuan 	hinic_free_all_rq(nic_dev);
296164727024SZiyang Xuan 
296264727024SZiyang Xuan 	/* free wq, db_addr */
296364727024SZiyang Xuan 	hinic_free_all_sq(nic_dev);
296464727024SZiyang Xuan 
296564727024SZiyang Xuan 	/* deinit mac vlan tbl */
296664727024SZiyang Xuan 	hinic_deinit_mac_addr(dev);
2967fdba3bf1SXiaoyun Wang 	hinic_remove_all_vlanid(dev);
296864727024SZiyang Xuan 
296964727024SZiyang Xuan 	/* disable hardware and uio interrupt */
297064727024SZiyang Xuan 	hinic_disable_interrupt(dev);
297164727024SZiyang Xuan 
2972511b7371SGuoyang Zhou 	/* destroy rx mode mutex */
2973511b7371SGuoyang Zhou 	hinic_mutex_destroy(&nic_dev->rx_mode_mutex);
2974511b7371SGuoyang Zhou 
297564727024SZiyang Xuan 	/* deinit nic hardware device */
297664727024SZiyang Xuan 	hinic_nic_dev_destroy(dev);
2977b142387bSThomas Monjalon 
297862024eb8SIvan Ilchenko 	return ret;
29791d09792aSZiyang Xuan }
29801d09792aSZiyang Xuan 
29811d09792aSZiyang Xuan static const struct eth_dev_ops hinic_pmd_ops = {
298264727024SZiyang Xuan 	.dev_configure                 = hinic_dev_configure,
29831d09792aSZiyang Xuan 	.dev_infos_get                 = hinic_dev_infos_get,
2984dbf524abSXiaoyun Wang 	.fw_version_get                = hinic_fw_version_get,
29852c473729SZiyang Xuan 	.rx_queue_setup                = hinic_rx_queue_setup,
29862c473729SZiyang Xuan 	.tx_queue_setup                = hinic_tx_queue_setup,
29872c473729SZiyang Xuan 	.dev_start                     = hinic_dev_start,
298854ac3386SXiaoyun Wang 	.dev_set_link_up               = hinic_dev_set_link_up,
298954ac3386SXiaoyun Wang 	.dev_set_link_down             = hinic_dev_set_link_down,
29902c473729SZiyang Xuan 	.link_update                   = hinic_link_update,
29912c473729SZiyang Xuan 	.rx_queue_release              = hinic_rx_queue_release,
29922c473729SZiyang Xuan 	.tx_queue_release              = hinic_tx_queue_release,
29932c473729SZiyang Xuan 	.dev_stop                      = hinic_dev_stop,
299464727024SZiyang Xuan 	.dev_close                     = hinic_dev_close,
29958260eba6SXiaoyun Wang 	.mtu_set                       = hinic_dev_set_mtu,
2996fdba3bf1SXiaoyun Wang 	.vlan_filter_set               = hinic_vlan_filter_set,
2997fdba3bf1SXiaoyun Wang 	.vlan_offload_set              = hinic_vlan_offload_set,
29988260eba6SXiaoyun Wang 	.allmulticast_enable           = hinic_dev_allmulticast_enable,
29998260eba6SXiaoyun Wang 	.allmulticast_disable          = hinic_dev_allmulticast_disable,
3000cb7b6606SZiyang Xuan 	.promiscuous_enable            = hinic_dev_promiscuous_enable,
3001cb7b6606SZiyang Xuan 	.promiscuous_disable           = hinic_dev_promiscuous_disable,
3002ef6f2f5cSXiaoyun Wang 	.flow_ctrl_get                 = hinic_flow_ctrl_get,
3003ef6f2f5cSXiaoyun Wang 	.flow_ctrl_set                 = hinic_flow_ctrl_set,
3004cb7b6606SZiyang Xuan 	.rss_hash_update               = hinic_rss_hash_update,
3005cb7b6606SZiyang Xuan 	.rss_hash_conf_get             = hinic_rss_conf_get,
3006cb7b6606SZiyang Xuan 	.reta_update                   = hinic_rss_indirtbl_update,
3007cb7b6606SZiyang Xuan 	.reta_query                    = hinic_rss_indirtbl_query,
3008cb7b6606SZiyang Xuan 	.stats_get                     = hinic_dev_stats_get,
3009cb7b6606SZiyang Xuan 	.stats_reset                   = hinic_dev_stats_reset,
3010cb7b6606SZiyang Xuan 	.xstats_get                    = hinic_dev_xstats_get,
3011cb7b6606SZiyang Xuan 	.xstats_reset                  = hinic_dev_xstats_reset,
3012cb7b6606SZiyang Xuan 	.xstats_get_names              = hinic_dev_xstats_get_names,
3013483b4817SXiaoyun Wang 	.rxq_info_get                  = hinic_rxq_info_get,
3014483b4817SXiaoyun Wang 	.txq_info_get                  = hinic_txq_info_get,
301500499a22SXiaoyun Wang 	.mac_addr_set                  = hinic_set_mac_addr,
301600499a22SXiaoyun Wang 	.mac_addr_remove               = hinic_mac_addr_remove,
301700499a22SXiaoyun Wang 	.mac_addr_add                  = hinic_mac_addr_add,
301800499a22SXiaoyun Wang 	.set_mc_addr_list              = hinic_set_mc_addr_list,
3019fb7ad441SThomas Monjalon 	.flow_ops_get                  = hinic_dev_flow_ops_get,
30201d09792aSZiyang Xuan };
30211d09792aSZiyang Xuan 
30226691acefSXiaoyun Wang static const struct eth_dev_ops hinic_pmd_vf_ops = {
30236691acefSXiaoyun Wang 	.dev_configure                 = hinic_dev_configure,
30246691acefSXiaoyun Wang 	.dev_infos_get                 = hinic_dev_infos_get,
3025dbf524abSXiaoyun Wang 	.fw_version_get                = hinic_fw_version_get,
30266691acefSXiaoyun Wang 	.rx_queue_setup                = hinic_rx_queue_setup,
30276691acefSXiaoyun Wang 	.tx_queue_setup                = hinic_tx_queue_setup,
30286691acefSXiaoyun Wang 	.dev_start                     = hinic_dev_start,
30296691acefSXiaoyun Wang 	.link_update                   = hinic_link_update,
30306691acefSXiaoyun Wang 	.rx_queue_release              = hinic_rx_queue_release,
30316691acefSXiaoyun Wang 	.tx_queue_release              = hinic_tx_queue_release,
30326691acefSXiaoyun Wang 	.dev_stop                      = hinic_dev_stop,
30336691acefSXiaoyun Wang 	.dev_close                     = hinic_dev_close,
30348260eba6SXiaoyun Wang 	.mtu_set                       = hinic_dev_set_mtu,
3035fdba3bf1SXiaoyun Wang 	.vlan_filter_set               = hinic_vlan_filter_set,
3036fdba3bf1SXiaoyun Wang 	.vlan_offload_set              = hinic_vlan_offload_set,
30378260eba6SXiaoyun Wang 	.allmulticast_enable           = hinic_dev_allmulticast_enable,
30388260eba6SXiaoyun Wang 	.allmulticast_disable          = hinic_dev_allmulticast_disable,
30396691acefSXiaoyun Wang 	.rss_hash_update               = hinic_rss_hash_update,
30406691acefSXiaoyun Wang 	.rss_hash_conf_get             = hinic_rss_conf_get,
30416691acefSXiaoyun Wang 	.reta_update                   = hinic_rss_indirtbl_update,
30426691acefSXiaoyun Wang 	.reta_query                    = hinic_rss_indirtbl_query,
30436691acefSXiaoyun Wang 	.stats_get                     = hinic_dev_stats_get,
30446691acefSXiaoyun Wang 	.stats_reset                   = hinic_dev_stats_reset,
30456691acefSXiaoyun Wang 	.xstats_get                    = hinic_dev_xstats_get,
30466691acefSXiaoyun Wang 	.xstats_reset                  = hinic_dev_xstats_reset,
30476691acefSXiaoyun Wang 	.xstats_get_names              = hinic_dev_xstats_get_names,
3048483b4817SXiaoyun Wang 	.rxq_info_get                  = hinic_rxq_info_get,
3049483b4817SXiaoyun Wang 	.txq_info_get                  = hinic_txq_info_get,
305000499a22SXiaoyun Wang 	.mac_addr_set                  = hinic_set_mac_addr,
305100499a22SXiaoyun Wang 	.mac_addr_remove               = hinic_mac_addr_remove,
305200499a22SXiaoyun Wang 	.mac_addr_add                  = hinic_mac_addr_add,
305300499a22SXiaoyun Wang 	.set_mc_addr_list              = hinic_set_mc_addr_list,
3054fb7ad441SThomas Monjalon 	.flow_ops_get                  = hinic_dev_flow_ops_get,
30556691acefSXiaoyun Wang };
30566691acefSXiaoyun Wang 
30574c670dfaSGuoyang Zhou static const struct eth_dev_ops hinic_dev_sec_ops = {
30584c670dfaSGuoyang Zhou 	.dev_infos_get                 = hinic_dev_infos_get,
30594c670dfaSGuoyang Zhou };
30604c670dfaSGuoyang Zhou 
30616691acefSXiaoyun Wang static int hinic_func_init(struct rte_eth_dev *eth_dev)
30626691acefSXiaoyun Wang {
30636691acefSXiaoyun Wang 	struct rte_pci_device *pci_dev;
30646691acefSXiaoyun Wang 	struct rte_ether_addr *eth_addr;
30656691acefSXiaoyun Wang 	struct hinic_nic_dev *nic_dev;
30661742421bSXiaoyun Wang 	struct hinic_filter_info *filter_info;
30671fe89aa3SXiaoyun Wang 	struct hinic_tcam_info *tcam_info;
306800499a22SXiaoyun Wang 	u32 mac_size;
30696691acefSXiaoyun Wang 	int rc;
30706691acefSXiaoyun Wang 
30716691acefSXiaoyun Wang 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
30726691acefSXiaoyun Wang 
30736691acefSXiaoyun Wang 	/* EAL is SECONDARY and eth_dev is already created */
30746691acefSXiaoyun Wang 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
30754c670dfaSGuoyang Zhou 		eth_dev->dev_ops = &hinic_dev_sec_ops;
307666f64dd6SXiaoyun Wang 		PMD_DRV_LOG(INFO, "Initialize %s in secondary process",
30776691acefSXiaoyun Wang 			    eth_dev->data->name);
30786691acefSXiaoyun Wang 
307966f64dd6SXiaoyun Wang 		return 0;
30806691acefSXiaoyun Wang 	}
30816691acefSXiaoyun Wang 
3082f30e69b4SFerruh Yigit 	eth_dev->data->dev_flags |= RTE_ETH_DEV_AUTOFILL_QUEUE_XSTATS;
3083f30e69b4SFerruh Yigit 
30846691acefSXiaoyun Wang 	nic_dev = HINIC_ETH_DEV_TO_PRIVATE_NIC_DEV(eth_dev);
30856691acefSXiaoyun Wang 	memset(nic_dev, 0, sizeof(*nic_dev));
30866691acefSXiaoyun Wang 
30876691acefSXiaoyun Wang 	snprintf(nic_dev->proc_dev_name,
30886691acefSXiaoyun Wang 		 sizeof(nic_dev->proc_dev_name),
30892fc03b23SThomas Monjalon 		 "hinic-" PCI_PRI_FMT,
30906691acefSXiaoyun Wang 		 pci_dev->addr.domain, pci_dev->addr.bus,
30916691acefSXiaoyun Wang 		 pci_dev->addr.devid, pci_dev->addr.function);
30926691acefSXiaoyun Wang 
30936691acefSXiaoyun Wang 	/* alloc mac_addrs */
309400499a22SXiaoyun Wang 	mac_size = HINIC_MAX_UC_MAC_ADDRS * sizeof(struct rte_ether_addr);
309500499a22SXiaoyun Wang 	eth_addr = rte_zmalloc("hinic_mac", mac_size, 0);
30966691acefSXiaoyun Wang 	if (!eth_addr) {
30976691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Allocate ethernet addresses' memory failed, dev_name: %s",
30986691acefSXiaoyun Wang 			    eth_dev->data->name);
30996691acefSXiaoyun Wang 		rc = -ENOMEM;
31006691acefSXiaoyun Wang 		goto eth_addr_fail;
31016691acefSXiaoyun Wang 	}
31026691acefSXiaoyun Wang 	eth_dev->data->mac_addrs = eth_addr;
31036691acefSXiaoyun Wang 
310400499a22SXiaoyun Wang 	mac_size = HINIC_MAX_MC_MAC_ADDRS * sizeof(struct rte_ether_addr);
310500499a22SXiaoyun Wang 	nic_dev->mc_list = rte_zmalloc("hinic_mc", mac_size, 0);
310600499a22SXiaoyun Wang 	if (!nic_dev->mc_list) {
310700499a22SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Allocate mcast address' memory failed, dev_name: %s",
310800499a22SXiaoyun Wang 			    eth_dev->data->name);
310900499a22SXiaoyun Wang 		rc = -ENOMEM;
311000499a22SXiaoyun Wang 		goto mc_addr_fail;
311100499a22SXiaoyun Wang 	}
311200499a22SXiaoyun Wang 
31136691acefSXiaoyun Wang 	/* create hardware nic_device */
31146691acefSXiaoyun Wang 	rc = hinic_nic_dev_create(eth_dev);
31156691acefSXiaoyun Wang 	if (rc) {
31166691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Create nic device failed, dev_name: %s",
31176691acefSXiaoyun Wang 			    eth_dev->data->name);
31186691acefSXiaoyun Wang 		goto create_nic_dev_fail;
31196691acefSXiaoyun Wang 	}
31206691acefSXiaoyun Wang 
31216691acefSXiaoyun Wang 	if (HINIC_IS_VF(nic_dev->hwdev))
31226691acefSXiaoyun Wang 		eth_dev->dev_ops = &hinic_pmd_vf_ops;
31236691acefSXiaoyun Wang 	else
31246691acefSXiaoyun Wang 		eth_dev->dev_ops = &hinic_pmd_ops;
31256691acefSXiaoyun Wang 
31266691acefSXiaoyun Wang 	rc = hinic_init_mac_addr(eth_dev);
31276691acefSXiaoyun Wang 	if (rc) {
31286691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Initialize mac table failed, dev_name: %s",
31296691acefSXiaoyun Wang 			    eth_dev->data->name);
31306691acefSXiaoyun Wang 		goto init_mac_fail;
31316691acefSXiaoyun Wang 	}
31326691acefSXiaoyun Wang 
31336691acefSXiaoyun Wang 	/* register callback func to eal lib */
3134d61138d4SHarman Kalra 	rc = rte_intr_callback_register(pci_dev->intr_handle,
31356691acefSXiaoyun Wang 					hinic_dev_interrupt_handler,
31366691acefSXiaoyun Wang 					(void *)eth_dev);
31376691acefSXiaoyun Wang 	if (rc) {
31386691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Register rte interrupt callback failed, dev_name: %s",
31396691acefSXiaoyun Wang 			    eth_dev->data->name);
31406691acefSXiaoyun Wang 		goto reg_intr_cb_fail;
31416691acefSXiaoyun Wang 	}
31426691acefSXiaoyun Wang 
31436691acefSXiaoyun Wang 	/* enable uio/vfio intr/eventfd mapping */
3144d61138d4SHarman Kalra 	rc = rte_intr_enable(pci_dev->intr_handle);
31456691acefSXiaoyun Wang 	if (rc) {
31466691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Enable rte interrupt failed, dev_name: %s",
31476691acefSXiaoyun Wang 			    eth_dev->data->name);
31486691acefSXiaoyun Wang 		goto enable_intr_fail;
31496691acefSXiaoyun Wang 	}
31500371535dSJoyce Kong 	rte_bit_relaxed_set32(HINIC_DEV_INTR_EN, &nic_dev->dev_status);
31516691acefSXiaoyun Wang 
3152224cff4bSXiaoyun Wang 	hinic_mutex_init(&nic_dev->rx_mode_mutex, NULL);
3153224cff4bSXiaoyun Wang 
31541742421bSXiaoyun Wang 	/* initialize filter info */
31551742421bSXiaoyun Wang 	filter_info = &nic_dev->filter;
31561fe89aa3SXiaoyun Wang 	tcam_info = &nic_dev->tcam;
31571742421bSXiaoyun Wang 	memset(filter_info, 0, sizeof(struct hinic_filter_info));
31581fe89aa3SXiaoyun Wang 	memset(tcam_info, 0, sizeof(struct hinic_tcam_info));
31591742421bSXiaoyun Wang 	/* initialize 5tuple filter list */
31601742421bSXiaoyun Wang 	TAILQ_INIT(&filter_info->fivetuple_list);
31611fe89aa3SXiaoyun Wang 	TAILQ_INIT(&tcam_info->tcam_list);
31621742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->filter_ntuple_list);
31631742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->filter_ethertype_list);
31641742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->filter_fdir_rule_list);
31651742421bSXiaoyun Wang 	TAILQ_INIT(&nic_dev->hinic_flow_list);
31661742421bSXiaoyun Wang 
31670371535dSJoyce Kong 	rte_bit_relaxed_set32(HINIC_DEV_INIT, &nic_dev->dev_status);
31686691acefSXiaoyun Wang 	PMD_DRV_LOG(INFO, "Initialize %s in primary successfully",
31696691acefSXiaoyun Wang 		    eth_dev->data->name);
31706691acefSXiaoyun Wang 
31716691acefSXiaoyun Wang 	return 0;
31726691acefSXiaoyun Wang 
31736691acefSXiaoyun Wang enable_intr_fail:
3174d61138d4SHarman Kalra 	(void)rte_intr_callback_unregister(pci_dev->intr_handle,
31756691acefSXiaoyun Wang 					   hinic_dev_interrupt_handler,
31766691acefSXiaoyun Wang 					   (void *)eth_dev);
31776691acefSXiaoyun Wang 
31786691acefSXiaoyun Wang reg_intr_cb_fail:
31796691acefSXiaoyun Wang 	hinic_deinit_mac_addr(eth_dev);
31806691acefSXiaoyun Wang 
31816691acefSXiaoyun Wang init_mac_fail:
31826691acefSXiaoyun Wang 	eth_dev->dev_ops = NULL;
31836691acefSXiaoyun Wang 	hinic_nic_dev_destroy(eth_dev);
31846691acefSXiaoyun Wang 
31856691acefSXiaoyun Wang create_nic_dev_fail:
318600499a22SXiaoyun Wang 	rte_free(nic_dev->mc_list);
318700499a22SXiaoyun Wang 	nic_dev->mc_list = NULL;
318800499a22SXiaoyun Wang 
318900499a22SXiaoyun Wang mc_addr_fail:
31906691acefSXiaoyun Wang 	rte_free(eth_addr);
31916691acefSXiaoyun Wang 	eth_dev->data->mac_addrs = NULL;
31926691acefSXiaoyun Wang 
31936691acefSXiaoyun Wang eth_addr_fail:
31946691acefSXiaoyun Wang 	PMD_DRV_LOG(ERR, "Initialize %s in primary failed",
31956691acefSXiaoyun Wang 		    eth_dev->data->name);
31966691acefSXiaoyun Wang 	return rc;
31976691acefSXiaoyun Wang }
31986691acefSXiaoyun Wang 
31991d09792aSZiyang Xuan static int hinic_dev_init(struct rte_eth_dev *eth_dev)
32001d09792aSZiyang Xuan {
32011d09792aSZiyang Xuan 	struct rte_pci_device *pci_dev;
32021d09792aSZiyang Xuan 
32031d09792aSZiyang Xuan 	pci_dev = RTE_ETH_DEV_TO_PCI(eth_dev);
32041d09792aSZiyang Xuan 
32052fc03b23SThomas Monjalon 	PMD_DRV_LOG(INFO, "Initializing pf hinic-" PCI_PRI_FMT " in %s process",
32061d09792aSZiyang Xuan 		    pci_dev->addr.domain, pci_dev->addr.bus,
32071d09792aSZiyang Xuan 		    pci_dev->addr.devid, pci_dev->addr.function,
32081d09792aSZiyang Xuan 		    (rte_eal_process_type() == RTE_PROC_PRIMARY) ?
32091d09792aSZiyang Xuan 		    "primary" : "secondary");
32101d09792aSZiyang Xuan 
32116691acefSXiaoyun Wang 	/* rte_eth_dev rx_burst and tx_burst */
3212076221c8SZiyang Xuan 	eth_dev->rx_pkt_burst = hinic_recv_pkts;
3213076221c8SZiyang Xuan 	eth_dev->tx_pkt_burst = hinic_xmit_pkts;
32141d09792aSZiyang Xuan 
32151d09792aSZiyang Xuan 	return hinic_func_init(eth_dev);
32161d09792aSZiyang Xuan }
32171d09792aSZiyang Xuan 
32181d09792aSZiyang Xuan static int hinic_dev_uninit(struct rte_eth_dev *dev)
32191d09792aSZiyang Xuan {
32201d09792aSZiyang Xuan 	if (rte_eal_process_type() != RTE_PROC_PRIMARY)
32211d09792aSZiyang Xuan 		return 0;
32221d09792aSZiyang Xuan 
32231d09792aSZiyang Xuan 	hinic_dev_close(dev);
32241d09792aSZiyang Xuan 
32251d09792aSZiyang Xuan 	return HINIC_OK;
32261d09792aSZiyang Xuan }
32271d09792aSZiyang Xuan 
32281d09792aSZiyang Xuan static struct rte_pci_id pci_id_hinic_map[] = {
32291d09792aSZiyang Xuan 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_PRD) },
32301d09792aSZiyang Xuan 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_25GE) },
32311d09792aSZiyang Xuan 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_MEZZ_100GE) },
32326691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF) },
32336691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_VF_HV) },
32346691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_DUAL_25GE) },
32356691acefSXiaoyun Wang 	{ RTE_PCI_DEVICE(HINIC_HUAWEI_VENDOR_ID, HINIC_DEV_ID_1822_100GE) },
32361d09792aSZiyang Xuan 	{.vendor_id = 0},
32371d09792aSZiyang Xuan };
32381d09792aSZiyang Xuan 
32391d09792aSZiyang Xuan static int hinic_pci_probe(struct rte_pci_driver *pci_drv __rte_unused,
32401d09792aSZiyang Xuan 			   struct rte_pci_device *pci_dev)
32411d09792aSZiyang Xuan {
32421d09792aSZiyang Xuan 	return rte_eth_dev_pci_generic_probe(pci_dev,
32431d09792aSZiyang Xuan 		sizeof(struct hinic_nic_dev), hinic_dev_init);
32441d09792aSZiyang Xuan }
32451d09792aSZiyang Xuan 
32461d09792aSZiyang Xuan static int hinic_pci_remove(struct rte_pci_device *pci_dev)
32471d09792aSZiyang Xuan {
32481d09792aSZiyang Xuan 	return rte_eth_dev_pci_generic_remove(pci_dev, hinic_dev_uninit);
32491d09792aSZiyang Xuan }
32501d09792aSZiyang Xuan 
32511d09792aSZiyang Xuan static struct rte_pci_driver rte_hinic_pmd = {
32521d09792aSZiyang Xuan 	.id_table = pci_id_hinic_map,
32531d09792aSZiyang Xuan 	.drv_flags = RTE_PCI_DRV_NEED_MAPPING | RTE_PCI_DRV_INTR_LSC,
32541d09792aSZiyang Xuan 	.probe = hinic_pci_probe,
32551d09792aSZiyang Xuan 	.remove = hinic_pci_remove,
32561d09792aSZiyang Xuan };
32571d09792aSZiyang Xuan 
32581d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI(net_hinic, rte_hinic_pmd);
32591d09792aSZiyang Xuan RTE_PMD_REGISTER_PCI_TABLE(net_hinic, pci_id_hinic_map);
3260eeded204SDavid Marchand RTE_LOG_REGISTER_DEFAULT(hinic_logtype, INFO);
3261