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);
661*55ff3ed5SJian Shen 		req->start_table_index =
662*55ff3ed5SJian Shen 			cpu_to_le16(i * HCLGEVF_RSS_CFG_TBL_SIZE);
663*55ff3ed5SJian 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++) {
704*55ff3ed5SJian Shen 		u16 mode = 0;
705*55ff3ed5SJian Shen 
706*55ff3ed5SJian Shen 		hnae3_set_bit(mode, HCLGEVF_RSS_TC_VALID_B,
707e2cb1decSSalil Mehta 			      (tc_valid[i] & 0x1));
708*55ff3ed5SJian Shen 		hnae3_set_field(mode, HCLGEVF_RSS_TC_SIZE_M,
709e2cb1decSSalil Mehta 				HCLGEVF_RSS_TC_SIZE_S, tc_size[i]);
710*55ff3ed5SJian Shen 		hnae3_set_field(mode, HCLGEVF_RSS_TC_OFFSET_M,
711e2cb1decSSalil Mehta 				HCLGEVF_RSS_TC_OFFSET_S, tc_offset[i]);
712*55ff3ed5SJian Shen 
713*55ff3ed5SJian 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 
876d97b3072SJian Shen static int hclgevf_set_rss_tuple(struct hnae3_handle *handle,
877d97b3072SJian Shen 				 struct ethtool_rxnfc *nfc)
878d97b3072SJian Shen {
879d97b3072SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
880d97b3072SJian Shen 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
881d97b3072SJian Shen 	struct hclgevf_rss_input_tuple_cmd *req;
882d97b3072SJian Shen 	struct hclgevf_desc desc;
883d97b3072SJian Shen 	u8 tuple_sets;
884d97b3072SJian Shen 	int ret;
885d97b3072SJian Shen 
886295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
887d97b3072SJian Shen 		return -EOPNOTSUPP;
888d97b3072SJian Shen 
889d97b3072SJian Shen 	if (nfc->data &
890d97b3072SJian Shen 	    ~(RXH_IP_SRC | RXH_IP_DST | RXH_L4_B_0_1 | RXH_L4_B_2_3))
891d97b3072SJian Shen 		return -EINVAL;
892d97b3072SJian Shen 
893d97b3072SJian Shen 	req = (struct hclgevf_rss_input_tuple_cmd *)desc.data;
894d97b3072SJian Shen 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false);
895d97b3072SJian Shen 
896d97b3072SJian Shen 	req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
897d97b3072SJian Shen 	req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
898d97b3072SJian Shen 	req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
899d97b3072SJian Shen 	req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
900d97b3072SJian Shen 	req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
901d97b3072SJian Shen 	req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
902d97b3072SJian Shen 	req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
903d97b3072SJian Shen 	req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
904d97b3072SJian Shen 
905d97b3072SJian Shen 	tuple_sets = hclgevf_get_rss_hash_bits(nfc);
906d97b3072SJian Shen 	switch (nfc->flow_type) {
907d97b3072SJian Shen 	case TCP_V4_FLOW:
908d97b3072SJian Shen 		req->ipv4_tcp_en = tuple_sets;
909d97b3072SJian Shen 		break;
910d97b3072SJian Shen 	case TCP_V6_FLOW:
911d97b3072SJian Shen 		req->ipv6_tcp_en = tuple_sets;
912d97b3072SJian Shen 		break;
913d97b3072SJian Shen 	case UDP_V4_FLOW:
914d97b3072SJian Shen 		req->ipv4_udp_en = tuple_sets;
915d97b3072SJian Shen 		break;
916d97b3072SJian Shen 	case UDP_V6_FLOW:
917d97b3072SJian Shen 		req->ipv6_udp_en = tuple_sets;
918d97b3072SJian Shen 		break;
919d97b3072SJian Shen 	case SCTP_V4_FLOW:
920d97b3072SJian Shen 		req->ipv4_sctp_en = tuple_sets;
921d97b3072SJian Shen 		break;
922d97b3072SJian Shen 	case SCTP_V6_FLOW:
923ab6e32d2SJian Shen 		if (hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 &&
924ab6e32d2SJian Shen 		    (nfc->data & (RXH_L4_B_0_1 | RXH_L4_B_2_3)))
925d97b3072SJian Shen 			return -EINVAL;
926d97b3072SJian Shen 
927d97b3072SJian Shen 		req->ipv6_sctp_en = tuple_sets;
928d97b3072SJian Shen 		break;
929d97b3072SJian Shen 	case IPV4_FLOW:
930d97b3072SJian Shen 		req->ipv4_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
931d97b3072SJian Shen 		break;
932d97b3072SJian Shen 	case IPV6_FLOW:
933d97b3072SJian Shen 		req->ipv6_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
934d97b3072SJian Shen 		break;
935d97b3072SJian Shen 	default:
936d97b3072SJian Shen 		return -EINVAL;
937d97b3072SJian Shen 	}
938d97b3072SJian Shen 
939d97b3072SJian Shen 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
940d97b3072SJian Shen 	if (ret) {
941d97b3072SJian Shen 		dev_err(&hdev->pdev->dev,
942d97b3072SJian Shen 			"Set rss tuple fail, status = %d\n", ret);
943d97b3072SJian Shen 		return ret;
944d97b3072SJian Shen 	}
945d97b3072SJian Shen 
946d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_tcp_en = req->ipv4_tcp_en;
947d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_udp_en = req->ipv4_udp_en;
948d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_sctp_en = req->ipv4_sctp_en;
949d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv4_fragment_en = req->ipv4_fragment_en;
950d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_tcp_en = req->ipv6_tcp_en;
951d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_udp_en = req->ipv6_udp_en;
952d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_sctp_en = req->ipv6_sctp_en;
953d97b3072SJian Shen 	rss_cfg->rss_tuple_sets.ipv6_fragment_en = req->ipv6_fragment_en;
954d97b3072SJian Shen 	return 0;
955d97b3072SJian Shen }
956d97b3072SJian Shen 
957d97b3072SJian Shen static int hclgevf_get_rss_tuple(struct hnae3_handle *handle,
958d97b3072SJian Shen 				 struct ethtool_rxnfc *nfc)
959d97b3072SJian Shen {
960d97b3072SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
961d97b3072SJian Shen 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
962d97b3072SJian Shen 	u8 tuple_sets;
963d97b3072SJian Shen 
964295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
965d97b3072SJian Shen 		return -EOPNOTSUPP;
966d97b3072SJian Shen 
967d97b3072SJian Shen 	nfc->data = 0;
968d97b3072SJian Shen 
969d97b3072SJian Shen 	switch (nfc->flow_type) {
970d97b3072SJian Shen 	case TCP_V4_FLOW:
971d97b3072SJian Shen 		tuple_sets = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
972d97b3072SJian Shen 		break;
973d97b3072SJian Shen 	case UDP_V4_FLOW:
974d97b3072SJian Shen 		tuple_sets = rss_cfg->rss_tuple_sets.ipv4_udp_en;
975d97b3072SJian Shen 		break;
976d97b3072SJian Shen 	case TCP_V6_FLOW:
977d97b3072SJian Shen 		tuple_sets = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
978d97b3072SJian Shen 		break;
979d97b3072SJian Shen 	case UDP_V6_FLOW:
980d97b3072SJian Shen 		tuple_sets = rss_cfg->rss_tuple_sets.ipv6_udp_en;
981d97b3072SJian Shen 		break;
982d97b3072SJian Shen 	case SCTP_V4_FLOW:
983d97b3072SJian Shen 		tuple_sets = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
984d97b3072SJian Shen 		break;
985d97b3072SJian Shen 	case SCTP_V6_FLOW:
986d97b3072SJian Shen 		tuple_sets = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
987d97b3072SJian Shen 		break;
988d97b3072SJian Shen 	case IPV4_FLOW:
989d97b3072SJian Shen 	case IPV6_FLOW:
990d97b3072SJian Shen 		tuple_sets = HCLGEVF_S_IP_BIT | HCLGEVF_D_IP_BIT;
991d97b3072SJian Shen 		break;
992d97b3072SJian Shen 	default:
993d97b3072SJian Shen 		return -EINVAL;
994d97b3072SJian Shen 	}
995d97b3072SJian Shen 
996d97b3072SJian Shen 	if (!tuple_sets)
997d97b3072SJian Shen 		return 0;
998d97b3072SJian Shen 
999d97b3072SJian Shen 	if (tuple_sets & HCLGEVF_D_PORT_BIT)
1000d97b3072SJian Shen 		nfc->data |= RXH_L4_B_2_3;
1001d97b3072SJian Shen 	if (tuple_sets & HCLGEVF_S_PORT_BIT)
1002d97b3072SJian Shen 		nfc->data |= RXH_L4_B_0_1;
1003d97b3072SJian Shen 	if (tuple_sets & HCLGEVF_D_IP_BIT)
1004d97b3072SJian Shen 		nfc->data |= RXH_IP_DST;
1005d97b3072SJian Shen 	if (tuple_sets & HCLGEVF_S_IP_BIT)
1006d97b3072SJian Shen 		nfc->data |= RXH_IP_SRC;
1007d97b3072SJian Shen 
1008d97b3072SJian Shen 	return 0;
1009d97b3072SJian Shen }
1010d97b3072SJian Shen 
1011d97b3072SJian Shen static int hclgevf_set_rss_input_tuple(struct hclgevf_dev *hdev,
1012d97b3072SJian Shen 				       struct hclgevf_rss_cfg *rss_cfg)
1013d97b3072SJian Shen {
1014d97b3072SJian Shen 	struct hclgevf_rss_input_tuple_cmd *req;
1015d97b3072SJian Shen 	struct hclgevf_desc desc;
1016d97b3072SJian Shen 	int ret;
1017d97b3072SJian Shen 
1018d97b3072SJian Shen 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_RSS_INPUT_TUPLE, false);
1019d97b3072SJian Shen 
1020d97b3072SJian Shen 	req = (struct hclgevf_rss_input_tuple_cmd *)desc.data;
1021d97b3072SJian Shen 
1022d97b3072SJian Shen 	req->ipv4_tcp_en = rss_cfg->rss_tuple_sets.ipv4_tcp_en;
1023d97b3072SJian Shen 	req->ipv4_udp_en = rss_cfg->rss_tuple_sets.ipv4_udp_en;
1024d97b3072SJian Shen 	req->ipv4_sctp_en = rss_cfg->rss_tuple_sets.ipv4_sctp_en;
1025d97b3072SJian Shen 	req->ipv4_fragment_en = rss_cfg->rss_tuple_sets.ipv4_fragment_en;
1026d97b3072SJian Shen 	req->ipv6_tcp_en = rss_cfg->rss_tuple_sets.ipv6_tcp_en;
1027d97b3072SJian Shen 	req->ipv6_udp_en = rss_cfg->rss_tuple_sets.ipv6_udp_en;
1028d97b3072SJian Shen 	req->ipv6_sctp_en = rss_cfg->rss_tuple_sets.ipv6_sctp_en;
1029d97b3072SJian Shen 	req->ipv6_fragment_en = rss_cfg->rss_tuple_sets.ipv6_fragment_en;
1030d97b3072SJian Shen 
1031d97b3072SJian Shen 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
1032d97b3072SJian Shen 	if (ret)
1033d97b3072SJian Shen 		dev_err(&hdev->pdev->dev,
1034d97b3072SJian Shen 			"Configure rss input fail, status = %d\n", ret);
1035d97b3072SJian Shen 	return ret;
1036d97b3072SJian Shen }
1037d97b3072SJian Shen 
1038e2cb1decSSalil Mehta static int hclgevf_get_tc_size(struct hnae3_handle *handle)
1039e2cb1decSSalil Mehta {
1040e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1041e2cb1decSSalil Mehta 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
1042e2cb1decSSalil Mehta 
1043e2cb1decSSalil Mehta 	return rss_cfg->rss_size;
1044e2cb1decSSalil Mehta }
1045e2cb1decSSalil Mehta 
1046e2cb1decSSalil Mehta static int hclgevf_bind_ring_to_vector(struct hnae3_handle *handle, bool en,
1047b204bc74SPeng Li 				       int vector_id,
1048e2cb1decSSalil Mehta 				       struct hnae3_ring_chain_node *ring_chain)
1049e2cb1decSSalil Mehta {
1050e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1051d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1052e2cb1decSSalil Mehta 	struct hnae3_ring_chain_node *node;
1053e2cb1decSSalil Mehta 	int status;
1054d3410018SYufeng Mo 	int i = 0;
1055e2cb1decSSalil Mehta 
1056d3410018SYufeng Mo 	memset(&send_msg, 0, sizeof(send_msg));
1057d3410018SYufeng Mo 	send_msg.code = en ? HCLGE_MBX_MAP_RING_TO_VECTOR :
1058c09ba484SPeng Li 		HCLGE_MBX_UNMAP_RING_TO_VECTOR;
1059d3410018SYufeng Mo 	send_msg.vector_id = vector_id;
1060e2cb1decSSalil Mehta 
1061e2cb1decSSalil Mehta 	for (node = ring_chain; node; node = node->next) {
1062d3410018SYufeng Mo 		send_msg.param[i].ring_type =
1063e4e87715SPeng Li 				hnae3_get_bit(node->flag, HNAE3_RING_TYPE_B);
1064d3410018SYufeng Mo 
1065d3410018SYufeng Mo 		send_msg.param[i].tqp_index = node->tqp_index;
1066d3410018SYufeng Mo 		send_msg.param[i].int_gl_index =
1067d3410018SYufeng Mo 					hnae3_get_field(node->int_gl_idx,
106879eee410SFuyun Liang 							HNAE3_RING_GL_IDX_M,
106979eee410SFuyun Liang 							HNAE3_RING_GL_IDX_S);
107079eee410SFuyun Liang 
10715d02a58dSYunsheng Lin 		i++;
1072d3410018SYufeng Mo 		if (i == HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM || !node->next) {
1073d3410018SYufeng Mo 			send_msg.ring_num = i;
1074e2cb1decSSalil Mehta 
1075d3410018SYufeng Mo 			status = hclgevf_send_mbx_msg(hdev, &send_msg, false,
1076d3410018SYufeng Mo 						      NULL, 0);
1077e2cb1decSSalil Mehta 			if (status) {
1078e2cb1decSSalil Mehta 				dev_err(&hdev->pdev->dev,
1079e2cb1decSSalil Mehta 					"Map TQP fail, status is %d.\n",
1080e2cb1decSSalil Mehta 					status);
1081e2cb1decSSalil Mehta 				return status;
1082e2cb1decSSalil Mehta 			}
1083e2cb1decSSalil Mehta 			i = 0;
1084e2cb1decSSalil Mehta 		}
1085e2cb1decSSalil Mehta 	}
1086e2cb1decSSalil Mehta 
1087e2cb1decSSalil Mehta 	return 0;
1088e2cb1decSSalil Mehta }
1089e2cb1decSSalil Mehta 
1090e2cb1decSSalil Mehta static int hclgevf_map_ring_to_vector(struct hnae3_handle *handle, int vector,
1091e2cb1decSSalil Mehta 				      struct hnae3_ring_chain_node *ring_chain)
1092e2cb1decSSalil Mehta {
1093b204bc74SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1094b204bc74SPeng Li 	int vector_id;
1095b204bc74SPeng Li 
1096b204bc74SPeng Li 	vector_id = hclgevf_get_vector_index(hdev, vector);
1097b204bc74SPeng Li 	if (vector_id < 0) {
1098b204bc74SPeng Li 		dev_err(&handle->pdev->dev,
1099b204bc74SPeng Li 			"Get vector index fail. ret =%d\n", vector_id);
1100b204bc74SPeng Li 		return vector_id;
1101b204bc74SPeng Li 	}
1102b204bc74SPeng Li 
1103b204bc74SPeng Li 	return hclgevf_bind_ring_to_vector(handle, true, vector_id, ring_chain);
1104e2cb1decSSalil Mehta }
1105e2cb1decSSalil Mehta 
1106e2cb1decSSalil Mehta static int hclgevf_unmap_ring_from_vector(
1107e2cb1decSSalil Mehta 				struct hnae3_handle *handle,
1108e2cb1decSSalil Mehta 				int vector,
1109e2cb1decSSalil Mehta 				struct hnae3_ring_chain_node *ring_chain)
1110e2cb1decSSalil Mehta {
1111e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1112e2cb1decSSalil Mehta 	int ret, vector_id;
1113e2cb1decSSalil Mehta 
1114dea846e8SHuazhong Tan 	if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
1115dea846e8SHuazhong Tan 		return 0;
1116dea846e8SHuazhong Tan 
1117e2cb1decSSalil Mehta 	vector_id = hclgevf_get_vector_index(hdev, vector);
1118e2cb1decSSalil Mehta 	if (vector_id < 0) {
1119e2cb1decSSalil Mehta 		dev_err(&handle->pdev->dev,
1120e2cb1decSSalil Mehta 			"Get vector index fail. ret =%d\n", vector_id);
1121e2cb1decSSalil Mehta 		return vector_id;
1122e2cb1decSSalil Mehta 	}
1123e2cb1decSSalil Mehta 
1124b204bc74SPeng Li 	ret = hclgevf_bind_ring_to_vector(handle, false, vector_id, ring_chain);
11250d3e6631SYunsheng Lin 	if (ret)
1126e2cb1decSSalil Mehta 		dev_err(&handle->pdev->dev,
1127e2cb1decSSalil Mehta 			"Unmap ring from vector fail. vector=%d, ret =%d\n",
1128e2cb1decSSalil Mehta 			vector_id,
1129e2cb1decSSalil Mehta 			ret);
11300d3e6631SYunsheng Lin 
1131e2cb1decSSalil Mehta 	return ret;
1132e2cb1decSSalil Mehta }
1133e2cb1decSSalil Mehta 
11340d3e6631SYunsheng Lin static int hclgevf_put_vector(struct hnae3_handle *handle, int vector)
11350d3e6631SYunsheng Lin {
11360d3e6631SYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
113703718db9SYunsheng Lin 	int vector_id;
11380d3e6631SYunsheng Lin 
113903718db9SYunsheng Lin 	vector_id = hclgevf_get_vector_index(hdev, vector);
114003718db9SYunsheng Lin 	if (vector_id < 0) {
114103718db9SYunsheng Lin 		dev_err(&handle->pdev->dev,
114203718db9SYunsheng Lin 			"hclgevf_put_vector get vector index fail. ret =%d\n",
114303718db9SYunsheng Lin 			vector_id);
114403718db9SYunsheng Lin 		return vector_id;
114503718db9SYunsheng Lin 	}
114603718db9SYunsheng Lin 
114703718db9SYunsheng Lin 	hclgevf_free_vector(hdev, vector_id);
1148e2cb1decSSalil Mehta 
1149e2cb1decSSalil Mehta 	return 0;
1150e2cb1decSSalil Mehta }
1151e2cb1decSSalil Mehta 
11523b75c3dfSPeng Li static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev,
1153e196ec75SJian Shen 					bool en_uc_pmc, bool en_mc_pmc,
1154f01f5559SJian Shen 					bool en_bc_pmc)
1155e2cb1decSSalil Mehta {
11565e7414cdSJian Shen 	struct hnae3_handle *handle = &hdev->nic;
1157d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1158f01f5559SJian Shen 	int ret;
1159e2cb1decSSalil Mehta 
1160d3410018SYufeng Mo 	memset(&send_msg, 0, sizeof(send_msg));
1161d3410018SYufeng Mo 	send_msg.code = HCLGE_MBX_SET_PROMISC_MODE;
1162d3410018SYufeng Mo 	send_msg.en_bc = en_bc_pmc ? 1 : 0;
1163d3410018SYufeng Mo 	send_msg.en_uc = en_uc_pmc ? 1 : 0;
1164d3410018SYufeng Mo 	send_msg.en_mc = en_mc_pmc ? 1 : 0;
11655e7414cdSJian Shen 	send_msg.en_limit_promisc = test_bit(HNAE3_PFLAG_LIMIT_PROMISC,
11665e7414cdSJian Shen 					     &handle->priv_flags) ? 1 : 0;
1167e2cb1decSSalil Mehta 
1168d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1169f01f5559SJian Shen 	if (ret)
1170e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
1171f01f5559SJian Shen 			"Set promisc mode fail, status is %d.\n", ret);
1172e2cb1decSSalil Mehta 
1173f01f5559SJian Shen 	return ret;
1174e2cb1decSSalil Mehta }
1175e2cb1decSSalil Mehta 
1176e196ec75SJian Shen static int hclgevf_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
1177e196ec75SJian Shen 				    bool en_mc_pmc)
1178e2cb1decSSalil Mehta {
1179e196ec75SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1180e196ec75SJian Shen 	bool en_bc_pmc;
1181e196ec75SJian Shen 
1182295ba232SGuangbin Huang 	en_bc_pmc = hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2;
1183e196ec75SJian Shen 
1184e196ec75SJian Shen 	return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc,
1185e196ec75SJian Shen 					    en_bc_pmc);
1186e2cb1decSSalil Mehta }
1187e2cb1decSSalil Mehta 
1188c631c696SJian Shen static void hclgevf_request_update_promisc_mode(struct hnae3_handle *handle)
1189c631c696SJian Shen {
1190c631c696SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1191c631c696SJian Shen 
1192c631c696SJian Shen 	set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
11935e7414cdSJian Shen 	hclgevf_task_schedule(hdev, 0);
1194c631c696SJian Shen }
1195c631c696SJian Shen 
1196c631c696SJian Shen static void hclgevf_sync_promisc_mode(struct hclgevf_dev *hdev)
1197c631c696SJian Shen {
1198c631c696SJian Shen 	struct hnae3_handle *handle = &hdev->nic;
1199c631c696SJian Shen 	bool en_uc_pmc = handle->netdev_flags & HNAE3_UPE;
1200c631c696SJian Shen 	bool en_mc_pmc = handle->netdev_flags & HNAE3_MPE;
1201c631c696SJian Shen 	int ret;
1202c631c696SJian Shen 
1203c631c696SJian Shen 	if (test_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state)) {
1204c631c696SJian Shen 		ret = hclgevf_set_promisc_mode(handle, en_uc_pmc, en_mc_pmc);
1205c631c696SJian Shen 		if (!ret)
1206c631c696SJian Shen 			clear_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
1207c631c696SJian Shen 	}
1208c631c696SJian Shen }
1209c631c696SJian Shen 
1210ebaf1908SWeihang Li static int hclgevf_tqp_enable(struct hclgevf_dev *hdev, unsigned int tqp_id,
1211e2cb1decSSalil Mehta 			      int stream_id, bool enable)
1212e2cb1decSSalil Mehta {
1213e2cb1decSSalil Mehta 	struct hclgevf_cfg_com_tqp_queue_cmd *req;
1214e2cb1decSSalil Mehta 	struct hclgevf_desc desc;
1215e2cb1decSSalil Mehta 	int status;
1216e2cb1decSSalil Mehta 
1217e2cb1decSSalil Mehta 	req = (struct hclgevf_cfg_com_tqp_queue_cmd *)desc.data;
1218e2cb1decSSalil Mehta 
1219e2cb1decSSalil Mehta 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_CFG_COM_TQP_QUEUE,
1220e2cb1decSSalil Mehta 				     false);
1221e2cb1decSSalil Mehta 	req->tqp_id = cpu_to_le16(tqp_id & HCLGEVF_RING_ID_MASK);
1222e2cb1decSSalil Mehta 	req->stream_id = cpu_to_le16(stream_id);
1223ebaf1908SWeihang Li 	if (enable)
1224ebaf1908SWeihang Li 		req->enable |= 1U << HCLGEVF_TQP_ENABLE_B;
1225e2cb1decSSalil Mehta 
1226e2cb1decSSalil Mehta 	status = hclgevf_cmd_send(&hdev->hw, &desc, 1);
1227e2cb1decSSalil Mehta 	if (status)
1228e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
1229e2cb1decSSalil Mehta 			"TQP enable fail, status =%d.\n", status);
1230e2cb1decSSalil Mehta 
1231e2cb1decSSalil Mehta 	return status;
1232e2cb1decSSalil Mehta }
1233e2cb1decSSalil Mehta 
1234e2cb1decSSalil Mehta static void hclgevf_reset_tqp_stats(struct hnae3_handle *handle)
1235e2cb1decSSalil Mehta {
1236b4f1d303SJian Shen 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
1237e2cb1decSSalil Mehta 	struct hclgevf_tqp *tqp;
1238e2cb1decSSalil Mehta 	int i;
1239e2cb1decSSalil Mehta 
1240b4f1d303SJian Shen 	for (i = 0; i < kinfo->num_tqps; i++) {
1241b4f1d303SJian Shen 		tqp = container_of(kinfo->tqp[i], struct hclgevf_tqp, q);
1242e2cb1decSSalil Mehta 		memset(&tqp->tqp_stats, 0, sizeof(tqp->tqp_stats));
1243e2cb1decSSalil Mehta 	}
1244e2cb1decSSalil Mehta }
1245e2cb1decSSalil Mehta 
12468e6de441SHuazhong Tan static int hclgevf_get_host_mac_addr(struct hclgevf_dev *hdev, u8 *p)
12478e6de441SHuazhong Tan {
1248d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
12498e6de441SHuazhong Tan 	u8 host_mac[ETH_ALEN];
12508e6de441SHuazhong Tan 	int status;
12518e6de441SHuazhong Tan 
1252d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_MAC_ADDR, 0);
1253d3410018SYufeng Mo 	status = hclgevf_send_mbx_msg(hdev, &send_msg, true, host_mac,
1254d3410018SYufeng Mo 				      ETH_ALEN);
12558e6de441SHuazhong Tan 	if (status) {
12568e6de441SHuazhong Tan 		dev_err(&hdev->pdev->dev,
12578e6de441SHuazhong Tan 			"fail to get VF MAC from host %d", status);
12588e6de441SHuazhong Tan 		return status;
12598e6de441SHuazhong Tan 	}
12608e6de441SHuazhong Tan 
12618e6de441SHuazhong Tan 	ether_addr_copy(p, host_mac);
12628e6de441SHuazhong Tan 
12638e6de441SHuazhong Tan 	return 0;
12648e6de441SHuazhong Tan }
12658e6de441SHuazhong Tan 
1266e2cb1decSSalil Mehta static void hclgevf_get_mac_addr(struct hnae3_handle *handle, u8 *p)
1267e2cb1decSSalil Mehta {
1268e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
12698e6de441SHuazhong Tan 	u8 host_mac_addr[ETH_ALEN];
1270e2cb1decSSalil Mehta 
12718e6de441SHuazhong Tan 	if (hclgevf_get_host_mac_addr(hdev, host_mac_addr))
12728e6de441SHuazhong Tan 		return;
12738e6de441SHuazhong Tan 
12748e6de441SHuazhong Tan 	hdev->has_pf_mac = !is_zero_ether_addr(host_mac_addr);
12758e6de441SHuazhong Tan 	if (hdev->has_pf_mac)
12768e6de441SHuazhong Tan 		ether_addr_copy(p, host_mac_addr);
12778e6de441SHuazhong Tan 	else
1278e2cb1decSSalil Mehta 		ether_addr_copy(p, hdev->hw.mac.mac_addr);
1279e2cb1decSSalil Mehta }
1280e2cb1decSSalil Mehta 
128159098055SFuyun Liang static int hclgevf_set_mac_addr(struct hnae3_handle *handle, void *p,
128259098055SFuyun Liang 				bool is_first)
1283e2cb1decSSalil Mehta {
1284e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1285e2cb1decSSalil Mehta 	u8 *old_mac_addr = (u8 *)hdev->hw.mac.mac_addr;
1286d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1287e2cb1decSSalil Mehta 	u8 *new_mac_addr = (u8 *)p;
1288e2cb1decSSalil Mehta 	int status;
1289e2cb1decSSalil Mehta 
1290d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_UNICAST, 0);
1291ee4bcd3bSJian Shen 	send_msg.subcode = HCLGE_MBX_MAC_VLAN_UC_MODIFY;
1292d3410018SYufeng Mo 	ether_addr_copy(send_msg.data, new_mac_addr);
1293ee4bcd3bSJian Shen 	if (is_first && !hdev->has_pf_mac)
1294ee4bcd3bSJian Shen 		eth_zero_addr(&send_msg.data[ETH_ALEN]);
1295ee4bcd3bSJian Shen 	else
1296d3410018SYufeng Mo 		ether_addr_copy(&send_msg.data[ETH_ALEN], old_mac_addr);
1297d3410018SYufeng Mo 	status = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1298e2cb1decSSalil Mehta 	if (!status)
1299e2cb1decSSalil Mehta 		ether_addr_copy(hdev->hw.mac.mac_addr, new_mac_addr);
1300e2cb1decSSalil Mehta 
1301e2cb1decSSalil Mehta 	return status;
1302e2cb1decSSalil Mehta }
1303e2cb1decSSalil Mehta 
1304ee4bcd3bSJian Shen static struct hclgevf_mac_addr_node *
1305ee4bcd3bSJian Shen hclgevf_find_mac_node(struct list_head *list, const u8 *mac_addr)
1306ee4bcd3bSJian Shen {
1307ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp;
1308ee4bcd3bSJian Shen 
1309ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node)
1310ee4bcd3bSJian Shen 		if (ether_addr_equal(mac_addr, mac_node->mac_addr))
1311ee4bcd3bSJian Shen 			return mac_node;
1312ee4bcd3bSJian Shen 
1313ee4bcd3bSJian Shen 	return NULL;
1314ee4bcd3bSJian Shen }
1315ee4bcd3bSJian Shen 
1316ee4bcd3bSJian Shen static void hclgevf_update_mac_node(struct hclgevf_mac_addr_node *mac_node,
1317ee4bcd3bSJian Shen 				    enum HCLGEVF_MAC_NODE_STATE state)
1318ee4bcd3bSJian Shen {
1319ee4bcd3bSJian Shen 	switch (state) {
1320ee4bcd3bSJian Shen 	/* from set_rx_mode or tmp_add_list */
1321ee4bcd3bSJian Shen 	case HCLGEVF_MAC_TO_ADD:
1322ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_DEL)
1323ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_ACTIVE;
1324ee4bcd3bSJian Shen 		break;
1325ee4bcd3bSJian Shen 	/* only from set_rx_mode */
1326ee4bcd3bSJian Shen 	case HCLGEVF_MAC_TO_DEL:
1327ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD) {
1328ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1329ee4bcd3bSJian Shen 			kfree(mac_node);
1330ee4bcd3bSJian Shen 		} else {
1331ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_TO_DEL;
1332ee4bcd3bSJian Shen 		}
1333ee4bcd3bSJian Shen 		break;
1334ee4bcd3bSJian Shen 	/* only from tmp_add_list, the mac_node->state won't be
1335ee4bcd3bSJian Shen 	 * HCLGEVF_MAC_ACTIVE
1336ee4bcd3bSJian Shen 	 */
1337ee4bcd3bSJian Shen 	case HCLGEVF_MAC_ACTIVE:
1338ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1339ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_ACTIVE;
1340ee4bcd3bSJian Shen 		break;
1341ee4bcd3bSJian Shen 	}
1342ee4bcd3bSJian Shen }
1343ee4bcd3bSJian Shen 
1344ee4bcd3bSJian Shen static int hclgevf_update_mac_list(struct hnae3_handle *handle,
1345ee4bcd3bSJian Shen 				   enum HCLGEVF_MAC_NODE_STATE state,
1346ee4bcd3bSJian Shen 				   enum HCLGEVF_MAC_ADDR_TYPE mac_type,
1347e2cb1decSSalil Mehta 				   const unsigned char *addr)
1348e2cb1decSSalil Mehta {
1349e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1350ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node;
1351ee4bcd3bSJian Shen 	struct list_head *list;
1352e2cb1decSSalil Mehta 
1353ee4bcd3bSJian Shen 	list = (mac_type == HCLGEVF_MAC_ADDR_UC) ?
1354ee4bcd3bSJian Shen 	       &hdev->mac_table.uc_mac_list : &hdev->mac_table.mc_mac_list;
1355ee4bcd3bSJian Shen 
1356ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1357ee4bcd3bSJian Shen 
1358ee4bcd3bSJian Shen 	/* if the mac addr is already in the mac list, no need to add a new
1359ee4bcd3bSJian Shen 	 * one into it, just check the mac addr state, convert it to a new
1360ee4bcd3bSJian Shen 	 * new state, or just remove it, or do nothing.
1361ee4bcd3bSJian Shen 	 */
1362ee4bcd3bSJian Shen 	mac_node = hclgevf_find_mac_node(list, addr);
1363ee4bcd3bSJian Shen 	if (mac_node) {
1364ee4bcd3bSJian Shen 		hclgevf_update_mac_node(mac_node, state);
1365ee4bcd3bSJian Shen 		spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1366ee4bcd3bSJian Shen 		return 0;
1367ee4bcd3bSJian Shen 	}
1368ee4bcd3bSJian Shen 	/* if this address is never added, unnecessary to delete */
1369ee4bcd3bSJian Shen 	if (state == HCLGEVF_MAC_TO_DEL) {
1370ee4bcd3bSJian Shen 		spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1371ee4bcd3bSJian Shen 		return -ENOENT;
1372ee4bcd3bSJian Shen 	}
1373ee4bcd3bSJian Shen 
1374ee4bcd3bSJian Shen 	mac_node = kzalloc(sizeof(*mac_node), GFP_ATOMIC);
1375ee4bcd3bSJian Shen 	if (!mac_node) {
1376ee4bcd3bSJian Shen 		spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1377ee4bcd3bSJian Shen 		return -ENOMEM;
1378ee4bcd3bSJian Shen 	}
1379ee4bcd3bSJian Shen 
1380ee4bcd3bSJian Shen 	mac_node->state = state;
1381ee4bcd3bSJian Shen 	ether_addr_copy(mac_node->mac_addr, addr);
1382ee4bcd3bSJian Shen 	list_add_tail(&mac_node->node, list);
1383ee4bcd3bSJian Shen 
1384ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1385ee4bcd3bSJian Shen 	return 0;
1386ee4bcd3bSJian Shen }
1387ee4bcd3bSJian Shen 
1388ee4bcd3bSJian Shen static int hclgevf_add_uc_addr(struct hnae3_handle *handle,
1389ee4bcd3bSJian Shen 			       const unsigned char *addr)
1390ee4bcd3bSJian Shen {
1391ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_ADD,
1392ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_UC, addr);
1393e2cb1decSSalil Mehta }
1394e2cb1decSSalil Mehta 
1395e2cb1decSSalil Mehta static int hclgevf_rm_uc_addr(struct hnae3_handle *handle,
1396e2cb1decSSalil Mehta 			      const unsigned char *addr)
1397e2cb1decSSalil Mehta {
1398ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_DEL,
1399ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_UC, addr);
1400e2cb1decSSalil Mehta }
1401e2cb1decSSalil Mehta 
1402e2cb1decSSalil Mehta static int hclgevf_add_mc_addr(struct hnae3_handle *handle,
1403e2cb1decSSalil Mehta 			       const unsigned char *addr)
1404e2cb1decSSalil Mehta {
1405ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_ADD,
1406ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_MC, addr);
1407e2cb1decSSalil Mehta }
1408e2cb1decSSalil Mehta 
1409e2cb1decSSalil Mehta static int hclgevf_rm_mc_addr(struct hnae3_handle *handle,
1410e2cb1decSSalil Mehta 			      const unsigned char *addr)
1411e2cb1decSSalil Mehta {
1412ee4bcd3bSJian Shen 	return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_DEL,
1413ee4bcd3bSJian Shen 				       HCLGEVF_MAC_ADDR_MC, addr);
1414ee4bcd3bSJian Shen }
1415e2cb1decSSalil Mehta 
1416ee4bcd3bSJian Shen static int hclgevf_add_del_mac_addr(struct hclgevf_dev *hdev,
1417ee4bcd3bSJian Shen 				    struct hclgevf_mac_addr_node *mac_node,
1418ee4bcd3bSJian Shen 				    enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1419ee4bcd3bSJian Shen {
1420ee4bcd3bSJian Shen 	struct hclge_vf_to_pf_msg send_msg;
1421ee4bcd3bSJian Shen 	u8 code, subcode;
1422ee4bcd3bSJian Shen 
1423ee4bcd3bSJian Shen 	if (mac_type == HCLGEVF_MAC_ADDR_UC) {
1424ee4bcd3bSJian Shen 		code = HCLGE_MBX_SET_UNICAST;
1425ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1426ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_UC_ADD;
1427ee4bcd3bSJian Shen 		else
1428ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_UC_REMOVE;
1429ee4bcd3bSJian Shen 	} else {
1430ee4bcd3bSJian Shen 		code = HCLGE_MBX_SET_MULTICAST;
1431ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1432ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_MC_ADD;
1433ee4bcd3bSJian Shen 		else
1434ee4bcd3bSJian Shen 			subcode = HCLGE_MBX_MAC_VLAN_MC_REMOVE;
1435ee4bcd3bSJian Shen 	}
1436ee4bcd3bSJian Shen 
1437ee4bcd3bSJian Shen 	hclgevf_build_send_msg(&send_msg, code, subcode);
1438ee4bcd3bSJian Shen 	ether_addr_copy(send_msg.data, mac_node->mac_addr);
1439d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1440e2cb1decSSalil Mehta }
1441e2cb1decSSalil Mehta 
1442ee4bcd3bSJian Shen static void hclgevf_config_mac_list(struct hclgevf_dev *hdev,
1443ee4bcd3bSJian Shen 				    struct list_head *list,
1444ee4bcd3bSJian Shen 				    enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1445ee4bcd3bSJian Shen {
1446ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp;
1447ee4bcd3bSJian Shen 	int ret;
1448ee4bcd3bSJian Shen 
1449ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node) {
1450ee4bcd3bSJian Shen 		ret = hclgevf_add_del_mac_addr(hdev, mac_node, mac_type);
1451ee4bcd3bSJian Shen 		if  (ret) {
1452ee4bcd3bSJian Shen 			dev_err(&hdev->pdev->dev,
1453ee4bcd3bSJian Shen 				"failed to configure mac %pM, state = %d, ret = %d\n",
1454ee4bcd3bSJian Shen 				mac_node->mac_addr, mac_node->state, ret);
1455ee4bcd3bSJian Shen 			return;
1456ee4bcd3bSJian Shen 		}
1457ee4bcd3bSJian Shen 		if (mac_node->state == HCLGEVF_MAC_TO_ADD) {
1458ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_ACTIVE;
1459ee4bcd3bSJian Shen 		} else {
1460ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1461ee4bcd3bSJian Shen 			kfree(mac_node);
1462ee4bcd3bSJian Shen 		}
1463ee4bcd3bSJian Shen 	}
1464ee4bcd3bSJian Shen }
1465ee4bcd3bSJian Shen 
1466ee4bcd3bSJian Shen static void hclgevf_sync_from_add_list(struct list_head *add_list,
1467ee4bcd3bSJian Shen 				       struct list_head *mac_list)
1468ee4bcd3bSJian Shen {
1469ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1470ee4bcd3bSJian Shen 
1471ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, add_list, node) {
1472ee4bcd3bSJian Shen 		/* if the mac address from tmp_add_list is not in the
1473ee4bcd3bSJian Shen 		 * uc/mc_mac_list, it means have received a TO_DEL request
1474ee4bcd3bSJian Shen 		 * during the time window of sending mac config request to PF
1475ee4bcd3bSJian Shen 		 * If mac_node state is ACTIVE, then change its state to TO_DEL,
1476ee4bcd3bSJian Shen 		 * then it will be removed at next time. If is TO_ADD, it means
1477ee4bcd3bSJian Shen 		 * send TO_ADD request failed, so just remove the mac node.
1478ee4bcd3bSJian Shen 		 */
1479ee4bcd3bSJian Shen 		new_node = hclgevf_find_mac_node(mac_list, mac_node->mac_addr);
1480ee4bcd3bSJian Shen 		if (new_node) {
1481ee4bcd3bSJian Shen 			hclgevf_update_mac_node(new_node, mac_node->state);
1482ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1483ee4bcd3bSJian Shen 			kfree(mac_node);
1484ee4bcd3bSJian Shen 		} else if (mac_node->state == HCLGEVF_MAC_ACTIVE) {
1485ee4bcd3bSJian Shen 			mac_node->state = HCLGEVF_MAC_TO_DEL;
1486ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1487ee4bcd3bSJian Shen 			list_add_tail(&mac_node->node, mac_list);
1488ee4bcd3bSJian Shen 		} else {
1489ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1490ee4bcd3bSJian Shen 			kfree(mac_node);
1491ee4bcd3bSJian Shen 		}
1492ee4bcd3bSJian Shen 	}
1493ee4bcd3bSJian Shen }
1494ee4bcd3bSJian Shen 
1495ee4bcd3bSJian Shen static void hclgevf_sync_from_del_list(struct list_head *del_list,
1496ee4bcd3bSJian Shen 				       struct list_head *mac_list)
1497ee4bcd3bSJian Shen {
1498ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1499ee4bcd3bSJian Shen 
1500ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, del_list, node) {
1501ee4bcd3bSJian Shen 		new_node = hclgevf_find_mac_node(mac_list, mac_node->mac_addr);
1502ee4bcd3bSJian Shen 		if (new_node) {
1503ee4bcd3bSJian Shen 			/* If the mac addr is exist in the mac list, it means
1504ee4bcd3bSJian Shen 			 * received a new request TO_ADD during the time window
1505ee4bcd3bSJian Shen 			 * of sending mac addr configurrequest to PF, so just
1506ee4bcd3bSJian Shen 			 * change the mac state to ACTIVE.
1507ee4bcd3bSJian Shen 			 */
1508ee4bcd3bSJian Shen 			new_node->state = HCLGEVF_MAC_ACTIVE;
1509ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1510ee4bcd3bSJian Shen 			kfree(mac_node);
1511ee4bcd3bSJian Shen 		} else {
1512ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1513ee4bcd3bSJian Shen 			list_add_tail(&mac_node->node, mac_list);
1514ee4bcd3bSJian Shen 		}
1515ee4bcd3bSJian Shen 	}
1516ee4bcd3bSJian Shen }
1517ee4bcd3bSJian Shen 
1518ee4bcd3bSJian Shen static void hclgevf_clear_list(struct list_head *list)
1519ee4bcd3bSJian Shen {
1520ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp;
1521ee4bcd3bSJian Shen 
1522ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node) {
1523ee4bcd3bSJian Shen 		list_del(&mac_node->node);
1524ee4bcd3bSJian Shen 		kfree(mac_node);
1525ee4bcd3bSJian Shen 	}
1526ee4bcd3bSJian Shen }
1527ee4bcd3bSJian Shen 
1528ee4bcd3bSJian Shen static void hclgevf_sync_mac_list(struct hclgevf_dev *hdev,
1529ee4bcd3bSJian Shen 				  enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1530ee4bcd3bSJian Shen {
1531ee4bcd3bSJian Shen 	struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1532ee4bcd3bSJian Shen 	struct list_head tmp_add_list, tmp_del_list;
1533ee4bcd3bSJian Shen 	struct list_head *list;
1534ee4bcd3bSJian Shen 
1535ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&tmp_add_list);
1536ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&tmp_del_list);
1537ee4bcd3bSJian Shen 
1538ee4bcd3bSJian Shen 	/* move the mac addr to the tmp_add_list and tmp_del_list, then
1539ee4bcd3bSJian Shen 	 * we can add/delete these mac addr outside the spin lock
1540ee4bcd3bSJian Shen 	 */
1541ee4bcd3bSJian Shen 	list = (mac_type == HCLGEVF_MAC_ADDR_UC) ?
1542ee4bcd3bSJian Shen 		&hdev->mac_table.uc_mac_list : &hdev->mac_table.mc_mac_list;
1543ee4bcd3bSJian Shen 
1544ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1545ee4bcd3bSJian Shen 
1546ee4bcd3bSJian Shen 	list_for_each_entry_safe(mac_node, tmp, list, node) {
1547ee4bcd3bSJian Shen 		switch (mac_node->state) {
1548ee4bcd3bSJian Shen 		case HCLGEVF_MAC_TO_DEL:
1549ee4bcd3bSJian Shen 			list_del(&mac_node->node);
1550ee4bcd3bSJian Shen 			list_add_tail(&mac_node->node, &tmp_del_list);
1551ee4bcd3bSJian Shen 			break;
1552ee4bcd3bSJian Shen 		case HCLGEVF_MAC_TO_ADD:
1553ee4bcd3bSJian Shen 			new_node = kzalloc(sizeof(*new_node), GFP_ATOMIC);
1554ee4bcd3bSJian Shen 			if (!new_node)
1555ee4bcd3bSJian Shen 				goto stop_traverse;
1556ee4bcd3bSJian Shen 
1557ee4bcd3bSJian Shen 			ether_addr_copy(new_node->mac_addr, mac_node->mac_addr);
1558ee4bcd3bSJian Shen 			new_node->state = mac_node->state;
1559ee4bcd3bSJian Shen 			list_add_tail(&new_node->node, &tmp_add_list);
1560ee4bcd3bSJian Shen 			break;
1561ee4bcd3bSJian Shen 		default:
1562ee4bcd3bSJian Shen 			break;
1563ee4bcd3bSJian Shen 		}
1564ee4bcd3bSJian Shen 	}
1565ee4bcd3bSJian Shen 
1566ee4bcd3bSJian Shen stop_traverse:
1567ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1568ee4bcd3bSJian Shen 
1569ee4bcd3bSJian Shen 	/* delete first, in order to get max mac table space for adding */
1570ee4bcd3bSJian Shen 	hclgevf_config_mac_list(hdev, &tmp_del_list, mac_type);
1571ee4bcd3bSJian Shen 	hclgevf_config_mac_list(hdev, &tmp_add_list, mac_type);
1572ee4bcd3bSJian Shen 
1573ee4bcd3bSJian Shen 	/* if some mac addresses were added/deleted fail, move back to the
1574ee4bcd3bSJian Shen 	 * mac_list, and retry at next time.
1575ee4bcd3bSJian Shen 	 */
1576ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1577ee4bcd3bSJian Shen 
1578ee4bcd3bSJian Shen 	hclgevf_sync_from_del_list(&tmp_del_list, list);
1579ee4bcd3bSJian Shen 	hclgevf_sync_from_add_list(&tmp_add_list, list);
1580ee4bcd3bSJian Shen 
1581ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1582ee4bcd3bSJian Shen }
1583ee4bcd3bSJian Shen 
1584ee4bcd3bSJian Shen static void hclgevf_sync_mac_table(struct hclgevf_dev *hdev)
1585ee4bcd3bSJian Shen {
1586ee4bcd3bSJian Shen 	hclgevf_sync_mac_list(hdev, HCLGEVF_MAC_ADDR_UC);
1587ee4bcd3bSJian Shen 	hclgevf_sync_mac_list(hdev, HCLGEVF_MAC_ADDR_MC);
1588ee4bcd3bSJian Shen }
1589ee4bcd3bSJian Shen 
1590ee4bcd3bSJian Shen static void hclgevf_uninit_mac_list(struct hclgevf_dev *hdev)
1591ee4bcd3bSJian Shen {
1592ee4bcd3bSJian Shen 	spin_lock_bh(&hdev->mac_table.mac_list_lock);
1593ee4bcd3bSJian Shen 
1594ee4bcd3bSJian Shen 	hclgevf_clear_list(&hdev->mac_table.uc_mac_list);
1595ee4bcd3bSJian Shen 	hclgevf_clear_list(&hdev->mac_table.mc_mac_list);
1596ee4bcd3bSJian Shen 
1597ee4bcd3bSJian Shen 	spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1598ee4bcd3bSJian Shen }
1599ee4bcd3bSJian Shen 
1600e2cb1decSSalil Mehta static int hclgevf_set_vlan_filter(struct hnae3_handle *handle,
1601e2cb1decSSalil Mehta 				   __be16 proto, u16 vlan_id,
1602e2cb1decSSalil Mehta 				   bool is_kill)
1603e2cb1decSSalil Mehta {
1604d3410018SYufeng Mo #define HCLGEVF_VLAN_MBX_IS_KILL_OFFSET	0
1605d3410018SYufeng Mo #define HCLGEVF_VLAN_MBX_VLAN_ID_OFFSET	1
1606d3410018SYufeng Mo #define HCLGEVF_VLAN_MBX_PROTO_OFFSET	3
1607d3410018SYufeng Mo 
1608e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1609d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1610fe4144d4SJian Shen 	int ret;
1611e2cb1decSSalil Mehta 
1612b37ce587SYufeng Mo 	if (vlan_id > HCLGEVF_MAX_VLAN_ID)
1613e2cb1decSSalil Mehta 		return -EINVAL;
1614e2cb1decSSalil Mehta 
1615e2cb1decSSalil Mehta 	if (proto != htons(ETH_P_8021Q))
1616e2cb1decSSalil Mehta 		return -EPROTONOSUPPORT;
1617e2cb1decSSalil Mehta 
1618b7b5d25bSGuojia Liao 	/* When device is resetting or reset failed, firmware is unable to
1619b7b5d25bSGuojia Liao 	 * handle mailbox. Just record the vlan id, and remove it after
1620fe4144d4SJian Shen 	 * reset finished.
1621fe4144d4SJian Shen 	 */
1622b7b5d25bSGuojia Liao 	if ((test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
1623b7b5d25bSGuojia Liao 	     test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) && is_kill) {
1624fe4144d4SJian Shen 		set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1625fe4144d4SJian Shen 		return -EBUSY;
1626fe4144d4SJian Shen 	}
1627fe4144d4SJian Shen 
1628d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
1629d3410018SYufeng Mo 			       HCLGE_MBX_VLAN_FILTER);
1630d3410018SYufeng Mo 	send_msg.data[HCLGEVF_VLAN_MBX_IS_KILL_OFFSET] = is_kill;
1631d3410018SYufeng Mo 	memcpy(&send_msg.data[HCLGEVF_VLAN_MBX_VLAN_ID_OFFSET], &vlan_id,
1632d3410018SYufeng Mo 	       sizeof(vlan_id));
1633d3410018SYufeng Mo 	memcpy(&send_msg.data[HCLGEVF_VLAN_MBX_PROTO_OFFSET], &proto,
1634d3410018SYufeng Mo 	       sizeof(proto));
163546ee7350SGuojia Liao 	/* when remove hw vlan filter failed, record the vlan id,
1636fe4144d4SJian Shen 	 * and try to remove it from hw later, to be consistence
1637fe4144d4SJian Shen 	 * with stack.
1638fe4144d4SJian Shen 	 */
1639d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1640fe4144d4SJian Shen 	if (is_kill && ret)
1641fe4144d4SJian Shen 		set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1642fe4144d4SJian Shen 
1643fe4144d4SJian Shen 	return ret;
1644fe4144d4SJian Shen }
1645fe4144d4SJian Shen 
1646fe4144d4SJian Shen static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev)
1647fe4144d4SJian Shen {
1648fe4144d4SJian Shen #define HCLGEVF_MAX_SYNC_COUNT	60
1649fe4144d4SJian Shen 	struct hnae3_handle *handle = &hdev->nic;
1650fe4144d4SJian Shen 	int ret, sync_cnt = 0;
1651fe4144d4SJian Shen 	u16 vlan_id;
1652fe4144d4SJian Shen 
1653fe4144d4SJian Shen 	vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1654fe4144d4SJian Shen 	while (vlan_id != VLAN_N_VID) {
1655fe4144d4SJian Shen 		ret = hclgevf_set_vlan_filter(handle, htons(ETH_P_8021Q),
1656fe4144d4SJian Shen 					      vlan_id, true);
1657fe4144d4SJian Shen 		if (ret)
1658fe4144d4SJian Shen 			return;
1659fe4144d4SJian Shen 
1660fe4144d4SJian Shen 		clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
1661fe4144d4SJian Shen 		sync_cnt++;
1662fe4144d4SJian Shen 		if (sync_cnt >= HCLGEVF_MAX_SYNC_COUNT)
1663fe4144d4SJian Shen 			return;
1664fe4144d4SJian Shen 
1665fe4144d4SJian Shen 		vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1666fe4144d4SJian Shen 	}
1667e2cb1decSSalil Mehta }
1668e2cb1decSSalil Mehta 
1669b2641e2aSYunsheng Lin static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
1670b2641e2aSYunsheng Lin {
1671b2641e2aSYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1672d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1673b2641e2aSYunsheng Lin 
1674d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
1675d3410018SYufeng Mo 			       HCLGE_MBX_VLAN_RX_OFF_CFG);
1676d3410018SYufeng Mo 	send_msg.data[0] = enable ? 1 : 0;
1677d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1678b2641e2aSYunsheng Lin }
1679b2641e2aSYunsheng Lin 
16807fa6be4fSHuazhong Tan static int hclgevf_reset_tqp(struct hnae3_handle *handle, u16 queue_id)
1681e2cb1decSSalil Mehta {
1682e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1683d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
16841a426f8bSPeng Li 	int ret;
1685e2cb1decSSalil Mehta 
16861a426f8bSPeng Li 	/* disable vf queue before send queue reset msg to PF */
16871a426f8bSPeng Li 	ret = hclgevf_tqp_enable(hdev, queue_id, 0, false);
16881a426f8bSPeng Li 	if (ret)
16897fa6be4fSHuazhong Tan 		return ret;
16901a426f8bSPeng Li 
1691d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_QUEUE_RESET, 0);
1692d3410018SYufeng Mo 	memcpy(send_msg.data, &queue_id, sizeof(queue_id));
1693d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1694e2cb1decSSalil Mehta }
1695e2cb1decSSalil Mehta 
1696818f1675SYunsheng Lin static int hclgevf_set_mtu(struct hnae3_handle *handle, int new_mtu)
1697818f1675SYunsheng Lin {
1698818f1675SYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1699d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
1700818f1675SYunsheng Lin 
1701d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_MTU, 0);
1702d3410018SYufeng Mo 	memcpy(send_msg.data, &new_mtu, sizeof(new_mtu));
1703d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1704818f1675SYunsheng Lin }
1705818f1675SYunsheng Lin 
17066988eb2aSSalil Mehta static int hclgevf_notify_client(struct hclgevf_dev *hdev,
17076988eb2aSSalil Mehta 				 enum hnae3_reset_notify_type type)
17086988eb2aSSalil Mehta {
17096988eb2aSSalil Mehta 	struct hnae3_client *client = hdev->nic_client;
17106988eb2aSSalil Mehta 	struct hnae3_handle *handle = &hdev->nic;
17116a5f6fa3SHuazhong Tan 	int ret;
17126988eb2aSSalil Mehta 
171325d1817cSHuazhong Tan 	if (!test_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state) ||
171425d1817cSHuazhong Tan 	    !client)
171525d1817cSHuazhong Tan 		return 0;
171625d1817cSHuazhong Tan 
17176988eb2aSSalil Mehta 	if (!client->ops->reset_notify)
17186988eb2aSSalil Mehta 		return -EOPNOTSUPP;
17196988eb2aSSalil Mehta 
17206a5f6fa3SHuazhong Tan 	ret = client->ops->reset_notify(handle, type);
17216a5f6fa3SHuazhong Tan 	if (ret)
17226a5f6fa3SHuazhong Tan 		dev_err(&hdev->pdev->dev, "notify nic client failed %d(%d)\n",
17236a5f6fa3SHuazhong Tan 			type, ret);
17246a5f6fa3SHuazhong Tan 
17256a5f6fa3SHuazhong Tan 	return ret;
17266988eb2aSSalil Mehta }
17276988eb2aSSalil Mehta 
1728fe735c84SHuazhong Tan static int hclgevf_notify_roce_client(struct hclgevf_dev *hdev,
1729fe735c84SHuazhong Tan 				      enum hnae3_reset_notify_type type)
1730fe735c84SHuazhong Tan {
1731fe735c84SHuazhong Tan 	struct hnae3_client *client = hdev->roce_client;
1732fe735c84SHuazhong Tan 	struct hnae3_handle *handle = &hdev->roce;
1733fe735c84SHuazhong Tan 	int ret;
1734fe735c84SHuazhong Tan 
1735fe735c84SHuazhong Tan 	if (!test_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state) || !client)
1736fe735c84SHuazhong Tan 		return 0;
1737fe735c84SHuazhong Tan 
1738fe735c84SHuazhong Tan 	if (!client->ops->reset_notify)
1739fe735c84SHuazhong Tan 		return -EOPNOTSUPP;
1740fe735c84SHuazhong Tan 
1741fe735c84SHuazhong Tan 	ret = client->ops->reset_notify(handle, type);
1742fe735c84SHuazhong Tan 	if (ret)
1743fe735c84SHuazhong Tan 		dev_err(&hdev->pdev->dev, "notify roce client failed %d(%d)",
1744fe735c84SHuazhong Tan 			type, ret);
1745fe735c84SHuazhong Tan 	return ret;
1746fe735c84SHuazhong Tan }
1747fe735c84SHuazhong Tan 
17486988eb2aSSalil Mehta static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
17496988eb2aSSalil Mehta {
1750aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_US	20000
1751aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_CNT	2000
1752aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_TIMEOUT_US	\
1753aa5c4f17SHuazhong Tan 	(HCLGEVF_RESET_WAIT_US * HCLGEVF_RESET_WAIT_CNT)
1754aa5c4f17SHuazhong Tan 
1755aa5c4f17SHuazhong Tan 	u32 val;
1756aa5c4f17SHuazhong Tan 	int ret;
17576988eb2aSSalil Mehta 
1758f28368bbSHuazhong Tan 	if (hdev->reset_type == HNAE3_VF_RESET)
175972e2fb07SHuazhong Tan 		ret = readl_poll_timeout(hdev->hw.io_base +
176072e2fb07SHuazhong Tan 					 HCLGEVF_VF_RST_ING, val,
176172e2fb07SHuazhong Tan 					 !(val & HCLGEVF_VF_RST_ING_BIT),
176272e2fb07SHuazhong Tan 					 HCLGEVF_RESET_WAIT_US,
176372e2fb07SHuazhong Tan 					 HCLGEVF_RESET_WAIT_TIMEOUT_US);
176472e2fb07SHuazhong Tan 	else
176572e2fb07SHuazhong Tan 		ret = readl_poll_timeout(hdev->hw.io_base +
176672e2fb07SHuazhong Tan 					 HCLGEVF_RST_ING, val,
1767aa5c4f17SHuazhong Tan 					 !(val & HCLGEVF_RST_ING_BITS),
1768aa5c4f17SHuazhong Tan 					 HCLGEVF_RESET_WAIT_US,
1769aa5c4f17SHuazhong Tan 					 HCLGEVF_RESET_WAIT_TIMEOUT_US);
17706988eb2aSSalil Mehta 
17716988eb2aSSalil Mehta 	/* hardware completion status should be available by this time */
1772aa5c4f17SHuazhong Tan 	if (ret) {
1773aa5c4f17SHuazhong Tan 		dev_err(&hdev->pdev->dev,
17748912fd6aSColin Ian King 			"couldn't get reset done status from h/w, timeout!\n");
1775aa5c4f17SHuazhong Tan 		return ret;
17766988eb2aSSalil Mehta 	}
17776988eb2aSSalil Mehta 
17786988eb2aSSalil Mehta 	/* we will wait a bit more to let reset of the stack to complete. This
17796988eb2aSSalil Mehta 	 * might happen in case reset assertion was made by PF. Yes, this also
17806988eb2aSSalil Mehta 	 * means we might end up waiting bit more even for VF reset.
17816988eb2aSSalil Mehta 	 */
17826988eb2aSSalil Mehta 	msleep(5000);
17836988eb2aSSalil Mehta 
17846988eb2aSSalil Mehta 	return 0;
17856988eb2aSSalil Mehta }
17866988eb2aSSalil Mehta 
17876b428b4fSHuazhong Tan static void hclgevf_reset_handshake(struct hclgevf_dev *hdev, bool enable)
17886b428b4fSHuazhong Tan {
17896b428b4fSHuazhong Tan 	u32 reg_val;
17906b428b4fSHuazhong Tan 
17916b428b4fSHuazhong Tan 	reg_val = hclgevf_read_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG);
17926b428b4fSHuazhong Tan 	if (enable)
17936b428b4fSHuazhong Tan 		reg_val |= HCLGEVF_NIC_SW_RST_RDY;
17946b428b4fSHuazhong Tan 	else
17956b428b4fSHuazhong Tan 		reg_val &= ~HCLGEVF_NIC_SW_RST_RDY;
17966b428b4fSHuazhong Tan 
17976b428b4fSHuazhong Tan 	hclgevf_write_dev(&hdev->hw, HCLGEVF_NIC_CSQ_DEPTH_REG,
17986b428b4fSHuazhong Tan 			  reg_val);
17996b428b4fSHuazhong Tan }
18006b428b4fSHuazhong Tan 
18016988eb2aSSalil Mehta static int hclgevf_reset_stack(struct hclgevf_dev *hdev)
18026988eb2aSSalil Mehta {
18037a01c897SSalil Mehta 	int ret;
18047a01c897SSalil Mehta 
18056988eb2aSSalil Mehta 	/* uninitialize the nic client */
18066a5f6fa3SHuazhong Tan 	ret = hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
18076a5f6fa3SHuazhong Tan 	if (ret)
18086a5f6fa3SHuazhong Tan 		return ret;
18096988eb2aSSalil Mehta 
18107a01c897SSalil Mehta 	/* re-initialize the hclge device */
18119c6f7085SHuazhong Tan 	ret = hclgevf_reset_hdev(hdev);
18127a01c897SSalil Mehta 	if (ret) {
18137a01c897SSalil Mehta 		dev_err(&hdev->pdev->dev,
18147a01c897SSalil Mehta 			"hclge device re-init failed, VF is disabled!\n");
18157a01c897SSalil Mehta 		return ret;
18167a01c897SSalil Mehta 	}
18176988eb2aSSalil Mehta 
18186988eb2aSSalil Mehta 	/* bring up the nic client again */
18196a5f6fa3SHuazhong Tan 	ret = hclgevf_notify_client(hdev, HNAE3_INIT_CLIENT);
18206a5f6fa3SHuazhong Tan 	if (ret)
18216a5f6fa3SHuazhong Tan 		return ret;
18226988eb2aSSalil Mehta 
18236b428b4fSHuazhong Tan 	/* clear handshake status with IMP */
18246b428b4fSHuazhong Tan 	hclgevf_reset_handshake(hdev, false);
18256b428b4fSHuazhong Tan 
18261cc9bc6eSHuazhong Tan 	/* bring up the nic to enable TX/RX again */
18271cc9bc6eSHuazhong Tan 	return hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
18286988eb2aSSalil Mehta }
18296988eb2aSSalil Mehta 
1830dea846e8SHuazhong Tan static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
1831dea846e8SHuazhong Tan {
1832ada13ee3SHuazhong Tan #define HCLGEVF_RESET_SYNC_TIME 100
1833ada13ee3SHuazhong Tan 
1834f28368bbSHuazhong Tan 	if (hdev->reset_type == HNAE3_VF_FUNC_RESET) {
1835d41884eeSHuazhong Tan 		struct hclge_vf_to_pf_msg send_msg;
1836d41884eeSHuazhong Tan 		int ret;
1837d41884eeSHuazhong Tan 
1838d3410018SYufeng Mo 		hclgevf_build_send_msg(&send_msg, HCLGE_MBX_RESET, 0);
1839d3410018SYufeng Mo 		ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1840cddd5648SHuazhong Tan 		if (ret) {
1841cddd5648SHuazhong Tan 			dev_err(&hdev->pdev->dev,
1842cddd5648SHuazhong Tan 				"failed to assert VF reset, ret = %d\n", ret);
1843cddd5648SHuazhong Tan 			return ret;
1844cddd5648SHuazhong Tan 		}
1845c88a6e7dSHuazhong Tan 		hdev->rst_stats.vf_func_rst_cnt++;
1846dea846e8SHuazhong Tan 	}
1847dea846e8SHuazhong Tan 
1848ef5f8e50SHuazhong Tan 	set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
1849ada13ee3SHuazhong Tan 	/* inform hardware that preparatory work is done */
1850ada13ee3SHuazhong Tan 	msleep(HCLGEVF_RESET_SYNC_TIME);
18516b428b4fSHuazhong Tan 	hclgevf_reset_handshake(hdev, true);
1852d41884eeSHuazhong Tan 	dev_info(&hdev->pdev->dev, "prepare reset(%d) wait done\n",
1853d41884eeSHuazhong Tan 		 hdev->reset_type);
1854dea846e8SHuazhong Tan 
1855d41884eeSHuazhong Tan 	return 0;
1856dea846e8SHuazhong Tan }
1857dea846e8SHuazhong Tan 
18583d77d0cbSHuazhong Tan static void hclgevf_dump_rst_info(struct hclgevf_dev *hdev)
18593d77d0cbSHuazhong Tan {
18603d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "VF function reset count: %u\n",
18613d77d0cbSHuazhong Tan 		 hdev->rst_stats.vf_func_rst_cnt);
18623d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "FLR reset count: %u\n",
18633d77d0cbSHuazhong Tan 		 hdev->rst_stats.flr_rst_cnt);
18643d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "VF reset count: %u\n",
18653d77d0cbSHuazhong Tan 		 hdev->rst_stats.vf_rst_cnt);
18663d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "reset done count: %u\n",
18673d77d0cbSHuazhong Tan 		 hdev->rst_stats.rst_done_cnt);
18683d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "HW reset done count: %u\n",
18693d77d0cbSHuazhong Tan 		 hdev->rst_stats.hw_rst_done_cnt);
18703d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "reset count: %u\n",
18713d77d0cbSHuazhong Tan 		 hdev->rst_stats.rst_cnt);
18723d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "reset fail count: %u\n",
18733d77d0cbSHuazhong Tan 		 hdev->rst_stats.rst_fail_cnt);
18743d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "vector0 interrupt enable status: 0x%x\n",
18753d77d0cbSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_MISC_VECTOR_REG_BASE));
18763d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "vector0 interrupt status: 0x%x\n",
18779cee2e8dSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_VECTOR0_CMDQ_STATE_REG));
18783d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "handshake status: 0x%x\n",
18793d77d0cbSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_CMDQ_TX_DEPTH_REG));
18803d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "function reset status: 0x%x\n",
18813d77d0cbSHuazhong Tan 		 hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING));
18823d77d0cbSHuazhong Tan 	dev_info(&hdev->pdev->dev, "hdev state: 0x%lx\n", hdev->state);
18833d77d0cbSHuazhong Tan }
18843d77d0cbSHuazhong Tan 
1885bbe6540eSHuazhong Tan static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev)
1886bbe6540eSHuazhong Tan {
18876b428b4fSHuazhong Tan 	/* recover handshake status with IMP when reset fail */
18886b428b4fSHuazhong Tan 	hclgevf_reset_handshake(hdev, true);
1889bbe6540eSHuazhong Tan 	hdev->rst_stats.rst_fail_cnt++;
1890adcf738bSGuojia Liao 	dev_err(&hdev->pdev->dev, "failed to reset VF(%u)\n",
1891bbe6540eSHuazhong Tan 		hdev->rst_stats.rst_fail_cnt);
1892bbe6540eSHuazhong Tan 
1893bbe6540eSHuazhong Tan 	if (hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT)
1894bbe6540eSHuazhong Tan 		set_bit(hdev->reset_type, &hdev->reset_pending);
1895bbe6540eSHuazhong Tan 
1896bbe6540eSHuazhong Tan 	if (hclgevf_is_reset_pending(hdev)) {
1897bbe6540eSHuazhong Tan 		set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
1898bbe6540eSHuazhong Tan 		hclgevf_reset_task_schedule(hdev);
18993d77d0cbSHuazhong Tan 	} else {
1900d5432455SGuojia Liao 		set_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
19013d77d0cbSHuazhong Tan 		hclgevf_dump_rst_info(hdev);
1902bbe6540eSHuazhong Tan 	}
1903bbe6540eSHuazhong Tan }
1904bbe6540eSHuazhong Tan 
19051cc9bc6eSHuazhong Tan static int hclgevf_reset_prepare(struct hclgevf_dev *hdev)
19066988eb2aSSalil Mehta {
19076988eb2aSSalil Mehta 	int ret;
19086988eb2aSSalil Mehta 
1909c88a6e7dSHuazhong Tan 	hdev->rst_stats.rst_cnt++;
19106988eb2aSSalil Mehta 
1911fe735c84SHuazhong Tan 	/* perform reset of the stack & ae device for a client */
1912fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_DOWN_CLIENT);
1913fe735c84SHuazhong Tan 	if (ret)
1914fe735c84SHuazhong Tan 		return ret;
1915fe735c84SHuazhong Tan 
19161cc9bc6eSHuazhong Tan 	rtnl_lock();
19176988eb2aSSalil Mehta 	/* bring down the nic to stop any ongoing TX/RX */
19186a5f6fa3SHuazhong Tan 	ret = hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
191929118ab9SHuazhong Tan 	rtnl_unlock();
19206a5f6fa3SHuazhong Tan 	if (ret)
19211cc9bc6eSHuazhong Tan 		return ret;
1922dea846e8SHuazhong Tan 
19231cc9bc6eSHuazhong Tan 	return hclgevf_reset_prepare_wait(hdev);
19246988eb2aSSalil Mehta }
19256988eb2aSSalil Mehta 
19261cc9bc6eSHuazhong Tan static int hclgevf_reset_rebuild(struct hclgevf_dev *hdev)
19271cc9bc6eSHuazhong Tan {
19281cc9bc6eSHuazhong Tan 	int ret;
19291cc9bc6eSHuazhong Tan 
1930c88a6e7dSHuazhong Tan 	hdev->rst_stats.hw_rst_done_cnt++;
1931fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_UNINIT_CLIENT);
1932fe735c84SHuazhong Tan 	if (ret)
1933fe735c84SHuazhong Tan 		return ret;
1934c88a6e7dSHuazhong Tan 
193529118ab9SHuazhong Tan 	rtnl_lock();
19366988eb2aSSalil Mehta 	/* now, re-initialize the nic client and ae device */
19376988eb2aSSalil Mehta 	ret = hclgevf_reset_stack(hdev);
19381cc9bc6eSHuazhong Tan 	rtnl_unlock();
19396a5f6fa3SHuazhong Tan 	if (ret) {
19406988eb2aSSalil Mehta 		dev_err(&hdev->pdev->dev, "failed to reset VF stack\n");
19411cc9bc6eSHuazhong Tan 		return ret;
19426a5f6fa3SHuazhong Tan 	}
19436988eb2aSSalil Mehta 
1944fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_INIT_CLIENT);
1945fe735c84SHuazhong Tan 	/* ignore RoCE notify error if it fails HCLGEVF_RESET_MAX_FAIL_CNT - 1
1946fe735c84SHuazhong Tan 	 * times
1947fe735c84SHuazhong Tan 	 */
1948fe735c84SHuazhong Tan 	if (ret &&
1949fe735c84SHuazhong Tan 	    hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT - 1)
1950fe735c84SHuazhong Tan 		return ret;
1951fe735c84SHuazhong Tan 
1952fe735c84SHuazhong Tan 	ret = hclgevf_notify_roce_client(hdev, HNAE3_UP_CLIENT);
1953fe735c84SHuazhong Tan 	if (ret)
1954fe735c84SHuazhong Tan 		return ret;
1955fe735c84SHuazhong Tan 
1956b644a8d4SHuazhong Tan 	hdev->last_reset_time = jiffies;
1957c88a6e7dSHuazhong Tan 	hdev->rst_stats.rst_done_cnt++;
1958bbe6540eSHuazhong Tan 	hdev->rst_stats.rst_fail_cnt = 0;
1959d5432455SGuojia Liao 	clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
1960b644a8d4SHuazhong Tan 
19611cc9bc6eSHuazhong Tan 	return 0;
19621cc9bc6eSHuazhong Tan }
19631cc9bc6eSHuazhong Tan 
19641cc9bc6eSHuazhong Tan static void hclgevf_reset(struct hclgevf_dev *hdev)
19651cc9bc6eSHuazhong Tan {
19661cc9bc6eSHuazhong Tan 	if (hclgevf_reset_prepare(hdev))
19671cc9bc6eSHuazhong Tan 		goto err_reset;
19681cc9bc6eSHuazhong Tan 
19691cc9bc6eSHuazhong Tan 	/* check if VF could successfully fetch the hardware reset completion
19701cc9bc6eSHuazhong Tan 	 * status from the hardware
19711cc9bc6eSHuazhong Tan 	 */
19721cc9bc6eSHuazhong Tan 	if (hclgevf_reset_wait(hdev)) {
19731cc9bc6eSHuazhong Tan 		/* can't do much in this situation, will disable VF */
19741cc9bc6eSHuazhong Tan 		dev_err(&hdev->pdev->dev,
19751cc9bc6eSHuazhong Tan 			"failed to fetch H/W reset completion status\n");
19761cc9bc6eSHuazhong Tan 		goto err_reset;
19771cc9bc6eSHuazhong Tan 	}
19781cc9bc6eSHuazhong Tan 
19791cc9bc6eSHuazhong Tan 	if (hclgevf_reset_rebuild(hdev))
19801cc9bc6eSHuazhong Tan 		goto err_reset;
19811cc9bc6eSHuazhong Tan 
19821cc9bc6eSHuazhong Tan 	return;
19831cc9bc6eSHuazhong Tan 
19846a5f6fa3SHuazhong Tan err_reset:
1985bbe6540eSHuazhong Tan 	hclgevf_reset_err_handle(hdev);
19866988eb2aSSalil Mehta }
19876988eb2aSSalil Mehta 
1988720bd583SHuazhong Tan static enum hnae3_reset_type hclgevf_get_reset_level(struct hclgevf_dev *hdev,
1989720bd583SHuazhong Tan 						     unsigned long *addr)
1990720bd583SHuazhong Tan {
1991720bd583SHuazhong Tan 	enum hnae3_reset_type rst_level = HNAE3_NONE_RESET;
1992720bd583SHuazhong Tan 
1993dea846e8SHuazhong Tan 	/* return the highest priority reset level amongst all */
1994b90fcc5bSHuazhong Tan 	if (test_bit(HNAE3_VF_RESET, addr)) {
1995b90fcc5bSHuazhong Tan 		rst_level = HNAE3_VF_RESET;
1996b90fcc5bSHuazhong Tan 		clear_bit(HNAE3_VF_RESET, addr);
1997b90fcc5bSHuazhong Tan 		clear_bit(HNAE3_VF_PF_FUNC_RESET, addr);
1998b90fcc5bSHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
1999b90fcc5bSHuazhong Tan 	} else if (test_bit(HNAE3_VF_FULL_RESET, addr)) {
2000dea846e8SHuazhong Tan 		rst_level = HNAE3_VF_FULL_RESET;
2001dea846e8SHuazhong Tan 		clear_bit(HNAE3_VF_FULL_RESET, addr);
2002dea846e8SHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
2003aa5c4f17SHuazhong Tan 	} else if (test_bit(HNAE3_VF_PF_FUNC_RESET, addr)) {
2004aa5c4f17SHuazhong Tan 		rst_level = HNAE3_VF_PF_FUNC_RESET;
2005aa5c4f17SHuazhong Tan 		clear_bit(HNAE3_VF_PF_FUNC_RESET, addr);
2006aa5c4f17SHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
2007dea846e8SHuazhong Tan 	} else if (test_bit(HNAE3_VF_FUNC_RESET, addr)) {
2008dea846e8SHuazhong Tan 		rst_level = HNAE3_VF_FUNC_RESET;
2009dea846e8SHuazhong Tan 		clear_bit(HNAE3_VF_FUNC_RESET, addr);
20106ff3cf07SHuazhong Tan 	} else if (test_bit(HNAE3_FLR_RESET, addr)) {
20116ff3cf07SHuazhong Tan 		rst_level = HNAE3_FLR_RESET;
20126ff3cf07SHuazhong Tan 		clear_bit(HNAE3_FLR_RESET, addr);
2013720bd583SHuazhong Tan 	}
2014720bd583SHuazhong Tan 
2015720bd583SHuazhong Tan 	return rst_level;
2016720bd583SHuazhong Tan }
2017720bd583SHuazhong Tan 
20186ae4e733SShiju Jose static void hclgevf_reset_event(struct pci_dev *pdev,
20196ae4e733SShiju Jose 				struct hnae3_handle *handle)
20206d4c3981SSalil Mehta {
20216ff3cf07SHuazhong Tan 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
20226ff3cf07SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
20236d4c3981SSalil Mehta 
20246d4c3981SSalil Mehta 	dev_info(&hdev->pdev->dev, "received reset request from VF enet\n");
20256d4c3981SSalil Mehta 
20266ff3cf07SHuazhong Tan 	if (hdev->default_reset_request)
20270742ed7cSHuazhong Tan 		hdev->reset_level =
2028720bd583SHuazhong Tan 			hclgevf_get_reset_level(hdev,
2029720bd583SHuazhong Tan 						&hdev->default_reset_request);
2030720bd583SHuazhong Tan 	else
2031dea846e8SHuazhong Tan 		hdev->reset_level = HNAE3_VF_FUNC_RESET;
20326d4c3981SSalil Mehta 
2033436667d2SSalil Mehta 	/* reset of this VF requested */
2034436667d2SSalil Mehta 	set_bit(HCLGEVF_RESET_REQUESTED, &hdev->reset_state);
2035436667d2SSalil Mehta 	hclgevf_reset_task_schedule(hdev);
20366d4c3981SSalil Mehta 
20370742ed7cSHuazhong Tan 	hdev->last_reset_time = jiffies;
20386d4c3981SSalil Mehta }
20396d4c3981SSalil Mehta 
2040720bd583SHuazhong Tan static void hclgevf_set_def_reset_request(struct hnae3_ae_dev *ae_dev,
2041720bd583SHuazhong Tan 					  enum hnae3_reset_type rst_type)
2042720bd583SHuazhong Tan {
2043720bd583SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
2044720bd583SHuazhong Tan 
2045720bd583SHuazhong Tan 	set_bit(rst_type, &hdev->default_reset_request);
2046720bd583SHuazhong Tan }
2047720bd583SHuazhong Tan 
2048f28368bbSHuazhong Tan static void hclgevf_enable_vector(struct hclgevf_misc_vector *vector, bool en)
2049f28368bbSHuazhong Tan {
2050f28368bbSHuazhong Tan 	writel(en ? 1 : 0, vector->addr);
2051f28368bbSHuazhong Tan }
2052f28368bbSHuazhong Tan 
20536ff3cf07SHuazhong Tan static void hclgevf_flr_prepare(struct hnae3_ae_dev *ae_dev)
20546ff3cf07SHuazhong Tan {
2055f28368bbSHuazhong Tan #define HCLGEVF_FLR_RETRY_WAIT_MS	500
2056f28368bbSHuazhong Tan #define HCLGEVF_FLR_RETRY_CNT		5
2057f28368bbSHuazhong Tan 
20586ff3cf07SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
2059f28368bbSHuazhong Tan 	int retry_cnt = 0;
2060f28368bbSHuazhong Tan 	int ret;
20616ff3cf07SHuazhong Tan 
2062f28368bbSHuazhong Tan retry:
2063f28368bbSHuazhong Tan 	down(&hdev->reset_sem);
2064f28368bbSHuazhong Tan 	set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2065f28368bbSHuazhong Tan 	hdev->reset_type = HNAE3_FLR_RESET;
2066f28368bbSHuazhong Tan 	ret = hclgevf_reset_prepare(hdev);
2067f28368bbSHuazhong Tan 	if (ret) {
2068f28368bbSHuazhong Tan 		dev_err(&hdev->pdev->dev, "fail to prepare FLR, ret=%d\n",
2069f28368bbSHuazhong Tan 			ret);
2070f28368bbSHuazhong Tan 		if (hdev->reset_pending ||
2071f28368bbSHuazhong Tan 		    retry_cnt++ < HCLGEVF_FLR_RETRY_CNT) {
20726ff3cf07SHuazhong Tan 			dev_err(&hdev->pdev->dev,
2073f28368bbSHuazhong Tan 				"reset_pending:0x%lx, retry_cnt:%d\n",
2074f28368bbSHuazhong Tan 				hdev->reset_pending, retry_cnt);
2075f28368bbSHuazhong Tan 			clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2076f28368bbSHuazhong Tan 			up(&hdev->reset_sem);
2077f28368bbSHuazhong Tan 			msleep(HCLGEVF_FLR_RETRY_WAIT_MS);
2078f28368bbSHuazhong Tan 			goto retry;
2079f28368bbSHuazhong Tan 		}
2080f28368bbSHuazhong Tan 	}
2081f28368bbSHuazhong Tan 
2082f28368bbSHuazhong Tan 	/* disable misc vector before FLR done */
2083f28368bbSHuazhong Tan 	hclgevf_enable_vector(&hdev->misc_vector, false);
2084f28368bbSHuazhong Tan 	hdev->rst_stats.flr_rst_cnt++;
2085f28368bbSHuazhong Tan }
2086f28368bbSHuazhong Tan 
2087f28368bbSHuazhong Tan static void hclgevf_flr_done(struct hnae3_ae_dev *ae_dev)
2088f28368bbSHuazhong Tan {
2089f28368bbSHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
2090f28368bbSHuazhong Tan 	int ret;
2091f28368bbSHuazhong Tan 
2092f28368bbSHuazhong Tan 	hclgevf_enable_vector(&hdev->misc_vector, true);
2093f28368bbSHuazhong Tan 
2094f28368bbSHuazhong Tan 	ret = hclgevf_reset_rebuild(hdev);
2095f28368bbSHuazhong Tan 	if (ret)
2096f28368bbSHuazhong Tan 		dev_warn(&hdev->pdev->dev, "fail to rebuild, ret=%d\n",
2097f28368bbSHuazhong Tan 			 ret);
2098f28368bbSHuazhong Tan 
2099f28368bbSHuazhong Tan 	hdev->reset_type = HNAE3_NONE_RESET;
2100f28368bbSHuazhong Tan 	clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2101f28368bbSHuazhong Tan 	up(&hdev->reset_sem);
21026ff3cf07SHuazhong Tan }
21036ff3cf07SHuazhong Tan 
2104e2cb1decSSalil Mehta static u32 hclgevf_get_fw_version(struct hnae3_handle *handle)
2105e2cb1decSSalil Mehta {
2106e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2107e2cb1decSSalil Mehta 
2108e2cb1decSSalil Mehta 	return hdev->fw_version;
2109e2cb1decSSalil Mehta }
2110e2cb1decSSalil Mehta 
2111e2cb1decSSalil Mehta static void hclgevf_get_misc_vector(struct hclgevf_dev *hdev)
2112e2cb1decSSalil Mehta {
2113e2cb1decSSalil Mehta 	struct hclgevf_misc_vector *vector = &hdev->misc_vector;
2114e2cb1decSSalil Mehta 
2115e2cb1decSSalil Mehta 	vector->vector_irq = pci_irq_vector(hdev->pdev,
2116e2cb1decSSalil Mehta 					    HCLGEVF_MISC_VECTOR_NUM);
2117e2cb1decSSalil Mehta 	vector->addr = hdev->hw.io_base + HCLGEVF_MISC_VECTOR_REG_BASE;
2118e2cb1decSSalil Mehta 	/* vector status always valid for Vector 0 */
2119e2cb1decSSalil Mehta 	hdev->vector_status[HCLGEVF_MISC_VECTOR_NUM] = 0;
2120e2cb1decSSalil Mehta 	hdev->vector_irq[HCLGEVF_MISC_VECTOR_NUM] = vector->vector_irq;
2121e2cb1decSSalil Mehta 
2122e2cb1decSSalil Mehta 	hdev->num_msi_left -= 1;
2123e2cb1decSSalil Mehta 	hdev->num_msi_used += 1;
2124e2cb1decSSalil Mehta }
2125e2cb1decSSalil Mehta 
212635a1e503SSalil Mehta void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev)
212735a1e503SSalil Mehta {
2128ff200099SYunsheng Lin 	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
2129ff200099SYunsheng Lin 	    !test_and_set_bit(HCLGEVF_STATE_RST_SERVICE_SCHED,
2130ff200099SYunsheng Lin 			      &hdev->state))
21310ea68902SYunsheng Lin 		mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
213235a1e503SSalil Mehta }
213335a1e503SSalil Mehta 
213407a0556aSSalil Mehta void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev)
2135e2cb1decSSalil Mehta {
2136ff200099SYunsheng Lin 	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
2137ff200099SYunsheng Lin 	    !test_and_set_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED,
2138ff200099SYunsheng Lin 			      &hdev->state))
21390ea68902SYunsheng Lin 		mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
214007a0556aSSalil Mehta }
2141e2cb1decSSalil Mehta 
2142ff200099SYunsheng Lin static void hclgevf_task_schedule(struct hclgevf_dev *hdev,
2143ff200099SYunsheng Lin 				  unsigned long delay)
2144e2cb1decSSalil Mehta {
2145d5432455SGuojia Liao 	if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
2146d5432455SGuojia Liao 	    !test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state))
21470ea68902SYunsheng Lin 		mod_delayed_work(hclgevf_wq, &hdev->service_task, delay);
2148e2cb1decSSalil Mehta }
2149e2cb1decSSalil Mehta 
2150ff200099SYunsheng Lin static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
215135a1e503SSalil Mehta {
2152d6ad7c53SGuojia Liao #define	HCLGEVF_MAX_RESET_ATTEMPTS_CNT	3
2153d6ad7c53SGuojia Liao 
2154ff200099SYunsheng Lin 	if (!test_and_clear_bit(HCLGEVF_STATE_RST_SERVICE_SCHED, &hdev->state))
2155ff200099SYunsheng Lin 		return;
2156ff200099SYunsheng Lin 
2157f28368bbSHuazhong Tan 	down(&hdev->reset_sem);
2158f28368bbSHuazhong Tan 	set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
215935a1e503SSalil Mehta 
2160436667d2SSalil Mehta 	if (test_and_clear_bit(HCLGEVF_RESET_PENDING,
2161436667d2SSalil Mehta 			       &hdev->reset_state)) {
2162436667d2SSalil Mehta 		/* PF has initmated that it is about to reset the hardware.
21639b2f3477SWeihang Li 		 * We now have to poll & check if hardware has actually
21649b2f3477SWeihang Li 		 * completed the reset sequence. On hardware reset completion,
21659b2f3477SWeihang Li 		 * VF needs to reset the client and ae device.
216635a1e503SSalil Mehta 		 */
2167436667d2SSalil Mehta 		hdev->reset_attempts = 0;
2168436667d2SSalil Mehta 
2169dea846e8SHuazhong Tan 		hdev->last_reset_time = jiffies;
2170dea846e8SHuazhong Tan 		while ((hdev->reset_type =
2171dea846e8SHuazhong Tan 			hclgevf_get_reset_level(hdev, &hdev->reset_pending))
21721cc9bc6eSHuazhong Tan 		       != HNAE3_NONE_RESET)
21731cc9bc6eSHuazhong Tan 			hclgevf_reset(hdev);
2174436667d2SSalil Mehta 	} else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
2175436667d2SSalil Mehta 				      &hdev->reset_state)) {
2176436667d2SSalil Mehta 		/* we could be here when either of below happens:
21779b2f3477SWeihang Li 		 * 1. reset was initiated due to watchdog timeout caused by
2178436667d2SSalil Mehta 		 *    a. IMP was earlier reset and our TX got choked down and
2179436667d2SSalil Mehta 		 *       which resulted in watchdog reacting and inducing VF
2180436667d2SSalil Mehta 		 *       reset. This also means our cmdq would be unreliable.
2181436667d2SSalil Mehta 		 *    b. problem in TX due to other lower layer(example link
2182436667d2SSalil Mehta 		 *       layer not functioning properly etc.)
2183436667d2SSalil Mehta 		 * 2. VF reset might have been initiated due to some config
2184436667d2SSalil Mehta 		 *    change.
2185436667d2SSalil Mehta 		 *
2186436667d2SSalil Mehta 		 * NOTE: Theres no clear way to detect above cases than to react
2187436667d2SSalil Mehta 		 * to the response of PF for this reset request. PF will ack the
2188436667d2SSalil Mehta 		 * 1b and 2. cases but we will not get any intimation about 1a
2189436667d2SSalil Mehta 		 * from PF as cmdq would be in unreliable state i.e. mailbox
2190436667d2SSalil Mehta 		 * communication between PF and VF would be broken.
219146ee7350SGuojia Liao 		 *
219246ee7350SGuojia Liao 		 * if we are never geting into pending state it means either:
2193436667d2SSalil Mehta 		 * 1. PF is not receiving our request which could be due to IMP
2194436667d2SSalil Mehta 		 *    reset
2195436667d2SSalil Mehta 		 * 2. PF is screwed
2196436667d2SSalil Mehta 		 * We cannot do much for 2. but to check first we can try reset
2197436667d2SSalil Mehta 		 * our PCIe + stack and see if it alleviates the problem.
2198436667d2SSalil Mehta 		 */
2199d6ad7c53SGuojia Liao 		if (hdev->reset_attempts > HCLGEVF_MAX_RESET_ATTEMPTS_CNT) {
2200436667d2SSalil Mehta 			/* prepare for full reset of stack + pcie interface */
2201dea846e8SHuazhong Tan 			set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending);
2202436667d2SSalil Mehta 
2203436667d2SSalil Mehta 			/* "defer" schedule the reset task again */
2204436667d2SSalil Mehta 			set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
2205436667d2SSalil Mehta 		} else {
2206436667d2SSalil Mehta 			hdev->reset_attempts++;
2207436667d2SSalil Mehta 
2208dea846e8SHuazhong Tan 			set_bit(hdev->reset_level, &hdev->reset_pending);
2209dea846e8SHuazhong Tan 			set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
2210436667d2SSalil Mehta 		}
2211dea846e8SHuazhong Tan 		hclgevf_reset_task_schedule(hdev);
2212436667d2SSalil Mehta 	}
221335a1e503SSalil Mehta 
2214afb6afdbSHuazhong Tan 	hdev->reset_type = HNAE3_NONE_RESET;
221535a1e503SSalil Mehta 	clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
2216f28368bbSHuazhong Tan 	up(&hdev->reset_sem);
221735a1e503SSalil Mehta }
221835a1e503SSalil Mehta 
2219ff200099SYunsheng Lin static void hclgevf_mailbox_service_task(struct hclgevf_dev *hdev)
2220e2cb1decSSalil Mehta {
2221ff200099SYunsheng Lin 	if (!test_and_clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state))
2222ff200099SYunsheng Lin 		return;
2223e2cb1decSSalil Mehta 
2224e2cb1decSSalil Mehta 	if (test_and_set_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state))
2225e2cb1decSSalil Mehta 		return;
2226e2cb1decSSalil Mehta 
222707a0556aSSalil Mehta 	hclgevf_mbx_async_handler(hdev);
2228e2cb1decSSalil Mehta 
2229e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
2230e2cb1decSSalil Mehta }
2231e2cb1decSSalil Mehta 
2232ff200099SYunsheng Lin static void hclgevf_keep_alive(struct hclgevf_dev *hdev)
2233a6d818e3SYunsheng Lin {
2234d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
2235a6d818e3SYunsheng Lin 	int ret;
2236a6d818e3SYunsheng Lin 
22371416d333SHuazhong Tan 	if (test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state))
2238c59a85c0SJian Shen 		return;
2239c59a85c0SJian Shen 
2240d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_KEEP_ALIVE, 0);
2241d3410018SYufeng Mo 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
2242a6d818e3SYunsheng Lin 	if (ret)
2243a6d818e3SYunsheng Lin 		dev_err(&hdev->pdev->dev,
2244a6d818e3SYunsheng Lin 			"VF sends keep alive cmd failed(=%d)\n", ret);
2245a6d818e3SYunsheng Lin }
2246a6d818e3SYunsheng Lin 
2247ff200099SYunsheng Lin static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev)
2248e2cb1decSSalil Mehta {
2249ff200099SYunsheng Lin 	unsigned long delta = round_jiffies_relative(HZ);
2250ff200099SYunsheng Lin 	struct hnae3_handle *handle = &hdev->nic;
2251e2cb1decSSalil Mehta 
2252e6394363SGuangbin Huang 	if (test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state))
2253e6394363SGuangbin Huang 		return;
2254e6394363SGuangbin Huang 
2255ff200099SYunsheng Lin 	if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) {
2256ff200099SYunsheng Lin 		delta = jiffies - hdev->last_serv_processed;
2257db01afebSliuzhongzhu 
2258ff200099SYunsheng Lin 		if (delta < round_jiffies_relative(HZ)) {
2259ff200099SYunsheng Lin 			delta = round_jiffies_relative(HZ) - delta;
2260ff200099SYunsheng Lin 			goto out;
2261db01afebSliuzhongzhu 		}
2262ff200099SYunsheng Lin 	}
2263ff200099SYunsheng Lin 
2264ff200099SYunsheng Lin 	hdev->serv_processed_cnt++;
2265ff200099SYunsheng Lin 	if (!(hdev->serv_processed_cnt % HCLGEVF_KEEP_ALIVE_TASK_INTERVAL))
2266ff200099SYunsheng Lin 		hclgevf_keep_alive(hdev);
2267ff200099SYunsheng Lin 
2268ff200099SYunsheng Lin 	if (test_bit(HCLGEVF_STATE_DOWN, &hdev->state)) {
2269ff200099SYunsheng Lin 		hdev->last_serv_processed = jiffies;
2270ff200099SYunsheng Lin 		goto out;
2271ff200099SYunsheng Lin 	}
2272ff200099SYunsheng Lin 
2273ff200099SYunsheng Lin 	if (!(hdev->serv_processed_cnt % HCLGEVF_STATS_TIMER_INTERVAL))
2274ff200099SYunsheng Lin 		hclgevf_tqps_update_stats(handle);
2275e2cb1decSSalil Mehta 
2276e2cb1decSSalil Mehta 	/* request the link status from the PF. PF would be able to tell VF
2277e2cb1decSSalil Mehta 	 * about such updates in future so we might remove this later
2278e2cb1decSSalil Mehta 	 */
2279e2cb1decSSalil Mehta 	hclgevf_request_link_info(hdev);
2280e2cb1decSSalil Mehta 
22819194d18bSliuzhongzhu 	hclgevf_update_link_mode(hdev);
22829194d18bSliuzhongzhu 
2283fe4144d4SJian Shen 	hclgevf_sync_vlan_filter(hdev);
2284fe4144d4SJian Shen 
2285ee4bcd3bSJian Shen 	hclgevf_sync_mac_table(hdev);
2286ee4bcd3bSJian Shen 
2287c631c696SJian Shen 	hclgevf_sync_promisc_mode(hdev);
2288c631c696SJian Shen 
2289ff200099SYunsheng Lin 	hdev->last_serv_processed = jiffies;
2290436667d2SSalil Mehta 
2291ff200099SYunsheng Lin out:
2292ff200099SYunsheng Lin 	hclgevf_task_schedule(hdev, delta);
2293ff200099SYunsheng Lin }
2294b3c3fe8eSYunsheng Lin 
2295ff200099SYunsheng Lin static void hclgevf_service_task(struct work_struct *work)
2296ff200099SYunsheng Lin {
2297ff200099SYunsheng Lin 	struct hclgevf_dev *hdev = container_of(work, struct hclgevf_dev,
2298ff200099SYunsheng Lin 						service_task.work);
2299ff200099SYunsheng Lin 
2300ff200099SYunsheng Lin 	hclgevf_reset_service_task(hdev);
2301ff200099SYunsheng Lin 	hclgevf_mailbox_service_task(hdev);
2302ff200099SYunsheng Lin 	hclgevf_periodic_service_task(hdev);
2303ff200099SYunsheng Lin 
2304ff200099SYunsheng Lin 	/* Handle reset and mbx again in case periodical task delays the
2305ff200099SYunsheng Lin 	 * handling by calling hclgevf_task_schedule() in
2306ff200099SYunsheng Lin 	 * hclgevf_periodic_service_task()
2307ff200099SYunsheng Lin 	 */
2308ff200099SYunsheng Lin 	hclgevf_reset_service_task(hdev);
2309ff200099SYunsheng Lin 	hclgevf_mailbox_service_task(hdev);
2310e2cb1decSSalil Mehta }
2311e2cb1decSSalil Mehta 
2312e2cb1decSSalil Mehta static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr)
2313e2cb1decSSalil Mehta {
2314e2cb1decSSalil Mehta 	hclgevf_write_dev(&hdev->hw, HCLGEVF_VECTOR0_CMDQ_SRC_REG, regclr);
2315e2cb1decSSalil Mehta }
2316e2cb1decSSalil Mehta 
2317b90fcc5bSHuazhong Tan static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
2318b90fcc5bSHuazhong Tan 						      u32 *clearval)
2319e2cb1decSSalil Mehta {
232013050921SHuazhong Tan 	u32 val, cmdq_stat_reg, rst_ing_reg;
2321e2cb1decSSalil Mehta 
2322e2cb1decSSalil Mehta 	/* fetch the events from their corresponding regs */
232313050921SHuazhong Tan 	cmdq_stat_reg = hclgevf_read_dev(&hdev->hw,
23249cee2e8dSHuazhong Tan 					 HCLGEVF_VECTOR0_CMDQ_STATE_REG);
2325e2cb1decSSalil Mehta 
232613050921SHuazhong Tan 	if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_stat_reg) {
2327b90fcc5bSHuazhong Tan 		rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
2328b90fcc5bSHuazhong Tan 		dev_info(&hdev->pdev->dev,
2329b90fcc5bSHuazhong Tan 			 "receive reset interrupt 0x%x!\n", rst_ing_reg);
2330b90fcc5bSHuazhong Tan 		set_bit(HNAE3_VF_RESET, &hdev->reset_pending);
2331b90fcc5bSHuazhong Tan 		set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
2332ef5f8e50SHuazhong Tan 		set_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
233313050921SHuazhong Tan 		*clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B);
2334c88a6e7dSHuazhong Tan 		hdev->rst_stats.vf_rst_cnt++;
233572e2fb07SHuazhong Tan 		/* set up VF hardware reset status, its PF will clear
233672e2fb07SHuazhong Tan 		 * this status when PF has initialized done.
233772e2fb07SHuazhong Tan 		 */
233872e2fb07SHuazhong Tan 		val = hclgevf_read_dev(&hdev->hw, HCLGEVF_VF_RST_ING);
233972e2fb07SHuazhong Tan 		hclgevf_write_dev(&hdev->hw, HCLGEVF_VF_RST_ING,
234072e2fb07SHuazhong Tan 				  val | HCLGEVF_VF_RST_ING_BIT);
2341b90fcc5bSHuazhong Tan 		return HCLGEVF_VECTOR0_EVENT_RST;
2342b90fcc5bSHuazhong Tan 	}
2343b90fcc5bSHuazhong Tan 
2344e2cb1decSSalil Mehta 	/* check for vector0 mailbox(=CMDQ RX) event source */
234513050921SHuazhong Tan 	if (BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B) & cmdq_stat_reg) {
234613050921SHuazhong Tan 		/* for revision 0x21, clearing interrupt is writing bit 0
234713050921SHuazhong Tan 		 * to the clear register, writing bit 1 means to keep the
234813050921SHuazhong Tan 		 * old value.
234913050921SHuazhong Tan 		 * for revision 0x20, the clear register is a read & write
235013050921SHuazhong Tan 		 * register, so we should just write 0 to the bit we are
235113050921SHuazhong Tan 		 * handling, and keep other bits as cmdq_stat_reg.
235213050921SHuazhong Tan 		 */
2353295ba232SGuangbin Huang 		if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2)
235413050921SHuazhong Tan 			*clearval = ~(1U << HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
235513050921SHuazhong Tan 		else
235613050921SHuazhong Tan 			*clearval = cmdq_stat_reg &
235713050921SHuazhong Tan 				    ~BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
235813050921SHuazhong Tan 
2359b90fcc5bSHuazhong Tan 		return HCLGEVF_VECTOR0_EVENT_MBX;
2360e2cb1decSSalil Mehta 	}
2361e2cb1decSSalil Mehta 
2362e45afb39SHuazhong Tan 	/* print other vector0 event source */
2363e45afb39SHuazhong Tan 	dev_info(&hdev->pdev->dev,
2364e45afb39SHuazhong Tan 		 "vector 0 interrupt from unknown source, cmdq_src = %#x\n",
2365e45afb39SHuazhong Tan 		 cmdq_stat_reg);
2366e2cb1decSSalil Mehta 
2367b90fcc5bSHuazhong Tan 	return HCLGEVF_VECTOR0_EVENT_OTHER;
2368e2cb1decSSalil Mehta }
2369e2cb1decSSalil Mehta 
2370e2cb1decSSalil Mehta static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
2371e2cb1decSSalil Mehta {
2372b90fcc5bSHuazhong Tan 	enum hclgevf_evt_cause event_cause;
2373e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = data;
2374e2cb1decSSalil Mehta 	u32 clearval;
2375e2cb1decSSalil Mehta 
2376e2cb1decSSalil Mehta 	hclgevf_enable_vector(&hdev->misc_vector, false);
2377b90fcc5bSHuazhong Tan 	event_cause = hclgevf_check_evt_cause(hdev, &clearval);
2378e2cb1decSSalil Mehta 
2379b90fcc5bSHuazhong Tan 	switch (event_cause) {
2380b90fcc5bSHuazhong Tan 	case HCLGEVF_VECTOR0_EVENT_RST:
2381b90fcc5bSHuazhong Tan 		hclgevf_reset_task_schedule(hdev);
2382b90fcc5bSHuazhong Tan 		break;
2383b90fcc5bSHuazhong Tan 	case HCLGEVF_VECTOR0_EVENT_MBX:
238407a0556aSSalil Mehta 		hclgevf_mbx_handler(hdev);
2385b90fcc5bSHuazhong Tan 		break;
2386b90fcc5bSHuazhong Tan 	default:
2387b90fcc5bSHuazhong Tan 		break;
2388b90fcc5bSHuazhong Tan 	}
2389e2cb1decSSalil Mehta 
2390b90fcc5bSHuazhong Tan 	if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER) {
2391e2cb1decSSalil Mehta 		hclgevf_clear_event_cause(hdev, clearval);
2392e2cb1decSSalil Mehta 		hclgevf_enable_vector(&hdev->misc_vector, true);
2393b90fcc5bSHuazhong Tan 	}
2394e2cb1decSSalil Mehta 
2395e2cb1decSSalil Mehta 	return IRQ_HANDLED;
2396e2cb1decSSalil Mehta }
2397e2cb1decSSalil Mehta 
2398e2cb1decSSalil Mehta static int hclgevf_configure(struct hclgevf_dev *hdev)
2399e2cb1decSSalil Mehta {
2400e2cb1decSSalil Mehta 	int ret;
2401e2cb1decSSalil Mehta 
240292f11ea1SJian Shen 	/* get current port based vlan state from PF */
240392f11ea1SJian Shen 	ret = hclgevf_get_port_base_vlan_filter_state(hdev);
240492f11ea1SJian Shen 	if (ret)
240592f11ea1SJian Shen 		return ret;
240692f11ea1SJian Shen 
2407e2cb1decSSalil Mehta 	/* get queue configuration from PF */
24086cee6fc3SJian Shen 	ret = hclgevf_get_queue_info(hdev);
2409e2cb1decSSalil Mehta 	if (ret)
2410e2cb1decSSalil Mehta 		return ret;
2411c0425944SPeng Li 
2412c0425944SPeng Li 	/* get queue depth info from PF */
2413c0425944SPeng Li 	ret = hclgevf_get_queue_depth(hdev);
2414c0425944SPeng Li 	if (ret)
2415c0425944SPeng Li 		return ret;
2416c0425944SPeng Li 
24179c3e7130Sliuzhongzhu 	ret = hclgevf_get_pf_media_type(hdev);
24189c3e7130Sliuzhongzhu 	if (ret)
24199c3e7130Sliuzhongzhu 		return ret;
24209c3e7130Sliuzhongzhu 
2421e2cb1decSSalil Mehta 	/* get tc configuration from PF */
2422e2cb1decSSalil Mehta 	return hclgevf_get_tc_info(hdev);
2423e2cb1decSSalil Mehta }
2424e2cb1decSSalil Mehta 
24257a01c897SSalil Mehta static int hclgevf_alloc_hdev(struct hnae3_ae_dev *ae_dev)
24267a01c897SSalil Mehta {
24277a01c897SSalil Mehta 	struct pci_dev *pdev = ae_dev->pdev;
24281154bb26SPeng Li 	struct hclgevf_dev *hdev;
24297a01c897SSalil Mehta 
24307a01c897SSalil Mehta 	hdev = devm_kzalloc(&pdev->dev, sizeof(*hdev), GFP_KERNEL);
24317a01c897SSalil Mehta 	if (!hdev)
24327a01c897SSalil Mehta 		return -ENOMEM;
24337a01c897SSalil Mehta 
24347a01c897SSalil Mehta 	hdev->pdev = pdev;
24357a01c897SSalil Mehta 	hdev->ae_dev = ae_dev;
24367a01c897SSalil Mehta 	ae_dev->priv = hdev;
24377a01c897SSalil Mehta 
24387a01c897SSalil Mehta 	return 0;
24397a01c897SSalil Mehta }
24407a01c897SSalil Mehta 
2441e2cb1decSSalil Mehta static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
2442e2cb1decSSalil Mehta {
2443e2cb1decSSalil Mehta 	struct hnae3_handle *roce = &hdev->roce;
2444e2cb1decSSalil Mehta 	struct hnae3_handle *nic = &hdev->nic;
2445e2cb1decSSalil Mehta 
244607acf909SJian Shen 	roce->rinfo.num_vectors = hdev->num_roce_msix;
2447e2cb1decSSalil Mehta 
2448e2cb1decSSalil Mehta 	if (hdev->num_msi_left < roce->rinfo.num_vectors ||
2449e2cb1decSSalil Mehta 	    hdev->num_msi_left == 0)
2450e2cb1decSSalil Mehta 		return -EINVAL;
2451e2cb1decSSalil Mehta 
245207acf909SJian Shen 	roce->rinfo.base_vector = hdev->roce_base_vector;
2453e2cb1decSSalil Mehta 
2454e2cb1decSSalil Mehta 	roce->rinfo.netdev = nic->kinfo.netdev;
2455e2cb1decSSalil Mehta 	roce->rinfo.roce_io_base = hdev->hw.io_base;
245630ae7f8aSHuazhong Tan 	roce->rinfo.roce_mem_base = hdev->hw.mem_base;
2457e2cb1decSSalil Mehta 
2458e2cb1decSSalil Mehta 	roce->pdev = nic->pdev;
2459e2cb1decSSalil Mehta 	roce->ae_algo = nic->ae_algo;
2460e2cb1decSSalil Mehta 	roce->numa_node_mask = nic->numa_node_mask;
2461e2cb1decSSalil Mehta 
2462e2cb1decSSalil Mehta 	return 0;
2463e2cb1decSSalil Mehta }
2464e2cb1decSSalil Mehta 
2465b26a6feaSPeng Li static int hclgevf_config_gro(struct hclgevf_dev *hdev, bool en)
2466b26a6feaSPeng Li {
2467b26a6feaSPeng Li 	struct hclgevf_cfg_gro_status_cmd *req;
2468b26a6feaSPeng Li 	struct hclgevf_desc desc;
2469b26a6feaSPeng Li 	int ret;
2470b26a6feaSPeng Li 
2471b26a6feaSPeng Li 	if (!hnae3_dev_gro_supported(hdev))
2472b26a6feaSPeng Li 		return 0;
2473b26a6feaSPeng Li 
2474b26a6feaSPeng Li 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_GRO_GENERIC_CONFIG,
2475b26a6feaSPeng Li 				     false);
2476b26a6feaSPeng Li 	req = (struct hclgevf_cfg_gro_status_cmd *)desc.data;
2477b26a6feaSPeng Li 
2478fb9e44d6SHuazhong Tan 	req->gro_en = en ? 1 : 0;
2479b26a6feaSPeng Li 
2480b26a6feaSPeng Li 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
2481b26a6feaSPeng Li 	if (ret)
2482b26a6feaSPeng Li 		dev_err(&hdev->pdev->dev,
2483b26a6feaSPeng Li 			"VF GRO hardware config cmd failed, ret = %d.\n", ret);
2484b26a6feaSPeng Li 
2485b26a6feaSPeng Li 	return ret;
2486b26a6feaSPeng Li }
2487b26a6feaSPeng Li 
248887ce161eSGuangbin Huang static int hclgevf_rss_init_cfg(struct hclgevf_dev *hdev)
2489e2cb1decSSalil Mehta {
249087ce161eSGuangbin Huang 	u16 rss_ind_tbl_size = hdev->ae_dev->dev_specs.rss_ind_tbl_size;
2491e2cb1decSSalil Mehta 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
2492944de484SGuojia Liao 	struct hclgevf_rss_tuple_cfg *tuple_sets;
24934093d1a2SGuangbin Huang 	u32 i;
2494e2cb1decSSalil Mehta 
2495944de484SGuojia Liao 	rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_TOEPLITZ;
24964093d1a2SGuangbin Huang 	rss_cfg->rss_size = hdev->nic.kinfo.rss_size;
2497944de484SGuojia Liao 	tuple_sets = &rss_cfg->rss_tuple_sets;
2498295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
249987ce161eSGuangbin Huang 		u8 *rss_ind_tbl;
250087ce161eSGuangbin Huang 
2501472d7eceSJian Shen 		rss_cfg->hash_algo = HCLGEVF_RSS_HASH_ALGO_SIMPLE;
250287ce161eSGuangbin Huang 
250387ce161eSGuangbin Huang 		rss_ind_tbl = devm_kcalloc(&hdev->pdev->dev, rss_ind_tbl_size,
250487ce161eSGuangbin Huang 					   sizeof(*rss_ind_tbl), GFP_KERNEL);
250587ce161eSGuangbin Huang 		if (!rss_ind_tbl)
250687ce161eSGuangbin Huang 			return -ENOMEM;
250787ce161eSGuangbin Huang 
250887ce161eSGuangbin Huang 		rss_cfg->rss_indirection_tbl = rss_ind_tbl;
2509472d7eceSJian Shen 		memcpy(rss_cfg->rss_hash_key, hclgevf_hash_key,
2510374ad291SJian Shen 		       HCLGEVF_RSS_KEY_SIZE);
2511374ad291SJian Shen 
2512944de484SGuojia Liao 		tuple_sets->ipv4_tcp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2513944de484SGuojia Liao 		tuple_sets->ipv4_udp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2514944de484SGuojia Liao 		tuple_sets->ipv4_sctp_en = HCLGEVF_RSS_INPUT_TUPLE_SCTP;
2515944de484SGuojia Liao 		tuple_sets->ipv4_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2516944de484SGuojia Liao 		tuple_sets->ipv6_tcp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2517944de484SGuojia Liao 		tuple_sets->ipv6_udp_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2518ab6e32d2SJian Shen 		tuple_sets->ipv6_sctp_en =
2519ab6e32d2SJian Shen 			hdev->ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2 ?
2520ab6e32d2SJian Shen 					HCLGEVF_RSS_INPUT_TUPLE_SCTP_NO_PORT :
2521ab6e32d2SJian Shen 					HCLGEVF_RSS_INPUT_TUPLE_SCTP;
2522944de484SGuojia Liao 		tuple_sets->ipv6_fragment_en = HCLGEVF_RSS_INPUT_TUPLE_OTHER;
2523374ad291SJian Shen 	}
2524374ad291SJian Shen 
25259b2f3477SWeihang Li 	/* Initialize RSS indirect table */
252687ce161eSGuangbin Huang 	for (i = 0; i < rss_ind_tbl_size; i++)
25274093d1a2SGuangbin Huang 		rss_cfg->rss_indirection_tbl[i] = i % rss_cfg->rss_size;
252887ce161eSGuangbin Huang 
252987ce161eSGuangbin Huang 	return 0;
2530944de484SGuojia Liao }
2531944de484SGuojia Liao 
2532944de484SGuojia Liao static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
2533944de484SGuojia Liao {
2534944de484SGuojia Liao 	struct hclgevf_rss_cfg *rss_cfg = &hdev->rss_cfg;
2535944de484SGuojia Liao 	int ret;
2536944de484SGuojia Liao 
2537295ba232SGuangbin Huang 	if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
2538944de484SGuojia Liao 		ret = hclgevf_set_rss_algo_key(hdev, rss_cfg->hash_algo,
2539944de484SGuojia Liao 					       rss_cfg->rss_hash_key);
2540944de484SGuojia Liao 		if (ret)
2541944de484SGuojia Liao 			return ret;
2542944de484SGuojia Liao 
2543944de484SGuojia Liao 		ret = hclgevf_set_rss_input_tuple(hdev, rss_cfg);
2544944de484SGuojia Liao 		if (ret)
2545944de484SGuojia Liao 			return ret;
2546944de484SGuojia Liao 	}
2547e2cb1decSSalil Mehta 
2548e2cb1decSSalil Mehta 	ret = hclgevf_set_rss_indir_table(hdev);
2549e2cb1decSSalil Mehta 	if (ret)
2550e2cb1decSSalil Mehta 		return ret;
2551e2cb1decSSalil Mehta 
25524093d1a2SGuangbin Huang 	return hclgevf_set_rss_tc_mode(hdev, rss_cfg->rss_size);
2553e2cb1decSSalil Mehta }
2554e2cb1decSSalil Mehta 
2555e2cb1decSSalil Mehta static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev)
2556e2cb1decSSalil Mehta {
2557e2cb1decSSalil Mehta 	return hclgevf_set_vlan_filter(&hdev->nic, htons(ETH_P_8021Q), 0,
2558e2cb1decSSalil Mehta 				       false);
2559e2cb1decSSalil Mehta }
2560e2cb1decSSalil Mehta 
2561ff200099SYunsheng Lin static void hclgevf_flush_link_update(struct hclgevf_dev *hdev)
2562ff200099SYunsheng Lin {
2563ff200099SYunsheng Lin #define HCLGEVF_FLUSH_LINK_TIMEOUT	100000
2564ff200099SYunsheng Lin 
2565ff200099SYunsheng Lin 	unsigned long last = hdev->serv_processed_cnt;
2566ff200099SYunsheng Lin 	int i = 0;
2567ff200099SYunsheng Lin 
2568ff200099SYunsheng Lin 	while (test_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state) &&
2569ff200099SYunsheng Lin 	       i++ < HCLGEVF_FLUSH_LINK_TIMEOUT &&
2570ff200099SYunsheng Lin 	       last == hdev->serv_processed_cnt)
2571ff200099SYunsheng Lin 		usleep_range(1, 1);
2572ff200099SYunsheng Lin }
2573ff200099SYunsheng Lin 
25748cdb992fSJian Shen static void hclgevf_set_timer_task(struct hnae3_handle *handle, bool enable)
25758cdb992fSJian Shen {
25768cdb992fSJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
25778cdb992fSJian Shen 
25788cdb992fSJian Shen 	if (enable) {
2579ff200099SYunsheng Lin 		hclgevf_task_schedule(hdev, 0);
25808cdb992fSJian Shen 	} else {
2581b3c3fe8eSYunsheng Lin 		set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2582ff200099SYunsheng Lin 
2583ff200099SYunsheng Lin 		/* flush memory to make sure DOWN is seen by service task */
2584ff200099SYunsheng Lin 		smp_mb__before_atomic();
2585ff200099SYunsheng Lin 		hclgevf_flush_link_update(hdev);
25868cdb992fSJian Shen 	}
25878cdb992fSJian Shen }
25888cdb992fSJian Shen 
2589e2cb1decSSalil Mehta static int hclgevf_ae_start(struct hnae3_handle *handle)
2590e2cb1decSSalil Mehta {
2591e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2592e2cb1decSSalil Mehta 
2593e2cb1decSSalil Mehta 	hclgevf_reset_tqp_stats(handle);
2594e2cb1decSSalil Mehta 
2595e2cb1decSSalil Mehta 	hclgevf_request_link_info(hdev);
2596e2cb1decSSalil Mehta 
25979194d18bSliuzhongzhu 	hclgevf_update_link_mode(hdev);
25989194d18bSliuzhongzhu 
2599e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2600e2cb1decSSalil Mehta 
2601e2cb1decSSalil Mehta 	return 0;
2602e2cb1decSSalil Mehta }
2603e2cb1decSSalil Mehta 
2604e2cb1decSSalil Mehta static void hclgevf_ae_stop(struct hnae3_handle *handle)
2605e2cb1decSSalil Mehta {
2606e2cb1decSSalil Mehta 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
260739cfbc9cSHuazhong Tan 	int i;
2608e2cb1decSSalil Mehta 
26092f7e4896SFuyun Liang 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
26102f7e4896SFuyun Liang 
2611146e92c1SHuazhong Tan 	if (hdev->reset_type != HNAE3_VF_RESET)
261239cfbc9cSHuazhong Tan 		for (i = 0; i < handle->kinfo.num_tqps; i++)
2613146e92c1SHuazhong Tan 			if (hclgevf_reset_tqp(handle, i))
2614146e92c1SHuazhong Tan 				break;
261539cfbc9cSHuazhong Tan 
2616e2cb1decSSalil Mehta 	hclgevf_reset_tqp_stats(handle);
26178cc6c1f7SFuyun Liang 	hclgevf_update_link_status(hdev, 0);
2618e2cb1decSSalil Mehta }
2619e2cb1decSSalil Mehta 
2620a6d818e3SYunsheng Lin static int hclgevf_set_alive(struct hnae3_handle *handle, bool alive)
2621a6d818e3SYunsheng Lin {
2622d3410018SYufeng Mo #define HCLGEVF_STATE_ALIVE	1
2623d3410018SYufeng Mo #define HCLGEVF_STATE_NOT_ALIVE	0
2624a6d818e3SYunsheng Lin 
2625d3410018SYufeng Mo 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2626d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
2627d3410018SYufeng Mo 
2628d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_ALIVE, 0);
2629d3410018SYufeng Mo 	send_msg.data[0] = alive ? HCLGEVF_STATE_ALIVE :
2630d3410018SYufeng Mo 				HCLGEVF_STATE_NOT_ALIVE;
2631d3410018SYufeng Mo 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
2632a6d818e3SYunsheng Lin }
2633a6d818e3SYunsheng Lin 
2634a6d818e3SYunsheng Lin static int hclgevf_client_start(struct hnae3_handle *handle)
2635a6d818e3SYunsheng Lin {
2636f621df96SQinglang Miao 	return hclgevf_set_alive(handle, true);
2637a6d818e3SYunsheng Lin }
2638a6d818e3SYunsheng Lin 
2639a6d818e3SYunsheng Lin static void hclgevf_client_stop(struct hnae3_handle *handle)
2640a6d818e3SYunsheng Lin {
2641a6d818e3SYunsheng Lin 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2642a6d818e3SYunsheng Lin 	int ret;
2643a6d818e3SYunsheng Lin 
2644a6d818e3SYunsheng Lin 	ret = hclgevf_set_alive(handle, false);
2645a6d818e3SYunsheng Lin 	if (ret)
2646a6d818e3SYunsheng Lin 		dev_warn(&hdev->pdev->dev,
2647a6d818e3SYunsheng Lin 			 "%s failed %d\n", __func__, ret);
2648a6d818e3SYunsheng Lin }
2649a6d818e3SYunsheng Lin 
2650e2cb1decSSalil Mehta static void hclgevf_state_init(struct hclgevf_dev *hdev)
2651e2cb1decSSalil Mehta {
2652e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state);
2653e2cb1decSSalil Mehta 	clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
2654d5432455SGuojia Liao 	clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
2655e2cb1decSSalil Mehta 
2656b3c3fe8eSYunsheng Lin 	INIT_DELAYED_WORK(&hdev->service_task, hclgevf_service_task);
265735a1e503SSalil Mehta 
2658e2cb1decSSalil Mehta 	mutex_init(&hdev->mbx_resp.mbx_mutex);
2659f28368bbSHuazhong Tan 	sema_init(&hdev->reset_sem, 1);
2660e2cb1decSSalil Mehta 
2661ee4bcd3bSJian Shen 	spin_lock_init(&hdev->mac_table.mac_list_lock);
2662ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&hdev->mac_table.uc_mac_list);
2663ee4bcd3bSJian Shen 	INIT_LIST_HEAD(&hdev->mac_table.mc_mac_list);
2664ee4bcd3bSJian Shen 
2665e2cb1decSSalil Mehta 	/* bring the device down */
2666e2cb1decSSalil Mehta 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2667e2cb1decSSalil Mehta }
2668e2cb1decSSalil Mehta 
2669e2cb1decSSalil Mehta static void hclgevf_state_uninit(struct hclgevf_dev *hdev)
2670e2cb1decSSalil Mehta {
2671e2cb1decSSalil Mehta 	set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2672acfc3d55SHuazhong Tan 	set_bit(HCLGEVF_STATE_REMOVING, &hdev->state);
2673e2cb1decSSalil Mehta 
2674b3c3fe8eSYunsheng Lin 	if (hdev->service_task.work.func)
2675b3c3fe8eSYunsheng Lin 		cancel_delayed_work_sync(&hdev->service_task);
2676e2cb1decSSalil Mehta 
2677e2cb1decSSalil Mehta 	mutex_destroy(&hdev->mbx_resp.mbx_mutex);
2678e2cb1decSSalil Mehta }
2679e2cb1decSSalil Mehta 
2680e2cb1decSSalil Mehta static int hclgevf_init_msi(struct hclgevf_dev *hdev)
2681e2cb1decSSalil Mehta {
2682e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
2683e2cb1decSSalil Mehta 	int vectors;
2684e2cb1decSSalil Mehta 	int i;
2685e2cb1decSSalil Mehta 
2686580a05f9SYonglong Liu 	if (hnae3_dev_roce_supported(hdev))
268707acf909SJian Shen 		vectors = pci_alloc_irq_vectors(pdev,
268807acf909SJian Shen 						hdev->roce_base_msix_offset + 1,
268907acf909SJian Shen 						hdev->num_msi,
269007acf909SJian Shen 						PCI_IRQ_MSIX);
269107acf909SJian Shen 	else
2692580a05f9SYonglong Liu 		vectors = pci_alloc_irq_vectors(pdev, HNAE3_MIN_VECTOR_NUM,
2693580a05f9SYonglong Liu 						hdev->num_msi,
2694e2cb1decSSalil Mehta 						PCI_IRQ_MSI | PCI_IRQ_MSIX);
269507acf909SJian Shen 
2696e2cb1decSSalil Mehta 	if (vectors < 0) {
2697e2cb1decSSalil Mehta 		dev_err(&pdev->dev,
2698e2cb1decSSalil Mehta 			"failed(%d) to allocate MSI/MSI-X vectors\n",
2699e2cb1decSSalil Mehta 			vectors);
2700e2cb1decSSalil Mehta 		return vectors;
2701e2cb1decSSalil Mehta 	}
2702e2cb1decSSalil Mehta 	if (vectors < hdev->num_msi)
2703e2cb1decSSalil Mehta 		dev_warn(&hdev->pdev->dev,
2704adcf738bSGuojia Liao 			 "requested %u MSI/MSI-X, but allocated %d MSI/MSI-X\n",
2705e2cb1decSSalil Mehta 			 hdev->num_msi, vectors);
2706e2cb1decSSalil Mehta 
2707e2cb1decSSalil Mehta 	hdev->num_msi = vectors;
2708e2cb1decSSalil Mehta 	hdev->num_msi_left = vectors;
2709580a05f9SYonglong Liu 
2710e2cb1decSSalil Mehta 	hdev->base_msi_vector = pdev->irq;
271107acf909SJian Shen 	hdev->roce_base_vector = pdev->irq + hdev->roce_base_msix_offset;
2712e2cb1decSSalil Mehta 
2713e2cb1decSSalil Mehta 	hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi,
2714e2cb1decSSalil Mehta 					   sizeof(u16), GFP_KERNEL);
2715e2cb1decSSalil Mehta 	if (!hdev->vector_status) {
2716e2cb1decSSalil Mehta 		pci_free_irq_vectors(pdev);
2717e2cb1decSSalil Mehta 		return -ENOMEM;
2718e2cb1decSSalil Mehta 	}
2719e2cb1decSSalil Mehta 
2720e2cb1decSSalil Mehta 	for (i = 0; i < hdev->num_msi; i++)
2721e2cb1decSSalil Mehta 		hdev->vector_status[i] = HCLGEVF_INVALID_VPORT;
2722e2cb1decSSalil Mehta 
2723e2cb1decSSalil Mehta 	hdev->vector_irq = devm_kcalloc(&pdev->dev, hdev->num_msi,
2724e2cb1decSSalil Mehta 					sizeof(int), GFP_KERNEL);
2725e2cb1decSSalil Mehta 	if (!hdev->vector_irq) {
2726862d969aSHuazhong Tan 		devm_kfree(&pdev->dev, hdev->vector_status);
2727e2cb1decSSalil Mehta 		pci_free_irq_vectors(pdev);
2728e2cb1decSSalil Mehta 		return -ENOMEM;
2729e2cb1decSSalil Mehta 	}
2730e2cb1decSSalil Mehta 
2731e2cb1decSSalil Mehta 	return 0;
2732e2cb1decSSalil Mehta }
2733e2cb1decSSalil Mehta 
2734e2cb1decSSalil Mehta static void hclgevf_uninit_msi(struct hclgevf_dev *hdev)
2735e2cb1decSSalil Mehta {
2736e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
2737e2cb1decSSalil Mehta 
2738862d969aSHuazhong Tan 	devm_kfree(&pdev->dev, hdev->vector_status);
2739862d969aSHuazhong Tan 	devm_kfree(&pdev->dev, hdev->vector_irq);
2740e2cb1decSSalil Mehta 	pci_free_irq_vectors(pdev);
2741e2cb1decSSalil Mehta }
2742e2cb1decSSalil Mehta 
2743e2cb1decSSalil Mehta static int hclgevf_misc_irq_init(struct hclgevf_dev *hdev)
2744e2cb1decSSalil Mehta {
2745cdd332acSGuojia Liao 	int ret;
2746e2cb1decSSalil Mehta 
2747e2cb1decSSalil Mehta 	hclgevf_get_misc_vector(hdev);
2748e2cb1decSSalil Mehta 
2749f97c4d82SYonglong Liu 	snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s",
2750f97c4d82SYonglong Liu 		 HCLGEVF_NAME, pci_name(hdev->pdev));
2751e2cb1decSSalil Mehta 	ret = request_irq(hdev->misc_vector.vector_irq, hclgevf_misc_irq_handle,
2752f97c4d82SYonglong Liu 			  0, hdev->misc_vector.name, hdev);
2753e2cb1decSSalil Mehta 	if (ret) {
2754e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev, "VF failed to request misc irq(%d)\n",
2755e2cb1decSSalil Mehta 			hdev->misc_vector.vector_irq);
2756e2cb1decSSalil Mehta 		return ret;
2757e2cb1decSSalil Mehta 	}
2758e2cb1decSSalil Mehta 
27591819e409SXi Wang 	hclgevf_clear_event_cause(hdev, 0);
27601819e409SXi Wang 
2761e2cb1decSSalil Mehta 	/* enable misc. vector(vector 0) */
2762e2cb1decSSalil Mehta 	hclgevf_enable_vector(&hdev->misc_vector, true);
2763e2cb1decSSalil Mehta 
2764e2cb1decSSalil Mehta 	return ret;
2765e2cb1decSSalil Mehta }
2766e2cb1decSSalil Mehta 
2767e2cb1decSSalil Mehta static void hclgevf_misc_irq_uninit(struct hclgevf_dev *hdev)
2768e2cb1decSSalil Mehta {
2769e2cb1decSSalil Mehta 	/* disable misc vector(vector 0) */
2770e2cb1decSSalil Mehta 	hclgevf_enable_vector(&hdev->misc_vector, false);
27711819e409SXi Wang 	synchronize_irq(hdev->misc_vector.vector_irq);
2772e2cb1decSSalil Mehta 	free_irq(hdev->misc_vector.vector_irq, hdev);
2773e2cb1decSSalil Mehta 	hclgevf_free_vector(hdev, 0);
2774e2cb1decSSalil Mehta }
2775e2cb1decSSalil Mehta 
2776bb87be87SYonglong Liu static void hclgevf_info_show(struct hclgevf_dev *hdev)
2777bb87be87SYonglong Liu {
2778bb87be87SYonglong Liu 	struct device *dev = &hdev->pdev->dev;
2779bb87be87SYonglong Liu 
2780bb87be87SYonglong Liu 	dev_info(dev, "VF info begin:\n");
2781bb87be87SYonglong Liu 
2782adcf738bSGuojia Liao 	dev_info(dev, "Task queue pairs numbers: %u\n", hdev->num_tqps);
2783adcf738bSGuojia Liao 	dev_info(dev, "Desc num per TX queue: %u\n", hdev->num_tx_desc);
2784adcf738bSGuojia Liao 	dev_info(dev, "Desc num per RX queue: %u\n", hdev->num_rx_desc);
2785adcf738bSGuojia Liao 	dev_info(dev, "Numbers of vports: %u\n", hdev->num_alloc_vport);
2786adcf738bSGuojia Liao 	dev_info(dev, "HW tc map: 0x%x\n", hdev->hw_tc_map);
2787adcf738bSGuojia Liao 	dev_info(dev, "PF media type of this VF: %u\n",
2788bb87be87SYonglong Liu 		 hdev->hw.mac.media_type);
2789bb87be87SYonglong Liu 
2790bb87be87SYonglong Liu 	dev_info(dev, "VF info end.\n");
2791bb87be87SYonglong Liu }
2792bb87be87SYonglong Liu 
27931db58f86SHuazhong Tan static int hclgevf_init_nic_client_instance(struct hnae3_ae_dev *ae_dev,
27941db58f86SHuazhong Tan 					    struct hnae3_client *client)
27951db58f86SHuazhong Tan {
27961db58f86SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
27974cd5beaaSGuangbin Huang 	int rst_cnt = hdev->rst_stats.rst_cnt;
27981db58f86SHuazhong Tan 	int ret;
27991db58f86SHuazhong Tan 
28001db58f86SHuazhong Tan 	ret = client->ops->init_instance(&hdev->nic);
28011db58f86SHuazhong Tan 	if (ret)
28021db58f86SHuazhong Tan 		return ret;
28031db58f86SHuazhong Tan 
28041db58f86SHuazhong Tan 	set_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
28054cd5beaaSGuangbin Huang 	if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
28064cd5beaaSGuangbin Huang 	    rst_cnt != hdev->rst_stats.rst_cnt) {
28074cd5beaaSGuangbin Huang 		clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
28084cd5beaaSGuangbin Huang 
28094cd5beaaSGuangbin Huang 		client->ops->uninit_instance(&hdev->nic, 0);
28104cd5beaaSGuangbin Huang 		return -EBUSY;
28114cd5beaaSGuangbin Huang 	}
28124cd5beaaSGuangbin Huang 
28131db58f86SHuazhong Tan 	hnae3_set_client_init_flag(client, ae_dev, 1);
28141db58f86SHuazhong Tan 
28151db58f86SHuazhong Tan 	if (netif_msg_drv(&hdev->nic))
28161db58f86SHuazhong Tan 		hclgevf_info_show(hdev);
28171db58f86SHuazhong Tan 
28181db58f86SHuazhong Tan 	return 0;
28191db58f86SHuazhong Tan }
28201db58f86SHuazhong Tan 
28211db58f86SHuazhong Tan static int hclgevf_init_roce_client_instance(struct hnae3_ae_dev *ae_dev,
28221db58f86SHuazhong Tan 					     struct hnae3_client *client)
28231db58f86SHuazhong Tan {
28241db58f86SHuazhong Tan 	struct hclgevf_dev *hdev = ae_dev->priv;
28251db58f86SHuazhong Tan 	int ret;
28261db58f86SHuazhong Tan 
28271db58f86SHuazhong Tan 	if (!hnae3_dev_roce_supported(hdev) || !hdev->roce_client ||
28281db58f86SHuazhong Tan 	    !hdev->nic_client)
28291db58f86SHuazhong Tan 		return 0;
28301db58f86SHuazhong Tan 
28311db58f86SHuazhong Tan 	ret = hclgevf_init_roce_base_info(hdev);
28321db58f86SHuazhong Tan 	if (ret)
28331db58f86SHuazhong Tan 		return ret;
28341db58f86SHuazhong Tan 
28351db58f86SHuazhong Tan 	ret = client->ops->init_instance(&hdev->roce);
28361db58f86SHuazhong Tan 	if (ret)
28371db58f86SHuazhong Tan 		return ret;
28381db58f86SHuazhong Tan 
2839fe735c84SHuazhong Tan 	set_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state);
28401db58f86SHuazhong Tan 	hnae3_set_client_init_flag(client, ae_dev, 1);
28411db58f86SHuazhong Tan 
28421db58f86SHuazhong Tan 	return 0;
28431db58f86SHuazhong Tan }
28441db58f86SHuazhong Tan 
2845e718a93fSPeng Li static int hclgevf_init_client_instance(struct hnae3_client *client,
2846e718a93fSPeng Li 					struct hnae3_ae_dev *ae_dev)
2847e2cb1decSSalil Mehta {
2848e718a93fSPeng Li 	struct hclgevf_dev *hdev = ae_dev->priv;
2849e2cb1decSSalil Mehta 	int ret;
2850e2cb1decSSalil Mehta 
2851e2cb1decSSalil Mehta 	switch (client->type) {
2852e2cb1decSSalil Mehta 	case HNAE3_CLIENT_KNIC:
2853e2cb1decSSalil Mehta 		hdev->nic_client = client;
2854e2cb1decSSalil Mehta 		hdev->nic.client = client;
2855e2cb1decSSalil Mehta 
28561db58f86SHuazhong Tan 		ret = hclgevf_init_nic_client_instance(ae_dev, client);
2857e2cb1decSSalil Mehta 		if (ret)
285849dd8054SJian Shen 			goto clear_nic;
2859e2cb1decSSalil Mehta 
28601db58f86SHuazhong Tan 		ret = hclgevf_init_roce_client_instance(ae_dev,
28611db58f86SHuazhong Tan 							hdev->roce_client);
2862e2cb1decSSalil Mehta 		if (ret)
286349dd8054SJian Shen 			goto clear_roce;
2864d9f28fc2SJian Shen 
2865e2cb1decSSalil Mehta 		break;
2866e2cb1decSSalil Mehta 	case HNAE3_CLIENT_ROCE:
2867544a7bcdSLijun Ou 		if (hnae3_dev_roce_supported(hdev)) {
2868e2cb1decSSalil Mehta 			hdev->roce_client = client;
2869e2cb1decSSalil Mehta 			hdev->roce.client = client;
2870544a7bcdSLijun Ou 		}
2871e2cb1decSSalil Mehta 
28721db58f86SHuazhong Tan 		ret = hclgevf_init_roce_client_instance(ae_dev, client);
2873e2cb1decSSalil Mehta 		if (ret)
287449dd8054SJian Shen 			goto clear_roce;
2875e2cb1decSSalil Mehta 
2876fa7a4bd5SJian Shen 		break;
2877fa7a4bd5SJian Shen 	default:
2878fa7a4bd5SJian Shen 		return -EINVAL;
2879e2cb1decSSalil Mehta 	}
2880e2cb1decSSalil Mehta 
2881e2cb1decSSalil Mehta 	return 0;
288249dd8054SJian Shen 
288349dd8054SJian Shen clear_nic:
288449dd8054SJian Shen 	hdev->nic_client = NULL;
288549dd8054SJian Shen 	hdev->nic.client = NULL;
288649dd8054SJian Shen 	return ret;
288749dd8054SJian Shen clear_roce:
288849dd8054SJian Shen 	hdev->roce_client = NULL;
288949dd8054SJian Shen 	hdev->roce.client = NULL;
289049dd8054SJian Shen 	return ret;
2891e2cb1decSSalil Mehta }
2892e2cb1decSSalil Mehta 
2893e718a93fSPeng Li static void hclgevf_uninit_client_instance(struct hnae3_client *client,
2894e718a93fSPeng Li 					   struct hnae3_ae_dev *ae_dev)
2895e2cb1decSSalil Mehta {
2896e718a93fSPeng Li 	struct hclgevf_dev *hdev = ae_dev->priv;
2897e718a93fSPeng Li 
2898e2cb1decSSalil Mehta 	/* un-init roce, if it exists */
289949dd8054SJian Shen 	if (hdev->roce_client) {
2900fe735c84SHuazhong Tan 		clear_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state);
2901e2cb1decSSalil Mehta 		hdev->roce_client->ops->uninit_instance(&hdev->roce, 0);
290249dd8054SJian Shen 		hdev->roce_client = NULL;
290349dd8054SJian Shen 		hdev->roce.client = NULL;
290449dd8054SJian Shen 	}
2905e2cb1decSSalil Mehta 
2906e2cb1decSSalil Mehta 	/* un-init nic/unic, if this was not called by roce client */
290749dd8054SJian Shen 	if (client->ops->uninit_instance && hdev->nic_client &&
290849dd8054SJian Shen 	    client->type != HNAE3_CLIENT_ROCE) {
290925d1817cSHuazhong Tan 		clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
291025d1817cSHuazhong Tan 
2911e2cb1decSSalil Mehta 		client->ops->uninit_instance(&hdev->nic, 0);
291249dd8054SJian Shen 		hdev->nic_client = NULL;
291349dd8054SJian Shen 		hdev->nic.client = NULL;
291449dd8054SJian Shen 	}
2915e2cb1decSSalil Mehta }
2916e2cb1decSSalil Mehta 
291730ae7f8aSHuazhong Tan static int hclgevf_dev_mem_map(struct hclgevf_dev *hdev)
291830ae7f8aSHuazhong Tan {
291930ae7f8aSHuazhong Tan #define HCLGEVF_MEM_BAR		4
292030ae7f8aSHuazhong Tan 
292130ae7f8aSHuazhong Tan 	struct pci_dev *pdev = hdev->pdev;
292230ae7f8aSHuazhong Tan 	struct hclgevf_hw *hw = &hdev->hw;
292330ae7f8aSHuazhong Tan 
292430ae7f8aSHuazhong Tan 	/* for device does not have device memory, return directly */
292530ae7f8aSHuazhong Tan 	if (!(pci_select_bars(pdev, IORESOURCE_MEM) & BIT(HCLGEVF_MEM_BAR)))
292630ae7f8aSHuazhong Tan 		return 0;
292730ae7f8aSHuazhong Tan 
292830ae7f8aSHuazhong Tan 	hw->mem_base = devm_ioremap_wc(&pdev->dev,
292930ae7f8aSHuazhong Tan 				       pci_resource_start(pdev,
293030ae7f8aSHuazhong Tan 							  HCLGEVF_MEM_BAR),
293130ae7f8aSHuazhong Tan 				       pci_resource_len(pdev, HCLGEVF_MEM_BAR));
293230ae7f8aSHuazhong Tan 	if (!hw->mem_base) {
2933be419fcaSColin Ian King 		dev_err(&pdev->dev, "failed to map device memory\n");
293430ae7f8aSHuazhong Tan 		return -EFAULT;
293530ae7f8aSHuazhong Tan 	}
293630ae7f8aSHuazhong Tan 
293730ae7f8aSHuazhong Tan 	return 0;
293830ae7f8aSHuazhong Tan }
293930ae7f8aSHuazhong Tan 
2940e2cb1decSSalil Mehta static int hclgevf_pci_init(struct hclgevf_dev *hdev)
2941e2cb1decSSalil Mehta {
2942e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
2943e2cb1decSSalil Mehta 	struct hclgevf_hw *hw;
2944e2cb1decSSalil Mehta 	int ret;
2945e2cb1decSSalil Mehta 
2946e2cb1decSSalil Mehta 	ret = pci_enable_device(pdev);
2947e2cb1decSSalil Mehta 	if (ret) {
2948e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "failed to enable PCI device\n");
29493e249d3bSFuyun Liang 		return ret;
2950e2cb1decSSalil Mehta 	}
2951e2cb1decSSalil Mehta 
2952e2cb1decSSalil Mehta 	ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
2953e2cb1decSSalil Mehta 	if (ret) {
2954e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "can't set consistent PCI DMA, exiting");
2955e2cb1decSSalil Mehta 		goto err_disable_device;
2956e2cb1decSSalil Mehta 	}
2957e2cb1decSSalil Mehta 
2958e2cb1decSSalil Mehta 	ret = pci_request_regions(pdev, HCLGEVF_DRIVER_NAME);
2959e2cb1decSSalil Mehta 	if (ret) {
2960e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "PCI request regions failed %d\n", ret);
2961e2cb1decSSalil Mehta 		goto err_disable_device;
2962e2cb1decSSalil Mehta 	}
2963e2cb1decSSalil Mehta 
2964e2cb1decSSalil Mehta 	pci_set_master(pdev);
2965e2cb1decSSalil Mehta 	hw = &hdev->hw;
2966e2cb1decSSalil Mehta 	hw->hdev = hdev;
29672e1ea493SPeng Li 	hw->io_base = pci_iomap(pdev, 2, 0);
2968e2cb1decSSalil Mehta 	if (!hw->io_base) {
2969e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "can't map configuration register space\n");
2970e2cb1decSSalil Mehta 		ret = -ENOMEM;
2971e2cb1decSSalil Mehta 		goto err_clr_master;
2972e2cb1decSSalil Mehta 	}
2973e2cb1decSSalil Mehta 
297430ae7f8aSHuazhong Tan 	ret = hclgevf_dev_mem_map(hdev);
297530ae7f8aSHuazhong Tan 	if (ret)
297630ae7f8aSHuazhong Tan 		goto err_unmap_io_base;
297730ae7f8aSHuazhong Tan 
2978e2cb1decSSalil Mehta 	return 0;
2979e2cb1decSSalil Mehta 
298030ae7f8aSHuazhong Tan err_unmap_io_base:
298130ae7f8aSHuazhong Tan 	pci_iounmap(pdev, hdev->hw.io_base);
2982e2cb1decSSalil Mehta err_clr_master:
2983e2cb1decSSalil Mehta 	pci_clear_master(pdev);
2984e2cb1decSSalil Mehta 	pci_release_regions(pdev);
2985e2cb1decSSalil Mehta err_disable_device:
2986e2cb1decSSalil Mehta 	pci_disable_device(pdev);
29873e249d3bSFuyun Liang 
2988e2cb1decSSalil Mehta 	return ret;
2989e2cb1decSSalil Mehta }
2990e2cb1decSSalil Mehta 
2991e2cb1decSSalil Mehta static void hclgevf_pci_uninit(struct hclgevf_dev *hdev)
2992e2cb1decSSalil Mehta {
2993e2cb1decSSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
2994e2cb1decSSalil Mehta 
299530ae7f8aSHuazhong Tan 	if (hdev->hw.mem_base)
299630ae7f8aSHuazhong Tan 		devm_iounmap(&pdev->dev, hdev->hw.mem_base);
299730ae7f8aSHuazhong Tan 
2998e2cb1decSSalil Mehta 	pci_iounmap(pdev, hdev->hw.io_base);
2999e2cb1decSSalil Mehta 	pci_clear_master(pdev);
3000e2cb1decSSalil Mehta 	pci_release_regions(pdev);
3001e2cb1decSSalil Mehta 	pci_disable_device(pdev);
3002e2cb1decSSalil Mehta }
3003e2cb1decSSalil Mehta 
300407acf909SJian Shen static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev)
300507acf909SJian Shen {
300607acf909SJian Shen 	struct hclgevf_query_res_cmd *req;
300707acf909SJian Shen 	struct hclgevf_desc desc;
300807acf909SJian Shen 	int ret;
300907acf909SJian Shen 
301007acf909SJian Shen 	hclgevf_cmd_setup_basic_desc(&desc, HCLGEVF_OPC_QUERY_VF_RSRC, true);
301107acf909SJian Shen 	ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
301207acf909SJian Shen 	if (ret) {
301307acf909SJian Shen 		dev_err(&hdev->pdev->dev,
301407acf909SJian Shen 			"query vf resource failed, ret = %d.\n", ret);
301507acf909SJian Shen 		return ret;
301607acf909SJian Shen 	}
301707acf909SJian Shen 
301807acf909SJian Shen 	req = (struct hclgevf_query_res_cmd *)desc.data;
301907acf909SJian Shen 
3020580a05f9SYonglong Liu 	if (hnae3_dev_roce_supported(hdev)) {
302107acf909SJian Shen 		hdev->roce_base_msix_offset =
302260df7e91SHuazhong Tan 		hnae3_get_field(le16_to_cpu(req->msixcap_localid_ba_rocee),
302307acf909SJian Shen 				HCLGEVF_MSIX_OFT_ROCEE_M,
302407acf909SJian Shen 				HCLGEVF_MSIX_OFT_ROCEE_S);
302507acf909SJian Shen 		hdev->num_roce_msix =
302660df7e91SHuazhong Tan 		hnae3_get_field(le16_to_cpu(req->vf_intr_vector_number),
302707acf909SJian Shen 				HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
302807acf909SJian Shen 
3029580a05f9SYonglong Liu 		/* nic's msix numbers is always equals to the roce's. */
3030580a05f9SYonglong Liu 		hdev->num_nic_msix = hdev->num_roce_msix;
3031580a05f9SYonglong Liu 
303207acf909SJian Shen 		/* VF should have NIC vectors and Roce vectors, NIC vectors
303307acf909SJian Shen 		 * are queued before Roce vectors. The offset is fixed to 64.
303407acf909SJian Shen 		 */
303507acf909SJian Shen 		hdev->num_msi = hdev->num_roce_msix +
303607acf909SJian Shen 				hdev->roce_base_msix_offset;
303707acf909SJian Shen 	} else {
303807acf909SJian Shen 		hdev->num_msi =
303960df7e91SHuazhong Tan 		hnae3_get_field(le16_to_cpu(req->vf_intr_vector_number),
304007acf909SJian Shen 				HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
3041580a05f9SYonglong Liu 
3042580a05f9SYonglong Liu 		hdev->num_nic_msix = hdev->num_msi;
3043580a05f9SYonglong Liu 	}
3044580a05f9SYonglong Liu 
3045580a05f9SYonglong Liu 	if (hdev->num_nic_msix < HNAE3_MIN_VECTOR_NUM) {
3046580a05f9SYonglong Liu 		dev_err(&hdev->pdev->dev,
3047580a05f9SYonglong Liu 			"Just %u msi resources, not enough for vf(min:2).\n",
3048580a05f9SYonglong Liu 			hdev->num_nic_msix);
3049580a05f9SYonglong Liu 		return -EINVAL;
305007acf909SJian Shen 	}
305107acf909SJian Shen 
305207acf909SJian Shen 	return 0;
305307acf909SJian Shen }
305407acf909SJian Shen 
3055af2aedc5SGuangbin Huang static void hclgevf_set_default_dev_specs(struct hclgevf_dev *hdev)
3056af2aedc5SGuangbin Huang {
3057af2aedc5SGuangbin Huang #define HCLGEVF_MAX_NON_TSO_BD_NUM			8U
3058af2aedc5SGuangbin Huang 
3059af2aedc5SGuangbin Huang 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
3060af2aedc5SGuangbin Huang 
3061af2aedc5SGuangbin Huang 	ae_dev->dev_specs.max_non_tso_bd_num =
3062af2aedc5SGuangbin Huang 					HCLGEVF_MAX_NON_TSO_BD_NUM;
3063af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_ind_tbl_size = HCLGEVF_RSS_IND_TBL_SIZE;
3064af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_key_size = HCLGEVF_RSS_KEY_SIZE;
3065ab16b49cSHuazhong Tan 	ae_dev->dev_specs.max_int_gl = HCLGEVF_DEF_MAX_INT_GL;
3066e070c8b9SYufeng Mo 	ae_dev->dev_specs.max_frm_size = HCLGEVF_MAC_MAX_FRAME;
3067af2aedc5SGuangbin Huang }
3068af2aedc5SGuangbin Huang 
3069af2aedc5SGuangbin Huang static void hclgevf_parse_dev_specs(struct hclgevf_dev *hdev,
3070af2aedc5SGuangbin Huang 				    struct hclgevf_desc *desc)
3071af2aedc5SGuangbin Huang {
3072af2aedc5SGuangbin Huang 	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
3073af2aedc5SGuangbin Huang 	struct hclgevf_dev_specs_0_cmd *req0;
3074ab16b49cSHuazhong Tan 	struct hclgevf_dev_specs_1_cmd *req1;
3075af2aedc5SGuangbin Huang 
3076af2aedc5SGuangbin Huang 	req0 = (struct hclgevf_dev_specs_0_cmd *)desc[0].data;
3077ab16b49cSHuazhong Tan 	req1 = (struct hclgevf_dev_specs_1_cmd *)desc[1].data;
3078af2aedc5SGuangbin Huang 
3079af2aedc5SGuangbin Huang 	ae_dev->dev_specs.max_non_tso_bd_num = req0->max_non_tso_bd_num;
3080af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_ind_tbl_size =
3081af2aedc5SGuangbin Huang 					le16_to_cpu(req0->rss_ind_tbl_size);
308291bfae25SHuazhong Tan 	ae_dev->dev_specs.int_ql_max = le16_to_cpu(req0->int_ql_max);
3083af2aedc5SGuangbin Huang 	ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size);
3084ab16b49cSHuazhong Tan 	ae_dev->dev_specs.max_int_gl = le16_to_cpu(req1->max_int_gl);
3085e070c8b9SYufeng Mo 	ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size);
3086af2aedc5SGuangbin Huang }
3087af2aedc5SGuangbin Huang 
308813297028SGuangbin Huang static void hclgevf_check_dev_specs(struct hclgevf_dev *hdev)
308913297028SGuangbin Huang {
309013297028SGuangbin Huang 	struct hnae3_dev_specs *dev_specs = &hdev->ae_dev->dev_specs;
309113297028SGuangbin Huang 
309213297028SGuangbin Huang 	if (!dev_specs->max_non_tso_bd_num)
309313297028SGuangbin Huang 		dev_specs->max_non_tso_bd_num = HCLGEVF_MAX_NON_TSO_BD_NUM;
309413297028SGuangbin Huang 	if (!dev_specs->rss_ind_tbl_size)
309513297028SGuangbin Huang 		dev_specs->rss_ind_tbl_size = HCLGEVF_RSS_IND_TBL_SIZE;
309613297028SGuangbin Huang 	if (!dev_specs->rss_key_size)
309713297028SGuangbin Huang 		dev_specs->rss_key_size = HCLGEVF_RSS_KEY_SIZE;
3098ab16b49cSHuazhong Tan 	if (!dev_specs->max_int_gl)
3099ab16b49cSHuazhong Tan 		dev_specs->max_int_gl = HCLGEVF_DEF_MAX_INT_GL;
3100e070c8b9SYufeng Mo 	if (!dev_specs->max_frm_size)
3101e070c8b9SYufeng Mo 		dev_specs->max_frm_size = HCLGEVF_MAC_MAX_FRAME;
310213297028SGuangbin Huang }
310313297028SGuangbin Huang 
3104af2aedc5SGuangbin Huang static int hclgevf_query_dev_specs(struct hclgevf_dev *hdev)
3105af2aedc5SGuangbin Huang {
3106af2aedc5SGuangbin Huang 	struct hclgevf_desc desc[HCLGEVF_QUERY_DEV_SPECS_BD_NUM];
3107af2aedc5SGuangbin Huang 	int ret;
3108af2aedc5SGuangbin Huang 	int i;
3109af2aedc5SGuangbin Huang 
3110af2aedc5SGuangbin Huang 	/* set default specifications as devices lower than version V3 do not
3111af2aedc5SGuangbin Huang 	 * support querying specifications from firmware.
3112af2aedc5SGuangbin Huang 	 */
3113af2aedc5SGuangbin Huang 	if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) {
3114af2aedc5SGuangbin Huang 		hclgevf_set_default_dev_specs(hdev);
3115af2aedc5SGuangbin Huang 		return 0;
3116af2aedc5SGuangbin Huang 	}
3117af2aedc5SGuangbin Huang 
3118af2aedc5SGuangbin Huang 	for (i = 0; i < HCLGEVF_QUERY_DEV_SPECS_BD_NUM - 1; i++) {
3119af2aedc5SGuangbin Huang 		hclgevf_cmd_setup_basic_desc(&desc[i],
3120af2aedc5SGuangbin Huang 					     HCLGEVF_OPC_QUERY_DEV_SPECS, true);
3121af2aedc5SGuangbin Huang 		desc[i].flag |= cpu_to_le16(HCLGEVF_CMD_FLAG_NEXT);
3122af2aedc5SGuangbin Huang 	}
3123af2aedc5SGuangbin Huang 	hclgevf_cmd_setup_basic_desc(&desc[i], HCLGEVF_OPC_QUERY_DEV_SPECS,
3124af2aedc5SGuangbin Huang 				     true);
3125af2aedc5SGuangbin Huang 
3126af2aedc5SGuangbin Huang 	ret = hclgevf_cmd_send(&hdev->hw, desc, HCLGEVF_QUERY_DEV_SPECS_BD_NUM);
3127af2aedc5SGuangbin Huang 	if (ret)
3128af2aedc5SGuangbin Huang 		return ret;
3129af2aedc5SGuangbin Huang 
3130af2aedc5SGuangbin Huang 	hclgevf_parse_dev_specs(hdev, desc);
313113297028SGuangbin Huang 	hclgevf_check_dev_specs(hdev);
3132af2aedc5SGuangbin Huang 
3133af2aedc5SGuangbin Huang 	return 0;
3134af2aedc5SGuangbin Huang }
3135af2aedc5SGuangbin Huang 
3136862d969aSHuazhong Tan static int hclgevf_pci_reset(struct hclgevf_dev *hdev)
3137862d969aSHuazhong Tan {
3138862d969aSHuazhong Tan 	struct pci_dev *pdev = hdev->pdev;
3139862d969aSHuazhong Tan 	int ret = 0;
3140862d969aSHuazhong Tan 
3141862d969aSHuazhong Tan 	if (hdev->reset_type == HNAE3_VF_FULL_RESET &&
3142862d969aSHuazhong Tan 	    test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
3143862d969aSHuazhong Tan 		hclgevf_misc_irq_uninit(hdev);
3144862d969aSHuazhong Tan 		hclgevf_uninit_msi(hdev);
3145862d969aSHuazhong Tan 		clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3146862d969aSHuazhong Tan 	}
3147862d969aSHuazhong Tan 
3148862d969aSHuazhong Tan 	if (!test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
3149862d969aSHuazhong Tan 		pci_set_master(pdev);
3150862d969aSHuazhong Tan 		ret = hclgevf_init_msi(hdev);
3151862d969aSHuazhong Tan 		if (ret) {
3152862d969aSHuazhong Tan 			dev_err(&pdev->dev,
3153862d969aSHuazhong Tan 				"failed(%d) to init MSI/MSI-X\n", ret);
3154862d969aSHuazhong Tan 			return ret;
3155862d969aSHuazhong Tan 		}
3156862d969aSHuazhong Tan 
3157862d969aSHuazhong Tan 		ret = hclgevf_misc_irq_init(hdev);
3158862d969aSHuazhong Tan 		if (ret) {
3159862d969aSHuazhong Tan 			hclgevf_uninit_msi(hdev);
3160862d969aSHuazhong Tan 			dev_err(&pdev->dev, "failed(%d) to init Misc IRQ(vector0)\n",
3161862d969aSHuazhong Tan 				ret);
3162862d969aSHuazhong Tan 			return ret;
3163862d969aSHuazhong Tan 		}
3164862d969aSHuazhong Tan 
3165862d969aSHuazhong Tan 		set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3166862d969aSHuazhong Tan 	}
3167862d969aSHuazhong Tan 
3168862d969aSHuazhong Tan 	return ret;
3169862d969aSHuazhong Tan }
3170862d969aSHuazhong Tan 
3171039ba863SJian Shen static int hclgevf_clear_vport_list(struct hclgevf_dev *hdev)
3172039ba863SJian Shen {
3173039ba863SJian Shen 	struct hclge_vf_to_pf_msg send_msg;
3174039ba863SJian Shen 
3175039ba863SJian Shen 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_HANDLE_VF_TBL,
3176039ba863SJian Shen 			       HCLGE_MBX_VPORT_LIST_CLEAR);
3177039ba863SJian Shen 	return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
3178039ba863SJian Shen }
3179039ba863SJian Shen 
31809c6f7085SHuazhong Tan static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
3181e2cb1decSSalil Mehta {
31827a01c897SSalil Mehta 	struct pci_dev *pdev = hdev->pdev;
3183e2cb1decSSalil Mehta 	int ret;
3184e2cb1decSSalil Mehta 
3185862d969aSHuazhong Tan 	ret = hclgevf_pci_reset(hdev);
3186862d969aSHuazhong Tan 	if (ret) {
3187862d969aSHuazhong Tan 		dev_err(&pdev->dev, "pci reset failed %d\n", ret);
3188862d969aSHuazhong Tan 		return ret;
3189862d969aSHuazhong Tan 	}
3190862d969aSHuazhong Tan 
31919c6f7085SHuazhong Tan 	ret = hclgevf_cmd_init(hdev);
31929c6f7085SHuazhong Tan 	if (ret) {
31939c6f7085SHuazhong Tan 		dev_err(&pdev->dev, "cmd failed %d\n", ret);
31949c6f7085SHuazhong Tan 		return ret;
31957a01c897SSalil Mehta 	}
3196e2cb1decSSalil Mehta 
31979c6f7085SHuazhong Tan 	ret = hclgevf_rss_init_hw(hdev);
31989c6f7085SHuazhong Tan 	if (ret) {
31999c6f7085SHuazhong Tan 		dev_err(&hdev->pdev->dev,
32009c6f7085SHuazhong Tan 			"failed(%d) to initialize RSS\n", ret);
32019c6f7085SHuazhong Tan 		return ret;
32029c6f7085SHuazhong Tan 	}
32039c6f7085SHuazhong Tan 
3204b26a6feaSPeng Li 	ret = hclgevf_config_gro(hdev, true);
3205b26a6feaSPeng Li 	if (ret)
3206b26a6feaSPeng Li 		return ret;
3207b26a6feaSPeng Li 
32089c6f7085SHuazhong Tan 	ret = hclgevf_init_vlan_config(hdev);
32099c6f7085SHuazhong Tan 	if (ret) {
32109c6f7085SHuazhong Tan 		dev_err(&hdev->pdev->dev,
32119c6f7085SHuazhong Tan 			"failed(%d) to initialize VLAN config\n", ret);
32129c6f7085SHuazhong Tan 		return ret;
32139c6f7085SHuazhong Tan 	}
32149c6f7085SHuazhong Tan 
3215c631c696SJian Shen 	set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
3216c631c696SJian Shen 
32179c6f7085SHuazhong Tan 	dev_info(&hdev->pdev->dev, "Reset done\n");
32189c6f7085SHuazhong Tan 
32199c6f7085SHuazhong Tan 	return 0;
32209c6f7085SHuazhong Tan }
32219c6f7085SHuazhong Tan 
32229c6f7085SHuazhong Tan static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
32239c6f7085SHuazhong Tan {
32249c6f7085SHuazhong Tan 	struct pci_dev *pdev = hdev->pdev;
32259c6f7085SHuazhong Tan 	int ret;
32269c6f7085SHuazhong Tan 
3227e2cb1decSSalil Mehta 	ret = hclgevf_pci_init(hdev);
322860df7e91SHuazhong Tan 	if (ret)
3229e2cb1decSSalil Mehta 		return ret;
3230e2cb1decSSalil Mehta 
32318b0195a3SHuazhong Tan 	ret = hclgevf_cmd_queue_init(hdev);
323260df7e91SHuazhong Tan 	if (ret)
32338b0195a3SHuazhong Tan 		goto err_cmd_queue_init;
32348b0195a3SHuazhong Tan 
3235eddf0462SYunsheng Lin 	ret = hclgevf_cmd_init(hdev);
3236eddf0462SYunsheng Lin 	if (ret)
3237eddf0462SYunsheng Lin 		goto err_cmd_init;
3238eddf0462SYunsheng Lin 
323907acf909SJian Shen 	/* Get vf resource */
324007acf909SJian Shen 	ret = hclgevf_query_vf_resource(hdev);
324160df7e91SHuazhong Tan 	if (ret)
32428b0195a3SHuazhong Tan 		goto err_cmd_init;
324307acf909SJian Shen 
3244af2aedc5SGuangbin Huang 	ret = hclgevf_query_dev_specs(hdev);
3245af2aedc5SGuangbin Huang 	if (ret) {
3246af2aedc5SGuangbin Huang 		dev_err(&pdev->dev,
3247af2aedc5SGuangbin Huang 			"failed to query dev specifications, ret = %d\n", ret);
3248af2aedc5SGuangbin Huang 		goto err_cmd_init;
3249af2aedc5SGuangbin Huang 	}
3250af2aedc5SGuangbin Huang 
325107acf909SJian Shen 	ret = hclgevf_init_msi(hdev);
325207acf909SJian Shen 	if (ret) {
325307acf909SJian Shen 		dev_err(&pdev->dev, "failed(%d) to init MSI/MSI-X\n", ret);
32548b0195a3SHuazhong Tan 		goto err_cmd_init;
325507acf909SJian Shen 	}
325607acf909SJian Shen 
325707acf909SJian Shen 	hclgevf_state_init(hdev);
3258dea846e8SHuazhong Tan 	hdev->reset_level = HNAE3_VF_FUNC_RESET;
3259afb6afdbSHuazhong Tan 	hdev->reset_type = HNAE3_NONE_RESET;
326007acf909SJian Shen 
3261e2cb1decSSalil Mehta 	ret = hclgevf_misc_irq_init(hdev);
326260df7e91SHuazhong Tan 	if (ret)
3263e2cb1decSSalil Mehta 		goto err_misc_irq_init;
3264e2cb1decSSalil Mehta 
3265862d969aSHuazhong Tan 	set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3266862d969aSHuazhong Tan 
3267e2cb1decSSalil Mehta 	ret = hclgevf_configure(hdev);
3268e2cb1decSSalil Mehta 	if (ret) {
3269e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "failed(%d) to fetch configuration\n", ret);
3270e2cb1decSSalil Mehta 		goto err_config;
3271e2cb1decSSalil Mehta 	}
3272e2cb1decSSalil Mehta 
3273e2cb1decSSalil Mehta 	ret = hclgevf_alloc_tqps(hdev);
3274e2cb1decSSalil Mehta 	if (ret) {
3275e2cb1decSSalil Mehta 		dev_err(&pdev->dev, "failed(%d) to allocate TQPs\n", ret);
3276e2cb1decSSalil Mehta 		goto err_config;
3277e2cb1decSSalil Mehta 	}
3278e2cb1decSSalil Mehta 
3279e2cb1decSSalil Mehta 	ret = hclgevf_set_handle_info(hdev);
328060df7e91SHuazhong Tan 	if (ret)
3281e2cb1decSSalil Mehta 		goto err_config;
3282e2cb1decSSalil Mehta 
3283b26a6feaSPeng Li 	ret = hclgevf_config_gro(hdev, true);
3284b26a6feaSPeng Li 	if (ret)
3285b26a6feaSPeng Li 		goto err_config;
3286b26a6feaSPeng Li 
3287e2cb1decSSalil Mehta 	/* Initialize RSS for this VF */
328887ce161eSGuangbin Huang 	ret = hclgevf_rss_init_cfg(hdev);
328987ce161eSGuangbin Huang 	if (ret) {
329087ce161eSGuangbin Huang 		dev_err(&pdev->dev, "failed to init rss cfg, ret = %d\n", ret);
329187ce161eSGuangbin Huang 		goto err_config;
329287ce161eSGuangbin Huang 	}
329387ce161eSGuangbin Huang 
3294e2cb1decSSalil Mehta 	ret = hclgevf_rss_init_hw(hdev);
3295e2cb1decSSalil Mehta 	if (ret) {
3296e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
3297e2cb1decSSalil Mehta 			"failed(%d) to initialize RSS\n", ret);
3298e2cb1decSSalil Mehta 		goto err_config;
3299e2cb1decSSalil Mehta 	}
3300e2cb1decSSalil Mehta 
3301039ba863SJian Shen 	/* ensure vf tbl list as empty before init*/
3302039ba863SJian Shen 	ret = hclgevf_clear_vport_list(hdev);
3303039ba863SJian Shen 	if (ret) {
3304039ba863SJian Shen 		dev_err(&pdev->dev,
3305039ba863SJian Shen 			"failed to clear tbl list configuration, ret = %d.\n",
3306039ba863SJian Shen 			ret);
3307039ba863SJian Shen 		goto err_config;
3308039ba863SJian Shen 	}
3309039ba863SJian Shen 
3310e2cb1decSSalil Mehta 	ret = hclgevf_init_vlan_config(hdev);
3311e2cb1decSSalil Mehta 	if (ret) {
3312e2cb1decSSalil Mehta 		dev_err(&hdev->pdev->dev,
3313e2cb1decSSalil Mehta 			"failed(%d) to initialize VLAN config\n", ret);
3314e2cb1decSSalil Mehta 		goto err_config;
3315e2cb1decSSalil Mehta 	}
3316e2cb1decSSalil Mehta 
33170742ed7cSHuazhong Tan 	hdev->last_reset_time = jiffies;
331808d80a4cSHuazhong Tan 	dev_info(&hdev->pdev->dev, "finished initializing %s driver\n",
331908d80a4cSHuazhong Tan 		 HCLGEVF_DRIVER_NAME);
3320e2cb1decSSalil Mehta 
3321ff200099SYunsheng Lin 	hclgevf_task_schedule(hdev, round_jiffies_relative(HZ));
3322ff200099SYunsheng Lin 
3323e2cb1decSSalil Mehta 	return 0;
3324e2cb1decSSalil Mehta 
3325e2cb1decSSalil Mehta err_config:
3326e2cb1decSSalil Mehta 	hclgevf_misc_irq_uninit(hdev);
3327e2cb1decSSalil Mehta err_misc_irq_init:
3328e2cb1decSSalil Mehta 	hclgevf_state_uninit(hdev);
3329e2cb1decSSalil Mehta 	hclgevf_uninit_msi(hdev);
333007acf909SJian Shen err_cmd_init:
33318b0195a3SHuazhong Tan 	hclgevf_cmd_uninit(hdev);
33328b0195a3SHuazhong Tan err_cmd_queue_init:
3333e2cb1decSSalil Mehta 	hclgevf_pci_uninit(hdev);
3334862d969aSHuazhong Tan 	clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3335e2cb1decSSalil Mehta 	return ret;
3336e2cb1decSSalil Mehta }
3337e2cb1decSSalil Mehta 
33387a01c897SSalil Mehta static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
3339e2cb1decSSalil Mehta {
3340d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
3341d3410018SYufeng Mo 
3342e2cb1decSSalil Mehta 	hclgevf_state_uninit(hdev);
3343862d969aSHuazhong Tan 
3344d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_VF_UNINIT, 0);
3345d3410018SYufeng Mo 	hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
334623b4201dSJian Shen 
3347862d969aSHuazhong Tan 	if (test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
3348eddf0462SYunsheng Lin 		hclgevf_misc_irq_uninit(hdev);
3349e2cb1decSSalil Mehta 		hclgevf_uninit_msi(hdev);
33507a01c897SSalil Mehta 	}
33517a01c897SSalil Mehta 
3352862d969aSHuazhong Tan 	hclgevf_cmd_uninit(hdev);
3353e3364c5fSZenghui Yu 	hclgevf_pci_uninit(hdev);
3354ee4bcd3bSJian Shen 	hclgevf_uninit_mac_list(hdev);
3355862d969aSHuazhong Tan }
3356862d969aSHuazhong Tan 
33577a01c897SSalil Mehta static int hclgevf_init_ae_dev(struct hnae3_ae_dev *ae_dev)
33587a01c897SSalil Mehta {
33597a01c897SSalil Mehta 	struct pci_dev *pdev = ae_dev->pdev;
33607a01c897SSalil Mehta 	int ret;
33617a01c897SSalil Mehta 
33627a01c897SSalil Mehta 	ret = hclgevf_alloc_hdev(ae_dev);
33637a01c897SSalil Mehta 	if (ret) {
33647a01c897SSalil Mehta 		dev_err(&pdev->dev, "hclge device allocation failed\n");
33657a01c897SSalil Mehta 		return ret;
33667a01c897SSalil Mehta 	}
33677a01c897SSalil Mehta 
33687a01c897SSalil Mehta 	ret = hclgevf_init_hdev(ae_dev->priv);
3369a6d818e3SYunsheng Lin 	if (ret) {
33707a01c897SSalil Mehta 		dev_err(&pdev->dev, "hclge device initialization failed\n");
33717a01c897SSalil Mehta 		return ret;
33727a01c897SSalil Mehta 	}
33737a01c897SSalil Mehta 
3374a6d818e3SYunsheng Lin 	return 0;
3375a6d818e3SYunsheng Lin }
3376a6d818e3SYunsheng Lin 
33777a01c897SSalil Mehta static void hclgevf_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
33787a01c897SSalil Mehta {
33797a01c897SSalil Mehta 	struct hclgevf_dev *hdev = ae_dev->priv;
33807a01c897SSalil Mehta 
33817a01c897SSalil Mehta 	hclgevf_uninit_hdev(hdev);
3382e2cb1decSSalil Mehta 	ae_dev->priv = NULL;
3383e2cb1decSSalil Mehta }
3384e2cb1decSSalil Mehta 
3385849e4607SPeng Li static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev)
3386849e4607SPeng Li {
3387849e4607SPeng Li 	struct hnae3_handle *nic = &hdev->nic;
3388849e4607SPeng Li 	struct hnae3_knic_private_info *kinfo = &nic->kinfo;
3389849e4607SPeng Li 
33908be73621SHuazhong Tan 	return min_t(u32, hdev->rss_size_max,
339135244430SJian Shen 		     hdev->num_tqps / kinfo->tc_info.num_tc);
3392849e4607SPeng Li }
3393849e4607SPeng Li 
3394849e4607SPeng Li /**
3395849e4607SPeng Li  * hclgevf_get_channels - Get the current channels enabled and max supported.
3396849e4607SPeng Li  * @handle: hardware information for network interface
3397849e4607SPeng Li  * @ch: ethtool channels structure
3398849e4607SPeng Li  *
3399849e4607SPeng Li  * We don't support separate tx and rx queues as channels. The other count
3400849e4607SPeng Li  * represents how many queues are being used for control. max_combined counts
3401849e4607SPeng Li  * how many queue pairs we can support. They may not be mapped 1 to 1 with
3402849e4607SPeng Li  * q_vectors since we support a lot more queue pairs than q_vectors.
3403849e4607SPeng Li  **/
3404849e4607SPeng Li static void hclgevf_get_channels(struct hnae3_handle *handle,
3405849e4607SPeng Li 				 struct ethtool_channels *ch)
3406849e4607SPeng Li {
3407849e4607SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3408849e4607SPeng Li 
3409849e4607SPeng Li 	ch->max_combined = hclgevf_get_max_channels(hdev);
3410849e4607SPeng Li 	ch->other_count = 0;
3411849e4607SPeng Li 	ch->max_other = 0;
34128be73621SHuazhong Tan 	ch->combined_count = handle->kinfo.rss_size;
3413849e4607SPeng Li }
3414849e4607SPeng Li 
3415cc719218SPeng Li static void hclgevf_get_tqps_and_rss_info(struct hnae3_handle *handle,
34160d43bf45SHuazhong Tan 					  u16 *alloc_tqps, u16 *max_rss_size)
3417cc719218SPeng Li {
3418cc719218SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3419cc719218SPeng Li 
34200d43bf45SHuazhong Tan 	*alloc_tqps = hdev->num_tqps;
3421cc719218SPeng Li 	*max_rss_size = hdev->rss_size_max;
3422cc719218SPeng Li }
3423cc719218SPeng Li 
34244093d1a2SGuangbin Huang static void hclgevf_update_rss_size(struct hnae3_handle *handle,
34254093d1a2SGuangbin Huang 				    u32 new_tqps_num)
34264093d1a2SGuangbin Huang {
34274093d1a2SGuangbin Huang 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
34284093d1a2SGuangbin Huang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
34294093d1a2SGuangbin Huang 	u16 max_rss_size;
34304093d1a2SGuangbin Huang 
34314093d1a2SGuangbin Huang 	kinfo->req_rss_size = new_tqps_num;
34324093d1a2SGuangbin Huang 
34334093d1a2SGuangbin Huang 	max_rss_size = min_t(u16, hdev->rss_size_max,
343435244430SJian Shen 			     hdev->num_tqps / kinfo->tc_info.num_tc);
34354093d1a2SGuangbin Huang 
34364093d1a2SGuangbin Huang 	/* Use the user's configuration when it is not larger than
34374093d1a2SGuangbin Huang 	 * max_rss_size, otherwise, use the maximum specification value.
34384093d1a2SGuangbin Huang 	 */
34394093d1a2SGuangbin Huang 	if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
34404093d1a2SGuangbin Huang 	    kinfo->req_rss_size <= max_rss_size)
34414093d1a2SGuangbin Huang 		kinfo->rss_size = kinfo->req_rss_size;
34424093d1a2SGuangbin Huang 	else if (kinfo->rss_size > max_rss_size ||
34434093d1a2SGuangbin Huang 		 (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size))
34444093d1a2SGuangbin Huang 		kinfo->rss_size = max_rss_size;
34454093d1a2SGuangbin Huang 
344635244430SJian Shen 	kinfo->num_tqps = kinfo->tc_info.num_tc * kinfo->rss_size;
34474093d1a2SGuangbin Huang }
34484093d1a2SGuangbin Huang 
34494093d1a2SGuangbin Huang static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
34504093d1a2SGuangbin Huang 				bool rxfh_configured)
34514093d1a2SGuangbin Huang {
34524093d1a2SGuangbin Huang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
34534093d1a2SGuangbin Huang 	struct hnae3_knic_private_info *kinfo = &handle->kinfo;
34544093d1a2SGuangbin Huang 	u16 cur_rss_size = kinfo->rss_size;
34554093d1a2SGuangbin Huang 	u16 cur_tqps = kinfo->num_tqps;
34564093d1a2SGuangbin Huang 	u32 *rss_indir;
34574093d1a2SGuangbin Huang 	unsigned int i;
34584093d1a2SGuangbin Huang 	int ret;
34594093d1a2SGuangbin Huang 
34604093d1a2SGuangbin Huang 	hclgevf_update_rss_size(handle, new_tqps_num);
34614093d1a2SGuangbin Huang 
34624093d1a2SGuangbin Huang 	ret = hclgevf_set_rss_tc_mode(hdev, kinfo->rss_size);
34634093d1a2SGuangbin Huang 	if (ret)
34644093d1a2SGuangbin Huang 		return ret;
34654093d1a2SGuangbin Huang 
34664093d1a2SGuangbin Huang 	/* RSS indirection table has been configuared by user */
34674093d1a2SGuangbin Huang 	if (rxfh_configured)
34684093d1a2SGuangbin Huang 		goto out;
34694093d1a2SGuangbin Huang 
34704093d1a2SGuangbin Huang 	/* Reinitializes the rss indirect table according to the new RSS size */
347187ce161eSGuangbin Huang 	rss_indir = kcalloc(hdev->ae_dev->dev_specs.rss_ind_tbl_size,
347287ce161eSGuangbin Huang 			    sizeof(u32), GFP_KERNEL);
34734093d1a2SGuangbin Huang 	if (!rss_indir)
34744093d1a2SGuangbin Huang 		return -ENOMEM;
34754093d1a2SGuangbin Huang 
347687ce161eSGuangbin Huang 	for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++)
34774093d1a2SGuangbin Huang 		rss_indir[i] = i % kinfo->rss_size;
34784093d1a2SGuangbin Huang 
3479944de484SGuojia Liao 	hdev->rss_cfg.rss_size = kinfo->rss_size;
3480944de484SGuojia Liao 
34814093d1a2SGuangbin Huang 	ret = hclgevf_set_rss(handle, rss_indir, NULL, 0);
34824093d1a2SGuangbin Huang 	if (ret)
34834093d1a2SGuangbin Huang 		dev_err(&hdev->pdev->dev, "set rss indir table fail, ret=%d\n",
34844093d1a2SGuangbin Huang 			ret);
34854093d1a2SGuangbin Huang 
34864093d1a2SGuangbin Huang 	kfree(rss_indir);
34874093d1a2SGuangbin Huang 
34884093d1a2SGuangbin Huang out:
34894093d1a2SGuangbin Huang 	if (!ret)
34904093d1a2SGuangbin Huang 		dev_info(&hdev->pdev->dev,
34914093d1a2SGuangbin Huang 			 "Channels changed, rss_size from %u to %u, tqps from %u to %u",
34924093d1a2SGuangbin Huang 			 cur_rss_size, kinfo->rss_size,
349335244430SJian Shen 			 cur_tqps, kinfo->rss_size * kinfo->tc_info.num_tc);
34944093d1a2SGuangbin Huang 
34954093d1a2SGuangbin Huang 	return ret;
34964093d1a2SGuangbin Huang }
34974093d1a2SGuangbin Huang 
3498175ec96bSFuyun Liang static int hclgevf_get_status(struct hnae3_handle *handle)
3499175ec96bSFuyun Liang {
3500175ec96bSFuyun Liang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3501175ec96bSFuyun Liang 
3502175ec96bSFuyun Liang 	return hdev->hw.mac.link;
3503175ec96bSFuyun Liang }
3504175ec96bSFuyun Liang 
35054a152de9SFuyun Liang static void hclgevf_get_ksettings_an_result(struct hnae3_handle *handle,
35064a152de9SFuyun Liang 					    u8 *auto_neg, u32 *speed,
35074a152de9SFuyun Liang 					    u8 *duplex)
35084a152de9SFuyun Liang {
35094a152de9SFuyun Liang 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35104a152de9SFuyun Liang 
35114a152de9SFuyun Liang 	if (speed)
35124a152de9SFuyun Liang 		*speed = hdev->hw.mac.speed;
35134a152de9SFuyun Liang 	if (duplex)
35144a152de9SFuyun Liang 		*duplex = hdev->hw.mac.duplex;
35154a152de9SFuyun Liang 	if (auto_neg)
35164a152de9SFuyun Liang 		*auto_neg = AUTONEG_DISABLE;
35174a152de9SFuyun Liang }
35184a152de9SFuyun Liang 
35194a152de9SFuyun Liang void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed,
35204a152de9SFuyun Liang 				 u8 duplex)
35214a152de9SFuyun Liang {
35224a152de9SFuyun Liang 	hdev->hw.mac.speed = speed;
35234a152de9SFuyun Liang 	hdev->hw.mac.duplex = duplex;
35244a152de9SFuyun Liang }
35254a152de9SFuyun Liang 
35261731be4cSYonglong Liu static int hclgevf_gro_en(struct hnae3_handle *handle, bool enable)
35275c9f6b39SPeng Li {
35285c9f6b39SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35295c9f6b39SPeng Li 
35305c9f6b39SPeng Li 	return hclgevf_config_gro(hdev, enable);
35315c9f6b39SPeng Li }
35325c9f6b39SPeng Li 
353388d10bd6SJian Shen static void hclgevf_get_media_type(struct hnae3_handle *handle, u8 *media_type,
353488d10bd6SJian Shen 				   u8 *module_type)
3535c136b884SPeng Li {
3536c136b884SPeng Li 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
353788d10bd6SJian Shen 
3538c136b884SPeng Li 	if (media_type)
3539c136b884SPeng Li 		*media_type = hdev->hw.mac.media_type;
354088d10bd6SJian Shen 
354188d10bd6SJian Shen 	if (module_type)
354288d10bd6SJian Shen 		*module_type = hdev->hw.mac.module_type;
3543c136b884SPeng Li }
3544c136b884SPeng Li 
35454d60291bSHuazhong Tan static bool hclgevf_get_hw_reset_stat(struct hnae3_handle *handle)
35464d60291bSHuazhong Tan {
35474d60291bSHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35484d60291bSHuazhong Tan 
3549aa5c4f17SHuazhong Tan 	return !!hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
35504d60291bSHuazhong Tan }
35514d60291bSHuazhong Tan 
3552fe735c84SHuazhong Tan static bool hclgevf_get_cmdq_stat(struct hnae3_handle *handle)
3553fe735c84SHuazhong Tan {
3554fe735c84SHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3555fe735c84SHuazhong Tan 
3556fe735c84SHuazhong Tan 	return test_bit(HCLGEVF_STATE_CMD_DISABLE, &hdev->state);
3557fe735c84SHuazhong Tan }
3558fe735c84SHuazhong Tan 
35594d60291bSHuazhong Tan static bool hclgevf_ae_dev_resetting(struct hnae3_handle *handle)
35604d60291bSHuazhong Tan {
35614d60291bSHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35624d60291bSHuazhong Tan 
35634d60291bSHuazhong Tan 	return test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
35644d60291bSHuazhong Tan }
35654d60291bSHuazhong Tan 
35664d60291bSHuazhong Tan static unsigned long hclgevf_ae_dev_reset_cnt(struct hnae3_handle *handle)
35674d60291bSHuazhong Tan {
35684d60291bSHuazhong Tan 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35694d60291bSHuazhong Tan 
3570c88a6e7dSHuazhong Tan 	return hdev->rst_stats.hw_rst_done_cnt;
35714d60291bSHuazhong Tan }
35724d60291bSHuazhong Tan 
35739194d18bSliuzhongzhu static void hclgevf_get_link_mode(struct hnae3_handle *handle,
35749194d18bSliuzhongzhu 				  unsigned long *supported,
35759194d18bSliuzhongzhu 				  unsigned long *advertising)
35769194d18bSliuzhongzhu {
35779194d18bSliuzhongzhu 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35789194d18bSliuzhongzhu 
35799194d18bSliuzhongzhu 	*supported = hdev->hw.mac.supported;
35809194d18bSliuzhongzhu 	*advertising = hdev->hw.mac.advertising;
35819194d18bSliuzhongzhu }
35829194d18bSliuzhongzhu 
35831600c3e5SJian Shen #define MAX_SEPARATE_NUM	4
35841600c3e5SJian Shen #define SEPARATOR_VALUE		0xFFFFFFFF
35851600c3e5SJian Shen #define REG_NUM_PER_LINE	4
35861600c3e5SJian Shen #define REG_LEN_PER_LINE	(REG_NUM_PER_LINE * sizeof(u32))
35871600c3e5SJian Shen 
35881600c3e5SJian Shen static int hclgevf_get_regs_len(struct hnae3_handle *handle)
35891600c3e5SJian Shen {
35901600c3e5SJian Shen 	int cmdq_lines, common_lines, ring_lines, tqp_intr_lines;
35911600c3e5SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
35921600c3e5SJian Shen 
35931600c3e5SJian Shen 	cmdq_lines = sizeof(cmdq_reg_addr_list) / REG_LEN_PER_LINE + 1;
35941600c3e5SJian Shen 	common_lines = sizeof(common_reg_addr_list) / REG_LEN_PER_LINE + 1;
35951600c3e5SJian Shen 	ring_lines = sizeof(ring_reg_addr_list) / REG_LEN_PER_LINE + 1;
35961600c3e5SJian Shen 	tqp_intr_lines = sizeof(tqp_intr_reg_addr_list) / REG_LEN_PER_LINE + 1;
35971600c3e5SJian Shen 
35981600c3e5SJian Shen 	return (cmdq_lines + common_lines + ring_lines * hdev->num_tqps +
35991600c3e5SJian Shen 		tqp_intr_lines * (hdev->num_msi_used - 1)) * REG_LEN_PER_LINE;
36001600c3e5SJian Shen }
36011600c3e5SJian Shen 
36021600c3e5SJian Shen static void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
36031600c3e5SJian Shen 			     void *data)
36041600c3e5SJian Shen {
36051600c3e5SJian Shen 	struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
36061600c3e5SJian Shen 	int i, j, reg_um, separator_num;
36071600c3e5SJian Shen 	u32 *reg = data;
36081600c3e5SJian Shen 
36091600c3e5SJian Shen 	*version = hdev->fw_version;
36101600c3e5SJian Shen 
36111600c3e5SJian Shen 	/* fetching per-VF registers values from VF PCIe register space */
36121600c3e5SJian Shen 	reg_um = sizeof(cmdq_reg_addr_list) / sizeof(u32);
36131600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36141600c3e5SJian Shen 	for (i = 0; i < reg_um; i++)
36151600c3e5SJian Shen 		*reg++ = hclgevf_read_dev(&hdev->hw, cmdq_reg_addr_list[i]);
36161600c3e5SJian Shen 	for (i = 0; i < separator_num; i++)
36171600c3e5SJian Shen 		*reg++ = SEPARATOR_VALUE;
36181600c3e5SJian Shen 
36191600c3e5SJian Shen 	reg_um = sizeof(common_reg_addr_list) / sizeof(u32);
36201600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36211600c3e5SJian Shen 	for (i = 0; i < reg_um; i++)
36221600c3e5SJian Shen 		*reg++ = hclgevf_read_dev(&hdev->hw, common_reg_addr_list[i]);
36231600c3e5SJian Shen 	for (i = 0; i < separator_num; i++)
36241600c3e5SJian Shen 		*reg++ = SEPARATOR_VALUE;
36251600c3e5SJian Shen 
36261600c3e5SJian Shen 	reg_um = sizeof(ring_reg_addr_list) / sizeof(u32);
36271600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36281600c3e5SJian Shen 	for (j = 0; j < hdev->num_tqps; j++) {
36291600c3e5SJian Shen 		for (i = 0; i < reg_um; i++)
36301600c3e5SJian Shen 			*reg++ = hclgevf_read_dev(&hdev->hw,
36311600c3e5SJian Shen 						  ring_reg_addr_list[i] +
36321600c3e5SJian Shen 						  0x200 * j);
36331600c3e5SJian Shen 		for (i = 0; i < separator_num; i++)
36341600c3e5SJian Shen 			*reg++ = SEPARATOR_VALUE;
36351600c3e5SJian Shen 	}
36361600c3e5SJian Shen 
36371600c3e5SJian Shen 	reg_um = sizeof(tqp_intr_reg_addr_list) / sizeof(u32);
36381600c3e5SJian Shen 	separator_num = MAX_SEPARATE_NUM - reg_um % REG_NUM_PER_LINE;
36391600c3e5SJian Shen 	for (j = 0; j < hdev->num_msi_used - 1; j++) {
36401600c3e5SJian Shen 		for (i = 0; i < reg_um; i++)
36411600c3e5SJian Shen 			*reg++ = hclgevf_read_dev(&hdev->hw,
36421600c3e5SJian Shen 						  tqp_intr_reg_addr_list[i] +
36431600c3e5SJian Shen 						  4 * j);
36441600c3e5SJian Shen 		for (i = 0; i < separator_num; i++)
36451600c3e5SJian Shen 			*reg++ = SEPARATOR_VALUE;
36461600c3e5SJian Shen 	}
36471600c3e5SJian Shen }
36481600c3e5SJian Shen 
364992f11ea1SJian Shen void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
365092f11ea1SJian Shen 					u8 *port_base_vlan_info, u8 data_size)
365192f11ea1SJian Shen {
365292f11ea1SJian Shen 	struct hnae3_handle *nic = &hdev->nic;
3653d3410018SYufeng Mo 	struct hclge_vf_to_pf_msg send_msg;
3654a6f7bfdcSJian Shen 	int ret;
365592f11ea1SJian Shen 
365692f11ea1SJian Shen 	rtnl_lock();
3657a6f7bfdcSJian Shen 
3658b7b5d25bSGuojia Liao 	if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
3659b7b5d25bSGuojia Liao 	    test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) {
3660a6f7bfdcSJian Shen 		dev_warn(&hdev->pdev->dev,
3661a6f7bfdcSJian Shen 			 "is resetting when updating port based vlan info\n");
366292f11ea1SJian Shen 		rtnl_unlock();
3663a6f7bfdcSJian Shen 		return;
3664a6f7bfdcSJian Shen 	}
3665a6f7bfdcSJian Shen 
3666a6f7bfdcSJian Shen 	ret = hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
3667a6f7bfdcSJian Shen 	if (ret) {
3668a6f7bfdcSJian Shen 		rtnl_unlock();
3669a6f7bfdcSJian Shen 		return;
3670a6f7bfdcSJian Shen 	}
367192f11ea1SJian Shen 
367292f11ea1SJian Shen 	/* send msg to PF and wait update port based vlan info */
3673d3410018SYufeng Mo 	hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
3674d3410018SYufeng Mo 			       HCLGE_MBX_PORT_BASE_VLAN_CFG);
3675d3410018SYufeng Mo 	memcpy(send_msg.data, port_base_vlan_info, data_size);
3676a6f7bfdcSJian Shen 	ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
3677a6f7bfdcSJian Shen 	if (!ret) {
367892f11ea1SJian Shen 		if (state == HNAE3_PORT_BASE_VLAN_DISABLE)
3679a6f7bfdcSJian Shen 			nic->port_base_vlan_state = state;
368092f11ea1SJian Shen 		else
368192f11ea1SJian Shen 			nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
3682a6f7bfdcSJian Shen 	}
368392f11ea1SJian Shen 
368492f11ea1SJian Shen 	hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
368592f11ea1SJian Shen 	rtnl_unlock();
368692f11ea1SJian Shen }
368792f11ea1SJian Shen 
3688e2cb1decSSalil Mehta static const struct hnae3_ae_ops hclgevf_ops = {
3689e2cb1decSSalil Mehta 	.init_ae_dev = hclgevf_init_ae_dev,
3690e2cb1decSSalil Mehta 	.uninit_ae_dev = hclgevf_uninit_ae_dev,
36916ff3cf07SHuazhong Tan 	.flr_prepare = hclgevf_flr_prepare,
36926ff3cf07SHuazhong Tan 	.flr_done = hclgevf_flr_done,
3693e718a93fSPeng Li 	.init_client_instance = hclgevf_init_client_instance,
3694e718a93fSPeng Li 	.uninit_client_instance = hclgevf_uninit_client_instance,
3695e2cb1decSSalil Mehta 	.start = hclgevf_ae_start,
3696e2cb1decSSalil Mehta 	.stop = hclgevf_ae_stop,
3697a6d818e3SYunsheng Lin 	.client_start = hclgevf_client_start,
3698a6d818e3SYunsheng Lin 	.client_stop = hclgevf_client_stop,
3699e2cb1decSSalil Mehta 	.map_ring_to_vector = hclgevf_map_ring_to_vector,
3700e2cb1decSSalil Mehta 	.unmap_ring_from_vector = hclgevf_unmap_ring_from_vector,
3701e2cb1decSSalil Mehta 	.get_vector = hclgevf_get_vector,
37020d3e6631SYunsheng Lin 	.put_vector = hclgevf_put_vector,
3703e2cb1decSSalil Mehta 	.reset_queue = hclgevf_reset_tqp,
3704e2cb1decSSalil Mehta 	.get_mac_addr = hclgevf_get_mac_addr,
3705e2cb1decSSalil Mehta 	.set_mac_addr = hclgevf_set_mac_addr,
3706e2cb1decSSalil Mehta 	.add_uc_addr = hclgevf_add_uc_addr,
3707e2cb1decSSalil Mehta 	.rm_uc_addr = hclgevf_rm_uc_addr,
3708e2cb1decSSalil Mehta 	.add_mc_addr = hclgevf_add_mc_addr,
3709e2cb1decSSalil Mehta 	.rm_mc_addr = hclgevf_rm_mc_addr,
3710e2cb1decSSalil Mehta 	.get_stats = hclgevf_get_stats,
3711e2cb1decSSalil Mehta 	.update_stats = hclgevf_update_stats,
3712e2cb1decSSalil Mehta 	.get_strings = hclgevf_get_strings,
3713e2cb1decSSalil Mehta 	.get_sset_count = hclgevf_get_sset_count,
3714e2cb1decSSalil Mehta 	.get_rss_key_size = hclgevf_get_rss_key_size,
3715e2cb1decSSalil Mehta 	.get_rss = hclgevf_get_rss,
3716e2cb1decSSalil Mehta 	.set_rss = hclgevf_set_rss,
3717d97b3072SJian Shen 	.get_rss_tuple = hclgevf_get_rss_tuple,
3718d97b3072SJian Shen 	.set_rss_tuple = hclgevf_set_rss_tuple,
3719e2cb1decSSalil Mehta 	.get_tc_size = hclgevf_get_tc_size,
3720e2cb1decSSalil Mehta 	.get_fw_version = hclgevf_get_fw_version,
3721e2cb1decSSalil Mehta 	.set_vlan_filter = hclgevf_set_vlan_filter,
3722b2641e2aSYunsheng Lin 	.enable_hw_strip_rxvtag = hclgevf_en_hw_strip_rxvtag,
37236d4c3981SSalil Mehta 	.reset_event = hclgevf_reset_event,
3724720bd583SHuazhong Tan 	.set_default_reset_request = hclgevf_set_def_reset_request,
37254093d1a2SGuangbin Huang 	.set_channels = hclgevf_set_channels,
3726849e4607SPeng Li 	.get_channels = hclgevf_get_channels,
3727cc719218SPeng Li 	.get_tqps_and_rss_info = hclgevf_get_tqps_and_rss_info,
37281600c3e5SJian Shen 	.get_regs_len = hclgevf_get_regs_len,
37291600c3e5SJian Shen 	.get_regs = hclgevf_get_regs,
3730175ec96bSFuyun Liang 	.get_status = hclgevf_get_status,
37314a152de9SFuyun Liang 	.get_ksettings_an_result = hclgevf_get_ksettings_an_result,
3732c136b884SPeng Li 	.get_media_type = hclgevf_get_media_type,
37334d60291bSHuazhong Tan 	.get_hw_reset_stat = hclgevf_get_hw_reset_stat,
37344d60291bSHuazhong Tan 	.ae_dev_resetting = hclgevf_ae_dev_resetting,
37354d60291bSHuazhong Tan 	.ae_dev_reset_cnt = hclgevf_ae_dev_reset_cnt,
37365c9f6b39SPeng Li 	.set_gro_en = hclgevf_gro_en,
3737818f1675SYunsheng Lin 	.set_mtu = hclgevf_set_mtu,
37380c29d191Sliuzhongzhu 	.get_global_queue_id = hclgevf_get_qid_global,
37398cdb992fSJian Shen 	.set_timer_task = hclgevf_set_timer_task,
37409194d18bSliuzhongzhu 	.get_link_mode = hclgevf_get_link_mode,
3741e196ec75SJian Shen 	.set_promisc_mode = hclgevf_set_promisc_mode,
3742c631c696SJian Shen 	.request_update_promisc_mode = hclgevf_request_update_promisc_mode,
3743fe735c84SHuazhong Tan 	.get_cmdq_stat = hclgevf_get_cmdq_stat,
3744e2cb1decSSalil Mehta };
3745e2cb1decSSalil Mehta 
3746e2cb1decSSalil Mehta static struct hnae3_ae_algo ae_algovf = {
3747e2cb1decSSalil Mehta 	.ops = &hclgevf_ops,
3748e2cb1decSSalil Mehta 	.pdev_id_table = ae_algovf_pci_tbl,
3749e2cb1decSSalil Mehta };
3750e2cb1decSSalil Mehta 
3751e2cb1decSSalil Mehta static int hclgevf_init(void)
3752e2cb1decSSalil Mehta {
3753e2cb1decSSalil Mehta 	pr_info("%s is initializing\n", HCLGEVF_NAME);
3754e2cb1decSSalil Mehta 
375516deaef2SYunsheng Lin 	hclgevf_wq = alloc_workqueue("%s", 0, 0, HCLGEVF_NAME);
37560ea68902SYunsheng Lin 	if (!hclgevf_wq) {
37570ea68902SYunsheng Lin 		pr_err("%s: failed to create workqueue\n", HCLGEVF_NAME);
37580ea68902SYunsheng Lin 		return -ENOMEM;
37590ea68902SYunsheng Lin 	}
37600ea68902SYunsheng Lin 
3761854cf33aSFuyun Liang 	hnae3_register_ae_algo(&ae_algovf);
3762854cf33aSFuyun Liang 
3763854cf33aSFuyun Liang 	return 0;
3764e2cb1decSSalil Mehta }
3765e2cb1decSSalil Mehta 
3766e2cb1decSSalil Mehta static void hclgevf_exit(void)
3767e2cb1decSSalil Mehta {
3768e2cb1decSSalil Mehta 	hnae3_unregister_ae_algo(&ae_algovf);
37690ea68902SYunsheng Lin 	destroy_workqueue(hclgevf_wq);
3770e2cb1decSSalil Mehta }
3771e2cb1decSSalil Mehta module_init(hclgevf_init);
3772e2cb1decSSalil Mehta module_exit(hclgevf_exit);
3773e2cb1decSSalil Mehta 
3774e2cb1decSSalil Mehta MODULE_LICENSE("GPL");
3775e2cb1decSSalil Mehta MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
3776e2cb1decSSalil Mehta MODULE_DESCRIPTION("HCLGEVF Driver");
3777e2cb1decSSalil Mehta MODULE_VERSION(HCLGEVF_MOD_VERSION);
3778