xref: /dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.c (revision f665790a5dbad7b645ff46f31d65e977324e7bfc)
12d5fd101SZiyang Xuan /* SPDX-License-Identifier: BSD-3-Clause
22d5fd101SZiyang Xuan  * Copyright(c) 2017 Huawei Technologies Co., Ltd
32d5fd101SZiyang Xuan  */
42d5fd101SZiyang Xuan 
52d5fd101SZiyang Xuan #include "hinic_compat.h"
62d5fd101SZiyang Xuan #include "hinic_pmd_hwdev.h"
72d5fd101SZiyang Xuan #include "hinic_pmd_hwif.h"
82d5fd101SZiyang Xuan #include "hinic_pmd_eqs.h"
92d5fd101SZiyang Xuan #include "hinic_pmd_wq.h"
102d5fd101SZiyang Xuan #include "hinic_pmd_mgmt.h"
112d5fd101SZiyang Xuan #include "hinic_pmd_cmdq.h"
122d5fd101SZiyang Xuan #include "hinic_pmd_niccfg.h"
13b8582d05SXiaoyun Wang #include "hinic_pmd_mbox.h"
142d5fd101SZiyang Xuan 
152d5fd101SZiyang Xuan #define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in,		\
162d5fd101SZiyang Xuan 			       in_size, buf_out, out_size)	\
172d5fd101SZiyang Xuan 	hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, cmd,	\
182d5fd101SZiyang Xuan 			buf_in, in_size,			\
192d5fd101SZiyang Xuan 			buf_out, out_size, 0)
202d5fd101SZiyang Xuan 
21b8582d05SXiaoyun Wang /**
22b8582d05SXiaoyun Wang  * hinic_init_function_table - Initialize function table.
23b8582d05SXiaoyun Wang  *
24b8582d05SXiaoyun Wang  * @param hwdev
25b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
26b8582d05SXiaoyun Wang  * @param rx_buf_sz
27b8582d05SXiaoyun Wang  *   Receive buffer size.
28b8582d05SXiaoyun Wang  *
29b8582d05SXiaoyun Wang  * @return
30b8582d05SXiaoyun Wang  *   0 on success.
31b8582d05SXiaoyun Wang  *   negative error value otherwise.
32b8582d05SXiaoyun Wang  */
332d5fd101SZiyang Xuan int hinic_init_function_table(void *hwdev, u16 rx_buf_sz)
342d5fd101SZiyang Xuan {
352d5fd101SZiyang Xuan 	struct hinic_function_table function_table;
362d5fd101SZiyang Xuan 	u16 out_size = sizeof(function_table);
372d5fd101SZiyang Xuan 	int err;
382d5fd101SZiyang Xuan 
392d5fd101SZiyang Xuan 	if (!hwdev) {
402d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
412d5fd101SZiyang Xuan 		return -EINVAL;
422d5fd101SZiyang Xuan 	}
432d5fd101SZiyang Xuan 
442d5fd101SZiyang Xuan 	memset(&function_table, 0, sizeof(function_table));
452d5fd101SZiyang Xuan 	function_table.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
462d5fd101SZiyang Xuan 	function_table.func_id = hinic_global_func_id(hwdev);
472d5fd101SZiyang Xuan 	function_table.mtu = 0x3FFF;	/* default, max mtu */
482d5fd101SZiyang Xuan 	function_table.rx_wqe_buf_size = rx_buf_sz;
492d5fd101SZiyang Xuan 
502d5fd101SZiyang Xuan 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
512d5fd101SZiyang Xuan 				     HINIC_PORT_CMD_INIT_FUNC,
522d5fd101SZiyang Xuan 				     &function_table, sizeof(function_table),
532d5fd101SZiyang Xuan 				     &function_table, &out_size, 0);
542d5fd101SZiyang Xuan 	if (err || function_table.mgmt_msg_head.status || !out_size) {
552d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
56b8582d05SXiaoyun Wang 			"Failed to init func table, err: %d, status: 0x%x, out size: 0x%x",
57b8582d05SXiaoyun Wang 			err, function_table.mgmt_msg_head.status, out_size);
582ae8e130SXiaoyun Wang 		return -EIO;
592d5fd101SZiyang Xuan 	}
602d5fd101SZiyang Xuan 
612d5fd101SZiyang Xuan 	return 0;
622d5fd101SZiyang Xuan }
632d5fd101SZiyang Xuan 
642d5fd101SZiyang Xuan /**
65b8582d05SXiaoyun Wang  * hinic_get_base_qpn - Get global queue number.
66b8582d05SXiaoyun Wang  *
67b8582d05SXiaoyun Wang  * @param hwdev
68b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
69b8582d05SXiaoyun Wang  * @param global_qpn
70b8582d05SXiaoyun Wang  *   Global queue number.
71b8582d05SXiaoyun Wang  *
722d5fd101SZiyang Xuan  * @return
73b8582d05SXiaoyun Wang  *   0 on success.
742d5fd101SZiyang Xuan  *   negative error value otherwise.
75b8582d05SXiaoyun Wang  */
762d5fd101SZiyang Xuan int hinic_get_base_qpn(void *hwdev, u16 *global_qpn)
772d5fd101SZiyang Xuan {
782d5fd101SZiyang Xuan 	struct hinic_cmd_qpn cmd_qpn;
792d5fd101SZiyang Xuan 	u16 out_size = sizeof(cmd_qpn);
802d5fd101SZiyang Xuan 	int err;
812d5fd101SZiyang Xuan 
822d5fd101SZiyang Xuan 	if (!hwdev || !global_qpn) {
832d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or global_qpn is NULL");
842d5fd101SZiyang Xuan 		return -EINVAL;
852d5fd101SZiyang Xuan 	}
862d5fd101SZiyang Xuan 
872d5fd101SZiyang Xuan 	memset(&cmd_qpn, 0, sizeof(cmd_qpn));
882d5fd101SZiyang Xuan 	cmd_qpn.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
892d5fd101SZiyang Xuan 	cmd_qpn.func_id = hinic_global_func_id(hwdev);
902d5fd101SZiyang Xuan 
912d5fd101SZiyang Xuan 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
922d5fd101SZiyang Xuan 				     HINIC_PORT_CMD_GET_GLOBAL_QPN,
932d5fd101SZiyang Xuan 				     &cmd_qpn, sizeof(cmd_qpn), &cmd_qpn,
942d5fd101SZiyang Xuan 				     &out_size, 0);
952d5fd101SZiyang Xuan 	if (err || !out_size || cmd_qpn.mgmt_msg_head.status) {
962d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
97b8582d05SXiaoyun Wang 			"Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x",
98b8582d05SXiaoyun Wang 			err, cmd_qpn.mgmt_msg_head.status, out_size);
992ae8e130SXiaoyun Wang 		return -EIO;
1002d5fd101SZiyang Xuan 	}
1012d5fd101SZiyang Xuan 
1022d5fd101SZiyang Xuan 	*global_qpn = cmd_qpn.base_qpn;
1032d5fd101SZiyang Xuan 
1042d5fd101SZiyang Xuan 	return 0;
1052d5fd101SZiyang Xuan }
1062d5fd101SZiyang Xuan 
1072d5fd101SZiyang Xuan /**
1082d5fd101SZiyang Xuan  * hinic_set_mac - Init mac_vlan table in NIC.
109b8582d05SXiaoyun Wang  *
110b8582d05SXiaoyun Wang  * @param hwdev
111b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
112b8582d05SXiaoyun Wang  * @param mac_addr
113b8582d05SXiaoyun Wang  *   MAC address.
114b8582d05SXiaoyun Wang  * @param vlan_id
115b8582d05SXiaoyun Wang  *   Set 0 for mac_vlan table initialization.
116b8582d05SXiaoyun Wang  * @param func_id
117b8582d05SXiaoyun Wang  *   Global function id of NIC.
118b8582d05SXiaoyun Wang  *
1192d5fd101SZiyang Xuan  * @return
120b8582d05SXiaoyun Wang  *   0 on success.
1212d5fd101SZiyang Xuan  *   negative error value otherwise.
1222d5fd101SZiyang Xuan  */
1232d5fd101SZiyang Xuan int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
1242d5fd101SZiyang Xuan {
1252d5fd101SZiyang Xuan 	struct hinic_port_mac_set mac_info;
1262d5fd101SZiyang Xuan 	u16 out_size = sizeof(mac_info);
1272d5fd101SZiyang Xuan 	int err;
1282d5fd101SZiyang Xuan 
1292d5fd101SZiyang Xuan 	if (!hwdev || !mac_addr) {
1302d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
1312d5fd101SZiyang Xuan 		return -EINVAL;
1322d5fd101SZiyang Xuan 	}
1332d5fd101SZiyang Xuan 
1342d5fd101SZiyang Xuan 	memset(&mac_info, 0, sizeof(mac_info));
1352d5fd101SZiyang Xuan 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1362d5fd101SZiyang Xuan 	mac_info.func_id = func_id;
1372d5fd101SZiyang Xuan 	mac_info.vlan_id = vlan_id;
1382d5fd101SZiyang Xuan 	memmove(mac_info.mac, mac_addr, ETH_ALEN);
1392d5fd101SZiyang Xuan 
1402d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
1412d5fd101SZiyang Xuan 				     sizeof(mac_info), &mac_info, &out_size);
1422d5fd101SZiyang Xuan 	if (err || !out_size || (mac_info.mgmt_msg_head.status &&
1432d5fd101SZiyang Xuan 	    mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
1442d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x",
1452d5fd101SZiyang Xuan 			err, mac_info.mgmt_msg_head.status, out_size);
1462ae8e130SXiaoyun Wang 		return -EIO;
1472d5fd101SZiyang Xuan 	}
148b8582d05SXiaoyun Wang 
1492d5fd101SZiyang Xuan 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
1502d5fd101SZiyang Xuan 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore set operation.");
1512d5fd101SZiyang Xuan 		return HINIC_PF_SET_VF_ALREADY;
1522d5fd101SZiyang Xuan 	}
1532d5fd101SZiyang Xuan 
1542d5fd101SZiyang Xuan 	return 0;
1552d5fd101SZiyang Xuan }
1562d5fd101SZiyang Xuan 
1572d5fd101SZiyang Xuan /**
1582d5fd101SZiyang Xuan  * hinic_del_mac - Uninit mac_vlan table in NIC.
159b8582d05SXiaoyun Wang  *
160b8582d05SXiaoyun Wang  * @param hwdev
161b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
162b8582d05SXiaoyun Wang  * @param mac_addr
163b8582d05SXiaoyun Wang  *   MAC address.
164b8582d05SXiaoyun Wang  * @param vlan_id
165b8582d05SXiaoyun Wang  *   Set 0 for mac_vlan table initialization.
166b8582d05SXiaoyun Wang  * @param func_id
167b8582d05SXiaoyun Wang  *   Global function id of NIC.
168b8582d05SXiaoyun Wang  *
1692d5fd101SZiyang Xuan  * @return
170b8582d05SXiaoyun Wang  *   0 on success.
1712d5fd101SZiyang Xuan  *   negative error value otherwise.
1722d5fd101SZiyang Xuan  */
173b8582d05SXiaoyun Wang int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
1742d5fd101SZiyang Xuan {
1752d5fd101SZiyang Xuan 	struct hinic_port_mac_set mac_info;
1762d5fd101SZiyang Xuan 	u16 out_size = sizeof(mac_info);
1772d5fd101SZiyang Xuan 	int err;
1782d5fd101SZiyang Xuan 
1792d5fd101SZiyang Xuan 	if (!hwdev || !mac_addr) {
1802d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
1812d5fd101SZiyang Xuan 		return -EINVAL;
1822d5fd101SZiyang Xuan 	}
1832d5fd101SZiyang Xuan 
1842d5fd101SZiyang Xuan 	if (vlan_id >= VLAN_N_VID) {
1852d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Invalid VLAN number");
1862d5fd101SZiyang Xuan 		return -EINVAL;
1872d5fd101SZiyang Xuan 	}
1882d5fd101SZiyang Xuan 
1892d5fd101SZiyang Xuan 	memset(&mac_info, 0, sizeof(mac_info));
1902d5fd101SZiyang Xuan 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1912d5fd101SZiyang Xuan 	mac_info.func_id = func_id;
1922d5fd101SZiyang Xuan 	mac_info.vlan_id = vlan_id;
1932d5fd101SZiyang Xuan 	memmove(mac_info.mac, mac_addr, ETH_ALEN);
1942d5fd101SZiyang Xuan 
1952d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_DEL_MAC, &mac_info,
1962d5fd101SZiyang Xuan 				     sizeof(mac_info), &mac_info, &out_size);
1972d5fd101SZiyang Xuan 	if (err || !out_size || (mac_info.mgmt_msg_head.status &&
1982d5fd101SZiyang Xuan 		mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
1992d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x",
2002d5fd101SZiyang Xuan 			err, mac_info.mgmt_msg_head.status, out_size);
2012ae8e130SXiaoyun Wang 		return -EIO;
2022d5fd101SZiyang Xuan 	}
2032d5fd101SZiyang Xuan 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
2042d5fd101SZiyang Xuan 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore delete operation.");
2052d5fd101SZiyang Xuan 		return HINIC_PF_SET_VF_ALREADY;
2062d5fd101SZiyang Xuan 	}
2072d5fd101SZiyang Xuan 
2082d5fd101SZiyang Xuan 	return 0;
2092d5fd101SZiyang Xuan }
2102d5fd101SZiyang Xuan 
211b8582d05SXiaoyun Wang /**
212b8582d05SXiaoyun Wang  * hinic_get_default_mac - Get default mac address from hardware.
213b8582d05SXiaoyun Wang  *
214b8582d05SXiaoyun Wang  * @param hwdev
215b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
216b8582d05SXiaoyun Wang  * @param mac_addr
217b8582d05SXiaoyun Wang  *   MAC address.
218b8582d05SXiaoyun Wang  *
219b8582d05SXiaoyun Wang  * @return
220b8582d05SXiaoyun Wang  *   0 on success.
221b8582d05SXiaoyun Wang  *   negative error value otherwise.
222b8582d05SXiaoyun Wang  */
2232d5fd101SZiyang Xuan int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
2242d5fd101SZiyang Xuan {
2252d5fd101SZiyang Xuan 	struct hinic_port_mac_set mac_info;
2262d5fd101SZiyang Xuan 	u16 out_size = sizeof(mac_info);
2272d5fd101SZiyang Xuan 	int err;
2282d5fd101SZiyang Xuan 
2292d5fd101SZiyang Xuan 	if (!hwdev || !mac_addr) {
2302d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
2312d5fd101SZiyang Xuan 		return -EINVAL;
2322d5fd101SZiyang Xuan 	}
2332d5fd101SZiyang Xuan 
2342d5fd101SZiyang Xuan 	memset(&mac_info, 0, sizeof(mac_info));
2352d5fd101SZiyang Xuan 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
2362d5fd101SZiyang Xuan 	mac_info.func_id = hinic_global_func_id(hwdev);
2372d5fd101SZiyang Xuan 
2382d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MAC,
2392d5fd101SZiyang Xuan 				     &mac_info, sizeof(mac_info),
2402d5fd101SZiyang Xuan 				     &mac_info, &out_size);
2412d5fd101SZiyang Xuan 	if (err || !out_size || mac_info.mgmt_msg_head.status) {
2422d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x",
2432d5fd101SZiyang Xuan 			err, mac_info.mgmt_msg_head.status, out_size);
2442ae8e130SXiaoyun Wang 		return -EIO;
2452d5fd101SZiyang Xuan 	}
2462d5fd101SZiyang Xuan 
2472d5fd101SZiyang Xuan 	memmove(mac_addr, mac_info.mac, ETH_ALEN);
2482d5fd101SZiyang Xuan 
2492d5fd101SZiyang Xuan 	return 0;
2502d5fd101SZiyang Xuan }
2512d5fd101SZiyang Xuan 
252b8582d05SXiaoyun Wang /**
25300499a22SXiaoyun Wang *  hinic_update_mac - Update mac address to hardware.
25400499a22SXiaoyun Wang *
25500499a22SXiaoyun Wang * @param hwdev
25600499a22SXiaoyun Wang *   The hardware interface of a nic device.
25700499a22SXiaoyun Wang * @param old_mac
25800499a22SXiaoyun Wang *   Old mac address.
25900499a22SXiaoyun Wang * @param new_mac
26000499a22SXiaoyun Wang *   New mac address.
26100499a22SXiaoyun Wang * @param vlan_id
26200499a22SXiaoyun Wang *   Set 0 for mac_vlan table initialization.
26300499a22SXiaoyun Wang * @param func_id
26400499a22SXiaoyun Wang *   Global function id of NIC.
26500499a22SXiaoyun Wang *
26600499a22SXiaoyun Wang * @return
26700499a22SXiaoyun Wang *   0 on success.
26800499a22SXiaoyun Wang *   negative error value otherwise.
26900499a22SXiaoyun Wang */
27000499a22SXiaoyun Wang int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
27100499a22SXiaoyun Wang 		     u16 func_id)
27200499a22SXiaoyun Wang {
27300499a22SXiaoyun Wang 	struct hinic_port_mac_update mac_info;
27400499a22SXiaoyun Wang 	u16 out_size = sizeof(mac_info);
27500499a22SXiaoyun Wang 	int err;
27600499a22SXiaoyun Wang 
27700499a22SXiaoyun Wang 	if (!hwdev || !old_mac || !new_mac) {
2784f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev, old_mac or new_mac is NULL");
27900499a22SXiaoyun Wang 		return -EINVAL;
28000499a22SXiaoyun Wang 	}
28100499a22SXiaoyun Wang 
28200499a22SXiaoyun Wang 	memset(&mac_info, 0, sizeof(mac_info));
28300499a22SXiaoyun Wang 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
28400499a22SXiaoyun Wang 	mac_info.func_id = func_id;
28500499a22SXiaoyun Wang 	mac_info.vlan_id = vlan_id;
28600499a22SXiaoyun Wang 	memcpy(mac_info.old_mac, old_mac, ETH_ALEN);
28700499a22SXiaoyun Wang 	memcpy(mac_info.new_mac, new_mac, ETH_ALEN);
28800499a22SXiaoyun Wang 
28900499a22SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UPDATE_MAC,
29000499a22SXiaoyun Wang 				     &mac_info, sizeof(mac_info),
29100499a22SXiaoyun Wang 				     &mac_info, &out_size);
29200499a22SXiaoyun Wang 	if (err || !out_size ||
29300499a22SXiaoyun Wang 	    (mac_info.mgmt_msg_head.status &&
29400499a22SXiaoyun Wang 	     mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
2954f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x",
29600499a22SXiaoyun Wang 			    err, mac_info.mgmt_msg_head.status, out_size);
2972ae8e130SXiaoyun Wang 		return -EIO;
29800499a22SXiaoyun Wang 	}
29900499a22SXiaoyun Wang 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
3004f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore update operation");
30100499a22SXiaoyun Wang 		return HINIC_PF_SET_VF_ALREADY;
30200499a22SXiaoyun Wang 	}
30300499a22SXiaoyun Wang 
30400499a22SXiaoyun Wang 	return 0;
30500499a22SXiaoyun Wang }
30600499a22SXiaoyun Wang 
30700499a22SXiaoyun Wang /**
308b8582d05SXiaoyun Wang  * hinic_set_port_mtu -  Set MTU to port.
309b8582d05SXiaoyun Wang  *
310b8582d05SXiaoyun Wang  * @param hwdev
311b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
312b8582d05SXiaoyun Wang  * @param new_mtu
313b8582d05SXiaoyun Wang  *   MTU size.
314b8582d05SXiaoyun Wang  *
315b8582d05SXiaoyun Wang  * @return
316b8582d05SXiaoyun Wang  *   0 on success.
317b8582d05SXiaoyun Wang  *   negative error value otherwise.
318b8582d05SXiaoyun Wang  */
3192d5fd101SZiyang Xuan int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
3202d5fd101SZiyang Xuan {
3212d5fd101SZiyang Xuan 	struct hinic_mtu mtu_info;
3222d5fd101SZiyang Xuan 	u16 out_size = sizeof(mtu_info);
3232d5fd101SZiyang Xuan 	int err;
3242d5fd101SZiyang Xuan 
3252d5fd101SZiyang Xuan 	if (!hwdev) {
3262d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
3272d5fd101SZiyang Xuan 		return -EINVAL;
3282d5fd101SZiyang Xuan 	}
3292d5fd101SZiyang Xuan 
3302d5fd101SZiyang Xuan 	memset(&mtu_info, 0, sizeof(mtu_info));
3312d5fd101SZiyang Xuan 	mtu_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
3322d5fd101SZiyang Xuan 	mtu_info.func_id = hinic_global_func_id(hwdev);
3332d5fd101SZiyang Xuan 	mtu_info.mtu = new_mtu;
3342d5fd101SZiyang Xuan 
3352d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
3362d5fd101SZiyang Xuan 				     &mtu_info, sizeof(mtu_info),
3372d5fd101SZiyang Xuan 				     &mtu_info, &out_size);
3382d5fd101SZiyang Xuan 	if (err || !out_size || mtu_info.mgmt_msg_head.status) {
3392d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x",
3402d5fd101SZiyang Xuan 			err, mtu_info.mgmt_msg_head.status, out_size);
3412ae8e130SXiaoyun Wang 		return -EIO;
3422d5fd101SZiyang Xuan 	}
3432d5fd101SZiyang Xuan 
3442d5fd101SZiyang Xuan 	return 0;
3452d5fd101SZiyang Xuan }
3462d5fd101SZiyang Xuan 
347b8582d05SXiaoyun Wang /**
348fdba3bf1SXiaoyun Wang  * hinic_add_remove_vlan - Add or remove vlan id to vlan elb table.
349fdba3bf1SXiaoyun Wang  *
350fdba3bf1SXiaoyun Wang  * @param hwdev
351fdba3bf1SXiaoyun Wang  *   The hardware interface of a nic device.
352fdba3bf1SXiaoyun Wang  * @param vlan_id
353fdba3bf1SXiaoyun Wang  *   Vlan id.
354fdba3bf1SXiaoyun Wang  * @param func_id
355fdba3bf1SXiaoyun Wang  *   Global function id of NIC.
356fdba3bf1SXiaoyun Wang  * @param add
357fdba3bf1SXiaoyun Wang  *   Add or remove operation.
358fdba3bf1SXiaoyun Wang  *
359fdba3bf1SXiaoyun Wang  * @return
360fdba3bf1SXiaoyun Wang  *   0 on success.
361fdba3bf1SXiaoyun Wang  *   negative error value otherwise.
362fdba3bf1SXiaoyun Wang  */
363fdba3bf1SXiaoyun Wang int hinic_add_remove_vlan(void *hwdev, u16 vlan_id, u16 func_id, bool add)
364fdba3bf1SXiaoyun Wang {
365fdba3bf1SXiaoyun Wang 	struct hinic_vlan_config vlan_info;
366fdba3bf1SXiaoyun Wang 	u16 out_size = sizeof(vlan_info);
367fdba3bf1SXiaoyun Wang 	u8 cmd;
368fdba3bf1SXiaoyun Wang 	int err;
369fdba3bf1SXiaoyun Wang 
370fdba3bf1SXiaoyun Wang 	if (!hwdev) {
371fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
372fdba3bf1SXiaoyun Wang 		return -EINVAL;
373fdba3bf1SXiaoyun Wang 	}
374fdba3bf1SXiaoyun Wang 
375fdba3bf1SXiaoyun Wang 	cmd = add ? HINIC_PORT_CMD_ADD_VLAN : HINIC_PORT_CMD_DEL_VLAN;
376fdba3bf1SXiaoyun Wang 
377fdba3bf1SXiaoyun Wang 	memset(&vlan_info, 0, sizeof(vlan_info));
378fdba3bf1SXiaoyun Wang 	vlan_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
379fdba3bf1SXiaoyun Wang 	vlan_info.func_id = func_id;
380fdba3bf1SXiaoyun Wang 	vlan_info.vlan_id = vlan_id;
381fdba3bf1SXiaoyun Wang 
382d807dd7dSXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, cmd, &vlan_info, sizeof(vlan_info),
383d807dd7dSXiaoyun Wang 				     &vlan_info, &out_size);
384fdba3bf1SXiaoyun Wang 	if (err || !out_size || vlan_info.mgmt_msg_head.status) {
385fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(ERR,
3864f1af3cbSXiaoyun Wang 			"Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x",
387fdba3bf1SXiaoyun Wang 			add ? "add" : "remove", err,
388fdba3bf1SXiaoyun Wang 			vlan_info.mgmt_msg_head.status, out_size);
3892ae8e130SXiaoyun Wang 		return -EIO;
390fdba3bf1SXiaoyun Wang 	}
391fdba3bf1SXiaoyun Wang 
392fdba3bf1SXiaoyun Wang 	return 0;
393fdba3bf1SXiaoyun Wang }
394fdba3bf1SXiaoyun Wang 
395fdba3bf1SXiaoyun Wang /**
396fdba3bf1SXiaoyun Wang  * hinic_config_vlan_filter - Enable or Disable vlan filter.
397fdba3bf1SXiaoyun Wang  *
398fdba3bf1SXiaoyun Wang  * @param hwdev
399fdba3bf1SXiaoyun Wang  *   The hardware interface of a nic device.
400fdba3bf1SXiaoyun Wang  * @param vlan_filter_ctrl
401fdba3bf1SXiaoyun Wang  *   Enable or Disable.
402fdba3bf1SXiaoyun Wang  *
403fdba3bf1SXiaoyun Wang  * @return
404fdba3bf1SXiaoyun Wang  *   0 on success.
405fdba3bf1SXiaoyun Wang  *   negative error value otherwise.
406fdba3bf1SXiaoyun Wang  */
407fdba3bf1SXiaoyun Wang int hinic_config_vlan_filter(void *hwdev, u32 vlan_filter_ctrl)
408fdba3bf1SXiaoyun Wang {
409fdba3bf1SXiaoyun Wang 	struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
410fdba3bf1SXiaoyun Wang 	struct hinic_vlan_filter vlan_filter;
411fdba3bf1SXiaoyun Wang 	u16 out_size = sizeof(vlan_filter);
412fdba3bf1SXiaoyun Wang 	int err;
413fdba3bf1SXiaoyun Wang 
414fdba3bf1SXiaoyun Wang 	if (!hwdev)
415fdba3bf1SXiaoyun Wang 		return -EINVAL;
416fdba3bf1SXiaoyun Wang 
417fdba3bf1SXiaoyun Wang 	memset(&vlan_filter, 0, sizeof(vlan_filter));
418fdba3bf1SXiaoyun Wang 	vlan_filter.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
419fdba3bf1SXiaoyun Wang 	vlan_filter.func_id = hinic_global_func_id(nic_hwdev);
420fdba3bf1SXiaoyun Wang 	vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl;
421fdba3bf1SXiaoyun Wang 
422fdba3bf1SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(nic_hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,
423fdba3bf1SXiaoyun Wang 				     &vlan_filter, sizeof(vlan_filter),
424fdba3bf1SXiaoyun Wang 				     &vlan_filter, &out_size);
425fdba3bf1SXiaoyun Wang 	if (vlan_filter.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
426fdba3bf1SXiaoyun Wang 		err = HINIC_MGMT_CMD_UNSUPPORTED;
427fdba3bf1SXiaoyun Wang 	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
428fdba3bf1SXiaoyun Wang 		(HINIC_IS_VF(nic_hwdev))) {
429fdba3bf1SXiaoyun Wang 		err = HINIC_MGMT_CMD_UNSUPPORTED;
430fdba3bf1SXiaoyun Wang 	} else if (err || !out_size || vlan_filter.mgmt_msg_head.status) {
431fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(ERR,
4324f1af3cbSXiaoyun Wang 			"Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x",
433fdba3bf1SXiaoyun Wang 			vlan_filter_ctrl, err,
434fdba3bf1SXiaoyun Wang 			vlan_filter.mgmt_msg_head.status, out_size);
4352ae8e130SXiaoyun Wang 		err = -EIO;
436fdba3bf1SXiaoyun Wang 	}
437fdba3bf1SXiaoyun Wang 
438fdba3bf1SXiaoyun Wang 	return err;
439fdba3bf1SXiaoyun Wang }
440fdba3bf1SXiaoyun Wang 
441fdba3bf1SXiaoyun Wang /**
442fdba3bf1SXiaoyun Wang  * hinic_set_rx_vlan_offload - Enable or Disable vlan offload.
443fdba3bf1SXiaoyun Wang  *
444fdba3bf1SXiaoyun Wang  * @param hwdev
445fdba3bf1SXiaoyun Wang  *   The hardware interface of a nic device.
446fdba3bf1SXiaoyun Wang  * @param en
447fdba3bf1SXiaoyun Wang  *   Enable or Disable.
448fdba3bf1SXiaoyun Wang  *
449fdba3bf1SXiaoyun Wang  * @return
450fdba3bf1SXiaoyun Wang  *   0 on success.
451fdba3bf1SXiaoyun Wang  *   negative error value otherwise.
452fdba3bf1SXiaoyun Wang  */
453fdba3bf1SXiaoyun Wang int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
454fdba3bf1SXiaoyun Wang {
455fdba3bf1SXiaoyun Wang 	struct hinic_vlan_offload vlan_cfg;
456fdba3bf1SXiaoyun Wang 	u16 out_size = sizeof(vlan_cfg);
457fdba3bf1SXiaoyun Wang 	int err;
458fdba3bf1SXiaoyun Wang 
459fdba3bf1SXiaoyun Wang 	if (!hwdev) {
460fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
461fdba3bf1SXiaoyun Wang 		return -EINVAL;
462fdba3bf1SXiaoyun Wang 	}
463fdba3bf1SXiaoyun Wang 
464fdba3bf1SXiaoyun Wang 	memset(&vlan_cfg, 0, sizeof(vlan_cfg));
465fdba3bf1SXiaoyun Wang 	vlan_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
466fdba3bf1SXiaoyun Wang 	vlan_cfg.func_id = hinic_global_func_id(hwdev);
467fdba3bf1SXiaoyun Wang 	vlan_cfg.vlan_rx_offload = en;
468fdba3bf1SXiaoyun Wang 
469fdba3bf1SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
470fdba3bf1SXiaoyun Wang 				     &vlan_cfg, sizeof(vlan_cfg),
471fdba3bf1SXiaoyun Wang 				     &vlan_cfg, &out_size);
472fdba3bf1SXiaoyun Wang 	if (err || !out_size || vlan_cfg.mgmt_msg_head.status) {
473fdba3bf1SXiaoyun Wang 		PMD_DRV_LOG(ERR,
4744f1af3cbSXiaoyun Wang 			"Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x",
475fdba3bf1SXiaoyun Wang 			err, vlan_cfg.mgmt_msg_head.status, out_size);
4762ae8e130SXiaoyun Wang 		return -EIO;
477fdba3bf1SXiaoyun Wang 	}
478fdba3bf1SXiaoyun Wang 
479fdba3bf1SXiaoyun Wang 	return 0;
480fdba3bf1SXiaoyun Wang }
481fdba3bf1SXiaoyun Wang 
482fdba3bf1SXiaoyun Wang /**
483b8582d05SXiaoyun Wang  * hinic_get_link_status - Get link status from hardware.
484b8582d05SXiaoyun Wang  *
485b8582d05SXiaoyun Wang  * @param hwdev
486b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
487b8582d05SXiaoyun Wang  * @param link_state
488b8582d05SXiaoyun Wang  *   Link status.
489b8582d05SXiaoyun Wang  *
490b8582d05SXiaoyun Wang  * @return
491b8582d05SXiaoyun Wang  *   0 on success.
492b8582d05SXiaoyun Wang  *   negative error value otherwise.
493b8582d05SXiaoyun Wang  */
4942d5fd101SZiyang Xuan int hinic_get_link_status(void *hwdev, u8 *link_state)
4952d5fd101SZiyang Xuan {
4962d5fd101SZiyang Xuan 	struct hinic_get_link get_link;
4972d5fd101SZiyang Xuan 	u16 out_size = sizeof(get_link);
4982d5fd101SZiyang Xuan 	int err;
4992d5fd101SZiyang Xuan 
5002d5fd101SZiyang Xuan 	if (!hwdev || !link_state) {
5012d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL");
5022d5fd101SZiyang Xuan 		return -EINVAL;
5032d5fd101SZiyang Xuan 	}
5042d5fd101SZiyang Xuan 
5052d5fd101SZiyang Xuan 	memset(&get_link, 0, sizeof(get_link));
5062d5fd101SZiyang Xuan 	get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
5072d5fd101SZiyang Xuan 	get_link.func_id = hinic_global_func_id(hwdev);
5082d5fd101SZiyang Xuan 
5092d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
5102d5fd101SZiyang Xuan 				     &get_link, sizeof(get_link),
5112d5fd101SZiyang Xuan 				     &get_link, &out_size);
5122d5fd101SZiyang Xuan 	if (err || !out_size || get_link.mgmt_msg_head.status) {
5132d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x",
5142d5fd101SZiyang Xuan 			err, get_link.mgmt_msg_head.status, out_size);
5152ae8e130SXiaoyun Wang 		return -EIO;
5162d5fd101SZiyang Xuan 	}
5172d5fd101SZiyang Xuan 
5182d5fd101SZiyang Xuan 	*link_state = get_link.link_status;
5192d5fd101SZiyang Xuan 
5202d5fd101SZiyang Xuan 	return 0;
5212d5fd101SZiyang Xuan }
5222d5fd101SZiyang Xuan 
5232d5fd101SZiyang Xuan /**
5242d5fd101SZiyang Xuan  * hinic_set_vport_enable - Notify firmware that driver is ready or not.
525b8582d05SXiaoyun Wang  *
526b8582d05SXiaoyun Wang  * @param hwdev
527b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
528b8582d05SXiaoyun Wang  * @param enable
529b8582d05SXiaoyun Wang  *   1: driver is ready; 0: driver is not ok.
530b8582d05SXiaoyun Wang  *
531b8582d05SXiaoyun Wang  * @return
532b8582d05SXiaoyun Wang  *   0 on success.
533b8582d05SXiaoyun Wang  *   negative error value otherwise.
534b8582d05SXiaoyun Wang  */
5352d5fd101SZiyang Xuan int hinic_set_vport_enable(void *hwdev, bool enable)
5362d5fd101SZiyang Xuan {
5372d5fd101SZiyang Xuan 	struct hinic_vport_state en_state;
5382d5fd101SZiyang Xuan 	u16 out_size = sizeof(en_state);
5392d5fd101SZiyang Xuan 	int err;
5402d5fd101SZiyang Xuan 
5412d5fd101SZiyang Xuan 	if (!hwdev) {
5422d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
5432d5fd101SZiyang Xuan 		return -EINVAL;
5442d5fd101SZiyang Xuan 	}
5452d5fd101SZiyang Xuan 
5462d5fd101SZiyang Xuan 	memset(&en_state, 0, sizeof(en_state));
5472d5fd101SZiyang Xuan 	en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
5482d5fd101SZiyang Xuan 	en_state.func_id = hinic_global_func_id(hwdev);
5492d5fd101SZiyang Xuan 	en_state.state = (enable ? 1 : 0);
5502d5fd101SZiyang Xuan 
5512d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
5522d5fd101SZiyang Xuan 				     &en_state, sizeof(en_state),
5532d5fd101SZiyang Xuan 				     &en_state, &out_size);
5542d5fd101SZiyang Xuan 	if (err || !out_size || en_state.mgmt_msg_head.status) {
5552d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x",
5562d5fd101SZiyang Xuan 			err, en_state.mgmt_msg_head.status, out_size);
5572ae8e130SXiaoyun Wang 		return -EIO;
5582d5fd101SZiyang Xuan 	}
5592d5fd101SZiyang Xuan 
5602d5fd101SZiyang Xuan 	return 0;
5612d5fd101SZiyang Xuan }
5622d5fd101SZiyang Xuan 
5632d5fd101SZiyang Xuan /**
564b8582d05SXiaoyun Wang  * hinic_set_port_enable - Open MAG to receive packets.
565b8582d05SXiaoyun Wang  *
566b8582d05SXiaoyun Wang  * @param hwdev
567b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
568b8582d05SXiaoyun Wang  * @param enable
569b8582d05SXiaoyun Wang  *   1: open MAG; 0: close MAG.
570b8582d05SXiaoyun Wang  *
5712d5fd101SZiyang Xuan  * @return
572b8582d05SXiaoyun Wang  *   0 on success.
5732d5fd101SZiyang Xuan  *   negative error value otherwise.
5742d5fd101SZiyang Xuan  */
5752d5fd101SZiyang Xuan int hinic_set_port_enable(void *hwdev, bool enable)
5762d5fd101SZiyang Xuan {
5772d5fd101SZiyang Xuan 	struct hinic_port_state en_state;
5782d5fd101SZiyang Xuan 	u16 out_size = sizeof(en_state);
5792d5fd101SZiyang Xuan 	int err;
5802d5fd101SZiyang Xuan 
5812d5fd101SZiyang Xuan 	if (!hwdev) {
5822d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
5832d5fd101SZiyang Xuan 		return -EINVAL;
5842d5fd101SZiyang Xuan 	}
5852d5fd101SZiyang Xuan 
586b8582d05SXiaoyun Wang 	if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
587b8582d05SXiaoyun Wang 		return 0;
588b8582d05SXiaoyun Wang 
5892d5fd101SZiyang Xuan 	memset(&en_state, 0, sizeof(en_state));
5902d5fd101SZiyang Xuan 	en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
5912d5fd101SZiyang Xuan 	en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE);
5922d5fd101SZiyang Xuan 
5932d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
5942d5fd101SZiyang Xuan 				     &en_state, sizeof(en_state),
5952d5fd101SZiyang Xuan 				     &en_state, &out_size);
5962d5fd101SZiyang Xuan 	if (err || !out_size || en_state.mgmt_msg_head.status) {
5972d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x",
5982d5fd101SZiyang Xuan 			err, en_state.mgmt_msg_head.status, out_size);
5992ae8e130SXiaoyun Wang 		return -EIO;
6002d5fd101SZiyang Xuan 	}
6012d5fd101SZiyang Xuan 
6022d5fd101SZiyang Xuan 	return 0;
6032d5fd101SZiyang Xuan }
6042d5fd101SZiyang Xuan 
6052d5fd101SZiyang Xuan int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
6062d5fd101SZiyang Xuan {
6072d5fd101SZiyang Xuan 	struct hinic_port_info port_msg;
6082d5fd101SZiyang Xuan 	u16 out_size = sizeof(port_msg);
6092d5fd101SZiyang Xuan 	int err;
6102d5fd101SZiyang Xuan 
6112d5fd101SZiyang Xuan 	if (!hwdev || !port_info) {
6122d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL");
6132d5fd101SZiyang Xuan 		return -EINVAL;
6142d5fd101SZiyang Xuan 	}
6152d5fd101SZiyang Xuan 
6162d5fd101SZiyang Xuan 	memset(&port_msg, 0, sizeof(port_msg));
6172d5fd101SZiyang Xuan 	port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
6182d5fd101SZiyang Xuan 	port_msg.func_id = hinic_global_func_id(hwdev);
6192d5fd101SZiyang Xuan 
6202d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
6212d5fd101SZiyang Xuan 				     &port_msg, sizeof(port_msg),
6222d5fd101SZiyang Xuan 				     &port_msg, &out_size);
6232d5fd101SZiyang Xuan 	if (err || !out_size || port_msg.mgmt_msg_head.status) {
6242d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
6252d5fd101SZiyang Xuan 			"Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
6262d5fd101SZiyang Xuan 			err, port_msg.mgmt_msg_head.status, out_size);
627d807dd7dSXiaoyun Wang 		return -EIO;
6282d5fd101SZiyang Xuan 	}
6292d5fd101SZiyang Xuan 
6302d5fd101SZiyang Xuan 	port_info->autoneg_cap = port_msg.autoneg_cap;
6312d5fd101SZiyang Xuan 	port_info->autoneg_state = port_msg.autoneg_state;
6322d5fd101SZiyang Xuan 	port_info->duplex = port_msg.duplex;
6332d5fd101SZiyang Xuan 	port_info->port_type = port_msg.port_type;
6342d5fd101SZiyang Xuan 	port_info->speed = port_msg.speed;
6352d5fd101SZiyang Xuan 
6362d5fd101SZiyang Xuan 	return 0;
6372d5fd101SZiyang Xuan }
6382d5fd101SZiyang Xuan 
6392d5fd101SZiyang Xuan int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
6402d5fd101SZiyang Xuan {
6412d5fd101SZiyang Xuan 	struct hinic_pause_config pause_info;
6422d5fd101SZiyang Xuan 	u16 out_size = sizeof(pause_info);
6432d5fd101SZiyang Xuan 	int err;
6442d5fd101SZiyang Xuan 
6452d5fd101SZiyang Xuan 	if (!hwdev) {
6462d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
6472d5fd101SZiyang Xuan 		return -EINVAL;
6482d5fd101SZiyang Xuan 	}
6492d5fd101SZiyang Xuan 
6502d5fd101SZiyang Xuan 	memset(&pause_info, 0, sizeof(pause_info));
6512d5fd101SZiyang Xuan 	pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
6522d5fd101SZiyang Xuan 	pause_info.func_id = hinic_global_func_id(hwdev);
6532d5fd101SZiyang Xuan 	pause_info.auto_neg = nic_pause.auto_neg;
6542d5fd101SZiyang Xuan 	pause_info.rx_pause = nic_pause.rx_pause;
6552d5fd101SZiyang Xuan 	pause_info.tx_pause = nic_pause.tx_pause;
6562d5fd101SZiyang Xuan 
6572d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
6582d5fd101SZiyang Xuan 				     &pause_info, sizeof(pause_info),
6592d5fd101SZiyang Xuan 				     &pause_info, &out_size);
6602d5fd101SZiyang Xuan 	if (err || !out_size || pause_info.mgmt_msg_head.status) {
6612d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x",
6622d5fd101SZiyang Xuan 			err, pause_info.mgmt_msg_head.status, out_size);
6632ae8e130SXiaoyun Wang 		return -EIO;
6642d5fd101SZiyang Xuan 	}
6652d5fd101SZiyang Xuan 
6662d5fd101SZiyang Xuan 	return 0;
6672d5fd101SZiyang Xuan }
6682d5fd101SZiyang Xuan 
669ef6f2f5cSXiaoyun Wang int hinic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
670ef6f2f5cSXiaoyun Wang {
671ef6f2f5cSXiaoyun Wang 	struct hinic_pause_config pause_info;
672ef6f2f5cSXiaoyun Wang 	u16 out_size = sizeof(pause_info);
673ef6f2f5cSXiaoyun Wang 	int err;
674ef6f2f5cSXiaoyun Wang 
675ef6f2f5cSXiaoyun Wang 	if (!hwdev || !nic_pause)
676ef6f2f5cSXiaoyun Wang 		return -EINVAL;
677ef6f2f5cSXiaoyun Wang 
678ef6f2f5cSXiaoyun Wang 	memset(&pause_info, 0, sizeof(pause_info));
679ef6f2f5cSXiaoyun Wang 	pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
680ef6f2f5cSXiaoyun Wang 	pause_info.func_id = hinic_global_func_id(hwdev);
681ef6f2f5cSXiaoyun Wang 
682ef6f2f5cSXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
683ef6f2f5cSXiaoyun Wang 				     &pause_info, sizeof(pause_info),
684ef6f2f5cSXiaoyun Wang 				     &pause_info, &out_size);
685ef6f2f5cSXiaoyun Wang 	if (err || !out_size || pause_info.mgmt_msg_head.status) {
686*f665790aSDavid Marchand 		PMD_DRV_LOG(ERR, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x",
687ef6f2f5cSXiaoyun Wang 			err, pause_info.mgmt_msg_head.status, out_size);
6882ae8e130SXiaoyun Wang 		return -EIO;
689ef6f2f5cSXiaoyun Wang 	}
690ef6f2f5cSXiaoyun Wang 
691ef6f2f5cSXiaoyun Wang 	nic_pause->auto_neg = pause_info.auto_neg;
692ef6f2f5cSXiaoyun Wang 	nic_pause->rx_pause = pause_info.rx_pause;
693ef6f2f5cSXiaoyun Wang 	nic_pause->tx_pause = pause_info.tx_pause;
694ef6f2f5cSXiaoyun Wang 
695ef6f2f5cSXiaoyun Wang 	return 0;
696ef6f2f5cSXiaoyun Wang }
697ef6f2f5cSXiaoyun Wang 
6982d5fd101SZiyang Xuan int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
6992d5fd101SZiyang Xuan 		      u8 *pgid, u8 *up_bw, u8 *prio)
7002d5fd101SZiyang Xuan {
7012d5fd101SZiyang Xuan 	struct hinic_up_ets_cfg ets;
7022d5fd101SZiyang Xuan 	u16 out_size = sizeof(ets);
7032d5fd101SZiyang Xuan 	u16 up_bw_t = 0;
7042d5fd101SZiyang Xuan 	u8 pg_bw_t = 0;
7052d5fd101SZiyang Xuan 	int i, err;
7062d5fd101SZiyang Xuan 
7072d5fd101SZiyang Xuan 	if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) {
7082d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL");
7092d5fd101SZiyang Xuan 		return -EINVAL;
7102d5fd101SZiyang Xuan 	}
7112d5fd101SZiyang Xuan 
7122d5fd101SZiyang Xuan 	for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
7132d5fd101SZiyang Xuan 		up_bw_t += *(up_bw + i);
7142d5fd101SZiyang Xuan 		pg_bw_t += *(pg_bw + i);
7152d5fd101SZiyang Xuan 
7162d5fd101SZiyang Xuan 		if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
7174f1af3cbSXiaoyun Wang 			PMD_DRV_LOG(ERR, "Invalid up %d mapping tc: %d", i,
7182d5fd101SZiyang Xuan 				*(up_tc + i));
7192d5fd101SZiyang Xuan 			return -EINVAL;
7202d5fd101SZiyang Xuan 		}
7212d5fd101SZiyang Xuan 	}
7222d5fd101SZiyang Xuan 
7232d5fd101SZiyang Xuan 	if (pg_bw_t != 100 || (up_bw_t % 100) != 0) {
7242d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
7252d5fd101SZiyang Xuan 			"Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t);
7262d5fd101SZiyang Xuan 		return -EINVAL;
7272d5fd101SZiyang Xuan 	}
7282d5fd101SZiyang Xuan 
7292d5fd101SZiyang Xuan 	memset(&ets, 0, sizeof(ets));
7302d5fd101SZiyang Xuan 	ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
7312d5fd101SZiyang Xuan 	ets.port_id = 0;	/* reserved */
7322d5fd101SZiyang Xuan 	memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX);
7332d5fd101SZiyang Xuan 	memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX);
7342d5fd101SZiyang Xuan 	memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX);
7352d5fd101SZiyang Xuan 	memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX);
7362d5fd101SZiyang Xuan 	memcpy(ets.prio, prio, HINIC_DCB_UP_MAX);
7372d5fd101SZiyang Xuan 
7382d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS,
7392d5fd101SZiyang Xuan 				     &ets, sizeof(ets), &ets, &out_size);
7402d5fd101SZiyang Xuan 	if (err || ets.mgmt_msg_head.status || !out_size) {
7412d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
7422d5fd101SZiyang Xuan 			"Failed to set ets, err: %d, status: 0x%x, out size: 0x%x",
7432d5fd101SZiyang Xuan 			err, ets.mgmt_msg_head.status, out_size);
7442ae8e130SXiaoyun Wang 		return -EIO;
7452d5fd101SZiyang Xuan 	}
7462d5fd101SZiyang Xuan 
7472d5fd101SZiyang Xuan 	return 0;
7482d5fd101SZiyang Xuan }
7492d5fd101SZiyang Xuan 
7502d5fd101SZiyang Xuan int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats)
7512d5fd101SZiyang Xuan {
7522d5fd101SZiyang Xuan 	struct hinic_port_stats_info vport_stats_cmd;
7532d5fd101SZiyang Xuan 	struct hinic_cmd_vport_stats vport_stats_rsp;
7542d5fd101SZiyang Xuan 	u16 out_size = sizeof(vport_stats_rsp);
7552d5fd101SZiyang Xuan 	int err;
7562d5fd101SZiyang Xuan 
7572d5fd101SZiyang Xuan 	if (!hwdev || !stats) {
7582d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
7592d5fd101SZiyang Xuan 		return -EINVAL;
7602d5fd101SZiyang Xuan 	}
7612d5fd101SZiyang Xuan 
7622d5fd101SZiyang Xuan 	memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp));
7632d5fd101SZiyang Xuan 	memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd));
7642d5fd101SZiyang Xuan 	vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
7652d5fd101SZiyang Xuan 	vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
7662d5fd101SZiyang Xuan 	vport_stats_cmd.func_id = hinic_global_func_id(hwdev);
7672d5fd101SZiyang Xuan 	vport_stats_cmd.stats_size = sizeof(vport_stats_rsp);
7682d5fd101SZiyang Xuan 
7692d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
7702d5fd101SZiyang Xuan 				     &vport_stats_cmd, sizeof(vport_stats_cmd),
7712d5fd101SZiyang Xuan 				     &vport_stats_rsp, &out_size);
7722d5fd101SZiyang Xuan 	if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) {
7732d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
7742d5fd101SZiyang Xuan 			"Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x",
7752d5fd101SZiyang Xuan 			err, vport_stats_rsp.mgmt_msg_head.status, out_size);
7762ae8e130SXiaoyun Wang 		return -EIO;
7772d5fd101SZiyang Xuan 	}
7782d5fd101SZiyang Xuan 
7792d5fd101SZiyang Xuan 	memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats));
7802d5fd101SZiyang Xuan 
7812d5fd101SZiyang Xuan 	return 0;
7822d5fd101SZiyang Xuan }
7832d5fd101SZiyang Xuan 
7842d5fd101SZiyang Xuan int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats)
7852d5fd101SZiyang Xuan {
7862d5fd101SZiyang Xuan 	struct hinic_port_stats_info port_stats_cmd;
7872d5fd101SZiyang Xuan 	struct hinic_port_stats port_stats_rsp;
7882d5fd101SZiyang Xuan 	u16 out_size = sizeof(port_stats_rsp);
7892d5fd101SZiyang Xuan 	int err;
7902d5fd101SZiyang Xuan 
7912d5fd101SZiyang Xuan 	if (!hwdev || !stats) {
7922d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
7932d5fd101SZiyang Xuan 		return -EINVAL;
7942d5fd101SZiyang Xuan 	}
7952d5fd101SZiyang Xuan 
7962d5fd101SZiyang Xuan 	memset(&port_stats_rsp, 0, sizeof(port_stats_rsp));
7972d5fd101SZiyang Xuan 	memset(&port_stats_cmd, 0, sizeof(port_stats_cmd));
7982d5fd101SZiyang Xuan 	port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
7992d5fd101SZiyang Xuan 	port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
8002d5fd101SZiyang Xuan 	port_stats_cmd.stats_size = sizeof(port_stats_rsp);
8012d5fd101SZiyang Xuan 
8022d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
8032d5fd101SZiyang Xuan 				     &port_stats_cmd, sizeof(port_stats_cmd),
8042d5fd101SZiyang Xuan 				     &port_stats_rsp, &out_size);
8052d5fd101SZiyang Xuan 	if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) {
8062d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
8072d5fd101SZiyang Xuan 			"Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x",
8082d5fd101SZiyang Xuan 			err, port_stats_rsp.mgmt_msg_head.status, out_size);
8092ae8e130SXiaoyun Wang 		return -EIO;
8102d5fd101SZiyang Xuan 	}
8112d5fd101SZiyang Xuan 
8122d5fd101SZiyang Xuan 	memcpy(stats, &port_stats_rsp.stats, sizeof(*stats));
8132d5fd101SZiyang Xuan 
8142d5fd101SZiyang Xuan 	return 0;
8152d5fd101SZiyang Xuan }
8162d5fd101SZiyang Xuan 
8172d5fd101SZiyang Xuan int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type)
8182d5fd101SZiyang Xuan {
8192d5fd101SZiyang Xuan 	struct nic_rss_context_tbl *ctx_tbl;
8202d5fd101SZiyang Xuan 	struct hinic_cmd_buf *cmd_buf;
8212d5fd101SZiyang Xuan 	u32 ctx = 0;
8222d5fd101SZiyang Xuan 	u64 out_param;
8232d5fd101SZiyang Xuan 	int err;
8242d5fd101SZiyang Xuan 
8252d5fd101SZiyang Xuan 	if (!hwdev) {
8262d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
8272d5fd101SZiyang Xuan 		return -EINVAL;
8282d5fd101SZiyang Xuan 	}
8292d5fd101SZiyang Xuan 
8302d5fd101SZiyang Xuan 	cmd_buf = hinic_alloc_cmd_buf(hwdev);
8312d5fd101SZiyang Xuan 	if (!cmd_buf) {
8322d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
8332d5fd101SZiyang Xuan 		return -ENOMEM;
8342d5fd101SZiyang Xuan 	}
8352d5fd101SZiyang Xuan 
8362d5fd101SZiyang Xuan 	ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
8372d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
8382d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
8392d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
8402d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
8412d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
8422d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
8432d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
8442d5fd101SZiyang Xuan 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
8452d5fd101SZiyang Xuan 
8462d5fd101SZiyang Xuan 	cmd_buf->size = sizeof(struct nic_rss_context_tbl);
8472d5fd101SZiyang Xuan 
8482d5fd101SZiyang Xuan 	ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf;
8492d5fd101SZiyang Xuan 	ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
8502d5fd101SZiyang Xuan 	ctx_tbl->offset = 0;
8512d5fd101SZiyang Xuan 	ctx_tbl->size = sizeof(u32);
8522d5fd101SZiyang Xuan 	ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
8532d5fd101SZiyang Xuan 	ctx_tbl->rsvd = 0;
8542d5fd101SZiyang Xuan 	ctx_tbl->ctx = cpu_to_be32(ctx);
8552d5fd101SZiyang Xuan 
8562d5fd101SZiyang Xuan 	/* cfg the rss context table by command queue */
8572d5fd101SZiyang Xuan 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
8582d5fd101SZiyang Xuan 				     HINIC_MOD_L2NIC,
8592d5fd101SZiyang Xuan 				     HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
8602d5fd101SZiyang Xuan 				     cmd_buf, &out_param, 0);
8612d5fd101SZiyang Xuan 
8622d5fd101SZiyang Xuan 	hinic_free_cmd_buf(hwdev, cmd_buf);
8632d5fd101SZiyang Xuan 
8642d5fd101SZiyang Xuan 	if (err || out_param != 0) {
8652d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set rss context table");
8662ae8e130SXiaoyun Wang 		return -EIO;
8672d5fd101SZiyang Xuan 	}
8682d5fd101SZiyang Xuan 
8692d5fd101SZiyang Xuan 	return 0;
8702d5fd101SZiyang Xuan }
8712d5fd101SZiyang Xuan 
8722d5fd101SZiyang Xuan int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type)
8732d5fd101SZiyang Xuan {
8742d5fd101SZiyang Xuan 	struct hinic_rss_context_table ctx_tbl;
8752d5fd101SZiyang Xuan 	u16 out_size = sizeof(ctx_tbl);
8762d5fd101SZiyang Xuan 	int err;
8772d5fd101SZiyang Xuan 
8782d5fd101SZiyang Xuan 	if (!hwdev || !rss_type) {
8792d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL");
8802d5fd101SZiyang Xuan 		return -EINVAL;
8812d5fd101SZiyang Xuan 	}
8822d5fd101SZiyang Xuan 
8832d5fd101SZiyang Xuan 	ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
8842d5fd101SZiyang Xuan 	ctx_tbl.func_id = hinic_global_func_id(hwdev);
8852d5fd101SZiyang Xuan 	ctx_tbl.template_id = (u8)tmpl_idx;
8862d5fd101SZiyang Xuan 
8872d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
8882d5fd101SZiyang Xuan 				     &ctx_tbl, sizeof(ctx_tbl),
8892d5fd101SZiyang Xuan 				     &ctx_tbl, &out_size);
8902d5fd101SZiyang Xuan 	if (err || !out_size || ctx_tbl.mgmt_msg_head.status) {
8912d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
8922d5fd101SZiyang Xuan 			"Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x",
8932d5fd101SZiyang Xuan 			err, ctx_tbl.mgmt_msg_head.status, out_size);
8942ae8e130SXiaoyun Wang 		return -EIO;
8952d5fd101SZiyang Xuan 	}
8962d5fd101SZiyang Xuan 
8972d5fd101SZiyang Xuan 	rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
8982d5fd101SZiyang Xuan 	rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
8992d5fd101SZiyang Xuan 	rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
9002d5fd101SZiyang Xuan 	rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
9012d5fd101SZiyang Xuan 	rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
9022d5fd101SZiyang Xuan 	rss_type->tcp_ipv6_ext =
9032d5fd101SZiyang Xuan 			HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT);
9042d5fd101SZiyang Xuan 	rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
9052d5fd101SZiyang Xuan 	rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
9062d5fd101SZiyang Xuan 
9072d5fd101SZiyang Xuan 	return 0;
9082d5fd101SZiyang Xuan }
9092d5fd101SZiyang Xuan 
9102d5fd101SZiyang Xuan int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
9112d5fd101SZiyang Xuan {
9122d5fd101SZiyang Xuan 	struct hinic_rss_template_key temp_key;
9132d5fd101SZiyang Xuan 	u16 out_size = sizeof(temp_key);
9142d5fd101SZiyang Xuan 	int err;
9152d5fd101SZiyang Xuan 
9162d5fd101SZiyang Xuan 	if (!hwdev || !temp) {
9172d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
9182d5fd101SZiyang Xuan 		return -EINVAL;
9192d5fd101SZiyang Xuan 	}
9202d5fd101SZiyang Xuan 
9212d5fd101SZiyang Xuan 	memset(&temp_key, 0, sizeof(temp_key));
9222d5fd101SZiyang Xuan 	temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
9232d5fd101SZiyang Xuan 	temp_key.func_id = hinic_global_func_id(hwdev);
9242d5fd101SZiyang Xuan 	temp_key.template_id = (u8)tmpl_idx;
9252d5fd101SZiyang Xuan 	memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
9262d5fd101SZiyang Xuan 
9272d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
9282d5fd101SZiyang Xuan 				     &temp_key, sizeof(temp_key),
9292d5fd101SZiyang Xuan 				     &temp_key, &out_size);
9302d5fd101SZiyang Xuan 	if (err || !out_size || temp_key.mgmt_msg_head.status) {
9312d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
9322d5fd101SZiyang Xuan 			"Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x",
9332d5fd101SZiyang Xuan 			err, temp_key.mgmt_msg_head.status, out_size);
9342ae8e130SXiaoyun Wang 		return -EIO;
9352d5fd101SZiyang Xuan 	}
9362d5fd101SZiyang Xuan 
9372d5fd101SZiyang Xuan 	return 0;
9382d5fd101SZiyang Xuan }
9392d5fd101SZiyang Xuan 
9402d5fd101SZiyang Xuan int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
9412d5fd101SZiyang Xuan {
9422d5fd101SZiyang Xuan 	struct hinic_rss_template_key temp_key;
9432d5fd101SZiyang Xuan 	u16 out_size = sizeof(temp_key);
9442d5fd101SZiyang Xuan 	int err;
9452d5fd101SZiyang Xuan 
9462d5fd101SZiyang Xuan 	if (!hwdev || !temp) {
9472d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
9482d5fd101SZiyang Xuan 		return -EINVAL;
9492d5fd101SZiyang Xuan 	}
9502d5fd101SZiyang Xuan 
9512d5fd101SZiyang Xuan 	memset(&temp_key, 0, sizeof(temp_key));
9522d5fd101SZiyang Xuan 	temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
9532d5fd101SZiyang Xuan 	temp_key.func_id = hinic_global_func_id(hwdev);
9542d5fd101SZiyang Xuan 	temp_key.template_id = (u8)tmpl_idx;
9552d5fd101SZiyang Xuan 
9562d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
9572d5fd101SZiyang Xuan 				     &temp_key, sizeof(temp_key),
9582d5fd101SZiyang Xuan 				     &temp_key, &out_size);
9592d5fd101SZiyang Xuan 	if (err || !out_size || temp_key.mgmt_msg_head.status) {
9602d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x",
9612d5fd101SZiyang Xuan 			err, temp_key.mgmt_msg_head.status, out_size);
9622ae8e130SXiaoyun Wang 		return -EIO;
9632d5fd101SZiyang Xuan 	}
9642d5fd101SZiyang Xuan 
9652d5fd101SZiyang Xuan 	memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
9662d5fd101SZiyang Xuan 
9672d5fd101SZiyang Xuan 	return 0;
9682d5fd101SZiyang Xuan }
9692d5fd101SZiyang Xuan 
9702d5fd101SZiyang Xuan /**
9712d5fd101SZiyang Xuan  * hinic_rss_set_hash_engine - Init rss hash function.
972b8582d05SXiaoyun Wang  *
973b8582d05SXiaoyun Wang  * @param hwdev
974b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
975b8582d05SXiaoyun Wang  * @param tmpl_idx
976b8582d05SXiaoyun Wang  *   Index of rss template from NIC.
977b8582d05SXiaoyun Wang  * @param type
978b8582d05SXiaoyun Wang  *   Hash function, such as Toeplitz or XOR.
979b8582d05SXiaoyun Wang  *
9802d5fd101SZiyang Xuan  * @return
981b8582d05SXiaoyun Wang  *   0 on success.
9822d5fd101SZiyang Xuan  *   negative error value otherwise.
9832d5fd101SZiyang Xuan  */
9842d5fd101SZiyang Xuan int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
9852d5fd101SZiyang Xuan {
9862d5fd101SZiyang Xuan 	struct hinic_rss_engine_type hash_type;
9872d5fd101SZiyang Xuan 	u16 out_size = sizeof(hash_type);
9882d5fd101SZiyang Xuan 	int err;
9892d5fd101SZiyang Xuan 
9902d5fd101SZiyang Xuan 	if (!hwdev) {
9912d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
9922d5fd101SZiyang Xuan 		return -EINVAL;
9932d5fd101SZiyang Xuan 	}
9942d5fd101SZiyang Xuan 
9952d5fd101SZiyang Xuan 	memset(&hash_type, 0, sizeof(hash_type));
9962d5fd101SZiyang Xuan 	hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
9972d5fd101SZiyang Xuan 	hash_type.func_id = hinic_global_func_id(hwdev);
9982d5fd101SZiyang Xuan 	hash_type.hash_engine = type;
9992d5fd101SZiyang Xuan 	hash_type.template_id = tmpl_idx;
10002d5fd101SZiyang Xuan 
10012d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
10022d5fd101SZiyang Xuan 				     &hash_type, sizeof(hash_type),
10032d5fd101SZiyang Xuan 				     &hash_type, &out_size);
10042d5fd101SZiyang Xuan 	if (err || !out_size || hash_type.mgmt_msg_head.status) {
10052d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x",
10062d5fd101SZiyang Xuan 			err, hash_type.mgmt_msg_head.status, out_size);
10072ae8e130SXiaoyun Wang 		return -EIO;
10082d5fd101SZiyang Xuan 	}
10092d5fd101SZiyang Xuan 
10102d5fd101SZiyang Xuan 	return 0;
10112d5fd101SZiyang Xuan }
10122d5fd101SZiyang Xuan 
10132d5fd101SZiyang Xuan int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
10142d5fd101SZiyang Xuan {
10152d5fd101SZiyang Xuan 	struct nic_rss_indirect_tbl *indir_tbl;
10162d5fd101SZiyang Xuan 	struct hinic_cmd_buf *cmd_buf;
10172d5fd101SZiyang Xuan 	int i;
10182d5fd101SZiyang Xuan 	u32 *temp;
10192d5fd101SZiyang Xuan 	u32 indir_size;
10202d5fd101SZiyang Xuan 	u64 out_param;
10212d5fd101SZiyang Xuan 	int err;
10222d5fd101SZiyang Xuan 
10232d5fd101SZiyang Xuan 	if (!hwdev || !indir_table) {
10242d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
10252d5fd101SZiyang Xuan 		return -EINVAL;
10262d5fd101SZiyang Xuan 	}
10272d5fd101SZiyang Xuan 
10282d5fd101SZiyang Xuan 	cmd_buf = hinic_alloc_cmd_buf(hwdev);
10292d5fd101SZiyang Xuan 	if (!cmd_buf) {
10302d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
10312d5fd101SZiyang Xuan 		return -ENOMEM;
10322d5fd101SZiyang Xuan 	}
10332d5fd101SZiyang Xuan 
10342d5fd101SZiyang Xuan 	cmd_buf->size = sizeof(struct nic_rss_indirect_tbl);
10352d5fd101SZiyang Xuan 	indir_tbl = cmd_buf->buf;
10362d5fd101SZiyang Xuan 	indir_tbl->group_index = cpu_to_be32(tmpl_idx);
10372d5fd101SZiyang Xuan 
10382d5fd101SZiyang Xuan 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
10392d5fd101SZiyang Xuan 		indir_tbl->entry[i] = (u8)(*(indir_table + i));
10402d5fd101SZiyang Xuan 
10412d5fd101SZiyang Xuan 		if (0x3 == (i & 0x3)) {
10422d5fd101SZiyang Xuan 			temp = (u32 *)&indir_tbl->entry[i - 3];
10432d5fd101SZiyang Xuan 			*temp = cpu_to_be32(*temp);
10442d5fd101SZiyang Xuan 		}
10452d5fd101SZiyang Xuan 	}
10462d5fd101SZiyang Xuan 
10472d5fd101SZiyang Xuan 	/* configure the rss indirect table by command queue */
10482d5fd101SZiyang Xuan 	indir_size = HINIC_RSS_INDIR_SIZE / 2;
10492d5fd101SZiyang Xuan 	indir_tbl->offset = 0;
10502d5fd101SZiyang Xuan 	indir_tbl->size = cpu_to_be32(indir_size);
10512d5fd101SZiyang Xuan 
10522d5fd101SZiyang Xuan 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
10532d5fd101SZiyang Xuan 				     HINIC_MOD_L2NIC,
10542d5fd101SZiyang Xuan 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
10552d5fd101SZiyang Xuan 				     cmd_buf, &out_param, 0);
10562d5fd101SZiyang Xuan 	if (err || out_param != 0) {
10572d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set rss indir table");
10582ae8e130SXiaoyun Wang 		err = -EIO;
10592d5fd101SZiyang Xuan 		goto free_buf;
10602d5fd101SZiyang Xuan 	}
10612d5fd101SZiyang Xuan 
10622d5fd101SZiyang Xuan 	indir_tbl->offset = cpu_to_be32(indir_size);
10632d5fd101SZiyang Xuan 	indir_tbl->size = cpu_to_be32(indir_size);
10642d5fd101SZiyang Xuan 	memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size);
10652d5fd101SZiyang Xuan 
10662d5fd101SZiyang Xuan 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
10672d5fd101SZiyang Xuan 				     HINIC_MOD_L2NIC,
10682d5fd101SZiyang Xuan 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
10692d5fd101SZiyang Xuan 				     cmd_buf, &out_param, 0);
10702d5fd101SZiyang Xuan 	if (err || out_param != 0) {
10712d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set rss indir table");
10722ae8e130SXiaoyun Wang 		err = -EIO;
10732d5fd101SZiyang Xuan 	}
10742d5fd101SZiyang Xuan 
10752d5fd101SZiyang Xuan free_buf:
10762d5fd101SZiyang Xuan 	hinic_free_cmd_buf(hwdev, cmd_buf);
10772d5fd101SZiyang Xuan 
10782d5fd101SZiyang Xuan 	return err;
10792d5fd101SZiyang Xuan }
10802d5fd101SZiyang Xuan 
10812d5fd101SZiyang Xuan int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
10822d5fd101SZiyang Xuan {
10832d5fd101SZiyang Xuan 	struct hinic_rss_indir_table rss_cfg;
10842d5fd101SZiyang Xuan 	u16 out_size = sizeof(rss_cfg);
10852d5fd101SZiyang Xuan 	int err = 0, i;
10862d5fd101SZiyang Xuan 
10872d5fd101SZiyang Xuan 	if (!hwdev || !indir_table) {
10882d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
10892d5fd101SZiyang Xuan 		return -EINVAL;
10902d5fd101SZiyang Xuan 	}
10912d5fd101SZiyang Xuan 
10922d5fd101SZiyang Xuan 	memset(&rss_cfg, 0, sizeof(rss_cfg));
10932d5fd101SZiyang Xuan 	rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
10942d5fd101SZiyang Xuan 	rss_cfg.func_id = hinic_global_func_id(hwdev);
10952d5fd101SZiyang Xuan 	rss_cfg.template_id = (u8)tmpl_idx;
10962d5fd101SZiyang Xuan 
10972d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev,
10982d5fd101SZiyang Xuan 				     HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
10992d5fd101SZiyang Xuan 				     &rss_cfg, sizeof(rss_cfg), &rss_cfg,
11002d5fd101SZiyang Xuan 				     &out_size);
11012d5fd101SZiyang Xuan 	if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
11022d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x",
11032d5fd101SZiyang Xuan 			err, rss_cfg.mgmt_msg_head.status, out_size);
11042ae8e130SXiaoyun Wang 		return -EIO;
11052d5fd101SZiyang Xuan 	}
11062d5fd101SZiyang Xuan 
11072d5fd101SZiyang Xuan 	hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
11082d5fd101SZiyang Xuan 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
11092d5fd101SZiyang Xuan 		indir_table[i] = rss_cfg.indir[i];
11102d5fd101SZiyang Xuan 
11112d5fd101SZiyang Xuan 	return 0;
11122d5fd101SZiyang Xuan }
11132d5fd101SZiyang Xuan 
11142d5fd101SZiyang Xuan int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc)
11152d5fd101SZiyang Xuan {
11162d5fd101SZiyang Xuan 	struct hinic_rss_config rss_cfg;
11172d5fd101SZiyang Xuan 	u16 out_size = sizeof(rss_cfg);
11182d5fd101SZiyang Xuan 	int err;
11192d5fd101SZiyang Xuan 
11202d5fd101SZiyang Xuan 	/* micro code required: number of TC should be power of 2 */
11212d5fd101SZiyang Xuan 	if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) {
11222d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2",
11232d5fd101SZiyang Xuan 			tc_num);
11242d5fd101SZiyang Xuan 		return -EINVAL;
11252d5fd101SZiyang Xuan 	}
11262d5fd101SZiyang Xuan 
11272d5fd101SZiyang Xuan 	memset(&rss_cfg, 0, sizeof(rss_cfg));
11282d5fd101SZiyang Xuan 	rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
11292d5fd101SZiyang Xuan 	rss_cfg.func_id = hinic_global_func_id(hwdev);
11302d5fd101SZiyang Xuan 	rss_cfg.rss_en = rss_en;
11312d5fd101SZiyang Xuan 	rss_cfg.template_id = tmpl_idx;
11322d5fd101SZiyang Xuan 	rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
11332d5fd101SZiyang Xuan 
11342d5fd101SZiyang Xuan 	memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX);
11352d5fd101SZiyang Xuan 
11362d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG,
11372d5fd101SZiyang Xuan 				     &rss_cfg, sizeof(rss_cfg), &rss_cfg,
11382d5fd101SZiyang Xuan 				     &out_size);
11392d5fd101SZiyang Xuan 	if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
11402d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x",
11412d5fd101SZiyang Xuan 			err, rss_cfg.mgmt_msg_head.status, out_size);
11422ae8e130SXiaoyun Wang 		return -EIO;
11432d5fd101SZiyang Xuan 	}
11442d5fd101SZiyang Xuan 
11452d5fd101SZiyang Xuan 	return 0;
11462d5fd101SZiyang Xuan }
11472d5fd101SZiyang Xuan 
11482d5fd101SZiyang Xuan /**
1149b8582d05SXiaoyun Wang  * hinic_rss_template_alloc - Get rss template id from the chip,
11502d5fd101SZiyang Xuan  * all functions share 96 templates.
1151b8582d05SXiaoyun Wang  *
1152b8582d05SXiaoyun Wang  * @param hwdev
1153b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
1154b8582d05SXiaoyun Wang  * @param tmpl_idx
1155b8582d05SXiaoyun Wang  *   Index of rss template from chip.
1156b8582d05SXiaoyun Wang  *
1157b8582d05SXiaoyun Wang  * @return
1158b8582d05SXiaoyun Wang  *   0 on success.
1159b8582d05SXiaoyun Wang  *   negative error value otherwise.
1160b8582d05SXiaoyun Wang  */
11612d5fd101SZiyang Xuan int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
11622d5fd101SZiyang Xuan {
11632d5fd101SZiyang Xuan 	struct hinic_rss_template_mgmt template_mgmt;
11642d5fd101SZiyang Xuan 	u16 out_size = sizeof(template_mgmt);
11652d5fd101SZiyang Xuan 	int err;
11662d5fd101SZiyang Xuan 
11672d5fd101SZiyang Xuan 	if (!hwdev || !tmpl_idx) {
11682d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL");
11692d5fd101SZiyang Xuan 		return -EINVAL;
11702d5fd101SZiyang Xuan 	}
11712d5fd101SZiyang Xuan 
11722d5fd101SZiyang Xuan 	memset(&template_mgmt, 0, sizeof(template_mgmt));
11732d5fd101SZiyang Xuan 	template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
11742d5fd101SZiyang Xuan 	template_mgmt.func_id = hinic_global_func_id(hwdev);
11752d5fd101SZiyang Xuan 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
11762d5fd101SZiyang Xuan 
11772d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
11782d5fd101SZiyang Xuan 				     &template_mgmt, sizeof(template_mgmt),
11792d5fd101SZiyang Xuan 				     &template_mgmt, &out_size);
11802d5fd101SZiyang Xuan 	if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
11812d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x",
11822d5fd101SZiyang Xuan 			err, template_mgmt.mgmt_msg_head.status, out_size);
11832ae8e130SXiaoyun Wang 		return -EIO;
11842d5fd101SZiyang Xuan 	}
11852d5fd101SZiyang Xuan 
11862d5fd101SZiyang Xuan 	*tmpl_idx = template_mgmt.template_id;
11872d5fd101SZiyang Xuan 
11882d5fd101SZiyang Xuan 	return 0;
11892d5fd101SZiyang Xuan }
11902d5fd101SZiyang Xuan 
11912d5fd101SZiyang Xuan /**
1192b8582d05SXiaoyun Wang  * hinic_rss_template_free - Free rss template id to the chip.
1193b8582d05SXiaoyun Wang  *
1194b8582d05SXiaoyun Wang  * @param hwdev
1195b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
1196b8582d05SXiaoyun Wang  * @param tmpl_idx
1197b8582d05SXiaoyun Wang  *   Index of rss template from chip.
1198b8582d05SXiaoyun Wang  *
1199b8582d05SXiaoyun Wang  * @return
1200b8582d05SXiaoyun Wang  *   0 on success.
1201b8582d05SXiaoyun Wang  *   negative error value otherwise.
1202b8582d05SXiaoyun Wang  */
12032d5fd101SZiyang Xuan int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
12042d5fd101SZiyang Xuan {
12052d5fd101SZiyang Xuan 	struct hinic_rss_template_mgmt template_mgmt;
12062d5fd101SZiyang Xuan 	u16 out_size = sizeof(template_mgmt);
12072d5fd101SZiyang Xuan 	int err;
12082d5fd101SZiyang Xuan 
12092d5fd101SZiyang Xuan 	if (!hwdev) {
12102d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
12112d5fd101SZiyang Xuan 		return -EINVAL;
12122d5fd101SZiyang Xuan 	}
12132d5fd101SZiyang Xuan 
12142d5fd101SZiyang Xuan 	memset(&template_mgmt, 0, sizeof(template_mgmt));
12152d5fd101SZiyang Xuan 	template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
12162d5fd101SZiyang Xuan 	template_mgmt.func_id = hinic_global_func_id(hwdev);
12172d5fd101SZiyang Xuan 	template_mgmt.template_id = tmpl_idx;
12182d5fd101SZiyang Xuan 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
12192d5fd101SZiyang Xuan 
12202d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
12212d5fd101SZiyang Xuan 				     &template_mgmt, sizeof(template_mgmt),
12222d5fd101SZiyang Xuan 				     &template_mgmt, &out_size);
12232d5fd101SZiyang Xuan 	if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
12242d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x",
12252d5fd101SZiyang Xuan 			err, template_mgmt.mgmt_msg_head.status, out_size);
12262ae8e130SXiaoyun Wang 		return -EIO;
12272d5fd101SZiyang Xuan 	}
12282d5fd101SZiyang Xuan 
12292d5fd101SZiyang Xuan 	return 0;
12302d5fd101SZiyang Xuan }
12312d5fd101SZiyang Xuan 
12322d5fd101SZiyang Xuan /**
1233b8582d05SXiaoyun Wang  * hinic_set_rx_vhd_mode - Change rx buffer size after initialization.
1234b8582d05SXiaoyun Wang  *
1235b8582d05SXiaoyun Wang  * @param hwdev
1236b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
1237b8582d05SXiaoyun Wang  * @param vhd_mode
1238b8582d05SXiaoyun Wang  *   Not needed.
1239b8582d05SXiaoyun Wang  * @param rx_buf_sz
1240b8582d05SXiaoyun Wang  *   receive buffer size.
1241b8582d05SXiaoyun Wang  *
12422d5fd101SZiyang Xuan  * @return
1243b8582d05SXiaoyun Wang  *   0 on success.
12442d5fd101SZiyang Xuan  *   negative error value otherwise.
12452d5fd101SZiyang Xuan  */
12462d5fd101SZiyang Xuan int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
12472d5fd101SZiyang Xuan {
12482d5fd101SZiyang Xuan 	struct hinic_set_vhd_mode vhd_mode_cfg;
12492d5fd101SZiyang Xuan 	u16 out_size = sizeof(vhd_mode_cfg);
12502d5fd101SZiyang Xuan 	int err;
12512d5fd101SZiyang Xuan 
12522d5fd101SZiyang Xuan 	if (!hwdev) {
12532d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
12542d5fd101SZiyang Xuan 		return -EINVAL;
12552d5fd101SZiyang Xuan 	}
12562d5fd101SZiyang Xuan 
12572d5fd101SZiyang Xuan 	memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg));
12582d5fd101SZiyang Xuan 
12592d5fd101SZiyang Xuan 	vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
12602d5fd101SZiyang Xuan 	vhd_mode_cfg.func_id = hinic_global_func_id(hwdev);
12612d5fd101SZiyang Xuan 	vhd_mode_cfg.vhd_type = vhd_mode;
12622d5fd101SZiyang Xuan 	vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz;
12632d5fd101SZiyang Xuan 
12642d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG,
12652d5fd101SZiyang Xuan 				     &vhd_mode_cfg, sizeof(vhd_mode_cfg),
12662d5fd101SZiyang Xuan 				     &vhd_mode_cfg, &out_size);
12672d5fd101SZiyang Xuan 	if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) {
12682d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
12692d5fd101SZiyang Xuan 			"Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
12702d5fd101SZiyang Xuan 			err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
12712d5fd101SZiyang Xuan 		return -EIO;
12722d5fd101SZiyang Xuan 	}
12732d5fd101SZiyang Xuan 
12742d5fd101SZiyang Xuan 	return 0;
12752d5fd101SZiyang Xuan }
12762d5fd101SZiyang Xuan 
12772d5fd101SZiyang Xuan int hinic_set_rx_mode(void *hwdev, u32 enable)
12782d5fd101SZiyang Xuan {
12792d5fd101SZiyang Xuan 	struct hinic_rx_mode_config rx_mode_cfg;
12802d5fd101SZiyang Xuan 	u16 out_size = sizeof(rx_mode_cfg);
12812d5fd101SZiyang Xuan 	int err;
12822d5fd101SZiyang Xuan 
12832d5fd101SZiyang Xuan 	if (!hwdev) {
12842d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
12852d5fd101SZiyang Xuan 		return -EINVAL;
12862d5fd101SZiyang Xuan 	}
12872d5fd101SZiyang Xuan 
12882d5fd101SZiyang Xuan 	memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
12892d5fd101SZiyang Xuan 	rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
12902d5fd101SZiyang Xuan 	rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
12912d5fd101SZiyang Xuan 	rx_mode_cfg.rx_mode = enable;
12922d5fd101SZiyang Xuan 
12932d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
12942d5fd101SZiyang Xuan 				     &rx_mode_cfg, sizeof(rx_mode_cfg),
12952d5fd101SZiyang Xuan 				     &rx_mode_cfg, &out_size);
12962d5fd101SZiyang Xuan 	if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) {
12972d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x",
12982d5fd101SZiyang Xuan 			err, rx_mode_cfg.mgmt_msg_head.status, out_size);
12992ae8e130SXiaoyun Wang 		return -EIO;
13002d5fd101SZiyang Xuan 	}
13012d5fd101SZiyang Xuan 
13022d5fd101SZiyang Xuan 	return 0;
13032d5fd101SZiyang Xuan }
13042d5fd101SZiyang Xuan 
1305dbf524abSXiaoyun Wang /**
1306dbf524abSXiaoyun Wang  * hinic_get_mgmt_version - Get mgmt module version from chip.
1307dbf524abSXiaoyun Wang  *
1308dbf524abSXiaoyun Wang  * @param hwdev
1309dbf524abSXiaoyun Wang  *   The hardware interface of a nic device.
1310dbf524abSXiaoyun Wang  * @param fw
1311dbf524abSXiaoyun Wang  *   Firmware version.
1312dbf524abSXiaoyun Wang  *
1313dbf524abSXiaoyun Wang  * @return
1314dbf524abSXiaoyun Wang  *   0 on success.
1315dbf524abSXiaoyun Wang  *   negative error value otherwise.
1316dbf524abSXiaoyun Wang  */
1317dbf524abSXiaoyun Wang int hinic_get_mgmt_version(void *hwdev, char *fw)
1318dbf524abSXiaoyun Wang {
1319dbf524abSXiaoyun Wang 	struct hinic_version_info fw_ver;
1320dbf524abSXiaoyun Wang 	u16 out_size = sizeof(fw_ver);
1321dbf524abSXiaoyun Wang 	int err;
1322dbf524abSXiaoyun Wang 
1323dbf524abSXiaoyun Wang 	if (!hwdev || !fw) {
1324dbf524abSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev or fw is NULL");
1325dbf524abSXiaoyun Wang 		return -EINVAL;
1326dbf524abSXiaoyun Wang 	}
1327dbf524abSXiaoyun Wang 
1328dbf524abSXiaoyun Wang 	memset(&fw_ver, 0, sizeof(fw_ver));
1329dbf524abSXiaoyun Wang 	fw_ver.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1330dbf524abSXiaoyun Wang 
1331dbf524abSXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MGMT_VERSION,
1332dbf524abSXiaoyun Wang 				     &fw_ver, sizeof(fw_ver), &fw_ver,
1333dbf524abSXiaoyun Wang 				     &out_size);
1334dbf524abSXiaoyun Wang 	if (err || !out_size || fw_ver.mgmt_msg_head.status) {
1335*f665790aSDavid Marchand 		PMD_DRV_LOG(ERR, "Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x",
1336dbf524abSXiaoyun Wang 			err, fw_ver.mgmt_msg_head.status, out_size);
13372ae8e130SXiaoyun Wang 		return -EIO;
1338dbf524abSXiaoyun Wang 	}
1339dbf524abSXiaoyun Wang 
1340dbf524abSXiaoyun Wang 	snprintf(fw, HINIC_MGMT_VERSION_MAX_LEN, "%s", fw_ver.ver);
1341dbf524abSXiaoyun Wang 
1342dbf524abSXiaoyun Wang 	return 0;
1343dbf524abSXiaoyun Wang }
1344dbf524abSXiaoyun Wang 
13452d5fd101SZiyang Xuan int hinic_set_rx_csum_offload(void *hwdev, u32 en)
13462d5fd101SZiyang Xuan {
13472d5fd101SZiyang Xuan 	struct hinic_checksum_offload rx_csum_cfg;
13482d5fd101SZiyang Xuan 	u16 out_size = sizeof(rx_csum_cfg);
13492d5fd101SZiyang Xuan 	int err;
13502d5fd101SZiyang Xuan 
13512d5fd101SZiyang Xuan 	if (!hwdev) {
13522d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
13532d5fd101SZiyang Xuan 		return -EINVAL;
13542d5fd101SZiyang Xuan 	}
13552d5fd101SZiyang Xuan 
13562d5fd101SZiyang Xuan 	memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg));
13572d5fd101SZiyang Xuan 	rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
13582d5fd101SZiyang Xuan 	rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
13592d5fd101SZiyang Xuan 	rx_csum_cfg.rx_csum_offload = en;
13602d5fd101SZiyang Xuan 
13612d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
13622d5fd101SZiyang Xuan 				     &rx_csum_cfg, sizeof(rx_csum_cfg),
13632d5fd101SZiyang Xuan 				     &rx_csum_cfg, &out_size);
13642d5fd101SZiyang Xuan 	if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) {
13652d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
13662d5fd101SZiyang Xuan 			"Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x",
13672d5fd101SZiyang Xuan 			err, rx_csum_cfg.mgmt_msg_head.status, out_size);
13682ae8e130SXiaoyun Wang 		return -EIO;
13692d5fd101SZiyang Xuan 	}
13702d5fd101SZiyang Xuan 
13712d5fd101SZiyang Xuan 	return 0;
13722d5fd101SZiyang Xuan }
13732d5fd101SZiyang Xuan 
13742d5fd101SZiyang Xuan int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num)
13752d5fd101SZiyang Xuan {
13762d5fd101SZiyang Xuan 	struct hinic_lro_config lro_cfg;
13772d5fd101SZiyang Xuan 	u16 out_size = sizeof(lro_cfg);
13782d5fd101SZiyang Xuan 	int err;
13792d5fd101SZiyang Xuan 
13802d5fd101SZiyang Xuan 	if (!hwdev) {
13812d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
13822d5fd101SZiyang Xuan 		return -EINVAL;
13832d5fd101SZiyang Xuan 	}
13842d5fd101SZiyang Xuan 
13852d5fd101SZiyang Xuan 	memset(&lro_cfg, 0, sizeof(lro_cfg));
13862d5fd101SZiyang Xuan 	lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
13872d5fd101SZiyang Xuan 	lro_cfg.func_id = hinic_global_func_id(hwdev);
13882d5fd101SZiyang Xuan 	lro_cfg.lro_ipv4_en = ipv4_en;
13892d5fd101SZiyang Xuan 	lro_cfg.lro_ipv6_en = ipv6_en;
13902d5fd101SZiyang Xuan 	lro_cfg.lro_max_wqe_num = max_wqe_num;
13912d5fd101SZiyang Xuan 
13922d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO,
13932d5fd101SZiyang Xuan 				     &lro_cfg, sizeof(lro_cfg), &lro_cfg,
13942d5fd101SZiyang Xuan 				     &out_size);
13952d5fd101SZiyang Xuan 	if (err || !out_size || lro_cfg.mgmt_msg_head.status) {
13962d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x",
13972d5fd101SZiyang Xuan 			err, lro_cfg.mgmt_msg_head.status, out_size);
13982ae8e130SXiaoyun Wang 		return -EIO;
13992d5fd101SZiyang Xuan 	}
14002d5fd101SZiyang Xuan 
14012d5fd101SZiyang Xuan 	return 0;
14022d5fd101SZiyang Xuan }
14032d5fd101SZiyang Xuan 
14042d5fd101SZiyang Xuan int hinic_set_anti_attack(void *hwdev, bool enable)
14052d5fd101SZiyang Xuan {
14062d5fd101SZiyang Xuan 	struct hinic_port_anti_attack_rate rate;
14072d5fd101SZiyang Xuan 	u16 out_size = sizeof(rate);
14082d5fd101SZiyang Xuan 	int err;
14092d5fd101SZiyang Xuan 
14102d5fd101SZiyang Xuan 	if (!hwdev) {
14112d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
14122d5fd101SZiyang Xuan 		return -EINVAL;
14132d5fd101SZiyang Xuan 	}
14142d5fd101SZiyang Xuan 
14152d5fd101SZiyang Xuan 	memset(&rate, 0, sizeof(rate));
14162d5fd101SZiyang Xuan 	rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
14172d5fd101SZiyang Xuan 	rate.func_id = hinic_global_func_id(hwdev);
14182d5fd101SZiyang Xuan 	rate.enable = enable;
14192d5fd101SZiyang Xuan 	rate.cir = ANTI_ATTACK_DEFAULT_CIR;
14202d5fd101SZiyang Xuan 	rate.xir = ANTI_ATTACK_DEFAULT_XIR;
14212d5fd101SZiyang Xuan 	rate.cbs = ANTI_ATTACK_DEFAULT_CBS;
14222d5fd101SZiyang Xuan 	rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
14232d5fd101SZiyang Xuan 
14242d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
1425d807dd7dSXiaoyun Wang 				     &rate, sizeof(rate), &rate, &out_size);
14262d5fd101SZiyang Xuan 	if (err || !out_size || rate.mgmt_msg_head.status) {
14274f1af3cbSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
14282d5fd101SZiyang Xuan 			(enable ? "enable" : "disable"), err,
14292d5fd101SZiyang Xuan 			rate.mgmt_msg_head.status, out_size);
14302ae8e130SXiaoyun Wang 		return -EIO;
14312d5fd101SZiyang Xuan 	}
14322d5fd101SZiyang Xuan 
14332d5fd101SZiyang Xuan 	return 0;
14342d5fd101SZiyang Xuan }
14352d5fd101SZiyang Xuan 
14362d5fd101SZiyang Xuan /* Set autoneg status and restart port link status */
14372d5fd101SZiyang Xuan int hinic_reset_port_link_cfg(void *hwdev)
14382d5fd101SZiyang Xuan {
14392d5fd101SZiyang Xuan 	struct hinic_reset_link_cfg reset_cfg;
14402d5fd101SZiyang Xuan 	u16 out_size = sizeof(reset_cfg);
14412d5fd101SZiyang Xuan 	int err;
14422d5fd101SZiyang Xuan 
14432d5fd101SZiyang Xuan 	memset(&reset_cfg, 0, sizeof(reset_cfg));
14442d5fd101SZiyang Xuan 	reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
14452d5fd101SZiyang Xuan 	reset_cfg.func_id = hinic_global_func_id(hwdev);
14462d5fd101SZiyang Xuan 
14472d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
14482d5fd101SZiyang Xuan 				     &reset_cfg, sizeof(reset_cfg),
14492d5fd101SZiyang Xuan 				     &reset_cfg, &out_size);
14502d5fd101SZiyang Xuan 	if (err || !out_size || reset_cfg.mgmt_msg_head.status) {
14512d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x",
14522d5fd101SZiyang Xuan 			err, reset_cfg.mgmt_msg_head.status, out_size);
14532ae8e130SXiaoyun Wang 		return -EIO;
14542d5fd101SZiyang Xuan 	}
14552d5fd101SZiyang Xuan 
14562d5fd101SZiyang Xuan 	return 0;
14572d5fd101SZiyang Xuan }
14582d5fd101SZiyang Xuan 
1459b8582d05SXiaoyun Wang /**
1460b8582d05SXiaoyun Wang  * hinic_vf_func_init - Register VF to PF.
1461b8582d05SXiaoyun Wang  *
1462b8582d05SXiaoyun Wang  * @param hwdev
1463b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
1464b8582d05SXiaoyun Wang  *
1465b8582d05SXiaoyun Wang  * @return
1466b8582d05SXiaoyun Wang  *   0 on success.
1467b8582d05SXiaoyun Wang  *   negative error value otherwise.
1468b8582d05SXiaoyun Wang  */
1469b8582d05SXiaoyun Wang int hinic_vf_func_init(struct hinic_hwdev *hwdev)
1470b8582d05SXiaoyun Wang {
1471b8582d05SXiaoyun Wang 	int err, state = 0;
1472b8582d05SXiaoyun Wang 
1473b8582d05SXiaoyun Wang 	if (!HINIC_IS_VF(hwdev))
1474b8582d05SXiaoyun Wang 		return 0;
1475b8582d05SXiaoyun Wang 
1476b8582d05SXiaoyun Wang 	err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1477b8582d05SXiaoyun Wang 			HINIC_PORT_CMD_VF_REGISTER, &state, sizeof(state),
1478b8582d05SXiaoyun Wang 			NULL, NULL, 0);
1479b8582d05SXiaoyun Wang 	if (err) {
1480b8582d05SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Fail to register vf");
1481b8582d05SXiaoyun Wang 		return err;
1482b8582d05SXiaoyun Wang 	}
1483b8582d05SXiaoyun Wang 
1484b8582d05SXiaoyun Wang 	return 0;
1485b8582d05SXiaoyun Wang }
1486b8582d05SXiaoyun Wang 
1487b8582d05SXiaoyun Wang /**
1488b8582d05SXiaoyun Wang  * hinic_vf_func_free - Unregister VF from PF.
1489b8582d05SXiaoyun Wang  *
1490b8582d05SXiaoyun Wang  * @param hwdev
1491b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
1492b8582d05SXiaoyun Wang  */
1493b8582d05SXiaoyun Wang void hinic_vf_func_free(struct hinic_hwdev *hwdev)
1494b8582d05SXiaoyun Wang {
1495b8582d05SXiaoyun Wang 	int err;
1496b8582d05SXiaoyun Wang 
1497b8582d05SXiaoyun Wang 	if (hinic_func_type(hwdev) != TYPE_VF)
1498b8582d05SXiaoyun Wang 		return;
1499b8582d05SXiaoyun Wang 
1500b8582d05SXiaoyun Wang 	err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1501b8582d05SXiaoyun Wang 				HINIC_PORT_CMD_VF_UNREGISTER, &err, sizeof(err),
1502b8582d05SXiaoyun Wang 				NULL, NULL, 0);
1503b8582d05SXiaoyun Wang 	if (err)
1504b8582d05SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Fail to unregister VF, err: %d", err);
1505b8582d05SXiaoyun Wang }
1506b8582d05SXiaoyun Wang 
15072d5fd101SZiyang Xuan int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
15082d5fd101SZiyang Xuan {
15092d5fd101SZiyang Xuan 	struct hinic_fast_recycled_mode fast_recycled_mode;
15102d5fd101SZiyang Xuan 	u16 out_size = sizeof(fast_recycled_mode);
15112d5fd101SZiyang Xuan 	int err;
15122d5fd101SZiyang Xuan 
15132d5fd101SZiyang Xuan 	if (!hwdev) {
15142d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
15152d5fd101SZiyang Xuan 		return -EINVAL;
15162d5fd101SZiyang Xuan 	}
15172d5fd101SZiyang Xuan 
15182d5fd101SZiyang Xuan 	memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode));
15192d5fd101SZiyang Xuan 	fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
15202d5fd101SZiyang Xuan 	fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
15212d5fd101SZiyang Xuan 	fast_recycled_mode.fast_recycled_mode = mode;
15222d5fd101SZiyang Xuan 
15232d5fd101SZiyang Xuan 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
15242d5fd101SZiyang Xuan 				     HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET,
15252d5fd101SZiyang Xuan 				     &fast_recycled_mode,
15262d5fd101SZiyang Xuan 				     sizeof(fast_recycled_mode),
15272d5fd101SZiyang Xuan 				     &fast_recycled_mode, &out_size, 0);
15282d5fd101SZiyang Xuan 	if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
1529d807dd7dSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Failed to set recycle mode, err: %d, status: 0x%x, out size: 0x%x",
1530d807dd7dSXiaoyun Wang 			err, fast_recycled_mode.mgmt_msg_head.status, out_size);
1531d807dd7dSXiaoyun Wang 		return -EIO;
15322d5fd101SZiyang Xuan 	}
15332d5fd101SZiyang Xuan 
15342d5fd101SZiyang Xuan 	return 0;
15352d5fd101SZiyang Xuan }
15362d5fd101SZiyang Xuan 
15379970a9adSIgor Romanov int hinic_clear_vport_stats(struct hinic_hwdev *hwdev)
15382d5fd101SZiyang Xuan {
15392d5fd101SZiyang Xuan 	struct hinic_clear_vport_stats clear_vport_stats;
15402d5fd101SZiyang Xuan 	u16 out_size = sizeof(clear_vport_stats);
15412d5fd101SZiyang Xuan 	int err;
15422d5fd101SZiyang Xuan 
15432d5fd101SZiyang Xuan 	if (!hwdev) {
15442d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
15459970a9adSIgor Romanov 		return -EINVAL;
15462d5fd101SZiyang Xuan 	}
15472d5fd101SZiyang Xuan 
15482d5fd101SZiyang Xuan 	memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
15492d5fd101SZiyang Xuan 	clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
15502d5fd101SZiyang Xuan 	clear_vport_stats.func_id = hinic_global_func_id(hwdev);
15512d5fd101SZiyang Xuan 
15522d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT,
15532d5fd101SZiyang Xuan 				     &clear_vport_stats,
15542d5fd101SZiyang Xuan 				     sizeof(clear_vport_stats),
15552d5fd101SZiyang Xuan 				     &clear_vport_stats, &out_size);
15562d5fd101SZiyang Xuan 	if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) {
15572d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x",
15582d5fd101SZiyang Xuan 			err, clear_vport_stats.mgmt_msg_head.status, out_size);
15592ae8e130SXiaoyun Wang 		return -EIO;
15602d5fd101SZiyang Xuan 	}
15612d5fd101SZiyang Xuan 
15629970a9adSIgor Romanov 	return 0;
15639970a9adSIgor Romanov }
15649970a9adSIgor Romanov 
15659970a9adSIgor Romanov int hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev)
15662d5fd101SZiyang Xuan {
15672d5fd101SZiyang Xuan 	struct hinic_clear_port_stats clear_phy_port_stats;
15682d5fd101SZiyang Xuan 	u16 out_size = sizeof(clear_phy_port_stats);
15692d5fd101SZiyang Xuan 	int err;
15702d5fd101SZiyang Xuan 
15712d5fd101SZiyang Xuan 	if (!hwdev) {
15722d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
15739970a9adSIgor Romanov 		return -EINVAL;
15742d5fd101SZiyang Xuan 	}
15752d5fd101SZiyang Xuan 
15762d5fd101SZiyang Xuan 	memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats));
15772d5fd101SZiyang Xuan 	clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
15782d5fd101SZiyang Xuan 	clear_phy_port_stats.func_id = hinic_global_func_id(hwdev);
15792d5fd101SZiyang Xuan 
15802d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev,
15812d5fd101SZiyang Xuan 				     HINIC_PORT_CMD_CLEAR_PORT_STATISTICS,
15822d5fd101SZiyang Xuan 				     &clear_phy_port_stats,
15832d5fd101SZiyang Xuan 				     sizeof(clear_phy_port_stats),
15842d5fd101SZiyang Xuan 				     &clear_phy_port_stats, &out_size);
15852d5fd101SZiyang Xuan 	if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) {
15862d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x",
15872d5fd101SZiyang Xuan 			err, clear_phy_port_stats.mgmt_msg_head.status,
15882d5fd101SZiyang Xuan 			out_size);
15892ae8e130SXiaoyun Wang 		return -EIO;
15902d5fd101SZiyang Xuan 	}
15919970a9adSIgor Romanov 
15929970a9adSIgor Romanov 	return 0;
15932d5fd101SZiyang Xuan }
15942d5fd101SZiyang Xuan 
15952d5fd101SZiyang Xuan int hinic_set_link_status_follow(void *hwdev,
15962d5fd101SZiyang Xuan 				 enum hinic_link_follow_status status)
15972d5fd101SZiyang Xuan {
15982d5fd101SZiyang Xuan 	struct hinic_set_link_follow follow;
15992d5fd101SZiyang Xuan 	u16 out_size = sizeof(follow);
16002d5fd101SZiyang Xuan 	int err;
16012d5fd101SZiyang Xuan 
16022d5fd101SZiyang Xuan 	if (!hwdev)
16032d5fd101SZiyang Xuan 		return -EINVAL;
16042d5fd101SZiyang Xuan 
1605b8582d05SXiaoyun Wang 	if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
1606b8582d05SXiaoyun Wang 		return 0;
1607b8582d05SXiaoyun Wang 
16082d5fd101SZiyang Xuan 	if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) {
1609a528b671SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Invalid link follow status: %d", status);
16102d5fd101SZiyang Xuan 		return -EINVAL;
16112d5fd101SZiyang Xuan 	}
16122d5fd101SZiyang Xuan 
16132d5fd101SZiyang Xuan 	memset(&follow, 0, sizeof(follow));
16142d5fd101SZiyang Xuan 	follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
16152d5fd101SZiyang Xuan 	follow.func_id = hinic_global_func_id(hwdev);
16162d5fd101SZiyang Xuan 	follow.follow_status = status;
16172d5fd101SZiyang Xuan 
16182d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
16192d5fd101SZiyang Xuan 				     &follow, sizeof(follow),
16202d5fd101SZiyang Xuan 				     &follow, &out_size);
16212d5fd101SZiyang Xuan 	if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
16222d5fd101SZiyang Xuan 	     follow.mgmt_msg_head.status) || err || !out_size) {
16232d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
16242d5fd101SZiyang Xuan 			"Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x",
16252d5fd101SZiyang Xuan 			err, follow.mgmt_msg_head.status, out_size);
16262ae8e130SXiaoyun Wang 		return -EIO;
16272d5fd101SZiyang Xuan 	}
16282d5fd101SZiyang Xuan 
16292d5fd101SZiyang Xuan 	return follow.mgmt_msg_head.status;
16302d5fd101SZiyang Xuan }
16312d5fd101SZiyang Xuan 
16322d5fd101SZiyang Xuan int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
16332d5fd101SZiyang Xuan {
16342d5fd101SZiyang Xuan 	struct hinic_link_mode_cmd link_mode;
16352d5fd101SZiyang Xuan 	u16 out_size = sizeof(link_mode);
16362d5fd101SZiyang Xuan 	int err;
16372d5fd101SZiyang Xuan 
16382d5fd101SZiyang Xuan 	if (!hwdev || !supported || !advertised)
16392d5fd101SZiyang Xuan 		return -EINVAL;
16402d5fd101SZiyang Xuan 
16412d5fd101SZiyang Xuan 	memset(&link_mode, 0, sizeof(link_mode));
16422d5fd101SZiyang Xuan 	link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
16432d5fd101SZiyang Xuan 	link_mode.func_id = hinic_global_func_id(hwdev);
16442d5fd101SZiyang Xuan 
16452d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
16462d5fd101SZiyang Xuan 				     &link_mode, sizeof(link_mode),
16472d5fd101SZiyang Xuan 				     &link_mode, &out_size);
16482d5fd101SZiyang Xuan 	if (err || !out_size || link_mode.mgmt_msg_head.status) {
16492d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR,
16502d5fd101SZiyang Xuan 			"Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x",
16512d5fd101SZiyang Xuan 			err, link_mode.mgmt_msg_head.status, out_size);
16522ae8e130SXiaoyun Wang 		return -EIO;
16532d5fd101SZiyang Xuan 	}
16542d5fd101SZiyang Xuan 
16552d5fd101SZiyang Xuan 	*supported = link_mode.supported;
16562d5fd101SZiyang Xuan 	*advertised = link_mode.advertised;
16572d5fd101SZiyang Xuan 
16582d5fd101SZiyang Xuan 	return 0;
16592d5fd101SZiyang Xuan }
16602d5fd101SZiyang Xuan 
16612d5fd101SZiyang Xuan /**
1662b8582d05SXiaoyun Wang  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport
1663b8582d05SXiaoyun Wang  * fake failed when device start.
1664b8582d05SXiaoyun Wang  *
1665b8582d05SXiaoyun Wang  * @param hwdev
1666b8582d05SXiaoyun Wang  *   The hardware interface of a nic device.
1667b8582d05SXiaoyun Wang  *
1668b8582d05SXiaoyun Wang  * @return
1669b8582d05SXiaoyun Wang  *   0 on success.
1670b8582d05SXiaoyun Wang  *   negative error value otherwise.
1671b8582d05SXiaoyun Wang  */
16722d5fd101SZiyang Xuan int hinic_flush_qp_res(void *hwdev)
16732d5fd101SZiyang Xuan {
16742d5fd101SZiyang Xuan 	struct hinic_clear_qp_resource qp_res;
16752d5fd101SZiyang Xuan 	u16 out_size = sizeof(qp_res);
16762d5fd101SZiyang Xuan 	int err;
16772d5fd101SZiyang Xuan 
16782d5fd101SZiyang Xuan 	memset(&qp_res, 0, sizeof(qp_res));
16792d5fd101SZiyang Xuan 	qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
16802d5fd101SZiyang Xuan 	qp_res.func_id = hinic_global_func_id(hwdev);
16812d5fd101SZiyang Xuan 
16822d5fd101SZiyang Xuan 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES,
16832d5fd101SZiyang Xuan 				     &qp_res, sizeof(qp_res), &qp_res,
16842d5fd101SZiyang Xuan 				     &out_size);
16852d5fd101SZiyang Xuan 	if (err || !out_size || qp_res.mgmt_msg_head.status) {
16862d5fd101SZiyang Xuan 		PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x",
16872d5fd101SZiyang Xuan 			err, qp_res.mgmt_msg_head.status, out_size);
16882ae8e130SXiaoyun Wang 		return -EIO;
16892d5fd101SZiyang Xuan 	}
16902d5fd101SZiyang Xuan 
16912d5fd101SZiyang Xuan 	return 0;
16922d5fd101SZiyang Xuan }
16936691acefSXiaoyun Wang 
16946691acefSXiaoyun Wang /**
16956691acefSXiaoyun Wang  * hinic_vf_get_default_cos - Get default cos of VF.
16966691acefSXiaoyun Wang  *
16976691acefSXiaoyun Wang  * @param hwdev
16986691acefSXiaoyun Wang  *   The hardware interface of a nic device.
16996691acefSXiaoyun Wang  * @param cos_id
17006691acefSXiaoyun Wang  *   Cos value.
17016691acefSXiaoyun Wang  *
17026691acefSXiaoyun Wang  * @return
17036691acefSXiaoyun Wang  *   0 on success.
17046691acefSXiaoyun Wang  *   negative error value otherwise.
17056691acefSXiaoyun Wang  */
17066691acefSXiaoyun Wang int hinic_vf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
17076691acefSXiaoyun Wang {
17086691acefSXiaoyun Wang 	struct hinic_vf_default_cos vf_cos;
17096691acefSXiaoyun Wang 	u16 out_size = sizeof(vf_cos);
17106691acefSXiaoyun Wang 	int err;
17116691acefSXiaoyun Wang 
17126691acefSXiaoyun Wang 	memset(&vf_cos, 0, sizeof(vf_cos));
17136691acefSXiaoyun Wang 	vf_cos.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
17146691acefSXiaoyun Wang 
17156691acefSXiaoyun Wang 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
17166691acefSXiaoyun Wang 				     HINIC_PORT_CMD_GET_VF_COS, &vf_cos,
1717d807dd7dSXiaoyun Wang 				     sizeof(vf_cos), &vf_cos, &out_size, 0);
17186691acefSXiaoyun Wang 	if (err || !out_size || vf_cos.mgmt_msg_head.status) {
17196691acefSXiaoyun Wang 		PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d, status: 0x%x, out size: 0x%x",
17206691acefSXiaoyun Wang 			err, vf_cos.mgmt_msg_head.status, out_size);
1721d807dd7dSXiaoyun Wang 		return -EIO;
17226691acefSXiaoyun Wang 	}
17236691acefSXiaoyun Wang 	*cos_id = vf_cos.state.default_cos;
17246691acefSXiaoyun Wang 
17256691acefSXiaoyun Wang 	return 0;
17266691acefSXiaoyun Wang }
1727a5d668e6SXiaoyun Wang 
1728a5d668e6SXiaoyun Wang /**
1729a5d668e6SXiaoyun Wang  * hinic_set_fdir_filter - Set fdir filter for control path
1730a5d668e6SXiaoyun Wang  * packet to notify firmware.
1731a5d668e6SXiaoyun Wang  *
1732a5d668e6SXiaoyun Wang  * @param hwdev
1733a5d668e6SXiaoyun Wang  *   The hardware interface of a nic device.
1734a5d668e6SXiaoyun Wang  * @param filter_type
1735a5d668e6SXiaoyun Wang  *   Packet type to filter.
1736a5d668e6SXiaoyun Wang  * @param qid
1737a5d668e6SXiaoyun Wang  *   Rx qid to filter.
1738a5d668e6SXiaoyun Wang  * @param type_enable
1739a5d668e6SXiaoyun Wang  *   The status of pkt type filter.
1740a5d668e6SXiaoyun Wang  * @param enable
1741a5d668e6SXiaoyun Wang  *   Fdir function Enable or Disable.
1742a5d668e6SXiaoyun Wang  * @return
1743a5d668e6SXiaoyun Wang  *   0 on success,
1744a5d668e6SXiaoyun Wang  *   negative error value otherwise.
1745a5d668e6SXiaoyun Wang  */
1746a5d668e6SXiaoyun Wang int hinic_set_fdir_filter(void *hwdev, u8 filter_type, u8 qid, u8 type_enable,
1747a5d668e6SXiaoyun Wang 			  bool enable)
1748a5d668e6SXiaoyun Wang {
1749a5d668e6SXiaoyun Wang 	struct hinic_port_qfilter_info port_filer_cmd;
1750a5d668e6SXiaoyun Wang 	u16 out_size = sizeof(port_filer_cmd);
1751a5d668e6SXiaoyun Wang 	int err;
1752a5d668e6SXiaoyun Wang 
1753a5d668e6SXiaoyun Wang 	if (!hwdev)
1754a5d668e6SXiaoyun Wang 		return -EINVAL;
1755a5d668e6SXiaoyun Wang 
1756a5d668e6SXiaoyun Wang 	memset(&port_filer_cmd, 0, sizeof(port_filer_cmd));
1757a5d668e6SXiaoyun Wang 	port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1758a5d668e6SXiaoyun Wang 	port_filer_cmd.func_id = hinic_global_func_id(hwdev);
1759a5d668e6SXiaoyun Wang 	port_filer_cmd.filter_enable = (u8)enable;
1760a5d668e6SXiaoyun Wang 	port_filer_cmd.filter_type = filter_type;
1761a5d668e6SXiaoyun Wang 	port_filer_cmd.qid = qid;
1762a5d668e6SXiaoyun Wang 	port_filer_cmd.filter_type_enable = type_enable;
1763a5d668e6SXiaoyun Wang 	port_filer_cmd.fdir_flag = 0;
1764a5d668e6SXiaoyun Wang 
1765a5d668e6SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER,
1766a5d668e6SXiaoyun Wang 			&port_filer_cmd, sizeof(port_filer_cmd),
1767a5d668e6SXiaoyun Wang 			&port_filer_cmd, &out_size);
1768a5d668e6SXiaoyun Wang 	if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) {
1769a5d668e6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set port Q filter failed, err: %d, status: 0x%x, out size: 0x%x, type: 0x%x,"
1770*f665790aSDavid Marchand 			" enable: 0x%x, qid: 0x%x, filter_type_enable: 0x%x",
1771a5d668e6SXiaoyun Wang 			err, port_filer_cmd.mgmt_msg_head.status, out_size,
1772a5d668e6SXiaoyun Wang 			filter_type, enable, qid, type_enable);
17732ae8e130SXiaoyun Wang 		return -EIO;
1774a5d668e6SXiaoyun Wang 	}
1775a5d668e6SXiaoyun Wang 
1776a5d668e6SXiaoyun Wang 	return 0;
1777a5d668e6SXiaoyun Wang }
1778a5d668e6SXiaoyun Wang 
1779a5d668e6SXiaoyun Wang /**
1780a5d668e6SXiaoyun Wang  * hinic_set_normal_filter - Set fdir filter for IO path packet.
1781a5d668e6SXiaoyun Wang  *
1782a5d668e6SXiaoyun Wang  * @param hwdev
1783a5d668e6SXiaoyun Wang  *   The hardware interface of a nic device.
1784a5d668e6SXiaoyun Wang  * @param qid
1785a5d668e6SXiaoyun Wang  *   Rx qid to filter.
1786a5d668e6SXiaoyun Wang  * @param normal_type_enable
1787a5d668e6SXiaoyun Wang  *   IO path packet function Enable or Disable
1788a5d668e6SXiaoyun Wang  * @param key
1789a5d668e6SXiaoyun Wang  *   IO path packet filter key value, such as DIP from pkt.
1790a5d668e6SXiaoyun Wang  * @param enable
1791a5d668e6SXiaoyun Wang  *   Fdir function Enable or Disable.
1792a5d668e6SXiaoyun Wang  * @param flag
1793a5d668e6SXiaoyun Wang  *   Filter flag, such as dip or others.
1794a5d668e6SXiaoyun Wang  * @return
1795a5d668e6SXiaoyun Wang  *   0 on success,
1796a5d668e6SXiaoyun Wang  *   negative error value otherwise.
1797a5d668e6SXiaoyun Wang  */
1798a5d668e6SXiaoyun Wang int hinic_set_normal_filter(void *hwdev, u8 qid, u8 normal_type_enable,
1799a5d668e6SXiaoyun Wang 				u32 key, bool enable, u8 flag)
1800a5d668e6SXiaoyun Wang {
1801a5d668e6SXiaoyun Wang 	struct hinic_port_qfilter_info port_filer_cmd;
1802a5d668e6SXiaoyun Wang 	u16 out_size = sizeof(port_filer_cmd);
1803a5d668e6SXiaoyun Wang 	int err;
1804a5d668e6SXiaoyun Wang 
1805a5d668e6SXiaoyun Wang 	if (!hwdev)
1806a5d668e6SXiaoyun Wang 		return -EINVAL;
1807a5d668e6SXiaoyun Wang 
1808a5d668e6SXiaoyun Wang 	memset(&port_filer_cmd, 0, sizeof(port_filer_cmd));
1809a5d668e6SXiaoyun Wang 	port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1810a5d668e6SXiaoyun Wang 	port_filer_cmd.func_id = hinic_global_func_id(hwdev);
1811a5d668e6SXiaoyun Wang 	port_filer_cmd.filter_enable = (u8)enable;
1812a5d668e6SXiaoyun Wang 	port_filer_cmd.qid = qid;
1813a5d668e6SXiaoyun Wang 	port_filer_cmd.normal_type_enable = normal_type_enable;
1814a5d668e6SXiaoyun Wang 	port_filer_cmd.fdir_flag = flag; /* fdir flag: support dip */
1815a5d668e6SXiaoyun Wang 	port_filer_cmd.key = key;
1816a5d668e6SXiaoyun Wang 
1817a5d668e6SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER,
1818a5d668e6SXiaoyun Wang 			&port_filer_cmd, sizeof(port_filer_cmd),
1819a5d668e6SXiaoyun Wang 			&port_filer_cmd, &out_size);
1820a5d668e6SXiaoyun Wang 	if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) {
1821a5d668e6SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set normal filter failed, err: %d, status: 0x%x, out size: 0x%x, fdir_flag: 0x%x,"
1822*f665790aSDavid Marchand 			" enable: 0x%x, qid: 0x%x, normal_type_enable: 0x%x, key:0x%x",
1823a5d668e6SXiaoyun Wang 			err, port_filer_cmd.mgmt_msg_head.status, out_size,
1824a5d668e6SXiaoyun Wang 			flag, enable, qid, normal_type_enable, key);
18252ae8e130SXiaoyun Wang 		return -EIO;
1826a5d668e6SXiaoyun Wang 	}
1827a5d668e6SXiaoyun Wang 
1828a5d668e6SXiaoyun Wang 	return 0;
1829a5d668e6SXiaoyun Wang }
1830a5d668e6SXiaoyun Wang 
1831a5d668e6SXiaoyun Wang /**
1832a5d668e6SXiaoyun Wang  * hinic_set_fdir_tcam - Set fdir filter for control packet
1833a5d668e6SXiaoyun Wang  * by tcam table to notify hardware.
1834a5d668e6SXiaoyun Wang  *
1835a5d668e6SXiaoyun Wang  * @param hwdev
1836a5d668e6SXiaoyun Wang  *   The hardware interface of a nic device.
1837a5d668e6SXiaoyun Wang  * @param type_mask
1838a5d668e6SXiaoyun Wang  *   Index of TCAM.
1839a5d668e6SXiaoyun Wang  * @param filter_rule
1840a5d668e6SXiaoyun Wang  *   TCAM rule for control packet, such as lacp or bgp.
1841a5d668e6SXiaoyun Wang  * @param filter_action
1842a5d668e6SXiaoyun Wang  *   TCAM action for control packet, such as accept or drop.
1843a5d668e6SXiaoyun Wang  * @return
1844a5d668e6SXiaoyun Wang  *   0 on success,
1845a5d668e6SXiaoyun Wang  *   negative error value otherwise.
1846a5d668e6SXiaoyun Wang  */
1847a5d668e6SXiaoyun Wang int hinic_set_fdir_tcam(void *hwdev, u16 type_mask,
1848a5d668e6SXiaoyun Wang 			struct tag_pa_rule *filter_rule,
1849a5d668e6SXiaoyun Wang 			struct tag_pa_action *filter_action)
1850a5d668e6SXiaoyun Wang {
1851a5d668e6SXiaoyun Wang 	struct hinic_fdir_tcam_info port_tcam_cmd;
1852a5d668e6SXiaoyun Wang 	u16 out_size = sizeof(port_tcam_cmd);
1853a5d668e6SXiaoyun Wang 	int err;
1854a5d668e6SXiaoyun Wang 
1855a5d668e6SXiaoyun Wang 	if (!hwdev)
1856a5d668e6SXiaoyun Wang 		return -EINVAL;
1857a5d668e6SXiaoyun Wang 
1858a5d668e6SXiaoyun Wang 	memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
1859a5d668e6SXiaoyun Wang 	port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1860a5d668e6SXiaoyun Wang 	port_tcam_cmd.tcam_index = type_mask;
1861a5d668e6SXiaoyun Wang 	port_tcam_cmd.flag = TCAM_SET;
1862a5d668e6SXiaoyun Wang 	memcpy((void *)&port_tcam_cmd.filter_rule,
1863a5d668e6SXiaoyun Wang 		(void *)filter_rule, sizeof(struct tag_pa_rule));
1864a5d668e6SXiaoyun Wang 	memcpy((void *)&port_tcam_cmd.filter_action,
1865a5d668e6SXiaoyun Wang 		(void *)filter_action, sizeof(struct tag_pa_action));
1866a5d668e6SXiaoyun Wang 
1867a5d668e6SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER,
1868a5d668e6SXiaoyun Wang 			&port_tcam_cmd, sizeof(port_tcam_cmd),
1869a5d668e6SXiaoyun Wang 			&port_tcam_cmd, &out_size);
1870a5d668e6SXiaoyun Wang 	if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) {
18711fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set tcam table failed, err: %d, status: 0x%x, out size: 0x%x",
1872a5d668e6SXiaoyun Wang 			err, port_tcam_cmd.mgmt_msg_head.status, out_size);
18732ae8e130SXiaoyun Wang 		return -EIO;
1874a5d668e6SXiaoyun Wang 	}
1875a5d668e6SXiaoyun Wang 
1876a5d668e6SXiaoyun Wang 	return 0;
1877a5d668e6SXiaoyun Wang }
1878a5d668e6SXiaoyun Wang 
1879a5d668e6SXiaoyun Wang /**
1880a5d668e6SXiaoyun Wang  * hinic_clear_fdir_tcam - Clear fdir filter TCAM table for control packet.
1881a5d668e6SXiaoyun Wang  *
1882a5d668e6SXiaoyun Wang  * @param hwdev
1883a5d668e6SXiaoyun Wang  *   The hardware interface of a nic device.
1884a5d668e6SXiaoyun Wang  * @param type_mask
1885a5d668e6SXiaoyun Wang  *   Index of TCAM.
1886a5d668e6SXiaoyun Wang  * @return
1887a5d668e6SXiaoyun Wang  *   0 on success,
1888a5d668e6SXiaoyun Wang  *   negative error value otherwise.
1889a5d668e6SXiaoyun Wang  */
1890a5d668e6SXiaoyun Wang int hinic_clear_fdir_tcam(void *hwdev, u16 type_mask)
1891a5d668e6SXiaoyun Wang {
1892a5d668e6SXiaoyun Wang 	struct hinic_fdir_tcam_info port_tcam_cmd;
1893a5d668e6SXiaoyun Wang 	u16 out_size = sizeof(port_tcam_cmd);
1894a5d668e6SXiaoyun Wang 	int err;
1895a5d668e6SXiaoyun Wang 
1896a5d668e6SXiaoyun Wang 	if (!hwdev)
1897a5d668e6SXiaoyun Wang 		return -EINVAL;
1898a5d668e6SXiaoyun Wang 
1899a5d668e6SXiaoyun Wang 	memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
1900a5d668e6SXiaoyun Wang 	port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1901a5d668e6SXiaoyun Wang 	port_tcam_cmd.tcam_index = type_mask;
1902a5d668e6SXiaoyun Wang 	port_tcam_cmd.flag = TCAM_CLEAR;
1903a5d668e6SXiaoyun Wang 
1904a5d668e6SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER,
1905a5d668e6SXiaoyun Wang 			&port_tcam_cmd, sizeof(port_tcam_cmd),
1906a5d668e6SXiaoyun Wang 			&port_tcam_cmd, &out_size);
1907a5d668e6SXiaoyun Wang 	if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) {
19081fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Clear tcam table failed, err: %d, status: 0x%x, out size: 0x%x",
1909a5d668e6SXiaoyun Wang 			err, port_tcam_cmd.mgmt_msg_head.status, out_size);
19102ae8e130SXiaoyun Wang 		return -EIO;
1911a5d668e6SXiaoyun Wang 	}
1912a5d668e6SXiaoyun Wang 
1913a5d668e6SXiaoyun Wang 	return 0;
1914a5d668e6SXiaoyun Wang }
19151fe89aa3SXiaoyun Wang 
19161fe89aa3SXiaoyun Wang int hinic_add_tcam_rule(void *hwdev, struct tag_tcam_cfg_rule *tcam_rule)
19171fe89aa3SXiaoyun Wang {
19181fe89aa3SXiaoyun Wang 	u16 out_size = sizeof(struct tag_fdir_add_rule_cmd);
19191fe89aa3SXiaoyun Wang 	struct tag_fdir_add_rule_cmd tcam_cmd;
19201fe89aa3SXiaoyun Wang 	int err;
19211fe89aa3SXiaoyun Wang 
19221fe89aa3SXiaoyun Wang 	if (!hwdev) {
19231fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
19241fe89aa3SXiaoyun Wang 		return -EINVAL;
19251fe89aa3SXiaoyun Wang 	}
19261fe89aa3SXiaoyun Wang 
19271fe89aa3SXiaoyun Wang 	if (tcam_rule->index >= HINIC_MAX_TCAM_RULES_NUM) {
19281fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Tcam rules num to add is invalid");
19292ae8e130SXiaoyun Wang 		return -EINVAL;
19301fe89aa3SXiaoyun Wang 	}
19311fe89aa3SXiaoyun Wang 
19321fe89aa3SXiaoyun Wang 	memset(&tcam_cmd, 0, sizeof(struct tag_fdir_add_rule_cmd));
19331fe89aa3SXiaoyun Wang 	tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
19341fe89aa3SXiaoyun Wang 	memcpy((void *)&tcam_cmd.rule, (void *)tcam_rule,
19351fe89aa3SXiaoyun Wang 		sizeof(struct tag_tcam_cfg_rule));
19361fe89aa3SXiaoyun Wang 
19371fe89aa3SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ADD_FLOW,
19381fe89aa3SXiaoyun Wang 				&tcam_cmd, sizeof(tcam_cmd),
19391fe89aa3SXiaoyun Wang 				&tcam_cmd, &out_size);
19401fe89aa3SXiaoyun Wang 	if (err || tcam_cmd.mgmt_msg_head.status || !out_size) {
19411fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR,
19421fe89aa3SXiaoyun Wang 			"Add tcam rule failed, err: %d, status: 0x%x, out size: 0x%x",
19431fe89aa3SXiaoyun Wang 			err, tcam_cmd.mgmt_msg_head.status, out_size);
19442ae8e130SXiaoyun Wang 		return -EIO;
19451fe89aa3SXiaoyun Wang 	}
19461fe89aa3SXiaoyun Wang 
19471fe89aa3SXiaoyun Wang 	return 0;
19481fe89aa3SXiaoyun Wang }
19491fe89aa3SXiaoyun Wang 
19501fe89aa3SXiaoyun Wang int hinic_del_tcam_rule(void *hwdev, u32 index)
19511fe89aa3SXiaoyun Wang {
19521fe89aa3SXiaoyun Wang 	u16 out_size = sizeof(struct tag_fdir_del_rule_cmd);
19531fe89aa3SXiaoyun Wang 	struct tag_fdir_del_rule_cmd tcam_cmd;
19541fe89aa3SXiaoyun Wang 	int err;
19551fe89aa3SXiaoyun Wang 
19561fe89aa3SXiaoyun Wang 	if (!hwdev) {
19571fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
19581fe89aa3SXiaoyun Wang 		return -EINVAL;
19591fe89aa3SXiaoyun Wang 	}
19601fe89aa3SXiaoyun Wang 
19611fe89aa3SXiaoyun Wang 	if (index >= HINIC_MAX_TCAM_RULES_NUM) {
19621fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Tcam rules num to del is invalid");
19632ae8e130SXiaoyun Wang 		return -EINVAL;
19641fe89aa3SXiaoyun Wang 	}
19651fe89aa3SXiaoyun Wang 
19661fe89aa3SXiaoyun Wang 	memset(&tcam_cmd, 0, sizeof(struct tag_fdir_del_rule_cmd));
19671fe89aa3SXiaoyun Wang 	tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
19681fe89aa3SXiaoyun Wang 	tcam_cmd.index_start = index;
19691fe89aa3SXiaoyun Wang 	tcam_cmd.index_num = 1;
19701fe89aa3SXiaoyun Wang 
19711fe89aa3SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_DEL_FLOW,
19721fe89aa3SXiaoyun Wang 				&tcam_cmd, sizeof(tcam_cmd),
19731fe89aa3SXiaoyun Wang 				&tcam_cmd, &out_size);
19741fe89aa3SXiaoyun Wang 	if (err || tcam_cmd.mgmt_msg_head.status || !out_size) {
19751fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR,
19761fe89aa3SXiaoyun Wang 			"Del tcam rule failed, err: %d, status: 0x%x, out size: 0x%x",
19771fe89aa3SXiaoyun Wang 			err, tcam_cmd.mgmt_msg_head.status, out_size);
19782ae8e130SXiaoyun Wang 		return -EIO;
19791fe89aa3SXiaoyun Wang 	}
19801fe89aa3SXiaoyun Wang 
19811fe89aa3SXiaoyun Wang 	return 0;
19821fe89aa3SXiaoyun Wang }
19831fe89aa3SXiaoyun Wang 
19841fe89aa3SXiaoyun Wang static int hinic_mgmt_tcam_block(void *hwdev, u8 alloc_en,
19851fe89aa3SXiaoyun Wang 				u8 block_type, u16 *index)
19861fe89aa3SXiaoyun Wang {
19871fe89aa3SXiaoyun Wang 	struct hinic_cmd_ctrl_tcam_block tcam_block_info;
19881fe89aa3SXiaoyun Wang 	u16 out_size = sizeof(struct hinic_cmd_ctrl_tcam_block);
19891fe89aa3SXiaoyun Wang 	struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
19901fe89aa3SXiaoyun Wang 	int err;
19911fe89aa3SXiaoyun Wang 
19921fe89aa3SXiaoyun Wang 	if (!hwdev) {
19931fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
19941fe89aa3SXiaoyun Wang 		return -EINVAL;
19951fe89aa3SXiaoyun Wang 	}
19961fe89aa3SXiaoyun Wang 
19971fe89aa3SXiaoyun Wang 	memset(&tcam_block_info, 0, sizeof(struct hinic_cmd_ctrl_tcam_block));
19981fe89aa3SXiaoyun Wang 	tcam_block_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
19991fe89aa3SXiaoyun Wang 	tcam_block_info.func_id = hinic_global_func_id(hwdev);
20001fe89aa3SXiaoyun Wang 	tcam_block_info.alloc_en = alloc_en;
20011fe89aa3SXiaoyun Wang 	tcam_block_info.tcam_type = block_type;
20021fe89aa3SXiaoyun Wang 	tcam_block_info.tcam_block_index = *index;
20031fe89aa3SXiaoyun Wang 
20041fe89aa3SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev,
20051fe89aa3SXiaoyun Wang 				HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK,
20061fe89aa3SXiaoyun Wang 				&tcam_block_info, sizeof(tcam_block_info),
20071fe89aa3SXiaoyun Wang 				&tcam_block_info, &out_size);
20081fe89aa3SXiaoyun Wang 	if (tcam_block_info.mgmt_msg_head.status ==
20091fe89aa3SXiaoyun Wang 		HINIC_MGMT_CMD_UNSUPPORTED) {
20101fe89aa3SXiaoyun Wang 		err = HINIC_MGMT_CMD_UNSUPPORTED;
20111fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(INFO, "Firmware/uP doesn't support alloc or del tcam block");
20121fe89aa3SXiaoyun Wang 		return err;
20131fe89aa3SXiaoyun Wang 	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
20141fe89aa3SXiaoyun Wang 			(HINIC_IS_VF(nic_hwdev))) {
20151fe89aa3SXiaoyun Wang 		err = HINIC_MGMT_CMD_UNSUPPORTED;
20161fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(INFO, "VF doesn't support alloc and del tcam block.");
20171fe89aa3SXiaoyun Wang 		return err;
20181fe89aa3SXiaoyun Wang 	} else if (err || (!out_size) || tcam_block_info.mgmt_msg_head.status) {
20191fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR,
20201fe89aa3SXiaoyun Wang 			"Set tcam block failed, err: %d, status: 0x%x, out size: 0x%x",
20211fe89aa3SXiaoyun Wang 			err, tcam_block_info.mgmt_msg_head.status, out_size);
20222ae8e130SXiaoyun Wang 		return -EIO;
20231fe89aa3SXiaoyun Wang 	}
20241fe89aa3SXiaoyun Wang 
20251fe89aa3SXiaoyun Wang 	if (alloc_en)
20261fe89aa3SXiaoyun Wang 		*index = tcam_block_info.tcam_block_index;
20271fe89aa3SXiaoyun Wang 
20281fe89aa3SXiaoyun Wang 	return 0;
20291fe89aa3SXiaoyun Wang }
20301fe89aa3SXiaoyun Wang 
20311fe89aa3SXiaoyun Wang int hinic_alloc_tcam_block(void *hwdev, u8 block_type, u16 *index)
20321fe89aa3SXiaoyun Wang {
20331fe89aa3SXiaoyun Wang 	return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_ENABLE,
20341fe89aa3SXiaoyun Wang 				block_type, index);
20351fe89aa3SXiaoyun Wang }
20361fe89aa3SXiaoyun Wang 
20371fe89aa3SXiaoyun Wang int hinic_free_tcam_block(void *hwdev, u8 block_type, u16 *index)
20381fe89aa3SXiaoyun Wang {
20391fe89aa3SXiaoyun Wang 	return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_DISABLE,
20401fe89aa3SXiaoyun Wang 				block_type, index);
20411fe89aa3SXiaoyun Wang }
20421fe89aa3SXiaoyun Wang 
20431fe89aa3SXiaoyun Wang int hinic_flush_tcam_rule(void *hwdev)
20441fe89aa3SXiaoyun Wang {
20451fe89aa3SXiaoyun Wang 	struct hinic_cmd_flush_tcam_rules tcam_flush;
20461fe89aa3SXiaoyun Wang 	u16 out_size = sizeof(struct hinic_cmd_flush_tcam_rules);
20471fe89aa3SXiaoyun Wang 	struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
20481fe89aa3SXiaoyun Wang 	int err;
20491fe89aa3SXiaoyun Wang 
20501fe89aa3SXiaoyun Wang 	if (!hwdev) {
20511fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
20521fe89aa3SXiaoyun Wang 		return -EINVAL;
20531fe89aa3SXiaoyun Wang 	}
20541fe89aa3SXiaoyun Wang 
20551fe89aa3SXiaoyun Wang 	memset(&tcam_flush, 0, sizeof(struct hinic_cmd_flush_tcam_rules));
20561fe89aa3SXiaoyun Wang 	tcam_flush.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
20571fe89aa3SXiaoyun Wang 	tcam_flush.func_id = hinic_global_func_id(hwdev);
20581fe89aa3SXiaoyun Wang 
20591fe89aa3SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_FLUSH_TCAM,
20601fe89aa3SXiaoyun Wang 			&tcam_flush, sizeof(struct hinic_cmd_flush_tcam_rules),
20611fe89aa3SXiaoyun Wang 			&tcam_flush, &out_size);
20621fe89aa3SXiaoyun Wang 	if (tcam_flush.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
20631fe89aa3SXiaoyun Wang 		err = HINIC_MGMT_CMD_UNSUPPORTED;
20641fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(INFO, "Firmware/uP doesn't support flush tcam fdir");
20651fe89aa3SXiaoyun Wang 	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
20661fe89aa3SXiaoyun Wang 			(HINIC_IS_VF(nic_hwdev))) {
20671fe89aa3SXiaoyun Wang 		err = HINIC_MGMT_CMD_UNSUPPORTED;
20681fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(INFO, "VF doesn't support flush tcam fdir");
20691fe89aa3SXiaoyun Wang 	} else if (err || (!out_size) || tcam_flush.mgmt_msg_head.status) {
20701fe89aa3SXiaoyun Wang 		PMD_DRV_LOG(ERR,
20711fe89aa3SXiaoyun Wang 			"Flush tcam fdir rules failed, err: %d, status: 0x%x, out size: 0x%x",
20721fe89aa3SXiaoyun Wang 			err, tcam_flush.mgmt_msg_head.status, out_size);
20732ae8e130SXiaoyun Wang 		err = -EIO;
20741fe89aa3SXiaoyun Wang 	}
20751fe89aa3SXiaoyun Wang 
20761fe89aa3SXiaoyun Wang 	return err;
20771fe89aa3SXiaoyun Wang }
20781fe89aa3SXiaoyun Wang 
20790023e525SXiaoyun Wang int hinic_set_fdir_tcam_rule_filter(void *hwdev, bool enable)
20800023e525SXiaoyun Wang {
20810023e525SXiaoyun Wang 	struct hinic_port_tcam_info port_tcam_cmd;
20820023e525SXiaoyun Wang 	u16 out_size = sizeof(port_tcam_cmd);
20830023e525SXiaoyun Wang 	int err;
20840023e525SXiaoyun Wang 
20850023e525SXiaoyun Wang 	if (!hwdev)
20860023e525SXiaoyun Wang 		return -EINVAL;
20870023e525SXiaoyun Wang 
20880023e525SXiaoyun Wang 	memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
20890023e525SXiaoyun Wang 	port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
20900023e525SXiaoyun Wang 	port_tcam_cmd.func_id = hinic_global_func_id(hwdev);
20910023e525SXiaoyun Wang 	port_tcam_cmd.tcam_enable = (u8)enable;
20920023e525SXiaoyun Wang 
20930023e525SXiaoyun Wang 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ENABLE,
20940023e525SXiaoyun Wang 			&port_tcam_cmd, sizeof(port_tcam_cmd),
20950023e525SXiaoyun Wang 			&port_tcam_cmd, &out_size);
20960023e525SXiaoyun Wang 	if ((port_tcam_cmd.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
20970023e525SXiaoyun Wang 		port_tcam_cmd.mgmt_msg_head.status) || err || !out_size) {
20980023e525SXiaoyun Wang 		if (err == HINIC_MBOX_VF_CMD_ERROR &&
20990023e525SXiaoyun Wang 			HINIC_IS_VF((struct hinic_hwdev *)hwdev)) {
21000023e525SXiaoyun Wang 			err = HINIC_MGMT_CMD_UNSUPPORTED;
21010023e525SXiaoyun Wang 			PMD_DRV_LOG(WARNING, "VF doesn't support setting fdir tcam filter");
21020023e525SXiaoyun Wang 			return err;
21030023e525SXiaoyun Wang 		}
21040023e525SXiaoyun Wang 		PMD_DRV_LOG(ERR, "Set fdir tcam filter failed, err: %d, "
21050023e525SXiaoyun Wang 			"status: 0x%x, out size: 0x%x, enable: 0x%x",
21060023e525SXiaoyun Wang 			err, port_tcam_cmd.mgmt_msg_head.status, out_size,
21070023e525SXiaoyun Wang 			enable);
21082ae8e130SXiaoyun Wang 		return -EIO;
21090023e525SXiaoyun Wang 	}
21100023e525SXiaoyun Wang 
21110023e525SXiaoyun Wang 	if (port_tcam_cmd.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
21120023e525SXiaoyun Wang 		err = HINIC_MGMT_CMD_UNSUPPORTED;
21130023e525SXiaoyun Wang 		PMD_DRV_LOG(WARNING, "Fw doesn't support setting fdir tcam filter");
21140023e525SXiaoyun Wang 	}
21150023e525SXiaoyun Wang 
21160023e525SXiaoyun Wang 	return err;
21170023e525SXiaoyun Wang }
21180023e525SXiaoyun Wang 
21190023e525SXiaoyun Wang 
2120