xref: /dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.c (revision 089e5ed727a15da2729cfee9b63533dd120bd04c)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Huawei Technologies Co., Ltd
3  */
4 
5 #include "hinic_compat.h"
6 #include "hinic_pmd_hwdev.h"
7 #include "hinic_pmd_hwif.h"
8 #include "hinic_pmd_eqs.h"
9 #include "hinic_pmd_wq.h"
10 #include "hinic_pmd_mgmt.h"
11 #include "hinic_pmd_cmdq.h"
12 #include "hinic_pmd_niccfg.h"
13 
14 #define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in,		\
15 			       in_size, buf_out, out_size)	\
16 	hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, cmd,	\
17 			buf_in, in_size,			\
18 			buf_out, out_size, 0)
19 
20 int hinic_init_function_table(void *hwdev, u16 rx_buf_sz)
21 {
22 	struct hinic_function_table function_table;
23 	u16 out_size = sizeof(function_table);
24 	int err;
25 
26 	if (!hwdev) {
27 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
28 		return -EINVAL;
29 	}
30 
31 	memset(&function_table, 0, sizeof(function_table));
32 	function_table.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
33 	function_table.func_id = hinic_global_func_id(hwdev);
34 	function_table.mtu = 0x3FFF;	/* default, max mtu */
35 	function_table.rx_wqe_buf_size = rx_buf_sz;
36 
37 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
38 				     HINIC_PORT_CMD_INIT_FUNC,
39 				     &function_table, sizeof(function_table),
40 				     &function_table, &out_size, 0);
41 	if (err || function_table.mgmt_msg_head.status || !out_size) {
42 		PMD_DRV_LOG(ERR,
43 			"Failed to init func table, ret = %d",
44 			function_table.mgmt_msg_head.status);
45 		return -EFAULT;
46 	}
47 
48 	return 0;
49 }
50 
51 /**
52  * hinic_get_base_qpn - get global number of queue
53  * @hwdev: the hardware interface of a nic device
54  * @global_qpn: vat page size
55  * @return
56  *   0 on success,
57  *   negative error value otherwise.
58  **/
59 int hinic_get_base_qpn(void *hwdev, u16 *global_qpn)
60 {
61 	struct hinic_cmd_qpn cmd_qpn;
62 	u16 out_size = sizeof(cmd_qpn);
63 	int err;
64 
65 	if (!hwdev || !global_qpn) {
66 		PMD_DRV_LOG(ERR, "Hwdev or global_qpn is NULL");
67 		return -EINVAL;
68 	}
69 
70 	memset(&cmd_qpn, 0, sizeof(cmd_qpn));
71 	cmd_qpn.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
72 	cmd_qpn.func_id = hinic_global_func_id(hwdev);
73 
74 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
75 				     HINIC_PORT_CMD_GET_GLOBAL_QPN,
76 				     &cmd_qpn, sizeof(cmd_qpn), &cmd_qpn,
77 				     &out_size, 0);
78 	if (err || !out_size || cmd_qpn.mgmt_msg_head.status) {
79 		PMD_DRV_LOG(ERR,
80 			"Failed to get base qpn, status(%d)",
81 			cmd_qpn.mgmt_msg_head.status);
82 		return -EINVAL;
83 	}
84 
85 	*global_qpn = cmd_qpn.base_qpn;
86 
87 	return 0;
88 }
89 
90 /**
91  * hinic_set_mac - Init mac_vlan table in NIC.
92  * @hwdev: the hardware interface of a nic device
93  * @mac_addr: mac address
94  * @vlan_id: set 0 for mac_vlan table initialization
95  * @func_id: global function id of NIC
96  * @return
97  *   0 on success and stats is filled,
98  *   negative error value otherwise.
99  */
100 int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
101 {
102 	struct hinic_port_mac_set mac_info;
103 	u16 out_size = sizeof(mac_info);
104 	int err;
105 
106 	if (!hwdev || !mac_addr) {
107 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
108 		return -EINVAL;
109 	}
110 
111 	memset(&mac_info, 0, sizeof(mac_info));
112 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
113 	mac_info.func_id = func_id;
114 	mac_info.vlan_id = vlan_id;
115 	memmove(mac_info.mac, mac_addr, ETH_ALEN);
116 
117 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
118 				     sizeof(mac_info), &mac_info, &out_size);
119 	if (err || !out_size || (mac_info.mgmt_msg_head.status &&
120 	    mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
121 		PMD_DRV_LOG(ERR, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x",
122 			err, mac_info.mgmt_msg_head.status, out_size);
123 		return -EINVAL;
124 	}
125 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
126 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore set operation.");
127 		return HINIC_PF_SET_VF_ALREADY;
128 	}
129 
130 	return 0;
131 }
132 
133 /**
134  * hinic_del_mac - Uninit mac_vlan table in NIC.
135  * @hwdev: the hardware interface of a nic device
136  * @mac_addr: mac address
137  * @vlan_id: set 0 for mac_vlan table initialization
138  * @func_id: global function id of NIC
139  * @return
140  *   0 on success and stats is filled,
141  *   negative error value otherwise.
142  */
143 int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id,
144 		  u16 func_id)
145 {
146 	struct hinic_port_mac_set mac_info;
147 	u16 out_size = sizeof(mac_info);
148 	int err;
149 
150 	if (!hwdev || !mac_addr) {
151 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
152 		return -EINVAL;
153 	}
154 
155 	if (vlan_id >= VLAN_N_VID) {
156 		PMD_DRV_LOG(ERR, "Invalid VLAN number");
157 		return -EINVAL;
158 	}
159 
160 	memset(&mac_info, 0, sizeof(mac_info));
161 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
162 	mac_info.func_id = func_id;
163 	mac_info.vlan_id = vlan_id;
164 	memmove(mac_info.mac, mac_addr, ETH_ALEN);
165 
166 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_DEL_MAC, &mac_info,
167 				     sizeof(mac_info), &mac_info, &out_size);
168 	if (err || !out_size || (mac_info.mgmt_msg_head.status &&
169 		mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
170 		PMD_DRV_LOG(ERR, "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x",
171 			err, mac_info.mgmt_msg_head.status, out_size);
172 		return -EINVAL;
173 	}
174 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
175 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore delete operation.");
176 		return HINIC_PF_SET_VF_ALREADY;
177 	}
178 
179 	return 0;
180 }
181 
182 int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
183 {
184 	struct hinic_port_mac_set mac_info;
185 	u16 out_size = sizeof(mac_info);
186 	int err;
187 
188 	if (!hwdev || !mac_addr) {
189 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
190 		return -EINVAL;
191 	}
192 
193 	memset(&mac_info, 0, sizeof(mac_info));
194 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
195 	mac_info.func_id = hinic_global_func_id(hwdev);
196 
197 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MAC,
198 				     &mac_info, sizeof(mac_info),
199 				     &mac_info, &out_size);
200 	if (err || !out_size || mac_info.mgmt_msg_head.status) {
201 		PMD_DRV_LOG(ERR, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x",
202 			err, mac_info.mgmt_msg_head.status, out_size);
203 		return -EINVAL;
204 	}
205 
206 	memmove(mac_addr, mac_info.mac, ETH_ALEN);
207 
208 	return 0;
209 }
210 
211 int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
212 {
213 	struct hinic_mtu mtu_info;
214 	u16 out_size = sizeof(mtu_info);
215 	int err;
216 
217 	if (!hwdev) {
218 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
219 		return -EINVAL;
220 	}
221 
222 	memset(&mtu_info, 0, sizeof(mtu_info));
223 	mtu_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
224 	mtu_info.func_id = hinic_global_func_id(hwdev);
225 	mtu_info.mtu = new_mtu;
226 
227 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
228 				     &mtu_info, sizeof(mtu_info),
229 				     &mtu_info, &out_size);
230 	if (err || !out_size || mtu_info.mgmt_msg_head.status) {
231 		PMD_DRV_LOG(ERR, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x",
232 			err, mtu_info.mgmt_msg_head.status, out_size);
233 		return -EINVAL;
234 	}
235 
236 	return 0;
237 }
238 
239 int hinic_get_link_status(void *hwdev, u8 *link_state)
240 {
241 	struct hinic_get_link get_link;
242 	u16 out_size = sizeof(get_link);
243 	int err;
244 
245 	if (!hwdev || !link_state) {
246 		PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL");
247 		return -EINVAL;
248 	}
249 
250 	memset(&get_link, 0, sizeof(get_link));
251 	get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
252 	get_link.func_id = hinic_global_func_id(hwdev);
253 
254 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
255 				     &get_link, sizeof(get_link),
256 				     &get_link, &out_size);
257 	if (err || !out_size || get_link.mgmt_msg_head.status) {
258 		PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x",
259 			err, get_link.mgmt_msg_head.status, out_size);
260 		return -EINVAL;
261 	}
262 
263 	*link_state = get_link.link_status;
264 
265 	return 0;
266 }
267 
268 /**
269  * hinic_set_vport_enable - Notify firmware that driver is ready or not.
270  * @hwdev: the hardware interface of a nic device
271  * @enable: 1: driver is ready; 0: driver is not ok.
272  * Return: 0 on success and state is filled, negative error value otherwise.
273  **/
274 int hinic_set_vport_enable(void *hwdev, bool enable)
275 {
276 	struct hinic_vport_state en_state;
277 	u16 out_size = sizeof(en_state);
278 	int err;
279 
280 	if (!hwdev) {
281 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
282 		return -EINVAL;
283 	}
284 
285 	memset(&en_state, 0, sizeof(en_state));
286 	en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
287 	en_state.func_id = hinic_global_func_id(hwdev);
288 	en_state.state = (enable ? 1 : 0);
289 
290 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
291 				     &en_state, sizeof(en_state),
292 				     &en_state, &out_size);
293 	if (err || !out_size || en_state.mgmt_msg_head.status) {
294 		PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x",
295 			err, en_state.mgmt_msg_head.status, out_size);
296 		return -EINVAL;
297 	}
298 
299 	return 0;
300 }
301 
302 /**
303  * hinic_set_port_enable - open MAG to receive packets.
304  * @hwdev: the hardware interface of a nic device
305  * @enable: 1: open MAG; 0: close MAG.
306  * @return
307  *   0 on success and stats is filled,
308  *   negative error value otherwise.
309  */
310 int hinic_set_port_enable(void *hwdev, bool enable)
311 {
312 	struct hinic_port_state en_state;
313 	u16 out_size = sizeof(en_state);
314 	int err;
315 
316 	if (!hwdev) {
317 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
318 		return -EINVAL;
319 	}
320 
321 	memset(&en_state, 0, sizeof(en_state));
322 	en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
323 	en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE);
324 
325 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
326 				     &en_state, sizeof(en_state),
327 				     &en_state, &out_size);
328 	if (err || !out_size || en_state.mgmt_msg_head.status) {
329 		PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x",
330 			err, en_state.mgmt_msg_head.status, out_size);
331 		return -EINVAL;
332 	}
333 
334 	return 0;
335 }
336 
337 int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
338 {
339 	struct hinic_port_info port_msg;
340 	u16 out_size = sizeof(port_msg);
341 	int err;
342 
343 	if (!hwdev || !port_info) {
344 		PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL");
345 		return -EINVAL;
346 	}
347 
348 	memset(&port_msg, 0, sizeof(port_msg));
349 	port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
350 	port_msg.func_id = hinic_global_func_id(hwdev);
351 
352 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
353 				     &port_msg, sizeof(port_msg),
354 				     &port_msg, &out_size);
355 	if (err || !out_size || port_msg.mgmt_msg_head.status) {
356 		PMD_DRV_LOG(ERR,
357 			"Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
358 			err, port_msg.mgmt_msg_head.status, out_size);
359 		return err;
360 	}
361 
362 	port_info->autoneg_cap = port_msg.autoneg_cap;
363 	port_info->autoneg_state = port_msg.autoneg_state;
364 	port_info->duplex = port_msg.duplex;
365 	port_info->port_type = port_msg.port_type;
366 	port_info->speed = port_msg.speed;
367 
368 	return 0;
369 }
370 
371 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
372 {
373 	struct hinic_pause_config pause_info;
374 	u16 out_size = sizeof(pause_info);
375 	int err;
376 
377 	if (!hwdev) {
378 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
379 		return -EINVAL;
380 	}
381 
382 	memset(&pause_info, 0, sizeof(pause_info));
383 	pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
384 	pause_info.func_id = hinic_global_func_id(hwdev);
385 	pause_info.auto_neg = nic_pause.auto_neg;
386 	pause_info.rx_pause = nic_pause.rx_pause;
387 	pause_info.tx_pause = nic_pause.tx_pause;
388 
389 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
390 				     &pause_info, sizeof(pause_info),
391 				     &pause_info, &out_size);
392 	if (err || !out_size || pause_info.mgmt_msg_head.status) {
393 		PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x",
394 			err, pause_info.mgmt_msg_head.status, out_size);
395 		return -EINVAL;
396 	}
397 
398 	return 0;
399 }
400 
401 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
402 		      u8 *pgid, u8 *up_bw, u8 *prio)
403 {
404 	struct hinic_up_ets_cfg ets;
405 	u16 out_size = sizeof(ets);
406 	u16 up_bw_t = 0;
407 	u8 pg_bw_t = 0;
408 	int i, err;
409 
410 	if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) {
411 		PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL");
412 		return -EINVAL;
413 	}
414 
415 	for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
416 		up_bw_t += *(up_bw + i);
417 		pg_bw_t += *(pg_bw + i);
418 
419 		if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
420 			PMD_DRV_LOG(ERR,
421 				"Invalid up %d mapping tc: %d", i,
422 				*(up_tc + i));
423 			return -EINVAL;
424 		}
425 	}
426 
427 	if (pg_bw_t != 100 || (up_bw_t % 100) != 0) {
428 		PMD_DRV_LOG(ERR,
429 			"Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t);
430 		return -EINVAL;
431 	}
432 
433 	memset(&ets, 0, sizeof(ets));
434 	ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
435 	ets.port_id = 0;    /* reserved */
436 	memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX);
437 	memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX);
438 	memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX);
439 	memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX);
440 	memcpy(ets.prio, prio, HINIC_DCB_UP_MAX);
441 
442 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS,
443 				     &ets, sizeof(ets), &ets, &out_size);
444 	if (err || ets.mgmt_msg_head.status || !out_size) {
445 		PMD_DRV_LOG(ERR,
446 			"Failed to set ets, err: %d, status: 0x%x, out size: 0x%x",
447 			err, ets.mgmt_msg_head.status, out_size);
448 		return -EINVAL;
449 	}
450 
451 	return 0;
452 }
453 
454 int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats)
455 {
456 	struct hinic_port_stats_info vport_stats_cmd;
457 	struct hinic_cmd_vport_stats vport_stats_rsp;
458 	u16 out_size = sizeof(vport_stats_rsp);
459 	int err;
460 
461 	if (!hwdev || !stats) {
462 		PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
463 		return -EINVAL;
464 	}
465 
466 	memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp));
467 	memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd));
468 	vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
469 	vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
470 	vport_stats_cmd.func_id = hinic_global_func_id(hwdev);
471 	vport_stats_cmd.stats_size = sizeof(vport_stats_rsp);
472 
473 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
474 				     &vport_stats_cmd, sizeof(vport_stats_cmd),
475 				     &vport_stats_rsp, &out_size);
476 	if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) {
477 		PMD_DRV_LOG(ERR,
478 			"Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x",
479 			err, vport_stats_rsp.mgmt_msg_head.status, out_size);
480 		return -EFAULT;
481 	}
482 
483 	memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats));
484 
485 	return 0;
486 }
487 
488 int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats)
489 {
490 	struct hinic_port_stats_info port_stats_cmd;
491 	struct hinic_port_stats port_stats_rsp;
492 	u16 out_size = sizeof(port_stats_rsp);
493 	int err;
494 
495 	if (!hwdev || !stats) {
496 		PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
497 		return -EINVAL;
498 	}
499 
500 	memset(&port_stats_rsp, 0, sizeof(port_stats_rsp));
501 	memset(&port_stats_cmd, 0, sizeof(port_stats_cmd));
502 	port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
503 	port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
504 	port_stats_cmd.stats_size = sizeof(port_stats_rsp);
505 
506 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
507 				     &port_stats_cmd, sizeof(port_stats_cmd),
508 				     &port_stats_rsp, &out_size);
509 	if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) {
510 		PMD_DRV_LOG(ERR,
511 			"Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x",
512 			err, port_stats_rsp.mgmt_msg_head.status, out_size);
513 		return -EFAULT;
514 	}
515 
516 	memcpy(stats, &port_stats_rsp.stats, sizeof(*stats));
517 
518 	return 0;
519 }
520 
521 int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type)
522 {
523 	struct nic_rss_context_tbl *ctx_tbl;
524 	struct hinic_cmd_buf *cmd_buf;
525 	u32 ctx = 0;
526 	u64 out_param;
527 	int err;
528 
529 	if (!hwdev) {
530 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
531 		return -EINVAL;
532 	}
533 
534 	cmd_buf = hinic_alloc_cmd_buf(hwdev);
535 	if (!cmd_buf) {
536 		PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
537 		return -ENOMEM;
538 	}
539 
540 	ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
541 		HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
542 		HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
543 		HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
544 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
545 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
546 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
547 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
548 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
549 
550 	cmd_buf->size = sizeof(struct nic_rss_context_tbl);
551 
552 	ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf;
553 	ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
554 	ctx_tbl->offset = 0;
555 	ctx_tbl->size = sizeof(u32);
556 	ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
557 	ctx_tbl->rsvd = 0;
558 	ctx_tbl->ctx = cpu_to_be32(ctx);
559 
560 	/* cfg the rss context table by command queue */
561 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
562 				     HINIC_MOD_L2NIC,
563 				     HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
564 				     cmd_buf, &out_param, 0);
565 
566 	hinic_free_cmd_buf(hwdev, cmd_buf);
567 
568 	if (err || out_param != 0) {
569 		PMD_DRV_LOG(ERR, "Failed to set rss context table");
570 		return -EFAULT;
571 	}
572 
573 	return 0;
574 }
575 
576 int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type)
577 {
578 	struct hinic_rss_context_table ctx_tbl;
579 	u16 out_size = sizeof(ctx_tbl);
580 	int err;
581 
582 	if (!hwdev || !rss_type) {
583 		PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL");
584 		return -EINVAL;
585 	}
586 
587 	ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
588 	ctx_tbl.func_id = hinic_global_func_id(hwdev);
589 	ctx_tbl.template_id = (u8)tmpl_idx;
590 
591 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
592 				     &ctx_tbl, sizeof(ctx_tbl),
593 				     &ctx_tbl, &out_size);
594 	if (err || !out_size || ctx_tbl.mgmt_msg_head.status) {
595 		PMD_DRV_LOG(ERR,
596 			"Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x",
597 			err, ctx_tbl.mgmt_msg_head.status, out_size);
598 		return -EINVAL;
599 	}
600 
601 	rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
602 	rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
603 	rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
604 	rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
605 	rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
606 	rss_type->tcp_ipv6_ext =
607 			HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT);
608 	rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
609 	rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
610 
611 	return 0;
612 }
613 
614 int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
615 {
616 	struct hinic_rss_template_key temp_key;
617 	u16 out_size = sizeof(temp_key);
618 	int err;
619 
620 	if (!hwdev || !temp) {
621 		PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
622 		return -EINVAL;
623 	}
624 
625 	memset(&temp_key, 0, sizeof(temp_key));
626 	temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
627 	temp_key.func_id = hinic_global_func_id(hwdev);
628 	temp_key.template_id = (u8)tmpl_idx;
629 	memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
630 
631 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
632 				     &temp_key, sizeof(temp_key),
633 				     &temp_key, &out_size);
634 	if (err || !out_size || temp_key.mgmt_msg_head.status) {
635 		PMD_DRV_LOG(ERR,
636 			"Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x",
637 			err, temp_key.mgmt_msg_head.status, out_size);
638 		return -EINVAL;
639 	}
640 
641 	return 0;
642 }
643 
644 int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
645 {
646 	struct hinic_rss_template_key temp_key;
647 	u16 out_size = sizeof(temp_key);
648 	int err;
649 
650 	if (!hwdev || !temp) {
651 		PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
652 		return -EINVAL;
653 	}
654 
655 	memset(&temp_key, 0, sizeof(temp_key));
656 	temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
657 	temp_key.func_id = hinic_global_func_id(hwdev);
658 	temp_key.template_id = (u8)tmpl_idx;
659 
660 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
661 				     &temp_key, sizeof(temp_key),
662 				     &temp_key, &out_size);
663 	if (err || !out_size || temp_key.mgmt_msg_head.status) {
664 		PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x",
665 			err, temp_key.mgmt_msg_head.status, out_size);
666 		return -EINVAL;
667 	}
668 
669 	memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
670 
671 	return 0;
672 }
673 
674 /**
675  * hinic_rss_set_hash_engine - Init rss hash function .
676  * @hwdev: the hardware interface of a nic device
677  * @tmpl_idx: index of rss template from NIC.
678  * @type: hash function, such as Toeplitz or XOR.
679  * @return
680  *   0 on success and stats is filled,
681  *   negative error value otherwise.
682  */
683 int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
684 {
685 	struct hinic_rss_engine_type hash_type;
686 	u16 out_size = sizeof(hash_type);
687 	int err;
688 
689 	if (!hwdev) {
690 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
691 		return -EINVAL;
692 	}
693 
694 	memset(&hash_type, 0, sizeof(hash_type));
695 	hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
696 	hash_type.func_id = hinic_global_func_id(hwdev);
697 	hash_type.hash_engine = type;
698 	hash_type.template_id = tmpl_idx;
699 
700 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
701 				     &hash_type, sizeof(hash_type),
702 				     &hash_type, &out_size);
703 	if (err || !out_size || hash_type.mgmt_msg_head.status) {
704 		PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x",
705 			err, hash_type.mgmt_msg_head.status, out_size);
706 		return -EINVAL;
707 	}
708 
709 	return 0;
710 }
711 
712 int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
713 {
714 	struct nic_rss_indirect_tbl *indir_tbl;
715 	struct hinic_cmd_buf *cmd_buf;
716 	int i;
717 	u32 *temp;
718 	u32 indir_size;
719 	u64 out_param;
720 	int err;
721 
722 	if (!hwdev || !indir_table) {
723 		PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
724 		return -EINVAL;
725 	}
726 
727 	cmd_buf = hinic_alloc_cmd_buf(hwdev);
728 	if (!cmd_buf) {
729 		PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
730 		return -ENOMEM;
731 	}
732 
733 	cmd_buf->size = sizeof(struct nic_rss_indirect_tbl);
734 	indir_tbl = cmd_buf->buf;
735 	indir_tbl->group_index = cpu_to_be32(tmpl_idx);
736 
737 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
738 		indir_tbl->entry[i] = (u8)(*(indir_table + i));
739 
740 		if (0x3 == (i & 0x3)) {
741 			temp = (u32 *)&indir_tbl->entry[i - 3];
742 			*temp = cpu_to_be32(*temp);
743 		}
744 	}
745 
746 	/* configure the rss indirect table by command queue */
747 	indir_size = HINIC_RSS_INDIR_SIZE / 2;
748 	indir_tbl->offset = 0;
749 	indir_tbl->size = cpu_to_be32(indir_size);
750 
751 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
752 				     HINIC_MOD_L2NIC,
753 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
754 				     cmd_buf, &out_param, 0);
755 	if (err || out_param != 0) {
756 		PMD_DRV_LOG(ERR, "Failed to set rss indir table");
757 		err = -EFAULT;
758 		goto free_buf;
759 	}
760 
761 	indir_tbl->offset = cpu_to_be32(indir_size);
762 	indir_tbl->size = cpu_to_be32(indir_size);
763 	memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size);
764 
765 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
766 				     HINIC_MOD_L2NIC,
767 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
768 				     cmd_buf, &out_param, 0);
769 	if (err || out_param != 0) {
770 		PMD_DRV_LOG(ERR, "Failed to set rss indir table");
771 		err = -EFAULT;
772 	}
773 
774 free_buf:
775 	hinic_free_cmd_buf(hwdev, cmd_buf);
776 
777 	return err;
778 }
779 
780 int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
781 {
782 	struct hinic_rss_indir_table rss_cfg;
783 	u16 out_size = sizeof(rss_cfg);
784 	int err = 0, i;
785 
786 	if (!hwdev || !indir_table) {
787 		PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
788 		return -EINVAL;
789 	}
790 
791 	memset(&rss_cfg, 0, sizeof(rss_cfg));
792 	rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
793 	rss_cfg.func_id = hinic_global_func_id(hwdev);
794 	rss_cfg.template_id = (u8)tmpl_idx;
795 
796 	err = l2nic_msg_to_mgmt_sync(hwdev,
797 				     HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
798 				     &rss_cfg, sizeof(rss_cfg), &rss_cfg,
799 				     &out_size);
800 	if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
801 		PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x",
802 			err, rss_cfg.mgmt_msg_head.status, out_size);
803 		return -EINVAL;
804 	}
805 
806 	hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
807 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
808 		indir_table[i] = rss_cfg.indir[i];
809 
810 	return 0;
811 }
812 
813 int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc)
814 {
815 	struct hinic_rss_config rss_cfg;
816 	u16 out_size = sizeof(rss_cfg);
817 	int err;
818 
819 	/* micro code required: number of TC should be power of 2 */
820 	if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) {
821 		PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2",
822 			tc_num);
823 		return -EINVAL;
824 	}
825 
826 	memset(&rss_cfg, 0, sizeof(rss_cfg));
827 	rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
828 	rss_cfg.func_id = hinic_global_func_id(hwdev);
829 	rss_cfg.rss_en = rss_en;
830 	rss_cfg.template_id = tmpl_idx;
831 	rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
832 
833 	memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX);
834 
835 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG,
836 				     &rss_cfg, sizeof(rss_cfg), &rss_cfg,
837 				     &out_size);
838 	if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
839 		PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x",
840 			err, rss_cfg.mgmt_msg_head.status, out_size);
841 		return -EINVAL;
842 	}
843 
844 	return 0;
845 }
846 
847 /**
848  * hinic_rss_template_alloc - get rss template id from the chip,
849  *			      all functions share 96 templates.
850  * @hwdev: the pointer to the private hardware device object
851  * @tmpl_idx: index of rss template from chip.
852  * Return: 0 on success and stats is filled, negative error value otherwise.
853  **/
854 int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
855 {
856 	struct hinic_rss_template_mgmt template_mgmt;
857 	u16 out_size = sizeof(template_mgmt);
858 	int err;
859 
860 	if (!hwdev || !tmpl_idx) {
861 		PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL");
862 		return -EINVAL;
863 	}
864 
865 	memset(&template_mgmt, 0, sizeof(template_mgmt));
866 	template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
867 	template_mgmt.func_id = hinic_global_func_id(hwdev);
868 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
869 
870 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
871 				     &template_mgmt, sizeof(template_mgmt),
872 				     &template_mgmt, &out_size);
873 	if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
874 		PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x",
875 			err, template_mgmt.mgmt_msg_head.status, out_size);
876 		return -EINVAL;
877 	}
878 
879 	*tmpl_idx = template_mgmt.template_id;
880 
881 	return 0;
882 }
883 
884 /**
885  * hinic_rss_template_alloc - free rss template id to the chip
886  * @hwdev: the hardware interface of a nic device
887  * @tmpl_idx: index of rss template from NIC.
888  * Return: 0 on success and stats is filled, negative error value otherwise.
889  **/
890 int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
891 {
892 	struct hinic_rss_template_mgmt template_mgmt;
893 	u16 out_size = sizeof(template_mgmt);
894 	int err;
895 
896 	if (!hwdev) {
897 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
898 		return -EINVAL;
899 	}
900 
901 	memset(&template_mgmt, 0, sizeof(template_mgmt));
902 	template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
903 	template_mgmt.func_id = hinic_global_func_id(hwdev);
904 	template_mgmt.template_id = tmpl_idx;
905 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
906 
907 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
908 				     &template_mgmt, sizeof(template_mgmt),
909 				     &template_mgmt, &out_size);
910 	if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
911 		PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x",
912 			err, template_mgmt.mgmt_msg_head.status, out_size);
913 		return -EINVAL;
914 	}
915 
916 	return 0;
917 }
918 
919 /**
920  * hinic_set_rx_vhd_mode - change rx buffer size after initialization,
921  * @hwdev: the hardware interface of a nic device
922  * @mode: not needed.
923  * @rx_buf_sz: receive buffer size.
924  * @return
925  *   0 on success and stats is filled,
926  *   negative error value otherwise.
927  */
928 int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
929 {
930 	struct hinic_set_vhd_mode vhd_mode_cfg;
931 	u16 out_size = sizeof(vhd_mode_cfg);
932 	int err;
933 
934 	if (!hwdev) {
935 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
936 		return -EINVAL;
937 	}
938 
939 	memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg));
940 
941 	vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
942 	vhd_mode_cfg.func_id = hinic_global_func_id(hwdev);
943 	vhd_mode_cfg.vhd_type = vhd_mode;
944 	vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz;
945 
946 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG,
947 				     &vhd_mode_cfg, sizeof(vhd_mode_cfg),
948 				     &vhd_mode_cfg, &out_size);
949 	if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) {
950 		PMD_DRV_LOG(ERR,
951 			"Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
952 			err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
953 
954 		return -EIO;
955 	}
956 
957 	return 0;
958 }
959 
960 int hinic_set_rx_mode(void *hwdev, u32 enable)
961 {
962 	struct hinic_rx_mode_config rx_mode_cfg;
963 	u16 out_size = sizeof(rx_mode_cfg);
964 	int err;
965 
966 	if (!hwdev) {
967 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
968 		return -EINVAL;
969 	}
970 
971 	memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
972 	rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
973 	rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
974 	rx_mode_cfg.rx_mode = enable;
975 
976 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
977 				     &rx_mode_cfg, sizeof(rx_mode_cfg),
978 				     &rx_mode_cfg, &out_size);
979 	if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) {
980 		PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x",
981 			err, rx_mode_cfg.mgmt_msg_head.status, out_size);
982 		return -EINVAL;
983 	}
984 
985 	return 0;
986 }
987 
988 int hinic_set_rx_csum_offload(void *hwdev, u32 en)
989 {
990 	struct hinic_checksum_offload rx_csum_cfg;
991 	u16 out_size = sizeof(rx_csum_cfg);
992 	int err;
993 
994 	if (!hwdev) {
995 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
996 		return -EINVAL;
997 	}
998 
999 	memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg));
1000 	rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1001 	rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
1002 	rx_csum_cfg.rx_csum_offload = en;
1003 
1004 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
1005 				     &rx_csum_cfg, sizeof(rx_csum_cfg),
1006 				     &rx_csum_cfg, &out_size);
1007 	if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) {
1008 		PMD_DRV_LOG(ERR,
1009 			"Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x",
1010 			err, rx_csum_cfg.mgmt_msg_head.status, out_size);
1011 		return -EINVAL;
1012 	}
1013 
1014 	return 0;
1015 }
1016 
1017 int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num)
1018 {
1019 	struct hinic_lro_config lro_cfg;
1020 	u16 out_size = sizeof(lro_cfg);
1021 	int err;
1022 
1023 	if (!hwdev) {
1024 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1025 		return -EINVAL;
1026 	}
1027 
1028 	memset(&lro_cfg, 0, sizeof(lro_cfg));
1029 	lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1030 	lro_cfg.func_id = hinic_global_func_id(hwdev);
1031 	lro_cfg.lro_ipv4_en = ipv4_en;
1032 	lro_cfg.lro_ipv6_en = ipv6_en;
1033 	lro_cfg.lro_max_wqe_num = max_wqe_num;
1034 
1035 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO,
1036 				     &lro_cfg, sizeof(lro_cfg), &lro_cfg,
1037 				     &out_size);
1038 	if (err || !out_size || lro_cfg.mgmt_msg_head.status) {
1039 		PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x",
1040 			err, lro_cfg.mgmt_msg_head.status, out_size);
1041 		return -EINVAL;
1042 	}
1043 
1044 	return 0;
1045 }
1046 
1047 int hinic_set_anti_attack(void *hwdev, bool enable)
1048 {
1049 	struct hinic_port_anti_attack_rate rate;
1050 	u16 out_size = sizeof(rate);
1051 	int err;
1052 
1053 	if (!hwdev) {
1054 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1055 		return -EINVAL;
1056 	}
1057 
1058 	memset(&rate, 0, sizeof(rate));
1059 	rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1060 	rate.func_id = hinic_global_func_id(hwdev);
1061 	rate.enable = enable;
1062 	rate.cir = ANTI_ATTACK_DEFAULT_CIR;
1063 	rate.xir = ANTI_ATTACK_DEFAULT_XIR;
1064 	rate.cbs = ANTI_ATTACK_DEFAULT_CBS;
1065 	rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
1066 
1067 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
1068 				     &rate, sizeof(rate), &rate,
1069 				     &out_size);
1070 	if (err || !out_size || rate.mgmt_msg_head.status) {
1071 		PMD_DRV_LOG(ERR, "can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
1072 			(enable ? "enable" : "disable"), err,
1073 			rate.mgmt_msg_head.status, out_size);
1074 		return -EINVAL;
1075 	}
1076 
1077 	return 0;
1078 }
1079 
1080 /* Set autoneg status and restart port link status */
1081 int hinic_reset_port_link_cfg(void *hwdev)
1082 {
1083 	struct hinic_reset_link_cfg reset_cfg;
1084 	u16 out_size = sizeof(reset_cfg);
1085 	int err;
1086 
1087 	memset(&reset_cfg, 0, sizeof(reset_cfg));
1088 	reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1089 	reset_cfg.func_id = hinic_global_func_id(hwdev);
1090 
1091 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
1092 				     &reset_cfg, sizeof(reset_cfg),
1093 				     &reset_cfg, &out_size);
1094 	if (err || !out_size || reset_cfg.mgmt_msg_head.status) {
1095 		PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x",
1096 			err, reset_cfg.mgmt_msg_head.status, out_size);
1097 		return -EFAULT;
1098 	}
1099 
1100 	return 0;
1101 }
1102 
1103 int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
1104 {
1105 	struct hinic_fast_recycled_mode fast_recycled_mode;
1106 	u16 out_size = sizeof(fast_recycled_mode);
1107 	int err;
1108 
1109 	if (!hwdev) {
1110 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1111 		return -EINVAL;
1112 	}
1113 
1114 	memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode));
1115 	fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1116 	fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
1117 	fast_recycled_mode.fast_recycled_mode = mode;
1118 
1119 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1120 				     HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET,
1121 				     &fast_recycled_mode,
1122 				     sizeof(fast_recycled_mode),
1123 				     &fast_recycled_mode, &out_size, 0);
1124 	if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
1125 		PMD_DRV_LOG(ERR,
1126 			"Failed to set recycle mode, ret = %d",
1127 			fast_recycled_mode.mgmt_msg_head.status);
1128 		return -EFAULT;
1129 	}
1130 
1131 	return 0;
1132 }
1133 
1134 void hinic_clear_vport_stats(struct hinic_hwdev *hwdev)
1135 {
1136 	struct hinic_clear_vport_stats clear_vport_stats;
1137 	u16 out_size = sizeof(clear_vport_stats);
1138 	int err;
1139 
1140 	if (!hwdev) {
1141 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1142 		return;
1143 	}
1144 
1145 	memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
1146 	clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1147 	clear_vport_stats.func_id = hinic_global_func_id(hwdev);
1148 
1149 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT,
1150 				     &clear_vport_stats,
1151 				     sizeof(clear_vport_stats),
1152 				     &clear_vport_stats, &out_size);
1153 	if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) {
1154 		PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x",
1155 			err, clear_vport_stats.mgmt_msg_head.status, out_size);
1156 	}
1157 }
1158 
1159 void hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev)
1160 {
1161 	struct hinic_clear_port_stats clear_phy_port_stats;
1162 	u16 out_size = sizeof(clear_phy_port_stats);
1163 	int err;
1164 
1165 	if (!hwdev) {
1166 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1167 		return;
1168 	}
1169 
1170 	memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats));
1171 	clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1172 	clear_phy_port_stats.func_id = hinic_global_func_id(hwdev);
1173 
1174 	err = l2nic_msg_to_mgmt_sync(hwdev,
1175 				     HINIC_PORT_CMD_CLEAR_PORT_STATISTICS,
1176 				     &clear_phy_port_stats,
1177 				     sizeof(clear_phy_port_stats),
1178 				     &clear_phy_port_stats, &out_size);
1179 	if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) {
1180 		PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x",
1181 			err, clear_phy_port_stats.mgmt_msg_head.status,
1182 			out_size);
1183 	}
1184 }
1185 
1186 int hinic_set_link_status_follow(void *hwdev,
1187 				 enum hinic_link_follow_status status)
1188 {
1189 	struct hinic_set_link_follow follow;
1190 	u16 out_size = sizeof(follow);
1191 	int err;
1192 
1193 	if (!hwdev)
1194 		return -EINVAL;
1195 
1196 	if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) {
1197 		PMD_DRV_LOG(ERR,
1198 			"Invalid link follow status: %d", status);
1199 		return -EINVAL;
1200 	}
1201 
1202 	memset(&follow, 0, sizeof(follow));
1203 	follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1204 	follow.func_id = hinic_global_func_id(hwdev);
1205 	follow.follow_status = status;
1206 
1207 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
1208 				     &follow, sizeof(follow),
1209 				     &follow, &out_size);
1210 	if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
1211 	     follow.mgmt_msg_head.status) || err || !out_size) {
1212 		PMD_DRV_LOG(ERR,
1213 			"Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x",
1214 			err, follow.mgmt_msg_head.status, out_size);
1215 		return -EFAULT;
1216 	}
1217 
1218 	return follow.mgmt_msg_head.status;
1219 }
1220 
1221 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
1222 {
1223 	struct hinic_link_mode_cmd link_mode;
1224 	u16 out_size = sizeof(link_mode);
1225 	int err;
1226 
1227 	if (!hwdev || !supported || !advertised)
1228 		return -EINVAL;
1229 
1230 	memset(&link_mode, 0, sizeof(link_mode));
1231 	link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1232 	link_mode.func_id = hinic_global_func_id(hwdev);
1233 
1234 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
1235 				     &link_mode, sizeof(link_mode),
1236 				     &link_mode, &out_size);
1237 	if (err || !out_size || link_mode.mgmt_msg_head.status) {
1238 		PMD_DRV_LOG(ERR,
1239 			"Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x",
1240 			err, link_mode.mgmt_msg_head.status, out_size);
1241 		return -EINVAL;
1242 	}
1243 
1244 	*supported = link_mode.supported;
1245 	*advertised = link_mode.advertised;
1246 
1247 	return 0;
1248 }
1249 
1250 /**
1251  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport fake
1252  * failed when device start.
1253  * @hwdev: the hardware interface of a nic device
1254  * Return: 0 on success, negative error value otherwise.
1255  **/
1256 int hinic_flush_qp_res(void *hwdev)
1257 {
1258 	struct hinic_clear_qp_resource qp_res;
1259 	u16 out_size = sizeof(qp_res);
1260 	int err;
1261 
1262 	memset(&qp_res, 0, sizeof(qp_res));
1263 	qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1264 	qp_res.func_id = hinic_global_func_id(hwdev);
1265 
1266 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES,
1267 				     &qp_res, sizeof(qp_res), &qp_res,
1268 				     &out_size);
1269 	if (err || !out_size || qp_res.mgmt_msg_head.status) {
1270 		PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x",
1271 			err, qp_res.mgmt_msg_head.status, out_size);
1272 		return -EINVAL;
1273 	}
1274 
1275 	return 0;
1276 }
1277