1e2cb1decSSalil Mehta // SPDX-License-Identifier: GPL-2.0+
2e2cb1decSSalil Mehta // Copyright (c) 2016-2017 Hisilicon Limited.
3e2cb1decSSalil Mehta 
4e2cb1decSSalil Mehta #include <linux/etherdevice.h>
5aa5c4f17SHuazhong Tan #include <linux/iopoll.h>
66988eb2aSSalil Mehta #include <net/rtnetlink.h>
7e2cb1decSSalil Mehta #include "hclgevf_cmd.h"
8e2cb1decSSalil Mehta #include "hclgevf_main.h"
9e2cb1decSSalil Mehta #include "hclge_mbx.h"
10e2cb1decSSalil Mehta #include "hnae3.h"
11e2cb1decSSalil Mehta 
12e2cb1decSSalil Mehta #define HCLGEVF_NAME	"hclgevf"
13e2cb1decSSalil Mehta 
14bbe6540eSHuazhong Tan #define HCLGEVF_RESET_MAX_FAIL_CNT	5
15bbe6540eSHuazhong Tan 
169c6f7085SHuazhong Tan static int hclgevf_reset_hdev(struct hclgevf_dev *hdev);
175e7414cdSJian Shen static void hclgevf_task_schedule(struct hclgevf_dev *hdev,
185e7414cdSJian Shen 				  unsigned long delay);
195e7414cdSJian Shen 
20e2cb1decSSalil Mehta static struct hnae3_ae_algo ae_algovf;
21e2cb1decSSalil Mehta 
220ea68902SYunsheng Lin static struct workqueue_struct *hclgevf_wq;
230ea68902SYunsheng Lin 
24e2cb1decSSalil Mehta static const struct pci_device_id ae_algovf_pci_tbl[] = {
25c155e22bSGuangbin Huang 	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_VF), 0},
26c155e22bSGuangbin Huang 	{PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_RDMA_DCB_PFC_VF),
27c155e22bSGuangbin Huang 	 HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
28e2cb1decSSalil Mehta 	/* required last entry */
29e2cb1decSSalil Mehta 	{0, }
30e2cb1decSSalil Mehta };
31e2cb1decSSalil Mehta 
32472d7eceSJian Shen static const u8 hclgevf_hash_key[] = {
33472d7eceSJian Shen 	0x6D, 0x5A, 0x56, 0xDA, 0x25, 0x5B, 0x0E, 0xC2,
34472d7eceSJian Shen 	0x41, 0x67, 0x25, 0x3D, 0x43, 0xA3, 0x8F, 0xB0,
35472d7eceSJian Shen 	0xD0, 0xCA, 0x2B, 0xCB, 0xAE, 0x7B, 0x30, 0xB4,
36472d7eceSJian Shen 	0x77, 0xCB, 0x2D, 0xA3, 0x80, 0x30, 0xF2, 0x0C,
37472d7eceSJian Shen 	0x6A, 0x42, 0xB7, 0x3B, 0xBE, 0xAC, 0x01, 0xFA
38472d7eceSJian Shen };
39472d7eceSJian Shen 
402f550a46SYunsheng Lin MODULE_DEVICE_TABLE(pci, ae_algovf_pci_tbl);
412f550a46SYunsheng Lin 
421600c3e5SJian Shen static const u32 cmdq_reg_addr_list[] = {HCLGEVF_CMDQ_TX_ADDR_L_REG,
431600c3e5SJian Shen 					 HCLGEVF_CMDQ_TX_ADDR_H_REG,
441600c3e5SJian Shen 					 HCLGEVF_CMDQ_TX_DEPTH_REG,
451600c3e5SJian Shen 					 HCLGEVF_CMDQ_TX_TAIL_REG,
461600c3e5SJian Shen 					 HCLGEVF_CMDQ_TX_HEAD_REG,
471600c3e5SJian Shen 					 HCLGEVF_CMDQ_RX_ADDR_L_REG,
481600c3e5SJian Shen 					 HCLGEVF_CMDQ_RX_ADDR_H_REG,
491600c3e5SJian Shen 					 HCLGEVF_CMDQ_RX_DEPTH_REG,
501600c3e5SJian Shen 					 HCLGEVF_CMDQ_RX_TAIL_REG,
511600c3e5SJian Shen 					 HCLGEVF_CMDQ_RX_HEAD_REG,
521600c3e5SJian Shen 					 HCLGEVF_VECTOR0_CMDQ_SRC_REG,
539cee2e8dSHuazhong Tan 					 HCLGEVF_VECTOR0_CMDQ_STATE_REG,
541600c3e5SJian Shen 					 HCLGEVF_CMDQ_INTR_EN_REG,
551600c3e5SJian Shen 					 HCLGEVF_CMDQ_INTR_GEN_REG};
561600c3e5SJian Shen 
571600c3e5SJian Shen static const u32 common_reg_addr_list[] = {HCLGEVF_MISC_VECTOR_REG_BASE,
581600c3e5SJian Shen 					   HCLGEVF_RST_ING,
591600c3e5SJian Shen 					   HCLGEVF_GRO_EN_REG};
601600c3e5SJian Shen 
611600c3e5SJian Shen static const u32 ring_reg_addr_list[] = {HCLGEVF_RING_RX_ADDR_L_REG,
621600c3e5SJian Shen 					 HCLGEVF_RING_RX_ADDR_H_REG,
631600c3e5SJian Shen 					 HCLGEVF_RING_RX_BD_NUM_REG,
641600c3e5SJian Shen 					 HCLGEVF_RING_RX_BD_LENGTH_REG,
651600c3e5SJian Shen 					 HCLGEVF_RING_RX_MERGE_EN_REG,
661600c3e5SJian Shen 					 HCLGEVF_RING_RX_TAIL_REG,
671600c3e5SJian Shen 					 HCLGEVF_RING_RX_HEAD_REG,
681600c3e5SJian Shen 					 HCLGEVF_RING_RX_FBD_NUM_REG,
691600c3e5SJian Shen 					 HCLGEVF_RING_RX_OFFSET_REG,
701600c3e5SJian Shen 					 HCLGEVF_RING_RX_FBD_OFFSET_REG,
711600c3e5SJian Shen 					 HCLGEVF_RING_RX_STASH_REG,
721600c3e5SJian Shen 					 HCLGEVF_RING_RX_BD_ERR_REG,
731600c3e5SJian Shen 					 HCLGEVF_RING_TX_ADDR_L_REG,
741600c3e5SJian Shen 					 HCLGEVF_RING_TX_ADDR_H_REG,
751600c3e5SJian Shen 					 HCLGEVF_RING_TX_BD_NUM_REG,
761600c3e5SJian Shen 					 HCLGEVF_RING_TX_PRIORITY_REG,
771600c3e5SJian Shen 					 HCLGEVF_RING_TX_TC_REG,
781600c3e5SJian Shen 					 HCLGEVF_RING_TX_MERGE_EN_REG,
791600c3e5SJian Shen 					 HCLGEVF_RING_TX_TAIL_REG,
801600c3e5SJian Shen 					 HCLGEVF_RING_TX_HEAD_REG,
811600c3e5SJian Shen 					 HCLGEVF_RING_TX_FBD_NUM_REG,
821600c3e5SJian Shen 					 HCLGEVF_RING_TX_OFFSET_REG,
831600c3e5SJian Shen 					 HCLGEVF_RING_TX_EBD_NUM_REG,
841600c3e5SJian Shen 					 HCLGEVF_RING_TX_EBD_OFFSET_REG,
851600c3e5SJian Shen 					 HCLGEVF_RING_TX_BD_ERR_REG,
861600c3e5SJian Shen 					 HCLGEVF_RING_EN_REG};
871600c3e5SJian Shen 
881600c3e5SJian Shen static const u32 tqp_intr_reg_addr_list[] = {HCLGEVF_TQP_INTR_CTRL_REG,
891600c3e5SJian Shen 					     HCLGEVF_TQP_INTR_GL0_REG,
901600c3e5SJian Shen 					     HCLGEVF_TQP_INTR_GL1_REG,
911600c3e5SJian Shen 					     HCLGEVF_TQP_INTR_GL2_REG,
921600c3e5SJian Shen 					     HCLGEVF_TQP_INTR_RL_REG};
931600c3e5SJian Shen 
949b2f3477SWeihang Li static struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle)
95e2cb1decSSalil Mehta {
96eed9535fSPeng Li 	if (!handle->client)
97eed9535fSPeng Li 		return container_of(handle, struct hclgevf_dev, nic);
98eed9535fSPeng Li 	else if (handle->client->type == HNAE3_CLIENT_ROCE)
99eed9535fSPeng Li 		return container_of(handle, struct hclgevf_dev, roce);
100eed9535fSPeng Li 	else
101e2cb1decSSalil Mehta 		return container_of(handle, struct hclgevf_dev, nic);
102e2cb1decSSalil Mehta }
103e2cb1decSSalil Mehta 
104e2cb1decSSalil Mehta static int hclgevf_tqps_update_stats(struct hnae3_handle *handle)
105e2cb1decSSalil Mehta {
106b4f1d303SJian Shen 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
107e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
108e2cb1decSSalil Mehta 	struct hclgevf_desc desc;
109e2cb1decSSalil Mehta 	struct hclgevf_tqp *tqp;
110e2cb1decSSalil Mehta 	int status;
111e2cb1decSSalil Mehta 	int i;
112e2cb1decSSalil Mehta 
113b4f1d303SJian Shen 	for (i = 0; i < kinfo->num_tqps; i++) {
114b4f1d303SJian Shen 		tqp = container_of(kinfo->tqp[i], struct hclgevf_tqp, q);
115e2cb1decSSalil Mehta 		hclgevf_cmd_setup_basic_desc(&desc,
116e2cb1decSSalil Mehta 					     HCLGEVF_OPC_QUERY_RX_STATUS,
117e2cb1decSSalil Mehta 					     true);
118e2cb1decSSalil Mehta 
119e2cb1decSSalil Mehta 		desc.data[0] = cpu_to_le32(tqp->index & 0x1ff);
120e2cb1decSSalil Mehta 		status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
121e2cb1decSSalil Mehta 		if (status) {
122e2cb1decSSalil Mehta 			dev_err(&hdev->pdev->dev,
123e2cb1decSSalil Mehta 				"Query tqp stat fail, status = %d,queue = %d\n",
124e2cb1decSSalil Mehta 				status,	i);
125e2cb1decSSalil Mehta 			return status;
126e2cb1decSSalil Mehta 		}
127e2cb1decSSalil Mehta 		tqp->tqp_stats.rcb_rx_ring_pktnum_rcd +=
128cf72fa63SJian Shen 			le32_to_cpu(desc.data[1]);
129e2cb1decSSalil Mehta 
130e2cb1decSSalil Mehta 		hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_QUERY_TX_STATUS,
131e2cb1decSSalil Mehta 					     true);
132e2cb1decSSalil Mehta 
133e2cb1decSSalil Mehta 		desc.data[0] = cpu_to_le32(tqp->index & 0x1ff);
134e2cb1decSSalil Mehta 		status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
135e2cb1decSSalil Mehta 		if (status) {
136e2cb1decSSalil Mehta 			dev_err(&hdev->pdev->dev,
137e2cb1decSSalil Mehta 				"Query tqp stat fail, status = %d,queue = %d\n",
138e2cb1decSSalil Mehta 				status, i);
139e2cb1decSSalil Mehta 			return status;
140e2cb1decSSalil Mehta 		}
141e2cb1decSSalil Mehta 		tqp->tqp_stats.rcb_tx_ring_pktnum_rcd +=
142cf72fa63SJian Shen 			le32_to_cpu(desc.data[1]);
143e2cb1decSSalil Mehta 	}
144e2cb1decSSalil Mehta 
145e2cb1decSSalil Mehta 	return 0;
146e2cb1decSSalil Mehta }
147e2cb1decSSalil Mehta 
148e2cb1decSSalil Mehta static u64 *hclgevf_tqps_get_stats(struct hnae3_handle *handle, u64 *data)
149e2cb1decSSalil Mehta {
150e2cb1decSSalil Mehta 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
151e2cb1decSSalil Mehta 	struct hclgevf_tqp *tqp;
152e2cb1decSSalil Mehta 	u64 *buff = data;
153e2cb1decSSalil Mehta 	int i;
154e2cb1decSSalil Mehta 
155b4f1d303SJian Shen 	for (i = 0; i < kinfo->num_tqps; i++) {
156b4f1d303SJian Shen 		tqp = container_of(kinfo->tqp[i], struct hclgevf_tqp, q);
157e2cb1decSSalil Mehta 		*buff++ = tqp->tqp_stats.rcb_tx_ring_pktnum_rcd;
158e2cb1decSSalil Mehta 	}
159e2cb1decSSalil Mehta 	for (i = 0; i < kinfo->num_tqps; i++) {
160b4f1d303SJian Shen 		tqp = container_of(kinfo->tqp[i], struct hclgevf_tqp, q);
161e2cb1decSSalil Mehta 		*buff++ = tqp->tqp_stats.rcb_rx_ring_pktnum_rcd;
162e2cb1decSSalil Mehta 	}
163e2cb1decSSalil Mehta 
164e2cb1decSSalil Mehta 	return buff;
165e2cb1decSSalil Mehta }
166e2cb1decSSalil Mehta 
167e2cb1decSSalil Mehta static int hclgevf_tqps_get_sset_count(struct hnae3_handle *handle, int strset)
168e2cb1decSSalil Mehta {
169b4f1d303SJian Shen 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
170e2cb1decSSalil Mehta 
171b4f1d303SJian Shen 	return kinfo->num_tqps * 2;
172e2cb1decSSalil Mehta }
173e2cb1decSSalil Mehta 
174e2cb1decSSalil Mehta static u8 *hclgevf_tqps_get_strings(struct hnae3_handle *handle, u8 *data)
175e2cb1decSSalil Mehta {
176b4f1d303SJian Shen 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
177e2cb1decSSalil Mehta 	u8 *buff = data;
1789d8d5a36SYufeng Mo 	int i;
179e2cb1decSSalil Mehta 
180b4f1d303SJian Shen 	for (i = 0; i < kinfo->num_tqps; i++) {
181b4f1d303SJian Shen 		struct hclgevf_tqp *tqp = container_of(kinfo->tqp[i],
182e2cb1decSSalil Mehta 						       struct hclgevf_tqp, q);
183c5aaf176SJiaran Zhang 		snprintf(buff, ETH_GSTRING_LEN, "txq%u_pktnum_rcd",
184e2cb1decSSalil Mehta 			 tqp->index);
185e2cb1decSSalil Mehta 		buff += ETH_GSTRING_LEN;
186e2cb1decSSalil Mehta 	}
187e2cb1decSSalil Mehta 
188b4f1d303SJian Shen 	for (i = 0; i < kinfo->num_tqps; i++) {
189b4f1d303SJian Shen 		struct hclgevf_tqp *tqp = container_of(kinfo->tqp[i],
190e2cb1decSSalil Mehta 						       struct hclgevf_tqp, q);
191c5aaf176SJiaran Zhang 		snprintf(buff, ETH_GSTRING_LEN, "rxq%u_pktnum_rcd",
192e2cb1decSSalil Mehta 			 tqp->index);
193e2cb1decSSalil Mehta 		buff += ETH_GSTRING_LEN;
194e2cb1decSSalil Mehta 	}
195e2cb1decSSalil Mehta 
196e2cb1decSSalil Mehta 	return buff;
197e2cb1decSSalil Mehta }
198e2cb1decSSalil Mehta 
199e2cb1decSSalil Mehta static void hclgevf_update_stats(struct hnae3_handle *handle,
200e2cb1decSSalil Mehta 				 struct net_device_stats *net_stats)
201e2cb1decSSalil Mehta {
202e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
203e2cb1decSSalil Mehta 	int status;
204e2cb1decSSalil Mehta 
205e2cb1decSSalil Mehta 	status = hclgevf_tqps_update_stats(handle);
206e2cb1decSSalil Mehta 	if (status)
207e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
208e2cb1decSSalil Mehta 			"VF update of TQPS stats fail, status = %d.\n",
209e2cb1decSSalil Mehta 			status);
210e2cb1decSSalil Mehta }
211e2cb1decSSalil Mehta 
212e2cb1decSSalil Mehta static int hclgevf_get_sset_count(struct hnae3_handle *handle, int strset)
213e2cb1decSSalil Mehta {
214e2cb1decSSalil Mehta 	if (strset == ETH_SS_TEST)
215e2cb1decSSalil Mehta 		return -EOPNOTSUPP;
216e2cb1decSSalil Mehta 	else if (strset == ETH_SS_STATS)
217e2cb1decSSalil Mehta 		return hclgevf_tqps_get_sset_count(handle, strset);
218e2cb1decSSalil Mehta 
219e2cb1decSSalil Mehta 	return 0;
220e2cb1decSSalil Mehta }
221e2cb1decSSalil Mehta 
222e2cb1decSSalil Mehta static void hclgevf_get_strings(struct hnae3_handle *handle, u32 strset,
223e2cb1decSSalil Mehta 				u8 *data)
224e2cb1decSSalil Mehta {
225e2cb1decSSalil Mehta 	u8 *p = (char *)data;
226e2cb1decSSalil Mehta 
227e2cb1decSSalil Mehta 	if (strset == ETH_SS_STATS)
228e2cb1decSSalil Mehta 		p = hclgevf_tqps_get_strings(handle, p);
229e2cb1decSSalil Mehta }
230e2cb1decSSalil Mehta 
231e2cb1decSSalil Mehta static void hclgevf_get_stats(struct hnae3_handle *handle, u64 *data)
232e2cb1decSSalil Mehta {
233e2cb1decSSalil Mehta 	hclgevf_tqps_get_stats(handle, data);
234e2cb1decSSalil Mehta }
235e2cb1decSSalil Mehta 
236d3410018SYufeng Mo static void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code,
237d3410018SYufeng Mo 				   u8 subcode)
238d3410018SYufeng Mo {
239d3410018SYufeng Mo 	if (msg) {
240d3410018SYufeng Mo 		memset(msg, 0, sizeof(struct hclge_vf_to_pf_msg));
241d3410018SYufeng Mo 		msg->code = code;
242d3410018SYufeng Mo 		msg->subcode = subcode;
243d3410018SYufeng Mo 	}
244d3410018SYufeng Mo }
245d3410018SYufeng Mo 
246e2cb1decSSalil Mehta static int hclgevf_get_tc_info(struct hclgevf_dev *hdev)
247e2cb1decSSalil Mehta {
248d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
249e2cb1decSSalil Mehta 	u8 resp_msg;
250e2cb1decSSalil Mehta 	int status;
251e2cb1decSSalil Mehta 
252d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_TCINFO, 0);
253d3410018SYufeng Mo 	status = hclgevf_send_mbx_msg(hdev, &send_msg, true, &resp_msg,
254d3410018SYufeng Mo 				      sizeof(resp_msg));
255e2cb1decSSalil Mehta 	if (status) {
256e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
257e2cb1decSSalil Mehta 			"VF request to get TC info from PF failed %d",
258e2cb1decSSalil Mehta 			status);
259e2cb1decSSalil Mehta 		return status;
260e2cb1decSSalil Mehta 	}
261e2cb1decSSalil Mehta 
262e2cb1decSSalil Mehta 	hdev->hw_tc_map = resp_msg;
263e2cb1decSSalil Mehta 
264e2cb1decSSalil Mehta 	return 0;
265e2cb1decSSalil Mehta }
266e2cb1decSSalil Mehta 
26792f11ea1SJian Shen static int hclgevf_get_port_base_vlan_filter_state(struct hclgevf_dev *hdev)
26892f11ea1SJian Shen {
26992f11ea1SJian Shen 	struct hnae3_handle *nic = &hdev->nic;
270d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
27192f11ea1SJian Shen 	u8 resp_msg;
27292f11ea1SJian Shen 	int ret;
27392f11ea1SJian Shen 
274d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
275d3410018SYufeng Mo 			       HCLGE_MBX_GET_PORT_BASE_VLAN_STATE);
276d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, &resp_msg,
277d3410018SYufeng Mo 				   sizeof(u8));
27892f11ea1SJian Shen 	if (ret) {
27992f11ea1SJian Shen 		dev_err(&hdev->pdev->dev,
28092f11ea1SJian Shen 			"VF request to get port based vlan state failed %d",
28192f11ea1SJian Shen 			ret);
28292f11ea1SJian Shen 		return ret;
28392f11ea1SJian Shen 	}
28492f11ea1SJian Shen 
28592f11ea1SJian Shen 	nic->port_base_vlan_state = resp_msg;
28692f11ea1SJian Shen 
28792f11ea1SJian Shen 	return 0;
28892f11ea1SJian Shen }
28992f11ea1SJian Shen 
2906cee6fc3SJian Shen static int hclgevf_get_queue_info(struct hclgevf_dev *hdev)
291e2cb1decSSalil Mehta {
292c0425944SPeng Li #define HCLGEVF_TQPS_RSS_INFO_LEN	6
293d3410018SYufeng Mo #define HCLGEVF_TQPS_ALLOC_OFFSET	0
294d3410018SYufeng Mo #define HCLGEVF_TQPS_RSS_SIZE_OFFSET	2
295d3410018SYufeng Mo #define HCLGEVF_TQPS_RX_BUFFER_LEN_OFFSET	4
296d3410018SYufeng Mo 
297e2cb1decSSalil Mehta 	u8 resp_msg[HCLGEVF_TQPS_RSS_INFO_LEN];
298d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
299e2cb1decSSalil Mehta 	int status;
300e2cb1decSSalil Mehta 
301d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_QINFO, 0);
302d3410018SYufeng Mo 	status = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
303e2cb1decSSalil Mehta 				      HCLGEVF_TQPS_RSS_INFO_LEN);
304e2cb1decSSalil Mehta 	if (status) {
305e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
306e2cb1decSSalil Mehta 			"VF request to get tqp info from PF failed %d",
307e2cb1decSSalil Mehta 			status);
308e2cb1decSSalil Mehta 		return status;
309e2cb1decSSalil Mehta 	}
310e2cb1decSSalil Mehta 
311d3410018SYufeng Mo 	memcpy(&hdev->num_tqps, &resp_msg[HCLGEVF_TQPS_ALLOC_OFFSET],
312d3410018SYufeng Mo 	       sizeof(u16));
313d3410018SYufeng Mo 	memcpy(&hdev->rss_size_max, &resp_msg[HCLGEVF_TQPS_RSS_SIZE_OFFSET],
314d3410018SYufeng Mo 	       sizeof(u16));
315d3410018SYufeng Mo 	memcpy(&hdev->rx_buf_len, &resp_msg[HCLGEVF_TQPS_RX_BUFFER_LEN_OFFSET],
316d3410018SYufeng Mo 	       sizeof(u16));
317c0425944SPeng Li 
318c0425944SPeng Li 	return 0;
319c0425944SPeng Li }
320c0425944SPeng Li 
321c0425944SPeng Li static int hclgevf_get_queue_depth(struct hclgevf_dev *hdev)
322c0425944SPeng Li {
323c0425944SPeng Li #define HCLGEVF_TQPS_DEPTH_INFO_LEN	4
324d3410018SYufeng Mo #define HCLGEVF_TQPS_NUM_TX_DESC_OFFSET	0
325d3410018SYufeng Mo #define HCLGEVF_TQPS_NUM_RX_DESC_OFFSET	2
326d3410018SYufeng Mo 
327c0425944SPeng Li 	u8 resp_msg[HCLGEVF_TQPS_DEPTH_INFO_LEN];
328d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
329c0425944SPeng Li 	int ret;
330c0425944SPeng Li 
331d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_QDEPTH, 0);
332d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
333c0425944SPeng Li 				   HCLGEVF_TQPS_DEPTH_INFO_LEN);
334c0425944SPeng Li 	if (ret) {
335c0425944SPeng Li 		dev_err(&hdev->pdev->dev,
336c0425944SPeng Li 			"VF request to get tqp depth info from PF failed %d",
337c0425944SPeng Li 			ret);
338c0425944SPeng Li 		return ret;
339c0425944SPeng Li 	}
340c0425944SPeng Li 
341d3410018SYufeng Mo 	memcpy(&hdev->num_tx_desc, &resp_msg[HCLGEVF_TQPS_NUM_TX_DESC_OFFSET],
342d3410018SYufeng Mo 	       sizeof(u16));
343d3410018SYufeng Mo 	memcpy(&hdev->num_rx_desc, &resp_msg[HCLGEVF_TQPS_NUM_RX_DESC_OFFSET],
344d3410018SYufeng Mo 	       sizeof(u16));
345e2cb1decSSalil Mehta 
346e2cb1decSSalil Mehta 	return 0;
347e2cb1decSSalil Mehta }
348e2cb1decSSalil Mehta 
3490c29d191Sliuzhongzhu static u16 hclgevf_get_qid_global(struct hnae3_handle *handle, u16 queue_id)
3500c29d191Sliuzhongzhu {
3510c29d191Sliuzhongzhu 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
352d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
3530c29d191Sliuzhongzhu 	u16 qid_in_pf = 0;
354d3410018SYufeng Mo 	u8 resp_data[2];
3550c29d191Sliuzhongzhu 	int ret;
3560c29d191Sliuzhongzhu 
357d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_QID_IN_PF, 0);
358d3410018SYufeng Mo 	memcpy(send_msg.data, &queue_id, sizeof(queue_id));
359d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_data,
36063cbf7a9SYufeng Mo 				   sizeof(resp_data));
3610c29d191Sliuzhongzhu 	if (!ret)
3620c29d191Sliuzhongzhu 		qid_in_pf = *(u16 *)resp_data;
3630c29d191Sliuzhongzhu 
3640c29d191Sliuzhongzhu 	return qid_in_pf;
3650c29d191Sliuzhongzhu }
3660c29d191Sliuzhongzhu 
3679c3e7130Sliuzhongzhu static int hclgevf_get_pf_media_type(struct hclgevf_dev *hdev)
3689c3e7130Sliuzhongzhu {
369d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
37088d10bd6SJian Shen 	u8 resp_msg[2];
3719c3e7130Sliuzhongzhu 	int ret;
3729c3e7130Sliuzhongzhu 
373d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_MEDIA_TYPE, 0);
374d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
375d3410018SYufeng Mo 				   sizeof(resp_msg));
3769c3e7130Sliuzhongzhu 	if (ret) {
3779c3e7130Sliuzhongzhu 		dev_err(&hdev->pdev->dev,
3789c3e7130Sliuzhongzhu 			"VF request to get the pf port media type failed %d",
3799c3e7130Sliuzhongzhu 			ret);
3809c3e7130Sliuzhongzhu 		return ret;
3819c3e7130Sliuzhongzhu 	}
3829c3e7130Sliuzhongzhu 
38388d10bd6SJian Shen 	hdev->hw.mac.media_type = resp_msg[0];
38488d10bd6SJian Shen 	hdev->hw.mac.module_type = resp_msg[1];
3859c3e7130Sliuzhongzhu 
3869c3e7130Sliuzhongzhu 	return 0;
3879c3e7130Sliuzhongzhu }
3889c3e7130Sliuzhongzhu 
389e2cb1decSSalil Mehta static int hclgevf_alloc_tqps(struct hclgevf_dev *hdev)
390e2cb1decSSalil Mehta {
391e2cb1decSSalil Mehta 	struct hclgevf_tqp *tqp;
392e2cb1decSSalil Mehta 	int i;
393e2cb1decSSalil Mehta 
394e2cb1decSSalil Mehta 	hdev->htqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps,
395e2cb1decSSalil Mehta 				  sizeof(struct hclgevf_tqp), GFP_KERNEL);
396e2cb1decSSalil Mehta 	if (!hdev->htqp)
397e2cb1decSSalil Mehta 		return -ENOMEM;
398e2cb1decSSalil Mehta 
399e2cb1decSSalil Mehta 	tqp = hdev->htqp;
400e2cb1decSSalil Mehta 
401e2cb1decSSalil Mehta 	for (i = 0; i < hdev->num_tqps; i++) {
402e2cb1decSSalil Mehta 		tqp->dev = &hdev->pdev->dev;
403e2cb1decSSalil Mehta 		tqp->index = i;
404e2cb1decSSalil Mehta 
405e2cb1decSSalil Mehta 		tqp->q.ae_algo = &ae_algovf;
406e2cb1decSSalil Mehta 		tqp->q.buf_size = hdev->rx_buf_len;
407c0425944SPeng Li 		tqp->q.tx_desc_num = hdev->num_tx_desc;
408c0425944SPeng Li 		tqp->q.rx_desc_num = hdev->num_rx_desc;
4099a5ef4aaSYonglong Liu 
4109a5ef4aaSYonglong Liu 		/* need an extended offset to configure queues >=
4119a5ef4aaSYonglong Liu 		 * HCLGEVF_TQP_MAX_SIZE_DEV_V2.
4129a5ef4aaSYonglong Liu 		 */
4139a5ef4aaSYonglong Liu 		if (i < HCLGEVF_TQP_MAX_SIZE_DEV_V2)
4149a5ef4aaSYonglong Liu 			tqp->q.io_base = hdev->hw.io_base +
4159a5ef4aaSYonglong Liu 					 HCLGEVF_TQP_REG_OFFSET +
416e2cb1decSSalil Mehta 					 i * HCLGEVF_TQP_REG_SIZE;
4179a5ef4aaSYonglong Liu 		else
4189a5ef4aaSYonglong Liu 			tqp->q.io_base = hdev->hw.io_base +
4199a5ef4aaSYonglong Liu 					 HCLGEVF_TQP_REG_OFFSET +
4209a5ef4aaSYonglong Liu 					 HCLGEVF_TQP_EXT_REG_OFFSET +
4219a5ef4aaSYonglong Liu 					 (i - HCLGEVF_TQP_MAX_SIZE_DEV_V2) *
4229a5ef4aaSYonglong Liu 					 HCLGEVF_TQP_REG_SIZE;
423e2cb1decSSalil Mehta 
424e2cb1decSSalil Mehta 		tqp++;
425e2cb1decSSalil Mehta 	}
426e2cb1decSSalil Mehta 
427e2cb1decSSalil Mehta 	return 0;
428e2cb1decSSalil Mehta }
429e2cb1decSSalil Mehta 
430e2cb1decSSalil Mehta static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
431e2cb1decSSalil Mehta {
432e2cb1decSSalil Mehta 	struct hnae3_handle *nic = &hdev->nic;
433e2cb1decSSalil Mehta 	struct hnae3_knic_private_info *kinfo;
434e2cb1decSSalil Mehta 	u16 new_tqps = hdev->num_tqps;
435ebaf1908SWeihang Li 	unsigned int i;
43635244430SJian Shen 	u8 num_tc = 0;
437e2cb1decSSalil Mehta 
438e2cb1decSSalil Mehta 	kinfo = &nic->kinfo;
439c0425944SPeng Li 	kinfo->num_tx_desc = hdev->num_tx_desc;
440c0425944SPeng Li 	kinfo->num_rx_desc = hdev->num_rx_desc;
441e2cb1decSSalil Mehta 	kinfo->rx_buf_len = hdev->rx_buf_len;
442e2cb1decSSalil Mehta 	for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++)
443e2cb1decSSalil Mehta 		if (hdev->hw_tc_map & BIT(i))
44435244430SJian Shen 			num_tc++;
445e2cb1decSSalil Mehta 
44635244430SJian Shen 	num_tc = num_tc ? num_tc : 1;
44735244430SJian Shen 	kinfo->tc_info.num_tc = num_tc;
44835244430SJian Shen 	kinfo->rss_size = min_t(u16, hdev->rss_size_max, new_tqps / num_tc);
44935244430SJian Shen 	new_tqps = kinfo->rss_size * num_tc;
450e2cb1decSSalil Mehta 	kinfo->num_tqps = min(new_tqps, hdev->num_tqps);
451e2cb1decSSalil Mehta 
452e2cb1decSSalil Mehta 	kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps,
453e2cb1decSSalil Mehta 				  sizeof(struct hnae3_queue *), GFP_KERNEL);
454e2cb1decSSalil Mehta 	if (!kinfo->tqp)
455e2cb1decSSalil Mehta 		return -ENOMEM;
456e2cb1decSSalil Mehta 
457e2cb1decSSalil Mehta 	for (i = 0; i < kinfo->num_tqps; i++) {
458e2cb1decSSalil Mehta 		hdev->htqp[i].q.handle = &hdev->nic;
459e2cb1decSSalil Mehta 		hdev->htqp[i].q.tqp_index = i;
460e2cb1decSSalil Mehta 		kinfo->tqp[i] = &hdev->htqp[i].q;
461e2cb1decSSalil Mehta 	}
462e2cb1decSSalil Mehta 
463580a05f9SYonglong Liu 	/* after init the max rss_size and tqps, adjust the default tqp numbers
464580a05f9SYonglong Liu 	 * and rss size with the actual vector numbers
465580a05f9SYonglong Liu 	 */
466580a05f9SYonglong Liu 	kinfo->num_tqps = min_t(u16, hdev->num_nic_msix - 1, kinfo->num_tqps);
46735244430SJian Shen 	kinfo->rss_size = min_t(u16, kinfo->num_tqps / num_tc,
468580a05f9SYonglong Liu 				kinfo->rss_size);
469580a05f9SYonglong Liu 
470e2cb1decSSalil Mehta 	return 0;
471e2cb1decSSalil Mehta }
472e2cb1decSSalil Mehta 
473e2cb1decSSalil Mehta static void hclgevf_request_link_info(struct hclgevf_dev *hdev)
474e2cb1decSSalil Mehta {
475d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
476e2cb1decSSalil Mehta 	int status;
477e2cb1decSSalil Mehta 
478d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_LINK_STATUS, 0);
479d3410018SYufeng Mo 	status = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
480e2cb1decSSalil Mehta 	if (status)
481e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
482e2cb1decSSalil Mehta 			"VF failed to fetch link status(%d) from PF", status);
483e2cb1decSSalil Mehta }
484e2cb1decSSalil Mehta 
485e2cb1decSSalil Mehta void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state)
486e2cb1decSSalil Mehta {
48745e92b7eSPeng Li 	struct hnae3_handle *rhandle = &hdev->roce;
488e2cb1decSSalil Mehta 	struct hnae3_handle *handle = &hdev->nic;
48945e92b7eSPeng Li 	struct hnae3_client *rclient;
490e2cb1decSSalil Mehta 	struct hnae3_client *client;
491e2cb1decSSalil Mehta 
492ff200099SYunsheng Lin 	if (test_and_set_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state))
493ff200099SYunsheng Lin 		return;
494ff200099SYunsheng Lin 
495e2cb1decSSalil Mehta 	client = handle->client;
49645e92b7eSPeng Li 	rclient = hdev->roce_client;
497e2cb1decSSalil Mehta 
498582d37bbSPeng Li 	link_state =
499582d37bbSPeng Li 		test_bit(HCLGEVF_STATE_DOWN, &hdev->state) ? 0 : link_state;
500582d37bbSPeng Li 
501e2cb1decSSalil Mehta 	if (link_state != hdev->hw.mac.link) {
502e2cb1decSSalil Mehta 		client->ops->link_status_change(handle, !!link_state);
50345e92b7eSPeng Li 		if (rclient && rclient->ops->link_status_change)
50445e92b7eSPeng Li 			rclient->ops->link_status_change(rhandle, !!link_state);
505e2cb1decSSalil Mehta 		hdev->hw.mac.link = link_state;
506e2cb1decSSalil Mehta 	}
507ff200099SYunsheng Lin 
508ff200099SYunsheng Lin 	clear_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state);
509e2cb1decSSalil Mehta }
510e2cb1decSSalil Mehta 
511538abaf3SYueHaibing static void hclgevf_update_link_mode(struct hclgevf_dev *hdev)
5129194d18bSliuzhongzhu {
5139194d18bSliuzhongzhu #define HCLGEVF_ADVERTISING	0
5149194d18bSliuzhongzhu #define HCLGEVF_SUPPORTED	1
5159194d18bSliuzhongzhu 
516d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
517d3410018SYufeng Mo 
518d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_LINK_MODE, 0);
519d3410018SYufeng Mo 	send_msg.data[0] = HCLGEVF_ADVERTISING;
520d3410018SYufeng Mo 	hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
521d3410018SYufeng Mo 	send_msg.data[0] = HCLGEVF_SUPPORTED;
522d3410018SYufeng Mo 	hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
5239194d18bSliuzhongzhu }
5249194d18bSliuzhongzhu 
525e2cb1decSSalil Mehta static int hclgevf_set_handle_info(struct hclgevf_dev *hdev)
526e2cb1decSSalil Mehta {
527e2cb1decSSalil Mehta 	struct hnae3_handle *nic = &hdev->nic;
528e2cb1decSSalil Mehta 	int ret;
529e2cb1decSSalil Mehta 
530e2cb1decSSalil Mehta 	nic->ae_algo = &ae_algovf;
531e2cb1decSSalil Mehta 	nic->pdev = hdev->pdev;
532e2cb1decSSalil Mehta 	nic->numa_node_mask = hdev->numa_node_mask;
533424eb834SSalil Mehta 	nic->flags |= HNAE3_SUPPORT_VF;
534e2cb1decSSalil Mehta 
535e2cb1decSSalil Mehta 	ret = hclgevf_knic_setup(hdev);
536e2cb1decSSalil Mehta 	if (ret)
537e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev, "VF knic setup failed %d\n",
538e2cb1decSSalil Mehta 			ret);
539e2cb1decSSalil Mehta 	return ret;
540e2cb1decSSalil Mehta }
541e2cb1decSSalil Mehta 
542e2cb1decSSalil Mehta static void hclgevf_free_vector(struct hclgevf_dev *hdev, int vector_id)
543e2cb1decSSalil Mehta {
54436cbbdf6SPeng Li 	if (hdev->vector_status[vector_id] == HCLGEVF_INVALID_VPORT) {
54536cbbdf6SPeng Li 		dev_warn(&hdev->pdev->dev,
54636cbbdf6SPeng Li 			 "vector(vector_id %d) has been freed.\n", vector_id);
54736cbbdf6SPeng Li 		return;
54836cbbdf6SPeng Li 	}
54936cbbdf6SPeng Li 
550e2cb1decSSalil Mehta 	hdev->vector_status[vector_id] = HCLGEVF_INVALID_VPORT;
551e2cb1decSSalil Mehta 	hdev->num_msi_left += 1;
552e2cb1decSSalil Mehta 	hdev->num_msi_used -= 1;
553e2cb1decSSalil Mehta }
554e2cb1decSSalil Mehta 
555e2cb1decSSalil Mehta static int hclgevf_get_vector(struct hnae3_handle *handle, u16 vector_num,
556e2cb1decSSalil Mehta 			      struct hnae3_vector_info *vector_info)
557e2cb1decSSalil Mehta {
558e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
559e2cb1decSSalil Mehta 	struct hnae3_vector_info *vector = vector_info;
560e2cb1decSSalil Mehta 	int alloc = 0;
561e2cb1decSSalil Mehta 	int i, j;
562e2cb1decSSalil Mehta 
563580a05f9SYonglong Liu 	vector_num = min_t(u16, hdev->num_nic_msix - 1, vector_num);
564e2cb1decSSalil Mehta 	vector_num = min(hdev->num_msi_left, vector_num);
565e2cb1decSSalil Mehta 
566e2cb1decSSalil Mehta 	for (j = 0; j < vector_num; j++) {
567e2cb1decSSalil Mehta 		for (i = HCLGEVF_MISC_VECTOR_NUM + 1; i < hdev->num_msi; i++) {
568e2cb1decSSalil Mehta 			if (hdev->vector_status[i] == HCLGEVF_INVALID_VPORT) {
569e2cb1decSSalil Mehta 				vector->vector = pci_irq_vector(hdev->pdev, i);
570e2cb1decSSalil Mehta 				vector->io_addr = hdev->hw.io_base +
571e2cb1decSSalil Mehta 					HCLGEVF_VECTOR_REG_BASE +
572e2cb1decSSalil Mehta 					(i - 1) * HCLGEVF_VECTOR_REG_OFFSET;
573e2cb1decSSalil Mehta 				hdev->vector_status[i] = 0;
574e2cb1decSSalil Mehta 				hdev->vector_irq[i] = vector->vector;
575e2cb1decSSalil Mehta 
576e2cb1decSSalil Mehta 				vector++;
577e2cb1decSSalil Mehta 				alloc++;
578e2cb1decSSalil Mehta 
579e2cb1decSSalil Mehta 				break;
580e2cb1decSSalil Mehta 			}
581e2cb1decSSalil Mehta 		}
582e2cb1decSSalil Mehta 	}
583e2cb1decSSalil Mehta 	hdev->num_msi_left -= alloc;
584e2cb1decSSalil Mehta 	hdev->num_msi_used += alloc;
585e2cb1decSSalil Mehta 
586e2cb1decSSalil Mehta 	return alloc;
587e2cb1decSSalil Mehta }
588e2cb1decSSalil Mehta 
589e2cb1decSSalil Mehta static int hclgevf_get_vector_index(struct hclgevf_dev *hdev, int vector)
590e2cb1decSSalil Mehta {
591e2cb1decSSalil Mehta 	int i;
592e2cb1decSSalil Mehta 
593e2cb1decSSalil Mehta 	for (i = 0; i < hdev->num_msi; i++)
594e2cb1decSSalil Mehta 		if (vector == hdev->vector_irq[i])
595e2cb1decSSalil Mehta 			return i;
596e2cb1decSSalil Mehta 
597e2cb1decSSalil Mehta 	return -EINVAL;
598e2cb1decSSalil Mehta }
599e2cb1decSSalil Mehta 
600374ad291SJian Shen static int hclgevf_set_rss_algo_key(struct hclgevf_dev *hdev,
601374ad291SJian Shen 				    const u8 hfunc, const u8 *key)
602374ad291SJian Shen {
603374ad291SJian Shen 	struct hclgevf_rss_config_cmd *req;
604ebaf1908SWeihang Li 	unsigned int key_offset = 0;
605374ad291SJian Shen 	struct hclgevf_desc desc;
6063caf772bSYufeng Mo 	int key_counts;
607374ad291SJian Shen 	int key_size;
608374ad291SJian Shen 	int ret;
609374ad291SJian Shen 
6103caf772bSYufeng Mo 	key_counts = HCLGEVF_RSS_KEY_SIZE;
611374ad291SJian Shen 	req = (struct hclgevf_rss_config_cmd *)desc.data;
612374ad291SJian Shen 
6133caf772bSYufeng Mo 	while (key_counts) {
614374ad291SJian Shen 		hclgevf_cmd_setup_basic_desc(&desc,
615374ad291SJian Shen 					     HCLGEVF_OPC_RSS_GENERIC_CONFIG,
616374ad291SJian Shen 					     false);
617374ad291SJian Shen 
618374ad291SJian Shen 		req->hash_config |= (hfunc & HCLGEVF_RSS_HASH_ALGO_MASK);
619374ad291SJian Shen 		req->hash_config |=
620374ad291SJian Shen 			(key_offset << HCLGEVF_RSS_HASH_KEY_OFFSET_B);
621374ad291SJian Shen 
6223caf772bSYufeng Mo 		key_size = min(HCLGEVF_RSS_HASH_KEY_NUM, key_counts);
623374ad291SJian Shen 		memcpy(req->hash_key,
624374ad291SJian Shen 		       key + key_offset * HCLGEVF_RSS_HASH_KEY_NUM, key_size);
625374ad291SJian Shen 
6263caf772bSYufeng Mo 		key_counts -= key_size;
6273caf772bSYufeng Mo 		key_offset++;
628374ad291SJian Shen 		ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
629374ad291SJian Shen 		if (ret) {
630374ad291SJian Shen 			dev_err(&hdev->pdev->dev,
631374ad291SJian Shen 				"Configure RSS config fail, status = %d\n",
632374ad291SJian Shen 				ret);
633374ad291SJian Shen 			return ret;
634374ad291SJian Shen 		}
635374ad291SJian Shen 	}
636374ad291SJian Shen 
637374ad291SJian Shen 	return 0;
638374ad291SJian Shen }
639374ad291SJian Shen 
640e2cb1decSSalil Mehta static u32 hclgevf_get_rss_key_size(struct hnae3_handle *handle)
641e2cb1decSSalil Mehta {
642e2cb1decSSalil Mehta 	return HCLGEVF_RSS_KEY_SIZE;
643e2cb1decSSalil Mehta }
644e2cb1decSSalil Mehta 
645e2cb1decSSalil Mehta static int hclgevf_set_rss_indir_table(struct hclgevf_dev *hdev)
646e2cb1decSSalil Mehta {
647e2cb1decSSalil Mehta 	const u8 *indir = hdev->rss_cfg.rss_indirection_tbl;
648e2cb1decSSalil Mehta 	struct hclgevf_rss_indirection_table_cmd *req;
649e2cb1decSSalil Mehta 	struct hclgevf_desc desc;
65087ce161eSGuangbin Huang 	int rss_cfg_tbl_num;
651e2cb1decSSalil Mehta 	int status;
652e2cb1decSSalil Mehta 	int i, j;
653e2cb1decSSalil Mehta 
654e2cb1decSSalil Mehta 	req = (struct hclgevf_rss_indirection_table_cmd *)desc.data;
65587ce161eSGuangbin Huang 	rss_cfg_tbl_num = hdev->ae_dev->dev_specs.rss_ind_tbl_size /
65687ce161eSGuangbin Huang 			  HCLGEVF_RSS_CFG_TBL_SIZE;
657e2cb1decSSalil Mehta 
65887ce161eSGuangbin Huang 	for (i = 0; i < rss_cfg_tbl_num; i++) {
659e2cb1decSSalil Mehta 		hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INDIR_TABLE,
660e2cb1decSSalil Mehta 					     false);
66155ff3ed5SJian Shen 		req->start_table_index =
66255ff3ed5SJian Shen 			cpu_to_le16(i * HCLGEVF_RSS_CFG_TBL_SIZE);
66355ff3ed5SJian Shen 		req->rss_set_bitmap = cpu_to_le16(HCLGEVF_RSS_SET_BITMAP_MSK);
664e2cb1decSSalil Mehta 		for (j = 0; j < HCLGEVF_RSS_CFG_TBL_SIZE; j++)
665e2cb1decSSalil Mehta 			req->rss_result[j] =
666e2cb1decSSalil Mehta 				indir[i * HCLGEVF_RSS_CFG_TBL_SIZE + j];
667e2cb1decSSalil Mehta 
668e2cb1decSSalil Mehta 		status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
669e2cb1decSSalil Mehta 		if (status) {
670e2cb1decSSalil Mehta 			dev_err(&hdev->pdev->dev,
671e2cb1decSSalil Mehta 				"VF failed(=%d) to set RSS indirection table\n",
672e2cb1decSSalil Mehta 				status);
673e2cb1decSSalil Mehta 			return status;
674e2cb1decSSalil Mehta 		}
675e2cb1decSSalil Mehta 	}
676e2cb1decSSalil Mehta 
677e2cb1decSSalil Mehta 	return 0;
678e2cb1decSSalil Mehta }
679e2cb1decSSalil Mehta 
680e2cb1decSSalil Mehta static int hclgevf_set_rss_tc_mode(struct hclgevf_dev *hdev,  u16 rss_size)
681e2cb1decSSalil Mehta {
682e2cb1decSSalil Mehta 	struct hclgevf_rss_tc_mode_cmd *req;
683e2cb1decSSalil Mehta 	u16 tc_offset[HCLGEVF_MAX_TC_NUM];
684e2cb1decSSalil Mehta 	u16 tc_valid[HCLGEVF_MAX_TC_NUM];
685e2cb1decSSalil Mehta 	u16 tc_size[HCLGEVF_MAX_TC_NUM];
686e2cb1decSSalil Mehta 	struct hclgevf_desc desc;
687e2cb1decSSalil Mehta 	u16 roundup_size;
688ebaf1908SWeihang Li 	unsigned int i;
6892adb8187SHuazhong Tan 	int status;
690e2cb1decSSalil Mehta 
691e2cb1decSSalil Mehta 	req = (struct hclgevf_rss_tc_mode_cmd *)desc.data;
692e2cb1decSSalil Mehta 
693e2cb1decSSalil Mehta 	roundup_size = roundup_pow_of_two(rss_size);
694e2cb1decSSalil Mehta 	roundup_size = ilog2(roundup_size);
695e2cb1decSSalil Mehta 
696e2cb1decSSalil Mehta 	for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++) {
697e2cb1decSSalil Mehta 		tc_valid[i] = !!(hdev->hw_tc_map & BIT(i));
698e2cb1decSSalil Mehta 		tc_size[i] = roundup_size;
699e2cb1decSSalil Mehta 		tc_offset[i] = rss_size * i;
700e2cb1decSSalil Mehta 	}
701e2cb1decSSalil Mehta 
702e2cb1decSSalil Mehta 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_TC_MODE, false);
703e2cb1decSSalil Mehta 	for (i = 0; i < HCLGEVF_MAX_TC_NUM; i++) {
70455ff3ed5SJian Shen 		u16 mode = 0;
70555ff3ed5SJian Shen 
70655ff3ed5SJian Shen 		hnae3_set_bit(mode, HCLGEVF_RSS_TC_VALID_B,
707e2cb1decSSalil Mehta 			      (tc_valid[i] & 0x1));
70855ff3ed5SJian Shen 		hnae3_set_field(mode, HCLGEVF_RSS_TC_SIZE_M,
709e2cb1decSSalil Mehta 				HCLGEVF_RSS_TC_SIZE_S, tc_size[i]);
71055ff3ed5SJian Shen 		hnae3_set_field(mode, HCLGEVF_RSS_TC_OFFSET_M,
711e2cb1decSSalil Mehta 				HCLGEVF_RSS_TC_OFFSET_S, tc_offset[i]);
71255ff3ed5SJian Shen 
71355ff3ed5SJian Shen 		req->rss_tc_mode[i] = cpu_to_le16(mode);
714e2cb1decSSalil Mehta 	}
715e2cb1decSSalil Mehta 	status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
716e2cb1decSSalil Mehta 	if (status)
717e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
718e2cb1decSSalil Mehta 			"VF failed(=%d) to set rss tc mode\n", status);
719e2cb1decSSalil Mehta 
720e2cb1decSSalil Mehta 	return status;
721e2cb1decSSalil Mehta }
722e2cb1decSSalil Mehta 
723a638b1d8SJian Shen /* for revision 0x20, vf shared the same rss config with pf */
724a638b1d8SJian Shen static int hclgevf_get_rss_hash_key(struct hclgevf_dev *hdev)
725a638b1d8SJian Shen {
726a638b1d8SJian Shen #define HCLGEVF_RSS_MBX_RESP_LEN	8
727a638b1d8SJian Shen 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
728a638b1d8SJian Shen 	u8 resp_msg[HCLGEVF_RSS_MBX_RESP_LEN];
729d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
730a638b1d8SJian Shen 	u16 msg_num, hash_key_index;
731a638b1d8SJian Shen 	u8 index;
732a638b1d8SJian Shen 	int ret;
733a638b1d8SJian Shen 
734d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_RSS_KEY, 0);
735a638b1d8SJian Shen 	msg_num = (HCLGEVF_RSS_KEY_SIZE + HCLGEVF_RSS_MBX_RESP_LEN - 1) /
736a638b1d8SJian Shen 			HCLGEVF_RSS_MBX_RESP_LEN;
737a638b1d8SJian Shen 	for (index = 0; index < msg_num; index++) {
738d3410018SYufeng Mo 		send_msg.data[0] = index;
739d3410018SYufeng Mo 		ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
740a638b1d8SJian Shen 					   HCLGEVF_RSS_MBX_RESP_LEN);
741a638b1d8SJian Shen 		if (ret) {
742a638b1d8SJian Shen 			dev_err(&hdev->pdev->dev,
743a638b1d8SJian Shen 				"VF get rss hash key from PF failed, ret=%d",
744a638b1d8SJian Shen 				ret);
745a638b1d8SJian Shen 			return ret;
746a638b1d8SJian Shen 		}
747a638b1d8SJian Shen 
748a638b1d8SJian Shen 		hash_key_index = HCLGEVF_RSS_MBX_RESP_LEN * index;
749a638b1d8SJian Shen 		if (index == msg_num - 1)
750a638b1d8SJian Shen 			memcpy(&rss_cfg->rss_hash_key[hash_key_index],
751a638b1d8SJian Shen 			       &resp_msg[0],
752a638b1d8SJian Shen 			       HCLGEVF_RSS_KEY_SIZE - hash_key_index);
753a638b1d8SJian Shen 		else
754a638b1d8SJian Shen 			memcpy(&rss_cfg->rss_hash_key[hash_key_index],
755a638b1d8SJian Shen 			       &resp_msg[0], HCLGEVF_RSS_MBX_RESP_LEN);
756a638b1d8SJian Shen 	}
757a638b1d8SJian Shen 
758a638b1d8SJian Shen 	return 0;
759a638b1d8SJian Shen }
760a638b1d8SJian Shen 
761e2cb1decSSalil Mehta static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
762e2cb1decSSalil Mehta 			   u8 *hfunc)
763e2cb1decSSalil Mehta {
764e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
765e2cb1decSSalil Mehta 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
766a638b1d8SJian Shen 	int i, ret;
767e2cb1decSSalil Mehta 
768295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
769374ad291SJian Shen 		/* Get hash algorithm */
770374ad291SJian Shen 		if (hfunc) {
771374ad291SJian Shen 			switch (rss_cfg->hash_algo) {
772374ad291SJian Shen 			case HCLGEVF_RSS_HASH_ALGO_TOEPLITZ:
773374ad291SJian Shen 				*hfunc = ETH_RSS_HASH_TOP;
774374ad291SJian Shen 				break;
775374ad291SJian Shen 			case HCLGEVF_RSS_HASH_ALGO_SIMPLE:
776374ad291SJian Shen 				*hfunc = ETH_RSS_HASH_XOR;
777374ad291SJian Shen 				break;
778374ad291SJian Shen 			default:
779374ad291SJian Shen 				*hfunc = ETH_RSS_HASH_UNKNOWN;
780374ad291SJian Shen 				break;
781374ad291SJian Shen 			}
782374ad291SJian Shen 		}
783374ad291SJian Shen 
784374ad291SJian Shen 		/* Get the RSS Key required by the user */
785374ad291SJian Shen 		if (key)
786374ad291SJian Shen 			memcpy(key, rss_cfg->rss_hash_key,
787374ad291SJian Shen 			       HCLGEVF_RSS_KEY_SIZE);
788a638b1d8SJian Shen 	} else {
789a638b1d8SJian Shen 		if (hfunc)
790a638b1d8SJian Shen 			*hfunc = ETH_RSS_HASH_TOP;
791a638b1d8SJian Shen 		if (key) {
792a638b1d8SJian Shen 			ret = hclgevf_get_rss_hash_key(hdev);
793a638b1d8SJian Shen 			if (ret)
794a638b1d8SJian Shen 				return ret;
795a638b1d8SJian Shen 			memcpy(key, rss_cfg->rss_hash_key,
796a638b1d8SJian Shen 			       HCLGEVF_RSS_KEY_SIZE);
797a638b1d8SJian Shen 		}
798374ad291SJian Shen 	}
799374ad291SJian Shen 
800e2cb1decSSalil Mehta 	if (indir)
80187ce161eSGuangbin Huang 		for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++)
802e2cb1decSSalil Mehta 			indir[i] = rss_cfg->rss_indirection_tbl[i];
803e2cb1decSSalil Mehta 
804374ad291SJian Shen 	return 0;
805e2cb1decSSalil Mehta }
806e2cb1decSSalil Mehta 
807e2cb1decSSalil Mehta static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
808e2cb1decSSalil Mehta 			   const u8 *key, const u8 hfunc)
809e2cb1decSSalil Mehta {
810e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
811e2cb1decSSalil Mehta 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
812374ad291SJian Shen 	int ret, i;
813374ad291SJian Shen 
814295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
815374ad291SJian Shen 		/* Set the RSS Hash Key if specififed by the user */
816374ad291SJian Shen 		if (key) {
817374ad291SJian Shen 			switch (hfunc) {
818374ad291SJian Shen 			case ETH_RSS_HASH_TOP:
819374ad291SJian Shen 				rss_cfg->hash_algo =
820374ad291SJian Shen 					HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
821374ad291SJian Shen 				break;
822374ad291SJian Shen 			case ETH_RSS_HASH_XOR:
823374ad291SJian Shen 				rss_cfg->hash_algo =
824374ad291SJian Shen 					HCLGEVF_RSS_HASH_ALGO_SIMPLE;
825374ad291SJian Shen 				break;
826374ad291SJian Shen 			case ETH_RSS_HASH_NO_CHANGE:
827374ad291SJian Shen 				break;
828374ad291SJian Shen 			default:
829374ad291SJian Shen 				return -EINVAL;
830374ad291SJian Shen 			}
831374ad291SJian Shen 
832374ad291SJian Shen 			ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
833374ad291SJian Shen 						       key);
834374ad291SJian Shen 			if (ret)
835374ad291SJian Shen 				return ret;
836374ad291SJian Shen 
837374ad291SJian Shen 			/* Update the shadow RSS key with user specified qids */
838374ad291SJian Shen 			memcpy(rss_cfg->rss_hash_key, key,
839374ad291SJian Shen 			       HCLGEVF_RSS_KEY_SIZE);
840374ad291SJian Shen 		}
841374ad291SJian Shen 	}
842e2cb1decSSalil Mehta 
843e2cb1decSSalil Mehta 	/* update the shadow RSS table with user specified qids */
84487ce161eSGuangbin Huang 	for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++)
845e2cb1decSSalil Mehta 		rss_cfg->rss_indirection_tbl[i] = indir[i];
846e2cb1decSSalil Mehta 
847e2cb1decSSalil Mehta 	/* update the hardware */
848e2cb1decSSalil Mehta 	return hclgevf_set_rss_indir_table(hdev);
849e2cb1decSSalil Mehta }
850e2cb1decSSalil Mehta 
851d97b3072SJian Shen static u8 hclgevf_get_rss_hash_bits(struct ethtool_rxnfc *nfc)
852d97b3072SJian Shen {
853d97b3072SJian Shen 	u8 hash_sets = nfc->data & RXH_L4_B_0_1 ? HCLGEVF_S_PORT_BIT : 0;
854d97b3072SJian Shen 
855d97b3072SJian Shen 	if (nfc->data & RXH_L4_B_2_3)
856d97b3072SJian Shen 		hash_sets |= HCLGEVF_D_PORT_BIT;
857d97b3072SJian Shen 	else
858d97b3072SJian Shen 		hash_sets &= ~HCLGEVF_D_PORT_BIT;
859d97b3072SJian Shen 
860d97b3072SJian Shen 	if (nfc->data & RXH_IP_SRC)
861d97b3072SJian Shen 		hash_sets |= HCLGEVF_S_IP_BIT;
862d97b3072SJian Shen 	else
863d97b3072SJian Shen 		hash_sets &= ~HCLGEVF_S_IP_BIT;
864d97b3072SJian Shen 
865d97b3072SJian Shen 	if (nfc->data & RXH_IP_DST)
866d97b3072SJian Shen 		hash_sets |= HCLGEVF_D_IP_BIT;
867d97b3072SJian Shen 	else
868d97b3072SJian Shen 		hash_sets &= ~HCLGEVF_D_IP_BIT;
869d97b3072SJian Shen 
870d97b3072SJian Shen 	if (nfc->flow_type == SCTP_V4_FLOW || nfc->flow_type == SCTP_V6_FLOW)
871d97b3072SJian Shen 		hash_sets |= HCLGEVF_V_TAG_BIT;
872d97b3072SJian Shen 
873d97b3072SJian Shen 	return hash_sets;
874d97b3072SJian Shen }
875d97b3072SJian Shen 
876*5fd0e7b4SHuazhong Tan static int hclgevf_init_rss_tuple_cmd(struct hnae3_handle *handle,
877*5fd0e7b4SHuazhong Tan 				      struct ethtool_rxnfc *nfc,
878*5fd0e7b4SHuazhong Tan 				      struct hclgevf_rss_input_tuple_cmd *req)
879d97b3072SJian Shen {
880d97b3072SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
881d97b3072SJian Shen 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
882d97b3072SJian Shen 	u8 tuple_sets;
883d97b3072SJian Shen 
884d97b3072SJian Shen 	req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
885d97b3072SJian Shen 	req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
886d97b3072SJian Shen 	req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
887d97b3072SJian Shen 	req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
888d97b3072SJian Shen 	req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
889d97b3072SJian Shen 	req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
890d97b3072SJian Shen 	req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
891d97b3072SJian Shen 	req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
892d97b3072SJian Shen 
893d97b3072SJian Shen 	tuple_sets = hclgevf_get_rss_hash_bits(nfc);
894d97b3072SJian Shen 	switch (nfc->flow_type) {
895d97b3072SJian Shen 	case TCP_V4_FLOW:
896d97b3072SJian Shen 		req->ipv4_tcp_en = tuple_sets;
897d97b3072SJian Shen 		break;
898d97b3072SJian Shen 	case TCP_V6_FLOW:
899d97b3072SJian Shen 		req->ipv6_tcp_en = tuple_sets;
900d97b3072SJian Shen 		break;
901d97b3072SJian Shen 	case UDP_V4_FLOW:
902d97b3072SJian Shen 		req->ipv4_udp_en = tuple_sets;
903d97b3072SJian Shen 		break;
904d97b3072SJian Shen 	case UDP_V6_FLOW:
905d97b3072SJian Shen 		req->ipv6_udp_en = tuple_sets;
906d97b3072SJian Shen 		break;
907d97b3072SJian Shen 	case SCTP_V4_FLOW:
908d97b3072SJian Shen 		req->ipv4_sctp_en = tuple_sets;
909d97b3072SJian Shen 		break;
910d97b3072SJian Shen 	case SCTP_V6_FLOW:
911ab6e32d2SJian Shen 		if (hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 &&
912ab6e32d2SJian Shen 		    (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)))
913d97b3072SJian Shen 			return -EINVAL;
914d97b3072SJian Shen 
915d97b3072SJian Shen 		req->ipv6_sctp_en = tuple_sets;
916d97b3072SJian Shen 		break;
917d97b3072SJian Shen 	case IPV4_FLOW:
918d97b3072SJian Shen 		req->ipv4_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
919d97b3072SJian Shen 		break;
920d97b3072SJian Shen 	case IPV6_FLOW:
921d97b3072SJian Shen 		req->ipv6_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
922d97b3072SJian Shen 		break;
923d97b3072SJian Shen 	default:
924d97b3072SJian Shen 		return -EINVAL;
925d97b3072SJian Shen 	}
926d97b3072SJian Shen 
927*5fd0e7b4SHuazhong Tan 	return 0;
928*5fd0e7b4SHuazhong Tan }
929*5fd0e7b4SHuazhong Tan 
930*5fd0e7b4SHuazhong Tan static int hclgevf_set_rss_tuple(struct hnae3_handle *handle,
931*5fd0e7b4SHuazhong Tan 				 struct ethtool_rxnfc *nfc)
932*5fd0e7b4SHuazhong Tan {
933*5fd0e7b4SHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
934*5fd0e7b4SHuazhong Tan 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
935*5fd0e7b4SHuazhong Tan 	struct hclgevf_rss_input_tuple_cmd *req;
936*5fd0e7b4SHuazhong Tan 	struct hclgevf_desc desc;
937*5fd0e7b4SHuazhong Tan 	int ret;
938*5fd0e7b4SHuazhong Tan 
939*5fd0e7b4SHuazhong Tan 	if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
940*5fd0e7b4SHuazhong Tan 		return -EOPNOTSUPP;
941*5fd0e7b4SHuazhong Tan 
942*5fd0e7b4SHuazhong Tan 	if (nfc->data &
943*5fd0e7b4SHuazhong Tan 	    ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3))
944*5fd0e7b4SHuazhong Tan 		return -EINVAL;
945*5fd0e7b4SHuazhong Tan 
946*5fd0e7b4SHuazhong Tan 	req = (struct hclgevf_rss_input_tuple_cmd *)desc.data;
947*5fd0e7b4SHuazhong Tan 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false);
948*5fd0e7b4SHuazhong Tan 
949*5fd0e7b4SHuazhong Tan 	ret = hclgevf_init_rss_tuple_cmd(handle, nfc, req);
950*5fd0e7b4SHuazhong Tan 	if (ret) {
951*5fd0e7b4SHuazhong Tan 		dev_err(&hdev->pdev->dev,
952*5fd0e7b4SHuazhong Tan 			"failed to init rss tuple cmd, ret = %d\n", ret);
953*5fd0e7b4SHuazhong Tan 		return ret;
954*5fd0e7b4SHuazhong Tan 	}
955*5fd0e7b4SHuazhong Tan 
956d97b3072SJian Shen 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
957d97b3072SJian Shen 	if (ret) {
958d97b3072SJian Shen 		dev_err(&hdev->pdev->dev,
959d97b3072SJian Shen 			"Set rss tuple fail, status = %d\n", ret);
960d97b3072SJian Shen 		return ret;
961d97b3072SJian Shen 	}
962d97b3072SJian Shen 
963d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_tcp_en = req->ipv4_tcp_en;
964d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_udp_en = req->ipv4_udp_en;
965d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_sctp_en = req->ipv4_sctp_en;
966d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_fragment_en = req->ipv4_fragment_en;
967d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_tcp_en = req->ipv6_tcp_en;
968d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_udp_en = req->ipv6_udp_en;
969d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_sctp_en = req->ipv6_sctp_en;
970d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_fragment_en = req->ipv6_fragment_en;
971d97b3072SJian Shen 	return 0;
972d97b3072SJian Shen }
973d97b3072SJian Shen 
97473f7767eSJian Shen static int hclgevf_get_rss_tuple_by_flow_type(struct hclgevf_dev *hdev,
97573f7767eSJian Shen 					      int flow_type, u8 *tuple_sets)
97673f7767eSJian Shen {
97773f7767eSJian Shen 	switch (flow_type) {
97873f7767eSJian Shen 	case TCP_V4_FLOW:
97973f7767eSJian Shen 		*tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv4_tcp_en;
98073f7767eSJian Shen 		break;
98173f7767eSJian Shen 	case UDP_V4_FLOW:
98273f7767eSJian Shen 		*tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv4_udp_en;
98373f7767eSJian Shen 		break;
98473f7767eSJian Shen 	case TCP_V6_FLOW:
98573f7767eSJian Shen 		*tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv6_tcp_en;
98673f7767eSJian Shen 		break;
98773f7767eSJian Shen 	case UDP_V6_FLOW:
98873f7767eSJian Shen 		*tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv6_udp_en;
98973f7767eSJian Shen 		break;
99073f7767eSJian Shen 	case SCTP_V4_FLOW:
99173f7767eSJian Shen 		*tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv4_sctp_en;
99273f7767eSJian Shen 		break;
99373f7767eSJian Shen 	case SCTP_V6_FLOW:
99473f7767eSJian Shen 		*tuple_sets = hdev->rss_cfg.rss_tuple_sets.ipv6_sctp_en;
99573f7767eSJian Shen 		break;
99673f7767eSJian Shen 	case IPV4_FLOW:
99773f7767eSJian Shen 	case IPV6_FLOW:
99873f7767eSJian Shen 		*tuple_sets = HCLGEVF_S_IP_BIT | HCLGEVF_D_IP_BIT;
99973f7767eSJian Shen 		break;
100073f7767eSJian Shen 	default:
100173f7767eSJian Shen 		return -EINVAL;
100273f7767eSJian Shen 	}
100373f7767eSJian Shen 
100473f7767eSJian Shen 	return 0;
100573f7767eSJian Shen }
100673f7767eSJian Shen 
100773f7767eSJian Shen static u64 hclgevf_convert_rss_tuple(u8 tuple_sets)
100873f7767eSJian Shen {
100973f7767eSJian Shen 	u64 tuple_data = 0;
101073f7767eSJian Shen 
101173f7767eSJian Shen 	if (tuple_sets & HCLGEVF_D_PORT_BIT)
101273f7767eSJian Shen 		tuple_data |= RXH_L4_B_2_3;
101373f7767eSJian Shen 	if (tuple_sets & HCLGEVF_S_PORT_BIT)
101473f7767eSJian Shen 		tuple_data |= RXH_L4_B_0_1;
101573f7767eSJian Shen 	if (tuple_sets & HCLGEVF_D_IP_BIT)
101673f7767eSJian Shen 		tuple_data |= RXH_IP_DST;
101773f7767eSJian Shen 	if (tuple_sets & HCLGEVF_S_IP_BIT)
101873f7767eSJian Shen 		tuple_data |= RXH_IP_SRC;
101973f7767eSJian Shen 
102073f7767eSJian Shen 	return tuple_data;
102173f7767eSJian Shen }
102273f7767eSJian Shen 
1023d97b3072SJian Shen static int hclgevf_get_rss_tuple(struct hnae3_handle *handle,
1024d97b3072SJian Shen 				 struct ethtool_rxnfc *nfc)
1025d97b3072SJian Shen {
1026d97b3072SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1027d97b3072SJian Shen 	u8 tuple_sets;
102873f7767eSJian Shen 	int ret;
1029d97b3072SJian Shen 
1030295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
1031d97b3072SJian Shen 		return -EOPNOTSUPP;
1032d97b3072SJian Shen 
1033d97b3072SJian Shen 	nfc->data = 0;
1034d97b3072SJian Shen 
103573f7767eSJian Shen 	ret = hclgevf_get_rss_tuple_by_flow_type(hdev, nfc->flow_type,
103673f7767eSJian Shen 						 &tuple_sets);
103773f7767eSJian Shen 	if (ret || !tuple_sets)
103873f7767eSJian Shen 		return ret;
1039d97b3072SJian Shen 
104073f7767eSJian Shen 	nfc->data = hclgevf_convert_rss_tuple(tuple_sets);
1041d97b3072SJian Shen 
1042d97b3072SJian Shen 	return 0;
1043d97b3072SJian Shen }
1044d97b3072SJian Shen 
1045d97b3072SJian Shen static int hclgevf_set_rss_input_tuple(struct hclgevf_dev *hdev,
1046d97b3072SJian Shen 				       struct hclgevf_rss_cfg *rss_cfg)
1047d97b3072SJian Shen {
1048d97b3072SJian Shen 	struct hclgevf_rss_input_tuple_cmd *req;
1049d97b3072SJian Shen 	struct hclgevf_desc desc;
1050d97b3072SJian Shen 	int ret;
1051d97b3072SJian Shen 
1052d97b3072SJian Shen 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false);
1053d97b3072SJian Shen 
1054d97b3072SJian Shen 	req = (struct hclgevf_rss_input_tuple_cmd *)desc.data;
1055d97b3072SJian Shen 
1056d97b3072SJian Shen 	req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
1057d97b3072SJian Shen 	req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
1058d97b3072SJian Shen 	req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
1059d97b3072SJian Shen 	req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
1060d97b3072SJian Shen 	req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
1061d97b3072SJian Shen 	req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
1062d97b3072SJian Shen 	req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
1063d97b3072SJian Shen 	req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
1064d97b3072SJian Shen 
1065d97b3072SJian Shen 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
1066d97b3072SJian Shen 	if (ret)
1067d97b3072SJian Shen 		dev_err(&hdev->pdev->dev,
1068d97b3072SJian Shen 			"Configure rss input fail, status = %d\n", ret);
1069d97b3072SJian Shen 	return ret;
1070d97b3072SJian Shen }
1071d97b3072SJian Shen 
1072e2cb1decSSalil Mehta static int hclgevf_get_tc_size(struct hnae3_handle *handle)
1073e2cb1decSSalil Mehta {
1074e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1075e2cb1decSSalil Mehta 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
1076e2cb1decSSalil Mehta 
1077e2cb1decSSalil Mehta 	return rss_cfg->rss_size;
1078e2cb1decSSalil Mehta }
1079e2cb1decSSalil Mehta 
1080e2cb1decSSalil Mehta static int hclgevf_bind_ring_to_vector(struct hnae3_handle *handle, bool en,
1081b204bc74SPeng Li 				       int vector_id,
1082e2cb1decSSalil Mehta 				       struct hnae3_ring_chain_node *ring_chain)
1083e2cb1decSSalil Mehta {
1084e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1085d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1086e2cb1decSSalil Mehta 	struct hnae3_ring_chain_node *node;
1087e2cb1decSSalil Mehta 	int status;
1088d3410018SYufeng Mo 	int i = 0;
1089e2cb1decSSalil Mehta 
1090d3410018SYufeng Mo 	memset(&send_msg, 0, sizeof(send_msg));
1091d3410018SYufeng Mo 	send_msg.code = en ? HCLGE_MBX_MAP_RING_TO_VECTOR :
1092c09ba484SPeng Li 		HCLGE_MBX_UNMAP_RING_TO_VECTOR;
1093d3410018SYufeng Mo 	send_msg.vector_id = vector_id;
1094e2cb1decSSalil Mehta 
1095e2cb1decSSalil Mehta 	for (node = ring_chain; node; node = node->next) {
1096d3410018SYufeng Mo 		send_msg.param[i].ring_type =
1097e4e87715SPeng Li 				hnae3_get_bit(node->flag, HNAE3_RING_TYPE_B);
1098d3410018SYufeng Mo 
1099d3410018SYufeng Mo 		send_msg.param[i].tqp_index = node->tqp_index;
1100d3410018SYufeng Mo 		send_msg.param[i].int_gl_index =
1101d3410018SYufeng Mo 					hnae3_get_field(node->int_gl_idx,
110279eee410SFuyun Liang 							HNAE3_RING_GL_IDX_M,
110379eee410SFuyun Liang 							HNAE3_RING_GL_IDX_S);
110479eee410SFuyun Liang 
11055d02a58dSYunsheng Lin 		i++;
1106d3410018SYufeng Mo 		if (i == HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM || !node->next) {
1107d3410018SYufeng Mo 			send_msg.ring_num = i;
1108e2cb1decSSalil Mehta 
1109d3410018SYufeng Mo 			status = hclgevf_send_mbx_msg(hdev, &send_msg, false,
1110d3410018SYufeng Mo 						      NULL, 0);
1111e2cb1decSSalil Mehta 			if (status) {
1112e2cb1decSSalil Mehta 				dev_err(&hdev->pdev->dev,
1113e2cb1decSSalil Mehta 					"Map TQP fail, status is %d.\n",
1114e2cb1decSSalil Mehta 					status);
1115e2cb1decSSalil Mehta 				return status;
1116e2cb1decSSalil Mehta 			}
1117e2cb1decSSalil Mehta 			i = 0;
1118e2cb1decSSalil Mehta 		}
1119e2cb1decSSalil Mehta 	}
1120e2cb1decSSalil Mehta 
1121e2cb1decSSalil Mehta 	return 0;
1122e2cb1decSSalil Mehta }
1123e2cb1decSSalil Mehta 
1124e2cb1decSSalil Mehta static int hclgevf_map_ring_to_vector(struct hnae3_handle *handle, int vector,
1125e2cb1decSSalil Mehta 				      struct hnae3_ring_chain_node *ring_chain)
1126e2cb1decSSalil Mehta {
1127b204bc74SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1128b204bc74SPeng Li 	int vector_id;
1129b204bc74SPeng Li 
1130b204bc74SPeng Li 	vector_id = hclgevf_get_vector_index(hdev, vector);
1131b204bc74SPeng Li 	if (vector_id < 0) {
1132b204bc74SPeng Li 		dev_err(&handle->pdev->dev,
1133b204bc74SPeng Li 			"Get vector index fail. ret =%d\n", vector_id);
1134b204bc74SPeng Li 		return vector_id;
1135b204bc74SPeng Li 	}
1136b204bc74SPeng Li 
1137b204bc74SPeng Li 	return hclgevf_bind_ring_to_vector(handle, true, vector_id, ring_chain);
1138e2cb1decSSalil Mehta }
1139e2cb1decSSalil Mehta 
1140e2cb1decSSalil Mehta static int hclgevf_unmap_ring_from_vector(
1141e2cb1decSSalil Mehta 				struct hnae3_handle *handle,
1142e2cb1decSSalil Mehta 				int vector,
1143e2cb1decSSalil Mehta 				struct hnae3_ring_chain_node *ring_chain)
1144e2cb1decSSalil Mehta {
1145e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1146e2cb1decSSalil Mehta 	int ret, vector_id;
1147e2cb1decSSalil Mehta 
1148dea846e8SHuazhong Tan 	if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
1149dea846e8SHuazhong Tan 		return 0;
1150dea846e8SHuazhong Tan 
1151e2cb1decSSalil Mehta 	vector_id = hclgevf_get_vector_index(hdev, vector);
1152e2cb1decSSalil Mehta 	if (vector_id < 0) {
1153e2cb1decSSalil Mehta 		dev_err(&handle->pdev->dev,
1154e2cb1decSSalil Mehta 			"Get vector index fail. ret =%d\n", vector_id);
1155e2cb1decSSalil Mehta 		return vector_id;
1156e2cb1decSSalil Mehta 	}
1157e2cb1decSSalil Mehta 
1158b204bc74SPeng Li 	ret = hclgevf_bind_ring_to_vector(handle, false, vector_id, ring_chain);
11590d3e6631SYunsheng Lin 	if (ret)
1160e2cb1decSSalil Mehta 		dev_err(&handle->pdev->dev,
1161e2cb1decSSalil Mehta 			"Unmap ring from vector fail. vector=%d, ret =%d\n",
1162e2cb1decSSalil Mehta 			vector_id,
1163e2cb1decSSalil Mehta 			ret);
11640d3e6631SYunsheng Lin 
1165e2cb1decSSalil Mehta 	return ret;
1166e2cb1decSSalil Mehta }
1167e2cb1decSSalil Mehta 
11680d3e6631SYunsheng Lin static int hclgevf_put_vector(struct hnae3_handle *handle, int vector)
11690d3e6631SYunsheng Lin {
11700d3e6631SYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
117103718db9SYunsheng Lin 	int vector_id;
11720d3e6631SYunsheng Lin 
117303718db9SYunsheng Lin 	vector_id = hclgevf_get_vector_index(hdev, vector);
117403718db9SYunsheng Lin 	if (vector_id < 0) {
117503718db9SYunsheng Lin 		dev_err(&handle->pdev->dev,
117603718db9SYunsheng Lin 			"hclgevf_put_vector get vector index fail. ret =%d\n",
117703718db9SYunsheng Lin 			vector_id);
117803718db9SYunsheng Lin 		return vector_id;
117903718db9SYunsheng Lin 	}
118003718db9SYunsheng Lin 
118103718db9SYunsheng Lin 	hclgevf_free_vector(hdev, vector_id);
1182e2cb1decSSalil Mehta 
1183e2cb1decSSalil Mehta 	return 0;
1184e2cb1decSSalil Mehta }
1185e2cb1decSSalil Mehta 
11863b75c3dfSPeng Li static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev,
1187e196ec75SJian Shen 					bool en_uc_pmc, bool en_mc_pmc,
1188f01f5559SJian Shen 					bool en_bc_pmc)
1189e2cb1decSSalil Mehta {
11905e7414cdSJian Shen 	struct hnae3_handle *handle = &hdev->nic;
1191d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1192f01f5559SJian Shen 	int ret;
1193e2cb1decSSalil Mehta 
1194d3410018SYufeng Mo 	memset(&send_msg, 0, sizeof(send_msg));
1195d3410018SYufeng Mo 	send_msg.code = HCLGE_MBX_SET_PROMISC_MODE;
1196d3410018SYufeng Mo 	send_msg.en_bc = en_bc_pmc ? 1 : 0;
1197d3410018SYufeng Mo 	send_msg.en_uc = en_uc_pmc ? 1 : 0;
1198d3410018SYufeng Mo 	send_msg.en_mc = en_mc_pmc ? 1 : 0;
11995e7414cdSJian Shen 	send_msg.en_limit_promisc = test_bit(HNAE3_PFLAG_LIMIT_PROMISC,
12005e7414cdSJian Shen 					     &handle->priv_flags) ? 1 : 0;
1201e2cb1decSSalil Mehta 
1202d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1203f01f5559SJian Shen 	if (ret)
1204e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
1205f01f5559SJian Shen 			"Set promisc mode fail, status is %d.\n", ret);
1206e2cb1decSSalil Mehta 
1207f01f5559SJian Shen 	return ret;
1208e2cb1decSSalil Mehta }
1209e2cb1decSSalil Mehta 
1210e196ec75SJian Shen static int hclgevf_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
1211e196ec75SJian Shen 				    bool en_mc_pmc)
1212e2cb1decSSalil Mehta {
1213e196ec75SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1214e196ec75SJian Shen 	bool en_bc_pmc;
1215e196ec75SJian Shen 
1216295ba232SGuangbin Huang 	en_bc_pmc = hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2;
1217e196ec75SJian Shen 
1218e196ec75SJian Shen 	return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc,
1219e196ec75SJian Shen 					    en_bc_pmc);
1220e2cb1decSSalil Mehta }
1221e2cb1decSSalil Mehta 
1222c631c696SJian Shen static void hclgevf_request_update_promisc_mode(struct hnae3_handle *handle)
1223c631c696SJian Shen {
1224c631c696SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1225c631c696SJian Shen 
1226c631c696SJian Shen 	set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
12275e7414cdSJian Shen 	hclgevf_task_schedule(hdev, 0);
1228c631c696SJian Shen }
1229c631c696SJian Shen 
1230c631c696SJian Shen static void hclgevf_sync_promisc_mode(struct hclgevf_dev *hdev)
1231c631c696SJian Shen {
1232c631c696SJian Shen 	struct hnae3_handle *handle = &hdev->nic;
1233c631c696SJian Shen 	bool en_uc_pmc = handle->netdev_flags & HNAE3_UPE;
1234c631c696SJian Shen 	bool en_mc_pmc = handle->netdev_flags & HNAE3_MPE;
1235c631c696SJian Shen 	int ret;
1236c631c696SJian Shen 
1237c631c696SJian Shen 	if (test_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state)) {
1238c631c696SJian Shen 		ret = hclgevf_set_promisc_mode(handle, en_uc_pmc, en_mc_pmc);
1239c631c696SJian Shen 		if (!ret)
1240c631c696SJian Shen 			clear_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
1241c631c696SJian Shen 	}
1242c631c696SJian Shen }
1243c631c696SJian Shen 
1244ebaf1908SWeihang Li static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, unsigned int tqp_id,
1245e2cb1decSSalil Mehta 			      int stream_id, bool enable)
1246e2cb1decSSalil Mehta {
1247e2cb1decSSalil Mehta 	struct hclgevf_cfg_com_tqp_queue_cmd *req;
1248e2cb1decSSalil Mehta 	struct hclgevf_desc desc;
1249e2cb1decSSalil Mehta 	int status;
1250e2cb1decSSalil Mehta 
1251e2cb1decSSalil Mehta 	req = (struct hclgevf_cfg_com_tqp_queue_cmd *)desc.data;
1252e2cb1decSSalil Mehta 
1253e2cb1decSSalil Mehta 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_CFG_COM_TQP_QUEUE,
1254e2cb1decSSalil Mehta 				     false);
1255e2cb1decSSalil Mehta 	req->tqp_id = cpu_to_le16(tqp_id & HCLGEVF_RING_ID_MASK);
1256e2cb1decSSalil Mehta 	req->stream_id = cpu_to_le16(stream_id);
1257ebaf1908SWeihang Li 	if (enable)
1258ebaf1908SWeihang Li 		req->enable |= 1U << HCLGEVF_TQP_ENABLE_B;
1259e2cb1decSSalil Mehta 
1260e2cb1decSSalil Mehta 	status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
1261e2cb1decSSalil Mehta 	if (status)
1262e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
1263e2cb1decSSalil Mehta 			"TQP enable fail, status =%d.\n", status);
1264e2cb1decSSalil Mehta 
1265e2cb1decSSalil Mehta 	return status;
1266e2cb1decSSalil Mehta }
1267e2cb1decSSalil Mehta 
1268e2cb1decSSalil Mehta static void hclgevf_reset_tqp_stats(struct hnae3_handle *handle)
1269e2cb1decSSalil Mehta {
1270b4f1d303SJian Shen 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
1271e2cb1decSSalil Mehta 	struct hclgevf_tqp *tqp;
1272e2cb1decSSalil Mehta 	int i;
1273e2cb1decSSalil Mehta 
1274b4f1d303SJian Shen 	for (i = 0; i < kinfo->num_tqps; i++) {
1275b4f1d303SJian Shen 		tqp = container_of(kinfo->tqp[i], struct hclgevf_tqp, q);
1276e2cb1decSSalil Mehta 		memset(&tqp->tqp_stats, 0, sizeof(tqp->tqp_stats));
1277e2cb1decSSalil Mehta 	}
1278e2cb1decSSalil Mehta }
1279e2cb1decSSalil Mehta 
12808e6de441SHuazhong Tan static int hclgevf_get_host_mac_addr(struct hclgevf_dev *hdev, u8 *p)
12818e6de441SHuazhong Tan {
1282d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
12838e6de441SHuazhong Tan 	u8 host_mac[ETH_ALEN];
12848e6de441SHuazhong Tan 	int status;
12858e6de441SHuazhong Tan 
1286d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_MAC_ADDR, 0);
1287d3410018SYufeng Mo 	status = hclgevf_send_mbx_msg(hdev, &send_msg, true, host_mac,
1288d3410018SYufeng Mo 				      ETH_ALEN);
12898e6de441SHuazhong Tan 	if (status) {
12908e6de441SHuazhong Tan 		dev_err(&hdev->pdev->dev,
12918e6de441SHuazhong Tan 			"fail to get VF MAC from host %d", status);
12928e6de441SHuazhong Tan 		return status;
12938e6de441SHuazhong Tan 	}
12948e6de441SHuazhong Tan 
12958e6de441SHuazhong Tan 	ether_addr_copy(p, host_mac);
12968e6de441SHuazhong Tan 
12978e6de441SHuazhong Tan 	return 0;
12988e6de441SHuazhong Tan }
12998e6de441SHuazhong Tan 
1300e2cb1decSSalil Mehta static void hclgevf_get_mac_addr(struct hnae3_handle *handle, u8 *p)
1301e2cb1decSSalil Mehta {
1302e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
13038e6de441SHuazhong Tan 	u8 host_mac_addr[ETH_ALEN];
1304e2cb1decSSalil Mehta 
13058e6de441SHuazhong Tan 	if (hclgevf_get_host_mac_addr(hdev, host_mac_addr))
13068e6de441SHuazhong Tan 		return;
13078e6de441SHuazhong Tan 
13088e6de441SHuazhong Tan 	hdev->has_pf_mac = !is_zero_ether_addr(host_mac_addr);
13098e6de441SHuazhong Tan 	if (hdev->has_pf_mac)
13108e6de441SHuazhong Tan 		ether_addr_copy(p, host_mac_addr);
13118e6de441SHuazhong Tan 	else
1312e2cb1decSSalil Mehta 		ether_addr_copy(p, hdev->hw.mac.mac_addr);
1313e2cb1decSSalil Mehta }
1314e2cb1decSSalil Mehta 
131559098055SFuyun Liang static int hclgevf_set_mac_addr(struct hnae3_handle *handle, void *p,
131659098055SFuyun Liang 				bool is_first)
1317e2cb1decSSalil Mehta {
1318e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1319e2cb1decSSalil Mehta 	u8 *old_mac_addr = (u8 *)hdev->hw.mac.mac_addr;
1320d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1321e2cb1decSSalil Mehta 	u8 *new_mac_addr = (u8 *)p;
1322e2cb1decSSalil Mehta 	int status;
1323e2cb1decSSalil Mehta 
1324d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_UNICAST, 0);
1325ee4bcd3bSJian Shen 	send_msg.subcode = HCLGE_MBX_MAC_VLAN_UC_MODIFY;
1326d3410018SYufeng Mo 	ether_addr_copy(send_msg.data, new_mac_addr);
1327ee4bcd3bSJian Shen 	if (is_first && !hdev->has_pf_mac)
1328ee4bcd3bSJian Shen 		eth_zero_addr(&send_msg.data[ETH_ALEN]);
1329ee4bcd3bSJian Shen 	else
1330d3410018SYufeng Mo 		ether_addr_copy(&send_msg.data[ETH_ALEN], old_mac_addr);
1331d3410018SYufeng Mo 	status = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1332e2cb1decSSalil Mehta 	if (!status)
1333e2cb1decSSalil Mehta 		ether_addr_copy(hdev->hw.mac.mac_addr, new_mac_addr);
1334e2cb1decSSalil Mehta 
1335e2cb1decSSalil Mehta 	return status;
1336e2cb1decSSalil Mehta }
1337e2cb1decSSalil Mehta 
1338ee4bcd3bSJian Shen static struct hclgevf_mac_addr_node *
1339ee4bcd3bSJian Shen hclgevf_find_mac_node(struct list_head *list, const u8 *mac_addr)
1340ee4bcd3bSJian Shen {
1341ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp;
1342ee4bcd3bSJian Shen 
1343ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node)
1344ee4bcd3bSJian Shen 		if (ether_addr_equal(mac_addr, mac_node->mac_addr))
1345ee4bcd3bSJian Shen 			return mac_node;
1346ee4bcd3bSJian Shen 
1347ee4bcd3bSJian Shen 	return NULL;
1348ee4bcd3bSJian Shen }
1349ee4bcd3bSJian Shen 
1350ee4bcd3bSJian Shen static void hclgevf_update_mac_node(struct hclgevf_mac_addr_node *mac_node,
1351ee4bcd3bSJian Shen 				    enum HCLGEVF_MAC_NODE_STATE state)
1352ee4bcd3bSJian Shen {
1353ee4bcd3bSJian Shen 	switch (state) {
1354ee4bcd3bSJian Shen 	/* from set_rx_mode or tmp_add_list */
1355ee4bcd3bSJian Shen 	case HCLGEVF_MAC_TO_ADD:
1356ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_DEL)
1357ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_ACTIVE;
1358ee4bcd3bSJian Shen 		break;
1359ee4bcd3bSJian Shen 	/* only from set_rx_mode */
1360ee4bcd3bSJian Shen 	case HCLGEVF_MAC_TO_DEL:
1361ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD) {
1362ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1363ee4bcd3bSJian Shen 			kfree(mac_node);
1364ee4bcd3bSJian Shen 		} else {
1365ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_TO_DEL;
1366ee4bcd3bSJian Shen 		}
1367ee4bcd3bSJian Shen 		break;
1368ee4bcd3bSJian Shen 	/* only from tmp_add_list, the mac_node->state won't be
1369ee4bcd3bSJian Shen 	 * HCLGEVF_MAC_ACTIVE
1370ee4bcd3bSJian Shen 	 */
1371ee4bcd3bSJian Shen 	case HCLGEVF_MAC_ACTIVE:
1372ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1373ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_ACTIVE;
1374ee4bcd3bSJian Shen 		break;
1375ee4bcd3bSJian Shen 	}
1376ee4bcd3bSJian Shen }
1377ee4bcd3bSJian Shen 
1378ee4bcd3bSJian Shen static int hclgevf_update_mac_list(struct hnae3_handle *handle,
1379ee4bcd3bSJian Shen 				   enum HCLGEVF_MAC_NODE_STATE state,
1380ee4bcd3bSJian Shen 				   enum HCLGEVF_MAC_ADDR_TYPE mac_type,
1381e2cb1decSSalil Mehta 				   const unsigned char *addr)
1382e2cb1decSSalil Mehta {
1383e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1384ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node;
1385ee4bcd3bSJian Shen 	struct list_head *list;
1386e2cb1decSSalil Mehta 
1387ee4bcd3bSJian Shen 	list = (mac_type == HCLGEVF_MAC_ADDR_UC) ?
1388ee4bcd3bSJian Shen 	       &hdev->mac_table.uc_mac_list : &hdev->mac_table.mc_mac_list;
1389ee4bcd3bSJian Shen 
1390ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1391ee4bcd3bSJian Shen 
1392ee4bcd3bSJian Shen 	/* if the mac addr is already in the mac list, no need to add a new
1393ee4bcd3bSJian Shen 	 * one into it, just check the mac addr state, convert it to a new
1394ee4bcd3bSJian Shen 	 * new state, or just remove it, or do nothing.
1395ee4bcd3bSJian Shen 	 */
1396ee4bcd3bSJian Shen 	mac_node = hclgevf_find_mac_node(list, addr);
1397ee4bcd3bSJian Shen 	if (mac_node) {
1398ee4bcd3bSJian Shen 		hclgevf_update_mac_node(mac_node, state);
1399ee4bcd3bSJian Shen 		spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1400ee4bcd3bSJian Shen 		return 0;
1401ee4bcd3bSJian Shen 	}
1402ee4bcd3bSJian Shen 	/* if this address is never added, unnecessary to delete */
1403ee4bcd3bSJian Shen 	if (state == HCLGEVF_MAC_TO_DEL) {
1404ee4bcd3bSJian Shen 		spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1405ee4bcd3bSJian Shen 		return -ENOENT;
1406ee4bcd3bSJian Shen 	}
1407ee4bcd3bSJian Shen 
1408ee4bcd3bSJian Shen 	mac_node = kzalloc(sizeof(*mac_node), GFP_ATOMIC);
1409ee4bcd3bSJian Shen 	if (!mac_node) {
1410ee4bcd3bSJian Shen 		spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1411ee4bcd3bSJian Shen 		return -ENOMEM;
1412ee4bcd3bSJian Shen 	}
1413ee4bcd3bSJian Shen 
1414ee4bcd3bSJian Shen 	mac_node->state = state;
1415ee4bcd3bSJian Shen 	ether_addr_copy(mac_node->mac_addr, addr);
1416ee4bcd3bSJian Shen 	list_add_tail(&mac_node->node, list);
1417ee4bcd3bSJian Shen 
1418ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1419ee4bcd3bSJian Shen 	return 0;
1420ee4bcd3bSJian Shen }
1421ee4bcd3bSJian Shen 
1422ee4bcd3bSJian Shen static int hclgevf_add_uc_addr(struct hnae3_handle *handle,
1423ee4bcd3bSJian Shen 			       const unsigned char *addr)
1424ee4bcd3bSJian Shen {
1425ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_ADD,
1426ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_UC, addr);
1427e2cb1decSSalil Mehta }
1428e2cb1decSSalil Mehta 
1429e2cb1decSSalil Mehta static int hclgevf_rm_uc_addr(struct hnae3_handle *handle,
1430e2cb1decSSalil Mehta 			      const unsigned char *addr)
1431e2cb1decSSalil Mehta {
1432ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_DEL,
1433ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_UC, addr);
1434e2cb1decSSalil Mehta }
1435e2cb1decSSalil Mehta 
1436e2cb1decSSalil Mehta static int hclgevf_add_mc_addr(struct hnae3_handle *handle,
1437e2cb1decSSalil Mehta 			       const unsigned char *addr)
1438e2cb1decSSalil Mehta {
1439ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_ADD,
1440ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_MC, addr);
1441e2cb1decSSalil Mehta }
1442e2cb1decSSalil Mehta 
1443e2cb1decSSalil Mehta static int hclgevf_rm_mc_addr(struct hnae3_handle *handle,
1444e2cb1decSSalil Mehta 			      const unsigned char *addr)
1445e2cb1decSSalil Mehta {
1446ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_DEL,
1447ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_MC, addr);
1448ee4bcd3bSJian Shen }
1449e2cb1decSSalil Mehta 
1450ee4bcd3bSJian Shen static int hclgevf_add_del_mac_addr(struct hclgevf_dev *hdev,
1451ee4bcd3bSJian Shen 				    struct hclgevf_mac_addr_node *mac_node,
1452ee4bcd3bSJian Shen 				    enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1453ee4bcd3bSJian Shen {
1454ee4bcd3bSJian Shen 	struct hclge_vf_to_pf_msg send_msg;
1455ee4bcd3bSJian Shen 	u8 code, subcode;
1456ee4bcd3bSJian Shen 
1457ee4bcd3bSJian Shen 	if (mac_type == HCLGEVF_MAC_ADDR_UC) {
1458ee4bcd3bSJian Shen 		code = HCLGE_MBX_SET_UNICAST;
1459ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1460ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_UC_ADD;
1461ee4bcd3bSJian Shen 		else
1462ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_UC_REMOVE;
1463ee4bcd3bSJian Shen 	} else {
1464ee4bcd3bSJian Shen 		code = HCLGE_MBX_SET_MULTICAST;
1465ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1466ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_MC_ADD;
1467ee4bcd3bSJian Shen 		else
1468ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_MC_REMOVE;
1469ee4bcd3bSJian Shen 	}
1470ee4bcd3bSJian Shen 
1471ee4bcd3bSJian Shen 	hclgevf_build_send_msg(&send_msg, code, subcode);
1472ee4bcd3bSJian Shen 	ether_addr_copy(send_msg.data, mac_node->mac_addr);
1473d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1474e2cb1decSSalil Mehta }
1475e2cb1decSSalil Mehta 
1476ee4bcd3bSJian Shen static void hclgevf_config_mac_list(struct hclgevf_dev *hdev,
1477ee4bcd3bSJian Shen 				    struct list_head *list,
1478ee4bcd3bSJian Shen 				    enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1479ee4bcd3bSJian Shen {
1480ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp;
1481ee4bcd3bSJian Shen 	int ret;
1482ee4bcd3bSJian Shen 
1483ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node) {
1484ee4bcd3bSJian Shen 		ret = hclgevf_add_del_mac_addr(hdev, mac_node, mac_type);
1485ee4bcd3bSJian Shen 		if  (ret) {
1486ee4bcd3bSJian Shen 			dev_err(&hdev->pdev->dev,
1487ee4bcd3bSJian Shen 				"failed to configure mac %pM, state = %d, ret = %d\n",
1488ee4bcd3bSJian Shen 				mac_node->mac_addr, mac_node->state, ret);
1489ee4bcd3bSJian Shen 			return;
1490ee4bcd3bSJian Shen 		}
1491ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD) {
1492ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_ACTIVE;
1493ee4bcd3bSJian Shen 		} else {
1494ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1495ee4bcd3bSJian Shen 			kfree(mac_node);
1496ee4bcd3bSJian Shen 		}
1497ee4bcd3bSJian Shen 	}
1498ee4bcd3bSJian Shen }
1499ee4bcd3bSJian Shen 
1500ee4bcd3bSJian Shen static void hclgevf_sync_from_add_list(struct list_head *add_list,
1501ee4bcd3bSJian Shen 				       struct list_head *mac_list)
1502ee4bcd3bSJian Shen {
1503ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1504ee4bcd3bSJian Shen 
1505ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, add_list, node) {
1506ee4bcd3bSJian Shen 		/* if the mac address from tmp_add_list is not in the
1507ee4bcd3bSJian Shen 		 * uc/mc_mac_list, it means have received a TO_DEL request
1508ee4bcd3bSJian Shen 		 * during the time window of sending mac config request to PF
1509ee4bcd3bSJian Shen 		 * If mac_node state is ACTIVE, then change its state to TO_DEL,
1510ee4bcd3bSJian Shen 		 * then it will be removed at next time. If is TO_ADD, it means
1511ee4bcd3bSJian Shen 		 * send TO_ADD request failed, so just remove the mac node.
1512ee4bcd3bSJian Shen 		 */
1513ee4bcd3bSJian Shen 		new_node = hclgevf_find_mac_node(mac_list, mac_node->mac_addr);
1514ee4bcd3bSJian Shen 		if (new_node) {
1515ee4bcd3bSJian Shen 			hclgevf_update_mac_node(new_node, mac_node->state);
1516ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1517ee4bcd3bSJian Shen 			kfree(mac_node);
1518ee4bcd3bSJian Shen 		} else if (mac_node->state == HCLGEVF_MAC_ACTIVE) {
1519ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_TO_DEL;
1520ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1521ee4bcd3bSJian Shen 			list_add_tail(&mac_node->node, mac_list);
1522ee4bcd3bSJian Shen 		} else {
1523ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1524ee4bcd3bSJian Shen 			kfree(mac_node);
1525ee4bcd3bSJian Shen 		}
1526ee4bcd3bSJian Shen 	}
1527ee4bcd3bSJian Shen }
1528ee4bcd3bSJian Shen 
1529ee4bcd3bSJian Shen static void hclgevf_sync_from_del_list(struct list_head *del_list,
1530ee4bcd3bSJian Shen 				       struct list_head *mac_list)
1531ee4bcd3bSJian Shen {
1532ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1533ee4bcd3bSJian Shen 
1534ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, del_list, node) {
1535ee4bcd3bSJian Shen 		new_node = hclgevf_find_mac_node(mac_list, mac_node->mac_addr);
1536ee4bcd3bSJian Shen 		if (new_node) {
1537ee4bcd3bSJian Shen 			/* If the mac addr is exist in the mac list, it means
1538ee4bcd3bSJian Shen 			 * received a new request TO_ADD during the time window
1539ee4bcd3bSJian Shen 			 * of sending mac addr configurrequest to PF, so just
1540ee4bcd3bSJian Shen 			 * change the mac state to ACTIVE.
1541ee4bcd3bSJian Shen 			 */
1542ee4bcd3bSJian Shen 			new_node->state = HCLGEVF_MAC_ACTIVE;
1543ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1544ee4bcd3bSJian Shen 			kfree(mac_node);
1545ee4bcd3bSJian Shen 		} else {
1546ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1547ee4bcd3bSJian Shen 			list_add_tail(&mac_node->node, mac_list);
1548ee4bcd3bSJian Shen 		}
1549ee4bcd3bSJian Shen 	}
1550ee4bcd3bSJian Shen }
1551ee4bcd3bSJian Shen 
1552ee4bcd3bSJian Shen static void hclgevf_clear_list(struct list_head *list)
1553ee4bcd3bSJian Shen {
1554ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp;
1555ee4bcd3bSJian Shen 
1556ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node) {
1557ee4bcd3bSJian Shen 		list_del(&mac_node->node);
1558ee4bcd3bSJian Shen 		kfree(mac_node);
1559ee4bcd3bSJian Shen 	}
1560ee4bcd3bSJian Shen }
1561ee4bcd3bSJian Shen 
1562ee4bcd3bSJian Shen static void hclgevf_sync_mac_list(struct hclgevf_dev *hdev,
1563ee4bcd3bSJian Shen 				  enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1564ee4bcd3bSJian Shen {
1565ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1566ee4bcd3bSJian Shen 	struct list_head tmp_add_list, tmp_del_list;
1567ee4bcd3bSJian Shen 	struct list_head *list;
1568ee4bcd3bSJian Shen 
1569ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&tmp_add_list);
1570ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&tmp_del_list);
1571ee4bcd3bSJian Shen 
1572ee4bcd3bSJian Shen 	/* move the mac addr to the tmp_add_list and tmp_del_list, then
1573ee4bcd3bSJian Shen 	 * we can add/delete these mac addr outside the spin lock
1574ee4bcd3bSJian Shen 	 */
1575ee4bcd3bSJian Shen 	list = (mac_type == HCLGEVF_MAC_ADDR_UC) ?
1576ee4bcd3bSJian Shen 		&hdev->mac_table.uc_mac_list : &hdev->mac_table.mc_mac_list;
1577ee4bcd3bSJian Shen 
1578ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1579ee4bcd3bSJian Shen 
1580ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node) {
1581ee4bcd3bSJian Shen 		switch (mac_node->state) {
1582ee4bcd3bSJian Shen 		case HCLGEVF_MAC_TO_DEL:
1583ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1584ee4bcd3bSJian Shen 			list_add_tail(&mac_node->node, &tmp_del_list);
1585ee4bcd3bSJian Shen 			break;
1586ee4bcd3bSJian Shen 		case HCLGEVF_MAC_TO_ADD:
1587ee4bcd3bSJian Shen 			new_node = kzalloc(sizeof(*new_node), GFP_ATOMIC);
1588ee4bcd3bSJian Shen 			if (!new_node)
1589ee4bcd3bSJian Shen 				goto stop_traverse;
1590ee4bcd3bSJian Shen 
1591ee4bcd3bSJian Shen 			ether_addr_copy(new_node->mac_addr, mac_node->mac_addr);
1592ee4bcd3bSJian Shen 			new_node->state = mac_node->state;
1593ee4bcd3bSJian Shen 			list_add_tail(&new_node->node, &tmp_add_list);
1594ee4bcd3bSJian Shen 			break;
1595ee4bcd3bSJian Shen 		default:
1596ee4bcd3bSJian Shen 			break;
1597ee4bcd3bSJian Shen 		}
1598ee4bcd3bSJian Shen 	}
1599ee4bcd3bSJian Shen 
1600ee4bcd3bSJian Shen stop_traverse:
1601ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1602ee4bcd3bSJian Shen 
1603ee4bcd3bSJian Shen 	/* delete first, in order to get max mac table space for adding */
1604ee4bcd3bSJian Shen 	hclgevf_config_mac_list(hdev, &tmp_del_list, mac_type);
1605ee4bcd3bSJian Shen 	hclgevf_config_mac_list(hdev, &tmp_add_list, mac_type);
1606ee4bcd3bSJian Shen 
1607ee4bcd3bSJian Shen 	/* if some mac addresses were added/deleted fail, move back to the
1608ee4bcd3bSJian Shen 	 * mac_list, and retry at next time.
1609ee4bcd3bSJian Shen 	 */
1610ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1611ee4bcd3bSJian Shen 
1612ee4bcd3bSJian Shen 	hclgevf_sync_from_del_list(&tmp_del_list, list);
1613ee4bcd3bSJian Shen 	hclgevf_sync_from_add_list(&tmp_add_list, list);
1614ee4bcd3bSJian Shen 
1615ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1616ee4bcd3bSJian Shen }
1617ee4bcd3bSJian Shen 
1618ee4bcd3bSJian Shen static void hclgevf_sync_mac_table(struct hclgevf_dev *hdev)
1619ee4bcd3bSJian Shen {
1620ee4bcd3bSJian Shen 	hclgevf_sync_mac_list(hdev, HCLGEVF_MAC_ADDR_UC);
1621ee4bcd3bSJian Shen 	hclgevf_sync_mac_list(hdev, HCLGEVF_MAC_ADDR_MC);
1622ee4bcd3bSJian Shen }
1623ee4bcd3bSJian Shen 
1624ee4bcd3bSJian Shen static void hclgevf_uninit_mac_list(struct hclgevf_dev *hdev)
1625ee4bcd3bSJian Shen {
1626ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1627ee4bcd3bSJian Shen 
1628ee4bcd3bSJian Shen 	hclgevf_clear_list(&hdev->mac_table.uc_mac_list);
1629ee4bcd3bSJian Shen 	hclgevf_clear_list(&hdev->mac_table.mc_mac_list);
1630ee4bcd3bSJian Shen 
1631ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1632ee4bcd3bSJian Shen }
1633ee4bcd3bSJian Shen 
1634e2cb1decSSalil Mehta static int hclgevf_set_vlan_filter(struct hnae3_handle *handle,
1635e2cb1decSSalil Mehta 				   __be16 proto, u16 vlan_id,
1636e2cb1decSSalil Mehta 				   bool is_kill)
1637e2cb1decSSalil Mehta {
1638d3410018SYufeng Mo #define HCLGEVF_VLAN_MBX_IS_KILL_OFFSET	0
1639d3410018SYufeng Mo #define HCLGEVF_VLAN_MBX_VLAN_ID_OFFSET	1
1640d3410018SYufeng Mo #define HCLGEVF_VLAN_MBX_PROTO_OFFSET	3
1641d3410018SYufeng Mo 
1642e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1643d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1644fe4144d4SJian Shen 	int ret;
1645e2cb1decSSalil Mehta 
1646b37ce587SYufeng Mo 	if (vlan_id > HCLGEVF_MAX_VLAN_ID)
1647e2cb1decSSalil Mehta 		return -EINVAL;
1648e2cb1decSSalil Mehta 
1649e2cb1decSSalil Mehta 	if (proto != htons(ETH_P_8021Q))
1650e2cb1decSSalil Mehta 		return -EPROTONOSUPPORT;
1651e2cb1decSSalil Mehta 
1652b7b5d25bSGuojia Liao 	/* When device is resetting or reset failed, firmware is unable to
1653b7b5d25bSGuojia Liao 	 * handle mailbox. Just record the vlan id, and remove it after
1654fe4144d4SJian Shen 	 * reset finished.
1655fe4144d4SJian Shen 	 */
1656b7b5d25bSGuojia Liao 	if ((test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
1657b7b5d25bSGuojia Liao 	     test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) && is_kill) {
1658fe4144d4SJian Shen 		set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1659fe4144d4SJian Shen 		return -EBUSY;
1660fe4144d4SJian Shen 	}
1661fe4144d4SJian Shen 
1662d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
1663d3410018SYufeng Mo 			       HCLGE_MBX_VLAN_FILTER);
1664d3410018SYufeng Mo 	send_msg.data[HCLGEVF_VLAN_MBX_IS_KILL_OFFSET] = is_kill;
1665d3410018SYufeng Mo 	memcpy(&send_msg.data[HCLGEVF_VLAN_MBX_VLAN_ID_OFFSET], &vlan_id,
1666d3410018SYufeng Mo 	       sizeof(vlan_id));
1667d3410018SYufeng Mo 	memcpy(&send_msg.data[HCLGEVF_VLAN_MBX_PROTO_OFFSET], &proto,
1668d3410018SYufeng Mo 	       sizeof(proto));
166946ee7350SGuojia Liao 	/* when remove hw vlan filter failed, record the vlan id,
1670fe4144d4SJian Shen 	 * and try to remove it from hw later, to be consistence
1671fe4144d4SJian Shen 	 * with stack.
1672fe4144d4SJian Shen 	 */
1673d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1674fe4144d4SJian Shen 	if (is_kill && ret)
1675fe4144d4SJian Shen 		set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1676fe4144d4SJian Shen 
1677fe4144d4SJian Shen 	return ret;
1678fe4144d4SJian Shen }
1679fe4144d4SJian Shen 
1680fe4144d4SJian Shen static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev)
1681fe4144d4SJian Shen {
1682fe4144d4SJian Shen #define HCLGEVF_MAX_SYNC_COUNT	60
1683fe4144d4SJian Shen 	struct hnae3_handle *handle = &hdev->nic;
1684fe4144d4SJian Shen 	int ret, sync_cnt = 0;
1685fe4144d4SJian Shen 	u16 vlan_id;
1686fe4144d4SJian Shen 
1687fe4144d4SJian Shen 	vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1688fe4144d4SJian Shen 	while (vlan_id != VLAN_N_VID) {
1689fe4144d4SJian Shen 		ret = hclgevf_set_vlan_filter(handle, htons(ETH_P_8021Q),
1690fe4144d4SJian Shen 					      vlan_id, true);
1691fe4144d4SJian Shen 		if (ret)
1692fe4144d4SJian Shen 			return;
1693fe4144d4SJian Shen 
1694fe4144d4SJian Shen 		clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
1695fe4144d4SJian Shen 		sync_cnt++;
1696fe4144d4SJian Shen 		if (sync_cnt >= HCLGEVF_MAX_SYNC_COUNT)
1697fe4144d4SJian Shen 			return;
1698fe4144d4SJian Shen 
1699fe4144d4SJian Shen 		vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1700fe4144d4SJian Shen 	}
1701e2cb1decSSalil Mehta }
1702e2cb1decSSalil Mehta 
1703b2641e2aSYunsheng Lin static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
1704b2641e2aSYunsheng Lin {
1705b2641e2aSYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1706d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1707b2641e2aSYunsheng Lin 
1708d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
1709d3410018SYufeng Mo 			       HCLGE_MBX_VLAN_RX_OFF_CFG);
1710d3410018SYufeng Mo 	send_msg.data[0] = enable ? 1 : 0;
1711d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1712b2641e2aSYunsheng Lin }
1713b2641e2aSYunsheng Lin 
17147fa6be4fSHuazhong Tan static int hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
1715e2cb1decSSalil Mehta {
1716e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1717d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
17181a426f8bSPeng Li 	int ret;
1719e2cb1decSSalil Mehta 
17201a426f8bSPeng Li 	/* disable vf queue before send queue reset msg to PF */
17211a426f8bSPeng Li 	ret = hclgevf_tqp_enable(hdev, queue_id, 0, false);
17221a426f8bSPeng Li 	if (ret)
17237fa6be4fSHuazhong Tan 		return ret;
17241a426f8bSPeng Li 
1725d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_QUEUE_RESET, 0);
1726d3410018SYufeng Mo 	memcpy(send_msg.data, &queue_id, sizeof(queue_id));
1727d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1728e2cb1decSSalil Mehta }
1729e2cb1decSSalil Mehta 
1730818f1675SYunsheng Lin static int hclgevf_set_mtu(struct hnae3_handle *handle, int new_mtu)
1731818f1675SYunsheng Lin {
1732818f1675SYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1733d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1734818f1675SYunsheng Lin 
1735d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_MTU, 0);
1736d3410018SYufeng Mo 	memcpy(send_msg.data, &new_mtu, sizeof(new_mtu));
1737d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1738818f1675SYunsheng Lin }
1739818f1675SYunsheng Lin 
17406988eb2aSSalil Mehta static int hclgevf_notify_client(struct hclgevf_dev *hdev,
17416988eb2aSSalil Mehta 				 enum hnae3_reset_notify_type type)
17426988eb2aSSalil Mehta {
17436988eb2aSSalil Mehta 	struct hnae3_client *client = hdev->nic_client;
17446988eb2aSSalil Mehta 	struct hnae3_handle *handle = &hdev->nic;
17456a5f6fa3SHuazhong Tan 	int ret;
17466988eb2aSSalil Mehta 
174725d1817cSHuazhong Tan 	if (!test_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state) ||
174825d1817cSHuazhong Tan 	    !client)
174925d1817cSHuazhong Tan 		return 0;
175025d1817cSHuazhong Tan 
17516988eb2aSSalil Mehta 	if (!client->ops->reset_notify)
17526988eb2aSSalil Mehta 		return -EOPNOTSUPP;
17536988eb2aSSalil Mehta 
17546a5f6fa3SHuazhong Tan 	ret = client->ops->reset_notify(handle, type);
17556a5f6fa3SHuazhong Tan 	if (ret)
17566a5f6fa3SHuazhong Tan 		dev_err(&hdev->pdev->dev, "notify nic client failed %d(%d)\n",
17576a5f6fa3SHuazhong Tan 			type, ret);
17586a5f6fa3SHuazhong Tan 
17596a5f6fa3SHuazhong Tan 	return ret;
17606988eb2aSSalil Mehta }
17616988eb2aSSalil Mehta 
1762fe735c84SHuazhong Tan static int hclgevf_notify_roce_client(struct hclgevf_dev *hdev,
1763fe735c84SHuazhong Tan 				      enum hnae3_reset_notify_type type)
1764fe735c84SHuazhong Tan {
1765fe735c84SHuazhong Tan 	struct hnae3_client *client = hdev->roce_client;
1766fe735c84SHuazhong Tan 	struct hnae3_handle *handle = &hdev->roce;
1767fe735c84SHuazhong Tan 	int ret;
1768fe735c84SHuazhong Tan 
1769fe735c84SHuazhong Tan 	if (!test_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state) || !client)
1770fe735c84SHuazhong Tan 		return 0;
1771fe735c84SHuazhong Tan 
1772fe735c84SHuazhong Tan 	if (!client->ops->reset_notify)
1773fe735c84SHuazhong Tan 		return -EOPNOTSUPP;
1774fe735c84SHuazhong Tan 
1775fe735c84SHuazhong Tan 	ret = client->ops->reset_notify(handle, type);
1776fe735c84SHuazhong Tan 	if (ret)
1777fe735c84SHuazhong Tan 		dev_err(&hdev->pdev->dev, "notify roce client failed %d(%d)",
1778fe735c84SHuazhong Tan 			type, ret);
1779fe735c84SHuazhong Tan 	return ret;
1780fe735c84SHuazhong Tan }
1781fe735c84SHuazhong Tan 
17826988eb2aSSalil Mehta static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
17836988eb2aSSalil Mehta {
1784aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_US	20000
1785aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_CNT	2000
1786aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_TIMEOUT_US	\
1787aa5c4f17SHuazhong Tan 	(HCLGEVF_RESET_WAIT_US * HCLGEVF_RESET_WAIT_CNT)
1788aa5c4f17SHuazhong Tan 
1789aa5c4f17SHuazhong Tan 	u32 val;
1790aa5c4f17SHuazhong Tan 	int ret;
17916988eb2aSSalil Mehta 
1792f28368bbSHuazhong Tan 	if (hdev->reset_type == HNAE3_VF_RESET)
179372e2fb07SHuazhong Tan 		ret = readl_poll_timeout(hdev->hw.io_base +
179472e2fb07SHuazhong Tan 					 HCLGEVF_VF_RST_ING, val,
179572e2fb07SHuazhong Tan 					 !(val & HCLGEVF_VF_RST_ING_BIT),
179672e2fb07SHuazhong Tan 					 HCLGEVF_RESET_WAIT_US,
179772e2fb07SHuazhong Tan 					 HCLGEVF_RESET_WAIT_TIMEOUT_US);
179872e2fb07SHuazhong Tan 	else
179972e2fb07SHuazhong Tan 		ret = readl_poll_timeout(hdev->hw.io_base +
180072e2fb07SHuazhong Tan 					 HCLGEVF_RST_ING, val,
1801aa5c4f17SHuazhong Tan 					 !(val & HCLGEVF_RST_ING_BITS),
1802aa5c4f17SHuazhong Tan 					 HCLGEVF_RESET_WAIT_US,
1803aa5c4f17SHuazhong Tan 					 HCLGEVF_RESET_WAIT_TIMEOUT_US);
18046988eb2aSSalil Mehta 
18056988eb2aSSalil Mehta 	/* hardware completion status should be available by this time */
1806aa5c4f17SHuazhong Tan 	if (ret) {
1807aa5c4f17SHuazhong Tan 		dev_err(&hdev->pdev->dev,
18088912fd6aSColin Ian King 			"couldn't get reset done status from h/w, timeout!\n");
1809aa5c4f17SHuazhong Tan 		return ret;
18106988eb2aSSalil Mehta 	}
18116988eb2aSSalil Mehta 
18126988eb2aSSalil Mehta 	/* we will wait a bit more to let reset of the stack to complete. This
18136988eb2aSSalil Mehta 	 * might happen in case reset assertion was made by PF. Yes, this also
18146988eb2aSSalil Mehta 	 * means we might end up waiting bit more even for VF reset.
18156988eb2aSSalil Mehta 	 */
18166988eb2aSSalil Mehta 	msleep(5000);
18176988eb2aSSalil Mehta 
18186988eb2aSSalil Mehta 	return 0;
18196988eb2aSSalil Mehta }
18206988eb2aSSalil Mehta 
18216b428b4fSHuazhong Tan static void hclgevf_reset_handshake(struct hclgevf_dev *hdev, bool enable)
18226b428b4fSHuazhong Tan {
18236b428b4fSHuazhong Tan 	u32 reg_val;
18246b428b4fSHuazhong Tan 
18256b428b4fSHuazhong Tan 	reg_val = hclgevf_read_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG);
18266b428b4fSHuazhong Tan 	if (enable)
18276b428b4fSHuazhong Tan 		reg_val |= HCLGEVF_NIC_SW_RST_RDY;
18286b428b4fSHuazhong Tan 	else
18296b428b4fSHuazhong Tan 		reg_val &= ~HCLGEVF_NIC_SW_RST_RDY;
18306b428b4fSHuazhong Tan 
18316b428b4fSHuazhong Tan 	hclgevf_write_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG,
18326b428b4fSHuazhong Tan 			  reg_val);
18336b428b4fSHuazhong Tan }
18346b428b4fSHuazhong Tan 
18356988eb2aSSalil Mehta static int hclgevf_reset_stack(struct hclgevf_dev *hdev)
18366988eb2aSSalil Mehta {
18377a01c897SSalil Mehta 	int ret;
18387a01c897SSalil Mehta 
18396988eb2aSSalil Mehta 	/* uninitialize the nic client */
18406a5f6fa3SHuazhong Tan 	ret = hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
18416a5f6fa3SHuazhong Tan 	if (ret)
18426a5f6fa3SHuazhong Tan 		return ret;
18436988eb2aSSalil Mehta 
18447a01c897SSalil Mehta 	/* re-initialize the hclge device */
18459c6f7085SHuazhong Tan 	ret = hclgevf_reset_hdev(hdev);
18467a01c897SSalil Mehta 	if (ret) {
18477a01c897SSalil Mehta 		dev_err(&hdev->pdev->dev,
18487a01c897SSalil Mehta 			"hclge device re-init failed, VF is disabled!\n");
18497a01c897SSalil Mehta 		return ret;
18507a01c897SSalil Mehta 	}
18516988eb2aSSalil Mehta 
18526988eb2aSSalil Mehta 	/* bring up the nic client again */
18536a5f6fa3SHuazhong Tan 	ret = hclgevf_notify_client(hdev, HNAE3_INIT_CLIENT);
18546a5f6fa3SHuazhong Tan 	if (ret)
18556a5f6fa3SHuazhong Tan 		return ret;
18566988eb2aSSalil Mehta 
18576b428b4fSHuazhong Tan 	/* clear handshake status with IMP */
18586b428b4fSHuazhong Tan 	hclgevf_reset_handshake(hdev, false);
18596b428b4fSHuazhong Tan 
18601cc9bc6eSHuazhong Tan 	/* bring up the nic to enable TX/RX again */
18611cc9bc6eSHuazhong Tan 	return hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
18626988eb2aSSalil Mehta }
18636988eb2aSSalil Mehta 
1864dea846e8SHuazhong Tan static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
1865dea846e8SHuazhong Tan {
1866ada13ee3SHuazhong Tan #define HCLGEVF_RESET_SYNC_TIME 100
1867ada13ee3SHuazhong Tan 
1868f28368bbSHuazhong Tan 	if (hdev->reset_type == HNAE3_VF_FUNC_RESET) {
1869d41884eeSHuazhong Tan 		struct hclge_vf_to_pf_msg send_msg;
1870d41884eeSHuazhong Tan 		int ret;
1871d41884eeSHuazhong Tan 
1872d3410018SYufeng Mo 		hclgevf_build_send_msg(&send_msg, HCLGE_MBX_RESET, 0);
1873d3410018SYufeng Mo 		ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1874cddd5648SHuazhong Tan 		if (ret) {
1875cddd5648SHuazhong Tan 			dev_err(&hdev->pdev->dev,
1876cddd5648SHuazhong Tan 				"failed to assert VF reset, ret = %d\n", ret);
1877cddd5648SHuazhong Tan 			return ret;
1878cddd5648SHuazhong Tan 		}
1879c88a6e7dSHuazhong Tan 		hdev->rst_stats.vf_func_rst_cnt++;
1880dea846e8SHuazhong Tan 	}
1881dea846e8SHuazhong Tan 
1882ef5f8e50SHuazhong Tan 	set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
1883ada13ee3SHuazhong Tan 	/* inform hardware that preparatory work is done */
1884ada13ee3SHuazhong Tan 	msleep(HCLGEVF_RESET_SYNC_TIME);
18856b428b4fSHuazhong Tan 	hclgevf_reset_handshake(hdev, true);
1886d41884eeSHuazhong Tan 	dev_info(&hdev->pdev->dev, "prepare reset(%d) wait done\n",
1887d41884eeSHuazhong Tan 		 hdev->reset_type);
1888dea846e8SHuazhong Tan 
1889d41884eeSHuazhong Tan 	return 0;
1890dea846e8SHuazhong Tan }
1891dea846e8SHuazhong Tan 
18923d77d0cbSHuazhong Tan static void hclgevf_dump_rst_info(struct hclgevf_dev *hdev)
18933d77d0cbSHuazhong Tan {
18943d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "VF function reset count: %u\n",
18953d77d0cbSHuazhong Tan 		 hdev->rst_stats.vf_func_rst_cnt);
18963d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "FLR reset count: %u\n",
18973d77d0cbSHuazhong Tan 		 hdev->rst_stats.flr_rst_cnt);
18983d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "VF reset count: %u\n",
18993d77d0cbSHuazhong Tan 		 hdev->rst_stats.vf_rst_cnt);
19003d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "reset done count: %u\n",
19013d77d0cbSHuazhong Tan 		 hdev->rst_stats.rst_done_cnt);
19023d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "HW reset done count: %u\n",
19033d77d0cbSHuazhong Tan 		 hdev->rst_stats.hw_rst_done_cnt);
19043d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "reset count: %u\n",
19053d77d0cbSHuazhong Tan 		 hdev->rst_stats.rst_cnt);
19063d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "reset fail count: %u\n",
19073d77d0cbSHuazhong Tan 		 hdev->rst_stats.rst_fail_cnt);
19083d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "vector0 interrupt enable status: 0x%x\n",
19093d77d0cbSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_MISC_VECTOR_REG_BASE));
19103d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "vector0 interrupt status: 0x%x\n",
19119cee2e8dSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_VECTOR0_CMDQ_STATE_REG));
19123d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "handshake status: 0x%x\n",
19133d77d0cbSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_CMDQ_TX_DEPTH_REG));
19143d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "function reset status: 0x%x\n",
19153d77d0cbSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING));
19163d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "hdev state: 0x%lx\n", hdev->state);
19173d77d0cbSHuazhong Tan }
19183d77d0cbSHuazhong Tan 
1919bbe6540eSHuazhong Tan static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev)
1920bbe6540eSHuazhong Tan {
19216b428b4fSHuazhong Tan 	/* recover handshake status with IMP when reset fail */
19226b428b4fSHuazhong Tan 	hclgevf_reset_handshake(hdev, true);
1923bbe6540eSHuazhong Tan 	hdev->rst_stats.rst_fail_cnt++;
1924adcf738bSGuojia Liao 	dev_err(&hdev->pdev->dev, "failed to reset VF(%u)\n",
1925bbe6540eSHuazhong Tan 		hdev->rst_stats.rst_fail_cnt);
1926bbe6540eSHuazhong Tan 
1927bbe6540eSHuazhong Tan 	if (hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT)
1928bbe6540eSHuazhong Tan 		set_bit(hdev->reset_type, &hdev->reset_pending);
1929bbe6540eSHuazhong Tan 
1930bbe6540eSHuazhong Tan 	if (hclgevf_is_reset_pending(hdev)) {
1931bbe6540eSHuazhong Tan 		set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
1932bbe6540eSHuazhong Tan 		hclgevf_reset_task_schedule(hdev);
19333d77d0cbSHuazhong Tan 	} else {
1934d5432455SGuojia Liao 		set_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
19353d77d0cbSHuazhong Tan 		hclgevf_dump_rst_info(hdev);
1936bbe6540eSHuazhong Tan 	}
1937bbe6540eSHuazhong Tan }
1938bbe6540eSHuazhong Tan 
19391cc9bc6eSHuazhong Tan static int hclgevf_reset_prepare(struct hclgevf_dev *hdev)
19406988eb2aSSalil Mehta {
19416988eb2aSSalil Mehta 	int ret;
19426988eb2aSSalil Mehta 
1943c88a6e7dSHuazhong Tan 	hdev->rst_stats.rst_cnt++;
19446988eb2aSSalil Mehta 
1945fe735c84SHuazhong Tan 	/* perform reset of the stack & ae device for a client */
1946fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_DOWN_CLIENT);
1947fe735c84SHuazhong Tan 	if (ret)
1948fe735c84SHuazhong Tan 		return ret;
1949fe735c84SHuazhong Tan 
19501cc9bc6eSHuazhong Tan 	rtnl_lock();
19516988eb2aSSalil Mehta 	/* bring down the nic to stop any ongoing TX/RX */
19526a5f6fa3SHuazhong Tan 	ret = hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
195329118ab9SHuazhong Tan 	rtnl_unlock();
19546a5f6fa3SHuazhong Tan 	if (ret)
19551cc9bc6eSHuazhong Tan 		return ret;
1956dea846e8SHuazhong Tan 
19571cc9bc6eSHuazhong Tan 	return hclgevf_reset_prepare_wait(hdev);
19586988eb2aSSalil Mehta }
19596988eb2aSSalil Mehta 
19601cc9bc6eSHuazhong Tan static int hclgevf_reset_rebuild(struct hclgevf_dev *hdev)
19611cc9bc6eSHuazhong Tan {
19621cc9bc6eSHuazhong Tan 	int ret;
19631cc9bc6eSHuazhong Tan 
1964c88a6e7dSHuazhong Tan 	hdev->rst_stats.hw_rst_done_cnt++;
1965fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_UNINIT_CLIENT);
1966fe735c84SHuazhong Tan 	if (ret)
1967fe735c84SHuazhong Tan 		return ret;
1968c88a6e7dSHuazhong Tan 
196929118ab9SHuazhong Tan 	rtnl_lock();
19706988eb2aSSalil Mehta 	/* now, re-initialize the nic client and ae device */
19716988eb2aSSalil Mehta 	ret = hclgevf_reset_stack(hdev);
19721cc9bc6eSHuazhong Tan 	rtnl_unlock();
19736a5f6fa3SHuazhong Tan 	if (ret) {
19746988eb2aSSalil Mehta 		dev_err(&hdev->pdev->dev, "failed to reset VF stack\n");
19751cc9bc6eSHuazhong Tan 		return ret;
19766a5f6fa3SHuazhong Tan 	}
19776988eb2aSSalil Mehta 
1978fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_INIT_CLIENT);
1979fe735c84SHuazhong Tan 	/* ignore RoCE notify error if it fails HCLGEVF_RESET_MAX_FAIL_CNT - 1
1980fe735c84SHuazhong Tan 	 * times
1981fe735c84SHuazhong Tan 	 */
1982fe735c84SHuazhong Tan 	if (ret &&
1983fe735c84SHuazhong Tan 	    hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT - 1)
1984fe735c84SHuazhong Tan 		return ret;
1985fe735c84SHuazhong Tan 
1986fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_UP_CLIENT);
1987fe735c84SHuazhong Tan 	if (ret)
1988fe735c84SHuazhong Tan 		return ret;
1989fe735c84SHuazhong Tan 
1990b644a8d4SHuazhong Tan 	hdev->last_reset_time = jiffies;
1991c88a6e7dSHuazhong Tan 	hdev->rst_stats.rst_done_cnt++;
1992bbe6540eSHuazhong Tan 	hdev->rst_stats.rst_fail_cnt = 0;
1993d5432455SGuojia Liao 	clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
1994b644a8d4SHuazhong Tan 
19951cc9bc6eSHuazhong Tan 	return 0;
19961cc9bc6eSHuazhong Tan }
19971cc9bc6eSHuazhong Tan 
19981cc9bc6eSHuazhong Tan static void hclgevf_reset(struct hclgevf_dev *hdev)
19991cc9bc6eSHuazhong Tan {
20001cc9bc6eSHuazhong Tan 	if (hclgevf_reset_prepare(hdev))
20011cc9bc6eSHuazhong Tan 		goto err_reset;
20021cc9bc6eSHuazhong Tan 
20031cc9bc6eSHuazhong Tan 	/* check if VF could successfully fetch the hardware reset completion
20041cc9bc6eSHuazhong Tan 	 * status from the hardware
20051cc9bc6eSHuazhong Tan 	 */
20061cc9bc6eSHuazhong Tan 	if (hclgevf_reset_wait(hdev)) {
20071cc9bc6eSHuazhong Tan 		/* can't do much in this situation, will disable VF */
20081cc9bc6eSHuazhong Tan 		dev_err(&hdev->pdev->dev,
20091cc9bc6eSHuazhong Tan 			"failed to fetch H/W reset completion status\n");
20101cc9bc6eSHuazhong Tan 		goto err_reset;
20111cc9bc6eSHuazhong Tan 	}
20121cc9bc6eSHuazhong Tan 
20131cc9bc6eSHuazhong Tan 	if (hclgevf_reset_rebuild(hdev))
20141cc9bc6eSHuazhong Tan 		goto err_reset;
20151cc9bc6eSHuazhong Tan 
20161cc9bc6eSHuazhong Tan 	return;
20171cc9bc6eSHuazhong Tan 
20186a5f6fa3SHuazhong Tan err_reset:
2019bbe6540eSHuazhong Tan 	hclgevf_reset_err_handle(hdev);
20206988eb2aSSalil Mehta }
20216988eb2aSSalil Mehta 
2022720bd583SHuazhong Tan static enum hnae3_reset_type hclgevf_get_reset_level(struct hclgevf_dev *hdev,
2023720bd583SHuazhong Tan 						     unsigned long *addr)
2024720bd583SHuazhong Tan {
2025720bd583SHuazhong Tan 	enum hnae3_reset_type rst_level = HNAE3_NONE_RESET;
2026720bd583SHuazhong Tan 
2027dea846e8SHuazhong Tan 	/* return the highest priority reset level amongst all */
2028b90fcc5bSHuazhong Tan 	if (test_bit(HNAE3_VF_RESET, addr)) {
2029b90fcc5bSHuazhong Tan 		rst_level = HNAE3_VF_RESET;
2030b90fcc5bSHuazhong Tan 		clear_bit(HNAE3_VF_RESET, addr);
2031b90fcc5bSHuazhong Tan 		clear_bit(HNAE3_VF_PF_FUNC_RESET, addr);
2032b90fcc5bSHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
2033b90fcc5bSHuazhong Tan 	} else if (test_bit(HNAE3_VF_FULL_RESET, addr)) {
2034dea846e8SHuazhong Tan 		rst_level = HNAE3_VF_FULL_RESET;
2035dea846e8SHuazhong Tan 		clear_bit(HNAE3_VF_FULL_RESET, addr);
2036dea846e8SHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
2037aa5c4f17SHuazhong Tan 	} else if (test_bit(HNAE3_VF_PF_FUNC_RESET, addr)) {
2038aa5c4f17SHuazhong Tan 		rst_level = HNAE3_VF_PF_FUNC_RESET;
2039aa5c4f17SHuazhong Tan 		clear_bit(HNAE3_VF_PF_FUNC_RESET, addr);
2040aa5c4f17SHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
2041dea846e8SHuazhong Tan 	} else if (test_bit(HNAE3_VF_FUNC_RESET, addr)) {
2042dea846e8SHuazhong Tan 		rst_level = HNAE3_VF_FUNC_RESET;
2043dea846e8SHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
20446ff3cf07SHuazhong Tan 	} else if (test_bit(HNAE3_FLR_RESET, addr)) {
20456ff3cf07SHuazhong Tan 		rst_level = HNAE3_FLR_RESET;
20466ff3cf07SHuazhong Tan 		clear_bit(HNAE3_FLR_RESET, addr);
2047720bd583SHuazhong Tan 	}
2048720bd583SHuazhong Tan 
2049720bd583SHuazhong Tan 	return rst_level;
2050720bd583SHuazhong Tan }
2051720bd583SHuazhong Tan 
20526ae4e733SShiju Jose static void hclgevf_reset_event(struct pci_dev *pdev,
20536ae4e733SShiju Jose 				struct hnae3_handle *handle)
20546d4c3981SSalil Mehta {
20556ff3cf07SHuazhong Tan 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
20566ff3cf07SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
20576d4c3981SSalil Mehta 
20586d4c3981SSalil Mehta 	dev_info(&hdev->pdev->dev, "received reset request from VF enet\n");
20596d4c3981SSalil Mehta 
20606ff3cf07SHuazhong Tan 	if (hdev->default_reset_request)
20610742ed7cSHuazhong Tan 		hdev->reset_level =
2062720bd583SHuazhong Tan 			hclgevf_get_reset_level(hdev,
2063720bd583SHuazhong Tan 						&hdev->default_reset_request);
2064720bd583SHuazhong Tan 	else
2065dea846e8SHuazhong Tan 		hdev->reset_level = HNAE3_VF_FUNC_RESET;
20666d4c3981SSalil Mehta 
2067436667d2SSalil Mehta 	/* reset of this VF requested */
2068436667d2SSalil Mehta 	set_bit(HCLGEVF_RESET_REQUESTED, &hdev->reset_state);
2069436667d2SSalil Mehta 	hclgevf_reset_task_schedule(hdev);
20706d4c3981SSalil Mehta 
20710742ed7cSHuazhong Tan 	hdev->last_reset_time = jiffies;
20726d4c3981SSalil Mehta }
20736d4c3981SSalil Mehta 
2074720bd583SHuazhong Tan static void hclgevf_set_def_reset_request(struct hnae3_ae_dev *ae_dev,
2075720bd583SHuazhong Tan 					  enum hnae3_reset_type rst_type)
2076720bd583SHuazhong Tan {
2077720bd583SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
2078720bd583SHuazhong Tan 
2079720bd583SHuazhong Tan 	set_bit(rst_type, &hdev->default_reset_request);
2080720bd583SHuazhong Tan }
2081720bd583SHuazhong Tan 
2082f28368bbSHuazhong Tan static void hclgevf_enable_vector(struct hclgevf_misc_vector *vector, bool en)
2083f28368bbSHuazhong Tan {
2084f28368bbSHuazhong Tan 	writel(en ? 1 : 0, vector->addr);
2085f28368bbSHuazhong Tan }
2086f28368bbSHuazhong Tan 
20876ff3cf07SHuazhong Tan static void hclgevf_flr_prepare(struct hnae3_ae_dev *ae_dev)
20886ff3cf07SHuazhong Tan {
2089f28368bbSHuazhong Tan #define HCLGEVF_FLR_RETRY_WAIT_MS	500
2090f28368bbSHuazhong Tan #define HCLGEVF_FLR_RETRY_CNT		5
2091f28368bbSHuazhong Tan 
20926ff3cf07SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
2093f28368bbSHuazhong Tan 	int retry_cnt = 0;
2094f28368bbSHuazhong Tan 	int ret;
20956ff3cf07SHuazhong Tan 
2096f28368bbSHuazhong Tan retry:
2097f28368bbSHuazhong Tan 	down(&hdev->reset_sem);
2098f28368bbSHuazhong Tan 	set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2099f28368bbSHuazhong Tan 	hdev->reset_type = HNAE3_FLR_RESET;
2100f28368bbSHuazhong Tan 	ret = hclgevf_reset_prepare(hdev);
2101f28368bbSHuazhong Tan 	if (ret) {
2102f28368bbSHuazhong Tan 		dev_err(&hdev->pdev->dev, "fail to prepare FLR, ret=%d\n",
2103f28368bbSHuazhong Tan 			ret);
2104f28368bbSHuazhong Tan 		if (hdev->reset_pending ||
2105f28368bbSHuazhong Tan 		    retry_cnt++ < HCLGEVF_FLR_RETRY_CNT) {
21066ff3cf07SHuazhong Tan 			dev_err(&hdev->pdev->dev,
2107f28368bbSHuazhong Tan 				"reset_pending:0x%lx, retry_cnt:%d\n",
2108f28368bbSHuazhong Tan 				hdev->reset_pending, retry_cnt);
2109f28368bbSHuazhong Tan 			clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2110f28368bbSHuazhong Tan 			up(&hdev->reset_sem);
2111f28368bbSHuazhong Tan 			msleep(HCLGEVF_FLR_RETRY_WAIT_MS);
2112f28368bbSHuazhong Tan 			goto retry;
2113f28368bbSHuazhong Tan 		}
2114f28368bbSHuazhong Tan 	}
2115f28368bbSHuazhong Tan 
2116f28368bbSHuazhong Tan 	/* disable misc vector before FLR done */
2117f28368bbSHuazhong Tan 	hclgevf_enable_vector(&hdev->misc_vector, false);
2118f28368bbSHuazhong Tan 	hdev->rst_stats.flr_rst_cnt++;
2119f28368bbSHuazhong Tan }
2120f28368bbSHuazhong Tan 
2121f28368bbSHuazhong Tan static void hclgevf_flr_done(struct hnae3_ae_dev *ae_dev)
2122f28368bbSHuazhong Tan {
2123f28368bbSHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
2124f28368bbSHuazhong Tan 	int ret;
2125f28368bbSHuazhong Tan 
2126f28368bbSHuazhong Tan 	hclgevf_enable_vector(&hdev->misc_vector, true);
2127f28368bbSHuazhong Tan 
2128f28368bbSHuazhong Tan 	ret = hclgevf_reset_rebuild(hdev);
2129f28368bbSHuazhong Tan 	if (ret)
2130f28368bbSHuazhong Tan 		dev_warn(&hdev->pdev->dev, "fail to rebuild, ret=%d\n",
2131f28368bbSHuazhong Tan 			 ret);
2132f28368bbSHuazhong Tan 
2133f28368bbSHuazhong Tan 	hdev->reset_type = HNAE3_NONE_RESET;
2134f28368bbSHuazhong Tan 	clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2135f28368bbSHuazhong Tan 	up(&hdev->reset_sem);
21366ff3cf07SHuazhong Tan }
21376ff3cf07SHuazhong Tan 
2138e2cb1decSSalil Mehta static u32 hclgevf_get_fw_version(struct hnae3_handle *handle)
2139e2cb1decSSalil Mehta {
2140e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2141e2cb1decSSalil Mehta 
2142e2cb1decSSalil Mehta 	return hdev->fw_version;
2143e2cb1decSSalil Mehta }
2144e2cb1decSSalil Mehta 
2145e2cb1decSSalil Mehta static void hclgevf_get_misc_vector(struct hclgevf_dev *hdev)
2146e2cb1decSSalil Mehta {
2147e2cb1decSSalil Mehta 	struct hclgevf_misc_vector *vector = &hdev->misc_vector;
2148e2cb1decSSalil Mehta 
2149e2cb1decSSalil Mehta 	vector->vector_irq = pci_irq_vector(hdev->pdev,
2150e2cb1decSSalil Mehta 					    HCLGEVF_MISC_VECTOR_NUM);
2151e2cb1decSSalil Mehta 	vector->addr = hdev->hw.io_base + HCLGEVF_MISC_VECTOR_REG_BASE;
2152e2cb1decSSalil Mehta 	/* vector status always valid for Vector 0 */
2153e2cb1decSSalil Mehta 	hdev->vector_status[HCLGEVF_MISC_VECTOR_NUM] = 0;
2154e2cb1decSSalil Mehta 	hdev->vector_irq[HCLGEVF_MISC_VECTOR_NUM] = vector->vector_irq;
2155e2cb1decSSalil Mehta 
2156e2cb1decSSalil Mehta 	hdev->num_msi_left -= 1;
2157e2cb1decSSalil Mehta 	hdev->num_msi_used += 1;
2158e2cb1decSSalil Mehta }
2159e2cb1decSSalil Mehta 
216035a1e503SSalil Mehta void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev)
216135a1e503SSalil Mehta {
2162ff200099SYunsheng Lin 	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
2163ff200099SYunsheng Lin 	    !test_and_set_bit(HCLGEVF_STATE_RST_SERVICE_SCHED,
2164ff200099SYunsheng Lin 			      &hdev->state))
21650ea68902SYunsheng Lin 		mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
216635a1e503SSalil Mehta }
216735a1e503SSalil Mehta 
216807a0556aSSalil Mehta void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev)
2169e2cb1decSSalil Mehta {
2170ff200099SYunsheng Lin 	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
2171ff200099SYunsheng Lin 	    !test_and_set_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED,
2172ff200099SYunsheng Lin 			      &hdev->state))
21730ea68902SYunsheng Lin 		mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
217407a0556aSSalil Mehta }
2175e2cb1decSSalil Mehta 
2176ff200099SYunsheng Lin static void hclgevf_task_schedule(struct hclgevf_dev *hdev,
2177ff200099SYunsheng Lin 				  unsigned long delay)
2178e2cb1decSSalil Mehta {
2179d5432455SGuojia Liao 	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
2180d5432455SGuojia Liao 	    !test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state))
21810ea68902SYunsheng Lin 		mod_delayed_work(hclgevf_wq, &hdev->service_task, delay);
2182e2cb1decSSalil Mehta }
2183e2cb1decSSalil Mehta 
2184ff200099SYunsheng Lin static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
218535a1e503SSalil Mehta {
2186d6ad7c53SGuojia Liao #define	HCLGEVF_MAX_RESET_ATTEMPTS_CNT	3
2187d6ad7c53SGuojia Liao 
2188ff200099SYunsheng Lin 	if (!test_and_clear_bit(HCLGEVF_STATE_RST_SERVICE_SCHED, &hdev->state))
2189ff200099SYunsheng Lin 		return;
2190ff200099SYunsheng Lin 
2191f28368bbSHuazhong Tan 	down(&hdev->reset_sem);
2192f28368bbSHuazhong Tan 	set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
219335a1e503SSalil Mehta 
2194436667d2SSalil Mehta 	if (test_and_clear_bit(HCLGEVF_RESET_PENDING,
2195436667d2SSalil Mehta 			       &hdev->reset_state)) {
2196436667d2SSalil Mehta 		/* PF has initmated that it is about to reset the hardware.
21979b2f3477SWeihang Li 		 * We now have to poll & check if hardware has actually
21989b2f3477SWeihang Li 		 * completed the reset sequence. On hardware reset completion,
21999b2f3477SWeihang Li 		 * VF needs to reset the client and ae device.
220035a1e503SSalil Mehta 		 */
2201436667d2SSalil Mehta 		hdev->reset_attempts = 0;
2202436667d2SSalil Mehta 
2203dea846e8SHuazhong Tan 		hdev->last_reset_time = jiffies;
2204dea846e8SHuazhong Tan 		while ((hdev->reset_type =
2205dea846e8SHuazhong Tan 			hclgevf_get_reset_level(hdev, &hdev->reset_pending))
22061cc9bc6eSHuazhong Tan 		       != HNAE3_NONE_RESET)
22071cc9bc6eSHuazhong Tan 			hclgevf_reset(hdev);
2208436667d2SSalil Mehta 	} else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
2209436667d2SSalil Mehta 				      &hdev->reset_state)) {
2210436667d2SSalil Mehta 		/* we could be here when either of below happens:
22119b2f3477SWeihang Li 		 * 1. reset was initiated due to watchdog timeout caused by
2212436667d2SSalil Mehta 		 *    a. IMP was earlier reset and our TX got choked down and
2213436667d2SSalil Mehta 		 *       which resulted in watchdog reacting and inducing VF
2214436667d2SSalil Mehta 		 *       reset. This also means our cmdq would be unreliable.
2215436667d2SSalil Mehta 		 *    b. problem in TX due to other lower layer(example link
2216436667d2SSalil Mehta 		 *       layer not functioning properly etc.)
2217436667d2SSalil Mehta 		 * 2. VF reset might have been initiated due to some config
2218436667d2SSalil Mehta 		 *    change.
2219436667d2SSalil Mehta 		 *
2220436667d2SSalil Mehta 		 * NOTE: Theres no clear way to detect above cases than to react
2221436667d2SSalil Mehta 		 * to the response of PF for this reset request. PF will ack the
2222436667d2SSalil Mehta 		 * 1b and 2. cases but we will not get any intimation about 1a
2223436667d2SSalil Mehta 		 * from PF as cmdq would be in unreliable state i.e. mailbox
2224436667d2SSalil Mehta 		 * communication between PF and VF would be broken.
222546ee7350SGuojia Liao 		 *
222646ee7350SGuojia Liao 		 * if we are never geting into pending state it means either:
2227436667d2SSalil Mehta 		 * 1. PF is not receiving our request which could be due to IMP
2228436667d2SSalil Mehta 		 *    reset
2229436667d2SSalil Mehta 		 * 2. PF is screwed
2230436667d2SSalil Mehta 		 * We cannot do much for 2. but to check first we can try reset
2231436667d2SSalil Mehta 		 * our PCIe + stack and see if it alleviates the problem.
2232436667d2SSalil Mehta 		 */
2233d6ad7c53SGuojia Liao 		if (hdev->reset_attempts > HCLGEVF_MAX_RESET_ATTEMPTS_CNT) {
2234436667d2SSalil Mehta 			/* prepare for full reset of stack + pcie interface */
2235dea846e8SHuazhong Tan 			set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending);
2236436667d2SSalil Mehta 
2237436667d2SSalil Mehta 			/* "defer" schedule the reset task again */
2238436667d2SSalil Mehta 			set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
2239436667d2SSalil Mehta 		} else {
2240436667d2SSalil Mehta 			hdev->reset_attempts++;
2241436667d2SSalil Mehta 
2242dea846e8SHuazhong Tan 			set_bit(hdev->reset_level, &hdev->reset_pending);
2243dea846e8SHuazhong Tan 			set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
2244436667d2SSalil Mehta 		}
2245dea846e8SHuazhong Tan 		hclgevf_reset_task_schedule(hdev);
2246436667d2SSalil Mehta 	}
224735a1e503SSalil Mehta 
2248afb6afdbSHuazhong Tan 	hdev->reset_type = HNAE3_NONE_RESET;
224935a1e503SSalil Mehta 	clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2250f28368bbSHuazhong Tan 	up(&hdev->reset_sem);
225135a1e503SSalil Mehta }
225235a1e503SSalil Mehta 
2253ff200099SYunsheng Lin static void hclgevf_mailbox_service_task(struct hclgevf_dev *hdev)
2254e2cb1decSSalil Mehta {
2255ff200099SYunsheng Lin 	if (!test_and_clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state))
2256ff200099SYunsheng Lin 		return;
2257e2cb1decSSalil Mehta 
2258e2cb1decSSalil Mehta 	if (test_and_set_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state))
2259e2cb1decSSalil Mehta 		return;
2260e2cb1decSSalil Mehta 
226107a0556aSSalil Mehta 	hclgevf_mbx_async_handler(hdev);
2262e2cb1decSSalil Mehta 
2263e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
2264e2cb1decSSalil Mehta }
2265e2cb1decSSalil Mehta 
2266ff200099SYunsheng Lin static void hclgevf_keep_alive(struct hclgevf_dev *hdev)
2267a6d818e3SYunsheng Lin {
2268d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
2269a6d818e3SYunsheng Lin 	int ret;
2270a6d818e3SYunsheng Lin 
22711416d333SHuazhong Tan 	if (test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state))
2272c59a85c0SJian Shen 		return;
2273c59a85c0SJian Shen 
2274d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_KEEP_ALIVE, 0);
2275d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
2276a6d818e3SYunsheng Lin 	if (ret)
2277a6d818e3SYunsheng Lin 		dev_err(&hdev->pdev->dev,
2278a6d818e3SYunsheng Lin 			"VF sends keep alive cmd failed(=%d)\n", ret);
2279a6d818e3SYunsheng Lin }
2280a6d818e3SYunsheng Lin 
2281ff200099SYunsheng Lin static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev)
2282e2cb1decSSalil Mehta {
2283ff200099SYunsheng Lin 	unsigned long delta = round_jiffies_relative(HZ);
2284ff200099SYunsheng Lin 	struct hnae3_handle *handle = &hdev->nic;
2285e2cb1decSSalil Mehta 
2286e6394363SGuangbin Huang 	if (test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state))
2287e6394363SGuangbin Huang 		return;
2288e6394363SGuangbin Huang 
2289ff200099SYunsheng Lin 	if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) {
2290ff200099SYunsheng Lin 		delta = jiffies - hdev->last_serv_processed;
2291db01afebSliuzhongzhu 
2292ff200099SYunsheng Lin 		if (delta < round_jiffies_relative(HZ)) {
2293ff200099SYunsheng Lin 			delta = round_jiffies_relative(HZ) - delta;
2294ff200099SYunsheng Lin 			goto out;
2295db01afebSliuzhongzhu 		}
2296ff200099SYunsheng Lin 	}
2297ff200099SYunsheng Lin 
2298ff200099SYunsheng Lin 	hdev->serv_processed_cnt++;
2299ff200099SYunsheng Lin 	if (!(hdev->serv_processed_cnt % HCLGEVF_KEEP_ALIVE_TASK_INTERVAL))
2300ff200099SYunsheng Lin 		hclgevf_keep_alive(hdev);
2301ff200099SYunsheng Lin 
2302ff200099SYunsheng Lin 	if (test_bit(HCLGEVF_STATE_DOWN, &hdev->state)) {
2303ff200099SYunsheng Lin 		hdev->last_serv_processed = jiffies;
2304ff200099SYunsheng Lin 		goto out;
2305ff200099SYunsheng Lin 	}
2306ff200099SYunsheng Lin 
2307ff200099SYunsheng Lin 	if (!(hdev->serv_processed_cnt % HCLGEVF_STATS_TIMER_INTERVAL))
2308ff200099SYunsheng Lin 		hclgevf_tqps_update_stats(handle);
2309e2cb1decSSalil Mehta 
2310e2cb1decSSalil Mehta 	/* request the link status from the PF. PF would be able to tell VF
2311e2cb1decSSalil Mehta 	 * about such updates in future so we might remove this later
2312e2cb1decSSalil Mehta 	 */
2313e2cb1decSSalil Mehta 	hclgevf_request_link_info(hdev);
2314e2cb1decSSalil Mehta 
23159194d18bSliuzhongzhu 	hclgevf_update_link_mode(hdev);
23169194d18bSliuzhongzhu 
2317fe4144d4SJian Shen 	hclgevf_sync_vlan_filter(hdev);
2318fe4144d4SJian Shen 
2319ee4bcd3bSJian Shen 	hclgevf_sync_mac_table(hdev);
2320ee4bcd3bSJian Shen 
2321c631c696SJian Shen 	hclgevf_sync_promisc_mode(hdev);
2322c631c696SJian Shen 
2323ff200099SYunsheng Lin 	hdev->last_serv_processed = jiffies;
2324436667d2SSalil Mehta 
2325ff200099SYunsheng Lin out:
2326ff200099SYunsheng Lin 	hclgevf_task_schedule(hdev, delta);
2327ff200099SYunsheng Lin }
2328b3c3fe8eSYunsheng Lin 
2329ff200099SYunsheng Lin static void hclgevf_service_task(struct work_struct *work)
2330ff200099SYunsheng Lin {
2331ff200099SYunsheng Lin 	struct hclgevf_dev *hdev = container_of(work, struct hclgevf_dev,
2332ff200099SYunsheng Lin 						service_task.work);
2333ff200099SYunsheng Lin 
2334ff200099SYunsheng Lin 	hclgevf_reset_service_task(hdev);
2335ff200099SYunsheng Lin 	hclgevf_mailbox_service_task(hdev);
2336ff200099SYunsheng Lin 	hclgevf_periodic_service_task(hdev);
2337ff200099SYunsheng Lin 
2338ff200099SYunsheng Lin 	/* Handle reset and mbx again in case periodical task delays the
2339ff200099SYunsheng Lin 	 * handling by calling hclgevf_task_schedule() in
2340ff200099SYunsheng Lin 	 * hclgevf_periodic_service_task()
2341ff200099SYunsheng Lin 	 */
2342ff200099SYunsheng Lin 	hclgevf_reset_service_task(hdev);
2343ff200099SYunsheng Lin 	hclgevf_mailbox_service_task(hdev);
2344e2cb1decSSalil Mehta }
2345e2cb1decSSalil Mehta 
2346e2cb1decSSalil Mehta static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr)
2347e2cb1decSSalil Mehta {
2348e2cb1decSSalil Mehta 	hclgevf_write_dev(&hdev->hw, HCLGEVF_VECTOR0_CMDQ_SRC_REG, regclr);
2349e2cb1decSSalil Mehta }
2350e2cb1decSSalil Mehta 
2351b90fcc5bSHuazhong Tan static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
2352b90fcc5bSHuazhong Tan 						      u32 *clearval)
2353e2cb1decSSalil Mehta {
235413050921SHuazhong Tan 	u32 val, cmdq_stat_reg, rst_ing_reg;
2355e2cb1decSSalil Mehta 
2356e2cb1decSSalil Mehta 	/* fetch the events from their corresponding regs */
235713050921SHuazhong Tan 	cmdq_stat_reg = hclgevf_read_dev(&hdev->hw,
23589cee2e8dSHuazhong Tan 					 HCLGEVF_VECTOR0_CMDQ_STATE_REG);
2359e2cb1decSSalil Mehta 
236013050921SHuazhong Tan 	if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_stat_reg) {
2361b90fcc5bSHuazhong Tan 		rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
2362b90fcc5bSHuazhong Tan 		dev_info(&hdev->pdev->dev,
2363b90fcc5bSHuazhong Tan 			 "receive reset interrupt 0x%x!\n", rst_ing_reg);
2364b90fcc5bSHuazhong Tan 		set_bit(HNAE3_VF_RESET, &hdev->reset_pending);
2365b90fcc5bSHuazhong Tan 		set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
2366ef5f8e50SHuazhong Tan 		set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
236713050921SHuazhong Tan 		*clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B);
2368c88a6e7dSHuazhong Tan 		hdev->rst_stats.vf_rst_cnt++;
236972e2fb07SHuazhong Tan 		/* set up VF hardware reset status, its PF will clear
237072e2fb07SHuazhong Tan 		 * this status when PF has initialized done.
237172e2fb07SHuazhong Tan 		 */
237272e2fb07SHuazhong Tan 		val = hclgevf_read_dev(&hdev->hw, HCLGEVF_VF_RST_ING);
237372e2fb07SHuazhong Tan 		hclgevf_write_dev(&hdev->hw, HCLGEVF_VF_RST_ING,
237472e2fb07SHuazhong Tan 				  val | HCLGEVF_VF_RST_ING_BIT);
2375b90fcc5bSHuazhong Tan 		return HCLGEVF_VECTOR0_EVENT_RST;
2376b90fcc5bSHuazhong Tan 	}
2377b90fcc5bSHuazhong Tan 
2378e2cb1decSSalil Mehta 	/* check for vector0 mailbox(=CMDQ RX) event source */
237913050921SHuazhong Tan 	if (BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B) & cmdq_stat_reg) {
238013050921SHuazhong Tan 		/* for revision 0x21, clearing interrupt is writing bit 0
238113050921SHuazhong Tan 		 * to the clear register, writing bit 1 means to keep the
238213050921SHuazhong Tan 		 * old value.
238313050921SHuazhong Tan 		 * for revision 0x20, the clear register is a read & write
238413050921SHuazhong Tan 		 * register, so we should just write 0 to the bit we are
238513050921SHuazhong Tan 		 * handling, and keep other bits as cmdq_stat_reg.
238613050921SHuazhong Tan 		 */
2387295ba232SGuangbin Huang 		if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2)
238813050921SHuazhong Tan 			*clearval = ~(1U << HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
238913050921SHuazhong Tan 		else
239013050921SHuazhong Tan 			*clearval = cmdq_stat_reg &
239113050921SHuazhong Tan 				    ~BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
239213050921SHuazhong Tan 
2393b90fcc5bSHuazhong Tan 		return HCLGEVF_VECTOR0_EVENT_MBX;
2394e2cb1decSSalil Mehta 	}
2395e2cb1decSSalil Mehta 
2396e45afb39SHuazhong Tan 	/* print other vector0 event source */
2397e45afb39SHuazhong Tan 	dev_info(&hdev->pdev->dev,
2398e45afb39SHuazhong Tan 		 "vector 0 interrupt from unknown source, cmdq_src = %#x\n",
2399e45afb39SHuazhong Tan 		 cmdq_stat_reg);
2400e2cb1decSSalil Mehta 
2401b90fcc5bSHuazhong Tan 	return HCLGEVF_VECTOR0_EVENT_OTHER;
2402e2cb1decSSalil Mehta }
2403e2cb1decSSalil Mehta 
2404e2cb1decSSalil Mehta static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
2405e2cb1decSSalil Mehta {
2406b90fcc5bSHuazhong Tan 	enum hclgevf_evt_cause event_cause;
2407e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = data;
2408e2cb1decSSalil Mehta 	u32 clearval;
2409e2cb1decSSalil Mehta 
2410e2cb1decSSalil Mehta 	hclgevf_enable_vector(&hdev->misc_vector, false);
2411b90fcc5bSHuazhong Tan 	event_cause = hclgevf_check_evt_cause(hdev, &clearval);
2412e2cb1decSSalil Mehta 
2413b90fcc5bSHuazhong Tan 	switch (event_cause) {
2414b90fcc5bSHuazhong Tan 	case HCLGEVF_VECTOR0_EVENT_RST:
2415b90fcc5bSHuazhong Tan 		hclgevf_reset_task_schedule(hdev);
2416b90fcc5bSHuazhong Tan 		break;
2417b90fcc5bSHuazhong Tan 	case HCLGEVF_VECTOR0_EVENT_MBX:
241807a0556aSSalil Mehta 		hclgevf_mbx_handler(hdev);
2419b90fcc5bSHuazhong Tan 		break;
2420b90fcc5bSHuazhong Tan 	default:
2421b90fcc5bSHuazhong Tan 		break;
2422b90fcc5bSHuazhong Tan 	}
2423e2cb1decSSalil Mehta 
2424b90fcc5bSHuazhong Tan 	if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER) {
2425e2cb1decSSalil Mehta 		hclgevf_clear_event_cause(hdev, clearval);
2426e2cb1decSSalil Mehta 		hclgevf_enable_vector(&hdev->misc_vector, true);
2427b90fcc5bSHuazhong Tan 	}
2428e2cb1decSSalil Mehta 
2429e2cb1decSSalil Mehta 	return IRQ_HANDLED;
2430e2cb1decSSalil Mehta }
2431e2cb1decSSalil Mehta 
2432e2cb1decSSalil Mehta static int hclgevf_configure(struct hclgevf_dev *hdev)
2433e2cb1decSSalil Mehta {
2434e2cb1decSSalil Mehta 	int ret;
2435e2cb1decSSalil Mehta 
243692f11ea1SJian Shen 	/* get current port based vlan state from PF */
243792f11ea1SJian Shen 	ret = hclgevf_get_port_base_vlan_filter_state(hdev);
243892f11ea1SJian Shen 	if (ret)
243992f11ea1SJian Shen 		return ret;
244092f11ea1SJian Shen 
2441e2cb1decSSalil Mehta 	/* get queue configuration from PF */
24426cee6fc3SJian Shen 	ret = hclgevf_get_queue_info(hdev);
2443e2cb1decSSalil Mehta 	if (ret)
2444e2cb1decSSalil Mehta 		return ret;
2445c0425944SPeng Li 
2446c0425944SPeng Li 	/* get queue depth info from PF */
2447c0425944SPeng Li 	ret = hclgevf_get_queue_depth(hdev);
2448c0425944SPeng Li 	if (ret)
2449c0425944SPeng Li 		return ret;
2450c0425944SPeng Li 
24519c3e7130Sliuzhongzhu 	ret = hclgevf_get_pf_media_type(hdev);
24529c3e7130Sliuzhongzhu 	if (ret)
24539c3e7130Sliuzhongzhu 		return ret;
24549c3e7130Sliuzhongzhu 
2455e2cb1decSSalil Mehta 	/* get tc configuration from PF */
2456e2cb1decSSalil Mehta 	return hclgevf_get_tc_info(hdev);
2457e2cb1decSSalil Mehta }
2458e2cb1decSSalil Mehta 
24597a01c897SSalil Mehta static int hclgevf_alloc_hdev(struct hnae3_ae_dev *ae_dev)
24607a01c897SSalil Mehta {
24617a01c897SSalil Mehta 	struct pci_dev *pdev = ae_dev->pdev;
24621154bb26SPeng Li 	struct hclgevf_dev *hdev;
24637a01c897SSalil Mehta 
24647a01c897SSalil Mehta 	hdev = devm_kzalloc(&pdev->dev, sizeof(*hdev), GFP_KERNEL);
24657a01c897SSalil Mehta 	if (!hdev)
24667a01c897SSalil Mehta 		return -ENOMEM;
24677a01c897SSalil Mehta 
24687a01c897SSalil Mehta 	hdev->pdev = pdev;
24697a01c897SSalil Mehta 	hdev->ae_dev = ae_dev;
24707a01c897SSalil Mehta 	ae_dev->priv = hdev;
24717a01c897SSalil Mehta 
24727a01c897SSalil Mehta 	return 0;
24737a01c897SSalil Mehta }
24747a01c897SSalil Mehta 
2475e2cb1decSSalil Mehta static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
2476e2cb1decSSalil Mehta {
2477e2cb1decSSalil Mehta 	struct hnae3_handle *roce = &hdev->roce;
2478e2cb1decSSalil Mehta 	struct hnae3_handle *nic = &hdev->nic;
2479e2cb1decSSalil Mehta 
248007acf909SJian Shen 	roce->rinfo.num_vectors = hdev->num_roce_msix;
2481e2cb1decSSalil Mehta 
2482e2cb1decSSalil Mehta 	if (hdev->num_msi_left < roce->rinfo.num_vectors ||
2483e2cb1decSSalil Mehta 	    hdev->num_msi_left == 0)
2484e2cb1decSSalil Mehta 		return -EINVAL;
2485e2cb1decSSalil Mehta 
248607acf909SJian Shen 	roce->rinfo.base_vector = hdev->roce_base_vector;
2487e2cb1decSSalil Mehta 
2488e2cb1decSSalil Mehta 	roce->rinfo.netdev = nic->kinfo.netdev;
2489e2cb1decSSalil Mehta 	roce->rinfo.roce_io_base = hdev->hw.io_base;
249030ae7f8aSHuazhong Tan 	roce->rinfo.roce_mem_base = hdev->hw.mem_base;
2491e2cb1decSSalil Mehta 
2492e2cb1decSSalil Mehta 	roce->pdev = nic->pdev;
2493e2cb1decSSalil Mehta 	roce->ae_algo = nic->ae_algo;
2494e2cb1decSSalil Mehta 	roce->numa_node_mask = nic->numa_node_mask;
2495e2cb1decSSalil Mehta 
2496e2cb1decSSalil Mehta 	return 0;
2497e2cb1decSSalil Mehta }
2498e2cb1decSSalil Mehta 
2499b26a6feaSPeng Li static int hclgevf_config_gro(struct hclgevf_dev *hdev, bool en)
2500b26a6feaSPeng Li {
2501b26a6feaSPeng Li 	struct hclgevf_cfg_gro_status_cmd *req;
2502b26a6feaSPeng Li 	struct hclgevf_desc desc;
2503b26a6feaSPeng Li 	int ret;
2504b26a6feaSPeng Li 
2505b26a6feaSPeng Li 	if (!hnae3_dev_gro_supported(hdev))
2506b26a6feaSPeng Li 		return 0;
2507b26a6feaSPeng Li 
2508b26a6feaSPeng Li 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_GRO_GENERIC_CONFIG,
2509b26a6feaSPeng Li 				     false);
2510b26a6feaSPeng Li 	req = (struct hclgevf_cfg_gro_status_cmd *)desc.data;
2511b26a6feaSPeng Li 
2512fb9e44d6SHuazhong Tan 	req->gro_en = en ? 1 : 0;
2513b26a6feaSPeng Li 
2514b26a6feaSPeng Li 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
2515b26a6feaSPeng Li 	if (ret)
2516b26a6feaSPeng Li 		dev_err(&hdev->pdev->dev,
2517b26a6feaSPeng Li 			"VF GRO hardware config cmd failed, ret = %d.\n", ret);
2518b26a6feaSPeng Li 
2519b26a6feaSPeng Li 	return ret;
2520b26a6feaSPeng Li }
2521b26a6feaSPeng Li 
252287ce161eSGuangbin Huang static int hclgevf_rss_init_cfg(struct hclgevf_dev *hdev)
2523e2cb1decSSalil Mehta {
252487ce161eSGuangbin Huang 	u16 rss_ind_tbl_size = hdev->ae_dev->dev_specs.rss_ind_tbl_size;
2525e2cb1decSSalil Mehta 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
2526944de484SGuojia Liao 	struct hclgevf_rss_tuple_cfg *tuple_sets;
25274093d1a2SGuangbin Huang 	u32 i;
2528e2cb1decSSalil Mehta 
2529944de484SGuojia Liao 	rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
25304093d1a2SGuangbin Huang 	rss_cfg->rss_size = hdev->nic.kinfo.rss_size;
2531944de484SGuojia Liao 	tuple_sets = &rss_cfg->rss_tuple_sets;
2532295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
253387ce161eSGuangbin Huang 		u8 *rss_ind_tbl;
253487ce161eSGuangbin Huang 
2535472d7eceSJian Shen 		rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE;
253687ce161eSGuangbin Huang 
253787ce161eSGuangbin Huang 		rss_ind_tbl = devm_kcalloc(&hdev->pdev->dev, rss_ind_tbl_size,
253887ce161eSGuangbin Huang 					   sizeof(*rss_ind_tbl), GFP_KERNEL);
253987ce161eSGuangbin Huang 		if (!rss_ind_tbl)
254087ce161eSGuangbin Huang 			return -ENOMEM;
254187ce161eSGuangbin Huang 
254287ce161eSGuangbin Huang 		rss_cfg->rss_indirection_tbl = rss_ind_tbl;
2543472d7eceSJian Shen 		memcpy(rss_cfg->rss_hash_key, hclgevf_hash_key,
2544374ad291SJian Shen 		       HCLGEVF_RSS_KEY_SIZE);
2545374ad291SJian Shen 
2546944de484SGuojia Liao 		tuple_sets->ipv4_tcp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2547944de484SGuojia Liao 		tuple_sets->ipv4_udp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2548944de484SGuojia Liao 		tuple_sets->ipv4_sctp_en = HCLGEVF_RSS_INPUT_TUPLE_SCTP;
2549944de484SGuojia Liao 		tuple_sets->ipv4_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2550944de484SGuojia Liao 		tuple_sets->ipv6_tcp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2551944de484SGuojia Liao 		tuple_sets->ipv6_udp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2552ab6e32d2SJian Shen 		tuple_sets->ipv6_sctp_en =
2553ab6e32d2SJian Shen 			hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 ?
2554ab6e32d2SJian Shen 					HCLGEVF_RSS_INPUT_TUPLE_SCTP_NO_PORT :
2555ab6e32d2SJian Shen 					HCLGEVF_RSS_INPUT_TUPLE_SCTP;
2556944de484SGuojia Liao 		tuple_sets->ipv6_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2557374ad291SJian Shen 	}
2558374ad291SJian Shen 
25599b2f3477SWeihang Li 	/* Initialize RSS indirect table */
256087ce161eSGuangbin Huang 	for (i = 0; i < rss_ind_tbl_size; i++)
25614093d1a2SGuangbin Huang 		rss_cfg->rss_indirection_tbl[i] = i % rss_cfg->rss_size;
256287ce161eSGuangbin Huang 
256387ce161eSGuangbin Huang 	return 0;
2564944de484SGuojia Liao }
2565944de484SGuojia Liao 
2566944de484SGuojia Liao static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
2567944de484SGuojia Liao {
2568944de484SGuojia Liao 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
2569944de484SGuojia Liao 	int ret;
2570944de484SGuojia Liao 
2571295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
2572944de484SGuojia Liao 		ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
2573944de484SGuojia Liao 					       rss_cfg->rss_hash_key);
2574944de484SGuojia Liao 		if (ret)
2575944de484SGuojia Liao 			return ret;
2576944de484SGuojia Liao 
2577944de484SGuojia Liao 		ret = hclgevf_set_rss_input_tuple(hdev, rss_cfg);
2578944de484SGuojia Liao 		if (ret)
2579944de484SGuojia Liao 			return ret;
2580944de484SGuojia Liao 	}
2581e2cb1decSSalil Mehta 
2582e2cb1decSSalil Mehta 	ret = hclgevf_set_rss_indir_table(hdev);
2583e2cb1decSSalil Mehta 	if (ret)
2584e2cb1decSSalil Mehta 		return ret;
2585e2cb1decSSalil Mehta 
25864093d1a2SGuangbin Huang 	return hclgevf_set_rss_tc_mode(hdev, rss_cfg->rss_size);
2587e2cb1decSSalil Mehta }
2588e2cb1decSSalil Mehta 
2589e2cb1decSSalil Mehta static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev)
2590e2cb1decSSalil Mehta {
2591e2cb1decSSalil Mehta 	return hclgevf_set_vlan_filter(&hdev->nic, htons(ETH_P_8021Q), 0,
2592e2cb1decSSalil Mehta 				       false);
2593e2cb1decSSalil Mehta }
2594e2cb1decSSalil Mehta 
2595ff200099SYunsheng Lin static void hclgevf_flush_link_update(struct hclgevf_dev *hdev)
2596ff200099SYunsheng Lin {
2597ff200099SYunsheng Lin #define HCLGEVF_FLUSH_LINK_TIMEOUT	100000
2598ff200099SYunsheng Lin 
2599ff200099SYunsheng Lin 	unsigned long last = hdev->serv_processed_cnt;
2600ff200099SYunsheng Lin 	int i = 0;
2601ff200099SYunsheng Lin 
2602ff200099SYunsheng Lin 	while (test_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state) &&
2603ff200099SYunsheng Lin 	       i++ < HCLGEVF_FLUSH_LINK_TIMEOUT &&
2604ff200099SYunsheng Lin 	       last == hdev->serv_processed_cnt)
2605ff200099SYunsheng Lin 		usleep_range(1, 1);
2606ff200099SYunsheng Lin }
2607ff200099SYunsheng Lin 
26088cdb992fSJian Shen static void hclgevf_set_timer_task(struct hnae3_handle *handle, bool enable)
26098cdb992fSJian Shen {
26108cdb992fSJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
26118cdb992fSJian Shen 
26128cdb992fSJian Shen 	if (enable) {
2613ff200099SYunsheng Lin 		hclgevf_task_schedule(hdev, 0);
26148cdb992fSJian Shen 	} else {
2615b3c3fe8eSYunsheng Lin 		set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2616ff200099SYunsheng Lin 
2617ff200099SYunsheng Lin 		/* flush memory to make sure DOWN is seen by service task */
2618ff200099SYunsheng Lin 		smp_mb__before_atomic();
2619ff200099SYunsheng Lin 		hclgevf_flush_link_update(hdev);
26208cdb992fSJian Shen 	}
26218cdb992fSJian Shen }
26228cdb992fSJian Shen 
2623e2cb1decSSalil Mehta static int hclgevf_ae_start(struct hnae3_handle *handle)
2624e2cb1decSSalil Mehta {
2625e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2626e2cb1decSSalil Mehta 
2627e2cb1decSSalil Mehta 	hclgevf_reset_tqp_stats(handle);
2628e2cb1decSSalil Mehta 
2629e2cb1decSSalil Mehta 	hclgevf_request_link_info(hdev);
2630e2cb1decSSalil Mehta 
26319194d18bSliuzhongzhu 	hclgevf_update_link_mode(hdev);
26329194d18bSliuzhongzhu 
2633e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2634e2cb1decSSalil Mehta 
2635e2cb1decSSalil Mehta 	return 0;
2636e2cb1decSSalil Mehta }
2637e2cb1decSSalil Mehta 
2638e2cb1decSSalil Mehta static void hclgevf_ae_stop(struct hnae3_handle *handle)
2639e2cb1decSSalil Mehta {
2640e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
264139cfbc9cSHuazhong Tan 	int i;
2642e2cb1decSSalil Mehta 
26432f7e4896SFuyun Liang 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
26442f7e4896SFuyun Liang 
2645146e92c1SHuazhong Tan 	if (hdev->reset_type != HNAE3_VF_RESET)
264639cfbc9cSHuazhong Tan 		for (i = 0; i < handle->kinfo.num_tqps; i++)
2647146e92c1SHuazhong Tan 			if (hclgevf_reset_tqp(handle, i))
2648146e92c1SHuazhong Tan 				break;
264939cfbc9cSHuazhong Tan 
2650e2cb1decSSalil Mehta 	hclgevf_reset_tqp_stats(handle);
26518cc6c1f7SFuyun Liang 	hclgevf_update_link_status(hdev, 0);
2652e2cb1decSSalil Mehta }
2653e2cb1decSSalil Mehta 
2654a6d818e3SYunsheng Lin static int hclgevf_set_alive(struct hnae3_handle *handle, bool alive)
2655a6d818e3SYunsheng Lin {
2656d3410018SYufeng Mo #define HCLGEVF_STATE_ALIVE	1
2657d3410018SYufeng Mo #define HCLGEVF_STATE_NOT_ALIVE	0
2658a6d818e3SYunsheng Lin 
2659d3410018SYufeng Mo 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2660d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
2661d3410018SYufeng Mo 
2662d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_ALIVE, 0);
2663d3410018SYufeng Mo 	send_msg.data[0] = alive ? HCLGEVF_STATE_ALIVE :
2664d3410018SYufeng Mo 				HCLGEVF_STATE_NOT_ALIVE;
2665d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
2666a6d818e3SYunsheng Lin }
2667a6d818e3SYunsheng Lin 
2668a6d818e3SYunsheng Lin static int hclgevf_client_start(struct hnae3_handle *handle)
2669a6d818e3SYunsheng Lin {
2670f621df96SQinglang Miao 	return hclgevf_set_alive(handle, true);
2671a6d818e3SYunsheng Lin }
2672a6d818e3SYunsheng Lin 
2673a6d818e3SYunsheng Lin static void hclgevf_client_stop(struct hnae3_handle *handle)
2674a6d818e3SYunsheng Lin {
2675a6d818e3SYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2676a6d818e3SYunsheng Lin 	int ret;
2677a6d818e3SYunsheng Lin 
2678a6d818e3SYunsheng Lin 	ret = hclgevf_set_alive(handle, false);
2679a6d818e3SYunsheng Lin 	if (ret)
2680a6d818e3SYunsheng Lin 		dev_warn(&hdev->pdev->dev,
2681a6d818e3SYunsheng Lin 			 "%s failed %d\n", __func__, ret);
2682a6d818e3SYunsheng Lin }
2683a6d818e3SYunsheng Lin 
2684e2cb1decSSalil Mehta static void hclgevf_state_init(struct hclgevf_dev *hdev)
2685e2cb1decSSalil Mehta {
2686e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state);
2687e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
2688d5432455SGuojia Liao 	clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
2689e2cb1decSSalil Mehta 
2690b3c3fe8eSYunsheng Lin 	INIT_DELAYED_WORK(&hdev->service_task, hclgevf_service_task);
269135a1e503SSalil Mehta 
2692e2cb1decSSalil Mehta 	mutex_init(&hdev->mbx_resp.mbx_mutex);
2693f28368bbSHuazhong Tan 	sema_init(&hdev->reset_sem, 1);
2694e2cb1decSSalil Mehta 
2695ee4bcd3bSJian Shen 	spin_lock_init(&hdev->mac_table.mac_list_lock);
2696ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&hdev->mac_table.uc_mac_list);
2697ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&hdev->mac_table.mc_mac_list);
2698ee4bcd3bSJian Shen 
2699e2cb1decSSalil Mehta 	/* bring the device down */
2700e2cb1decSSalil Mehta 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2701e2cb1decSSalil Mehta }
2702e2cb1decSSalil Mehta 
2703e2cb1decSSalil Mehta static void hclgevf_state_uninit(struct hclgevf_dev *hdev)
2704e2cb1decSSalil Mehta {
2705e2cb1decSSalil Mehta 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2706acfc3d55SHuazhong Tan 	set_bit(HCLGEVF_STATE_REMOVING, &hdev->state);
2707e2cb1decSSalil Mehta 
2708b3c3fe8eSYunsheng Lin 	if (hdev->service_task.work.func)
2709b3c3fe8eSYunsheng Lin 		cancel_delayed_work_sync(&hdev->service_task);
2710e2cb1decSSalil Mehta 
2711e2cb1decSSalil Mehta 	mutex_destroy(&hdev->mbx_resp.mbx_mutex);
2712e2cb1decSSalil Mehta }
2713e2cb1decSSalil Mehta 
2714e2cb1decSSalil Mehta static int hclgevf_init_msi(struct hclgevf_dev *hdev)
2715e2cb1decSSalil Mehta {
2716e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
2717e2cb1decSSalil Mehta 	int vectors;
2718e2cb1decSSalil Mehta 	int i;
2719e2cb1decSSalil Mehta 
2720580a05f9SYonglong Liu 	if (hnae3_dev_roce_supported(hdev))
272107acf909SJian Shen 		vectors = pci_alloc_irq_vectors(pdev,
272207acf909SJian Shen 						hdev->roce_base_msix_offset + 1,
272307acf909SJian Shen 						hdev->num_msi,
272407acf909SJian Shen 						PCI_IRQ_MSIX);
272507acf909SJian Shen 	else
2726580a05f9SYonglong Liu 		vectors = pci_alloc_irq_vectors(pdev, HNAE3_MIN_VECTOR_NUM,
2727580a05f9SYonglong Liu 						hdev->num_msi,
2728e2cb1decSSalil Mehta 						PCI_IRQ_MSI | PCI_IRQ_MSIX);
272907acf909SJian Shen 
2730e2cb1decSSalil Mehta 	if (vectors < 0) {
2731e2cb1decSSalil Mehta 		dev_err(&pdev->dev,
2732e2cb1decSSalil Mehta 			"failed(%d) to allocate MSI/MSI-X vectors\n",
2733e2cb1decSSalil Mehta 			vectors);
2734e2cb1decSSalil Mehta 		return vectors;
2735e2cb1decSSalil Mehta 	}
2736e2cb1decSSalil Mehta 	if (vectors < hdev->num_msi)
2737e2cb1decSSalil Mehta 		dev_warn(&hdev->pdev->dev,
2738adcf738bSGuojia Liao 			 "requested %u MSI/MSI-X, but allocated %d MSI/MSI-X\n",
2739e2cb1decSSalil Mehta 			 hdev->num_msi, vectors);
2740e2cb1decSSalil Mehta 
2741e2cb1decSSalil Mehta 	hdev->num_msi = vectors;
2742e2cb1decSSalil Mehta 	hdev->num_msi_left = vectors;
2743580a05f9SYonglong Liu 
2744e2cb1decSSalil Mehta 	hdev->base_msi_vector = pdev->irq;
274507acf909SJian Shen 	hdev->roce_base_vector = pdev->irq + hdev->roce_base_msix_offset;
2746e2cb1decSSalil Mehta 
2747e2cb1decSSalil Mehta 	hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi,
2748e2cb1decSSalil Mehta 					   sizeof(u16), GFP_KERNEL);
2749e2cb1decSSalil Mehta 	if (!hdev->vector_status) {
2750e2cb1decSSalil Mehta 		pci_free_irq_vectors(pdev);
2751e2cb1decSSalil Mehta 		return -ENOMEM;
2752e2cb1decSSalil Mehta 	}
2753e2cb1decSSalil Mehta 
2754e2cb1decSSalil Mehta 	for (i = 0; i < hdev->num_msi; i++)
2755e2cb1decSSalil Mehta 		hdev->vector_status[i] = HCLGEVF_INVALID_VPORT;
2756e2cb1decSSalil Mehta 
2757e2cb1decSSalil Mehta 	hdev->vector_irq = devm_kcalloc(&pdev->dev, hdev->num_msi,
2758e2cb1decSSalil Mehta 					sizeof(int), GFP_KERNEL);
2759e2cb1decSSalil Mehta 	if (!hdev->vector_irq) {
2760862d969aSHuazhong Tan 		devm_kfree(&pdev->dev, hdev->vector_status);
2761e2cb1decSSalil Mehta 		pci_free_irq_vectors(pdev);
2762e2cb1decSSalil Mehta 		return -ENOMEM;
2763e2cb1decSSalil Mehta 	}
2764e2cb1decSSalil Mehta 
2765e2cb1decSSalil Mehta 	return 0;
2766e2cb1decSSalil Mehta }
2767e2cb1decSSalil Mehta 
2768e2cb1decSSalil Mehta static void hclgevf_uninit_msi(struct hclgevf_dev *hdev)
2769e2cb1decSSalil Mehta {
2770e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
2771e2cb1decSSalil Mehta 
2772862d969aSHuazhong Tan 	devm_kfree(&pdev->dev, hdev->vector_status);
2773862d969aSHuazhong Tan 	devm_kfree(&pdev->dev, hdev->vector_irq);
2774e2cb1decSSalil Mehta 	pci_free_irq_vectors(pdev);
2775e2cb1decSSalil Mehta }
2776e2cb1decSSalil Mehta 
2777e2cb1decSSalil Mehta static int hclgevf_misc_irq_init(struct hclgevf_dev *hdev)
2778e2cb1decSSalil Mehta {
2779cdd332acSGuojia Liao 	int ret;
2780e2cb1decSSalil Mehta 
2781e2cb1decSSalil Mehta 	hclgevf_get_misc_vector(hdev);
2782e2cb1decSSalil Mehta 
2783f97c4d82SYonglong Liu 	snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s",
2784f97c4d82SYonglong Liu 		 HCLGEVF_NAME, pci_name(hdev->pdev));
2785e2cb1decSSalil Mehta 	ret = request_irq(hdev->misc_vector.vector_irq, hclgevf_misc_irq_handle,
2786f97c4d82SYonglong Liu 			  0, hdev->misc_vector.name, hdev);
2787e2cb1decSSalil Mehta 	if (ret) {
2788e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev, "VF failed to request misc irq(%d)\n",
2789e2cb1decSSalil Mehta 			hdev->misc_vector.vector_irq);
2790e2cb1decSSalil Mehta 		return ret;
2791e2cb1decSSalil Mehta 	}
2792e2cb1decSSalil Mehta 
27931819e409SXi Wang 	hclgevf_clear_event_cause(hdev, 0);
27941819e409SXi Wang 
2795e2cb1decSSalil Mehta 	/* enable misc. vector(vector 0) */
2796e2cb1decSSalil Mehta 	hclgevf_enable_vector(&hdev->misc_vector, true);
2797e2cb1decSSalil Mehta 
2798e2cb1decSSalil Mehta 	return ret;
2799e2cb1decSSalil Mehta }
2800e2cb1decSSalil Mehta 
2801e2cb1decSSalil Mehta static void hclgevf_misc_irq_uninit(struct hclgevf_dev *hdev)
2802e2cb1decSSalil Mehta {
2803e2cb1decSSalil Mehta 	/* disable misc vector(vector 0) */
2804e2cb1decSSalil Mehta 	hclgevf_enable_vector(&hdev->misc_vector, false);
28051819e409SXi Wang 	synchronize_irq(hdev->misc_vector.vector_irq);
2806e2cb1decSSalil Mehta 	free_irq(hdev->misc_vector.vector_irq, hdev);
2807e2cb1decSSalil Mehta 	hclgevf_free_vector(hdev, 0);
2808e2cb1decSSalil Mehta }
2809e2cb1decSSalil Mehta 
2810bb87be87SYonglong Liu static void hclgevf_info_show(struct hclgevf_dev *hdev)
2811bb87be87SYonglong Liu {
2812bb87be87SYonglong Liu 	struct device *dev = &hdev->pdev->dev;
2813bb87be87SYonglong Liu 
2814bb87be87SYonglong Liu 	dev_info(dev, "VF info begin:\n");
2815bb87be87SYonglong Liu 
2816adcf738bSGuojia Liao 	dev_info(dev, "Task queue pairs numbers: %u\n", hdev->num_tqps);
2817adcf738bSGuojia Liao 	dev_info(dev, "Desc num per TX queue: %u\n", hdev->num_tx_desc);
2818adcf738bSGuojia Liao 	dev_info(dev, "Desc num per RX queue: %u\n", hdev->num_rx_desc);
2819adcf738bSGuojia Liao 	dev_info(dev, "Numbers of vports: %u\n", hdev->num_alloc_vport);
2820adcf738bSGuojia Liao 	dev_info(dev, "HW tc map: 0x%x\n", hdev->hw_tc_map);
2821adcf738bSGuojia Liao 	dev_info(dev, "PF media type of this VF: %u\n",
2822bb87be87SYonglong Liu 		 hdev->hw.mac.media_type);
2823bb87be87SYonglong Liu 
2824bb87be87SYonglong Liu 	dev_info(dev, "VF info end.\n");
2825bb87be87SYonglong Liu }
2826bb87be87SYonglong Liu 
28271db58f86SHuazhong Tan static int hclgevf_init_nic_client_instance(struct hnae3_ae_dev *ae_dev,
28281db58f86SHuazhong Tan 					    struct hnae3_client *client)
28291db58f86SHuazhong Tan {
28301db58f86SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
28314cd5beaaSGuangbin Huang 	int rst_cnt = hdev->rst_stats.rst_cnt;
28321db58f86SHuazhong Tan 	int ret;
28331db58f86SHuazhong Tan 
28341db58f86SHuazhong Tan 	ret = client->ops->init_instance(&hdev->nic);
28351db58f86SHuazhong Tan 	if (ret)
28361db58f86SHuazhong Tan 		return ret;
28371db58f86SHuazhong Tan 
28381db58f86SHuazhong Tan 	set_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
28394cd5beaaSGuangbin Huang 	if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
28404cd5beaaSGuangbin Huang 	    rst_cnt != hdev->rst_stats.rst_cnt) {
28414cd5beaaSGuangbin Huang 		clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
28424cd5beaaSGuangbin Huang 
28434cd5beaaSGuangbin Huang 		client->ops->uninit_instance(&hdev->nic, 0);
28444cd5beaaSGuangbin Huang 		return -EBUSY;
28454cd5beaaSGuangbin Huang 	}
28464cd5beaaSGuangbin Huang 
28471db58f86SHuazhong Tan 	hnae3_set_client_init_flag(client, ae_dev, 1);
28481db58f86SHuazhong Tan 
28491db58f86SHuazhong Tan 	if (netif_msg_drv(&hdev->nic))
28501db58f86SHuazhong Tan 		hclgevf_info_show(hdev);
28511db58f86SHuazhong Tan 
28521db58f86SHuazhong Tan 	return 0;
28531db58f86SHuazhong Tan }
28541db58f86SHuazhong Tan 
28551db58f86SHuazhong Tan static int hclgevf_init_roce_client_instance(struct hnae3_ae_dev *ae_dev,
28561db58f86SHuazhong Tan 					     struct hnae3_client *client)
28571db58f86SHuazhong Tan {
28581db58f86SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
28591db58f86SHuazhong Tan 	int ret;
28601db58f86SHuazhong Tan 
28611db58f86SHuazhong Tan 	if (!hnae3_dev_roce_supported(hdev) || !hdev->roce_client ||
28621db58f86SHuazhong Tan 	    !hdev->nic_client)
28631db58f86SHuazhong Tan 		return 0;
28641db58f86SHuazhong Tan 
28651db58f86SHuazhong Tan 	ret = hclgevf_init_roce_base_info(hdev);
28661db58f86SHuazhong Tan 	if (ret)
28671db58f86SHuazhong Tan 		return ret;
28681db58f86SHuazhong Tan 
28691db58f86SHuazhong Tan 	ret = client->ops->init_instance(&hdev->roce);
28701db58f86SHuazhong Tan 	if (ret)
28711db58f86SHuazhong Tan 		return ret;
28721db58f86SHuazhong Tan 
2873fe735c84SHuazhong Tan 	set_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state);
28741db58f86SHuazhong Tan 	hnae3_set_client_init_flag(client, ae_dev, 1);
28751db58f86SHuazhong Tan 
28761db58f86SHuazhong Tan 	return 0;
28771db58f86SHuazhong Tan }
28781db58f86SHuazhong Tan 
2879e718a93fSPeng Li static int hclgevf_init_client_instance(struct hnae3_client *client,
2880e718a93fSPeng Li 					struct hnae3_ae_dev *ae_dev)
2881e2cb1decSSalil Mehta {
2882e718a93fSPeng Li 	struct hclgevf_dev *hdev = ae_dev->priv;
2883e2cb1decSSalil Mehta 	int ret;
2884e2cb1decSSalil Mehta 
2885e2cb1decSSalil Mehta 	switch (client->type) {
2886e2cb1decSSalil Mehta 	case HNAE3_CLIENT_KNIC:
2887e2cb1decSSalil Mehta 		hdev->nic_client = client;
2888e2cb1decSSalil Mehta 		hdev->nic.client = client;
2889e2cb1decSSalil Mehta 
28901db58f86SHuazhong Tan 		ret = hclgevf_init_nic_client_instance(ae_dev, client);
2891e2cb1decSSalil Mehta 		if (ret)
289249dd8054SJian Shen 			goto clear_nic;
2893e2cb1decSSalil Mehta 
28941db58f86SHuazhong Tan 		ret = hclgevf_init_roce_client_instance(ae_dev,
28951db58f86SHuazhong Tan 							hdev->roce_client);
2896e2cb1decSSalil Mehta 		if (ret)
289749dd8054SJian Shen 			goto clear_roce;
2898d9f28fc2SJian Shen 
2899e2cb1decSSalil Mehta 		break;
2900e2cb1decSSalil Mehta 	case HNAE3_CLIENT_ROCE:
2901544a7bcdSLijun Ou 		if (hnae3_dev_roce_supported(hdev)) {
2902e2cb1decSSalil Mehta 			hdev->roce_client = client;
2903e2cb1decSSalil Mehta 			hdev->roce.client = client;
2904544a7bcdSLijun Ou 		}
2905e2cb1decSSalil Mehta 
29061db58f86SHuazhong Tan 		ret = hclgevf_init_roce_client_instance(ae_dev, client);
2907e2cb1decSSalil Mehta 		if (ret)
290849dd8054SJian Shen 			goto clear_roce;
2909e2cb1decSSalil Mehta 
2910fa7a4bd5SJian Shen 		break;
2911fa7a4bd5SJian Shen 	default:
2912fa7a4bd5SJian Shen 		return -EINVAL;
2913e2cb1decSSalil Mehta 	}
2914e2cb1decSSalil Mehta 
2915e2cb1decSSalil Mehta 	return 0;
291649dd8054SJian Shen 
291749dd8054SJian Shen clear_nic:
291849dd8054SJian Shen 	hdev->nic_client = NULL;
291949dd8054SJian Shen 	hdev->nic.client = NULL;
292049dd8054SJian Shen 	return ret;
292149dd8054SJian Shen clear_roce:
292249dd8054SJian Shen 	hdev->roce_client = NULL;
292349dd8054SJian Shen 	hdev->roce.client = NULL;
292449dd8054SJian Shen 	return ret;
2925e2cb1decSSalil Mehta }
2926e2cb1decSSalil Mehta 
2927e718a93fSPeng Li static void hclgevf_uninit_client_instance(struct hnae3_client *client,
2928e718a93fSPeng Li 					   struct hnae3_ae_dev *ae_dev)
2929e2cb1decSSalil Mehta {
2930e718a93fSPeng Li 	struct hclgevf_dev *hdev = ae_dev->priv;
2931e718a93fSPeng Li 
2932e2cb1decSSalil Mehta 	/* un-init roce, if it exists */
293349dd8054SJian Shen 	if (hdev->roce_client) {
2934fe735c84SHuazhong Tan 		clear_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state);
2935e2cb1decSSalil Mehta 		hdev->roce_client->ops->uninit_instance(&hdev->roce, 0);
293649dd8054SJian Shen 		hdev->roce_client = NULL;
293749dd8054SJian Shen 		hdev->roce.client = NULL;
293849dd8054SJian Shen 	}
2939e2cb1decSSalil Mehta 
2940e2cb1decSSalil Mehta 	/* un-init nic/unic, if this was not called by roce client */
294149dd8054SJian Shen 	if (client->ops->uninit_instance && hdev->nic_client &&
294249dd8054SJian Shen 	    client->type != HNAE3_CLIENT_ROCE) {
294325d1817cSHuazhong Tan 		clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
294425d1817cSHuazhong Tan 
2945e2cb1decSSalil Mehta 		client->ops->uninit_instance(&hdev->nic, 0);
294649dd8054SJian Shen 		hdev->nic_client = NULL;
294749dd8054SJian Shen 		hdev->nic.client = NULL;
294849dd8054SJian Shen 	}
2949e2cb1decSSalil Mehta }
2950e2cb1decSSalil Mehta 
295130ae7f8aSHuazhong Tan static int hclgevf_dev_mem_map(struct hclgevf_dev *hdev)
295230ae7f8aSHuazhong Tan {
295330ae7f8aSHuazhong Tan #define HCLGEVF_MEM_BAR		4
295430ae7f8aSHuazhong Tan 
295530ae7f8aSHuazhong Tan 	struct pci_dev *pdev = hdev->pdev;
295630ae7f8aSHuazhong Tan 	struct hclgevf_hw *hw = &hdev->hw;
295730ae7f8aSHuazhong Tan 
295830ae7f8aSHuazhong Tan 	/* for device does not have device memory, return directly */
295930ae7f8aSHuazhong Tan 	if (!(pci_select_bars(pdev, IORESOURCE_MEM) & BIT(HCLGEVF_MEM_BAR)))
296030ae7f8aSHuazhong Tan 		return 0;
296130ae7f8aSHuazhong Tan 
296230ae7f8aSHuazhong Tan 	hw->mem_base = devm_ioremap_wc(&pdev->dev,
296330ae7f8aSHuazhong Tan 				       pci_resource_start(pdev,
296430ae7f8aSHuazhong Tan 							  HCLGEVF_MEM_BAR),
296530ae7f8aSHuazhong Tan 				       pci_resource_len(pdev, HCLGEVF_MEM_BAR));
296630ae7f8aSHuazhong Tan 	if (!hw->mem_base) {
2967be419fcaSColin Ian King 		dev_err(&pdev->dev, "failed to map device memory\n");
296830ae7f8aSHuazhong Tan 		return -EFAULT;
296930ae7f8aSHuazhong Tan 	}
297030ae7f8aSHuazhong Tan 
297130ae7f8aSHuazhong Tan 	return 0;
297230ae7f8aSHuazhong Tan }
297330ae7f8aSHuazhong Tan 
2974e2cb1decSSalil Mehta static int hclgevf_pci_init(struct hclgevf_dev *hdev)
2975e2cb1decSSalil Mehta {
2976e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
2977e2cb1decSSalil Mehta 	struct hclgevf_hw *hw;
2978e2cb1decSSalil Mehta 	int ret;
2979e2cb1decSSalil Mehta 
2980e2cb1decSSalil Mehta 	ret = pci_enable_device(pdev);
2981e2cb1decSSalil Mehta 	if (ret) {
2982e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "failed to enable PCI device\n");
29833e249d3bSFuyun Liang 		return ret;
2984e2cb1decSSalil Mehta 	}
2985e2cb1decSSalil Mehta 
2986e2cb1decSSalil Mehta 	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
2987e2cb1decSSalil Mehta 	if (ret) {
2988e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "can't set consistent PCI DMA, exiting");
2989e2cb1decSSalil Mehta 		goto err_disable_device;
2990e2cb1decSSalil Mehta 	}
2991e2cb1decSSalil Mehta 
2992e2cb1decSSalil Mehta 	ret = pci_request_regions(pdev, HCLGEVF_DRIVER_NAME);
2993e2cb1decSSalil Mehta 	if (ret) {
2994e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "PCI request regions failed %d\n", ret);
2995e2cb1decSSalil Mehta 		goto err_disable_device;
2996e2cb1decSSalil Mehta 	}
2997e2cb1decSSalil Mehta 
2998e2cb1decSSalil Mehta 	pci_set_master(pdev);
2999e2cb1decSSalil Mehta 	hw = &hdev->hw;
3000e2cb1decSSalil Mehta 	hw->hdev = hdev;
30012e1ea493SPeng Li 	hw->io_base = pci_iomap(pdev, 2, 0);
3002e2cb1decSSalil Mehta 	if (!hw->io_base) {
3003e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "can't map configuration register space\n");
3004e2cb1decSSalil Mehta 		ret = -ENOMEM;
3005e2cb1decSSalil Mehta 		goto err_clr_master;
3006e2cb1decSSalil Mehta 	}
3007e2cb1decSSalil Mehta 
300830ae7f8aSHuazhong Tan 	ret = hclgevf_dev_mem_map(hdev);
300930ae7f8aSHuazhong Tan 	if (ret)
301030ae7f8aSHuazhong Tan 		goto err_unmap_io_base;
301130ae7f8aSHuazhong Tan 
3012e2cb1decSSalil Mehta 	return 0;
3013e2cb1decSSalil Mehta 
301430ae7f8aSHuazhong Tan err_unmap_io_base:
301530ae7f8aSHuazhong Tan 	pci_iounmap(pdev, hdev->hw.io_base);
3016e2cb1decSSalil Mehta err_clr_master:
3017e2cb1decSSalil Mehta 	pci_clear_master(pdev);
3018e2cb1decSSalil Mehta 	pci_release_regions(pdev);
3019e2cb1decSSalil Mehta err_disable_device:
3020e2cb1decSSalil Mehta 	pci_disable_device(pdev);
30213e249d3bSFuyun Liang 
3022e2cb1decSSalil Mehta 	return ret;
3023e2cb1decSSalil Mehta }
3024e2cb1decSSalil Mehta 
3025e2cb1decSSalil Mehta static void hclgevf_pci_uninit(struct hclgevf_dev *hdev)
3026e2cb1decSSalil Mehta {
3027e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
3028e2cb1decSSalil Mehta 
302930ae7f8aSHuazhong Tan 	if (hdev->hw.mem_base)
303030ae7f8aSHuazhong Tan 		devm_iounmap(&pdev->dev, hdev->hw.mem_base);
303130ae7f8aSHuazhong Tan 
3032e2cb1decSSalil Mehta 	pci_iounmap(pdev, hdev->hw.io_base);
3033e2cb1decSSalil Mehta 	pci_clear_master(pdev);
3034e2cb1decSSalil Mehta 	pci_release_regions(pdev);
3035e2cb1decSSalil Mehta 	pci_disable_device(pdev);
3036e2cb1decSSalil Mehta }
3037e2cb1decSSalil Mehta 
303807acf909SJian Shen static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev)
303907acf909SJian Shen {
304007acf909SJian Shen 	struct hclgevf_query_res_cmd *req;
304107acf909SJian Shen 	struct hclgevf_desc desc;
304207acf909SJian Shen 	int ret;
304307acf909SJian Shen 
304407acf909SJian Shen 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_QUERY_VF_RSRC, true);
304507acf909SJian Shen 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
304607acf909SJian Shen 	if (ret) {
304707acf909SJian Shen 		dev_err(&hdev->pdev->dev,
304807acf909SJian Shen 			"query vf resource failed, ret = %d.\n", ret);
304907acf909SJian Shen 		return ret;
305007acf909SJian Shen 	}
305107acf909SJian Shen 
305207acf909SJian Shen 	req = (struct hclgevf_query_res_cmd *)desc.data;
305307acf909SJian Shen 
3054580a05f9SYonglong Liu 	if (hnae3_dev_roce_supported(hdev)) {
305507acf909SJian Shen 		hdev->roce_base_msix_offset =
305660df7e91SHuazhong Tan 		hnae3_get_field(le16_to_cpu(req->msixcap_localid_ba_rocee),
305707acf909SJian Shen 				HCLGEVF_MSIX_OFT_ROCEE_M,
305807acf909SJian Shen 				HCLGEVF_MSIX_OFT_ROCEE_S);
305907acf909SJian Shen 		hdev->num_roce_msix =
306060df7e91SHuazhong Tan 		hnae3_get_field(le16_to_cpu(req->vf_intr_vector_number),
306107acf909SJian Shen 				HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
306207acf909SJian Shen 
3063580a05f9SYonglong Liu 		/* nic's msix numbers is always equals to the roce's. */
3064580a05f9SYonglong Liu 		hdev->num_nic_msix = hdev->num_roce_msix;
3065580a05f9SYonglong Liu 
306607acf909SJian Shen 		/* VF should have NIC vectors and Roce vectors, NIC vectors
306707acf909SJian Shen 		 * are queued before Roce vectors. The offset is fixed to 64.
306807acf909SJian Shen 		 */
306907acf909SJian Shen 		hdev->num_msi = hdev->num_roce_msix +
307007acf909SJian Shen 				hdev->roce_base_msix_offset;
307107acf909SJian Shen 	} else {
307207acf909SJian Shen 		hdev->num_msi =
307360df7e91SHuazhong Tan 		hnae3_get_field(le16_to_cpu(req->vf_intr_vector_number),
307407acf909SJian Shen 				HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
3075580a05f9SYonglong Liu 
3076580a05f9SYonglong Liu 		hdev->num_nic_msix = hdev->num_msi;
3077580a05f9SYonglong Liu 	}
3078580a05f9SYonglong Liu 
3079580a05f9SYonglong Liu 	if (hdev->num_nic_msix < HNAE3_MIN_VECTOR_NUM) {
3080580a05f9SYonglong Liu 		dev_err(&hdev->pdev->dev,
3081580a05f9SYonglong Liu 			"Just %u msi resources, not enough for vf(min:2).\n",
3082580a05f9SYonglong Liu 			hdev->num_nic_msix);
3083580a05f9SYonglong Liu 		return -EINVAL;
308407acf909SJian Shen 	}
308507acf909SJian Shen 
308607acf909SJian Shen 	return 0;
308707acf909SJian Shen }
308807acf909SJian Shen 
3089af2aedc5SGuangbin Huang static void hclgevf_set_default_dev_specs(struct hclgevf_dev *hdev)
3090af2aedc5SGuangbin Huang {
3091af2aedc5SGuangbin Huang #define HCLGEVF_MAX_NON_TSO_BD_NUM			8U
3092af2aedc5SGuangbin Huang 
3093af2aedc5SGuangbin Huang 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
3094af2aedc5SGuangbin Huang 
3095af2aedc5SGuangbin Huang 	ae_dev->dev_specs.max_non_tso_bd_num =
3096af2aedc5SGuangbin Huang 					HCLGEVF_MAX_NON_TSO_BD_NUM;
3097af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_ind_tbl_size = HCLGEVF_RSS_IND_TBL_SIZE;
3098af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_key_size = HCLGEVF_RSS_KEY_SIZE;
3099ab16b49cSHuazhong Tan 	ae_dev->dev_specs.max_int_gl = HCLGEVF_DEF_MAX_INT_GL;
3100e070c8b9SYufeng Mo 	ae_dev->dev_specs.max_frm_size = HCLGEVF_MAC_MAX_FRAME;
3101af2aedc5SGuangbin Huang }
3102af2aedc5SGuangbin Huang 
3103af2aedc5SGuangbin Huang static void hclgevf_parse_dev_specs(struct hclgevf_dev *hdev,
3104af2aedc5SGuangbin Huang 				    struct hclgevf_desc *desc)
3105af2aedc5SGuangbin Huang {
3106af2aedc5SGuangbin Huang 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
3107af2aedc5SGuangbin Huang 	struct hclgevf_dev_specs_0_cmd *req0;
3108ab16b49cSHuazhong Tan 	struct hclgevf_dev_specs_1_cmd *req1;
3109af2aedc5SGuangbin Huang 
3110af2aedc5SGuangbin Huang 	req0 = (struct hclgevf_dev_specs_0_cmd *)desc[0].data;
3111ab16b49cSHuazhong Tan 	req1 = (struct hclgevf_dev_specs_1_cmd *)desc[1].data;
3112af2aedc5SGuangbin Huang 
3113af2aedc5SGuangbin Huang 	ae_dev->dev_specs.max_non_tso_bd_num = req0->max_non_tso_bd_num;
3114af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_ind_tbl_size =
3115af2aedc5SGuangbin Huang 					le16_to_cpu(req0->rss_ind_tbl_size);
311691bfae25SHuazhong Tan 	ae_dev->dev_specs.int_ql_max = le16_to_cpu(req0->int_ql_max);
3117af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size);
3118ab16b49cSHuazhong Tan 	ae_dev->dev_specs.max_int_gl = le16_to_cpu(req1->max_int_gl);
3119e070c8b9SYufeng Mo 	ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size);
3120af2aedc5SGuangbin Huang }
3121af2aedc5SGuangbin Huang 
312213297028SGuangbin Huang static void hclgevf_check_dev_specs(struct hclgevf_dev *hdev)
312313297028SGuangbin Huang {
312413297028SGuangbin Huang 	struct hnae3_dev_specs *dev_specs = &hdev->ae_dev->dev_specs;
312513297028SGuangbin Huang 
312613297028SGuangbin Huang 	if (!dev_specs->max_non_tso_bd_num)
312713297028SGuangbin Huang 		dev_specs->max_non_tso_bd_num = HCLGEVF_MAX_NON_TSO_BD_NUM;
312813297028SGuangbin Huang 	if (!dev_specs->rss_ind_tbl_size)
312913297028SGuangbin Huang 		dev_specs->rss_ind_tbl_size = HCLGEVF_RSS_IND_TBL_SIZE;
313013297028SGuangbin Huang 	if (!dev_specs->rss_key_size)
313113297028SGuangbin Huang 		dev_specs->rss_key_size = HCLGEVF_RSS_KEY_SIZE;
3132ab16b49cSHuazhong Tan 	if (!dev_specs->max_int_gl)
3133ab16b49cSHuazhong Tan 		dev_specs->max_int_gl = HCLGEVF_DEF_MAX_INT_GL;
3134e070c8b9SYufeng Mo 	if (!dev_specs->max_frm_size)
3135e070c8b9SYufeng Mo 		dev_specs->max_frm_size = HCLGEVF_MAC_MAX_FRAME;
313613297028SGuangbin Huang }
313713297028SGuangbin Huang 
3138af2aedc5SGuangbin Huang static int hclgevf_query_dev_specs(struct hclgevf_dev *hdev)
3139af2aedc5SGuangbin Huang {
3140af2aedc5SGuangbin Huang 	struct hclgevf_desc desc[HCLGEVF_QUERY_DEV_SPECS_BD_NUM];
3141af2aedc5SGuangbin Huang 	int ret;
3142af2aedc5SGuangbin Huang 	int i;
3143af2aedc5SGuangbin Huang 
3144af2aedc5SGuangbin Huang 	/* set default specifications as devices lower than version V3 do not
3145af2aedc5SGuangbin Huang 	 * support querying specifications from firmware.
3146af2aedc5SGuangbin Huang 	 */
3147af2aedc5SGuangbin Huang 	if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) {
3148af2aedc5SGuangbin Huang 		hclgevf_set_default_dev_specs(hdev);
3149af2aedc5SGuangbin Huang 		return 0;
3150af2aedc5SGuangbin Huang 	}
3151af2aedc5SGuangbin Huang 
3152af2aedc5SGuangbin Huang 	for (i = 0; i < HCLGEVF_QUERY_DEV_SPECS_BD_NUM - 1; i++) {
3153af2aedc5SGuangbin Huang 		hclgevf_cmd_setup_basic_desc(&desc[i],
3154af2aedc5SGuangbin Huang 					     HCLGEVF_OPC_QUERY_DEV_SPECS, true);
3155af2aedc5SGuangbin Huang 		desc[i].flag |= cpu_to_le16(HCLGEVF_CMD_FLAG_NEXT);
3156af2aedc5SGuangbin Huang 	}
3157af2aedc5SGuangbin Huang 	hclgevf_cmd_setup_basic_desc(&desc[i], HCLGEVF_OPC_QUERY_DEV_SPECS,
3158af2aedc5SGuangbin Huang 				     true);
3159af2aedc5SGuangbin Huang 
3160af2aedc5SGuangbin Huang 	ret = hclgevf_cmd_send(&hdev->hw, desc, HCLGEVF_QUERY_DEV_SPECS_BD_NUM);
3161af2aedc5SGuangbin Huang 	if (ret)
3162af2aedc5SGuangbin Huang 		return ret;
3163af2aedc5SGuangbin Huang 
3164af2aedc5SGuangbin Huang 	hclgevf_parse_dev_specs(hdev, desc);
316513297028SGuangbin Huang 	hclgevf_check_dev_specs(hdev);
3166af2aedc5SGuangbin Huang 
3167af2aedc5SGuangbin Huang 	return 0;
3168af2aedc5SGuangbin Huang }
3169af2aedc5SGuangbin Huang 
3170862d969aSHuazhong Tan static int hclgevf_pci_reset(struct hclgevf_dev *hdev)
3171862d969aSHuazhong Tan {
3172862d969aSHuazhong Tan 	struct pci_dev *pdev = hdev->pdev;
3173862d969aSHuazhong Tan 	int ret = 0;
3174862d969aSHuazhong Tan 
3175862d969aSHuazhong Tan 	if (hdev->reset_type == HNAE3_VF_FULL_RESET &&
3176862d969aSHuazhong Tan 	    test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
3177862d969aSHuazhong Tan 		hclgevf_misc_irq_uninit(hdev);
3178862d969aSHuazhong Tan 		hclgevf_uninit_msi(hdev);
3179862d969aSHuazhong Tan 		clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3180862d969aSHuazhong Tan 	}
3181862d969aSHuazhong Tan 
3182862d969aSHuazhong Tan 	if (!test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
3183862d969aSHuazhong Tan 		pci_set_master(pdev);
3184862d969aSHuazhong Tan 		ret = hclgevf_init_msi(hdev);
3185862d969aSHuazhong Tan 		if (ret) {
3186862d969aSHuazhong Tan 			dev_err(&pdev->dev,
3187862d969aSHuazhong Tan 				"failed(%d) to init MSI/MSI-X\n", ret);
3188862d969aSHuazhong Tan 			return ret;
3189862d969aSHuazhong Tan 		}
3190862d969aSHuazhong Tan 
3191862d969aSHuazhong Tan 		ret = hclgevf_misc_irq_init(hdev);
3192862d969aSHuazhong Tan 		if (ret) {
3193862d969aSHuazhong Tan 			hclgevf_uninit_msi(hdev);
3194862d969aSHuazhong Tan 			dev_err(&pdev->dev, "failed(%d) to init Misc IRQ(vector0)\n",
3195862d969aSHuazhong Tan 				ret);
3196862d969aSHuazhong Tan 			return ret;
3197862d969aSHuazhong Tan 		}
3198862d969aSHuazhong Tan 
3199862d969aSHuazhong Tan 		set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3200862d969aSHuazhong Tan 	}
3201862d969aSHuazhong Tan 
3202862d969aSHuazhong Tan 	return ret;
3203862d969aSHuazhong Tan }
3204862d969aSHuazhong Tan 
3205039ba863SJian Shen static int hclgevf_clear_vport_list(struct hclgevf_dev *hdev)
3206039ba863SJian Shen {
3207039ba863SJian Shen 	struct hclge_vf_to_pf_msg send_msg;
3208039ba863SJian Shen 
3209039ba863SJian Shen 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_HANDLE_VF_TBL,
3210039ba863SJian Shen 			       HCLGE_MBX_VPORT_LIST_CLEAR);
3211039ba863SJian Shen 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
3212039ba863SJian Shen }
3213039ba863SJian Shen 
32149c6f7085SHuazhong Tan static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
3215e2cb1decSSalil Mehta {
32167a01c897SSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
3217e2cb1decSSalil Mehta 	int ret;
3218e2cb1decSSalil Mehta 
3219862d969aSHuazhong Tan 	ret = hclgevf_pci_reset(hdev);
3220862d969aSHuazhong Tan 	if (ret) {
3221862d969aSHuazhong Tan 		dev_err(&pdev->dev, "pci reset failed %d\n", ret);
3222862d969aSHuazhong Tan 		return ret;
3223862d969aSHuazhong Tan 	}
3224862d969aSHuazhong Tan 
32259c6f7085SHuazhong Tan 	ret = hclgevf_cmd_init(hdev);
32269c6f7085SHuazhong Tan 	if (ret) {
32279c6f7085SHuazhong Tan 		dev_err(&pdev->dev, "cmd failed %d\n", ret);
32289c6f7085SHuazhong Tan 		return ret;
32297a01c897SSalil Mehta 	}
3230e2cb1decSSalil Mehta 
32319c6f7085SHuazhong Tan 	ret = hclgevf_rss_init_hw(hdev);
32329c6f7085SHuazhong Tan 	if (ret) {
32339c6f7085SHuazhong Tan 		dev_err(&hdev->pdev->dev,
32349c6f7085SHuazhong Tan 			"failed(%d) to initialize RSS\n", ret);
32359c6f7085SHuazhong Tan 		return ret;
32369c6f7085SHuazhong Tan 	}
32379c6f7085SHuazhong Tan 
3238b26a6feaSPeng Li 	ret = hclgevf_config_gro(hdev, true);
3239b26a6feaSPeng Li 	if (ret)
3240b26a6feaSPeng Li 		return ret;
3241b26a6feaSPeng Li 
32429c6f7085SHuazhong Tan 	ret = hclgevf_init_vlan_config(hdev);
32439c6f7085SHuazhong Tan 	if (ret) {
32449c6f7085SHuazhong Tan 		dev_err(&hdev->pdev->dev,
32459c6f7085SHuazhong Tan 			"failed(%d) to initialize VLAN config\n", ret);
32469c6f7085SHuazhong Tan 		return ret;
32479c6f7085SHuazhong Tan 	}
32489c6f7085SHuazhong Tan 
3249c631c696SJian Shen 	set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
3250c631c696SJian Shen 
32519c6f7085SHuazhong Tan 	dev_info(&hdev->pdev->dev, "Reset done\n");
32529c6f7085SHuazhong Tan 
32539c6f7085SHuazhong Tan 	return 0;
32549c6f7085SHuazhong Tan }
32559c6f7085SHuazhong Tan 
32569c6f7085SHuazhong Tan static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
32579c6f7085SHuazhong Tan {
32589c6f7085SHuazhong Tan 	struct pci_dev *pdev = hdev->pdev;
32599c6f7085SHuazhong Tan 	int ret;
32609c6f7085SHuazhong Tan 
3261e2cb1decSSalil Mehta 	ret = hclgevf_pci_init(hdev);
326260df7e91SHuazhong Tan 	if (ret)
3263e2cb1decSSalil Mehta 		return ret;
3264e2cb1decSSalil Mehta 
32658b0195a3SHuazhong Tan 	ret = hclgevf_cmd_queue_init(hdev);
326660df7e91SHuazhong Tan 	if (ret)
32678b0195a3SHuazhong Tan 		goto err_cmd_queue_init;
32688b0195a3SHuazhong Tan 
3269eddf0462SYunsheng Lin 	ret = hclgevf_cmd_init(hdev);
3270eddf0462SYunsheng Lin 	if (ret)
3271eddf0462SYunsheng Lin 		goto err_cmd_init;
3272eddf0462SYunsheng Lin 
327307acf909SJian Shen 	/* Get vf resource */
327407acf909SJian Shen 	ret = hclgevf_query_vf_resource(hdev);
327560df7e91SHuazhong Tan 	if (ret)
32768b0195a3SHuazhong Tan 		goto err_cmd_init;
327707acf909SJian Shen 
3278af2aedc5SGuangbin Huang 	ret = hclgevf_query_dev_specs(hdev);
3279af2aedc5SGuangbin Huang 	if (ret) {
3280af2aedc5SGuangbin Huang 		dev_err(&pdev->dev,
3281af2aedc5SGuangbin Huang 			"failed to query dev specifications, ret = %d\n", ret);
3282af2aedc5SGuangbin Huang 		goto err_cmd_init;
3283af2aedc5SGuangbin Huang 	}
3284af2aedc5SGuangbin Huang 
328507acf909SJian Shen 	ret = hclgevf_init_msi(hdev);
328607acf909SJian Shen 	if (ret) {
328707acf909SJian Shen 		dev_err(&pdev->dev, "failed(%d) to init MSI/MSI-X\n", ret);
32888b0195a3SHuazhong Tan 		goto err_cmd_init;
328907acf909SJian Shen 	}
329007acf909SJian Shen 
329107acf909SJian Shen 	hclgevf_state_init(hdev);
3292dea846e8SHuazhong Tan 	hdev->reset_level = HNAE3_VF_FUNC_RESET;
3293afb6afdbSHuazhong Tan 	hdev->reset_type = HNAE3_NONE_RESET;
329407acf909SJian Shen 
3295e2cb1decSSalil Mehta 	ret = hclgevf_misc_irq_init(hdev);
329660df7e91SHuazhong Tan 	if (ret)
3297e2cb1decSSalil Mehta 		goto err_misc_irq_init;
3298e2cb1decSSalil Mehta 
3299862d969aSHuazhong Tan 	set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3300862d969aSHuazhong Tan 
3301e2cb1decSSalil Mehta 	ret = hclgevf_configure(hdev);
3302e2cb1decSSalil Mehta 	if (ret) {
3303e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "failed(%d) to fetch configuration\n", ret);
3304e2cb1decSSalil Mehta 		goto err_config;
3305e2cb1decSSalil Mehta 	}
3306e2cb1decSSalil Mehta 
3307e2cb1decSSalil Mehta 	ret = hclgevf_alloc_tqps(hdev);
3308e2cb1decSSalil Mehta 	if (ret) {
3309e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "failed(%d) to allocate TQPs\n", ret);
3310e2cb1decSSalil Mehta 		goto err_config;
3311e2cb1decSSalil Mehta 	}
3312e2cb1decSSalil Mehta 
3313e2cb1decSSalil Mehta 	ret = hclgevf_set_handle_info(hdev);
331460df7e91SHuazhong Tan 	if (ret)
3315e2cb1decSSalil Mehta 		goto err_config;
3316e2cb1decSSalil Mehta 
3317b26a6feaSPeng Li 	ret = hclgevf_config_gro(hdev, true);
3318b26a6feaSPeng Li 	if (ret)
3319b26a6feaSPeng Li 		goto err_config;
3320b26a6feaSPeng Li 
3321e2cb1decSSalil Mehta 	/* Initialize RSS for this VF */
332287ce161eSGuangbin Huang 	ret = hclgevf_rss_init_cfg(hdev);
332387ce161eSGuangbin Huang 	if (ret) {
332487ce161eSGuangbin Huang 		dev_err(&pdev->dev, "failed to init rss cfg, ret = %d\n", ret);
332587ce161eSGuangbin Huang 		goto err_config;
332687ce161eSGuangbin Huang 	}
332787ce161eSGuangbin Huang 
3328e2cb1decSSalil Mehta 	ret = hclgevf_rss_init_hw(hdev);
3329e2cb1decSSalil Mehta 	if (ret) {
3330e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
3331e2cb1decSSalil Mehta 			"failed(%d) to initialize RSS\n", ret);
3332e2cb1decSSalil Mehta 		goto err_config;
3333e2cb1decSSalil Mehta 	}
3334e2cb1decSSalil Mehta 
3335039ba863SJian Shen 	/* ensure vf tbl list as empty before init*/
3336039ba863SJian Shen 	ret = hclgevf_clear_vport_list(hdev);
3337039ba863SJian Shen 	if (ret) {
3338039ba863SJian Shen 		dev_err(&pdev->dev,
3339039ba863SJian Shen 			"failed to clear tbl list configuration, ret = %d.\n",
3340039ba863SJian Shen 			ret);
3341039ba863SJian Shen 		goto err_config;
3342039ba863SJian Shen 	}
3343039ba863SJian Shen 
3344e2cb1decSSalil Mehta 	ret = hclgevf_init_vlan_config(hdev);
3345e2cb1decSSalil Mehta 	if (ret) {
3346e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
3347e2cb1decSSalil Mehta 			"failed(%d) to initialize VLAN config\n", ret);
3348e2cb1decSSalil Mehta 		goto err_config;
3349e2cb1decSSalil Mehta 	}
3350e2cb1decSSalil Mehta 
33510742ed7cSHuazhong Tan 	hdev->last_reset_time = jiffies;
335208d80a4cSHuazhong Tan 	dev_info(&hdev->pdev->dev, "finished initializing %s driver\n",
335308d80a4cSHuazhong Tan 		 HCLGEVF_DRIVER_NAME);
3354e2cb1decSSalil Mehta 
3355ff200099SYunsheng Lin 	hclgevf_task_schedule(hdev, round_jiffies_relative(HZ));
3356ff200099SYunsheng Lin 
3357e2cb1decSSalil Mehta 	return 0;
3358e2cb1decSSalil Mehta 
3359e2cb1decSSalil Mehta err_config:
3360e2cb1decSSalil Mehta 	hclgevf_misc_irq_uninit(hdev);
3361e2cb1decSSalil Mehta err_misc_irq_init:
3362e2cb1decSSalil Mehta 	hclgevf_state_uninit(hdev);
3363e2cb1decSSalil Mehta 	hclgevf_uninit_msi(hdev);
336407acf909SJian Shen err_cmd_init:
33658b0195a3SHuazhong Tan 	hclgevf_cmd_uninit(hdev);
33668b0195a3SHuazhong Tan err_cmd_queue_init:
3367e2cb1decSSalil Mehta 	hclgevf_pci_uninit(hdev);
3368862d969aSHuazhong Tan 	clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3369e2cb1decSSalil Mehta 	return ret;
3370e2cb1decSSalil Mehta }
3371e2cb1decSSalil Mehta 
33727a01c897SSalil Mehta static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
3373e2cb1decSSalil Mehta {
3374d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
3375d3410018SYufeng Mo 
3376e2cb1decSSalil Mehta 	hclgevf_state_uninit(hdev);
3377862d969aSHuazhong Tan 
3378d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_VF_UNINIT, 0);
3379d3410018SYufeng Mo 	hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
338023b4201dSJian Shen 
3381862d969aSHuazhong Tan 	if (test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
3382eddf0462SYunsheng Lin 		hclgevf_misc_irq_uninit(hdev);
3383e2cb1decSSalil Mehta 		hclgevf_uninit_msi(hdev);
33847a01c897SSalil Mehta 	}
33857a01c897SSalil Mehta 
3386862d969aSHuazhong Tan 	hclgevf_cmd_uninit(hdev);
3387e3364c5fSZenghui Yu 	hclgevf_pci_uninit(hdev);
3388ee4bcd3bSJian Shen 	hclgevf_uninit_mac_list(hdev);
3389862d969aSHuazhong Tan }
3390862d969aSHuazhong Tan 
33917a01c897SSalil Mehta static int hclgevf_init_ae_dev(struct hnae3_ae_dev *ae_dev)
33927a01c897SSalil Mehta {
33937a01c897SSalil Mehta 	struct pci_dev *pdev = ae_dev->pdev;
33947a01c897SSalil Mehta 	int ret;
33957a01c897SSalil Mehta 
33967a01c897SSalil Mehta 	ret = hclgevf_alloc_hdev(ae_dev);
33977a01c897SSalil Mehta 	if (ret) {
33987a01c897SSalil Mehta 		dev_err(&pdev->dev, "hclge device allocation failed\n");
33997a01c897SSalil Mehta 		return ret;
34007a01c897SSalil Mehta 	}
34017a01c897SSalil Mehta 
34027a01c897SSalil Mehta 	ret = hclgevf_init_hdev(ae_dev->priv);
3403a6d818e3SYunsheng Lin 	if (ret) {
34047a01c897SSalil Mehta 		dev_err(&pdev->dev, "hclge device initialization failed\n");
34057a01c897SSalil Mehta 		return ret;
34067a01c897SSalil Mehta 	}
34077a01c897SSalil Mehta 
3408a6d818e3SYunsheng Lin 	return 0;
3409a6d818e3SYunsheng Lin }
3410a6d818e3SYunsheng Lin 
34117a01c897SSalil Mehta static void hclgevf_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
34127a01c897SSalil Mehta {
34137a01c897SSalil Mehta 	struct hclgevf_dev *hdev = ae_dev->priv;
34147a01c897SSalil Mehta 
34157a01c897SSalil Mehta 	hclgevf_uninit_hdev(hdev);
3416e2cb1decSSalil Mehta 	ae_dev->priv = NULL;
3417e2cb1decSSalil Mehta }
3418e2cb1decSSalil Mehta 
3419849e4607SPeng Li static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev)
3420849e4607SPeng Li {
3421849e4607SPeng Li 	struct hnae3_handle *nic = &hdev->nic;
3422849e4607SPeng Li 	struct hnae3_knic_private_info *kinfo = &nic->kinfo;
3423849e4607SPeng Li 
34248be73621SHuazhong Tan 	return min_t(u32, hdev->rss_size_max,
342535244430SJian Shen 		     hdev->num_tqps / kinfo->tc_info.num_tc);
3426849e4607SPeng Li }
3427849e4607SPeng Li 
3428849e4607SPeng Li /**
3429849e4607SPeng Li  * hclgevf_get_channels - Get the current channels enabled and max supported.
3430849e4607SPeng Li  * @handle: hardware information for network interface
3431849e4607SPeng Li  * @ch: ethtool channels structure
3432849e4607SPeng Li  *
3433849e4607SPeng Li  * We don't support separate tx and rx queues as channels. The other count
3434849e4607SPeng Li  * represents how many queues are being used for control. max_combined counts
3435849e4607SPeng Li  * how many queue pairs we can support. They may not be mapped 1 to 1 with
3436849e4607SPeng Li  * q_vectors since we support a lot more queue pairs than q_vectors.
3437849e4607SPeng Li  **/
3438849e4607SPeng Li static void hclgevf_get_channels(struct hnae3_handle *handle,
3439849e4607SPeng Li 				 struct ethtool_channels *ch)
3440849e4607SPeng Li {
3441849e4607SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3442849e4607SPeng Li 
3443849e4607SPeng Li 	ch->max_combined = hclgevf_get_max_channels(hdev);
3444849e4607SPeng Li 	ch->other_count = 0;
3445849e4607SPeng Li 	ch->max_other = 0;
34468be73621SHuazhong Tan 	ch->combined_count = handle->kinfo.rss_size;
3447849e4607SPeng Li }
3448849e4607SPeng Li 
3449cc719218SPeng Li static void hclgevf_get_tqps_and_rss_info(struct hnae3_handle *handle,
34500d43bf45SHuazhong Tan 					  u16 *alloc_tqps, u16 *max_rss_size)
3451cc719218SPeng Li {
3452cc719218SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3453cc719218SPeng Li 
34540d43bf45SHuazhong Tan 	*alloc_tqps = hdev->num_tqps;
3455cc719218SPeng Li 	*max_rss_size = hdev->rss_size_max;
3456cc719218SPeng Li }
3457cc719218SPeng Li 
34584093d1a2SGuangbin Huang static void hclgevf_update_rss_size(struct hnae3_handle *handle,
34594093d1a2SGuangbin Huang 				    u32 new_tqps_num)
34604093d1a2SGuangbin Huang {
34614093d1a2SGuangbin Huang 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
34624093d1a2SGuangbin Huang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
34634093d1a2SGuangbin Huang 	u16 max_rss_size;
34644093d1a2SGuangbin Huang 
34654093d1a2SGuangbin Huang 	kinfo->req_rss_size = new_tqps_num;
34664093d1a2SGuangbin Huang 
34674093d1a2SGuangbin Huang 	max_rss_size = min_t(u16, hdev->rss_size_max,
346835244430SJian Shen 			     hdev->num_tqps / kinfo->tc_info.num_tc);
34694093d1a2SGuangbin Huang 
34704093d1a2SGuangbin Huang 	/* Use the user's configuration when it is not larger than
34714093d1a2SGuangbin Huang 	 * max_rss_size, otherwise, use the maximum specification value.
34724093d1a2SGuangbin Huang 	 */
34734093d1a2SGuangbin Huang 	if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
34744093d1a2SGuangbin Huang 	    kinfo->req_rss_size <= max_rss_size)
34754093d1a2SGuangbin Huang 		kinfo->rss_size = kinfo->req_rss_size;
34764093d1a2SGuangbin Huang 	else if (kinfo->rss_size > max_rss_size ||
34774093d1a2SGuangbin Huang 		 (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size))
34784093d1a2SGuangbin Huang 		kinfo->rss_size = max_rss_size;
34794093d1a2SGuangbin Huang 
348035244430SJian Shen 	kinfo->num_tqps = kinfo->tc_info.num_tc * kinfo->rss_size;
34814093d1a2SGuangbin Huang }
34824093d1a2SGuangbin Huang 
34834093d1a2SGuangbin Huang static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
34844093d1a2SGuangbin Huang 				bool rxfh_configured)
34854093d1a2SGuangbin Huang {
34864093d1a2SGuangbin Huang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
34874093d1a2SGuangbin Huang 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
34884093d1a2SGuangbin Huang 	u16 cur_rss_size = kinfo->rss_size;
34894093d1a2SGuangbin Huang 	u16 cur_tqps = kinfo->num_tqps;
34904093d1a2SGuangbin Huang 	u32 *rss_indir;
34914093d1a2SGuangbin Huang 	unsigned int i;
34924093d1a2SGuangbin Huang 	int ret;
34934093d1a2SGuangbin Huang 
34944093d1a2SGuangbin Huang 	hclgevf_update_rss_size(handle, new_tqps_num);
34954093d1a2SGuangbin Huang 
34964093d1a2SGuangbin Huang 	ret = hclgevf_set_rss_tc_mode(hdev, kinfo->rss_size);
34974093d1a2SGuangbin Huang 	if (ret)
34984093d1a2SGuangbin Huang 		return ret;
34994093d1a2SGuangbin Huang 
35004093d1a2SGuangbin Huang 	/* RSS indirection table has been configuared by user */
35014093d1a2SGuangbin Huang 	if (rxfh_configured)
35024093d1a2SGuangbin Huang 		goto out;
35034093d1a2SGuangbin Huang 
35044093d1a2SGuangbin Huang 	/* Reinitializes the rss indirect table according to the new RSS size */
350587ce161eSGuangbin Huang 	rss_indir = kcalloc(hdev->ae_dev->dev_specs.rss_ind_tbl_size,
350687ce161eSGuangbin Huang 			    sizeof(u32), GFP_KERNEL);
35074093d1a2SGuangbin Huang 	if (!rss_indir)
35084093d1a2SGuangbin Huang 		return -ENOMEM;
35094093d1a2SGuangbin Huang 
351087ce161eSGuangbin Huang 	for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++)
35114093d1a2SGuangbin Huang 		rss_indir[i] = i % kinfo->rss_size;
35124093d1a2SGuangbin Huang 
3513944de484SGuojia Liao 	hdev->rss_cfg.rss_size = kinfo->rss_size;
3514944de484SGuojia Liao 
35154093d1a2SGuangbin Huang 	ret = hclgevf_set_rss(handle, rss_indir, NULL, 0);
35164093d1a2SGuangbin Huang 	if (ret)
35174093d1a2SGuangbin Huang 		dev_err(&hdev->pdev->dev, "set rss indir table fail, ret=%d\n",
35184093d1a2SGuangbin Huang 			ret);
35194093d1a2SGuangbin Huang 
35204093d1a2SGuangbin Huang 	kfree(rss_indir);
35214093d1a2SGuangbin Huang 
35224093d1a2SGuangbin Huang out:
35234093d1a2SGuangbin Huang 	if (!ret)
35244093d1a2SGuangbin Huang 		dev_info(&hdev->pdev->dev,
35254093d1a2SGuangbin Huang 			 "Channels changed, rss_size from %u to %u, tqps from %u to %u",
35264093d1a2SGuangbin Huang 			 cur_rss_size, kinfo->rss_size,
352735244430SJian Shen 			 cur_tqps, kinfo->rss_size * kinfo->tc_info.num_tc);
35284093d1a2SGuangbin Huang 
35294093d1a2SGuangbin Huang 	return ret;
35304093d1a2SGuangbin Huang }
35314093d1a2SGuangbin Huang 
3532175ec96bSFuyun Liang static int hclgevf_get_status(struct hnae3_handle *handle)
3533175ec96bSFuyun Liang {
3534175ec96bSFuyun Liang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3535175ec96bSFuyun Liang 
3536175ec96bSFuyun Liang 	return hdev->hw.mac.link;
3537175ec96bSFuyun Liang }
3538175ec96bSFuyun Liang 
35394a152de9SFuyun Liang static void hclgevf_get_ksettings_an_result(struct hnae3_handle *handle,
35404a152de9SFuyun Liang 					    u8 *auto_neg, u32 *speed,
35414a152de9SFuyun Liang 					    u8 *duplex)
35424a152de9SFuyun Liang {
35434a152de9SFuyun Liang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35444a152de9SFuyun Liang 
35454a152de9SFuyun Liang 	if (speed)
35464a152de9SFuyun Liang 		*speed = hdev->hw.mac.speed;
35474a152de9SFuyun Liang 	if (duplex)
35484a152de9SFuyun Liang 		*duplex = hdev->hw.mac.duplex;
35494a152de9SFuyun Liang 	if (auto_neg)
35504a152de9SFuyun Liang 		*auto_neg = AUTONEG_DISABLE;
35514a152de9SFuyun Liang }
35524a152de9SFuyun Liang 
35534a152de9SFuyun Liang void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed,
35544a152de9SFuyun Liang 				 u8 duplex)
35554a152de9SFuyun Liang {
35564a152de9SFuyun Liang 	hdev->hw.mac.speed = speed;
35574a152de9SFuyun Liang 	hdev->hw.mac.duplex = duplex;
35584a152de9SFuyun Liang }
35594a152de9SFuyun Liang 
35601731be4cSYonglong Liu static int hclgevf_gro_en(struct hnae3_handle *handle, bool enable)
35615c9f6b39SPeng Li {
35625c9f6b39SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35635c9f6b39SPeng Li 
35645c9f6b39SPeng Li 	return hclgevf_config_gro(hdev, enable);
35655c9f6b39SPeng Li }
35665c9f6b39SPeng Li 
356788d10bd6SJian Shen static void hclgevf_get_media_type(struct hnae3_handle *handle, u8 *media_type,
356888d10bd6SJian Shen 				   u8 *module_type)
3569c136b884SPeng Li {
3570c136b884SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
357188d10bd6SJian Shen 
3572c136b884SPeng Li 	if (media_type)
3573c136b884SPeng Li 		*media_type = hdev->hw.mac.media_type;
357488d10bd6SJian Shen 
357588d10bd6SJian Shen 	if (module_type)
357688d10bd6SJian Shen 		*module_type = hdev->hw.mac.module_type;
3577c136b884SPeng Li }
3578c136b884SPeng Li 
35794d60291bSHuazhong Tan static bool hclgevf_get_hw_reset_stat(struct hnae3_handle *handle)
35804d60291bSHuazhong Tan {
35814d60291bSHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35824d60291bSHuazhong Tan 
3583aa5c4f17SHuazhong Tan 	return !!hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
35844d60291bSHuazhong Tan }
35854d60291bSHuazhong Tan 
3586fe735c84SHuazhong Tan static bool hclgevf_get_cmdq_stat(struct hnae3_handle *handle)
3587fe735c84SHuazhong Tan {
3588fe735c84SHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3589fe735c84SHuazhong Tan 
3590fe735c84SHuazhong Tan 	return test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
3591fe735c84SHuazhong Tan }
3592fe735c84SHuazhong Tan 
35934d60291bSHuazhong Tan static bool hclgevf_ae_dev_resetting(struct hnae3_handle *handle)
35944d60291bSHuazhong Tan {
35954d60291bSHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35964d60291bSHuazhong Tan 
35974d60291bSHuazhong Tan 	return test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
35984d60291bSHuazhong Tan }
35994d60291bSHuazhong Tan 
36004d60291bSHuazhong Tan static unsigned long hclgevf_ae_dev_reset_cnt(struct hnae3_handle *handle)
36014d60291bSHuazhong Tan {
36024d60291bSHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
36034d60291bSHuazhong Tan 
3604c88a6e7dSHuazhong Tan 	return hdev->rst_stats.hw_rst_done_cnt;
36054d60291bSHuazhong Tan }
36064d60291bSHuazhong Tan 
36079194d18bSliuzhongzhu static void hclgevf_get_link_mode(struct hnae3_handle *handle,
36089194d18bSliuzhongzhu 				  unsigned long *supported,
36099194d18bSliuzhongzhu 				  unsigned long *advertising)
36109194d18bSliuzhongzhu {
36119194d18bSliuzhongzhu 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
36129194d18bSliuzhongzhu 
36139194d18bSliuzhongzhu 	*supported = hdev->hw.mac.supported;
36149194d18bSliuzhongzhu 	*advertising = hdev->hw.mac.advertising;
36159194d18bSliuzhongzhu }
36169194d18bSliuzhongzhu 
36171600c3e5SJian Shen #define MAX_SEPARATE_NUM	4
36181600c3e5SJian Shen #define SEPARATOR_VALUE		0xFFFFFFFF
36191600c3e5SJian Shen #define REG_NUM_PER_LINE	4
36201600c3e5SJian Shen #define REG_LEN_PER_LINE	(REG_NUM_PER_LINE * sizeof(u32))
36211600c3e5SJian Shen 
36221600c3e5SJian Shen static int hclgevf_get_regs_len(struct hnae3_handle *handle)
36231600c3e5SJian Shen {
36241600c3e5SJian Shen 	int cmdq_lines, common_lines, ring_lines, tqp_intr_lines;
36251600c3e5SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
36261600c3e5SJian Shen 
36271600c3e5SJian Shen 	cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1;
36281600c3e5SJian Shen 	common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1;
36291600c3e5SJian Shen 	ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1;
36301600c3e5SJian Shen 	tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1;
36311600c3e5SJian Shen 
36321600c3e5SJian Shen 	return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps +
36331600c3e5SJian Shen 		tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE;
36341600c3e5SJian Shen }
36351600c3e5SJian Shen 
36361600c3e5SJian Shen static void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
36371600c3e5SJian Shen 			     void *data)
36381600c3e5SJian Shen {
36391600c3e5SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
36401600c3e5SJian Shen 	int i, j, reg_um, separator_num;
36411600c3e5SJian Shen 	u32 *reg = data;
36421600c3e5SJian Shen 
36431600c3e5SJian Shen 	*version = hdev->fw_version;
36441600c3e5SJian Shen 
36451600c3e5SJian Shen 	/* fetching per-VF registers values from VF PCIe register space */
36461600c3e5SJian Shen 	reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32);
36471600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36481600c3e5SJian Shen 	for (i = 0; i < reg_um; i++)
36491600c3e5SJian Shen 		*reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]);
36501600c3e5SJian Shen 	for (i = 0; i < separator_num; i++)
36511600c3e5SJian Shen 		*reg++ = SEPARATOR_VALUE;
36521600c3e5SJian Shen 
36531600c3e5SJian Shen 	reg_um = sizeof(common_reg_addr_list) / sizeof(u32);
36541600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36551600c3e5SJian Shen 	for (i = 0; i < reg_um; i++)
36561600c3e5SJian Shen 		*reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]);
36571600c3e5SJian Shen 	for (i = 0; i < separator_num; i++)
36581600c3e5SJian Shen 		*reg++ = SEPARATOR_VALUE;
36591600c3e5SJian Shen 
36601600c3e5SJian Shen 	reg_um = sizeof(ring_reg_addr_list) / sizeof(u32);
36611600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36621600c3e5SJian Shen 	for (j = 0; j < hdev->num_tqps; j++) {
36631600c3e5SJian Shen 		for (i = 0; i < reg_um; i++)
36641600c3e5SJian Shen 			*reg++ = hclgevf_read_dev(&hdev->hw,
36651600c3e5SJian Shen 						  ring_reg_addr_list[i] +
36661600c3e5SJian Shen 						  0x200 * j);
36671600c3e5SJian Shen 		for (i = 0; i < separator_num; i++)
36681600c3e5SJian Shen 			*reg++ = SEPARATOR_VALUE;
36691600c3e5SJian Shen 	}
36701600c3e5SJian Shen 
36711600c3e5SJian Shen 	reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32);
36721600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36731600c3e5SJian Shen 	for (j = 0; j < hdev->num_msi_used - 1; j++) {
36741600c3e5SJian Shen 		for (i = 0; i < reg_um; i++)
36751600c3e5SJian Shen 			*reg++ = hclgevf_read_dev(&hdev->hw,
36761600c3e5SJian Shen 						  tqp_intr_reg_addr_list[i] +
36771600c3e5SJian Shen 						  4 * j);
36781600c3e5SJian Shen 		for (i = 0; i < separator_num; i++)
36791600c3e5SJian Shen 			*reg++ = SEPARATOR_VALUE;
36801600c3e5SJian Shen 	}
36811600c3e5SJian Shen }
36821600c3e5SJian Shen 
368392f11ea1SJian Shen void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
368492f11ea1SJian Shen 					u8 *port_base_vlan_info, u8 data_size)
368592f11ea1SJian Shen {
368692f11ea1SJian Shen 	struct hnae3_handle *nic = &hdev->nic;
3687d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
3688a6f7bfdcSJian Shen 	int ret;
368992f11ea1SJian Shen 
369092f11ea1SJian Shen 	rtnl_lock();
3691a6f7bfdcSJian Shen 
3692b7b5d25bSGuojia Liao 	if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
3693b7b5d25bSGuojia Liao 	    test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) {
3694a6f7bfdcSJian Shen 		dev_warn(&hdev->pdev->dev,
3695a6f7bfdcSJian Shen 			 "is resetting when updating port based vlan info\n");
369692f11ea1SJian Shen 		rtnl_unlock();
3697a6f7bfdcSJian Shen 		return;
3698a6f7bfdcSJian Shen 	}
3699a6f7bfdcSJian Shen 
3700a6f7bfdcSJian Shen 	ret = hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
3701a6f7bfdcSJian Shen 	if (ret) {
3702a6f7bfdcSJian Shen 		rtnl_unlock();
3703a6f7bfdcSJian Shen 		return;
3704a6f7bfdcSJian Shen 	}
370592f11ea1SJian Shen 
370692f11ea1SJian Shen 	/* send msg to PF and wait update port based vlan info */
3707d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
3708d3410018SYufeng Mo 			       HCLGE_MBX_PORT_BASE_VLAN_CFG);
3709d3410018SYufeng Mo 	memcpy(send_msg.data, port_base_vlan_info, data_size);
3710a6f7bfdcSJian Shen 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
3711a6f7bfdcSJian Shen 	if (!ret) {
371292f11ea1SJian Shen 		if (state == HNAE3_PORT_BASE_VLAN_DISABLE)
3713a6f7bfdcSJian Shen 			nic->port_base_vlan_state = state;
371492f11ea1SJian Shen 		else
371592f11ea1SJian Shen 			nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
3716a6f7bfdcSJian Shen 	}
371792f11ea1SJian Shen 
371892f11ea1SJian Shen 	hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
371992f11ea1SJian Shen 	rtnl_unlock();
372092f11ea1SJian Shen }
372192f11ea1SJian Shen 
3722e2cb1decSSalil Mehta static const struct hnae3_ae_ops hclgevf_ops = {
3723e2cb1decSSalil Mehta 	.init_ae_dev = hclgevf_init_ae_dev,
3724e2cb1decSSalil Mehta 	.uninit_ae_dev = hclgevf_uninit_ae_dev,
37256ff3cf07SHuazhong Tan 	.flr_prepare = hclgevf_flr_prepare,
37266ff3cf07SHuazhong Tan 	.flr_done = hclgevf_flr_done,
3727e718a93fSPeng Li 	.init_client_instance = hclgevf_init_client_instance,
3728e718a93fSPeng Li 	.uninit_client_instance = hclgevf_uninit_client_instance,
3729e2cb1decSSalil Mehta 	.start = hclgevf_ae_start,
3730e2cb1decSSalil Mehta 	.stop = hclgevf_ae_stop,
3731a6d818e3SYunsheng Lin 	.client_start = hclgevf_client_start,
3732a6d818e3SYunsheng Lin 	.client_stop = hclgevf_client_stop,
3733e2cb1decSSalil Mehta 	.map_ring_to_vector = hclgevf_map_ring_to_vector,
3734e2cb1decSSalil Mehta 	.unmap_ring_from_vector = hclgevf_unmap_ring_from_vector,
3735e2cb1decSSalil Mehta 	.get_vector = hclgevf_get_vector,
37360d3e6631SYunsheng Lin 	.put_vector = hclgevf_put_vector,
3737e2cb1decSSalil Mehta 	.reset_queue = hclgevf_reset_tqp,
3738e2cb1decSSalil Mehta 	.get_mac_addr = hclgevf_get_mac_addr,
3739e2cb1decSSalil Mehta 	.set_mac_addr = hclgevf_set_mac_addr,
3740e2cb1decSSalil Mehta 	.add_uc_addr = hclgevf_add_uc_addr,
3741e2cb1decSSalil Mehta 	.rm_uc_addr = hclgevf_rm_uc_addr,
3742e2cb1decSSalil Mehta 	.add_mc_addr = hclgevf_add_mc_addr,
3743e2cb1decSSalil Mehta 	.rm_mc_addr = hclgevf_rm_mc_addr,
3744e2cb1decSSalil Mehta 	.get_stats = hclgevf_get_stats,
3745e2cb1decSSalil Mehta 	.update_stats = hclgevf_update_stats,
3746e2cb1decSSalil Mehta 	.get_strings = hclgevf_get_strings,
3747e2cb1decSSalil Mehta 	.get_sset_count = hclgevf_get_sset_count,
3748e2cb1decSSalil Mehta 	.get_rss_key_size = hclgevf_get_rss_key_size,
3749e2cb1decSSalil Mehta 	.get_rss = hclgevf_get_rss,
3750e2cb1decSSalil Mehta 	.set_rss = hclgevf_set_rss,
3751d97b3072SJian Shen 	.get_rss_tuple = hclgevf_get_rss_tuple,
3752d97b3072SJian Shen 	.set_rss_tuple = hclgevf_set_rss_tuple,
3753e2cb1decSSalil Mehta 	.get_tc_size = hclgevf_get_tc_size,
3754e2cb1decSSalil Mehta 	.get_fw_version = hclgevf_get_fw_version,
3755e2cb1decSSalil Mehta 	.set_vlan_filter = hclgevf_set_vlan_filter,
3756b2641e2aSYunsheng Lin 	.enable_hw_strip_rxvtag = hclgevf_en_hw_strip_rxvtag,
37576d4c3981SSalil Mehta 	.reset_event = hclgevf_reset_event,
3758720bd583SHuazhong Tan 	.set_default_reset_request = hclgevf_set_def_reset_request,
37594093d1a2SGuangbin Huang 	.set_channels = hclgevf_set_channels,
3760849e4607SPeng Li 	.get_channels = hclgevf_get_channels,
3761cc719218SPeng Li 	.get_tqps_and_rss_info = hclgevf_get_tqps_and_rss_info,
37621600c3e5SJian Shen 	.get_regs_len = hclgevf_get_regs_len,
37631600c3e5SJian Shen 	.get_regs = hclgevf_get_regs,
3764175ec96bSFuyun Liang 	.get_status = hclgevf_get_status,
37654a152de9SFuyun Liang 	.get_ksettings_an_result = hclgevf_get_ksettings_an_result,
3766c136b884SPeng Li 	.get_media_type = hclgevf_get_media_type,
37674d60291bSHuazhong Tan 	.get_hw_reset_stat = hclgevf_get_hw_reset_stat,
37684d60291bSHuazhong Tan 	.ae_dev_resetting = hclgevf_ae_dev_resetting,
37694d60291bSHuazhong Tan 	.ae_dev_reset_cnt = hclgevf_ae_dev_reset_cnt,
37705c9f6b39SPeng Li 	.set_gro_en = hclgevf_gro_en,
3771818f1675SYunsheng Lin 	.set_mtu = hclgevf_set_mtu,
37720c29d191Sliuzhongzhu 	.get_global_queue_id = hclgevf_get_qid_global,
37738cdb992fSJian Shen 	.set_timer_task = hclgevf_set_timer_task,
37749194d18bSliuzhongzhu 	.get_link_mode = hclgevf_get_link_mode,
3775e196ec75SJian Shen 	.set_promisc_mode = hclgevf_set_promisc_mode,
3776c631c696SJian Shen 	.request_update_promisc_mode = hclgevf_request_update_promisc_mode,
3777fe735c84SHuazhong Tan 	.get_cmdq_stat = hclgevf_get_cmdq_stat,
3778e2cb1decSSalil Mehta };
3779e2cb1decSSalil Mehta 
3780e2cb1decSSalil Mehta static struct hnae3_ae_algo ae_algovf = {
3781e2cb1decSSalil Mehta 	.ops = &hclgevf_ops,
3782e2cb1decSSalil Mehta 	.pdev_id_table = ae_algovf_pci_tbl,
3783e2cb1decSSalil Mehta };
3784e2cb1decSSalil Mehta 
3785e2cb1decSSalil Mehta static int hclgevf_init(void)
3786e2cb1decSSalil Mehta {
3787e2cb1decSSalil Mehta 	pr_info("%s is initializing\n", HCLGEVF_NAME);
3788e2cb1decSSalil Mehta 
378916deaef2SYunsheng Lin 	hclgevf_wq = alloc_workqueue("%s", 0, 0, HCLGEVF_NAME);
37900ea68902SYunsheng Lin 	if (!hclgevf_wq) {
37910ea68902SYunsheng Lin 		pr_err("%s: failed to create workqueue\n", HCLGEVF_NAME);
37920ea68902SYunsheng Lin 		return -ENOMEM;
37930ea68902SYunsheng Lin 	}
37940ea68902SYunsheng Lin 
3795854cf33aSFuyun Liang 	hnae3_register_ae_algo(&ae_algovf);
3796854cf33aSFuyun Liang 
3797854cf33aSFuyun Liang 	return 0;
3798e2cb1decSSalil Mehta }
3799e2cb1decSSalil Mehta 
3800e2cb1decSSalil Mehta static void hclgevf_exit(void)
3801e2cb1decSSalil Mehta {
3802e2cb1decSSalil Mehta 	hnae3_unregister_ae_algo(&ae_algovf);
38030ea68902SYunsheng Lin 	destroy_workqueue(hclgevf_wq);
3804e2cb1decSSalil Mehta }
3805e2cb1decSSalil Mehta module_init(hclgevf_init);
3806e2cb1decSSalil Mehta module_exit(hclgevf_exit);
3807e2cb1decSSalil Mehta 
3808e2cb1decSSalil Mehta MODULE_LICENSE("GPL");
3809e2cb1decSSalil Mehta MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
3810e2cb1decSSalil Mehta MODULE_DESCRIPTION("HCLGEVF Driver");
3811e2cb1decSSalil Mehta MODULE_VERSION(HCLGEVF_MOD_VERSION);
3812