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"
9939ccd10SJijie Shao #include "hclgevf_regs.h"
10e2cb1decSSalil Mehta #include "hclge_mbx.h"
11e2cb1decSSalil Mehta #include "hnae3.h"
12cd624299SYufeng Mo #include "hclgevf_devlink.h"
13027733b1SJie Wang #include "hclge_comm_rss.h"
142a1a1a7bSHao Lan #include "hclgevf_trace.h"
15e2cb1decSSalil Mehta
16e2cb1decSSalil Mehta #define HCLGEVF_NAME "hclgevf"
17e2cb1decSSalil Mehta
18bbe6540eSHuazhong Tan #define HCLGEVF_RESET_MAX_FAIL_CNT 5
19bbe6540eSHuazhong Tan
209c6f7085SHuazhong Tan static int hclgevf_reset_hdev(struct hclgevf_dev *hdev);
215e7414cdSJian Shen static void hclgevf_task_schedule(struct hclgevf_dev *hdev,
225e7414cdSJian Shen unsigned long delay);
235e7414cdSJian Shen
24e2cb1decSSalil Mehta static struct hnae3_ae_algo ae_algovf;
25e2cb1decSSalil Mehta
260ea68902SYunsheng Lin static struct workqueue_struct *hclgevf_wq;
270ea68902SYunsheng Lin
28e2cb1decSSalil Mehta static const struct pci_device_id ae_algovf_pci_tbl[] = {
29c155e22bSGuangbin Huang {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_VF), 0},
30c155e22bSGuangbin Huang {PCI_VDEVICE(HUAWEI, HNAE3_DEV_ID_RDMA_DCB_PFC_VF),
31c155e22bSGuangbin Huang HNAE3_DEV_SUPPORT_ROCE_DCB_BITS},
32e2cb1decSSalil Mehta /* required last entry */
33e2cb1decSSalil Mehta {0, }
34e2cb1decSSalil Mehta };
35e2cb1decSSalil Mehta
362f550a46SYunsheng Lin MODULE_DEVICE_TABLE(pci, ae_algovf_pci_tbl);
372f550a46SYunsheng Lin
38aab8d1c6SJie Wang /* hclgevf_cmd_send - send command to command queue
39aab8d1c6SJie Wang * @hw: pointer to the hw struct
40aab8d1c6SJie Wang * @desc: prefilled descriptor for describing the command
41aab8d1c6SJie Wang * @num : the number of descriptors to be sent
42aab8d1c6SJie Wang *
43aab8d1c6SJie Wang * This is the main send command for command queue, it
44aab8d1c6SJie Wang * sends the queue, cleans the queue, etc
45aab8d1c6SJie Wang */
hclgevf_cmd_send(struct hclgevf_hw * hw,struct hclge_desc * desc,int num)46aab8d1c6SJie Wang int hclgevf_cmd_send(struct hclgevf_hw *hw, struct hclge_desc *desc, int num)
47aab8d1c6SJie Wang {
489970308fSJie Wang return hclge_comm_cmd_send(&hw->hw, desc, num);
49aab8d1c6SJie Wang }
50aab8d1c6SJie Wang
hclgevf_trace_cmd_send(struct hclge_comm_hw * hw,struct hclge_desc * desc,int num,bool is_special)512a1a1a7bSHao Lan static void hclgevf_trace_cmd_send(struct hclge_comm_hw *hw, struct hclge_desc *desc,
522a1a1a7bSHao Lan int num, bool is_special)
532a1a1a7bSHao Lan {
542a1a1a7bSHao Lan int i;
552a1a1a7bSHao Lan
562a1a1a7bSHao Lan trace_hclge_vf_cmd_send(hw, desc, 0, num);
572a1a1a7bSHao Lan
582a1a1a7bSHao Lan if (is_special)
592a1a1a7bSHao Lan return;
602a1a1a7bSHao Lan
612a1a1a7bSHao Lan for (i = 1; i < num; i++)
622a1a1a7bSHao Lan trace_hclge_vf_cmd_send(hw, &desc[i], i, num);
632a1a1a7bSHao Lan }
642a1a1a7bSHao Lan
hclgevf_trace_cmd_get(struct hclge_comm_hw * hw,struct hclge_desc * desc,int num,bool is_special)652a1a1a7bSHao Lan static void hclgevf_trace_cmd_get(struct hclge_comm_hw *hw, struct hclge_desc *desc,
662a1a1a7bSHao Lan int num, bool is_special)
672a1a1a7bSHao Lan {
682a1a1a7bSHao Lan int i;
692a1a1a7bSHao Lan
702a1a1a7bSHao Lan if (!HCLGE_COMM_SEND_SYNC(le16_to_cpu(desc->flag)))
712a1a1a7bSHao Lan return;
722a1a1a7bSHao Lan
732a1a1a7bSHao Lan trace_hclge_vf_cmd_get(hw, desc, 0, num);
742a1a1a7bSHao Lan
752a1a1a7bSHao Lan if (is_special)
762a1a1a7bSHao Lan return;
772a1a1a7bSHao Lan
782a1a1a7bSHao Lan for (i = 1; i < num; i++)
792a1a1a7bSHao Lan trace_hclge_vf_cmd_get(hw, &desc[i], i, num);
802a1a1a7bSHao Lan }
812a1a1a7bSHao Lan
822a1a1a7bSHao Lan static const struct hclge_comm_cmq_ops hclgevf_cmq_ops = {
832a1a1a7bSHao Lan .trace_cmd_send = hclgevf_trace_cmd_send,
842a1a1a7bSHao Lan .trace_cmd_get = hclgevf_trace_cmd_get,
852a1a1a7bSHao Lan };
862a1a1a7bSHao Lan
hclgevf_arq_init(struct hclgevf_dev * hdev)87aab8d1c6SJie Wang void hclgevf_arq_init(struct hclgevf_dev *hdev)
88aab8d1c6SJie Wang {
89aab8d1c6SJie Wang struct hclge_comm_cmq *cmdq = &hdev->hw.hw.cmq;
90aab8d1c6SJie Wang
91aab8d1c6SJie Wang spin_lock(&cmdq->crq.lock);
92aab8d1c6SJie Wang /* initialize the pointers of async rx queue of mailbox */
93aab8d1c6SJie Wang hdev->arq.hdev = hdev;
94aab8d1c6SJie Wang hdev->arq.head = 0;
95aab8d1c6SJie Wang hdev->arq.tail = 0;
96aab8d1c6SJie Wang atomic_set(&hdev->arq.count, 0);
97aab8d1c6SJie Wang spin_unlock(&cmdq->crq.lock);
98aab8d1c6SJie Wang }
99aab8d1c6SJie Wang
hclgevf_ae_get_hdev(struct hnae3_handle * handle)100939ccd10SJijie Shao struct hclgevf_dev *hclgevf_ae_get_hdev(struct hnae3_handle *handle)
101e2cb1decSSalil Mehta {
102eed9535fSPeng Li if (!handle->client)
103eed9535fSPeng Li return container_of(handle, struct hclgevf_dev, nic);
104eed9535fSPeng Li else if (handle->client->type == HNAE3_CLIENT_ROCE)
105eed9535fSPeng Li return container_of(handle, struct hclgevf_dev, roce);
106eed9535fSPeng Li else
107e2cb1decSSalil Mehta return container_of(handle, struct hclgevf_dev, nic);
108e2cb1decSSalil Mehta }
109e2cb1decSSalil Mehta
hclgevf_update_stats(struct hnae3_handle * handle)110ed1c6f35SPeiyang Wang static void hclgevf_update_stats(struct hnae3_handle *handle)
111e2cb1decSSalil Mehta {
112e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
113e2cb1decSSalil Mehta int status;
114e2cb1decSSalil Mehta
1154afc310cSJie Wang status = hclge_comm_tqps_update_stats(handle, &hdev->hw.hw);
116e2cb1decSSalil Mehta if (status)
117e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
118e2cb1decSSalil Mehta "VF update of TQPS stats fail, status = %d.\n",
119e2cb1decSSalil Mehta status);
120e2cb1decSSalil Mehta }
121e2cb1decSSalil Mehta
hclgevf_get_sset_count(struct hnae3_handle * handle,int strset)122e2cb1decSSalil Mehta static int hclgevf_get_sset_count(struct hnae3_handle *handle, int strset)
123e2cb1decSSalil Mehta {
124e2cb1decSSalil Mehta if (strset == ETH_SS_TEST)
125e2cb1decSSalil Mehta return -EOPNOTSUPP;
126e2cb1decSSalil Mehta else if (strset == ETH_SS_STATS)
1274afc310cSJie Wang return hclge_comm_tqps_get_sset_count(handle);
128e2cb1decSSalil Mehta
129e2cb1decSSalil Mehta return 0;
130e2cb1decSSalil Mehta }
131e2cb1decSSalil Mehta
hclgevf_get_strings(struct hnae3_handle * handle,u32 strset,u8 ** data)132e2cb1decSSalil Mehta static void hclgevf_get_strings(struct hnae3_handle *handle, u32 strset,
1334ea3e221SRosen Penev u8 **data)
134e2cb1decSSalil Mehta {
135e2cb1decSSalil Mehta if (strset == ETH_SS_STATS)
1364ea3e221SRosen Penev hclge_comm_tqps_get_strings(handle, data);
137e2cb1decSSalil Mehta }
138e2cb1decSSalil Mehta
hclgevf_get_stats(struct hnae3_handle * handle,u64 * data)139e2cb1decSSalil Mehta static void hclgevf_get_stats(struct hnae3_handle *handle, u64 *data)
140e2cb1decSSalil Mehta {
1414afc310cSJie Wang hclge_comm_tqps_get_stats(handle, data);
142e2cb1decSSalil Mehta }
143e2cb1decSSalil Mehta
hclgevf_build_send_msg(struct hclge_vf_to_pf_msg * msg,u8 code,u8 subcode)144d3410018SYufeng Mo static void hclgevf_build_send_msg(struct hclge_vf_to_pf_msg *msg, u8 code,
145d3410018SYufeng Mo u8 subcode)
146d3410018SYufeng Mo {
147d3410018SYufeng Mo if (msg) {
148d3410018SYufeng Mo memset(msg, 0, sizeof(struct hclge_vf_to_pf_msg));
149d3410018SYufeng Mo msg->code = code;
150d3410018SYufeng Mo msg->subcode = subcode;
151d3410018SYufeng Mo }
152d3410018SYufeng Mo }
153d3410018SYufeng Mo
hclgevf_get_basic_info(struct hclgevf_dev * hdev)15432e6d104SJian Shen static int hclgevf_get_basic_info(struct hclgevf_dev *hdev)
155e2cb1decSSalil Mehta {
15632e6d104SJian Shen struct hnae3_ae_dev *ae_dev = hdev->ae_dev;
15732e6d104SJian Shen u8 resp_msg[HCLGE_MBX_MAX_RESP_DATA_SIZE];
15832e6d104SJian Shen struct hclge_basic_info *basic_info;
159d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
16032e6d104SJian Shen unsigned long caps;
161e2cb1decSSalil Mehta int status;
162e2cb1decSSalil Mehta
16332e6d104SJian Shen hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_BASIC_INFO, 0);
16432e6d104SJian Shen status = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
165d3410018SYufeng Mo sizeof(resp_msg));
166e2cb1decSSalil Mehta if (status) {
167e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
16832e6d104SJian Shen "failed to get basic info from pf, ret = %d", status);
169e2cb1decSSalil Mehta return status;
170e2cb1decSSalil Mehta }
171e2cb1decSSalil Mehta
17232e6d104SJian Shen basic_info = (struct hclge_basic_info *)resp_msg;
17332e6d104SJian Shen
17432e6d104SJian Shen hdev->hw_tc_map = basic_info->hw_tc_map;
175416eedb6SJie Wang hdev->mbx_api_version = le16_to_cpu(basic_info->mbx_api_version);
176416eedb6SJie Wang caps = le32_to_cpu(basic_info->pf_caps);
17732e6d104SJian Shen if (test_bit(HNAE3_PF_SUPPORT_VLAN_FLTR_MDF_B, &caps))
17832e6d104SJian Shen set_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps);
179e2cb1decSSalil Mehta
180e2cb1decSSalil Mehta return 0;
181e2cb1decSSalil Mehta }
182e2cb1decSSalil Mehta
hclgevf_get_port_base_vlan_filter_state(struct hclgevf_dev * hdev)18392f11ea1SJian Shen static int hclgevf_get_port_base_vlan_filter_state(struct hclgevf_dev *hdev)
18492f11ea1SJian Shen {
18592f11ea1SJian Shen struct hnae3_handle *nic = &hdev->nic;
186d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
18792f11ea1SJian Shen u8 resp_msg;
18892f11ea1SJian Shen int ret;
18992f11ea1SJian Shen
190d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
191d3410018SYufeng Mo HCLGE_MBX_GET_PORT_BASE_VLAN_STATE);
192d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, &resp_msg,
193d3410018SYufeng Mo sizeof(u8));
19492f11ea1SJian Shen if (ret) {
19592f11ea1SJian Shen dev_err(&hdev->pdev->dev,
19692f11ea1SJian Shen "VF request to get port based vlan state failed %d",
19792f11ea1SJian Shen ret);
19892f11ea1SJian Shen return ret;
19992f11ea1SJian Shen }
20092f11ea1SJian Shen
20192f11ea1SJian Shen nic->port_base_vlan_state = resp_msg;
20292f11ea1SJian Shen
20392f11ea1SJian Shen return 0;
20492f11ea1SJian Shen }
20592f11ea1SJian Shen
hclgevf_get_queue_info(struct hclgevf_dev * hdev)2066cee6fc3SJian Shen static int hclgevf_get_queue_info(struct hclgevf_dev *hdev)
207e2cb1decSSalil Mehta {
208c0425944SPeng Li #define HCLGEVF_TQPS_RSS_INFO_LEN 6
209d3410018SYufeng Mo
210416eedb6SJie Wang struct hclge_mbx_vf_queue_info *queue_info;
211e2cb1decSSalil Mehta u8 resp_msg[HCLGEVF_TQPS_RSS_INFO_LEN];
212d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
213e2cb1decSSalil Mehta int status;
214e2cb1decSSalil Mehta
215d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_QINFO, 0);
216d3410018SYufeng Mo status = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
217e2cb1decSSalil Mehta HCLGEVF_TQPS_RSS_INFO_LEN);
218e2cb1decSSalil Mehta if (status) {
219e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
220e2cb1decSSalil Mehta "VF request to get tqp info from PF failed %d",
221e2cb1decSSalil Mehta status);
222e2cb1decSSalil Mehta return status;
223e2cb1decSSalil Mehta }
224e2cb1decSSalil Mehta
225416eedb6SJie Wang queue_info = (struct hclge_mbx_vf_queue_info *)resp_msg;
226416eedb6SJie Wang hdev->num_tqps = le16_to_cpu(queue_info->num_tqps);
227416eedb6SJie Wang hdev->rss_size_max = le16_to_cpu(queue_info->rss_size);
228416eedb6SJie Wang hdev->rx_buf_len = le16_to_cpu(queue_info->rx_buf_len);
229c0425944SPeng Li
230c0425944SPeng Li return 0;
231c0425944SPeng Li }
232c0425944SPeng Li
hclgevf_get_queue_depth(struct hclgevf_dev * hdev)233c0425944SPeng Li static int hclgevf_get_queue_depth(struct hclgevf_dev *hdev)
234c0425944SPeng Li {
235c0425944SPeng Li #define HCLGEVF_TQPS_DEPTH_INFO_LEN 4
236d3410018SYufeng Mo
237416eedb6SJie Wang struct hclge_mbx_vf_queue_depth *queue_depth;
238c0425944SPeng Li u8 resp_msg[HCLGEVF_TQPS_DEPTH_INFO_LEN];
239d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
240c0425944SPeng Li int ret;
241c0425944SPeng Li
242d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_QDEPTH, 0);
243d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
244c0425944SPeng Li HCLGEVF_TQPS_DEPTH_INFO_LEN);
245c0425944SPeng Li if (ret) {
246c0425944SPeng Li dev_err(&hdev->pdev->dev,
247c0425944SPeng Li "VF request to get tqp depth info from PF failed %d",
248c0425944SPeng Li ret);
249c0425944SPeng Li return ret;
250c0425944SPeng Li }
251c0425944SPeng Li
252416eedb6SJie Wang queue_depth = (struct hclge_mbx_vf_queue_depth *)resp_msg;
253416eedb6SJie Wang hdev->num_tx_desc = le16_to_cpu(queue_depth->num_tx_desc);
254416eedb6SJie Wang hdev->num_rx_desc = le16_to_cpu(queue_depth->num_rx_desc);
255e2cb1decSSalil Mehta
256e2cb1decSSalil Mehta return 0;
257e2cb1decSSalil Mehta }
258e2cb1decSSalil Mehta
hclgevf_get_qid_global(struct hnae3_handle * handle,u16 queue_id)2590c29d191Sliuzhongzhu static u16 hclgevf_get_qid_global(struct hnae3_handle *handle, u16 queue_id)
2600c29d191Sliuzhongzhu {
2610c29d191Sliuzhongzhu struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
262d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
2630c29d191Sliuzhongzhu u16 qid_in_pf = 0;
264d3410018SYufeng Mo u8 resp_data[2];
2650c29d191Sliuzhongzhu int ret;
2660c29d191Sliuzhongzhu
267d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_QID_IN_PF, 0);
268416eedb6SJie Wang *(__le16 *)send_msg.data = cpu_to_le16(queue_id);
269d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_data,
27063cbf7a9SYufeng Mo sizeof(resp_data));
2710c29d191Sliuzhongzhu if (!ret)
272416eedb6SJie Wang qid_in_pf = le16_to_cpu(*(__le16 *)resp_data);
2730c29d191Sliuzhongzhu
2740c29d191Sliuzhongzhu return qid_in_pf;
2750c29d191Sliuzhongzhu }
2760c29d191Sliuzhongzhu
hclgevf_get_pf_media_type(struct hclgevf_dev * hdev)2779c3e7130Sliuzhongzhu static int hclgevf_get_pf_media_type(struct hclgevf_dev *hdev)
2789c3e7130Sliuzhongzhu {
279d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
28088d10bd6SJian Shen u8 resp_msg[2];
2819c3e7130Sliuzhongzhu int ret;
2829c3e7130Sliuzhongzhu
283d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_MEDIA_TYPE, 0);
284d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
285d3410018SYufeng Mo sizeof(resp_msg));
2869c3e7130Sliuzhongzhu if (ret) {
2879c3e7130Sliuzhongzhu dev_err(&hdev->pdev->dev,
2889c3e7130Sliuzhongzhu "VF request to get the pf port media type failed %d",
2899c3e7130Sliuzhongzhu ret);
2909c3e7130Sliuzhongzhu return ret;
2919c3e7130Sliuzhongzhu }
2929c3e7130Sliuzhongzhu
29388d10bd6SJian Shen hdev->hw.mac.media_type = resp_msg[0];
29488d10bd6SJian Shen hdev->hw.mac.module_type = resp_msg[1];
2959c3e7130Sliuzhongzhu
2969c3e7130Sliuzhongzhu return 0;
2979c3e7130Sliuzhongzhu }
2989c3e7130Sliuzhongzhu
hclgevf_alloc_tqps(struct hclgevf_dev * hdev)299e2cb1decSSalil Mehta static int hclgevf_alloc_tqps(struct hclgevf_dev *hdev)
300e2cb1decSSalil Mehta {
30187a9b2fdSYufeng Mo struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
3024afc310cSJie Wang struct hclge_comm_tqp *tqp;
303e2cb1decSSalil Mehta int i;
304e2cb1decSSalil Mehta
305e2cb1decSSalil Mehta hdev->htqp = devm_kcalloc(&hdev->pdev->dev, hdev->num_tqps,
3064afc310cSJie Wang sizeof(struct hclge_comm_tqp), GFP_KERNEL);
307e2cb1decSSalil Mehta if (!hdev->htqp)
308e2cb1decSSalil Mehta return -ENOMEM;
309e2cb1decSSalil Mehta
310e2cb1decSSalil Mehta tqp = hdev->htqp;
311e2cb1decSSalil Mehta
312e2cb1decSSalil Mehta for (i = 0; i < hdev->num_tqps; i++) {
313e2cb1decSSalil Mehta tqp->dev = &hdev->pdev->dev;
314e2cb1decSSalil Mehta tqp->index = i;
315e2cb1decSSalil Mehta
316e2cb1decSSalil Mehta tqp->q.ae_algo = &ae_algovf;
317e2cb1decSSalil Mehta tqp->q.buf_size = hdev->rx_buf_len;
318c0425944SPeng Li tqp->q.tx_desc_num = hdev->num_tx_desc;
319c0425944SPeng Li tqp->q.rx_desc_num = hdev->num_rx_desc;
3209a5ef4aaSYonglong Liu
3219a5ef4aaSYonglong Liu /* need an extended offset to configure queues >=
3229a5ef4aaSYonglong Liu * HCLGEVF_TQP_MAX_SIZE_DEV_V2.
3239a5ef4aaSYonglong Liu */
3249a5ef4aaSYonglong Liu if (i < HCLGEVF_TQP_MAX_SIZE_DEV_V2)
325076bb537SJie Wang tqp->q.io_base = hdev->hw.hw.io_base +
3269a5ef4aaSYonglong Liu HCLGEVF_TQP_REG_OFFSET +
327e2cb1decSSalil Mehta i * HCLGEVF_TQP_REG_SIZE;
3289a5ef4aaSYonglong Liu else
329076bb537SJie Wang tqp->q.io_base = hdev->hw.hw.io_base +
3309a5ef4aaSYonglong Liu HCLGEVF_TQP_REG_OFFSET +
3319a5ef4aaSYonglong Liu HCLGEVF_TQP_EXT_REG_OFFSET +
3329a5ef4aaSYonglong Liu (i - HCLGEVF_TQP_MAX_SIZE_DEV_V2) *
3339a5ef4aaSYonglong Liu HCLGEVF_TQP_REG_SIZE;
334e2cb1decSSalil Mehta
33587a9b2fdSYufeng Mo /* when device supports tx push and has device memory,
33687a9b2fdSYufeng Mo * the queue can execute push mode or doorbell mode on
33787a9b2fdSYufeng Mo * device memory.
33887a9b2fdSYufeng Mo */
33987a9b2fdSYufeng Mo if (test_bit(HNAE3_DEV_SUPPORT_TX_PUSH_B, ae_dev->caps))
34087a9b2fdSYufeng Mo tqp->q.mem_base = hdev->hw.hw.mem_base +
34187a9b2fdSYufeng Mo HCLGEVF_TQP_MEM_OFFSET(hdev, i);
34287a9b2fdSYufeng Mo
343e2cb1decSSalil Mehta tqp++;
344e2cb1decSSalil Mehta }
345e2cb1decSSalil Mehta
346e2cb1decSSalil Mehta return 0;
347e2cb1decSSalil Mehta }
348e2cb1decSSalil Mehta
hclgevf_knic_setup(struct hclgevf_dev * hdev)349e2cb1decSSalil Mehta static int hclgevf_knic_setup(struct hclgevf_dev *hdev)
350e2cb1decSSalil Mehta {
351e2cb1decSSalil Mehta struct hnae3_handle *nic = &hdev->nic;
352e2cb1decSSalil Mehta struct hnae3_knic_private_info *kinfo;
353e2cb1decSSalil Mehta u16 new_tqps = hdev->num_tqps;
354ebaf1908SWeihang Li unsigned int i;
35535244430SJian Shen u8 num_tc = 0;
356e2cb1decSSalil Mehta
357e2cb1decSSalil Mehta kinfo = &nic->kinfo;
358c0425944SPeng Li kinfo->num_tx_desc = hdev->num_tx_desc;
359c0425944SPeng Li kinfo->num_rx_desc = hdev->num_rx_desc;
360e2cb1decSSalil Mehta kinfo->rx_buf_len = hdev->rx_buf_len;
36193969dc1SJie Wang for (i = 0; i < HCLGE_COMM_MAX_TC_NUM; i++)
362e2cb1decSSalil Mehta if (hdev->hw_tc_map & BIT(i))
36335244430SJian Shen num_tc++;
364e2cb1decSSalil Mehta
36535244430SJian Shen num_tc = num_tc ? num_tc : 1;
36635244430SJian Shen kinfo->tc_info.num_tc = num_tc;
36735244430SJian Shen kinfo->rss_size = min_t(u16, hdev->rss_size_max, new_tqps / num_tc);
36835244430SJian Shen new_tqps = kinfo->rss_size * num_tc;
369e2cb1decSSalil Mehta kinfo->num_tqps = min(new_tqps, hdev->num_tqps);
370e2cb1decSSalil Mehta
371e2cb1decSSalil Mehta kinfo->tqp = devm_kcalloc(&hdev->pdev->dev, kinfo->num_tqps,
372e2cb1decSSalil Mehta sizeof(struct hnae3_queue *), GFP_KERNEL);
373e2cb1decSSalil Mehta if (!kinfo->tqp)
374e2cb1decSSalil Mehta return -ENOMEM;
375e2cb1decSSalil Mehta
376e2cb1decSSalil Mehta for (i = 0; i < kinfo->num_tqps; i++) {
377e2cb1decSSalil Mehta hdev->htqp[i].q.handle = &hdev->nic;
378e2cb1decSSalil Mehta hdev->htqp[i].q.tqp_index = i;
379e2cb1decSSalil Mehta kinfo->tqp[i] = &hdev->htqp[i].q;
380e2cb1decSSalil Mehta }
381e2cb1decSSalil Mehta
382580a05f9SYonglong Liu /* after init the max rss_size and tqps, adjust the default tqp numbers
383580a05f9SYonglong Liu * and rss size with the actual vector numbers
384580a05f9SYonglong Liu */
385580a05f9SYonglong Liu kinfo->num_tqps = min_t(u16, hdev->num_nic_msix - 1, kinfo->num_tqps);
38635244430SJian Shen kinfo->rss_size = min_t(u16, kinfo->num_tqps / num_tc,
387580a05f9SYonglong Liu kinfo->rss_size);
388580a05f9SYonglong Liu
389e2cb1decSSalil Mehta return 0;
390e2cb1decSSalil Mehta }
391e2cb1decSSalil Mehta
hclgevf_request_link_info(struct hclgevf_dev * hdev)392e2cb1decSSalil Mehta static void hclgevf_request_link_info(struct hclgevf_dev *hdev)
393e2cb1decSSalil Mehta {
394d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
395e2cb1decSSalil Mehta int status;
396e2cb1decSSalil Mehta
397d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_LINK_STATUS, 0);
398d3410018SYufeng Mo status = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
399e2cb1decSSalil Mehta if (status)
400e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
401e2cb1decSSalil Mehta "VF failed to fetch link status(%d) from PF", status);
402e2cb1decSSalil Mehta }
403e2cb1decSSalil Mehta
hclgevf_update_link_status(struct hclgevf_dev * hdev,int link_state)404e2cb1decSSalil Mehta void hclgevf_update_link_status(struct hclgevf_dev *hdev, int link_state)
405e2cb1decSSalil Mehta {
40645e92b7eSPeng Li struct hnae3_handle *rhandle = &hdev->roce;
407e2cb1decSSalil Mehta struct hnae3_handle *handle = &hdev->nic;
40845e92b7eSPeng Li struct hnae3_client *rclient;
409e2cb1decSSalil Mehta struct hnae3_client *client;
410e2cb1decSSalil Mehta
411ff200099SYunsheng Lin if (test_and_set_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state))
412ff200099SYunsheng Lin return;
413ff200099SYunsheng Lin
414e2cb1decSSalil Mehta client = handle->client;
41545e92b7eSPeng Li rclient = hdev->roce_client;
416e2cb1decSSalil Mehta
417582d37bbSPeng Li link_state =
418582d37bbSPeng Li test_bit(HCLGEVF_STATE_DOWN, &hdev->state) ? 0 : link_state;
419e2cb1decSSalil Mehta if (link_state != hdev->hw.mac.link) {
420b15c072aSYonglong Liu hdev->hw.mac.link = link_state;
421e2cb1decSSalil Mehta client->ops->link_status_change(handle, !!link_state);
42245e92b7eSPeng Li if (rclient && rclient->ops->link_status_change)
42345e92b7eSPeng Li rclient->ops->link_status_change(rhandle, !!link_state);
424e2cb1decSSalil Mehta }
425ff200099SYunsheng Lin
426ff200099SYunsheng Lin clear_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state);
427e2cb1decSSalil Mehta }
428e2cb1decSSalil Mehta
hclgevf_update_link_mode(struct hclgevf_dev * hdev)429538abaf3SYueHaibing static void hclgevf_update_link_mode(struct hclgevf_dev *hdev)
4309194d18bSliuzhongzhu {
4319194d18bSliuzhongzhu #define HCLGEVF_ADVERTISING 0
4329194d18bSliuzhongzhu #define HCLGEVF_SUPPORTED 1
4339194d18bSliuzhongzhu
434d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
435d3410018SYufeng Mo
436d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_LINK_MODE, 0);
437d3410018SYufeng Mo send_msg.data[0] = HCLGEVF_ADVERTISING;
438d3410018SYufeng Mo hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
439d3410018SYufeng Mo send_msg.data[0] = HCLGEVF_SUPPORTED;
440d3410018SYufeng Mo hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
4419194d18bSliuzhongzhu }
4429194d18bSliuzhongzhu
hclgevf_set_handle_info(struct hclgevf_dev * hdev)443e2cb1decSSalil Mehta static int hclgevf_set_handle_info(struct hclgevf_dev *hdev)
444e2cb1decSSalil Mehta {
445e2cb1decSSalil Mehta struct hnae3_handle *nic = &hdev->nic;
446e2cb1decSSalil Mehta int ret;
447e2cb1decSSalil Mehta
448e2cb1decSSalil Mehta nic->ae_algo = &ae_algovf;
449e2cb1decSSalil Mehta nic->pdev = hdev->pdev;
4506639a7b9SPeiyang Wang bitmap_copy(nic->numa_node_mask.bits, hdev->numa_node_mask.bits,
4516639a7b9SPeiyang Wang MAX_NUMNODES);
452424eb834SSalil Mehta nic->flags |= HNAE3_SUPPORT_VF;
453076bb537SJie Wang nic->kinfo.io_base = hdev->hw.hw.io_base;
454e2cb1decSSalil Mehta
455e2cb1decSSalil Mehta ret = hclgevf_knic_setup(hdev);
456e2cb1decSSalil Mehta if (ret)
457e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev, "VF knic setup failed %d\n",
458e2cb1decSSalil Mehta ret);
459e2cb1decSSalil Mehta return ret;
460e2cb1decSSalil Mehta }
461e2cb1decSSalil Mehta
hclgevf_free_vector(struct hclgevf_dev * hdev,int vector_id)462e2cb1decSSalil Mehta static void hclgevf_free_vector(struct hclgevf_dev *hdev, int vector_id)
463e2cb1decSSalil Mehta {
46436cbbdf6SPeng Li if (hdev->vector_status[vector_id] == HCLGEVF_INVALID_VPORT) {
46536cbbdf6SPeng Li dev_warn(&hdev->pdev->dev,
46636cbbdf6SPeng Li "vector(vector_id %d) has been freed.\n", vector_id);
46736cbbdf6SPeng Li return;
46836cbbdf6SPeng Li }
46936cbbdf6SPeng Li
470e2cb1decSSalil Mehta hdev->vector_status[vector_id] = HCLGEVF_INVALID_VPORT;
471e2cb1decSSalil Mehta hdev->num_msi_left += 1;
472e2cb1decSSalil Mehta hdev->num_msi_used -= 1;
473e2cb1decSSalil Mehta }
474e2cb1decSSalil Mehta
hclgevf_get_vector(struct hnae3_handle * handle,u16 vector_num,struct hnae3_vector_info * vector_info)475e2cb1decSSalil Mehta static int hclgevf_get_vector(struct hnae3_handle *handle, u16 vector_num,
476e2cb1decSSalil Mehta struct hnae3_vector_info *vector_info)
477e2cb1decSSalil Mehta {
478e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
479e2cb1decSSalil Mehta struct hnae3_vector_info *vector = vector_info;
480e2cb1decSSalil Mehta int alloc = 0;
481e2cb1decSSalil Mehta int i, j;
482e2cb1decSSalil Mehta
483580a05f9SYonglong Liu vector_num = min_t(u16, hdev->num_nic_msix - 1, vector_num);
484e2cb1decSSalil Mehta vector_num = min(hdev->num_msi_left, vector_num);
485e2cb1decSSalil Mehta
486e2cb1decSSalil Mehta for (j = 0; j < vector_num; j++) {
487e2cb1decSSalil Mehta for (i = HCLGEVF_MISC_VECTOR_NUM + 1; i < hdev->num_msi; i++) {
488e2cb1decSSalil Mehta if (hdev->vector_status[i] == HCLGEVF_INVALID_VPORT) {
489e2cb1decSSalil Mehta vector->vector = pci_irq_vector(hdev->pdev, i);
490076bb537SJie Wang vector->io_addr = hdev->hw.hw.io_base +
491e2cb1decSSalil Mehta HCLGEVF_VECTOR_REG_BASE +
492e2cb1decSSalil Mehta (i - 1) * HCLGEVF_VECTOR_REG_OFFSET;
493e2cb1decSSalil Mehta hdev->vector_status[i] = 0;
494e2cb1decSSalil Mehta hdev->vector_irq[i] = vector->vector;
495e2cb1decSSalil Mehta
496e2cb1decSSalil Mehta vector++;
497e2cb1decSSalil Mehta alloc++;
498e2cb1decSSalil Mehta
499e2cb1decSSalil Mehta break;
500e2cb1decSSalil Mehta }
501e2cb1decSSalil Mehta }
502e2cb1decSSalil Mehta }
503e2cb1decSSalil Mehta hdev->num_msi_left -= alloc;
504e2cb1decSSalil Mehta hdev->num_msi_used += alloc;
505e2cb1decSSalil Mehta
506e2cb1decSSalil Mehta return alloc;
507e2cb1decSSalil Mehta }
508e2cb1decSSalil Mehta
hclgevf_get_vector_index(struct hclgevf_dev * hdev,int vector)509e2cb1decSSalil Mehta static int hclgevf_get_vector_index(struct hclgevf_dev *hdev, int vector)
510e2cb1decSSalil Mehta {
511e2cb1decSSalil Mehta int i;
512e2cb1decSSalil Mehta
513e2cb1decSSalil Mehta for (i = 0; i < hdev->num_msi; i++)
514e2cb1decSSalil Mehta if (vector == hdev->vector_irq[i])
515e2cb1decSSalil Mehta return i;
516e2cb1decSSalil Mehta
517e2cb1decSSalil Mehta return -EINVAL;
518e2cb1decSSalil Mehta }
519e2cb1decSSalil Mehta
520a638b1d8SJian Shen /* for revision 0x20, vf shared the same rss config with pf */
hclgevf_get_rss_hash_key(struct hclgevf_dev * hdev)521a638b1d8SJian Shen static int hclgevf_get_rss_hash_key(struct hclgevf_dev *hdev)
522a638b1d8SJian Shen {
523a638b1d8SJian Shen #define HCLGEVF_RSS_MBX_RESP_LEN 8
524027733b1SJie Wang struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg;
525a638b1d8SJian Shen u8 resp_msg[HCLGEVF_RSS_MBX_RESP_LEN];
526d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
527a638b1d8SJian Shen u16 msg_num, hash_key_index;
528a638b1d8SJian Shen u8 index;
529a638b1d8SJian Shen int ret;
530a638b1d8SJian Shen
531d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_RSS_KEY, 0);
5327428d6c9SJie Wang msg_num = (HCLGE_COMM_RSS_KEY_SIZE + HCLGEVF_RSS_MBX_RESP_LEN - 1) /
533a638b1d8SJian Shen HCLGEVF_RSS_MBX_RESP_LEN;
534a638b1d8SJian Shen for (index = 0; index < msg_num; index++) {
535d3410018SYufeng Mo send_msg.data[0] = index;
536d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, resp_msg,
537a638b1d8SJian Shen HCLGEVF_RSS_MBX_RESP_LEN);
538a638b1d8SJian Shen if (ret) {
539a638b1d8SJian Shen dev_err(&hdev->pdev->dev,
540a638b1d8SJian Shen "VF get rss hash key from PF failed, ret=%d",
541a638b1d8SJian Shen ret);
542a638b1d8SJian Shen return ret;
543a638b1d8SJian Shen }
544a638b1d8SJian Shen
545a638b1d8SJian Shen hash_key_index = HCLGEVF_RSS_MBX_RESP_LEN * index;
546a638b1d8SJian Shen if (index == msg_num - 1)
547a638b1d8SJian Shen memcpy(&rss_cfg->rss_hash_key[hash_key_index],
548a638b1d8SJian Shen &resp_msg[0],
5497428d6c9SJie Wang HCLGE_COMM_RSS_KEY_SIZE - hash_key_index);
550a638b1d8SJian Shen else
551a638b1d8SJian Shen memcpy(&rss_cfg->rss_hash_key[hash_key_index],
552a638b1d8SJian Shen &resp_msg[0], HCLGEVF_RSS_MBX_RESP_LEN);
553a638b1d8SJian Shen }
554a638b1d8SJian Shen
555a638b1d8SJian Shen return 0;
556a638b1d8SJian Shen }
557a638b1d8SJian Shen
hclgevf_get_rss(struct hnae3_handle * handle,u32 * indir,u8 * key,u8 * hfunc)558e2cb1decSSalil Mehta static int hclgevf_get_rss(struct hnae3_handle *handle, u32 *indir, u8 *key,
559e2cb1decSSalil Mehta u8 *hfunc)
560e2cb1decSSalil Mehta {
561e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
562027733b1SJie Wang struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg;
5637428d6c9SJie Wang int ret;
564e2cb1decSSalil Mehta
565295ba232SGuangbin Huang if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
5667428d6c9SJie Wang hclge_comm_get_rss_hash_info(rss_cfg, key, hfunc);
567a638b1d8SJian Shen } else {
568a638b1d8SJian Shen if (hfunc)
569a638b1d8SJian Shen *hfunc = ETH_RSS_HASH_TOP;
570a638b1d8SJian Shen if (key) {
571a638b1d8SJian Shen ret = hclgevf_get_rss_hash_key(hdev);
572a638b1d8SJian Shen if (ret)
573a638b1d8SJian Shen return ret;
574a638b1d8SJian Shen memcpy(key, rss_cfg->rss_hash_key,
5757428d6c9SJie Wang HCLGE_COMM_RSS_KEY_SIZE);
576a638b1d8SJian Shen }
577374ad291SJian Shen }
578374ad291SJian Shen
5797428d6c9SJie Wang hclge_comm_get_rss_indir_tbl(rss_cfg, indir,
5807428d6c9SJie Wang hdev->ae_dev->dev_specs.rss_ind_tbl_size);
581e2cb1decSSalil Mehta
582374ad291SJian Shen return 0;
583e2cb1decSSalil Mehta }
584e2cb1decSSalil Mehta
hclgevf_set_rss(struct hnae3_handle * handle,const u32 * indir,const u8 * key,const u8 hfunc)585e2cb1decSSalil Mehta static int hclgevf_set_rss(struct hnae3_handle *handle, const u32 *indir,
586e2cb1decSSalil Mehta const u8 *key, const u8 hfunc)
587e2cb1decSSalil Mehta {
588e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
589027733b1SJie Wang struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg;
590374ad291SJian Shen int ret, i;
591374ad291SJian Shen
592295ba232SGuangbin Huang if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
59393969dc1SJie Wang ret = hclge_comm_set_rss_hash_key(rss_cfg, &hdev->hw.hw, key,
59493969dc1SJie Wang hfunc);
595374ad291SJian Shen if (ret)
596374ad291SJian Shen return ret;
597374ad291SJian Shen }
598e2cb1decSSalil Mehta
599e2cb1decSSalil Mehta /* update the shadow RSS table with user specified qids */
60087ce161eSGuangbin Huang for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++)
601e2cb1decSSalil Mehta rss_cfg->rss_indirection_tbl[i] = indir[i];
602e2cb1decSSalil Mehta
603e2cb1decSSalil Mehta /* update the hardware */
6047428d6c9SJie Wang return hclge_comm_set_rss_indir_table(hdev->ae_dev, &hdev->hw.hw,
6057428d6c9SJie Wang rss_cfg->rss_indirection_tbl);
6065fd0e7b4SHuazhong Tan }
6075fd0e7b4SHuazhong Tan
hclgevf_set_rss_tuple(struct hnae3_handle * handle,const struct ethtool_rxfh_fields * nfc)6085fd0e7b4SHuazhong Tan static int hclgevf_set_rss_tuple(struct hnae3_handle *handle,
6095fd0e7b4SHuazhong Tan const struct ethtool_rxfh_fields *nfc)
6105fd0e7b4SHuazhong Tan {
6115fd0e7b4SHuazhong Tan struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
6125fd0e7b4SHuazhong Tan int ret;
6135fd0e7b4SHuazhong Tan
6145fd0e7b4SHuazhong Tan if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
6155fd0e7b4SHuazhong Tan return -EOPNOTSUPP;
6165fd0e7b4SHuazhong Tan
61793969dc1SJie Wang ret = hclge_comm_set_rss_tuple(hdev->ae_dev, &hdev->hw.hw,
61893969dc1SJie Wang &hdev->rss_cfg, nfc);
61993969dc1SJie Wang if (ret)
6205fd0e7b4SHuazhong Tan dev_err(&hdev->pdev->dev,
62193969dc1SJie Wang "failed to set rss tuple, ret = %d.\n", ret);
6225fd0e7b4SHuazhong Tan
623d97b3072SJian Shen return ret;
624d97b3072SJian Shen }
625d97b3072SJian Shen
hclgevf_get_rss_tuple(struct hnae3_handle * handle,struct ethtool_rxfh_fields * nfc)626d97b3072SJian Shen static int hclgevf_get_rss_tuple(struct hnae3_handle *handle,
627d97b3072SJian Shen struct ethtool_rxfh_fields *nfc)
628d97b3072SJian Shen {
629d97b3072SJian Shen struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
630d97b3072SJian Shen u8 tuple_sets;
63173f7767eSJian Shen int ret;
632d97b3072SJian Shen
633295ba232SGuangbin Huang if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V2)
634d97b3072SJian Shen return -EOPNOTSUPP;
635d97b3072SJian Shen
636d97b3072SJian Shen nfc->data = 0;
637d97b3072SJian Shen
638027733b1SJie Wang ret = hclge_comm_get_rss_tuple(&hdev->rss_cfg, nfc->flow_type,
63973f7767eSJian Shen &tuple_sets);
64073f7767eSJian Shen if (ret || !tuple_sets)
64173f7767eSJian Shen return ret;
642d97b3072SJian Shen
6437428d6c9SJie Wang nfc->data = hclge_comm_convert_rss_tuple(tuple_sets);
644d97b3072SJian Shen
645d97b3072SJian Shen return 0;
646d97b3072SJian Shen }
647d97b3072SJian Shen
hclgevf_get_tc_size(struct hnae3_handle * handle)648e2cb1decSSalil Mehta static int hclgevf_get_tc_size(struct hnae3_handle *handle)
649e2cb1decSSalil Mehta {
650e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
651027733b1SJie Wang struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg;
652e2cb1decSSalil Mehta
653e2cb1decSSalil Mehta return rss_cfg->rss_size;
654e2cb1decSSalil Mehta }
655e2cb1decSSalil Mehta
hclgevf_bind_ring_to_vector(struct hnae3_handle * handle,bool en,int vector_id,struct hnae3_ring_chain_node * ring_chain)656e2cb1decSSalil Mehta static int hclgevf_bind_ring_to_vector(struct hnae3_handle *handle, bool en,
657b204bc74SPeng Li int vector_id,
658e2cb1decSSalil Mehta struct hnae3_ring_chain_node *ring_chain)
659e2cb1decSSalil Mehta {
660e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
661d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
662e2cb1decSSalil Mehta struct hnae3_ring_chain_node *node;
663e2cb1decSSalil Mehta int status;
664d3410018SYufeng Mo int i = 0;
665e2cb1decSSalil Mehta
666d3410018SYufeng Mo memset(&send_msg, 0, sizeof(send_msg));
667d3410018SYufeng Mo send_msg.code = en ? HCLGE_MBX_MAP_RING_TO_VECTOR :
668c09ba484SPeng Li HCLGE_MBX_UNMAP_RING_TO_VECTOR;
669d3410018SYufeng Mo send_msg.vector_id = vector_id;
670e2cb1decSSalil Mehta
671e2cb1decSSalil Mehta for (node = ring_chain; node; node = node->next) {
672d3410018SYufeng Mo send_msg.param[i].ring_type =
673e4e87715SPeng Li hnae3_get_bit(node->flag, HNAE3_RING_TYPE_B);
674d3410018SYufeng Mo
675d3410018SYufeng Mo send_msg.param[i].tqp_index = node->tqp_index;
676d3410018SYufeng Mo send_msg.param[i].int_gl_index =
677d3410018SYufeng Mo hnae3_get_field(node->int_gl_idx,
67879eee410SFuyun Liang HNAE3_RING_GL_IDX_M,
67979eee410SFuyun Liang HNAE3_RING_GL_IDX_S);
68079eee410SFuyun Liang
6815d02a58dSYunsheng Lin i++;
682d3410018SYufeng Mo if (i == HCLGE_MBX_MAX_RING_CHAIN_PARAM_NUM || !node->next) {
683d3410018SYufeng Mo send_msg.ring_num = i;
684e2cb1decSSalil Mehta
685d3410018SYufeng Mo status = hclgevf_send_mbx_msg(hdev, &send_msg, false,
686d3410018SYufeng Mo NULL, 0);
687e2cb1decSSalil Mehta if (status) {
688e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
689e2cb1decSSalil Mehta "Map TQP fail, status is %d.\n",
690e2cb1decSSalil Mehta status);
691e2cb1decSSalil Mehta return status;
692e2cb1decSSalil Mehta }
693e2cb1decSSalil Mehta i = 0;
694e2cb1decSSalil Mehta }
695e2cb1decSSalil Mehta }
696e2cb1decSSalil Mehta
697e2cb1decSSalil Mehta return 0;
698e2cb1decSSalil Mehta }
699e2cb1decSSalil Mehta
hclgevf_map_ring_to_vector(struct hnae3_handle * handle,int vector,struct hnae3_ring_chain_node * ring_chain)700e2cb1decSSalil Mehta static int hclgevf_map_ring_to_vector(struct hnae3_handle *handle, int vector,
701e2cb1decSSalil Mehta struct hnae3_ring_chain_node *ring_chain)
702e2cb1decSSalil Mehta {
703b204bc74SPeng Li struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
704b204bc74SPeng Li int vector_id;
705b204bc74SPeng Li
706b204bc74SPeng Li vector_id = hclgevf_get_vector_index(hdev, vector);
707b204bc74SPeng Li if (vector_id < 0) {
708b204bc74SPeng Li dev_err(&handle->pdev->dev,
709b204bc74SPeng Li "Get vector index fail. ret =%d\n", vector_id);
710b204bc74SPeng Li return vector_id;
711b204bc74SPeng Li }
712b204bc74SPeng Li
713b204bc74SPeng Li return hclgevf_bind_ring_to_vector(handle, true, vector_id, ring_chain);
714e2cb1decSSalil Mehta }
715e2cb1decSSalil Mehta
hclgevf_unmap_ring_from_vector(struct hnae3_handle * handle,int vector,struct hnae3_ring_chain_node * ring_chain)716e2cb1decSSalil Mehta static int hclgevf_unmap_ring_from_vector(
717e2cb1decSSalil Mehta struct hnae3_handle *handle,
718e2cb1decSSalil Mehta int vector,
719e2cb1decSSalil Mehta struct hnae3_ring_chain_node *ring_chain)
720e2cb1decSSalil Mehta {
721e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
722e2cb1decSSalil Mehta int ret, vector_id;
723e2cb1decSSalil Mehta
724dea846e8SHuazhong Tan if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
725dea846e8SHuazhong Tan return 0;
726dea846e8SHuazhong Tan
727e2cb1decSSalil Mehta vector_id = hclgevf_get_vector_index(hdev, vector);
728e2cb1decSSalil Mehta if (vector_id < 0) {
729e2cb1decSSalil Mehta dev_err(&handle->pdev->dev,
730e2cb1decSSalil Mehta "Get vector index fail. ret =%d\n", vector_id);
731e2cb1decSSalil Mehta return vector_id;
732e2cb1decSSalil Mehta }
733e2cb1decSSalil Mehta
734b204bc74SPeng Li ret = hclgevf_bind_ring_to_vector(handle, false, vector_id, ring_chain);
7350d3e6631SYunsheng Lin if (ret)
736e2cb1decSSalil Mehta dev_err(&handle->pdev->dev,
737e2cb1decSSalil Mehta "Unmap ring from vector fail. vector=%d, ret =%d\n",
738e2cb1decSSalil Mehta vector_id,
739e2cb1decSSalil Mehta ret);
7400d3e6631SYunsheng Lin
741e2cb1decSSalil Mehta return ret;
742e2cb1decSSalil Mehta }
743e2cb1decSSalil Mehta
hclgevf_put_vector(struct hnae3_handle * handle,int vector)7440d3e6631SYunsheng Lin static int hclgevf_put_vector(struct hnae3_handle *handle, int vector)
7450d3e6631SYunsheng Lin {
7460d3e6631SYunsheng Lin struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
74703718db9SYunsheng Lin int vector_id;
7480d3e6631SYunsheng Lin
74903718db9SYunsheng Lin vector_id = hclgevf_get_vector_index(hdev, vector);
75003718db9SYunsheng Lin if (vector_id < 0) {
75103718db9SYunsheng Lin dev_err(&handle->pdev->dev,
75203718db9SYunsheng Lin "hclgevf_put_vector get vector index fail. ret =%d\n",
75303718db9SYunsheng Lin vector_id);
75403718db9SYunsheng Lin return vector_id;
75503718db9SYunsheng Lin }
75603718db9SYunsheng Lin
75703718db9SYunsheng Lin hclgevf_free_vector(hdev, vector_id);
758e2cb1decSSalil Mehta
759e2cb1decSSalil Mehta return 0;
760e2cb1decSSalil Mehta }
761e2cb1decSSalil Mehta
hclgevf_cmd_set_promisc_mode(struct hclgevf_dev * hdev,bool en_uc_pmc,bool en_mc_pmc,bool en_bc_pmc)7623b75c3dfSPeng Li static int hclgevf_cmd_set_promisc_mode(struct hclgevf_dev *hdev,
763e196ec75SJian Shen bool en_uc_pmc, bool en_mc_pmc,
764f01f5559SJian Shen bool en_bc_pmc)
765e2cb1decSSalil Mehta {
7665e7414cdSJian Shen struct hnae3_handle *handle = &hdev->nic;
767d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
768f01f5559SJian Shen int ret;
769e2cb1decSSalil Mehta
770d3410018SYufeng Mo memset(&send_msg, 0, sizeof(send_msg));
771d3410018SYufeng Mo send_msg.code = HCLGE_MBX_SET_PROMISC_MODE;
772d3410018SYufeng Mo send_msg.en_bc = en_bc_pmc ? 1 : 0;
773d3410018SYufeng Mo send_msg.en_uc = en_uc_pmc ? 1 : 0;
774d3410018SYufeng Mo send_msg.en_mc = en_mc_pmc ? 1 : 0;
7755e7414cdSJian Shen send_msg.en_limit_promisc = test_bit(HNAE3_PFLAG_LIMIT_PROMISC,
7765e7414cdSJian Shen &handle->priv_flags) ? 1 : 0;
777e2cb1decSSalil Mehta
778d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
779f01f5559SJian Shen if (ret)
780e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
781f01f5559SJian Shen "Set promisc mode fail, status is %d.\n", ret);
782e2cb1decSSalil Mehta
783f01f5559SJian Shen return ret;
784e2cb1decSSalil Mehta }
785e2cb1decSSalil Mehta
hclgevf_set_promisc_mode(struct hnae3_handle * handle,bool en_uc_pmc,bool en_mc_pmc)786e196ec75SJian Shen static int hclgevf_set_promisc_mode(struct hnae3_handle *handle, bool en_uc_pmc,
787e196ec75SJian Shen bool en_mc_pmc)
788e2cb1decSSalil Mehta {
789e196ec75SJian Shen struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
790e196ec75SJian Shen bool en_bc_pmc;
791e196ec75SJian Shen
792295ba232SGuangbin Huang en_bc_pmc = hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2;
793e196ec75SJian Shen
794e196ec75SJian Shen return hclgevf_cmd_set_promisc_mode(hdev, en_uc_pmc, en_mc_pmc,
795e196ec75SJian Shen en_bc_pmc);
796e2cb1decSSalil Mehta }
797e2cb1decSSalil Mehta
hclgevf_request_update_promisc_mode(struct hnae3_handle * handle)798c631c696SJian Shen static void hclgevf_request_update_promisc_mode(struct hnae3_handle *handle)
799c631c696SJian Shen {
800c631c696SJian Shen struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
801c631c696SJian Shen
802c631c696SJian Shen set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
8035e7414cdSJian Shen hclgevf_task_schedule(hdev, 0);
804c631c696SJian Shen }
805c631c696SJian Shen
hclgevf_sync_promisc_mode(struct hclgevf_dev * hdev)806c631c696SJian Shen static void hclgevf_sync_promisc_mode(struct hclgevf_dev *hdev)
807c631c696SJian Shen {
808c631c696SJian Shen struct hnae3_handle *handle = &hdev->nic;
809c631c696SJian Shen bool en_uc_pmc = handle->netdev_flags & HNAE3_UPE;
810c631c696SJian Shen bool en_mc_pmc = handle->netdev_flags & HNAE3_MPE;
811c631c696SJian Shen int ret;
812c631c696SJian Shen
813c631c696SJian Shen if (test_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state)) {
814c631c696SJian Shen ret = hclgevf_set_promisc_mode(handle, en_uc_pmc, en_mc_pmc);
815c631c696SJian Shen if (!ret)
816c631c696SJian Shen clear_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
817c631c696SJian Shen }
818c631c696SJian Shen }
819c631c696SJian Shen
hclgevf_tqp_enable_cmd_send(struct hclgevf_dev * hdev,u16 tqp_id,u16 stream_id,bool enable)8208fa86551SYufeng Mo static int hclgevf_tqp_enable_cmd_send(struct hclgevf_dev *hdev, u16 tqp_id,
8218fa86551SYufeng Mo u16 stream_id, bool enable)
822e2cb1decSSalil Mehta {
823e2cb1decSSalil Mehta struct hclgevf_cfg_com_tqp_queue_cmd *req;
8246befad60SJie Wang struct hclge_desc desc;
825e2cb1decSSalil Mehta
826e2cb1decSSalil Mehta req = (struct hclgevf_cfg_com_tqp_queue_cmd *)desc.data;
827e2cb1decSSalil Mehta
82843710bfeSJie Wang hclgevf_cmd_setup_basic_desc(&desc, HCLGE_OPC_CFG_COM_TQP_QUEUE, false);
829e2cb1decSSalil Mehta req->tqp_id = cpu_to_le16(tqp_id & HCLGEVF_RING_ID_MASK);
830e2cb1decSSalil Mehta req->stream_id = cpu_to_le16(stream_id);
831ebaf1908SWeihang Li if (enable)
832ebaf1908SWeihang Li req->enable |= 1U << HCLGEVF_TQP_ENABLE_B;
833e2cb1decSSalil Mehta
8348fa86551SYufeng Mo return hclgevf_cmd_send(&hdev->hw, &desc, 1);
8358fa86551SYufeng Mo }
836e2cb1decSSalil Mehta
hclgevf_tqp_enable(struct hnae3_handle * handle,bool enable)8378fa86551SYufeng Mo static int hclgevf_tqp_enable(struct hnae3_handle *handle, bool enable)
8388fa86551SYufeng Mo {
8398fa86551SYufeng Mo struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
8408fa86551SYufeng Mo int ret;
8418fa86551SYufeng Mo u16 i;
8428fa86551SYufeng Mo
8438fa86551SYufeng Mo for (i = 0; i < handle->kinfo.num_tqps; i++) {
8448fa86551SYufeng Mo ret = hclgevf_tqp_enable_cmd_send(hdev, i, 0, enable);
8458fa86551SYufeng Mo if (ret)
8468fa86551SYufeng Mo return ret;
8478fa86551SYufeng Mo }
8488fa86551SYufeng Mo
8498fa86551SYufeng Mo return 0;
850e2cb1decSSalil Mehta }
851e2cb1decSSalil Mehta
hclgevf_get_host_mac_addr(struct hclgevf_dev * hdev,u8 * p)8528e6de441SHuazhong Tan static int hclgevf_get_host_mac_addr(struct hclgevf_dev *hdev, u8 *p)
8538e6de441SHuazhong Tan {
854d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
8558e6de441SHuazhong Tan u8 host_mac[ETH_ALEN];
8568e6de441SHuazhong Tan int status;
8578e6de441SHuazhong Tan
858d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_GET_MAC_ADDR, 0);
859d3410018SYufeng Mo status = hclgevf_send_mbx_msg(hdev, &send_msg, true, host_mac,
860d3410018SYufeng Mo ETH_ALEN);
8618e6de441SHuazhong Tan if (status) {
8628e6de441SHuazhong Tan dev_err(&hdev->pdev->dev,
8638e6de441SHuazhong Tan "fail to get VF MAC from host %d", status);
8648e6de441SHuazhong Tan return status;
8658e6de441SHuazhong Tan }
8668e6de441SHuazhong Tan
8678e6de441SHuazhong Tan ether_addr_copy(p, host_mac);
8688e6de441SHuazhong Tan
8698e6de441SHuazhong Tan return 0;
8708e6de441SHuazhong Tan }
8718e6de441SHuazhong Tan
hclgevf_get_mac_addr(struct hnae3_handle * handle,u8 * p)872e2cb1decSSalil Mehta static void hclgevf_get_mac_addr(struct hnae3_handle *handle, u8 *p)
873e2cb1decSSalil Mehta {
874e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
8758e6de441SHuazhong Tan u8 host_mac_addr[ETH_ALEN];
876e2cb1decSSalil Mehta
8778e6de441SHuazhong Tan if (hclgevf_get_host_mac_addr(hdev, host_mac_addr))
8788e6de441SHuazhong Tan return;
8798e6de441SHuazhong Tan
8808e6de441SHuazhong Tan hdev->has_pf_mac = !is_zero_ether_addr(host_mac_addr);
8818e6de441SHuazhong Tan if (hdev->has_pf_mac)
8828e6de441SHuazhong Tan ether_addr_copy(p, host_mac_addr);
8838e6de441SHuazhong Tan else
884e2cb1decSSalil Mehta ether_addr_copy(p, hdev->hw.mac.mac_addr);
885e2cb1decSSalil Mehta }
886e2cb1decSSalil Mehta
hclgevf_set_mac_addr(struct hnae3_handle * handle,const void * p,bool is_first)88776660757SJakub Kicinski static int hclgevf_set_mac_addr(struct hnae3_handle *handle, const void *p,
88859098055SFuyun Liang bool is_first)
889e2cb1decSSalil Mehta {
890e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
891e2cb1decSSalil Mehta u8 *old_mac_addr = (u8 *)hdev->hw.mac.mac_addr;
892d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
893e2cb1decSSalil Mehta u8 *new_mac_addr = (u8 *)p;
894e2cb1decSSalil Mehta int status;
895e2cb1decSSalil Mehta
896d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_UNICAST, 0);
897ee4bcd3bSJian Shen send_msg.subcode = HCLGE_MBX_MAC_VLAN_UC_MODIFY;
898d3410018SYufeng Mo ether_addr_copy(send_msg.data, new_mac_addr);
899ee4bcd3bSJian Shen if (is_first && !hdev->has_pf_mac)
900ee4bcd3bSJian Shen eth_zero_addr(&send_msg.data[ETH_ALEN]);
901ee4bcd3bSJian Shen else
902d3410018SYufeng Mo ether_addr_copy(&send_msg.data[ETH_ALEN], old_mac_addr);
903d3410018SYufeng Mo status = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
904e2cb1decSSalil Mehta if (!status)
905e2cb1decSSalil Mehta ether_addr_copy(hdev->hw.mac.mac_addr, new_mac_addr);
906e2cb1decSSalil Mehta
907e2cb1decSSalil Mehta return status;
908e2cb1decSSalil Mehta }
909e2cb1decSSalil Mehta
910ee4bcd3bSJian Shen static struct hclgevf_mac_addr_node *
hclgevf_find_mac_node(struct list_head * list,const u8 * mac_addr)911ee4bcd3bSJian Shen hclgevf_find_mac_node(struct list_head *list, const u8 *mac_addr)
912ee4bcd3bSJian Shen {
913ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node, *tmp;
914ee4bcd3bSJian Shen
915ee4bcd3bSJian Shen list_for_each_entry_safe(mac_node, tmp, list, node)
916ee4bcd3bSJian Shen if (ether_addr_equal(mac_addr, mac_node->mac_addr))
917ee4bcd3bSJian Shen return mac_node;
918ee4bcd3bSJian Shen
919ee4bcd3bSJian Shen return NULL;
920ee4bcd3bSJian Shen }
921ee4bcd3bSJian Shen
hclgevf_update_mac_node(struct hclgevf_mac_addr_node * mac_node,enum HCLGEVF_MAC_NODE_STATE state)922ee4bcd3bSJian Shen static void hclgevf_update_mac_node(struct hclgevf_mac_addr_node *mac_node,
923ee4bcd3bSJian Shen enum HCLGEVF_MAC_NODE_STATE state)
924ee4bcd3bSJian Shen {
925ee4bcd3bSJian Shen switch (state) {
926ee4bcd3bSJian Shen /* from set_rx_mode or tmp_add_list */
927ee4bcd3bSJian Shen case HCLGEVF_MAC_TO_ADD:
928ee4bcd3bSJian Shen if (mac_node->state == HCLGEVF_MAC_TO_DEL)
929ee4bcd3bSJian Shen mac_node->state = HCLGEVF_MAC_ACTIVE;
930ee4bcd3bSJian Shen break;
931ee4bcd3bSJian Shen /* only from set_rx_mode */
932ee4bcd3bSJian Shen case HCLGEVF_MAC_TO_DEL:
933ee4bcd3bSJian Shen if (mac_node->state == HCLGEVF_MAC_TO_ADD) {
934ee4bcd3bSJian Shen list_del(&mac_node->node);
935ee4bcd3bSJian Shen kfree(mac_node);
936ee4bcd3bSJian Shen } else {
937ee4bcd3bSJian Shen mac_node->state = HCLGEVF_MAC_TO_DEL;
938ee4bcd3bSJian Shen }
939ee4bcd3bSJian Shen break;
940ee4bcd3bSJian Shen /* only from tmp_add_list, the mac_node->state won't be
941ee4bcd3bSJian Shen * HCLGEVF_MAC_ACTIVE
942ee4bcd3bSJian Shen */
943ee4bcd3bSJian Shen case HCLGEVF_MAC_ACTIVE:
944ee4bcd3bSJian Shen if (mac_node->state == HCLGEVF_MAC_TO_ADD)
945ee4bcd3bSJian Shen mac_node->state = HCLGEVF_MAC_ACTIVE;
946ee4bcd3bSJian Shen break;
947ee4bcd3bSJian Shen }
948ee4bcd3bSJian Shen }
949ee4bcd3bSJian Shen
hclgevf_update_mac_list(struct hnae3_handle * handle,enum HCLGEVF_MAC_NODE_STATE state,enum HCLGEVF_MAC_ADDR_TYPE mac_type,const unsigned char * addr)950ee4bcd3bSJian Shen static int hclgevf_update_mac_list(struct hnae3_handle *handle,
951ee4bcd3bSJian Shen enum HCLGEVF_MAC_NODE_STATE state,
952ee4bcd3bSJian Shen enum HCLGEVF_MAC_ADDR_TYPE mac_type,
953e2cb1decSSalil Mehta const unsigned char *addr)
954e2cb1decSSalil Mehta {
955e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
956ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node;
957ee4bcd3bSJian Shen struct list_head *list;
958e2cb1decSSalil Mehta
959ee4bcd3bSJian Shen list = (mac_type == HCLGEVF_MAC_ADDR_UC) ?
960ee4bcd3bSJian Shen &hdev->mac_table.uc_mac_list : &hdev->mac_table.mc_mac_list;
961ee4bcd3bSJian Shen
962ee4bcd3bSJian Shen spin_lock_bh(&hdev->mac_table.mac_list_lock);
963ee4bcd3bSJian Shen
964ee4bcd3bSJian Shen /* if the mac addr is already in the mac list, no need to add a new
965ee4bcd3bSJian Shen * one into it, just check the mac addr state, convert it to a new
96634eff17eSJilin Yuan * state, or just remove it, or do nothing.
967ee4bcd3bSJian Shen */
968ee4bcd3bSJian Shen mac_node = hclgevf_find_mac_node(list, addr);
969ee4bcd3bSJian Shen if (mac_node) {
970ee4bcd3bSJian Shen hclgevf_update_mac_node(mac_node, state);
971ee4bcd3bSJian Shen spin_unlock_bh(&hdev->mac_table.mac_list_lock);
972ee4bcd3bSJian Shen return 0;
973ee4bcd3bSJian Shen }
974ee4bcd3bSJian Shen /* if this address is never added, unnecessary to delete */
975ee4bcd3bSJian Shen if (state == HCLGEVF_MAC_TO_DEL) {
976ee4bcd3bSJian Shen spin_unlock_bh(&hdev->mac_table.mac_list_lock);
977ee4bcd3bSJian Shen return -ENOENT;
978ee4bcd3bSJian Shen }
979ee4bcd3bSJian Shen
980ee4bcd3bSJian Shen mac_node = kzalloc(sizeof(*mac_node), GFP_ATOMIC);
981ee4bcd3bSJian Shen if (!mac_node) {
982ee4bcd3bSJian Shen spin_unlock_bh(&hdev->mac_table.mac_list_lock);
983ee4bcd3bSJian Shen return -ENOMEM;
984ee4bcd3bSJian Shen }
985ee4bcd3bSJian Shen
986ee4bcd3bSJian Shen mac_node->state = state;
987ee4bcd3bSJian Shen ether_addr_copy(mac_node->mac_addr, addr);
988ee4bcd3bSJian Shen list_add_tail(&mac_node->node, list);
989ee4bcd3bSJian Shen
990ee4bcd3bSJian Shen spin_unlock_bh(&hdev->mac_table.mac_list_lock);
991ee4bcd3bSJian Shen return 0;
992ee4bcd3bSJian Shen }
993ee4bcd3bSJian Shen
hclgevf_add_uc_addr(struct hnae3_handle * handle,const unsigned char * addr)994ee4bcd3bSJian Shen static int hclgevf_add_uc_addr(struct hnae3_handle *handle,
995ee4bcd3bSJian Shen const unsigned char *addr)
996ee4bcd3bSJian Shen {
997ee4bcd3bSJian Shen return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_ADD,
998ee4bcd3bSJian Shen HCLGEVF_MAC_ADDR_UC, addr);
999e2cb1decSSalil Mehta }
1000e2cb1decSSalil Mehta
hclgevf_rm_uc_addr(struct hnae3_handle * handle,const unsigned char * addr)1001e2cb1decSSalil Mehta static int hclgevf_rm_uc_addr(struct hnae3_handle *handle,
1002e2cb1decSSalil Mehta const unsigned char *addr)
1003e2cb1decSSalil Mehta {
1004ee4bcd3bSJian Shen return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_DEL,
1005ee4bcd3bSJian Shen HCLGEVF_MAC_ADDR_UC, addr);
1006e2cb1decSSalil Mehta }
1007e2cb1decSSalil Mehta
hclgevf_add_mc_addr(struct hnae3_handle * handle,const unsigned char * addr)1008e2cb1decSSalil Mehta static int hclgevf_add_mc_addr(struct hnae3_handle *handle,
1009e2cb1decSSalil Mehta const unsigned char *addr)
1010e2cb1decSSalil Mehta {
1011ee4bcd3bSJian Shen return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_ADD,
1012ee4bcd3bSJian Shen HCLGEVF_MAC_ADDR_MC, addr);
1013e2cb1decSSalil Mehta }
1014e2cb1decSSalil Mehta
hclgevf_rm_mc_addr(struct hnae3_handle * handle,const unsigned char * addr)1015e2cb1decSSalil Mehta static int hclgevf_rm_mc_addr(struct hnae3_handle *handle,
1016e2cb1decSSalil Mehta const unsigned char *addr)
1017e2cb1decSSalil Mehta {
1018ee4bcd3bSJian Shen return hclgevf_update_mac_list(handle, HCLGEVF_MAC_TO_DEL,
1019ee4bcd3bSJian Shen HCLGEVF_MAC_ADDR_MC, addr);
1020ee4bcd3bSJian Shen }
1021e2cb1decSSalil Mehta
hclgevf_add_del_mac_addr(struct hclgevf_dev * hdev,struct hclgevf_mac_addr_node * mac_node,enum HCLGEVF_MAC_ADDR_TYPE mac_type)1022ee4bcd3bSJian Shen static int hclgevf_add_del_mac_addr(struct hclgevf_dev *hdev,
1023ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node,
1024ee4bcd3bSJian Shen enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1025ee4bcd3bSJian Shen {
1026ee4bcd3bSJian Shen struct hclge_vf_to_pf_msg send_msg;
1027ee4bcd3bSJian Shen u8 code, subcode;
1028ee4bcd3bSJian Shen
1029ee4bcd3bSJian Shen if (mac_type == HCLGEVF_MAC_ADDR_UC) {
1030ee4bcd3bSJian Shen code = HCLGE_MBX_SET_UNICAST;
1031ee4bcd3bSJian Shen if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1032ee4bcd3bSJian Shen subcode = HCLGE_MBX_MAC_VLAN_UC_ADD;
1033ee4bcd3bSJian Shen else
1034ee4bcd3bSJian Shen subcode = HCLGE_MBX_MAC_VLAN_UC_REMOVE;
1035ee4bcd3bSJian Shen } else {
1036ee4bcd3bSJian Shen code = HCLGE_MBX_SET_MULTICAST;
1037ee4bcd3bSJian Shen if (mac_node->state == HCLGEVF_MAC_TO_ADD)
1038ee4bcd3bSJian Shen subcode = HCLGE_MBX_MAC_VLAN_MC_ADD;
1039ee4bcd3bSJian Shen else
1040ee4bcd3bSJian Shen subcode = HCLGE_MBX_MAC_VLAN_MC_REMOVE;
1041ee4bcd3bSJian Shen }
1042ee4bcd3bSJian Shen
1043ee4bcd3bSJian Shen hclgevf_build_send_msg(&send_msg, code, subcode);
1044ee4bcd3bSJian Shen ether_addr_copy(send_msg.data, mac_node->mac_addr);
1045d3410018SYufeng Mo return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1046e2cb1decSSalil Mehta }
1047e2cb1decSSalil Mehta
hclgevf_config_mac_list(struct hclgevf_dev * hdev,struct list_head * list,enum HCLGEVF_MAC_ADDR_TYPE mac_type)1048ee4bcd3bSJian Shen static void hclgevf_config_mac_list(struct hclgevf_dev *hdev,
1049ee4bcd3bSJian Shen struct list_head *list,
1050ee4bcd3bSJian Shen enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1051ee4bcd3bSJian Shen {
10524f331fdaSYufeng Mo char format_mac_addr[HNAE3_FORMAT_MAC_ADDR_LEN];
1053ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node, *tmp;
1054ee4bcd3bSJian Shen int ret;
1055ee4bcd3bSJian Shen
1056ee4bcd3bSJian Shen list_for_each_entry_safe(mac_node, tmp, list, node) {
1057ee4bcd3bSJian Shen ret = hclgevf_add_del_mac_addr(hdev, mac_node, mac_type);
1058ee4bcd3bSJian Shen if (ret) {
10594f331fdaSYufeng Mo hnae3_format_mac_addr(format_mac_addr,
10604f331fdaSYufeng Mo mac_node->mac_addr);
1061ee4bcd3bSJian Shen dev_err(&hdev->pdev->dev,
10624f331fdaSYufeng Mo "failed to configure mac %s, state = %d, ret = %d\n",
10634f331fdaSYufeng Mo format_mac_addr, mac_node->state, ret);
1064ee4bcd3bSJian Shen return;
1065ee4bcd3bSJian Shen }
1066ee4bcd3bSJian Shen if (mac_node->state == HCLGEVF_MAC_TO_ADD) {
1067ee4bcd3bSJian Shen mac_node->state = HCLGEVF_MAC_ACTIVE;
1068ee4bcd3bSJian Shen } else {
1069ee4bcd3bSJian Shen list_del(&mac_node->node);
1070ee4bcd3bSJian Shen kfree(mac_node);
1071ee4bcd3bSJian Shen }
1072ee4bcd3bSJian Shen }
1073ee4bcd3bSJian Shen }
1074ee4bcd3bSJian Shen
hclgevf_sync_from_add_list(struct list_head * add_list,struct list_head * mac_list)1075ee4bcd3bSJian Shen static void hclgevf_sync_from_add_list(struct list_head *add_list,
1076ee4bcd3bSJian Shen struct list_head *mac_list)
1077ee4bcd3bSJian Shen {
1078ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1079ee4bcd3bSJian Shen
1080ee4bcd3bSJian Shen list_for_each_entry_safe(mac_node, tmp, add_list, node) {
1081ee4bcd3bSJian Shen /* if the mac address from tmp_add_list is not in the
1082ee4bcd3bSJian Shen * uc/mc_mac_list, it means have received a TO_DEL request
1083ee4bcd3bSJian Shen * during the time window of sending mac config request to PF
1084ee4bcd3bSJian Shen * If mac_node state is ACTIVE, then change its state to TO_DEL,
1085ee4bcd3bSJian Shen * then it will be removed at next time. If is TO_ADD, it means
1086ee4bcd3bSJian Shen * send TO_ADD request failed, so just remove the mac node.
1087ee4bcd3bSJian Shen */
1088ee4bcd3bSJian Shen new_node = hclgevf_find_mac_node(mac_list, mac_node->mac_addr);
1089ee4bcd3bSJian Shen if (new_node) {
1090ee4bcd3bSJian Shen hclgevf_update_mac_node(new_node, mac_node->state);
1091ee4bcd3bSJian Shen list_del(&mac_node->node);
1092ee4bcd3bSJian Shen kfree(mac_node);
1093ee4bcd3bSJian Shen } else if (mac_node->state == HCLGEVF_MAC_ACTIVE) {
1094ee4bcd3bSJian Shen mac_node->state = HCLGEVF_MAC_TO_DEL;
109549768ce9SBaokun Li list_move_tail(&mac_node->node, mac_list);
1096ee4bcd3bSJian Shen } else {
1097ee4bcd3bSJian Shen list_del(&mac_node->node);
1098ee4bcd3bSJian Shen kfree(mac_node);
1099ee4bcd3bSJian Shen }
1100ee4bcd3bSJian Shen }
1101ee4bcd3bSJian Shen }
1102ee4bcd3bSJian Shen
hclgevf_sync_from_del_list(struct list_head * del_list,struct list_head * mac_list)1103ee4bcd3bSJian Shen static void hclgevf_sync_from_del_list(struct list_head *del_list,
1104ee4bcd3bSJian Shen struct list_head *mac_list)
1105ee4bcd3bSJian Shen {
1106ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1107ee4bcd3bSJian Shen
1108ee4bcd3bSJian Shen list_for_each_entry_safe(mac_node, tmp, del_list, node) {
1109ee4bcd3bSJian Shen new_node = hclgevf_find_mac_node(mac_list, mac_node->mac_addr);
1110ee4bcd3bSJian Shen if (new_node) {
1111ee4bcd3bSJian Shen /* If the mac addr is exist in the mac list, it means
1112ee4bcd3bSJian Shen * received a new request TO_ADD during the time window
1113ee4bcd3bSJian Shen * of sending mac addr configurrequest to PF, so just
1114ee4bcd3bSJian Shen * change the mac state to ACTIVE.
1115ee4bcd3bSJian Shen */
1116ee4bcd3bSJian Shen new_node->state = HCLGEVF_MAC_ACTIVE;
1117ee4bcd3bSJian Shen list_del(&mac_node->node);
1118ee4bcd3bSJian Shen kfree(mac_node);
1119ee4bcd3bSJian Shen } else {
112049768ce9SBaokun Li list_move_tail(&mac_node->node, mac_list);
1121ee4bcd3bSJian Shen }
1122ee4bcd3bSJian Shen }
1123ee4bcd3bSJian Shen }
1124ee4bcd3bSJian Shen
hclgevf_clear_list(struct list_head * list)1125ee4bcd3bSJian Shen static void hclgevf_clear_list(struct list_head *list)
1126ee4bcd3bSJian Shen {
1127ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node, *tmp;
1128ee4bcd3bSJian Shen
1129ee4bcd3bSJian Shen list_for_each_entry_safe(mac_node, tmp, list, node) {
1130ee4bcd3bSJian Shen list_del(&mac_node->node);
1131ee4bcd3bSJian Shen kfree(mac_node);
1132ee4bcd3bSJian Shen }
1133ee4bcd3bSJian Shen }
1134ee4bcd3bSJian Shen
hclgevf_sync_mac_list(struct hclgevf_dev * hdev,enum HCLGEVF_MAC_ADDR_TYPE mac_type)1135ee4bcd3bSJian Shen static void hclgevf_sync_mac_list(struct hclgevf_dev *hdev,
1136ee4bcd3bSJian Shen enum HCLGEVF_MAC_ADDR_TYPE mac_type)
1137ee4bcd3bSJian Shen {
1138ee4bcd3bSJian Shen struct hclgevf_mac_addr_node *mac_node, *tmp, *new_node;
1139ee4bcd3bSJian Shen struct list_head tmp_add_list, tmp_del_list;
1140ee4bcd3bSJian Shen struct list_head *list;
1141ee4bcd3bSJian Shen
1142ee4bcd3bSJian Shen INIT_LIST_HEAD(&tmp_add_list);
1143ee4bcd3bSJian Shen INIT_LIST_HEAD(&tmp_del_list);
1144ee4bcd3bSJian Shen
1145ee4bcd3bSJian Shen /* move the mac addr to the tmp_add_list and tmp_del_list, then
1146ee4bcd3bSJian Shen * we can add/delete these mac addr outside the spin lock
1147ee4bcd3bSJian Shen */
1148ee4bcd3bSJian Shen list = (mac_type == HCLGEVF_MAC_ADDR_UC) ?
1149ee4bcd3bSJian Shen &hdev->mac_table.uc_mac_list : &hdev->mac_table.mc_mac_list;
1150ee4bcd3bSJian Shen
1151ee4bcd3bSJian Shen spin_lock_bh(&hdev->mac_table.mac_list_lock);
1152ee4bcd3bSJian Shen
1153ee4bcd3bSJian Shen list_for_each_entry_safe(mac_node, tmp, list, node) {
1154ee4bcd3bSJian Shen switch (mac_node->state) {
1155ee4bcd3bSJian Shen case HCLGEVF_MAC_TO_DEL:
115649768ce9SBaokun Li list_move_tail(&mac_node->node, &tmp_del_list);
1157ee4bcd3bSJian Shen break;
1158ee4bcd3bSJian Shen case HCLGEVF_MAC_TO_ADD:
1159ee4bcd3bSJian Shen new_node = kzalloc(sizeof(*new_node), GFP_ATOMIC);
1160ee4bcd3bSJian Shen if (!new_node)
1161ee4bcd3bSJian Shen goto stop_traverse;
1162ee4bcd3bSJian Shen
1163ee4bcd3bSJian Shen ether_addr_copy(new_node->mac_addr, mac_node->mac_addr);
1164ee4bcd3bSJian Shen new_node->state = mac_node->state;
1165ee4bcd3bSJian Shen list_add_tail(&new_node->node, &tmp_add_list);
1166ee4bcd3bSJian Shen break;
1167ee4bcd3bSJian Shen default:
1168ee4bcd3bSJian Shen break;
1169ee4bcd3bSJian Shen }
1170ee4bcd3bSJian Shen }
1171ee4bcd3bSJian Shen
1172ee4bcd3bSJian Shen stop_traverse:
1173ee4bcd3bSJian Shen spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1174ee4bcd3bSJian Shen
1175ee4bcd3bSJian Shen /* delete first, in order to get max mac table space for adding */
1176ee4bcd3bSJian Shen hclgevf_config_mac_list(hdev, &tmp_del_list, mac_type);
1177ee4bcd3bSJian Shen hclgevf_config_mac_list(hdev, &tmp_add_list, mac_type);
1178ee4bcd3bSJian Shen
1179ee4bcd3bSJian Shen /* if some mac addresses were added/deleted fail, move back to the
1180ee4bcd3bSJian Shen * mac_list, and retry at next time.
1181ee4bcd3bSJian Shen */
1182ee4bcd3bSJian Shen spin_lock_bh(&hdev->mac_table.mac_list_lock);
1183ee4bcd3bSJian Shen
1184ee4bcd3bSJian Shen hclgevf_sync_from_del_list(&tmp_del_list, list);
1185ee4bcd3bSJian Shen hclgevf_sync_from_add_list(&tmp_add_list, list);
1186ee4bcd3bSJian Shen
1187ee4bcd3bSJian Shen spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1188ee4bcd3bSJian Shen }
1189ee4bcd3bSJian Shen
hclgevf_sync_mac_table(struct hclgevf_dev * hdev)1190ee4bcd3bSJian Shen static void hclgevf_sync_mac_table(struct hclgevf_dev *hdev)
1191ee4bcd3bSJian Shen {
1192ee4bcd3bSJian Shen hclgevf_sync_mac_list(hdev, HCLGEVF_MAC_ADDR_UC);
1193ee4bcd3bSJian Shen hclgevf_sync_mac_list(hdev, HCLGEVF_MAC_ADDR_MC);
1194ee4bcd3bSJian Shen }
1195ee4bcd3bSJian Shen
hclgevf_uninit_mac_list(struct hclgevf_dev * hdev)1196ee4bcd3bSJian Shen static void hclgevf_uninit_mac_list(struct hclgevf_dev *hdev)
1197ee4bcd3bSJian Shen {
1198ee4bcd3bSJian Shen spin_lock_bh(&hdev->mac_table.mac_list_lock);
1199ee4bcd3bSJian Shen
1200ee4bcd3bSJian Shen hclgevf_clear_list(&hdev->mac_table.uc_mac_list);
1201ee4bcd3bSJian Shen hclgevf_clear_list(&hdev->mac_table.mc_mac_list);
1202ee4bcd3bSJian Shen
1203ee4bcd3bSJian Shen spin_unlock_bh(&hdev->mac_table.mac_list_lock);
1204ee4bcd3bSJian Shen }
1205ee4bcd3bSJian Shen
hclgevf_enable_vlan_filter(struct hnae3_handle * handle,bool enable)1206fa6a262aSJian Shen static int hclgevf_enable_vlan_filter(struct hnae3_handle *handle, bool enable)
1207fa6a262aSJian Shen {
1208fa6a262aSJian Shen struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1209fa6a262aSJian Shen struct hnae3_ae_dev *ae_dev = hdev->ae_dev;
1210fa6a262aSJian Shen struct hclge_vf_to_pf_msg send_msg;
1211fa6a262aSJian Shen
1212fa6a262aSJian Shen if (!test_bit(HNAE3_DEV_SUPPORT_VLAN_FLTR_MDF_B, ae_dev->caps))
1213fa6a262aSJian Shen return -EOPNOTSUPP;
1214fa6a262aSJian Shen
1215fa6a262aSJian Shen hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
1216fa6a262aSJian Shen HCLGE_MBX_ENABLE_VLAN_FILTER);
1217fa6a262aSJian Shen send_msg.data[0] = enable ? 1 : 0;
1218fa6a262aSJian Shen
1219fa6a262aSJian Shen return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1220fa6a262aSJian Shen }
1221fa6a262aSJian Shen
hclgevf_set_vlan_filter(struct hnae3_handle * handle,__be16 proto,u16 vlan_id,bool is_kill)1222e2cb1decSSalil Mehta static int hclgevf_set_vlan_filter(struct hnae3_handle *handle,
1223e2cb1decSSalil Mehta __be16 proto, u16 vlan_id,
1224e2cb1decSSalil Mehta bool is_kill)
1225e2cb1decSSalil Mehta {
1226e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1227416eedb6SJie Wang struct hclge_mbx_vlan_filter *vlan_filter;
1228d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
1229fe4144d4SJian Shen int ret;
1230e2cb1decSSalil Mehta
1231b37ce587SYufeng Mo if (vlan_id > HCLGEVF_MAX_VLAN_ID)
1232e2cb1decSSalil Mehta return -EINVAL;
1233e2cb1decSSalil Mehta
1234e2cb1decSSalil Mehta if (proto != htons(ETH_P_8021Q))
1235e2cb1decSSalil Mehta return -EPROTONOSUPPORT;
1236e2cb1decSSalil Mehta
1237b7b5d25bSGuojia Liao /* When device is resetting or reset failed, firmware is unable to
1238b7b5d25bSGuojia Liao * handle mailbox. Just record the vlan id, and remove it after
1239fe4144d4SJian Shen * reset finished.
1240fe4144d4SJian Shen */
1241b7b5d25bSGuojia Liao if ((test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
1242b7b5d25bSGuojia Liao test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) && is_kill) {
1243fe4144d4SJian Shen set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1244fe4144d4SJian Shen return -EBUSY;
1245472a2ff6SJian Shen } else if (!is_kill && test_bit(vlan_id, hdev->vlan_del_fail_bmap)) {
1246472a2ff6SJian Shen clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
1247fe4144d4SJian Shen }
1248fe4144d4SJian Shen
1249d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
1250d3410018SYufeng Mo HCLGE_MBX_VLAN_FILTER);
1251416eedb6SJie Wang vlan_filter = (struct hclge_mbx_vlan_filter *)send_msg.data;
1252416eedb6SJie Wang vlan_filter->is_kill = is_kill;
1253416eedb6SJie Wang vlan_filter->vlan_id = cpu_to_le16(vlan_id);
1254416eedb6SJie Wang vlan_filter->proto = cpu_to_le16(be16_to_cpu(proto));
1255416eedb6SJie Wang
125646ee7350SGuojia Liao /* when remove hw vlan filter failed, record the vlan id,
1257fe4144d4SJian Shen * and try to remove it from hw later, to be consistence
1258fe4144d4SJian Shen * with stack.
1259fe4144d4SJian Shen */
1260d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1261fe4144d4SJian Shen if (is_kill && ret)
1262fe4144d4SJian Shen set_bit(vlan_id, hdev->vlan_del_fail_bmap);
1263fe4144d4SJian Shen
1264fe4144d4SJian Shen return ret;
1265fe4144d4SJian Shen }
1266fe4144d4SJian Shen
hclgevf_sync_vlan_filter(struct hclgevf_dev * hdev)1267fe4144d4SJian Shen static void hclgevf_sync_vlan_filter(struct hclgevf_dev *hdev)
1268fe4144d4SJian Shen {
1269fe4144d4SJian Shen #define HCLGEVF_MAX_SYNC_COUNT 60
1270fe4144d4SJian Shen struct hnae3_handle *handle = &hdev->nic;
1271fe4144d4SJian Shen int ret, sync_cnt = 0;
1272fe4144d4SJian Shen u16 vlan_id;
1273fe4144d4SJian Shen
1274472a2ff6SJian Shen if (bitmap_empty(hdev->vlan_del_fail_bmap, VLAN_N_VID))
1275472a2ff6SJian Shen return;
1276472a2ff6SJian Shen
1277472a2ff6SJian Shen rtnl_lock();
1278fe4144d4SJian Shen vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1279fe4144d4SJian Shen while (vlan_id != VLAN_N_VID) {
1280fe4144d4SJian Shen ret = hclgevf_set_vlan_filter(handle, htons(ETH_P_8021Q),
1281fe4144d4SJian Shen vlan_id, true);
1282fe4144d4SJian Shen if (ret)
1283472a2ff6SJian Shen break;
1284fe4144d4SJian Shen
1285fe4144d4SJian Shen clear_bit(vlan_id, hdev->vlan_del_fail_bmap);
1286fe4144d4SJian Shen sync_cnt++;
1287fe4144d4SJian Shen if (sync_cnt >= HCLGEVF_MAX_SYNC_COUNT)
1288472a2ff6SJian Shen break;
1289fe4144d4SJian Shen
1290fe4144d4SJian Shen vlan_id = find_first_bit(hdev->vlan_del_fail_bmap, VLAN_N_VID);
1291fe4144d4SJian Shen }
1292472a2ff6SJian Shen rtnl_unlock();
1293e2cb1decSSalil Mehta }
1294e2cb1decSSalil Mehta
hclgevf_en_hw_strip_rxvtag_cmd(struct hclgevf_dev * hdev,bool enable)1295ef2383d0SJian Shen static int hclgevf_en_hw_strip_rxvtag_cmd(struct hclgevf_dev *hdev, bool enable)
1296b2641e2aSYunsheng Lin {
1297d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
1298b2641e2aSYunsheng Lin
1299d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
1300d3410018SYufeng Mo HCLGE_MBX_VLAN_RX_OFF_CFG);
1301d3410018SYufeng Mo send_msg.data[0] = enable ? 1 : 0;
1302d3410018SYufeng Mo return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1303b2641e2aSYunsheng Lin }
1304b2641e2aSYunsheng Lin
hclgevf_en_hw_strip_rxvtag(struct hnae3_handle * handle,bool enable)1305ef2383d0SJian Shen static int hclgevf_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
1306ef2383d0SJian Shen {
1307ef2383d0SJian Shen struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1308ef2383d0SJian Shen int ret;
1309ef2383d0SJian Shen
1310ef2383d0SJian Shen ret = hclgevf_en_hw_strip_rxvtag_cmd(hdev, enable);
1311ef2383d0SJian Shen if (ret)
1312ef2383d0SJian Shen return ret;
1313ef2383d0SJian Shen
1314ef2383d0SJian Shen hdev->rxvtag_strip_en = enable;
1315ef2383d0SJian Shen return 0;
1316ef2383d0SJian Shen }
1317ef2383d0SJian Shen
hclgevf_reset_tqp(struct hnae3_handle * handle)13188fa86551SYufeng Mo static int hclgevf_reset_tqp(struct hnae3_handle *handle)
1319e2cb1decSSalil Mehta {
13208fa86551SYufeng Mo #define HCLGEVF_RESET_ALL_QUEUE_DONE 1U
1321e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1322d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
13238fa86551SYufeng Mo u8 return_status = 0;
13241a426f8bSPeng Li int ret;
13258fa86551SYufeng Mo u16 i;
1326e2cb1decSSalil Mehta
13271a426f8bSPeng Li /* disable vf queue before send queue reset msg to PF */
13288fa86551SYufeng Mo ret = hclgevf_tqp_enable(handle, false);
13298fa86551SYufeng Mo if (ret) {
13308fa86551SYufeng Mo dev_err(&hdev->pdev->dev, "failed to disable tqp, ret = %d\n",
13318fa86551SYufeng Mo ret);
13327fa6be4fSHuazhong Tan return ret;
13338fa86551SYufeng Mo }
13341a426f8bSPeng Li
1335d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_QUEUE_RESET, 0);
13368fa86551SYufeng Mo
13378fa86551SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, &return_status,
13388fa86551SYufeng Mo sizeof(return_status));
13398fa86551SYufeng Mo if (ret || return_status == HCLGEVF_RESET_ALL_QUEUE_DONE)
13408fa86551SYufeng Mo return ret;
13418fa86551SYufeng Mo
13428fa86551SYufeng Mo for (i = 1; i < handle->kinfo.num_tqps; i++) {
13438fa86551SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_QUEUE_RESET, 0);
1344416eedb6SJie Wang *(__le16 *)send_msg.data = cpu_to_le16(i);
13458fa86551SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
13468fa86551SYufeng Mo if (ret)
13478fa86551SYufeng Mo return ret;
13488fa86551SYufeng Mo }
13498fa86551SYufeng Mo
13508fa86551SYufeng Mo return 0;
1351e2cb1decSSalil Mehta }
1352e2cb1decSSalil Mehta
hclgevf_set_mtu(struct hnae3_handle * handle,int new_mtu)1353818f1675SYunsheng Lin static int hclgevf_set_mtu(struct hnae3_handle *handle, int new_mtu)
1354818f1675SYunsheng Lin {
1355818f1675SYunsheng Lin struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1356416eedb6SJie Wang struct hclge_mbx_mtu_info *mtu_info;
1357d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
1358818f1675SYunsheng Lin
1359d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_MTU, 0);
1360416eedb6SJie Wang mtu_info = (struct hclge_mbx_mtu_info *)send_msg.data;
1361416eedb6SJie Wang mtu_info->mtu = cpu_to_le32(new_mtu);
1362416eedb6SJie Wang
1363d3410018SYufeng Mo return hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1364818f1675SYunsheng Lin }
1365818f1675SYunsheng Lin
hclgevf_notify_client(struct hclgevf_dev * hdev,enum hnae3_reset_notify_type type)13666988eb2aSSalil Mehta static int hclgevf_notify_client(struct hclgevf_dev *hdev,
13676988eb2aSSalil Mehta enum hnae3_reset_notify_type type)
13686988eb2aSSalil Mehta {
13696988eb2aSSalil Mehta struct hnae3_client *client = hdev->nic_client;
13706988eb2aSSalil Mehta struct hnae3_handle *handle = &hdev->nic;
13716a5f6fa3SHuazhong Tan int ret;
13726988eb2aSSalil Mehta
137325d1817cSHuazhong Tan if (!test_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state) ||
137425d1817cSHuazhong Tan !client)
137525d1817cSHuazhong Tan return 0;
137625d1817cSHuazhong Tan
13776988eb2aSSalil Mehta if (!client->ops->reset_notify)
13786988eb2aSSalil Mehta return -EOPNOTSUPP;
13796988eb2aSSalil Mehta
13806a5f6fa3SHuazhong Tan ret = client->ops->reset_notify(handle, type);
13816a5f6fa3SHuazhong Tan if (ret)
13826a5f6fa3SHuazhong Tan dev_err(&hdev->pdev->dev, "notify nic client failed %d(%d)\n",
13836a5f6fa3SHuazhong Tan type, ret);
13846a5f6fa3SHuazhong Tan
13856a5f6fa3SHuazhong Tan return ret;
13866988eb2aSSalil Mehta }
13876988eb2aSSalil Mehta
hclgevf_notify_roce_client(struct hclgevf_dev * hdev,enum hnae3_reset_notify_type type)1388fe735c84SHuazhong Tan static int hclgevf_notify_roce_client(struct hclgevf_dev *hdev,
1389fe735c84SHuazhong Tan enum hnae3_reset_notify_type type)
1390fe735c84SHuazhong Tan {
1391fe735c84SHuazhong Tan struct hnae3_client *client = hdev->roce_client;
1392fe735c84SHuazhong Tan struct hnae3_handle *handle = &hdev->roce;
1393fe735c84SHuazhong Tan int ret;
1394fe735c84SHuazhong Tan
1395fe735c84SHuazhong Tan if (!test_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state) || !client)
1396fe735c84SHuazhong Tan return 0;
1397fe735c84SHuazhong Tan
1398fe735c84SHuazhong Tan if (!client->ops->reset_notify)
1399fe735c84SHuazhong Tan return -EOPNOTSUPP;
1400fe735c84SHuazhong Tan
1401fe735c84SHuazhong Tan ret = client->ops->reset_notify(handle, type);
1402fe735c84SHuazhong Tan if (ret)
1403fe735c84SHuazhong Tan dev_err(&hdev->pdev->dev, "notify roce client failed %d(%d)",
1404fe735c84SHuazhong Tan type, ret);
1405fe735c84SHuazhong Tan return ret;
1406fe735c84SHuazhong Tan }
1407fe735c84SHuazhong Tan
hclgevf_set_reset_pending(struct hclgevf_dev * hdev,enum hnae3_reset_type reset_type)14085a4b584cSHao Lan static void hclgevf_set_reset_pending(struct hclgevf_dev *hdev,
14095a4b584cSHao Lan enum hnae3_reset_type reset_type)
14105a4b584cSHao Lan {
14115a4b584cSHao Lan /* When an incorrect reset type is executed, the get_reset_level
14125a4b584cSHao Lan * function generates the HNAE3_NONE_RESET flag. As a result, this
14135a4b584cSHao Lan * type do not need to pending.
14145a4b584cSHao Lan */
14155a4b584cSHao Lan if (reset_type != HNAE3_NONE_RESET)
14165a4b584cSHao Lan set_bit(reset_type, &hdev->reset_pending);
14175a4b584cSHao Lan }
14185a4b584cSHao Lan
hclgevf_reset_wait(struct hclgevf_dev * hdev)14196988eb2aSSalil Mehta static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
14206988eb2aSSalil Mehta {
1421aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_US 20000
1422aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_CNT 2000
1423aa5c4f17SHuazhong Tan #define HCLGEVF_RESET_WAIT_TIMEOUT_US \
1424aa5c4f17SHuazhong Tan (HCLGEVF_RESET_WAIT_US * HCLGEVF_RESET_WAIT_CNT)
1425aa5c4f17SHuazhong Tan
1426aa5c4f17SHuazhong Tan u32 val;
1427aa5c4f17SHuazhong Tan int ret;
14286988eb2aSSalil Mehta
1429f28368bbSHuazhong Tan if (hdev->reset_type == HNAE3_VF_RESET)
1430076bb537SJie Wang ret = readl_poll_timeout(hdev->hw.hw.io_base +
143172e2fb07SHuazhong Tan HCLGEVF_VF_RST_ING, val,
143272e2fb07SHuazhong Tan !(val & HCLGEVF_VF_RST_ING_BIT),
143372e2fb07SHuazhong Tan HCLGEVF_RESET_WAIT_US,
143472e2fb07SHuazhong Tan HCLGEVF_RESET_WAIT_TIMEOUT_US);
143572e2fb07SHuazhong Tan else
1436076bb537SJie Wang ret = readl_poll_timeout(hdev->hw.hw.io_base +
143772e2fb07SHuazhong Tan HCLGEVF_RST_ING, val,
1438aa5c4f17SHuazhong Tan !(val & HCLGEVF_RST_ING_BITS),
1439aa5c4f17SHuazhong Tan HCLGEVF_RESET_WAIT_US,
1440aa5c4f17SHuazhong Tan HCLGEVF_RESET_WAIT_TIMEOUT_US);
14416988eb2aSSalil Mehta
14426988eb2aSSalil Mehta /* hardware completion status should be available by this time */
1443aa5c4f17SHuazhong Tan if (ret) {
1444aa5c4f17SHuazhong Tan dev_err(&hdev->pdev->dev,
14458912fd6aSColin Ian King "couldn't get reset done status from h/w, timeout!\n");
1446aa5c4f17SHuazhong Tan return ret;
14476988eb2aSSalil Mehta }
14486988eb2aSSalil Mehta
14496988eb2aSSalil Mehta /* we will wait a bit more to let reset of the stack to complete. This
14506988eb2aSSalil Mehta * might happen in case reset assertion was made by PF. Yes, this also
14516988eb2aSSalil Mehta * means we might end up waiting bit more even for VF reset.
14526988eb2aSSalil Mehta */
1453814d0c78SJie Wang if (hdev->reset_type == HNAE3_VF_FULL_RESET)
14546988eb2aSSalil Mehta msleep(5000);
1455814d0c78SJie Wang else
1456814d0c78SJie Wang msleep(500);
14576988eb2aSSalil Mehta
14586988eb2aSSalil Mehta return 0;
14596988eb2aSSalil Mehta }
14606988eb2aSSalil Mehta
hclgevf_reset_handshake(struct hclgevf_dev * hdev,bool enable)14616b428b4fSHuazhong Tan static void hclgevf_reset_handshake(struct hclgevf_dev *hdev, bool enable)
14626b428b4fSHuazhong Tan {
14636b428b4fSHuazhong Tan u32 reg_val;
14646b428b4fSHuazhong Tan
1465cb413bfaSJie Wang reg_val = hclgevf_read_dev(&hdev->hw, HCLGE_COMM_NIC_CSQ_DEPTH_REG);
14666b428b4fSHuazhong Tan if (enable)
14676b428b4fSHuazhong Tan reg_val |= HCLGEVF_NIC_SW_RST_RDY;
14686b428b4fSHuazhong Tan else
14696b428b4fSHuazhong Tan reg_val &= ~HCLGEVF_NIC_SW_RST_RDY;
14706b428b4fSHuazhong Tan
1471cb413bfaSJie Wang hclgevf_write_dev(&hdev->hw, HCLGE_COMM_NIC_CSQ_DEPTH_REG,
14726b428b4fSHuazhong Tan reg_val);
14736b428b4fSHuazhong Tan }
14746b428b4fSHuazhong Tan
hclgevf_reset_stack(struct hclgevf_dev * hdev)14756988eb2aSSalil Mehta static int hclgevf_reset_stack(struct hclgevf_dev *hdev)
14766988eb2aSSalil Mehta {
14777a01c897SSalil Mehta int ret;
14787a01c897SSalil Mehta
14796988eb2aSSalil Mehta /* uninitialize the nic client */
14806a5f6fa3SHuazhong Tan ret = hclgevf_notify_client(hdev, HNAE3_UNINIT_CLIENT);
14816a5f6fa3SHuazhong Tan if (ret)
14826a5f6fa3SHuazhong Tan return ret;
14836988eb2aSSalil Mehta
14847a01c897SSalil Mehta /* re-initialize the hclge device */
14859c6f7085SHuazhong Tan ret = hclgevf_reset_hdev(hdev);
14867a01c897SSalil Mehta if (ret) {
14877a01c897SSalil Mehta dev_err(&hdev->pdev->dev,
14887a01c897SSalil Mehta "hclge device re-init failed, VF is disabled!\n");
14897a01c897SSalil Mehta return ret;
14907a01c897SSalil Mehta }
14916988eb2aSSalil Mehta
14926988eb2aSSalil Mehta /* bring up the nic client again */
14936a5f6fa3SHuazhong Tan ret = hclgevf_notify_client(hdev, HNAE3_INIT_CLIENT);
14946a5f6fa3SHuazhong Tan if (ret)
14956a5f6fa3SHuazhong Tan return ret;
14966988eb2aSSalil Mehta
14976b428b4fSHuazhong Tan /* clear handshake status with IMP */
14986b428b4fSHuazhong Tan hclgevf_reset_handshake(hdev, false);
14996b428b4fSHuazhong Tan
15001cc9bc6eSHuazhong Tan /* bring up the nic to enable TX/RX again */
15011cc9bc6eSHuazhong Tan return hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
15026988eb2aSSalil Mehta }
15036988eb2aSSalil Mehta
hclgevf_reset_prepare_wait(struct hclgevf_dev * hdev)1504dea846e8SHuazhong Tan static int hclgevf_reset_prepare_wait(struct hclgevf_dev *hdev)
1505dea846e8SHuazhong Tan {
1506ada13ee3SHuazhong Tan #define HCLGEVF_RESET_SYNC_TIME 100
1507ada13ee3SHuazhong Tan
1508f28368bbSHuazhong Tan if (hdev->reset_type == HNAE3_VF_FUNC_RESET) {
1509d41884eeSHuazhong Tan struct hclge_vf_to_pf_msg send_msg;
1510d41884eeSHuazhong Tan int ret;
1511d41884eeSHuazhong Tan
1512d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_RESET, 0);
1513d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, true, NULL, 0);
1514cddd5648SHuazhong Tan if (ret) {
1515cddd5648SHuazhong Tan dev_err(&hdev->pdev->dev,
1516cddd5648SHuazhong Tan "failed to assert VF reset, ret = %d\n", ret);
1517cddd5648SHuazhong Tan return ret;
1518cddd5648SHuazhong Tan }
1519c88a6e7dSHuazhong Tan hdev->rst_stats.vf_func_rst_cnt++;
1520dea846e8SHuazhong Tan }
1521dea846e8SHuazhong Tan
1522076bb537SJie Wang set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
1523ada13ee3SHuazhong Tan /* inform hardware that preparatory work is done */
1524ada13ee3SHuazhong Tan msleep(HCLGEVF_RESET_SYNC_TIME);
15256b428b4fSHuazhong Tan hclgevf_reset_handshake(hdev, true);
1526d41884eeSHuazhong Tan dev_info(&hdev->pdev->dev, "prepare reset(%d) wait done\n",
1527d41884eeSHuazhong Tan hdev->reset_type);
1528dea846e8SHuazhong Tan
1529d41884eeSHuazhong Tan return 0;
1530dea846e8SHuazhong Tan }
1531dea846e8SHuazhong Tan
hclgevf_dump_rst_info(struct hclgevf_dev * hdev)15323d77d0cbSHuazhong Tan static void hclgevf_dump_rst_info(struct hclgevf_dev *hdev)
15333d77d0cbSHuazhong Tan {
15343d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "VF function reset count: %u\n",
15353d77d0cbSHuazhong Tan hdev->rst_stats.vf_func_rst_cnt);
15363d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "FLR reset count: %u\n",
15373d77d0cbSHuazhong Tan hdev->rst_stats.flr_rst_cnt);
15383d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "VF reset count: %u\n",
15393d77d0cbSHuazhong Tan hdev->rst_stats.vf_rst_cnt);
15403d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "reset done count: %u\n",
15413d77d0cbSHuazhong Tan hdev->rst_stats.rst_done_cnt);
15423d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "HW reset done count: %u\n",
15433d77d0cbSHuazhong Tan hdev->rst_stats.hw_rst_done_cnt);
15443d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "reset count: %u\n",
15453d77d0cbSHuazhong Tan hdev->rst_stats.rst_cnt);
15463d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "reset fail count: %u\n",
15473d77d0cbSHuazhong Tan hdev->rst_stats.rst_fail_cnt);
15483d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "vector0 interrupt enable status: 0x%x\n",
15493d77d0cbSHuazhong Tan hclgevf_read_dev(&hdev->hw, HCLGEVF_MISC_VECTOR_REG_BASE));
15503d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "vector0 interrupt status: 0x%x\n",
1551cb413bfaSJie Wang hclgevf_read_dev(&hdev->hw, HCLGE_COMM_VECTOR0_CMDQ_STATE_REG));
15523d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "handshake status: 0x%x\n",
1553cb413bfaSJie Wang hclgevf_read_dev(&hdev->hw, HCLGE_COMM_NIC_CSQ_DEPTH_REG));
15543d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "function reset status: 0x%x\n",
15553d77d0cbSHuazhong Tan hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING));
15563d77d0cbSHuazhong Tan dev_info(&hdev->pdev->dev, "hdev state: 0x%lx\n", hdev->state);
15573d77d0cbSHuazhong Tan }
15583d77d0cbSHuazhong Tan
hclgevf_reset_err_handle(struct hclgevf_dev * hdev)1559bbe6540eSHuazhong Tan static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev)
1560bbe6540eSHuazhong Tan {
15616b428b4fSHuazhong Tan /* recover handshake status with IMP when reset fail */
15626b428b4fSHuazhong Tan hclgevf_reset_handshake(hdev, true);
1563bbe6540eSHuazhong Tan hdev->rst_stats.rst_fail_cnt++;
1564adcf738bSGuojia Liao dev_err(&hdev->pdev->dev, "failed to reset VF(%u)\n",
1565bbe6540eSHuazhong Tan hdev->rst_stats.rst_fail_cnt);
1566bbe6540eSHuazhong Tan
1567bbe6540eSHuazhong Tan if (hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT)
15685a4b584cSHao Lan hclgevf_set_reset_pending(hdev, hdev->reset_type);
1569bbe6540eSHuazhong Tan
1570bbe6540eSHuazhong Tan if (hclgevf_is_reset_pending(hdev)) {
1571bbe6540eSHuazhong Tan set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
1572bbe6540eSHuazhong Tan hclgevf_reset_task_schedule(hdev);
15733d77d0cbSHuazhong Tan } else {
1574d5432455SGuojia Liao set_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
15753d77d0cbSHuazhong Tan hclgevf_dump_rst_info(hdev);
1576bbe6540eSHuazhong Tan }
1577bbe6540eSHuazhong Tan }
1578bbe6540eSHuazhong Tan
hclgevf_reset_prepare(struct hclgevf_dev * hdev)15791cc9bc6eSHuazhong Tan static int hclgevf_reset_prepare(struct hclgevf_dev *hdev)
15806988eb2aSSalil Mehta {
15816988eb2aSSalil Mehta int ret;
15826988eb2aSSalil Mehta
1583c88a6e7dSHuazhong Tan hdev->rst_stats.rst_cnt++;
15846988eb2aSSalil Mehta
1585fe735c84SHuazhong Tan /* perform reset of the stack & ae device for a client */
1586fe735c84SHuazhong Tan ret = hclgevf_notify_roce_client(hdev, HNAE3_DOWN_CLIENT);
1587fe735c84SHuazhong Tan if (ret)
1588fe735c84SHuazhong Tan return ret;
1589fe735c84SHuazhong Tan
15901cc9bc6eSHuazhong Tan rtnl_lock();
15916988eb2aSSalil Mehta /* bring down the nic to stop any ongoing TX/RX */
15926a5f6fa3SHuazhong Tan ret = hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
159329118ab9SHuazhong Tan rtnl_unlock();
15946a5f6fa3SHuazhong Tan if (ret)
15951cc9bc6eSHuazhong Tan return ret;
1596dea846e8SHuazhong Tan
15971cc9bc6eSHuazhong Tan return hclgevf_reset_prepare_wait(hdev);
15986988eb2aSSalil Mehta }
15996988eb2aSSalil Mehta
hclgevf_reset_rebuild(struct hclgevf_dev * hdev)16001cc9bc6eSHuazhong Tan static int hclgevf_reset_rebuild(struct hclgevf_dev *hdev)
16011cc9bc6eSHuazhong Tan {
16021cc9bc6eSHuazhong Tan int ret;
16031cc9bc6eSHuazhong Tan
1604c88a6e7dSHuazhong Tan hdev->rst_stats.hw_rst_done_cnt++;
1605fe735c84SHuazhong Tan ret = hclgevf_notify_roce_client(hdev, HNAE3_UNINIT_CLIENT);
1606fe735c84SHuazhong Tan if (ret)
1607fe735c84SHuazhong Tan return ret;
1608c88a6e7dSHuazhong Tan
160929118ab9SHuazhong Tan rtnl_lock();
16106988eb2aSSalil Mehta /* now, re-initialize the nic client and ae device */
16116988eb2aSSalil Mehta ret = hclgevf_reset_stack(hdev);
16121cc9bc6eSHuazhong Tan rtnl_unlock();
16136a5f6fa3SHuazhong Tan if (ret) {
16146988eb2aSSalil Mehta dev_err(&hdev->pdev->dev, "failed to reset VF stack\n");
16151cc9bc6eSHuazhong Tan return ret;
16166a5f6fa3SHuazhong Tan }
16176988eb2aSSalil Mehta
1618fe735c84SHuazhong Tan ret = hclgevf_notify_roce_client(hdev, HNAE3_INIT_CLIENT);
1619fe735c84SHuazhong Tan /* ignore RoCE notify error if it fails HCLGEVF_RESET_MAX_FAIL_CNT - 1
1620fe735c84SHuazhong Tan * times
1621fe735c84SHuazhong Tan */
1622fe735c84SHuazhong Tan if (ret &&
1623fe735c84SHuazhong Tan hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT - 1)
1624fe735c84SHuazhong Tan return ret;
1625fe735c84SHuazhong Tan
1626fe735c84SHuazhong Tan ret = hclgevf_notify_roce_client(hdev, HNAE3_UP_CLIENT);
1627fe735c84SHuazhong Tan if (ret)
1628fe735c84SHuazhong Tan return ret;
1629fe735c84SHuazhong Tan
1630b644a8d4SHuazhong Tan hdev->last_reset_time = jiffies;
1631c88a6e7dSHuazhong Tan hdev->rst_stats.rst_done_cnt++;
1632bbe6540eSHuazhong Tan hdev->rst_stats.rst_fail_cnt = 0;
1633d5432455SGuojia Liao clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
1634b644a8d4SHuazhong Tan
16351cc9bc6eSHuazhong Tan return 0;
16361cc9bc6eSHuazhong Tan }
16371cc9bc6eSHuazhong Tan
hclgevf_reset(struct hclgevf_dev * hdev)16381cc9bc6eSHuazhong Tan static void hclgevf_reset(struct hclgevf_dev *hdev)
16391cc9bc6eSHuazhong Tan {
16401cc9bc6eSHuazhong Tan if (hclgevf_reset_prepare(hdev))
16411cc9bc6eSHuazhong Tan goto err_reset;
16421cc9bc6eSHuazhong Tan
16431cc9bc6eSHuazhong Tan /* check if VF could successfully fetch the hardware reset completion
16441cc9bc6eSHuazhong Tan * status from the hardware
16451cc9bc6eSHuazhong Tan */
16461cc9bc6eSHuazhong Tan if (hclgevf_reset_wait(hdev)) {
16471cc9bc6eSHuazhong Tan /* can't do much in this situation, will disable VF */
16481cc9bc6eSHuazhong Tan dev_err(&hdev->pdev->dev,
16491cc9bc6eSHuazhong Tan "failed to fetch H/W reset completion status\n");
16501cc9bc6eSHuazhong Tan goto err_reset;
16511cc9bc6eSHuazhong Tan }
16521cc9bc6eSHuazhong Tan
16531cc9bc6eSHuazhong Tan if (hclgevf_reset_rebuild(hdev))
16541cc9bc6eSHuazhong Tan goto err_reset;
16551cc9bc6eSHuazhong Tan
16561cc9bc6eSHuazhong Tan return;
16571cc9bc6eSHuazhong Tan
16586a5f6fa3SHuazhong Tan err_reset:
1659bbe6540eSHuazhong Tan hclgevf_reset_err_handle(hdev);
16606988eb2aSSalil Mehta }
16616988eb2aSSalil Mehta
hclgevf_get_reset_level(unsigned long * addr)1662ed1c6f35SPeiyang Wang static enum hnae3_reset_type hclgevf_get_reset_level(unsigned long *addr)
1663720bd583SHuazhong Tan {
1664720bd583SHuazhong Tan enum hnae3_reset_type rst_level = HNAE3_NONE_RESET;
1665720bd583SHuazhong Tan
1666dea846e8SHuazhong Tan /* return the highest priority reset level amongst all */
1667b90fcc5bSHuazhong Tan if (test_bit(HNAE3_VF_RESET, addr)) {
1668b90fcc5bSHuazhong Tan rst_level = HNAE3_VF_RESET;
1669b90fcc5bSHuazhong Tan clear_bit(HNAE3_VF_RESET, addr);
1670b90fcc5bSHuazhong Tan clear_bit(HNAE3_VF_PF_FUNC_RESET, addr);
1671b90fcc5bSHuazhong Tan clear_bit(HNAE3_VF_FUNC_RESET, addr);
1672b90fcc5bSHuazhong Tan } else if (test_bit(HNAE3_VF_FULL_RESET, addr)) {
1673dea846e8SHuazhong Tan rst_level = HNAE3_VF_FULL_RESET;
1674dea846e8SHuazhong Tan clear_bit(HNAE3_VF_FULL_RESET, addr);
1675dea846e8SHuazhong Tan clear_bit(HNAE3_VF_FUNC_RESET, addr);
1676aa5c4f17SHuazhong Tan } else if (test_bit(HNAE3_VF_PF_FUNC_RESET, addr)) {
1677aa5c4f17SHuazhong Tan rst_level = HNAE3_VF_PF_FUNC_RESET;
1678aa5c4f17SHuazhong Tan clear_bit(HNAE3_VF_PF_FUNC_RESET, addr);
1679aa5c4f17SHuazhong Tan clear_bit(HNAE3_VF_FUNC_RESET, addr);
1680dea846e8SHuazhong Tan } else if (test_bit(HNAE3_VF_FUNC_RESET, addr)) {
1681dea846e8SHuazhong Tan rst_level = HNAE3_VF_FUNC_RESET;
1682dea846e8SHuazhong Tan clear_bit(HNAE3_VF_FUNC_RESET, addr);
16836ff3cf07SHuazhong Tan } else if (test_bit(HNAE3_FLR_RESET, addr)) {
16846ff3cf07SHuazhong Tan rst_level = HNAE3_FLR_RESET;
16856ff3cf07SHuazhong Tan clear_bit(HNAE3_FLR_RESET, addr);
1686720bd583SHuazhong Tan }
1687720bd583SHuazhong Tan
16885a4b584cSHao Lan clear_bit(HNAE3_NONE_RESET, addr);
16895a4b584cSHao Lan
1690720bd583SHuazhong Tan return rst_level;
1691720bd583SHuazhong Tan }
1692720bd583SHuazhong Tan
hclgevf_reset_event(struct pci_dev * pdev,struct hnae3_handle * handle)16936ae4e733SShiju Jose static void hclgevf_reset_event(struct pci_dev *pdev,
16946ae4e733SShiju Jose struct hnae3_handle *handle)
16956d4c3981SSalil Mehta {
16966ff3cf07SHuazhong Tan struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
16976ff3cf07SHuazhong Tan struct hclgevf_dev *hdev = ae_dev->priv;
16986d4c3981SSalil Mehta
16996ff3cf07SHuazhong Tan if (hdev->default_reset_request)
17000742ed7cSHuazhong Tan hdev->reset_level =
1701ed1c6f35SPeiyang Wang hclgevf_get_reset_level(&hdev->default_reset_request);
1702720bd583SHuazhong Tan else
1703dea846e8SHuazhong Tan hdev->reset_level = HNAE3_VF_FUNC_RESET;
17046d4c3981SSalil Mehta
17055a4b584cSHao Lan dev_info(&hdev->pdev->dev, "received reset request from VF enet, reset level is %d\n",
17065a4b584cSHao Lan hdev->reset_level);
17075a4b584cSHao Lan
1708436667d2SSalil Mehta /* reset of this VF requested */
1709436667d2SSalil Mehta set_bit(HCLGEVF_RESET_REQUESTED, &hdev->reset_state);
1710436667d2SSalil Mehta hclgevf_reset_task_schedule(hdev);
17116d4c3981SSalil Mehta
17120742ed7cSHuazhong Tan hdev->last_reset_time = jiffies;
17136d4c3981SSalil Mehta }
17146d4c3981SSalil Mehta
hclgevf_set_def_reset_request(struct hnae3_ae_dev * ae_dev,enum hnae3_reset_type rst_type)1715720bd583SHuazhong Tan static void hclgevf_set_def_reset_request(struct hnae3_ae_dev *ae_dev,
1716720bd583SHuazhong Tan enum hnae3_reset_type rst_type)
1717720bd583SHuazhong Tan {
17185a4b584cSHao Lan #define HCLGEVF_SUPPORT_RESET_TYPE \
17195a4b584cSHao Lan (BIT(HNAE3_VF_RESET) | BIT(HNAE3_VF_FUNC_RESET) | \
17205a4b584cSHao Lan BIT(HNAE3_VF_PF_FUNC_RESET) | BIT(HNAE3_VF_FULL_RESET) | \
17215a4b584cSHao Lan BIT(HNAE3_FLR_RESET) | BIT(HNAE3_VF_EXP_RESET))
17225a4b584cSHao Lan
1723720bd583SHuazhong Tan struct hclgevf_dev *hdev = ae_dev->priv;
1724720bd583SHuazhong Tan
17255a4b584cSHao Lan if (!(BIT(rst_type) & HCLGEVF_SUPPORT_RESET_TYPE)) {
17265a4b584cSHao Lan /* To prevent reset triggered by hclge_reset_event */
17275a4b584cSHao Lan set_bit(HNAE3_NONE_RESET, &hdev->default_reset_request);
17285a4b584cSHao Lan dev_info(&hdev->pdev->dev, "unsupported reset type %d\n",
17295a4b584cSHao Lan rst_type);
17305a4b584cSHao Lan return;
17315a4b584cSHao Lan }
1732720bd583SHuazhong Tan set_bit(rst_type, &hdev->default_reset_request);
1733720bd583SHuazhong Tan }
1734720bd583SHuazhong Tan
hclgevf_enable_vector(struct hclgevf_misc_vector * vector,bool en)1735f28368bbSHuazhong Tan static void hclgevf_enable_vector(struct hclgevf_misc_vector *vector, bool en)
1736f28368bbSHuazhong Tan {
1737f28368bbSHuazhong Tan writel(en ? 1 : 0, vector->addr);
1738f28368bbSHuazhong Tan }
1739f28368bbSHuazhong Tan
hclgevf_reset_prepare_general(struct hnae3_ae_dev * ae_dev,enum hnae3_reset_type rst_type)1740bb1890d5SJiaran Zhang static void hclgevf_reset_prepare_general(struct hnae3_ae_dev *ae_dev,
1741bb1890d5SJiaran Zhang enum hnae3_reset_type rst_type)
17426ff3cf07SHuazhong Tan {
1743bb1890d5SJiaran Zhang #define HCLGEVF_RESET_RETRY_WAIT_MS 500
1744bb1890d5SJiaran Zhang #define HCLGEVF_RESET_RETRY_CNT 5
1745f28368bbSHuazhong Tan
17466ff3cf07SHuazhong Tan struct hclgevf_dev *hdev = ae_dev->priv;
1747f28368bbSHuazhong Tan int retry_cnt = 0;
1748f28368bbSHuazhong Tan int ret;
17496ff3cf07SHuazhong Tan
1750ed0e658cSJiaran Zhang while (retry_cnt++ < HCLGEVF_RESET_RETRY_CNT) {
1751f28368bbSHuazhong Tan down(&hdev->reset_sem);
1752f28368bbSHuazhong Tan set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
1753bb1890d5SJiaran Zhang hdev->reset_type = rst_type;
1754f28368bbSHuazhong Tan ret = hclgevf_reset_prepare(hdev);
1755ed0e658cSJiaran Zhang if (!ret && !hdev->reset_pending)
1756ed0e658cSJiaran Zhang break;
1757ed0e658cSJiaran Zhang
17586ff3cf07SHuazhong Tan dev_err(&hdev->pdev->dev,
1759ed0e658cSJiaran Zhang "failed to prepare to reset, ret=%d, reset_pending:0x%lx, retry_cnt:%d\n",
1760ed0e658cSJiaran Zhang ret, hdev->reset_pending, retry_cnt);
1761f28368bbSHuazhong Tan clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
1762f28368bbSHuazhong Tan up(&hdev->reset_sem);
1763bb1890d5SJiaran Zhang msleep(HCLGEVF_RESET_RETRY_WAIT_MS);
1764f28368bbSHuazhong Tan }
1765f28368bbSHuazhong Tan
1766bb1890d5SJiaran Zhang /* disable misc vector before reset done */
1767f28368bbSHuazhong Tan hclgevf_enable_vector(&hdev->misc_vector, false);
1768bb1890d5SJiaran Zhang
1769bb1890d5SJiaran Zhang if (hdev->reset_type == HNAE3_FLR_RESET)
1770f28368bbSHuazhong Tan hdev->rst_stats.flr_rst_cnt++;
1771f28368bbSHuazhong Tan }
1772f28368bbSHuazhong Tan
hclgevf_reset_done(struct hnae3_ae_dev * ae_dev)1773bb1890d5SJiaran Zhang static void hclgevf_reset_done(struct hnae3_ae_dev *ae_dev)
1774f28368bbSHuazhong Tan {
1775f28368bbSHuazhong Tan struct hclgevf_dev *hdev = ae_dev->priv;
1776f28368bbSHuazhong Tan int ret;
1777f28368bbSHuazhong Tan
1778f28368bbSHuazhong Tan hclgevf_enable_vector(&hdev->misc_vector, true);
1779f28368bbSHuazhong Tan
1780f28368bbSHuazhong Tan ret = hclgevf_reset_rebuild(hdev);
1781f28368bbSHuazhong Tan if (ret)
1782f28368bbSHuazhong Tan dev_warn(&hdev->pdev->dev, "fail to rebuild, ret=%d\n",
1783f28368bbSHuazhong Tan ret);
1784f28368bbSHuazhong Tan
1785f28368bbSHuazhong Tan hdev->reset_type = HNAE3_NONE_RESET;
17868445d9d3SJie Wang if (test_and_clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
1787f28368bbSHuazhong Tan up(&hdev->reset_sem);
17886ff3cf07SHuazhong Tan }
17896ff3cf07SHuazhong Tan
hclgevf_get_fw_version(struct hnae3_handle * handle)1790e2cb1decSSalil Mehta static u32 hclgevf_get_fw_version(struct hnae3_handle *handle)
1791e2cb1decSSalil Mehta {
1792e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
1793e2cb1decSSalil Mehta
1794e2cb1decSSalil Mehta return hdev->fw_version;
1795e2cb1decSSalil Mehta }
1796e2cb1decSSalil Mehta
hclgevf_get_misc_vector(struct hclgevf_dev * hdev)1797e2cb1decSSalil Mehta static void hclgevf_get_misc_vector(struct hclgevf_dev *hdev)
1798e2cb1decSSalil Mehta {
1799e2cb1decSSalil Mehta struct hclgevf_misc_vector *vector = &hdev->misc_vector;
1800e2cb1decSSalil Mehta
1801e2cb1decSSalil Mehta vector->vector_irq = pci_irq_vector(hdev->pdev,
1802e2cb1decSSalil Mehta HCLGEVF_MISC_VECTOR_NUM);
1803076bb537SJie Wang vector->addr = hdev->hw.hw.io_base + HCLGEVF_MISC_VECTOR_REG_BASE;
1804e2cb1decSSalil Mehta /* vector status always valid for Vector 0 */
1805e2cb1decSSalil Mehta hdev->vector_status[HCLGEVF_MISC_VECTOR_NUM] = 0;
1806e2cb1decSSalil Mehta hdev->vector_irq[HCLGEVF_MISC_VECTOR_NUM] = vector->vector_irq;
1807e2cb1decSSalil Mehta
1808e2cb1decSSalil Mehta hdev->num_msi_left -= 1;
1809e2cb1decSSalil Mehta hdev->num_msi_used += 1;
1810e2cb1decSSalil Mehta }
1811e2cb1decSSalil Mehta
hclgevf_reset_task_schedule(struct hclgevf_dev * hdev)181235a1e503SSalil Mehta void hclgevf_reset_task_schedule(struct hclgevf_dev *hdev)
181335a1e503SSalil Mehta {
1814ff200099SYunsheng Lin if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
18150251d196SGuangbin Huang test_bit(HCLGEVF_STATE_SERVICE_INITED, &hdev->state) &&
1816ff200099SYunsheng Lin !test_and_set_bit(HCLGEVF_STATE_RST_SERVICE_SCHED,
1817ff200099SYunsheng Lin &hdev->state))
18180ea68902SYunsheng Lin mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
181935a1e503SSalil Mehta }
182035a1e503SSalil Mehta
hclgevf_mbx_task_schedule(struct hclgevf_dev * hdev)182107a0556aSSalil Mehta void hclgevf_mbx_task_schedule(struct hclgevf_dev *hdev)
1822e2cb1decSSalil Mehta {
1823ff200099SYunsheng Lin if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
1824ff200099SYunsheng Lin !test_and_set_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED,
1825ff200099SYunsheng Lin &hdev->state))
18260ea68902SYunsheng Lin mod_delayed_work(hclgevf_wq, &hdev->service_task, 0);
182707a0556aSSalil Mehta }
1828e2cb1decSSalil Mehta
hclgevf_task_schedule(struct hclgevf_dev * hdev,unsigned long delay)1829ff200099SYunsheng Lin static void hclgevf_task_schedule(struct hclgevf_dev *hdev,
1830ff200099SYunsheng Lin unsigned long delay)
1831e2cb1decSSalil Mehta {
1832d5432455SGuojia Liao if (!test_bit(HCLGEVF_STATE_REMOVING, &hdev->state) &&
1833d5432455SGuojia Liao !test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state))
18340ea68902SYunsheng Lin mod_delayed_work(hclgevf_wq, &hdev->service_task, delay);
1835e2cb1decSSalil Mehta }
1836e2cb1decSSalil Mehta
hclgevf_reset_service_task(struct hclgevf_dev * hdev)1837ff200099SYunsheng Lin static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
183835a1e503SSalil Mehta {
1839d6ad7c53SGuojia Liao #define HCLGEVF_MAX_RESET_ATTEMPTS_CNT 3
1840d6ad7c53SGuojia Liao
1841ff200099SYunsheng Lin if (!test_and_clear_bit(HCLGEVF_STATE_RST_SERVICE_SCHED, &hdev->state))
1842ff200099SYunsheng Lin return;
1843ff200099SYunsheng Lin
1844f28368bbSHuazhong Tan down(&hdev->reset_sem);
1845f28368bbSHuazhong Tan set_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
184635a1e503SSalil Mehta
1847436667d2SSalil Mehta if (test_and_clear_bit(HCLGEVF_RESET_PENDING,
1848436667d2SSalil Mehta &hdev->reset_state)) {
1849cd7e963dSSalil Mehta /* PF has intimated that it is about to reset the hardware.
18509b2f3477SWeihang Li * We now have to poll & check if hardware has actually
18519b2f3477SWeihang Li * completed the reset sequence. On hardware reset completion,
18529b2f3477SWeihang Li * VF needs to reset the client and ae device.
185335a1e503SSalil Mehta */
1854436667d2SSalil Mehta hdev->reset_attempts = 0;
1855436667d2SSalil Mehta
1856dea846e8SHuazhong Tan hdev->last_reset_time = jiffies;
18571385cc81SYufeng Mo hdev->reset_type =
1858ed1c6f35SPeiyang Wang hclgevf_get_reset_level(&hdev->reset_pending);
18591385cc81SYufeng Mo if (hdev->reset_type != HNAE3_NONE_RESET)
18601cc9bc6eSHuazhong Tan hclgevf_reset(hdev);
1861436667d2SSalil Mehta } else if (test_and_clear_bit(HCLGEVF_RESET_REQUESTED,
1862436667d2SSalil Mehta &hdev->reset_state)) {
1863436667d2SSalil Mehta /* we could be here when either of below happens:
18649b2f3477SWeihang Li * 1. reset was initiated due to watchdog timeout caused by
1865436667d2SSalil Mehta * a. IMP was earlier reset and our TX got choked down and
1866436667d2SSalil Mehta * which resulted in watchdog reacting and inducing VF
1867436667d2SSalil Mehta * reset. This also means our cmdq would be unreliable.
1868436667d2SSalil Mehta * b. problem in TX due to other lower layer(example link
1869436667d2SSalil Mehta * layer not functioning properly etc.)
1870436667d2SSalil Mehta * 2. VF reset might have been initiated due to some config
1871436667d2SSalil Mehta * change.
1872436667d2SSalil Mehta *
1873436667d2SSalil Mehta * NOTE: Theres no clear way to detect above cases than to react
1874436667d2SSalil Mehta * to the response of PF for this reset request. PF will ack the
1875436667d2SSalil Mehta * 1b and 2. cases but we will not get any intimation about 1a
1876436667d2SSalil Mehta * from PF as cmdq would be in unreliable state i.e. mailbox
1877436667d2SSalil Mehta * communication between PF and VF would be broken.
187846ee7350SGuojia Liao *
187946ee7350SGuojia Liao * if we are never geting into pending state it means either:
1880436667d2SSalil Mehta * 1. PF is not receiving our request which could be due to IMP
1881436667d2SSalil Mehta * reset
1882436667d2SSalil Mehta * 2. PF is screwed
1883436667d2SSalil Mehta * We cannot do much for 2. but to check first we can try reset
1884436667d2SSalil Mehta * our PCIe + stack and see if it alleviates the problem.
1885436667d2SSalil Mehta */
1886d6ad7c53SGuojia Liao if (hdev->reset_attempts > HCLGEVF_MAX_RESET_ATTEMPTS_CNT) {
1887436667d2SSalil Mehta /* prepare for full reset of stack + pcie interface */
18885a4b584cSHao Lan hclgevf_set_reset_pending(hdev, HNAE3_VF_FULL_RESET);
1889436667d2SSalil Mehta
1890436667d2SSalil Mehta /* "defer" schedule the reset task again */
1891436667d2SSalil Mehta set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
1892436667d2SSalil Mehta } else {
1893436667d2SSalil Mehta hdev->reset_attempts++;
1894436667d2SSalil Mehta
18955a4b584cSHao Lan hclgevf_set_reset_pending(hdev, hdev->reset_level);
1896dea846e8SHuazhong Tan set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
1897436667d2SSalil Mehta }
1898dea846e8SHuazhong Tan hclgevf_reset_task_schedule(hdev);
1899436667d2SSalil Mehta }
190035a1e503SSalil Mehta
1901afb6afdbSHuazhong Tan hdev->reset_type = HNAE3_NONE_RESET;
190235a1e503SSalil Mehta clear_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
1903f28368bbSHuazhong Tan up(&hdev->reset_sem);
190435a1e503SSalil Mehta }
190535a1e503SSalil Mehta
hclgevf_mailbox_service_task(struct hclgevf_dev * hdev)1906ff200099SYunsheng Lin static void hclgevf_mailbox_service_task(struct hclgevf_dev *hdev)
1907e2cb1decSSalil Mehta {
1908ff200099SYunsheng Lin if (!test_and_clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state))
1909ff200099SYunsheng Lin return;
1910e2cb1decSSalil Mehta
1911e2cb1decSSalil Mehta if (test_and_set_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state))
1912e2cb1decSSalil Mehta return;
1913e2cb1decSSalil Mehta
191407a0556aSSalil Mehta hclgevf_mbx_async_handler(hdev);
1915e2cb1decSSalil Mehta
1916e2cb1decSSalil Mehta clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
1917e2cb1decSSalil Mehta }
1918e2cb1decSSalil Mehta
hclgevf_keep_alive(struct hclgevf_dev * hdev)1919ff200099SYunsheng Lin static void hclgevf_keep_alive(struct hclgevf_dev *hdev)
1920a6d818e3SYunsheng Lin {
1921d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
1922a6d818e3SYunsheng Lin int ret;
1923a6d818e3SYunsheng Lin
1924076bb537SJie Wang if (test_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state))
1925c59a85c0SJian Shen return;
1926c59a85c0SJian Shen
1927d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_KEEP_ALIVE, 0);
1928d3410018SYufeng Mo ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
1929a6d818e3SYunsheng Lin if (ret)
1930a6d818e3SYunsheng Lin dev_err(&hdev->pdev->dev,
1931a6d818e3SYunsheng Lin "VF sends keep alive cmd failed(=%d)\n", ret);
1932a6d818e3SYunsheng Lin }
1933a6d818e3SYunsheng Lin
hclgevf_periodic_service_task(struct hclgevf_dev * hdev)1934ff200099SYunsheng Lin static void hclgevf_periodic_service_task(struct hclgevf_dev *hdev)
1935e2cb1decSSalil Mehta {
1936ff200099SYunsheng Lin unsigned long delta = round_jiffies_relative(HZ);
1937ff200099SYunsheng Lin struct hnae3_handle *handle = &hdev->nic;
1938e2cb1decSSalil Mehta
1939bd3caddfSJie Wang if (test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state) ||
1940bd3caddfSJie Wang test_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state))
1941e6394363SGuangbin Huang return;
1942e6394363SGuangbin Huang
1943ff200099SYunsheng Lin if (time_is_after_jiffies(hdev->last_serv_processed + HZ)) {
1944ff200099SYunsheng Lin delta = jiffies - hdev->last_serv_processed;
1945db01afebSliuzhongzhu
1946ff200099SYunsheng Lin if (delta < round_jiffies_relative(HZ)) {
1947ff200099SYunsheng Lin delta = round_jiffies_relative(HZ) - delta;
1948ff200099SYunsheng Lin goto out;
1949db01afebSliuzhongzhu }
1950ff200099SYunsheng Lin }
1951ff200099SYunsheng Lin
1952ff200099SYunsheng Lin hdev->serv_processed_cnt++;
1953ff200099SYunsheng Lin if (!(hdev->serv_processed_cnt % HCLGEVF_KEEP_ALIVE_TASK_INTERVAL))
1954ff200099SYunsheng Lin hclgevf_keep_alive(hdev);
1955ff200099SYunsheng Lin
1956ff200099SYunsheng Lin if (test_bit(HCLGEVF_STATE_DOWN, &hdev->state)) {
1957ff200099SYunsheng Lin hdev->last_serv_processed = jiffies;
1958ff200099SYunsheng Lin goto out;
1959ff200099SYunsheng Lin }
1960ff200099SYunsheng Lin
1961ff200099SYunsheng Lin if (!(hdev->serv_processed_cnt % HCLGEVF_STATS_TIMER_INTERVAL))
19624afc310cSJie Wang hclge_comm_tqps_update_stats(handle, &hdev->hw.hw);
1963e2cb1decSSalil Mehta
196401305e16SGuangbin Huang /* VF does not need to request link status when this bit is set, because
196501305e16SGuangbin Huang * PF will push its link status to VFs when link status changed.
1966e2cb1decSSalil Mehta */
196701305e16SGuangbin Huang if (!test_bit(HCLGEVF_STATE_PF_PUSH_LINK_STATUS, &hdev->state))
1968e2cb1decSSalil Mehta hclgevf_request_link_info(hdev);
1969e2cb1decSSalil Mehta
19709194d18bSliuzhongzhu hclgevf_update_link_mode(hdev);
19719194d18bSliuzhongzhu
1972fe4144d4SJian Shen hclgevf_sync_vlan_filter(hdev);
1973fe4144d4SJian Shen
1974ee4bcd3bSJian Shen hclgevf_sync_mac_table(hdev);
1975ee4bcd3bSJian Shen
1976c631c696SJian Shen hclgevf_sync_promisc_mode(hdev);
1977c631c696SJian Shen
1978ff200099SYunsheng Lin hdev->last_serv_processed = jiffies;
1979436667d2SSalil Mehta
1980ff200099SYunsheng Lin out:
1981ff200099SYunsheng Lin hclgevf_task_schedule(hdev, delta);
1982ff200099SYunsheng Lin }
1983b3c3fe8eSYunsheng Lin
hclgevf_service_task(struct work_struct * work)1984ff200099SYunsheng Lin static void hclgevf_service_task(struct work_struct *work)
1985ff200099SYunsheng Lin {
1986ff200099SYunsheng Lin struct hclgevf_dev *hdev = container_of(work, struct hclgevf_dev,
1987ff200099SYunsheng Lin service_task.work);
1988ff200099SYunsheng Lin
1989ff200099SYunsheng Lin hclgevf_reset_service_task(hdev);
1990ff200099SYunsheng Lin hclgevf_mailbox_service_task(hdev);
1991ff200099SYunsheng Lin hclgevf_periodic_service_task(hdev);
1992ff200099SYunsheng Lin
1993ff200099SYunsheng Lin /* Handle reset and mbx again in case periodical task delays the
1994ff200099SYunsheng Lin * handling by calling hclgevf_task_schedule() in
1995ff200099SYunsheng Lin * hclgevf_periodic_service_task()
1996ff200099SYunsheng Lin */
1997ff200099SYunsheng Lin hclgevf_reset_service_task(hdev);
1998ff200099SYunsheng Lin hclgevf_mailbox_service_task(hdev);
1999e2cb1decSSalil Mehta }
2000e2cb1decSSalil Mehta
hclgevf_clear_event_cause(struct hclgevf_dev * hdev,u32 regclr)2001e2cb1decSSalil Mehta static void hclgevf_clear_event_cause(struct hclgevf_dev *hdev, u32 regclr)
2002e2cb1decSSalil Mehta {
2003cb413bfaSJie Wang hclgevf_write_dev(&hdev->hw, HCLGE_COMM_VECTOR0_CMDQ_SRC_REG, regclr);
2004e2cb1decSSalil Mehta }
2005e2cb1decSSalil Mehta
hclgevf_check_evt_cause(struct hclgevf_dev * hdev,u32 * clearval)2006b90fcc5bSHuazhong Tan static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
2007b90fcc5bSHuazhong Tan u32 *clearval)
2008e2cb1decSSalil Mehta {
200913050921SHuazhong Tan u32 val, cmdq_stat_reg, rst_ing_reg;
2010e2cb1decSSalil Mehta
2011e2cb1decSSalil Mehta /* fetch the events from their corresponding regs */
201213050921SHuazhong Tan cmdq_stat_reg = hclgevf_read_dev(&hdev->hw,
2013cb413bfaSJie Wang HCLGE_COMM_VECTOR0_CMDQ_STATE_REG);
201413050921SHuazhong Tan if (BIT(HCLGEVF_VECTOR0_RST_INT_B) & cmdq_stat_reg) {
2015b90fcc5bSHuazhong Tan rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
2016b90fcc5bSHuazhong Tan dev_info(&hdev->pdev->dev,
2017b90fcc5bSHuazhong Tan "receive reset interrupt 0x%x!\n", rst_ing_reg);
20185a4b584cSHao Lan hclgevf_set_reset_pending(hdev, HNAE3_VF_RESET);
2019b90fcc5bSHuazhong Tan set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
2020076bb537SJie Wang set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
202113050921SHuazhong Tan *clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B);
2022c88a6e7dSHuazhong Tan hdev->rst_stats.vf_rst_cnt++;
202372e2fb07SHuazhong Tan /* set up VF hardware reset status, its PF will clear
202472e2fb07SHuazhong Tan * this status when PF has initialized done.
202572e2fb07SHuazhong Tan */
202672e2fb07SHuazhong Tan val = hclgevf_read_dev(&hdev->hw, HCLGEVF_VF_RST_ING);
202772e2fb07SHuazhong Tan hclgevf_write_dev(&hdev->hw, HCLGEVF_VF_RST_ING,
202872e2fb07SHuazhong Tan val | HCLGEVF_VF_RST_ING_BIT);
2029b90fcc5bSHuazhong Tan return HCLGEVF_VECTOR0_EVENT_RST;
2030b90fcc5bSHuazhong Tan }
2031b90fcc5bSHuazhong Tan
2032e2cb1decSSalil Mehta /* check for vector0 mailbox(=CMDQ RX) event source */
203313050921SHuazhong Tan if (BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B) & cmdq_stat_reg) {
203413050921SHuazhong Tan /* for revision 0x21, clearing interrupt is writing bit 0
203513050921SHuazhong Tan * to the clear register, writing bit 1 means to keep the
203613050921SHuazhong Tan * old value.
203713050921SHuazhong Tan * for revision 0x20, the clear register is a read & write
203813050921SHuazhong Tan * register, so we should just write 0 to the bit we are
203913050921SHuazhong Tan * handling, and keep other bits as cmdq_stat_reg.
204013050921SHuazhong Tan */
2041295ba232SGuangbin Huang if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2)
204213050921SHuazhong Tan *clearval = ~(1U << HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
204313050921SHuazhong Tan else
204413050921SHuazhong Tan *clearval = cmdq_stat_reg &
204513050921SHuazhong Tan ~BIT(HCLGEVF_VECTOR0_RX_CMDQ_INT_B);
204613050921SHuazhong Tan
2047b90fcc5bSHuazhong Tan return HCLGEVF_VECTOR0_EVENT_MBX;
2048e2cb1decSSalil Mehta }
2049e2cb1decSSalil Mehta
2050e45afb39SHuazhong Tan /* print other vector0 event source */
2051e45afb39SHuazhong Tan dev_info(&hdev->pdev->dev,
2052e45afb39SHuazhong Tan "vector 0 interrupt from unknown source, cmdq_src = %#x\n",
2053e45afb39SHuazhong Tan cmdq_stat_reg);
2054e2cb1decSSalil Mehta
2055b90fcc5bSHuazhong Tan return HCLGEVF_VECTOR0_EVENT_OTHER;
2056e2cb1decSSalil Mehta }
2057e2cb1decSSalil Mehta
hclgevf_reset_timer(struct timer_list * t)205865e98bb5SJijie Shao static void hclgevf_reset_timer(struct timer_list *t)
205965e98bb5SJijie Shao {
2060*41cb0855SIngo Molnar struct hclgevf_dev *hdev = timer_container_of(hdev, t, reset_timer);
206165e98bb5SJijie Shao
206265e98bb5SJijie Shao hclgevf_clear_event_cause(hdev, HCLGEVF_VECTOR0_EVENT_RST);
206365e98bb5SJijie Shao hclgevf_reset_task_schedule(hdev);
206465e98bb5SJijie Shao }
206565e98bb5SJijie Shao
hclgevf_misc_irq_handle(int irq,void * data)2066e2cb1decSSalil Mehta static irqreturn_t hclgevf_misc_irq_handle(int irq, void *data)
2067e2cb1decSSalil Mehta {
206865e98bb5SJijie Shao #define HCLGEVF_RESET_DELAY 5
206965e98bb5SJijie Shao
2070b90fcc5bSHuazhong Tan enum hclgevf_evt_cause event_cause;
2071e2cb1decSSalil Mehta struct hclgevf_dev *hdev = data;
2072e2cb1decSSalil Mehta u32 clearval;
2073e2cb1decSSalil Mehta
2074e2cb1decSSalil Mehta hclgevf_enable_vector(&hdev->misc_vector, false);
2075b90fcc5bSHuazhong Tan event_cause = hclgevf_check_evt_cause(hdev, &clearval);
2076427900d2SJiaran Zhang if (event_cause != HCLGEVF_VECTOR0_EVENT_OTHER)
2077427900d2SJiaran Zhang hclgevf_clear_event_cause(hdev, clearval);
2078e2cb1decSSalil Mehta
2079b90fcc5bSHuazhong Tan switch (event_cause) {
2080b90fcc5bSHuazhong Tan case HCLGEVF_VECTOR0_EVENT_RST:
208165e98bb5SJijie Shao mod_timer(&hdev->reset_timer,
208265e98bb5SJijie Shao jiffies + msecs_to_jiffies(HCLGEVF_RESET_DELAY));
2083b90fcc5bSHuazhong Tan break;
2084b90fcc5bSHuazhong Tan case HCLGEVF_VECTOR0_EVENT_MBX:
208507a0556aSSalil Mehta hclgevf_mbx_handler(hdev);
2086b90fcc5bSHuazhong Tan break;
2087b90fcc5bSHuazhong Tan default:
2088b90fcc5bSHuazhong Tan break;
2089b90fcc5bSHuazhong Tan }
2090e2cb1decSSalil Mehta
2091e2cb1decSSalil Mehta hclgevf_enable_vector(&hdev->misc_vector, true);
2092e2cb1decSSalil Mehta
2093e2cb1decSSalil Mehta return IRQ_HANDLED;
2094e2cb1decSSalil Mehta }
2095e2cb1decSSalil Mehta
hclgevf_configure(struct hclgevf_dev * hdev)2096e2cb1decSSalil Mehta static int hclgevf_configure(struct hclgevf_dev *hdev)
2097e2cb1decSSalil Mehta {
2098e2cb1decSSalil Mehta int ret;
2099e2cb1decSSalil Mehta
21003462207dSYufeng Mo hdev->gro_en = true;
21013462207dSYufeng Mo
210232e6d104SJian Shen ret = hclgevf_get_basic_info(hdev);
210332e6d104SJian Shen if (ret)
210432e6d104SJian Shen return ret;
210532e6d104SJian Shen
210692f11ea1SJian Shen /* get current port based vlan state from PF */
210792f11ea1SJian Shen ret = hclgevf_get_port_base_vlan_filter_state(hdev);
210892f11ea1SJian Shen if (ret)
210992f11ea1SJian Shen return ret;
211092f11ea1SJian Shen
2111e2cb1decSSalil Mehta /* get queue configuration from PF */
21126cee6fc3SJian Shen ret = hclgevf_get_queue_info(hdev);
2113e2cb1decSSalil Mehta if (ret)
2114e2cb1decSSalil Mehta return ret;
2115c0425944SPeng Li
2116c0425944SPeng Li /* get queue depth info from PF */
2117c0425944SPeng Li ret = hclgevf_get_queue_depth(hdev);
2118c0425944SPeng Li if (ret)
2119c0425944SPeng Li return ret;
2120c0425944SPeng Li
212132e6d104SJian Shen return hclgevf_get_pf_media_type(hdev);
2122e2cb1decSSalil Mehta }
2123e2cb1decSSalil Mehta
hclgevf_alloc_hdev(struct hnae3_ae_dev * ae_dev)21247a01c897SSalil Mehta static int hclgevf_alloc_hdev(struct hnae3_ae_dev *ae_dev)
21257a01c897SSalil Mehta {
21267a01c897SSalil Mehta struct pci_dev *pdev = ae_dev->pdev;
21271154bb26SPeng Li struct hclgevf_dev *hdev;
21287a01c897SSalil Mehta
21297a01c897SSalil Mehta hdev = devm_kzalloc(&pdev->dev, sizeof(*hdev), GFP_KERNEL);
21307a01c897SSalil Mehta if (!hdev)
21317a01c897SSalil Mehta return -ENOMEM;
21327a01c897SSalil Mehta
21337a01c897SSalil Mehta hdev->pdev = pdev;
21347a01c897SSalil Mehta hdev->ae_dev = ae_dev;
21357a01c897SSalil Mehta ae_dev->priv = hdev;
21367a01c897SSalil Mehta
21377a01c897SSalil Mehta return 0;
21387a01c897SSalil Mehta }
21397a01c897SSalil Mehta
hclgevf_init_roce_base_info(struct hclgevf_dev * hdev)2140e2cb1decSSalil Mehta static int hclgevf_init_roce_base_info(struct hclgevf_dev *hdev)
2141e2cb1decSSalil Mehta {
2142e2cb1decSSalil Mehta struct hnae3_handle *roce = &hdev->roce;
2143e2cb1decSSalil Mehta struct hnae3_handle *nic = &hdev->nic;
2144e2cb1decSSalil Mehta
214507acf909SJian Shen roce->rinfo.num_vectors = hdev->num_roce_msix;
2146e2cb1decSSalil Mehta
2147e2cb1decSSalil Mehta if (hdev->num_msi_left < roce->rinfo.num_vectors ||
2148e2cb1decSSalil Mehta hdev->num_msi_left == 0)
2149e2cb1decSSalil Mehta return -EINVAL;
2150e2cb1decSSalil Mehta
2151beb27ca4SJie Wang roce->rinfo.base_vector = hdev->roce_base_msix_offset;
2152e2cb1decSSalil Mehta
2153e2cb1decSSalil Mehta roce->rinfo.netdev = nic->kinfo.netdev;
2154076bb537SJie Wang roce->rinfo.roce_io_base = hdev->hw.hw.io_base;
2155076bb537SJie Wang roce->rinfo.roce_mem_base = hdev->hw.hw.mem_base;
2156e2cb1decSSalil Mehta
2157e2cb1decSSalil Mehta roce->pdev = nic->pdev;
2158e2cb1decSSalil Mehta roce->ae_algo = nic->ae_algo;
21596639a7b9SPeiyang Wang bitmap_copy(roce->numa_node_mask.bits, nic->numa_node_mask.bits,
21606639a7b9SPeiyang Wang MAX_NUMNODES);
2161e2cb1decSSalil Mehta return 0;
2162e2cb1decSSalil Mehta }
2163e2cb1decSSalil Mehta
hclgevf_config_gro(struct hclgevf_dev * hdev)21643462207dSYufeng Mo static int hclgevf_config_gro(struct hclgevf_dev *hdev)
2165b26a6feaSPeng Li {
2166b26a6feaSPeng Li struct hclgevf_cfg_gro_status_cmd *req;
21676befad60SJie Wang struct hclge_desc desc;
2168b26a6feaSPeng Li int ret;
2169b26a6feaSPeng Li
2170507e46aeSGuangbin Huang if (!hnae3_ae_dev_gro_supported(hdev->ae_dev))
2171b26a6feaSPeng Li return 0;
2172b26a6feaSPeng Li
217343710bfeSJie Wang hclgevf_cmd_setup_basic_desc(&desc, HCLGE_OPC_GRO_GENERIC_CONFIG,
2174b26a6feaSPeng Li false);
2175b26a6feaSPeng Li req = (struct hclgevf_cfg_gro_status_cmd *)desc.data;
2176b26a6feaSPeng Li
21773462207dSYufeng Mo req->gro_en = hdev->gro_en ? 1 : 0;
2178b26a6feaSPeng Li
2179b26a6feaSPeng Li ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
2180b26a6feaSPeng Li if (ret)
2181b26a6feaSPeng Li dev_err(&hdev->pdev->dev,
2182b26a6feaSPeng Li "VF GRO hardware config cmd failed, ret = %d.\n", ret);
2183b26a6feaSPeng Li
2184b26a6feaSPeng Li return ret;
2185b26a6feaSPeng Li }
2186b26a6feaSPeng Li
hclgevf_rss_init_hw(struct hclgevf_dev * hdev)2187944de484SGuojia Liao static int hclgevf_rss_init_hw(struct hclgevf_dev *hdev)
2188944de484SGuojia Liao {
2189027733b1SJie Wang struct hclge_comm_rss_cfg *rss_cfg = &hdev->rss_cfg;
219093969dc1SJie Wang u16 tc_offset[HCLGE_COMM_MAX_TC_NUM];
219193969dc1SJie Wang u16 tc_valid[HCLGE_COMM_MAX_TC_NUM];
219293969dc1SJie Wang u16 tc_size[HCLGE_COMM_MAX_TC_NUM];
2193944de484SGuojia Liao int ret;
2194944de484SGuojia Liao
2195295ba232SGuangbin Huang if (hdev->ae_dev->dev_version >= HNAE3_DEVICE_VERSION_V2) {
21967428d6c9SJie Wang ret = hclge_comm_set_rss_algo_key(&hdev->hw.hw,
21977428d6c9SJie Wang rss_cfg->rss_algo,
2198944de484SGuojia Liao rss_cfg->rss_hash_key);
2199944de484SGuojia Liao if (ret)
2200944de484SGuojia Liao return ret;
2201944de484SGuojia Liao
2202ed1c6f35SPeiyang Wang ret = hclge_comm_set_rss_input_tuple(&hdev->hw.hw, rss_cfg);
2203944de484SGuojia Liao if (ret)
2204944de484SGuojia Liao return ret;
2205944de484SGuojia Liao }
2206e2cb1decSSalil Mehta
22077428d6c9SJie Wang ret = hclge_comm_set_rss_indir_table(hdev->ae_dev, &hdev->hw.hw,
22087428d6c9SJie Wang rss_cfg->rss_indirection_tbl);
2209e2cb1decSSalil Mehta if (ret)
2210e2cb1decSSalil Mehta return ret;
2211e2cb1decSSalil Mehta
221293969dc1SJie Wang hclge_comm_get_rss_tc_info(rss_cfg->rss_size, hdev->hw_tc_map,
221393969dc1SJie Wang tc_offset, tc_valid, tc_size);
221493969dc1SJie Wang
221593969dc1SJie Wang return hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset,
221693969dc1SJie Wang tc_valid, tc_size);
2217e2cb1decSSalil Mehta }
2218e2cb1decSSalil Mehta
hclgevf_init_vlan_config(struct hclgevf_dev * hdev,bool rxvtag_strip_en)2219ef2383d0SJian Shen static int hclgevf_init_vlan_config(struct hclgevf_dev *hdev,
2220ef2383d0SJian Shen bool rxvtag_strip_en)
2221e2cb1decSSalil Mehta {
2222bbfd4506SJian Shen struct hnae3_handle *nic = &hdev->nic;
2223bbfd4506SJian Shen int ret;
2224bbfd4506SJian Shen
2225ef2383d0SJian Shen ret = hclgevf_en_hw_strip_rxvtag(nic, rxvtag_strip_en);
2226bbfd4506SJian Shen if (ret) {
2227bbfd4506SJian Shen dev_err(&hdev->pdev->dev,
2228bbfd4506SJian Shen "failed to enable rx vlan offload, ret = %d\n", ret);
2229bbfd4506SJian Shen return ret;
2230bbfd4506SJian Shen }
2231bbfd4506SJian Shen
2232e2cb1decSSalil Mehta return hclgevf_set_vlan_filter(&hdev->nic, htons(ETH_P_8021Q), 0,
2233e2cb1decSSalil Mehta false);
2234e2cb1decSSalil Mehta }
2235e2cb1decSSalil Mehta
hclgevf_flush_link_update(struct hclgevf_dev * hdev)2236ff200099SYunsheng Lin static void hclgevf_flush_link_update(struct hclgevf_dev *hdev)
2237ff200099SYunsheng Lin {
2238ff200099SYunsheng Lin #define HCLGEVF_FLUSH_LINK_TIMEOUT 100000
2239ff200099SYunsheng Lin
2240ff200099SYunsheng Lin unsigned long last = hdev->serv_processed_cnt;
2241ff200099SYunsheng Lin int i = 0;
2242ff200099SYunsheng Lin
2243ff200099SYunsheng Lin while (test_bit(HCLGEVF_STATE_LINK_UPDATING, &hdev->state) &&
2244ff200099SYunsheng Lin i++ < HCLGEVF_FLUSH_LINK_TIMEOUT &&
2245ff200099SYunsheng Lin last == hdev->serv_processed_cnt)
2246ff200099SYunsheng Lin usleep_range(1, 1);
2247ff200099SYunsheng Lin }
2248ff200099SYunsheng Lin
hclgevf_set_timer_task(struct hnae3_handle * handle,bool enable)22498cdb992fSJian Shen static void hclgevf_set_timer_task(struct hnae3_handle *handle, bool enable)
22508cdb992fSJian Shen {
22518cdb992fSJian Shen struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
22528cdb992fSJian Shen
22538cdb992fSJian Shen if (enable) {
2254ff200099SYunsheng Lin hclgevf_task_schedule(hdev, 0);
22558cdb992fSJian Shen } else {
2256b3c3fe8eSYunsheng Lin set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2257ff200099SYunsheng Lin
2258094c2812SPeiyang Wang smp_mb__after_atomic(); /* flush memory to make sure DOWN is seen by service task */
2259ff200099SYunsheng Lin hclgevf_flush_link_update(hdev);
22608cdb992fSJian Shen }
22618cdb992fSJian Shen }
22628cdb992fSJian Shen
hclgevf_ae_start(struct hnae3_handle * handle)2263e2cb1decSSalil Mehta static int hclgevf_ae_start(struct hnae3_handle *handle)
2264e2cb1decSSalil Mehta {
2265e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2266e2cb1decSSalil Mehta
2267ed7bedd2SGuangbin Huang clear_bit(HCLGEVF_STATE_DOWN, &hdev->state);
226801305e16SGuangbin Huang clear_bit(HCLGEVF_STATE_PF_PUSH_LINK_STATUS, &hdev->state);
2269ed7bedd2SGuangbin Huang
22704afc310cSJie Wang hclge_comm_reset_tqp_stats(handle);
2271e2cb1decSSalil Mehta
2272e2cb1decSSalil Mehta hclgevf_request_link_info(hdev);
2273e2cb1decSSalil Mehta
22749194d18bSliuzhongzhu hclgevf_update_link_mode(hdev);
22759194d18bSliuzhongzhu
2276e2cb1decSSalil Mehta return 0;
2277e2cb1decSSalil Mehta }
2278e2cb1decSSalil Mehta
hclgevf_ae_stop(struct hnae3_handle * handle)2279e2cb1decSSalil Mehta static void hclgevf_ae_stop(struct hnae3_handle *handle)
2280e2cb1decSSalil Mehta {
2281e2cb1decSSalil Mehta struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2282e2cb1decSSalil Mehta
22832f7e4896SFuyun Liang set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
22842f7e4896SFuyun Liang
2285146e92c1SHuazhong Tan if (hdev->reset_type != HNAE3_VF_RESET)
22868fa86551SYufeng Mo hclgevf_reset_tqp(handle);
228739cfbc9cSHuazhong Tan
22884afc310cSJie Wang hclge_comm_reset_tqp_stats(handle);
22898cc6c1f7SFuyun Liang hclgevf_update_link_status(hdev, 0);
2290e2cb1decSSalil Mehta }
2291e2cb1decSSalil Mehta
hclgevf_set_alive(struct hnae3_handle * handle,bool alive)2292a6d818e3SYunsheng Lin static int hclgevf_set_alive(struct hnae3_handle *handle, bool alive)
2293a6d818e3SYunsheng Lin {
2294d3410018SYufeng Mo #define HCLGEVF_STATE_ALIVE 1
2295d3410018SYufeng Mo #define HCLGEVF_STATE_NOT_ALIVE 0
2296a6d818e3SYunsheng Lin
2297d3410018SYufeng Mo struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2298d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
2299d3410018SYufeng Mo
2300d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_ALIVE, 0);
2301d3410018SYufeng Mo send_msg.data[0] = alive ? HCLGEVF_STATE_ALIVE :
2302d3410018SYufeng Mo HCLGEVF_STATE_NOT_ALIVE;
2303d3410018SYufeng Mo return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
2304a6d818e3SYunsheng Lin }
2305a6d818e3SYunsheng Lin
hclgevf_client_start(struct hnae3_handle * handle)2306a6d818e3SYunsheng Lin static int hclgevf_client_start(struct hnae3_handle *handle)
2307a6d818e3SYunsheng Lin {
2308f621df96SQinglang Miao return hclgevf_set_alive(handle, true);
2309a6d818e3SYunsheng Lin }
2310a6d818e3SYunsheng Lin
hclgevf_client_stop(struct hnae3_handle * handle)2311a6d818e3SYunsheng Lin static void hclgevf_client_stop(struct hnae3_handle *handle)
2312a6d818e3SYunsheng Lin {
2313a6d818e3SYunsheng Lin struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
2314a6d818e3SYunsheng Lin int ret;
2315a6d818e3SYunsheng Lin
2316a6d818e3SYunsheng Lin ret = hclgevf_set_alive(handle, false);
2317a6d818e3SYunsheng Lin if (ret)
2318a6d818e3SYunsheng Lin dev_warn(&hdev->pdev->dev,
2319a6d818e3SYunsheng Lin "%s failed %d\n", __func__, ret);
2320a6d818e3SYunsheng Lin }
2321a6d818e3SYunsheng Lin
hclgevf_state_init(struct hclgevf_dev * hdev)2322e2cb1decSSalil Mehta static void hclgevf_state_init(struct hclgevf_dev *hdev)
2323e2cb1decSSalil Mehta {
2324e2cb1decSSalil Mehta clear_bit(HCLGEVF_STATE_MBX_SERVICE_SCHED, &hdev->state);
2325e2cb1decSSalil Mehta clear_bit(HCLGEVF_STATE_MBX_HANDLING, &hdev->state);
2326d5432455SGuojia Liao clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
2327e2cb1decSSalil Mehta
2328b3c3fe8eSYunsheng Lin INIT_DELAYED_WORK(&hdev->service_task, hclgevf_service_task);
2329247fd1e3SJian Shen /* timer needs to be initialized before misc irq */
2330247fd1e3SJian Shen timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0);
233135a1e503SSalil Mehta
2332e2cb1decSSalil Mehta mutex_init(&hdev->mbx_resp.mbx_mutex);
2333f28368bbSHuazhong Tan sema_init(&hdev->reset_sem, 1);
2334e2cb1decSSalil Mehta
2335ee4bcd3bSJian Shen spin_lock_init(&hdev->mac_table.mac_list_lock);
2336ee4bcd3bSJian Shen INIT_LIST_HEAD(&hdev->mac_table.uc_mac_list);
2337ee4bcd3bSJian Shen INIT_LIST_HEAD(&hdev->mac_table.mc_mac_list);
2338ee4bcd3bSJian Shen
2339e2cb1decSSalil Mehta /* bring the device down */
2340e2cb1decSSalil Mehta set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2341e2cb1decSSalil Mehta }
2342e2cb1decSSalil Mehta
hclgevf_state_uninit(struct hclgevf_dev * hdev)2343e2cb1decSSalil Mehta static void hclgevf_state_uninit(struct hclgevf_dev *hdev)
2344e2cb1decSSalil Mehta {
2345e2cb1decSSalil Mehta set_bit(HCLGEVF_STATE_DOWN, &hdev->state);
2346acfc3d55SHuazhong Tan set_bit(HCLGEVF_STATE_REMOVING, &hdev->state);
2347e2cb1decSSalil Mehta
2348b3c3fe8eSYunsheng Lin if (hdev->service_task.work.func)
2349b3c3fe8eSYunsheng Lin cancel_delayed_work_sync(&hdev->service_task);
2350e2cb1decSSalil Mehta
2351e2cb1decSSalil Mehta mutex_destroy(&hdev->mbx_resp.mbx_mutex);
2352e2cb1decSSalil Mehta }
2353e2cb1decSSalil Mehta
hclgevf_init_msi(struct hclgevf_dev * hdev)2354e2cb1decSSalil Mehta static int hclgevf_init_msi(struct hclgevf_dev *hdev)
2355e2cb1decSSalil Mehta {
2356e2cb1decSSalil Mehta struct pci_dev *pdev = hdev->pdev;
2357e2cb1decSSalil Mehta int vectors;
2358e2cb1decSSalil Mehta int i;
2359e2cb1decSSalil Mehta
2360580a05f9SYonglong Liu if (hnae3_dev_roce_supported(hdev))
236107acf909SJian Shen vectors = pci_alloc_irq_vectors(pdev,
236207acf909SJian Shen hdev->roce_base_msix_offset + 1,
236307acf909SJian Shen hdev->num_msi,
236407acf909SJian Shen PCI_IRQ_MSIX);
236507acf909SJian Shen else
2366580a05f9SYonglong Liu vectors = pci_alloc_irq_vectors(pdev, HNAE3_MIN_VECTOR_NUM,
2367580a05f9SYonglong Liu hdev->num_msi,
2368e2cb1decSSalil Mehta PCI_IRQ_MSI | PCI_IRQ_MSIX);
236907acf909SJian Shen
2370e2cb1decSSalil Mehta if (vectors < 0) {
2371e2cb1decSSalil Mehta dev_err(&pdev->dev,
2372e2cb1decSSalil Mehta "failed(%d) to allocate MSI/MSI-X vectors\n",
2373e2cb1decSSalil Mehta vectors);
2374e2cb1decSSalil Mehta return vectors;
2375e2cb1decSSalil Mehta }
2376e2cb1decSSalil Mehta if (vectors < hdev->num_msi)
2377e2cb1decSSalil Mehta dev_warn(&hdev->pdev->dev,
2378adcf738bSGuojia Liao "requested %u MSI/MSI-X, but allocated %d MSI/MSI-X\n",
2379e2cb1decSSalil Mehta hdev->num_msi, vectors);
2380e2cb1decSSalil Mehta
2381e2cb1decSSalil Mehta hdev->num_msi = vectors;
2382e2cb1decSSalil Mehta hdev->num_msi_left = vectors;
2383580a05f9SYonglong Liu
2384e2cb1decSSalil Mehta hdev->vector_status = devm_kcalloc(&pdev->dev, hdev->num_msi,
2385e2cb1decSSalil Mehta sizeof(u16), GFP_KERNEL);
2386e2cb1decSSalil Mehta if (!hdev->vector_status) {
2387e2cb1decSSalil Mehta pci_free_irq_vectors(pdev);
2388e2cb1decSSalil Mehta return -ENOMEM;
2389e2cb1decSSalil Mehta }
2390e2cb1decSSalil Mehta
2391e2cb1decSSalil Mehta for (i = 0; i < hdev->num_msi; i++)
2392e2cb1decSSalil Mehta hdev->vector_status[i] = HCLGEVF_INVALID_VPORT;
2393e2cb1decSSalil Mehta
2394e2cb1decSSalil Mehta hdev->vector_irq = devm_kcalloc(&pdev->dev, hdev->num_msi,
2395e2cb1decSSalil Mehta sizeof(int), GFP_KERNEL);
2396e2cb1decSSalil Mehta if (!hdev->vector_irq) {
2397862d969aSHuazhong Tan devm_kfree(&pdev->dev, hdev->vector_status);
2398e2cb1decSSalil Mehta pci_free_irq_vectors(pdev);
2399e2cb1decSSalil Mehta return -ENOMEM;
2400e2cb1decSSalil Mehta }
2401e2cb1decSSalil Mehta
2402e2cb1decSSalil Mehta return 0;
2403e2cb1decSSalil Mehta }
2404e2cb1decSSalil Mehta
hclgevf_uninit_msi(struct hclgevf_dev * hdev)2405e2cb1decSSalil Mehta static void hclgevf_uninit_msi(struct hclgevf_dev *hdev)
2406e2cb1decSSalil Mehta {
2407e2cb1decSSalil Mehta struct pci_dev *pdev = hdev->pdev;
2408e2cb1decSSalil Mehta
2409862d969aSHuazhong Tan devm_kfree(&pdev->dev, hdev->vector_status);
2410862d969aSHuazhong Tan devm_kfree(&pdev->dev, hdev->vector_irq);
2411e2cb1decSSalil Mehta pci_free_irq_vectors(pdev);
2412e2cb1decSSalil Mehta }
2413e2cb1decSSalil Mehta
hclgevf_misc_irq_init(struct hclgevf_dev * hdev)2414e2cb1decSSalil Mehta static int hclgevf_misc_irq_init(struct hclgevf_dev *hdev)
2415e2cb1decSSalil Mehta {
2416cdd332acSGuojia Liao int ret;
2417e2cb1decSSalil Mehta
2418e2cb1decSSalil Mehta hclgevf_get_misc_vector(hdev);
2419e2cb1decSSalil Mehta
2420f97c4d82SYonglong Liu snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s",
2421f97c4d82SYonglong Liu HCLGEVF_NAME, pci_name(hdev->pdev));
2422e2cb1decSSalil Mehta ret = request_irq(hdev->misc_vector.vector_irq, hclgevf_misc_irq_handle,
2423f97c4d82SYonglong Liu 0, hdev->misc_vector.name, hdev);
2424e2cb1decSSalil Mehta if (ret) {
2425e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev, "VF failed to request misc irq(%d)\n",
2426e2cb1decSSalil Mehta hdev->misc_vector.vector_irq);
2427e2cb1decSSalil Mehta return ret;
2428e2cb1decSSalil Mehta }
2429e2cb1decSSalil Mehta
24301819e409SXi Wang hclgevf_clear_event_cause(hdev, 0);
24311819e409SXi Wang
2432e2cb1decSSalil Mehta /* enable misc. vector(vector 0) */
2433e2cb1decSSalil Mehta hclgevf_enable_vector(&hdev->misc_vector, true);
2434e2cb1decSSalil Mehta
2435e2cb1decSSalil Mehta return ret;
2436e2cb1decSSalil Mehta }
2437e2cb1decSSalil Mehta
hclgevf_misc_irq_uninit(struct hclgevf_dev * hdev)2438e2cb1decSSalil Mehta static void hclgevf_misc_irq_uninit(struct hclgevf_dev *hdev)
2439e2cb1decSSalil Mehta {
2440e2cb1decSSalil Mehta /* disable misc vector(vector 0) */
2441e2cb1decSSalil Mehta hclgevf_enable_vector(&hdev->misc_vector, false);
24421819e409SXi Wang synchronize_irq(hdev->misc_vector.vector_irq);
2443e2cb1decSSalil Mehta free_irq(hdev->misc_vector.vector_irq, hdev);
2444e2cb1decSSalil Mehta hclgevf_free_vector(hdev, 0);
2445e2cb1decSSalil Mehta }
2446e2cb1decSSalil Mehta
hclgevf_info_show(struct hclgevf_dev * hdev)2447bb87be87SYonglong Liu static void hclgevf_info_show(struct hclgevf_dev *hdev)
2448bb87be87SYonglong Liu {
2449bb87be87SYonglong Liu struct device *dev = &hdev->pdev->dev;
2450bb87be87SYonglong Liu
2451bb87be87SYonglong Liu dev_info(dev, "VF info begin:\n");
2452bb87be87SYonglong Liu
2453adcf738bSGuojia Liao dev_info(dev, "Task queue pairs numbers: %u\n", hdev->num_tqps);
2454adcf738bSGuojia Liao dev_info(dev, "Desc num per TX queue: %u\n", hdev->num_tx_desc);
2455adcf738bSGuojia Liao dev_info(dev, "Desc num per RX queue: %u\n", hdev->num_rx_desc);
2456adcf738bSGuojia Liao dev_info(dev, "Numbers of vports: %u\n", hdev->num_alloc_vport);
2457adcf738bSGuojia Liao dev_info(dev, "HW tc map: 0x%x\n", hdev->hw_tc_map);
2458adcf738bSGuojia Liao dev_info(dev, "PF media type of this VF: %u\n",
2459bb87be87SYonglong Liu hdev->hw.mac.media_type);
2460bb87be87SYonglong Liu
2461bb87be87SYonglong Liu dev_info(dev, "VF info end.\n");
2462bb87be87SYonglong Liu }
2463bb87be87SYonglong Liu
hclgevf_init_nic_client_instance(struct hnae3_ae_dev * ae_dev,struct hnae3_client * client)24641db58f86SHuazhong Tan static int hclgevf_init_nic_client_instance(struct hnae3_ae_dev *ae_dev,
24651db58f86SHuazhong Tan struct hnae3_client *client)
24661db58f86SHuazhong Tan {
24671db58f86SHuazhong Tan struct hclgevf_dev *hdev = ae_dev->priv;
24684cd5beaaSGuangbin Huang u32 rst_cnt = hdev->rst_stats.rst_cnt;
24691db58f86SHuazhong Tan int ret;
24701db58f86SHuazhong Tan
24711db58f86SHuazhong Tan ret = client->ops->init_instance(&hdev->nic);
24721db58f86SHuazhong Tan if (ret)
24731db58f86SHuazhong Tan return ret;
24741db58f86SHuazhong Tan
24751db58f86SHuazhong Tan set_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
24764cd5beaaSGuangbin Huang if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
24774cd5beaaSGuangbin Huang rst_cnt != hdev->rst_stats.rst_cnt) {
24784cd5beaaSGuangbin Huang clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
24794cd5beaaSGuangbin Huang
24804cd5beaaSGuangbin Huang client->ops->uninit_instance(&hdev->nic, 0);
24814cd5beaaSGuangbin Huang return -EBUSY;
24824cd5beaaSGuangbin Huang }
24834cd5beaaSGuangbin Huang
24841db58f86SHuazhong Tan hnae3_set_client_init_flag(client, ae_dev, 1);
24851db58f86SHuazhong Tan
24861db58f86SHuazhong Tan if (netif_msg_drv(&hdev->nic))
24871db58f86SHuazhong Tan hclgevf_info_show(hdev);
24881db58f86SHuazhong Tan
24891db58f86SHuazhong Tan return 0;
24901db58f86SHuazhong Tan }
24911db58f86SHuazhong Tan
hclgevf_init_roce_client_instance(struct hnae3_ae_dev * ae_dev,struct hnae3_client * client)24921db58f86SHuazhong Tan static int hclgevf_init_roce_client_instance(struct hnae3_ae_dev *ae_dev,
24931db58f86SHuazhong Tan struct hnae3_client *client)
24941db58f86SHuazhong Tan {
24951db58f86SHuazhong Tan struct hclgevf_dev *hdev = ae_dev->priv;
24961db58f86SHuazhong Tan int ret;
24971db58f86SHuazhong Tan
24981db58f86SHuazhong Tan if (!hnae3_dev_roce_supported(hdev) || !hdev->roce_client ||
24991db58f86SHuazhong Tan !hdev->nic_client)
25001db58f86SHuazhong Tan return 0;
25011db58f86SHuazhong Tan
25021db58f86SHuazhong Tan ret = hclgevf_init_roce_base_info(hdev);
25031db58f86SHuazhong Tan if (ret)
25041db58f86SHuazhong Tan return ret;
25051db58f86SHuazhong Tan
25061db58f86SHuazhong Tan ret = client->ops->init_instance(&hdev->roce);
25071db58f86SHuazhong Tan if (ret)
25081db58f86SHuazhong Tan return ret;
25091db58f86SHuazhong Tan
2510fe735c84SHuazhong Tan set_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state);
25111db58f86SHuazhong Tan hnae3_set_client_init_flag(client, ae_dev, 1);
25121db58f86SHuazhong Tan
25131db58f86SHuazhong Tan return 0;
25141db58f86SHuazhong Tan }
25151db58f86SHuazhong Tan
hclgevf_init_client_instance(struct hnae3_client * client,struct hnae3_ae_dev * ae_dev)2516e718a93fSPeng Li static int hclgevf_init_client_instance(struct hnae3_client *client,
2517e718a93fSPeng Li struct hnae3_ae_dev *ae_dev)
2518e2cb1decSSalil Mehta {
2519e718a93fSPeng Li struct hclgevf_dev *hdev = ae_dev->priv;
2520e2cb1decSSalil Mehta int ret;
2521e2cb1decSSalil Mehta
2522e2cb1decSSalil Mehta switch (client->type) {
2523e2cb1decSSalil Mehta case HNAE3_CLIENT_KNIC:
2524e2cb1decSSalil Mehta hdev->nic_client = client;
2525e2cb1decSSalil Mehta hdev->nic.client = client;
2526e2cb1decSSalil Mehta
25271db58f86SHuazhong Tan ret = hclgevf_init_nic_client_instance(ae_dev, client);
2528e2cb1decSSalil Mehta if (ret)
252949dd8054SJian Shen goto clear_nic;
2530e2cb1decSSalil Mehta
25311db58f86SHuazhong Tan ret = hclgevf_init_roce_client_instance(ae_dev,
25321db58f86SHuazhong Tan hdev->roce_client);
2533e2cb1decSSalil Mehta if (ret)
253449dd8054SJian Shen goto clear_roce;
2535d9f28fc2SJian Shen
2536e2cb1decSSalil Mehta break;
2537e2cb1decSSalil Mehta case HNAE3_CLIENT_ROCE:
2538544a7bcdSLijun Ou if (hnae3_dev_roce_supported(hdev)) {
2539e2cb1decSSalil Mehta hdev->roce_client = client;
2540e2cb1decSSalil Mehta hdev->roce.client = client;
2541544a7bcdSLijun Ou }
2542e2cb1decSSalil Mehta
25431db58f86SHuazhong Tan ret = hclgevf_init_roce_client_instance(ae_dev, client);
2544e2cb1decSSalil Mehta if (ret)
254549dd8054SJian Shen goto clear_roce;
2546e2cb1decSSalil Mehta
2547fa7a4bd5SJian Shen break;
2548fa7a4bd5SJian Shen default:
2549fa7a4bd5SJian Shen return -EINVAL;
2550e2cb1decSSalil Mehta }
2551e2cb1decSSalil Mehta
2552e2cb1decSSalil Mehta return 0;
255349dd8054SJian Shen
255449dd8054SJian Shen clear_nic:
255549dd8054SJian Shen hdev->nic_client = NULL;
255649dd8054SJian Shen hdev->nic.client = NULL;
255749dd8054SJian Shen return ret;
255849dd8054SJian Shen clear_roce:
255949dd8054SJian Shen hdev->roce_client = NULL;
256049dd8054SJian Shen hdev->roce.client = NULL;
256149dd8054SJian Shen return ret;
2562e2cb1decSSalil Mehta }
2563e2cb1decSSalil Mehta
hclgevf_uninit_client_instance(struct hnae3_client * client,struct hnae3_ae_dev * ae_dev)2564e718a93fSPeng Li static void hclgevf_uninit_client_instance(struct hnae3_client *client,
2565e718a93fSPeng Li struct hnae3_ae_dev *ae_dev)
2566e2cb1decSSalil Mehta {
2567e718a93fSPeng Li struct hclgevf_dev *hdev = ae_dev->priv;
2568e718a93fSPeng Li
2569e2cb1decSSalil Mehta /* un-init roce, if it exists */
257049dd8054SJian Shen if (hdev->roce_client) {
2571e140c798SYufeng Mo while (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
2572e140c798SYufeng Mo msleep(HCLGEVF_WAIT_RESET_DONE);
2573fe735c84SHuazhong Tan clear_bit(HCLGEVF_STATE_ROCE_REGISTERED, &hdev->state);
2574e140c798SYufeng Mo
2575e2cb1decSSalil Mehta hdev->roce_client->ops->uninit_instance(&hdev->roce, 0);
257649dd8054SJian Shen hdev->roce_client = NULL;
257749dd8054SJian Shen hdev->roce.client = NULL;
257849dd8054SJian Shen }
2579e2cb1decSSalil Mehta
2580e2cb1decSSalil Mehta /* un-init nic/unic, if this was not called by roce client */
258149dd8054SJian Shen if (client->ops->uninit_instance && hdev->nic_client &&
258249dd8054SJian Shen client->type != HNAE3_CLIENT_ROCE) {
2583e140c798SYufeng Mo while (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state))
2584e140c798SYufeng Mo msleep(HCLGEVF_WAIT_RESET_DONE);
258525d1817cSHuazhong Tan clear_bit(HCLGEVF_STATE_NIC_REGISTERED, &hdev->state);
258625d1817cSHuazhong Tan
2587e2cb1decSSalil Mehta client->ops->uninit_instance(&hdev->nic, 0);
258849dd8054SJian Shen hdev->nic_client = NULL;
258949dd8054SJian Shen hdev->nic.client = NULL;
259049dd8054SJian Shen }
2591e2cb1decSSalil Mehta }
2592e2cb1decSSalil Mehta
hclgevf_dev_mem_map(struct hclgevf_dev * hdev)259330ae7f8aSHuazhong Tan static int hclgevf_dev_mem_map(struct hclgevf_dev *hdev)
259430ae7f8aSHuazhong Tan {
259530ae7f8aSHuazhong Tan struct pci_dev *pdev = hdev->pdev;
259630ae7f8aSHuazhong Tan struct hclgevf_hw *hw = &hdev->hw;
259730ae7f8aSHuazhong Tan
259830ae7f8aSHuazhong Tan /* for device does not have device memory, return directly */
259930ae7f8aSHuazhong Tan if (!(pci_select_bars(pdev, IORESOURCE_MEM) & BIT(HCLGEVF_MEM_BAR)))
260030ae7f8aSHuazhong Tan return 0;
260130ae7f8aSHuazhong Tan
2602076bb537SJie Wang hw->hw.mem_base =
2603076bb537SJie Wang devm_ioremap_wc(&pdev->dev,
2604076bb537SJie Wang pci_resource_start(pdev, HCLGEVF_MEM_BAR),
260530ae7f8aSHuazhong Tan pci_resource_len(pdev, HCLGEVF_MEM_BAR));
2606076bb537SJie Wang if (!hw->hw.mem_base) {
2607be419fcaSColin Ian King dev_err(&pdev->dev, "failed to map device memory\n");
260830ae7f8aSHuazhong Tan return -EFAULT;
260930ae7f8aSHuazhong Tan }
261030ae7f8aSHuazhong Tan
261130ae7f8aSHuazhong Tan return 0;
261230ae7f8aSHuazhong Tan }
261330ae7f8aSHuazhong Tan
hclgevf_pci_init(struct hclgevf_dev * hdev)2614e2cb1decSSalil Mehta static int hclgevf_pci_init(struct hclgevf_dev *hdev)
2615e2cb1decSSalil Mehta {
2616e2cb1decSSalil Mehta struct pci_dev *pdev = hdev->pdev;
2617e2cb1decSSalil Mehta struct hclgevf_hw *hw;
2618e2cb1decSSalil Mehta int ret;
2619e2cb1decSSalil Mehta
2620e2cb1decSSalil Mehta ret = pci_enable_device(pdev);
2621e2cb1decSSalil Mehta if (ret) {
2622e2cb1decSSalil Mehta dev_err(&pdev->dev, "failed to enable PCI device\n");
26233e249d3bSFuyun Liang return ret;
2624e2cb1decSSalil Mehta }
2625e2cb1decSSalil Mehta
2626e2cb1decSSalil Mehta ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
2627e2cb1decSSalil Mehta if (ret) {
2628e2cb1decSSalil Mehta dev_err(&pdev->dev, "can't set consistent PCI DMA, exiting\n");
2629e2cb1decSSalil Mehta goto err_disable_device;
2630e2cb1decSSalil Mehta }
2631e2cb1decSSalil Mehta
2632e2cb1decSSalil Mehta ret = pci_request_regions(pdev, HCLGEVF_DRIVER_NAME);
2633e2cb1decSSalil Mehta if (ret) {
2634e2cb1decSSalil Mehta dev_err(&pdev->dev, "PCI request regions failed %d\n", ret);
2635e2cb1decSSalil Mehta goto err_disable_device;
2636e2cb1decSSalil Mehta }
2637e2cb1decSSalil Mehta
2638e2cb1decSSalil Mehta pci_set_master(pdev);
2639e2cb1decSSalil Mehta hw = &hdev->hw;
2640076bb537SJie Wang hw->hw.io_base = pci_iomap(pdev, 2, 0);
2641076bb537SJie Wang if (!hw->hw.io_base) {
2642e2cb1decSSalil Mehta dev_err(&pdev->dev, "can't map configuration register space\n");
2643e2cb1decSSalil Mehta ret = -ENOMEM;
2644fc3e07e8SCai Huoqing goto err_release_regions;
2645e2cb1decSSalil Mehta }
2646e2cb1decSSalil Mehta
264730ae7f8aSHuazhong Tan ret = hclgevf_dev_mem_map(hdev);
264830ae7f8aSHuazhong Tan if (ret)
264930ae7f8aSHuazhong Tan goto err_unmap_io_base;
265030ae7f8aSHuazhong Tan
2651e2cb1decSSalil Mehta return 0;
2652e2cb1decSSalil Mehta
265330ae7f8aSHuazhong Tan err_unmap_io_base:
2654076bb537SJie Wang pci_iounmap(pdev, hdev->hw.hw.io_base);
2655fc3e07e8SCai Huoqing err_release_regions:
2656e2cb1decSSalil Mehta pci_release_regions(pdev);
2657e2cb1decSSalil Mehta err_disable_device:
2658e2cb1decSSalil Mehta pci_disable_device(pdev);
26593e249d3bSFuyun Liang
2660e2cb1decSSalil Mehta return ret;
2661e2cb1decSSalil Mehta }
2662e2cb1decSSalil Mehta
hclgevf_pci_uninit(struct hclgevf_dev * hdev)2663e2cb1decSSalil Mehta static void hclgevf_pci_uninit(struct hclgevf_dev *hdev)
2664e2cb1decSSalil Mehta {
2665e2cb1decSSalil Mehta struct pci_dev *pdev = hdev->pdev;
2666e2cb1decSSalil Mehta
2667076bb537SJie Wang if (hdev->hw.hw.mem_base)
2668076bb537SJie Wang devm_iounmap(&pdev->dev, hdev->hw.hw.mem_base);
266930ae7f8aSHuazhong Tan
2670076bb537SJie Wang pci_iounmap(pdev, hdev->hw.hw.io_base);
2671e2cb1decSSalil Mehta pci_release_regions(pdev);
2672e2cb1decSSalil Mehta pci_disable_device(pdev);
2673e2cb1decSSalil Mehta }
2674e2cb1decSSalil Mehta
hclgevf_query_vf_resource(struct hclgevf_dev * hdev)267507acf909SJian Shen static int hclgevf_query_vf_resource(struct hclgevf_dev *hdev)
267607acf909SJian Shen {
267707acf909SJian Shen struct hclgevf_query_res_cmd *req;
26786befad60SJie Wang struct hclge_desc desc;
267907acf909SJian Shen int ret;
268007acf909SJian Shen
268143710bfeSJie Wang hclgevf_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_VF_RSRC, true);
268207acf909SJian Shen ret = hclgevf_cmd_send(&hdev->hw, &desc, 1);
268307acf909SJian Shen if (ret) {
268407acf909SJian Shen dev_err(&hdev->pdev->dev,
268507acf909SJian Shen "query vf resource failed, ret = %d.\n", ret);
268607acf909SJian Shen return ret;
268707acf909SJian Shen }
268807acf909SJian Shen
268907acf909SJian Shen req = (struct hclgevf_query_res_cmd *)desc.data;
269007acf909SJian Shen
2691580a05f9SYonglong Liu if (hnae3_dev_roce_supported(hdev)) {
269207acf909SJian Shen hdev->roce_base_msix_offset =
269360df7e91SHuazhong Tan hnae3_get_field(le16_to_cpu(req->msixcap_localid_ba_rocee),
269407acf909SJian Shen HCLGEVF_MSIX_OFT_ROCEE_M,
269507acf909SJian Shen HCLGEVF_MSIX_OFT_ROCEE_S);
269607acf909SJian Shen hdev->num_roce_msix =
269760df7e91SHuazhong Tan hnae3_get_field(le16_to_cpu(req->vf_intr_vector_number),
269807acf909SJian Shen HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
269907acf909SJian Shen
2700580a05f9SYonglong Liu /* nic's msix numbers is always equals to the roce's. */
2701580a05f9SYonglong Liu hdev->num_nic_msix = hdev->num_roce_msix;
2702580a05f9SYonglong Liu
270307acf909SJian Shen /* VF should have NIC vectors and Roce vectors, NIC vectors
270407acf909SJian Shen * are queued before Roce vectors. The offset is fixed to 64.
270507acf909SJian Shen */
270607acf909SJian Shen hdev->num_msi = hdev->num_roce_msix +
270707acf909SJian Shen hdev->roce_base_msix_offset;
270807acf909SJian Shen } else {
270907acf909SJian Shen hdev->num_msi =
271060df7e91SHuazhong Tan hnae3_get_field(le16_to_cpu(req->vf_intr_vector_number),
271107acf909SJian Shen HCLGEVF_VEC_NUM_M, HCLGEVF_VEC_NUM_S);
2712580a05f9SYonglong Liu
2713580a05f9SYonglong Liu hdev->num_nic_msix = hdev->num_msi;
2714580a05f9SYonglong Liu }
2715580a05f9SYonglong Liu
2716580a05f9SYonglong Liu if (hdev->num_nic_msix < HNAE3_MIN_VECTOR_NUM) {
2717580a05f9SYonglong Liu dev_err(&hdev->pdev->dev,
2718580a05f9SYonglong Liu "Just %u msi resources, not enough for vf(min:2).\n",
2719580a05f9SYonglong Liu hdev->num_nic_msix);
2720580a05f9SYonglong Liu return -EINVAL;
272107acf909SJian Shen }
272207acf909SJian Shen
272307acf909SJian Shen return 0;
272407acf909SJian Shen }
272507acf909SJian Shen
hclgevf_set_default_dev_specs(struct hclgevf_dev * hdev)2726af2aedc5SGuangbin Huang static void hclgevf_set_default_dev_specs(struct hclgevf_dev *hdev)
2727af2aedc5SGuangbin Huang {
2728af2aedc5SGuangbin Huang #define HCLGEVF_MAX_NON_TSO_BD_NUM 8U
2729af2aedc5SGuangbin Huang
2730af2aedc5SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
2731af2aedc5SGuangbin Huang
2732af2aedc5SGuangbin Huang ae_dev->dev_specs.max_non_tso_bd_num =
2733af2aedc5SGuangbin Huang HCLGEVF_MAX_NON_TSO_BD_NUM;
2734af2aedc5SGuangbin Huang ae_dev->dev_specs.rss_ind_tbl_size = HCLGEVF_RSS_IND_TBL_SIZE;
27357428d6c9SJie Wang ae_dev->dev_specs.rss_key_size = HCLGE_COMM_RSS_KEY_SIZE;
2736ab16b49cSHuazhong Tan ae_dev->dev_specs.max_int_gl = HCLGEVF_DEF_MAX_INT_GL;
2737e070c8b9SYufeng Mo ae_dev->dev_specs.max_frm_size = HCLGEVF_MAC_MAX_FRAME;
2738af2aedc5SGuangbin Huang }
2739af2aedc5SGuangbin Huang
hclgevf_parse_dev_specs(struct hclgevf_dev * hdev,struct hclge_desc * desc)2740af2aedc5SGuangbin Huang static void hclgevf_parse_dev_specs(struct hclgevf_dev *hdev,
27416befad60SJie Wang struct hclge_desc *desc)
2742af2aedc5SGuangbin Huang {
2743af2aedc5SGuangbin Huang struct hnae3_ae_dev *ae_dev = pci_get_drvdata(hdev->pdev);
2744af2aedc5SGuangbin Huang struct hclgevf_dev_specs_0_cmd *req0;
2745ab16b49cSHuazhong Tan struct hclgevf_dev_specs_1_cmd *req1;
2746af2aedc5SGuangbin Huang
2747af2aedc5SGuangbin Huang req0 = (struct hclgevf_dev_specs_0_cmd *)desc[0].data;
2748ab16b49cSHuazhong Tan req1 = (struct hclgevf_dev_specs_1_cmd *)desc[1].data;
2749af2aedc5SGuangbin Huang
2750af2aedc5SGuangbin Huang ae_dev->dev_specs.max_non_tso_bd_num = req0->max_non_tso_bd_num;
2751af2aedc5SGuangbin Huang ae_dev->dev_specs.rss_ind_tbl_size =
2752af2aedc5SGuangbin Huang le16_to_cpu(req0->rss_ind_tbl_size);
275391bfae25SHuazhong Tan ae_dev->dev_specs.int_ql_max = le16_to_cpu(req0->int_ql_max);
2754af2aedc5SGuangbin Huang ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size);
2755ab16b49cSHuazhong Tan ae_dev->dev_specs.max_int_gl = le16_to_cpu(req1->max_int_gl);
2756e070c8b9SYufeng Mo ae_dev->dev_specs.max_frm_size = le16_to_cpu(req1->max_frm_size);
2757af2aedc5SGuangbin Huang }
2758af2aedc5SGuangbin Huang
hclgevf_check_dev_specs(struct hclgevf_dev * hdev)275913297028SGuangbin Huang static void hclgevf_check_dev_specs(struct hclgevf_dev *hdev)
276013297028SGuangbin Huang {
276113297028SGuangbin Huang struct hnae3_dev_specs *dev_specs = &hdev->ae_dev->dev_specs;
276213297028SGuangbin Huang
276313297028SGuangbin Huang if (!dev_specs->max_non_tso_bd_num)
276413297028SGuangbin Huang dev_specs->max_non_tso_bd_num = HCLGEVF_MAX_NON_TSO_BD_NUM;
276513297028SGuangbin Huang if (!dev_specs->rss_ind_tbl_size)
276613297028SGuangbin Huang dev_specs->rss_ind_tbl_size = HCLGEVF_RSS_IND_TBL_SIZE;
276713297028SGuangbin Huang if (!dev_specs->rss_key_size)
27687428d6c9SJie Wang dev_specs->rss_key_size = HCLGE_COMM_RSS_KEY_SIZE;
2769ab16b49cSHuazhong Tan if (!dev_specs->max_int_gl)
2770ab16b49cSHuazhong Tan dev_specs->max_int_gl = HCLGEVF_DEF_MAX_INT_GL;
2771e070c8b9SYufeng Mo if (!dev_specs->max_frm_size)
2772e070c8b9SYufeng Mo dev_specs->max_frm_size = HCLGEVF_MAC_MAX_FRAME;
277313297028SGuangbin Huang }
277413297028SGuangbin Huang
hclgevf_query_dev_specs(struct hclgevf_dev * hdev)2775af2aedc5SGuangbin Huang static int hclgevf_query_dev_specs(struct hclgevf_dev *hdev)
2776af2aedc5SGuangbin Huang {
27776befad60SJie Wang struct hclge_desc desc[HCLGEVF_QUERY_DEV_SPECS_BD_NUM];
2778af2aedc5SGuangbin Huang int ret;
2779af2aedc5SGuangbin Huang int i;
2780af2aedc5SGuangbin Huang
2781af2aedc5SGuangbin Huang /* set default specifications as devices lower than version V3 do not
2782af2aedc5SGuangbin Huang * support querying specifications from firmware.
2783af2aedc5SGuangbin Huang */
2784af2aedc5SGuangbin Huang if (hdev->ae_dev->dev_version < HNAE3_DEVICE_VERSION_V3) {
2785af2aedc5SGuangbin Huang hclgevf_set_default_dev_specs(hdev);
2786af2aedc5SGuangbin Huang return 0;
2787af2aedc5SGuangbin Huang }
2788af2aedc5SGuangbin Huang
2789af2aedc5SGuangbin Huang for (i = 0; i < HCLGEVF_QUERY_DEV_SPECS_BD_NUM - 1; i++) {
2790af2aedc5SGuangbin Huang hclgevf_cmd_setup_basic_desc(&desc[i],
279143710bfeSJie Wang HCLGE_OPC_QUERY_DEV_SPECS, true);
2792cb413bfaSJie Wang desc[i].flag |= cpu_to_le16(HCLGE_COMM_CMD_FLAG_NEXT);
2793af2aedc5SGuangbin Huang }
279443710bfeSJie Wang hclgevf_cmd_setup_basic_desc(&desc[i], HCLGE_OPC_QUERY_DEV_SPECS, true);
2795af2aedc5SGuangbin Huang
2796af2aedc5SGuangbin Huang ret = hclgevf_cmd_send(&hdev->hw, desc, HCLGEVF_QUERY_DEV_SPECS_BD_NUM);
2797af2aedc5SGuangbin Huang if (ret)
2798af2aedc5SGuangbin Huang return ret;
2799af2aedc5SGuangbin Huang
2800af2aedc5SGuangbin Huang hclgevf_parse_dev_specs(hdev, desc);
280113297028SGuangbin Huang hclgevf_check_dev_specs(hdev);
2802af2aedc5SGuangbin Huang
2803af2aedc5SGuangbin Huang return 0;
2804af2aedc5SGuangbin Huang }
2805af2aedc5SGuangbin Huang
hclgevf_pci_reset(struct hclgevf_dev * hdev)2806862d969aSHuazhong Tan static int hclgevf_pci_reset(struct hclgevf_dev *hdev)
2807862d969aSHuazhong Tan {
2808862d969aSHuazhong Tan struct pci_dev *pdev = hdev->pdev;
2809862d969aSHuazhong Tan int ret = 0;
2810862d969aSHuazhong Tan
281109e6b30eSJie Wang if ((hdev->reset_type == HNAE3_VF_FULL_RESET ||
281209e6b30eSJie Wang hdev->reset_type == HNAE3_FLR_RESET) &&
2813862d969aSHuazhong Tan test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
2814862d969aSHuazhong Tan hclgevf_misc_irq_uninit(hdev);
2815862d969aSHuazhong Tan hclgevf_uninit_msi(hdev);
2816862d969aSHuazhong Tan clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
2817862d969aSHuazhong Tan }
2818862d969aSHuazhong Tan
2819862d969aSHuazhong Tan if (!test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
2820862d969aSHuazhong Tan pci_set_master(pdev);
2821862d969aSHuazhong Tan ret = hclgevf_init_msi(hdev);
2822862d969aSHuazhong Tan if (ret) {
2823862d969aSHuazhong Tan dev_err(&pdev->dev,
2824862d969aSHuazhong Tan "failed(%d) to init MSI/MSI-X\n", ret);
2825862d969aSHuazhong Tan return ret;
2826862d969aSHuazhong Tan }
2827862d969aSHuazhong Tan
2828862d969aSHuazhong Tan ret = hclgevf_misc_irq_init(hdev);
2829862d969aSHuazhong Tan if (ret) {
2830862d969aSHuazhong Tan hclgevf_uninit_msi(hdev);
2831862d969aSHuazhong Tan dev_err(&pdev->dev, "failed(%d) to init Misc IRQ(vector0)\n",
2832862d969aSHuazhong Tan ret);
2833862d969aSHuazhong Tan return ret;
2834862d969aSHuazhong Tan }
2835862d969aSHuazhong Tan
2836862d969aSHuazhong Tan set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
2837862d969aSHuazhong Tan }
2838862d969aSHuazhong Tan
2839862d969aSHuazhong Tan return ret;
2840862d969aSHuazhong Tan }
2841862d969aSHuazhong Tan
hclgevf_clear_vport_list(struct hclgevf_dev * hdev)2842039ba863SJian Shen static int hclgevf_clear_vport_list(struct hclgevf_dev *hdev)
2843039ba863SJian Shen {
2844039ba863SJian Shen struct hclge_vf_to_pf_msg send_msg;
2845039ba863SJian Shen
2846039ba863SJian Shen hclgevf_build_send_msg(&send_msg, HCLGE_MBX_HANDLE_VF_TBL,
2847039ba863SJian Shen HCLGE_MBX_VPORT_LIST_CLEAR);
2848039ba863SJian Shen return hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
2849039ba863SJian Shen }
2850039ba863SJian Shen
hclgevf_init_rxd_adv_layout(struct hclgevf_dev * hdev)285179664077SHuazhong Tan static void hclgevf_init_rxd_adv_layout(struct hclgevf_dev *hdev)
285279664077SHuazhong Tan {
285379664077SHuazhong Tan if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev))
285479664077SHuazhong Tan hclgevf_write_dev(&hdev->hw, HCLGEVF_RXD_ADV_LAYOUT_EN_REG, 1);
285579664077SHuazhong Tan }
285679664077SHuazhong Tan
hclgevf_uninit_rxd_adv_layout(struct hclgevf_dev * hdev)285779664077SHuazhong Tan static void hclgevf_uninit_rxd_adv_layout(struct hclgevf_dev *hdev)
285879664077SHuazhong Tan {
285979664077SHuazhong Tan if (hnae3_ae_dev_rxd_adv_layout_supported(hdev->ae_dev))
286079664077SHuazhong Tan hclgevf_write_dev(&hdev->hw, HCLGEVF_RXD_ADV_LAYOUT_EN_REG, 0);
286179664077SHuazhong Tan }
286279664077SHuazhong Tan
hclgevf_reset_hdev(struct hclgevf_dev * hdev)28639c6f7085SHuazhong Tan static int hclgevf_reset_hdev(struct hclgevf_dev *hdev)
2864e2cb1decSSalil Mehta {
28657a01c897SSalil Mehta struct pci_dev *pdev = hdev->pdev;
2866e2cb1decSSalil Mehta int ret;
2867e2cb1decSSalil Mehta
2868862d969aSHuazhong Tan ret = hclgevf_pci_reset(hdev);
2869862d969aSHuazhong Tan if (ret) {
2870862d969aSHuazhong Tan dev_err(&pdev->dev, "pci reset failed %d\n", ret);
2871862d969aSHuazhong Tan return ret;
2872862d969aSHuazhong Tan }
2873862d969aSHuazhong Tan
2874cb413bfaSJie Wang hclgevf_arq_init(hdev);
28752a1a1a7bSHao Lan
2876cb413bfaSJie Wang ret = hclge_comm_cmd_init(hdev->ae_dev, &hdev->hw.hw,
2877cb413bfaSJie Wang &hdev->fw_version, false,
2878cb413bfaSJie Wang hdev->reset_pending);
28799c6f7085SHuazhong Tan if (ret) {
28809c6f7085SHuazhong Tan dev_err(&pdev->dev, "cmd failed %d\n", ret);
28819c6f7085SHuazhong Tan return ret;
28827a01c897SSalil Mehta }
2883e2cb1decSSalil Mehta
28849c6f7085SHuazhong Tan ret = hclgevf_rss_init_hw(hdev);
28859c6f7085SHuazhong Tan if (ret) {
28869c6f7085SHuazhong Tan dev_err(&hdev->pdev->dev,
28879c6f7085SHuazhong Tan "failed(%d) to initialize RSS\n", ret);
28889c6f7085SHuazhong Tan return ret;
28899c6f7085SHuazhong Tan }
28909c6f7085SHuazhong Tan
28913462207dSYufeng Mo ret = hclgevf_config_gro(hdev);
2892b26a6feaSPeng Li if (ret)
2893b26a6feaSPeng Li return ret;
2894b26a6feaSPeng Li
2895ef2383d0SJian Shen ret = hclgevf_init_vlan_config(hdev, hdev->rxvtag_strip_en);
28969c6f7085SHuazhong Tan if (ret) {
28979c6f7085SHuazhong Tan dev_err(&hdev->pdev->dev,
28989c6f7085SHuazhong Tan "failed(%d) to initialize VLAN config\n", ret);
28999c6f7085SHuazhong Tan return ret;
29009c6f7085SHuazhong Tan }
29019c6f7085SHuazhong Tan
2902190cd8a7SJian Shen /* get current port based vlan state from PF */
2903190cd8a7SJian Shen ret = hclgevf_get_port_base_vlan_filter_state(hdev);
2904190cd8a7SJian Shen if (ret)
2905190cd8a7SJian Shen return ret;
2906190cd8a7SJian Shen
2907c631c696SJian Shen set_bit(HCLGEVF_STATE_PROMISC_CHANGED, &hdev->state);
2908c631c696SJian Shen
290979664077SHuazhong Tan hclgevf_init_rxd_adv_layout(hdev);
291079664077SHuazhong Tan
29119c6f7085SHuazhong Tan dev_info(&hdev->pdev->dev, "Reset done\n");
29129c6f7085SHuazhong Tan
29139c6f7085SHuazhong Tan return 0;
29149c6f7085SHuazhong Tan }
29159c6f7085SHuazhong Tan
hclgevf_init_hdev(struct hclgevf_dev * hdev)29169c6f7085SHuazhong Tan static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
29179c6f7085SHuazhong Tan {
29189c6f7085SHuazhong Tan struct pci_dev *pdev = hdev->pdev;
29199c6f7085SHuazhong Tan int ret;
29209c6f7085SHuazhong Tan
2921e2cb1decSSalil Mehta ret = hclgevf_pci_init(hdev);
292260df7e91SHuazhong Tan if (ret)
2923e2cb1decSSalil Mehta return ret;
2924e2cb1decSSalil Mehta
2925cb413bfaSJie Wang ret = hclge_comm_cmd_queue_init(hdev->pdev, &hdev->hw.hw);
292660df7e91SHuazhong Tan if (ret)
29278b0195a3SHuazhong Tan goto err_cmd_queue_init;
29288b0195a3SHuazhong Tan
2929cb413bfaSJie Wang hclgevf_arq_init(hdev);
29302a1a1a7bSHao Lan
29312a1a1a7bSHao Lan hclge_comm_cmd_init_ops(&hdev->hw.hw, &hclgevf_cmq_ops);
2932cb413bfaSJie Wang ret = hclge_comm_cmd_init(hdev->ae_dev, &hdev->hw.hw,
2933cb413bfaSJie Wang &hdev->fw_version, false,
2934cb413bfaSJie Wang hdev->reset_pending);
2935eddf0462SYunsheng Lin if (ret)
2936eddf0462SYunsheng Lin goto err_cmd_init;
2937eddf0462SYunsheng Lin
293807acf909SJian Shen /* Get vf resource */
293907acf909SJian Shen ret = hclgevf_query_vf_resource(hdev);
294060df7e91SHuazhong Tan if (ret)
29418b0195a3SHuazhong Tan goto err_cmd_init;
294207acf909SJian Shen
2943af2aedc5SGuangbin Huang ret = hclgevf_query_dev_specs(hdev);
2944af2aedc5SGuangbin Huang if (ret) {
2945af2aedc5SGuangbin Huang dev_err(&pdev->dev,
2946af2aedc5SGuangbin Huang "failed to query dev specifications, ret = %d\n", ret);
2947af2aedc5SGuangbin Huang goto err_cmd_init;
2948af2aedc5SGuangbin Huang }
2949af2aedc5SGuangbin Huang
295007acf909SJian Shen ret = hclgevf_init_msi(hdev);
295107acf909SJian Shen if (ret) {
295207acf909SJian Shen dev_err(&pdev->dev, "failed(%d) to init MSI/MSI-X\n", ret);
29538b0195a3SHuazhong Tan goto err_cmd_init;
295407acf909SJian Shen }
295507acf909SJian Shen
295607acf909SJian Shen hclgevf_state_init(hdev);
2957dea846e8SHuazhong Tan hdev->reset_level = HNAE3_VF_FUNC_RESET;
2958afb6afdbSHuazhong Tan hdev->reset_type = HNAE3_NONE_RESET;
295907acf909SJian Shen
2960e2cb1decSSalil Mehta ret = hclgevf_misc_irq_init(hdev);
296160df7e91SHuazhong Tan if (ret)
2962e2cb1decSSalil Mehta goto err_misc_irq_init;
2963e2cb1decSSalil Mehta
2964862d969aSHuazhong Tan set_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
2965862d969aSHuazhong Tan
2966e2cb1decSSalil Mehta ret = hclgevf_configure(hdev);
2967e2cb1decSSalil Mehta if (ret) {
2968e2cb1decSSalil Mehta dev_err(&pdev->dev, "failed(%d) to fetch configuration\n", ret);
2969e2cb1decSSalil Mehta goto err_config;
2970e2cb1decSSalil Mehta }
2971e2cb1decSSalil Mehta
2972e2cb1decSSalil Mehta ret = hclgevf_alloc_tqps(hdev);
2973e2cb1decSSalil Mehta if (ret) {
2974e2cb1decSSalil Mehta dev_err(&pdev->dev, "failed(%d) to allocate TQPs\n", ret);
2975e2cb1decSSalil Mehta goto err_config;
2976e2cb1decSSalil Mehta }
2977e2cb1decSSalil Mehta
2978e2cb1decSSalil Mehta ret = hclgevf_set_handle_info(hdev);
297960df7e91SHuazhong Tan if (ret)
2980e2cb1decSSalil Mehta goto err_config;
2981e2cb1decSSalil Mehta
29823462207dSYufeng Mo ret = hclgevf_config_gro(hdev);
2983b26a6feaSPeng Li if (ret)
2984b26a6feaSPeng Li goto err_config;
2985b26a6feaSPeng Li
2986e2cb1decSSalil Mehta /* Initialize RSS for this VF */
298793969dc1SJie Wang ret = hclge_comm_rss_init_cfg(&hdev->nic, hdev->ae_dev,
298893969dc1SJie Wang &hdev->rss_cfg);
298987ce161eSGuangbin Huang if (ret) {
299087ce161eSGuangbin Huang dev_err(&pdev->dev, "failed to init rss cfg, ret = %d\n", ret);
299187ce161eSGuangbin Huang goto err_config;
299287ce161eSGuangbin Huang }
299387ce161eSGuangbin Huang
2994e2cb1decSSalil Mehta ret = hclgevf_rss_init_hw(hdev);
2995e2cb1decSSalil Mehta if (ret) {
2996e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
2997e2cb1decSSalil Mehta "failed(%d) to initialize RSS\n", ret);
2998e2cb1decSSalil Mehta goto err_config;
2999e2cb1decSSalil Mehta }
3000e2cb1decSSalil Mehta
3001039ba863SJian Shen /* ensure vf tbl list as empty before init */
3002039ba863SJian Shen ret = hclgevf_clear_vport_list(hdev);
3003039ba863SJian Shen if (ret) {
3004039ba863SJian Shen dev_err(&pdev->dev,
3005039ba863SJian Shen "failed to clear tbl list configuration, ret = %d.\n",
3006039ba863SJian Shen ret);
3007039ba863SJian Shen goto err_config;
3008039ba863SJian Shen }
3009039ba863SJian Shen
3010ef2383d0SJian Shen ret = hclgevf_init_vlan_config(hdev, true);
3011e2cb1decSSalil Mehta if (ret) {
3012e2cb1decSSalil Mehta dev_err(&hdev->pdev->dev,
3013e2cb1decSSalil Mehta "failed(%d) to initialize VLAN config\n", ret);
3014e2cb1decSSalil Mehta goto err_config;
3015e2cb1decSSalil Mehta }
3016e2cb1decSSalil Mehta
301779664077SHuazhong Tan hclgevf_init_rxd_adv_layout(hdev);
301879664077SHuazhong Tan
301935d92abfSYonglong Liu ret = hclgevf_devlink_init(hdev);
302035d92abfSYonglong Liu if (ret)
302135d92abfSYonglong Liu goto err_config;
302235d92abfSYonglong Liu
30230251d196SGuangbin Huang set_bit(HCLGEVF_STATE_SERVICE_INITED, &hdev->state);
30240251d196SGuangbin Huang
30250742ed7cSHuazhong Tan hdev->last_reset_time = jiffies;
302608d80a4cSHuazhong Tan dev_info(&hdev->pdev->dev, "finished initializing %s driver\n",
302708d80a4cSHuazhong Tan HCLGEVF_DRIVER_NAME);
3028e2cb1decSSalil Mehta
3029ff200099SYunsheng Lin hclgevf_task_schedule(hdev, round_jiffies_relative(HZ));
3030ff200099SYunsheng Lin
3031e2cb1decSSalil Mehta return 0;
3032e2cb1decSSalil Mehta
3033e2cb1decSSalil Mehta err_config:
3034e2cb1decSSalil Mehta hclgevf_misc_irq_uninit(hdev);
3035e2cb1decSSalil Mehta err_misc_irq_init:
3036e2cb1decSSalil Mehta hclgevf_state_uninit(hdev);
3037e2cb1decSSalil Mehta hclgevf_uninit_msi(hdev);
303807acf909SJian Shen err_cmd_init:
30399970308fSJie Wang hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
30408b0195a3SHuazhong Tan err_cmd_queue_init:
3041e2cb1decSSalil Mehta hclgevf_pci_uninit(hdev);
3042862d969aSHuazhong Tan clear_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state);
3043e2cb1decSSalil Mehta return ret;
3044e2cb1decSSalil Mehta }
3045e2cb1decSSalil Mehta
hclgevf_uninit_hdev(struct hclgevf_dev * hdev)30467a01c897SSalil Mehta static void hclgevf_uninit_hdev(struct hclgevf_dev *hdev)
3047e2cb1decSSalil Mehta {
3048d3410018SYufeng Mo struct hclge_vf_to_pf_msg send_msg;
3049d3410018SYufeng Mo
3050e2cb1decSSalil Mehta hclgevf_state_uninit(hdev);
305179664077SHuazhong Tan hclgevf_uninit_rxd_adv_layout(hdev);
3052862d969aSHuazhong Tan
3053d3410018SYufeng Mo hclgevf_build_send_msg(&send_msg, HCLGE_MBX_VF_UNINIT, 0);
3054d3410018SYufeng Mo hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
305523b4201dSJian Shen
3056862d969aSHuazhong Tan if (test_bit(HCLGEVF_STATE_IRQ_INITED, &hdev->state)) {
3057eddf0462SYunsheng Lin hclgevf_misc_irq_uninit(hdev);
3058e2cb1decSSalil Mehta hclgevf_uninit_msi(hdev);
30597a01c897SSalil Mehta }
30607a01c897SSalil Mehta
30619970308fSJie Wang hclge_comm_cmd_uninit(hdev->ae_dev, &hdev->hw.hw);
3062cd624299SYufeng Mo hclgevf_devlink_uninit(hdev);
3063e3364c5fSZenghui Yu hclgevf_pci_uninit(hdev);
3064ee4bcd3bSJian Shen hclgevf_uninit_mac_list(hdev);
3065862d969aSHuazhong Tan }
3066862d969aSHuazhong Tan
hclgevf_init_ae_dev(struct hnae3_ae_dev * ae_dev)30677a01c897SSalil Mehta static int hclgevf_init_ae_dev(struct hnae3_ae_dev *ae_dev)
30687a01c897SSalil Mehta {
30697a01c897SSalil Mehta struct pci_dev *pdev = ae_dev->pdev;
30707a01c897SSalil Mehta int ret;
30717a01c897SSalil Mehta
30727a01c897SSalil Mehta ret = hclgevf_alloc_hdev(ae_dev);
30737a01c897SSalil Mehta if (ret) {
30747a01c897SSalil Mehta dev_err(&pdev->dev, "hclge device allocation failed\n");
30757a01c897SSalil Mehta return ret;
30767a01c897SSalil Mehta }
30777a01c897SSalil Mehta
30787a01c897SSalil Mehta ret = hclgevf_init_hdev(ae_dev->priv);
3079a6d818e3SYunsheng Lin if (ret) {
30807a01c897SSalil Mehta dev_err(&pdev->dev, "hclge device initialization failed\n");
30817a01c897SSalil Mehta return ret;
30827a01c897SSalil Mehta }
30837a01c897SSalil Mehta
3084a6d818e3SYunsheng Lin return 0;
3085a6d818e3SYunsheng Lin }
3086a6d818e3SYunsheng Lin
hclgevf_uninit_ae_dev(struct hnae3_ae_dev * ae_dev)30877a01c897SSalil Mehta static void hclgevf_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
30887a01c897SSalil Mehta {
30897a01c897SSalil Mehta struct hclgevf_dev *hdev = ae_dev->priv;
30907a01c897SSalil Mehta
30917a01c897SSalil Mehta hclgevf_uninit_hdev(hdev);
3092e2cb1decSSalil Mehta ae_dev->priv = NULL;
3093e2cb1decSSalil Mehta }
3094e2cb1decSSalil Mehta
hclgevf_get_max_channels(struct hclgevf_dev * hdev)3095849e4607SPeng Li static u32 hclgevf_get_max_channels(struct hclgevf_dev *hdev)
3096849e4607SPeng Li {
3097849e4607SPeng Li return min(hdev->rss_size_max, hdev->num_tqps);
3098849e4607SPeng Li }
3099849e4607SPeng Li
31008be73621SHuazhong Tan /**
310135244430SJian Shen * hclgevf_get_channels - Get the current channels enabled and max supported.
3102849e4607SPeng Li * @handle: hardware information for network interface
3103849e4607SPeng Li * @ch: ethtool channels structure
3104849e4607SPeng Li *
3105849e4607SPeng Li * We don't support separate tx and rx queues as channels. The other count
3106849e4607SPeng Li * represents how many queues are being used for control. max_combined counts
3107849e4607SPeng Li * how many queue pairs we can support. They may not be mapped 1 to 1 with
3108849e4607SPeng Li * q_vectors since we support a lot more queue pairs than q_vectors.
3109849e4607SPeng Li **/
hclgevf_get_channels(struct hnae3_handle * handle,struct ethtool_channels * ch)3110849e4607SPeng Li static void hclgevf_get_channels(struct hnae3_handle *handle,
3111849e4607SPeng Li struct ethtool_channels *ch)
3112849e4607SPeng Li {
3113849e4607SPeng Li struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3114849e4607SPeng Li
3115849e4607SPeng Li ch->max_combined = hclgevf_get_max_channels(hdev);
3116849e4607SPeng Li ch->other_count = 0;
3117849e4607SPeng Li ch->max_other = 0;
3118849e4607SPeng Li ch->combined_count = handle->kinfo.rss_size;
3119849e4607SPeng Li }
3120849e4607SPeng Li
hclgevf_get_tqps_and_rss_info(struct hnae3_handle * handle,u16 * alloc_tqps,u16 * max_rss_size)3121849e4607SPeng Li static void hclgevf_get_tqps_and_rss_info(struct hnae3_handle *handle,
31228be73621SHuazhong Tan u16 *alloc_tqps, u16 *max_rss_size)
3123849e4607SPeng Li {
3124849e4607SPeng Li struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3125cc719218SPeng Li
31260d43bf45SHuazhong Tan *alloc_tqps = hdev->num_tqps;
3127cc719218SPeng Li *max_rss_size = hdev->rss_size_max;
3128cc719218SPeng Li }
3129cc719218SPeng Li
hclgevf_update_rss_size(struct hnae3_handle * handle,u32 new_tqps_num)31300d43bf45SHuazhong Tan static void hclgevf_update_rss_size(struct hnae3_handle *handle,
3131cc719218SPeng Li u32 new_tqps_num)
3132cc719218SPeng Li {
3133cc719218SPeng Li struct hnae3_knic_private_info *kinfo = &handle->kinfo;
31344093d1a2SGuangbin Huang struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
31354093d1a2SGuangbin Huang u16 max_rss_size;
31364093d1a2SGuangbin Huang
31374093d1a2SGuangbin Huang kinfo->req_rss_size = new_tqps_num;
31384093d1a2SGuangbin Huang
31394093d1a2SGuangbin Huang max_rss_size = min_t(u16, hdev->rss_size_max,
31404093d1a2SGuangbin Huang hdev->num_tqps / kinfo->tc_info.num_tc);
31414093d1a2SGuangbin Huang
31424093d1a2SGuangbin Huang /* Use the user's configuration when it is not larger than
31434093d1a2SGuangbin Huang * max_rss_size, otherwise, use the maximum specification value.
314435244430SJian Shen */
31454093d1a2SGuangbin Huang if (kinfo->req_rss_size != kinfo->rss_size && kinfo->req_rss_size &&
31464093d1a2SGuangbin Huang kinfo->req_rss_size <= max_rss_size)
31474093d1a2SGuangbin Huang kinfo->rss_size = kinfo->req_rss_size;
31484093d1a2SGuangbin Huang else if (kinfo->rss_size > max_rss_size ||
31494093d1a2SGuangbin Huang (!kinfo->req_rss_size && kinfo->rss_size < max_rss_size))
31504093d1a2SGuangbin Huang kinfo->rss_size = max_rss_size;
31514093d1a2SGuangbin Huang
31524093d1a2SGuangbin Huang kinfo->num_tqps = kinfo->tc_info.num_tc * kinfo->rss_size;
31534093d1a2SGuangbin Huang }
31544093d1a2SGuangbin Huang
hclgevf_set_channels(struct hnae3_handle * handle,u32 new_tqps_num,bool rxfh_configured)31554093d1a2SGuangbin Huang static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num,
315635244430SJian Shen bool rxfh_configured)
31574093d1a2SGuangbin Huang {
31584093d1a2SGuangbin Huang struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
31594093d1a2SGuangbin Huang struct hnae3_knic_private_info *kinfo = &handle->kinfo;
31604093d1a2SGuangbin Huang u16 tc_offset[HCLGE_COMM_MAX_TC_NUM];
31614093d1a2SGuangbin Huang u16 tc_valid[HCLGE_COMM_MAX_TC_NUM];
31624093d1a2SGuangbin Huang u16 tc_size[HCLGE_COMM_MAX_TC_NUM];
31634093d1a2SGuangbin Huang u16 cur_rss_size = kinfo->rss_size;
316493969dc1SJie Wang u16 cur_tqps = kinfo->num_tqps;
316593969dc1SJie Wang u32 *rss_indir;
316693969dc1SJie Wang unsigned int i;
31674093d1a2SGuangbin Huang int ret;
31684093d1a2SGuangbin Huang
31694093d1a2SGuangbin Huang hclgevf_update_rss_size(handle, new_tqps_num);
31704093d1a2SGuangbin Huang
31714093d1a2SGuangbin Huang hclge_comm_get_rss_tc_info(kinfo->rss_size, hdev->hw_tc_map,
31724093d1a2SGuangbin Huang tc_offset, tc_valid, tc_size);
31734093d1a2SGuangbin Huang ret = hclge_comm_set_rss_tc_mode(&hdev->hw.hw, tc_offset,
31744093d1a2SGuangbin Huang tc_valid, tc_size);
3175ae9f29fdSJie Wang if (ret)
317693969dc1SJie Wang return ret;
317793969dc1SJie Wang
317893969dc1SJie Wang /* RSS indirection table has been configured by user */
31794093d1a2SGuangbin Huang if (rxfh_configured)
31804093d1a2SGuangbin Huang goto out;
31814093d1a2SGuangbin Huang
3182cd7e963dSSalil Mehta /* Reinitializes the rss indirect table according to the new RSS size */
31834093d1a2SGuangbin Huang rss_indir = kcalloc(hdev->ae_dev->dev_specs.rss_ind_tbl_size,
31844093d1a2SGuangbin Huang sizeof(u32), GFP_KERNEL);
31854093d1a2SGuangbin Huang if (!rss_indir)
31864093d1a2SGuangbin Huang return -ENOMEM;
318787ce161eSGuangbin Huang
318887ce161eSGuangbin Huang for (i = 0; i < hdev->ae_dev->dev_specs.rss_ind_tbl_size; i++)
31894093d1a2SGuangbin Huang rss_indir[i] = i % kinfo->rss_size;
31904093d1a2SGuangbin Huang
31914093d1a2SGuangbin Huang hdev->rss_cfg.rss_size = kinfo->rss_size;
319287ce161eSGuangbin Huang
31934093d1a2SGuangbin Huang ret = hclgevf_set_rss(handle, rss_indir, NULL, 0);
31944093d1a2SGuangbin Huang if (ret)
3195944de484SGuojia Liao dev_err(&hdev->pdev->dev, "set rss indir table fail, ret=%d\n",
3196944de484SGuojia Liao ret);
31974093d1a2SGuangbin Huang
31984093d1a2SGuangbin Huang kfree(rss_indir);
31994093d1a2SGuangbin Huang
32004093d1a2SGuangbin Huang out:
32014093d1a2SGuangbin Huang if (!ret)
32024093d1a2SGuangbin Huang dev_info(&hdev->pdev->dev,
32034093d1a2SGuangbin Huang "Channels changed, rss_size from %u to %u, tqps from %u to %u",
32044093d1a2SGuangbin Huang cur_rss_size, kinfo->rss_size,
32054093d1a2SGuangbin Huang cur_tqps, kinfo->rss_size * kinfo->tc_info.num_tc);
32064093d1a2SGuangbin Huang
32074093d1a2SGuangbin Huang return ret;
32084093d1a2SGuangbin Huang }
320935244430SJian Shen
hclgevf_get_status(struct hnae3_handle * handle)32104093d1a2SGuangbin Huang static int hclgevf_get_status(struct hnae3_handle *handle)
32114093d1a2SGuangbin Huang {
32124093d1a2SGuangbin Huang struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
32134093d1a2SGuangbin Huang
3214175ec96bSFuyun Liang return hdev->hw.mac.link;
3215175ec96bSFuyun Liang }
3216175ec96bSFuyun Liang
hclgevf_get_ksettings_an_result(struct hnae3_handle * handle,u8 * auto_neg,u32 * speed,u8 * duplex,u32 * lane_num)3217175ec96bSFuyun Liang static void hclgevf_get_ksettings_an_result(struct hnae3_handle *handle,
3218175ec96bSFuyun Liang u8 *auto_neg, u32 *speed,
3219175ec96bSFuyun Liang u8 *duplex, u32 *lane_num)
3220175ec96bSFuyun Liang {
32214a152de9SFuyun Liang struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
32224a152de9SFuyun Liang
32230f032f93SHao Chen if (speed)
32244a152de9SFuyun Liang *speed = hdev->hw.mac.speed;
32254a152de9SFuyun Liang if (duplex)
32264a152de9SFuyun Liang *duplex = hdev->hw.mac.duplex;
32274a152de9SFuyun Liang if (auto_neg)
32284a152de9SFuyun Liang *auto_neg = AUTONEG_DISABLE;
32294a152de9SFuyun Liang }
32304a152de9SFuyun Liang
hclgevf_update_speed_duplex(struct hclgevf_dev * hdev,u32 speed,u8 duplex)32314a152de9SFuyun Liang void hclgevf_update_speed_duplex(struct hclgevf_dev *hdev, u32 speed,
32324a152de9SFuyun Liang u8 duplex)
32334a152de9SFuyun Liang {
32344a152de9SFuyun Liang hdev->hw.mac.speed = speed;
32354a152de9SFuyun Liang hdev->hw.mac.duplex = duplex;
32364a152de9SFuyun Liang }
32374a152de9SFuyun Liang
hclgevf_gro_en(struct hnae3_handle * handle,bool enable)32384a152de9SFuyun Liang static int hclgevf_gro_en(struct hnae3_handle *handle, bool enable)
32394a152de9SFuyun Liang {
32404a152de9SFuyun Liang struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
32414a152de9SFuyun Liang bool gro_en_old = hdev->gro_en;
32421731be4cSYonglong Liu int ret;
32435c9f6b39SPeng Li
32445c9f6b39SPeng Li hdev->gro_en = enable;
32453462207dSYufeng Mo ret = hclgevf_config_gro(hdev);
32463462207dSYufeng Mo if (ret)
32475c9f6b39SPeng Li hdev->gro_en = gro_en_old;
32483462207dSYufeng Mo
32493462207dSYufeng Mo return ret;
32503462207dSYufeng Mo }
32513462207dSYufeng Mo
hclgevf_get_media_type(struct hnae3_handle * handle,u8 * media_type,u8 * module_type)32523462207dSYufeng Mo static void hclgevf_get_media_type(struct hnae3_handle *handle, u8 *media_type,
32533462207dSYufeng Mo u8 *module_type)
32545c9f6b39SPeng Li {
32555c9f6b39SPeng Li struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
325688d10bd6SJian Shen
325788d10bd6SJian Shen if (media_type)
3258c136b884SPeng Li *media_type = hdev->hw.mac.media_type;
3259c136b884SPeng Li
326088d10bd6SJian Shen if (module_type)
3261c136b884SPeng Li *module_type = hdev->hw.mac.module_type;
3262c136b884SPeng Li }
326388d10bd6SJian Shen
hclgevf_get_hw_reset_stat(struct hnae3_handle * handle)326488d10bd6SJian Shen static bool hclgevf_get_hw_reset_stat(struct hnae3_handle *handle)
326588d10bd6SJian Shen {
3266c136b884SPeng Li struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3267c136b884SPeng Li
32684d60291bSHuazhong Tan return !!hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
32694d60291bSHuazhong Tan }
32704d60291bSHuazhong Tan
hclgevf_get_cmdq_stat(struct hnae3_handle * handle)32714d60291bSHuazhong Tan static bool hclgevf_get_cmdq_stat(struct hnae3_handle *handle)
3272aa5c4f17SHuazhong Tan {
32734d60291bSHuazhong Tan struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
32744d60291bSHuazhong Tan
3275fe735c84SHuazhong Tan return test_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
3276fe735c84SHuazhong Tan }
3277fe735c84SHuazhong Tan
hclgevf_ae_dev_resetting(struct hnae3_handle * handle)3278fe735c84SHuazhong Tan static bool hclgevf_ae_dev_resetting(struct hnae3_handle *handle)
3279076bb537SJie Wang {
3280fe735c84SHuazhong Tan struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
3281fe735c84SHuazhong Tan
32824d60291bSHuazhong Tan return test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state);
32834d60291bSHuazhong Tan }
32844d60291bSHuazhong Tan
hclgevf_ae_dev_reset_cnt(struct hnae3_handle * handle)32854d60291bSHuazhong Tan static unsigned long hclgevf_ae_dev_reset_cnt(struct hnae3_handle *handle)
32864d60291bSHuazhong Tan {
32874d60291bSHuazhong Tan struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
32884d60291bSHuazhong Tan
32894d60291bSHuazhong Tan return hdev->rst_stats.hw_rst_done_cnt;
32904d60291bSHuazhong Tan }
32914d60291bSHuazhong Tan
hclgevf_get_link_mode(struct hnae3_handle * handle,unsigned long * supported,unsigned long * advertising)32924d60291bSHuazhong Tan static void hclgevf_get_link_mode(struct hnae3_handle *handle,
3293c88a6e7dSHuazhong Tan unsigned long *supported,
32944d60291bSHuazhong Tan unsigned long *advertising)
32954d60291bSHuazhong Tan {
32969194d18bSliuzhongzhu struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
32979194d18bSliuzhongzhu
32989194d18bSliuzhongzhu *supported = hdev->hw.mac.supported;
32999194d18bSliuzhongzhu *advertising = hdev->hw.mac.advertising;
33009194d18bSliuzhongzhu }
33019194d18bSliuzhongzhu
hclgevf_update_port_base_vlan_info(struct hclgevf_dev * hdev,u16 state,struct hclge_mbx_port_base_vlan * port_base_vlan)33029194d18bSliuzhongzhu void hclgevf_update_port_base_vlan_info(struct hclgevf_dev *hdev, u16 state,
33039194d18bSliuzhongzhu struct hclge_mbx_port_base_vlan *port_base_vlan)
33049194d18bSliuzhongzhu {
33059194d18bSliuzhongzhu struct hnae3_handle *nic = &hdev->nic;
330692f11ea1SJian Shen struct hclge_vf_to_pf_msg send_msg;
3307767975e5SJie Wang int ret;
330892f11ea1SJian Shen
330992f11ea1SJian Shen rtnl_lock();
3310d3410018SYufeng Mo
3311a6f7bfdcSJian Shen if (test_bit(HCLGEVF_STATE_RST_HANDLING, &hdev->state) ||
331292f11ea1SJian Shen test_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state)) {
331392f11ea1SJian Shen dev_warn(&hdev->pdev->dev,
3314a6f7bfdcSJian Shen "is resetting when updating port based vlan info\n");
3315b7b5d25bSGuojia Liao rtnl_unlock();
3316b7b5d25bSGuojia Liao return;
3317a6f7bfdcSJian Shen }
3318a6f7bfdcSJian Shen
331992f11ea1SJian Shen ret = hclgevf_notify_client(hdev, HNAE3_DOWN_CLIENT);
3320a6f7bfdcSJian Shen if (ret) {
3321a6f7bfdcSJian Shen rtnl_unlock();
3322a6f7bfdcSJian Shen return;
3323a6f7bfdcSJian Shen }
3324a6f7bfdcSJian Shen
3325a6f7bfdcSJian Shen /* send msg to PF and wait update port based vlan info */
3326a6f7bfdcSJian Shen hclgevf_build_send_msg(&send_msg, HCLGE_MBX_SET_VLAN,
3327a6f7bfdcSJian Shen HCLGE_MBX_PORT_BASE_VLAN_CFG);
332892f11ea1SJian Shen memcpy(send_msg.data, port_base_vlan, sizeof(*port_base_vlan));
332992f11ea1SJian Shen ret = hclgevf_send_mbx_msg(hdev, &send_msg, false, NULL, 0);
3330d3410018SYufeng Mo if (!ret) {
3331d3410018SYufeng Mo if (state == HNAE3_PORT_BASE_VLAN_DISABLE)
3332767975e5SJie Wang nic->port_base_vlan_state = state;
3333a6f7bfdcSJian Shen else
3334a6f7bfdcSJian Shen nic->port_base_vlan_state = HNAE3_PORT_BASE_VLAN_ENABLE;
333592f11ea1SJian Shen }
3336a6f7bfdcSJian Shen
333792f11ea1SJian Shen hclgevf_notify_client(hdev, HNAE3_UP_CLIENT);
333892f11ea1SJian Shen rtnl_unlock();
3339a6f7bfdcSJian Shen }
334092f11ea1SJian Shen
334192f11ea1SJian Shen static const struct hnae3_ae_ops hclgevf_ops = {
334292f11ea1SJian Shen .init_ae_dev = hclgevf_init_ae_dev,
334392f11ea1SJian Shen .uninit_ae_dev = hclgevf_uninit_ae_dev,
334492f11ea1SJian Shen .reset_prepare = hclgevf_reset_prepare_general,
3345e2cb1decSSalil Mehta .reset_done = hclgevf_reset_done,
3346e2cb1decSSalil Mehta .init_client_instance = hclgevf_init_client_instance,
3347e2cb1decSSalil Mehta .uninit_client_instance = hclgevf_uninit_client_instance,
3348bb1890d5SJiaran Zhang .start = hclgevf_ae_start,
3349bb1890d5SJiaran Zhang .stop = hclgevf_ae_stop,
3350e718a93fSPeng Li .client_start = hclgevf_client_start,
3351e718a93fSPeng Li .client_stop = hclgevf_client_stop,
3352e2cb1decSSalil Mehta .map_ring_to_vector = hclgevf_map_ring_to_vector,
3353e2cb1decSSalil Mehta .unmap_ring_from_vector = hclgevf_unmap_ring_from_vector,
3354a6d818e3SYunsheng Lin .get_vector = hclgevf_get_vector,
3355a6d818e3SYunsheng Lin .put_vector = hclgevf_put_vector,
3356e2cb1decSSalil Mehta .reset_queue = hclgevf_reset_tqp,
3357e2cb1decSSalil Mehta .get_mac_addr = hclgevf_get_mac_addr,
3358e2cb1decSSalil Mehta .set_mac_addr = hclgevf_set_mac_addr,
33590d3e6631SYunsheng Lin .add_uc_addr = hclgevf_add_uc_addr,
3360e2cb1decSSalil Mehta .rm_uc_addr = hclgevf_rm_uc_addr,
3361e2cb1decSSalil Mehta .add_mc_addr = hclgevf_add_mc_addr,
3362e2cb1decSSalil Mehta .rm_mc_addr = hclgevf_rm_mc_addr,
3363e2cb1decSSalil Mehta .get_stats = hclgevf_get_stats,
3364e2cb1decSSalil Mehta .update_stats = hclgevf_update_stats,
3365e2cb1decSSalil Mehta .get_strings = hclgevf_get_strings,
3366e2cb1decSSalil Mehta .get_sset_count = hclgevf_get_sset_count,
3367e2cb1decSSalil Mehta .get_rss_key_size = hclge_comm_get_rss_key_size,
3368e2cb1decSSalil Mehta .get_rss = hclgevf_get_rss,
3369e2cb1decSSalil Mehta .set_rss = hclgevf_set_rss,
3370e2cb1decSSalil Mehta .get_rss_tuple = hclgevf_get_rss_tuple,
3371027733b1SJie Wang .set_rss_tuple = hclgevf_set_rss_tuple,
3372e2cb1decSSalil Mehta .get_tc_size = hclgevf_get_tc_size,
3373e2cb1decSSalil Mehta .get_fw_version = hclgevf_get_fw_version,
3374d97b3072SJian Shen .set_vlan_filter = hclgevf_set_vlan_filter,
3375d97b3072SJian Shen .enable_vlan_filter = hclgevf_enable_vlan_filter,
3376e2cb1decSSalil Mehta .enable_hw_strip_rxvtag = hclgevf_en_hw_strip_rxvtag,
3377e2cb1decSSalil Mehta .reset_event = hclgevf_reset_event,
3378e2cb1decSSalil Mehta .set_default_reset_request = hclgevf_set_def_reset_request,
3379fa6a262aSJian Shen .set_channels = hclgevf_set_channels,
3380b2641e2aSYunsheng Lin .get_channels = hclgevf_get_channels,
33816d4c3981SSalil Mehta .get_tqps_and_rss_info = hclgevf_get_tqps_and_rss_info,
3382720bd583SHuazhong Tan .get_regs_len = hclgevf_get_regs_len,
33834093d1a2SGuangbin Huang .get_regs = hclgevf_get_regs,
3384849e4607SPeng Li .get_status = hclgevf_get_status,
3385cc719218SPeng Li .get_ksettings_an_result = hclgevf_get_ksettings_an_result,
33861600c3e5SJian Shen .get_media_type = hclgevf_get_media_type,
33871600c3e5SJian Shen .get_hw_reset_stat = hclgevf_get_hw_reset_stat,
3388175ec96bSFuyun Liang .ae_dev_resetting = hclgevf_ae_dev_resetting,
33894a152de9SFuyun Liang .ae_dev_reset_cnt = hclgevf_ae_dev_reset_cnt,
3390c136b884SPeng Li .set_gro_en = hclgevf_gro_en,
33914d60291bSHuazhong Tan .set_mtu = hclgevf_set_mtu,
33924d60291bSHuazhong Tan .get_global_queue_id = hclgevf_get_qid_global,
33934d60291bSHuazhong Tan .set_timer_task = hclgevf_set_timer_task,
33945c9f6b39SPeng Li .get_link_mode = hclgevf_get_link_mode,
3395818f1675SYunsheng Lin .set_promisc_mode = hclgevf_set_promisc_mode,
33960c29d191Sliuzhongzhu .request_update_promisc_mode = hclgevf_request_update_promisc_mode,
33978cdb992fSJian Shen .get_cmdq_stat = hclgevf_get_cmdq_stat,
33989194d18bSliuzhongzhu };
3399e196ec75SJian Shen
3400c631c696SJian Shen static struct hnae3_ae_algo ae_algovf = {
3401fe735c84SHuazhong Tan .ops = &hclgevf_ops,
3402e2cb1decSSalil Mehta .pdev_id_table = ae_algovf_pci_tbl,
3403e2cb1decSSalil Mehta };
3404e2cb1decSSalil Mehta
hclgevf_init(void)3405e2cb1decSSalil Mehta static int __init hclgevf_init(void)
3406e2cb1decSSalil Mehta {
3407e2cb1decSSalil Mehta pr_info("%s is initializing\n", HCLGEVF_NAME);
3408e2cb1decSSalil Mehta
3409134a4647SXiu Jianfeng hclgevf_wq = alloc_workqueue("%s", WQ_UNBOUND, 0, HCLGEVF_NAME);
3410e2cb1decSSalil Mehta if (!hclgevf_wq) {
3411e2cb1decSSalil Mehta pr_err("%s: failed to create workqueue\n", HCLGEVF_NAME);
3412e2cb1decSSalil Mehta return -ENOMEM;
3413f29da408SYufeng Mo }
34140ea68902SYunsheng Lin
34150ea68902SYunsheng Lin hnae3_register_ae_algo(&ae_algovf);
34160ea68902SYunsheng Lin
34170ea68902SYunsheng Lin return 0;
34180ea68902SYunsheng Lin }
3419854cf33aSFuyun Liang
hclgevf_exit(void)3420854cf33aSFuyun Liang static void __exit hclgevf_exit(void)
3421854cf33aSFuyun Liang {
3422e2cb1decSSalil Mehta hnae3_acquire_unload_lock();
3423e2cb1decSSalil Mehta hnae3_unregister_ae_algo(&ae_algovf);
3424134a4647SXiu Jianfeng destroy_workqueue(hclgevf_wq);
3425e2cb1decSSalil Mehta hnae3_release_unload_lock();
342692e59957SJian Shen }
3427e2cb1decSSalil Mehta module_init(hclgevf_init);
34280ea68902SYunsheng Lin module_exit(hclgevf_exit);
342992e59957SJian Shen
3430e2cb1decSSalil Mehta MODULE_LICENSE("GPL");
3431e2cb1decSSalil Mehta MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
3432e2cb1decSSalil Mehta MODULE_DESCRIPTION("HCLGEVF Driver");
3433e2cb1decSSalil Mehta MODULE_VERSION(HCLGEVF_MOD_VERSION);
3434e2cb1decSSalil Mehta