xref: /dpdk/drivers/net/hinic/base/hinic_pmd_niccfg.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
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 #include "hinic_pmd_mbox.h"
14 
15 #define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in,		\
16 			       in_size, buf_out, out_size)	\
17 	hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, cmd,	\
18 			buf_in, in_size,			\
19 			buf_out, out_size, 0)
20 
21 /**
22  * hinic_init_function_table - Initialize function table.
23  *
24  * @param hwdev
25  *   The hardware interface of a nic device.
26  * @param rx_buf_sz
27  *   Receive buffer size.
28  *
29  * @return
30  *   0 on success.
31  *   negative error value otherwise.
32  */
33 int hinic_init_function_table(void *hwdev, u16 rx_buf_sz)
34 {
35 	struct hinic_function_table function_table;
36 	u16 out_size = sizeof(function_table);
37 	int err;
38 
39 	if (!hwdev) {
40 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
41 		return -EINVAL;
42 	}
43 
44 	memset(&function_table, 0, sizeof(function_table));
45 	function_table.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
46 	function_table.func_id = hinic_global_func_id(hwdev);
47 	function_table.mtu = 0x3FFF;	/* default, max mtu */
48 	function_table.rx_wqe_buf_size = rx_buf_sz;
49 
50 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
51 				     HINIC_PORT_CMD_INIT_FUNC,
52 				     &function_table, sizeof(function_table),
53 				     &function_table, &out_size, 0);
54 	if (err || function_table.mgmt_msg_head.status || !out_size) {
55 		PMD_DRV_LOG(ERR,
56 			"Failed to init func table, err: %d, status: 0x%x, out size: 0x%x",
57 			err, function_table.mgmt_msg_head.status, out_size);
58 		return -EIO;
59 	}
60 
61 	return 0;
62 }
63 
64 /**
65  * hinic_get_base_qpn - Get global queue number.
66  *
67  * @param hwdev
68  *   The hardware interface of a nic device.
69  * @param global_qpn
70  *   Global queue number.
71  *
72  * @return
73  *   0 on success.
74  *   negative error value otherwise.
75  */
76 int hinic_get_base_qpn(void *hwdev, u16 *global_qpn)
77 {
78 	struct hinic_cmd_qpn cmd_qpn;
79 	u16 out_size = sizeof(cmd_qpn);
80 	int err;
81 
82 	if (!hwdev || !global_qpn) {
83 		PMD_DRV_LOG(ERR, "Hwdev or global_qpn is NULL");
84 		return -EINVAL;
85 	}
86 
87 	memset(&cmd_qpn, 0, sizeof(cmd_qpn));
88 	cmd_qpn.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
89 	cmd_qpn.func_id = hinic_global_func_id(hwdev);
90 
91 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
92 				     HINIC_PORT_CMD_GET_GLOBAL_QPN,
93 				     &cmd_qpn, sizeof(cmd_qpn), &cmd_qpn,
94 				     &out_size, 0);
95 	if (err || !out_size || cmd_qpn.mgmt_msg_head.status) {
96 		PMD_DRV_LOG(ERR,
97 			"Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x",
98 			err, cmd_qpn.mgmt_msg_head.status, out_size);
99 		return -EIO;
100 	}
101 
102 	*global_qpn = cmd_qpn.base_qpn;
103 
104 	return 0;
105 }
106 
107 /**
108  * hinic_set_mac - Init mac_vlan table in NIC.
109  *
110  * @param hwdev
111  *   The hardware interface of a nic device.
112  * @param mac_addr
113  *   MAC address.
114  * @param vlan_id
115  *   Set 0 for mac_vlan table initialization.
116  * @param func_id
117  *   Global function id of NIC.
118  *
119  * @return
120  *   0 on success.
121  *   negative error value otherwise.
122  */
123 int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
124 {
125 	struct hinic_port_mac_set mac_info;
126 	u16 out_size = sizeof(mac_info);
127 	int err;
128 
129 	if (!hwdev || !mac_addr) {
130 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
131 		return -EINVAL;
132 	}
133 
134 	memset(&mac_info, 0, sizeof(mac_info));
135 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
136 	mac_info.func_id = func_id;
137 	mac_info.vlan_id = vlan_id;
138 	memmove(mac_info.mac, mac_addr, ETH_ALEN);
139 
140 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
141 				     sizeof(mac_info), &mac_info, &out_size);
142 	if (err || !out_size || (mac_info.mgmt_msg_head.status &&
143 	    mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
144 		PMD_DRV_LOG(ERR, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x",
145 			err, mac_info.mgmt_msg_head.status, out_size);
146 		return -EIO;
147 	}
148 
149 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
150 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore set operation.");
151 		return HINIC_PF_SET_VF_ALREADY;
152 	}
153 
154 	return 0;
155 }
156 
157 /**
158  * hinic_del_mac - Uninit mac_vlan table in NIC.
159  *
160  * @param hwdev
161  *   The hardware interface of a nic device.
162  * @param mac_addr
163  *   MAC address.
164  * @param vlan_id
165  *   Set 0 for mac_vlan table initialization.
166  * @param func_id
167  *   Global function id of NIC.
168  *
169  * @return
170  *   0 on success.
171  *   negative error value otherwise.
172  */
173 int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
174 {
175 	struct hinic_port_mac_set mac_info;
176 	u16 out_size = sizeof(mac_info);
177 	int err;
178 
179 	if (!hwdev || !mac_addr) {
180 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
181 		return -EINVAL;
182 	}
183 
184 	if (vlan_id >= VLAN_N_VID) {
185 		PMD_DRV_LOG(ERR, "Invalid VLAN number");
186 		return -EINVAL;
187 	}
188 
189 	memset(&mac_info, 0, sizeof(mac_info));
190 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
191 	mac_info.func_id = func_id;
192 	mac_info.vlan_id = vlan_id;
193 	memmove(mac_info.mac, mac_addr, ETH_ALEN);
194 
195 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_DEL_MAC, &mac_info,
196 				     sizeof(mac_info), &mac_info, &out_size);
197 	if (err || !out_size || (mac_info.mgmt_msg_head.status &&
198 		mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
199 		PMD_DRV_LOG(ERR, "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x",
200 			err, mac_info.mgmt_msg_head.status, out_size);
201 		return -EIO;
202 	}
203 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
204 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore delete operation.");
205 		return HINIC_PF_SET_VF_ALREADY;
206 	}
207 
208 	return 0;
209 }
210 
211 /**
212  * hinic_get_default_mac - Get default mac address from hardware.
213  *
214  * @param hwdev
215  *   The hardware interface of a nic device.
216  * @param mac_addr
217  *   MAC address.
218  *
219  * @return
220  *   0 on success.
221  *   negative error value otherwise.
222  */
223 int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
224 {
225 	struct hinic_port_mac_set mac_info;
226 	u16 out_size = sizeof(mac_info);
227 	int err;
228 
229 	if (!hwdev || !mac_addr) {
230 		PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
231 		return -EINVAL;
232 	}
233 
234 	memset(&mac_info, 0, sizeof(mac_info));
235 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
236 	mac_info.func_id = hinic_global_func_id(hwdev);
237 
238 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MAC,
239 				     &mac_info, sizeof(mac_info),
240 				     &mac_info, &out_size);
241 	if (err || !out_size || mac_info.mgmt_msg_head.status) {
242 		PMD_DRV_LOG(ERR, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x",
243 			err, mac_info.mgmt_msg_head.status, out_size);
244 		return -EIO;
245 	}
246 
247 	memmove(mac_addr, mac_info.mac, ETH_ALEN);
248 
249 	return 0;
250 }
251 
252 /**
253 *  hinic_update_mac - Update mac address to hardware.
254 *
255 * @param hwdev
256 *   The hardware interface of a nic device.
257 * @param old_mac
258 *   Old mac address.
259 * @param new_mac
260 *   New mac address.
261 * @param vlan_id
262 *   Set 0 for mac_vlan table initialization.
263 * @param func_id
264 *   Global function id of NIC.
265 *
266 * @return
267 *   0 on success.
268 *   negative error value otherwise.
269 */
270 int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id,
271 		     u16 func_id)
272 {
273 	struct hinic_port_mac_update mac_info;
274 	u16 out_size = sizeof(mac_info);
275 	int err;
276 
277 	if (!hwdev || !old_mac || !new_mac) {
278 		PMD_DRV_LOG(ERR, "Hwdev, old_mac or new_mac is NULL");
279 		return -EINVAL;
280 	}
281 
282 	memset(&mac_info, 0, sizeof(mac_info));
283 	mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
284 	mac_info.func_id = func_id;
285 	mac_info.vlan_id = vlan_id;
286 	memcpy(mac_info.old_mac, old_mac, ETH_ALEN);
287 	memcpy(mac_info.new_mac, new_mac, ETH_ALEN);
288 
289 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UPDATE_MAC,
290 				     &mac_info, sizeof(mac_info),
291 				     &mac_info, &out_size);
292 	if (err || !out_size ||
293 	    (mac_info.mgmt_msg_head.status &&
294 	     mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
295 		PMD_DRV_LOG(ERR, "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x",
296 			    err, mac_info.mgmt_msg_head.status, out_size);
297 		return -EIO;
298 	}
299 	if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
300 		PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore update operation");
301 		return HINIC_PF_SET_VF_ALREADY;
302 	}
303 
304 	return 0;
305 }
306 
307 /**
308  * hinic_set_port_mtu -  Set MTU to port.
309  *
310  * @param hwdev
311  *   The hardware interface of a nic device.
312  * @param new_mtu
313  *   MTU size.
314  *
315  * @return
316  *   0 on success.
317  *   negative error value otherwise.
318  */
319 int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
320 {
321 	struct hinic_mtu mtu_info;
322 	u16 out_size = sizeof(mtu_info);
323 	int err;
324 
325 	if (!hwdev) {
326 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
327 		return -EINVAL;
328 	}
329 
330 	memset(&mtu_info, 0, sizeof(mtu_info));
331 	mtu_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
332 	mtu_info.func_id = hinic_global_func_id(hwdev);
333 	mtu_info.mtu = new_mtu;
334 
335 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
336 				     &mtu_info, sizeof(mtu_info),
337 				     &mtu_info, &out_size);
338 	if (err || !out_size || mtu_info.mgmt_msg_head.status) {
339 		PMD_DRV_LOG(ERR, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x",
340 			err, mtu_info.mgmt_msg_head.status, out_size);
341 		return -EIO;
342 	}
343 
344 	return 0;
345 }
346 
347 /**
348  * hinic_add_remove_vlan - Add or remove vlan id to vlan elb table.
349  *
350  * @param hwdev
351  *   The hardware interface of a nic device.
352  * @param vlan_id
353  *   Vlan id.
354  * @param func_id
355  *   Global function id of NIC.
356  * @param add
357  *   Add or remove operation.
358  *
359  * @return
360  *   0 on success.
361  *   negative error value otherwise.
362  */
363 int hinic_add_remove_vlan(void *hwdev, u16 vlan_id, u16 func_id, bool add)
364 {
365 	struct hinic_vlan_config vlan_info;
366 	u16 out_size = sizeof(vlan_info);
367 	u8 cmd;
368 	int err;
369 
370 	if (!hwdev) {
371 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
372 		return -EINVAL;
373 	}
374 
375 	cmd = add ? HINIC_PORT_CMD_ADD_VLAN : HINIC_PORT_CMD_DEL_VLAN;
376 
377 	memset(&vlan_info, 0, sizeof(vlan_info));
378 	vlan_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
379 	vlan_info.func_id = func_id;
380 	vlan_info.vlan_id = vlan_id;
381 
382 	err = l2nic_msg_to_mgmt_sync(hwdev, cmd, &vlan_info, sizeof(vlan_info),
383 				     &vlan_info, &out_size);
384 	if (err || !out_size || vlan_info.mgmt_msg_head.status) {
385 		PMD_DRV_LOG(ERR,
386 			"Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x",
387 			add ? "add" : "remove", err,
388 			vlan_info.mgmt_msg_head.status, out_size);
389 		return -EIO;
390 	}
391 
392 	return 0;
393 }
394 
395 /**
396  * hinic_config_vlan_filter - Enable or Disable vlan filter.
397  *
398  * @param hwdev
399  *   The hardware interface of a nic device.
400  * @param vlan_filter_ctrl
401  *   Enable or Disable.
402  *
403  * @return
404  *   0 on success.
405  *   negative error value otherwise.
406  */
407 int hinic_config_vlan_filter(void *hwdev, u32 vlan_filter_ctrl)
408 {
409 	struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
410 	struct hinic_vlan_filter vlan_filter;
411 	u16 out_size = sizeof(vlan_filter);
412 	int err;
413 
414 	if (!hwdev)
415 		return -EINVAL;
416 
417 	memset(&vlan_filter, 0, sizeof(vlan_filter));
418 	vlan_filter.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
419 	vlan_filter.func_id = hinic_global_func_id(nic_hwdev);
420 	vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl;
421 
422 	err = l2nic_msg_to_mgmt_sync(nic_hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,
423 				     &vlan_filter, sizeof(vlan_filter),
424 				     &vlan_filter, &out_size);
425 	if (vlan_filter.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
426 		err = HINIC_MGMT_CMD_UNSUPPORTED;
427 	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
428 		(HINIC_IS_VF(nic_hwdev))) {
429 		err = HINIC_MGMT_CMD_UNSUPPORTED;
430 	} else if (err || !out_size || vlan_filter.mgmt_msg_head.status) {
431 		PMD_DRV_LOG(ERR,
432 			"Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x",
433 			vlan_filter_ctrl, err,
434 			vlan_filter.mgmt_msg_head.status, out_size);
435 		err = -EIO;
436 	}
437 
438 	return err;
439 }
440 
441 /**
442  * hinic_set_rx_vlan_offload - Enable or Disable vlan offload.
443  *
444  * @param hwdev
445  *   The hardware interface of a nic device.
446  * @param en
447  *   Enable or Disable.
448  *
449  * @return
450  *   0 on success.
451  *   negative error value otherwise.
452  */
453 int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
454 {
455 	struct hinic_vlan_offload vlan_cfg;
456 	u16 out_size = sizeof(vlan_cfg);
457 	int err;
458 
459 	if (!hwdev) {
460 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
461 		return -EINVAL;
462 	}
463 
464 	memset(&vlan_cfg, 0, sizeof(vlan_cfg));
465 	vlan_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
466 	vlan_cfg.func_id = hinic_global_func_id(hwdev);
467 	vlan_cfg.vlan_rx_offload = en;
468 
469 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
470 				     &vlan_cfg, sizeof(vlan_cfg),
471 				     &vlan_cfg, &out_size);
472 	if (err || !out_size || vlan_cfg.mgmt_msg_head.status) {
473 		PMD_DRV_LOG(ERR,
474 			"Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x",
475 			err, vlan_cfg.mgmt_msg_head.status, out_size);
476 		return -EIO;
477 	}
478 
479 	return 0;
480 }
481 
482 /**
483  * hinic_get_link_status - Get link status from hardware.
484  *
485  * @param hwdev
486  *   The hardware interface of a nic device.
487  * @param link_state
488  *   Link status.
489  *
490  * @return
491  *   0 on success.
492  *   negative error value otherwise.
493  */
494 int hinic_get_link_status(void *hwdev, u8 *link_state)
495 {
496 	struct hinic_get_link get_link;
497 	u16 out_size = sizeof(get_link);
498 	int err;
499 
500 	if (!hwdev || !link_state) {
501 		PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL");
502 		return -EINVAL;
503 	}
504 
505 	memset(&get_link, 0, sizeof(get_link));
506 	get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
507 	get_link.func_id = hinic_global_func_id(hwdev);
508 
509 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
510 				     &get_link, sizeof(get_link),
511 				     &get_link, &out_size);
512 	if (err || !out_size || get_link.mgmt_msg_head.status) {
513 		PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x",
514 			err, get_link.mgmt_msg_head.status, out_size);
515 		return -EIO;
516 	}
517 
518 	*link_state = get_link.link_status;
519 
520 	return 0;
521 }
522 
523 /**
524  * hinic_set_vport_enable - Notify firmware that driver is ready or not.
525  *
526  * @param hwdev
527  *   The hardware interface of a nic device.
528  * @param enable
529  *   1: driver is ready; 0: driver is not ok.
530  *
531  * @return
532  *   0 on success.
533  *   negative error value otherwise.
534  */
535 int hinic_set_vport_enable(void *hwdev, bool enable)
536 {
537 	struct hinic_vport_state en_state;
538 	u16 out_size = sizeof(en_state);
539 	int err;
540 
541 	if (!hwdev) {
542 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
543 		return -EINVAL;
544 	}
545 
546 	memset(&en_state, 0, sizeof(en_state));
547 	en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
548 	en_state.func_id = hinic_global_func_id(hwdev);
549 	en_state.state = (enable ? 1 : 0);
550 
551 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
552 				     &en_state, sizeof(en_state),
553 				     &en_state, &out_size);
554 	if (err || !out_size || en_state.mgmt_msg_head.status) {
555 		PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x",
556 			err, en_state.mgmt_msg_head.status, out_size);
557 		return -EIO;
558 	}
559 
560 	return 0;
561 }
562 
563 /**
564  * hinic_set_port_enable - Open MAG to receive packets.
565  *
566  * @param hwdev
567  *   The hardware interface of a nic device.
568  * @param enable
569  *   1: open MAG; 0: close MAG.
570  *
571  * @return
572  *   0 on success.
573  *   negative error value otherwise.
574  */
575 int hinic_set_port_enable(void *hwdev, bool enable)
576 {
577 	struct hinic_port_state en_state;
578 	u16 out_size = sizeof(en_state);
579 	int err;
580 
581 	if (!hwdev) {
582 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
583 		return -EINVAL;
584 	}
585 
586 	if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
587 		return 0;
588 
589 	memset(&en_state, 0, sizeof(en_state));
590 	en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
591 	en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE);
592 
593 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
594 				     &en_state, sizeof(en_state),
595 				     &en_state, &out_size);
596 	if (err || !out_size || en_state.mgmt_msg_head.status) {
597 		PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x",
598 			err, en_state.mgmt_msg_head.status, out_size);
599 		return -EIO;
600 	}
601 
602 	return 0;
603 }
604 
605 int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
606 {
607 	struct hinic_port_info port_msg;
608 	u16 out_size = sizeof(port_msg);
609 	int err;
610 
611 	if (!hwdev || !port_info) {
612 		PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL");
613 		return -EINVAL;
614 	}
615 
616 	memset(&port_msg, 0, sizeof(port_msg));
617 	port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
618 	port_msg.func_id = hinic_global_func_id(hwdev);
619 
620 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
621 				     &port_msg, sizeof(port_msg),
622 				     &port_msg, &out_size);
623 	if (err || !out_size || port_msg.mgmt_msg_head.status) {
624 		PMD_DRV_LOG(ERR,
625 			"Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
626 			err, port_msg.mgmt_msg_head.status, out_size);
627 		return -EIO;
628 	}
629 
630 	port_info->autoneg_cap = port_msg.autoneg_cap;
631 	port_info->autoneg_state = port_msg.autoneg_state;
632 	port_info->duplex = port_msg.duplex;
633 	port_info->port_type = port_msg.port_type;
634 	port_info->speed = port_msg.speed;
635 
636 	return 0;
637 }
638 
639 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
640 {
641 	struct hinic_pause_config pause_info;
642 	u16 out_size = sizeof(pause_info);
643 	int err;
644 
645 	if (!hwdev) {
646 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
647 		return -EINVAL;
648 	}
649 
650 	memset(&pause_info, 0, sizeof(pause_info));
651 	pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
652 	pause_info.func_id = hinic_global_func_id(hwdev);
653 	pause_info.auto_neg = nic_pause.auto_neg;
654 	pause_info.rx_pause = nic_pause.rx_pause;
655 	pause_info.tx_pause = nic_pause.tx_pause;
656 
657 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
658 				     &pause_info, sizeof(pause_info),
659 				     &pause_info, &out_size);
660 	if (err || !out_size || pause_info.mgmt_msg_head.status) {
661 		PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x",
662 			err, pause_info.mgmt_msg_head.status, out_size);
663 		return -EIO;
664 	}
665 
666 	return 0;
667 }
668 
669 int hinic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause)
670 {
671 	struct hinic_pause_config pause_info;
672 	u16 out_size = sizeof(pause_info);
673 	int err;
674 
675 	if (!hwdev || !nic_pause)
676 		return -EINVAL;
677 
678 	memset(&pause_info, 0, sizeof(pause_info));
679 	pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
680 	pause_info.func_id = hinic_global_func_id(hwdev);
681 
682 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO,
683 				     &pause_info, sizeof(pause_info),
684 				     &pause_info, &out_size);
685 	if (err || !out_size || pause_info.mgmt_msg_head.status) {
686 		PMD_DRV_LOG(ERR, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x\n",
687 			err, pause_info.mgmt_msg_head.status, out_size);
688 		return -EIO;
689 	}
690 
691 	nic_pause->auto_neg = pause_info.auto_neg;
692 	nic_pause->rx_pause = pause_info.rx_pause;
693 	nic_pause->tx_pause = pause_info.tx_pause;
694 
695 	return 0;
696 }
697 
698 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
699 		      u8 *pgid, u8 *up_bw, u8 *prio)
700 {
701 	struct hinic_up_ets_cfg ets;
702 	u16 out_size = sizeof(ets);
703 	u16 up_bw_t = 0;
704 	u8 pg_bw_t = 0;
705 	int i, err;
706 
707 	if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) {
708 		PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL");
709 		return -EINVAL;
710 	}
711 
712 	for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
713 		up_bw_t += *(up_bw + i);
714 		pg_bw_t += *(pg_bw + i);
715 
716 		if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
717 			PMD_DRV_LOG(ERR, "Invalid up %d mapping tc: %d", i,
718 				*(up_tc + i));
719 			return -EINVAL;
720 		}
721 	}
722 
723 	if (pg_bw_t != 100 || (up_bw_t % 100) != 0) {
724 		PMD_DRV_LOG(ERR,
725 			"Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t);
726 		return -EINVAL;
727 	}
728 
729 	memset(&ets, 0, sizeof(ets));
730 	ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
731 	ets.port_id = 0;	/* reserved */
732 	memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX);
733 	memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX);
734 	memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX);
735 	memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX);
736 	memcpy(ets.prio, prio, HINIC_DCB_UP_MAX);
737 
738 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS,
739 				     &ets, sizeof(ets), &ets, &out_size);
740 	if (err || ets.mgmt_msg_head.status || !out_size) {
741 		PMD_DRV_LOG(ERR,
742 			"Failed to set ets, err: %d, status: 0x%x, out size: 0x%x",
743 			err, ets.mgmt_msg_head.status, out_size);
744 		return -EIO;
745 	}
746 
747 	return 0;
748 }
749 
750 int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats)
751 {
752 	struct hinic_port_stats_info vport_stats_cmd;
753 	struct hinic_cmd_vport_stats vport_stats_rsp;
754 	u16 out_size = sizeof(vport_stats_rsp);
755 	int err;
756 
757 	if (!hwdev || !stats) {
758 		PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
759 		return -EINVAL;
760 	}
761 
762 	memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp));
763 	memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd));
764 	vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
765 	vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
766 	vport_stats_cmd.func_id = hinic_global_func_id(hwdev);
767 	vport_stats_cmd.stats_size = sizeof(vport_stats_rsp);
768 
769 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
770 				     &vport_stats_cmd, sizeof(vport_stats_cmd),
771 				     &vport_stats_rsp, &out_size);
772 	if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) {
773 		PMD_DRV_LOG(ERR,
774 			"Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x",
775 			err, vport_stats_rsp.mgmt_msg_head.status, out_size);
776 		return -EIO;
777 	}
778 
779 	memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats));
780 
781 	return 0;
782 }
783 
784 int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats)
785 {
786 	struct hinic_port_stats_info port_stats_cmd;
787 	struct hinic_port_stats port_stats_rsp;
788 	u16 out_size = sizeof(port_stats_rsp);
789 	int err;
790 
791 	if (!hwdev || !stats) {
792 		PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
793 		return -EINVAL;
794 	}
795 
796 	memset(&port_stats_rsp, 0, sizeof(port_stats_rsp));
797 	memset(&port_stats_cmd, 0, sizeof(port_stats_cmd));
798 	port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
799 	port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
800 	port_stats_cmd.stats_size = sizeof(port_stats_rsp);
801 
802 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
803 				     &port_stats_cmd, sizeof(port_stats_cmd),
804 				     &port_stats_rsp, &out_size);
805 	if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) {
806 		PMD_DRV_LOG(ERR,
807 			"Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x",
808 			err, port_stats_rsp.mgmt_msg_head.status, out_size);
809 		return -EIO;
810 	}
811 
812 	memcpy(stats, &port_stats_rsp.stats, sizeof(*stats));
813 
814 	return 0;
815 }
816 
817 int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type)
818 {
819 	struct nic_rss_context_tbl *ctx_tbl;
820 	struct hinic_cmd_buf *cmd_buf;
821 	u32 ctx = 0;
822 	u64 out_param;
823 	int err;
824 
825 	if (!hwdev) {
826 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
827 		return -EINVAL;
828 	}
829 
830 	cmd_buf = hinic_alloc_cmd_buf(hwdev);
831 	if (!cmd_buf) {
832 		PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
833 		return -ENOMEM;
834 	}
835 
836 	ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
837 		HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
838 		HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
839 		HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
840 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
841 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
842 		HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
843 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
844 		HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
845 
846 	cmd_buf->size = sizeof(struct nic_rss_context_tbl);
847 
848 	ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf;
849 	ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
850 	ctx_tbl->offset = 0;
851 	ctx_tbl->size = sizeof(u32);
852 	ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
853 	ctx_tbl->rsvd = 0;
854 	ctx_tbl->ctx = cpu_to_be32(ctx);
855 
856 	/* cfg the rss context table by command queue */
857 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
858 				     HINIC_MOD_L2NIC,
859 				     HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
860 				     cmd_buf, &out_param, 0);
861 
862 	hinic_free_cmd_buf(hwdev, cmd_buf);
863 
864 	if (err || out_param != 0) {
865 		PMD_DRV_LOG(ERR, "Failed to set rss context table");
866 		return -EIO;
867 	}
868 
869 	return 0;
870 }
871 
872 int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type)
873 {
874 	struct hinic_rss_context_table ctx_tbl;
875 	u16 out_size = sizeof(ctx_tbl);
876 	int err;
877 
878 	if (!hwdev || !rss_type) {
879 		PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL");
880 		return -EINVAL;
881 	}
882 
883 	ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
884 	ctx_tbl.func_id = hinic_global_func_id(hwdev);
885 	ctx_tbl.template_id = (u8)tmpl_idx;
886 
887 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
888 				     &ctx_tbl, sizeof(ctx_tbl),
889 				     &ctx_tbl, &out_size);
890 	if (err || !out_size || ctx_tbl.mgmt_msg_head.status) {
891 		PMD_DRV_LOG(ERR,
892 			"Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x",
893 			err, ctx_tbl.mgmt_msg_head.status, out_size);
894 		return -EIO;
895 	}
896 
897 	rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
898 	rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
899 	rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
900 	rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
901 	rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
902 	rss_type->tcp_ipv6_ext =
903 			HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT);
904 	rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
905 	rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
906 
907 	return 0;
908 }
909 
910 int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
911 {
912 	struct hinic_rss_template_key temp_key;
913 	u16 out_size = sizeof(temp_key);
914 	int err;
915 
916 	if (!hwdev || !temp) {
917 		PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
918 		return -EINVAL;
919 	}
920 
921 	memset(&temp_key, 0, sizeof(temp_key));
922 	temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
923 	temp_key.func_id = hinic_global_func_id(hwdev);
924 	temp_key.template_id = (u8)tmpl_idx;
925 	memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
926 
927 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
928 				     &temp_key, sizeof(temp_key),
929 				     &temp_key, &out_size);
930 	if (err || !out_size || temp_key.mgmt_msg_head.status) {
931 		PMD_DRV_LOG(ERR,
932 			"Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x",
933 			err, temp_key.mgmt_msg_head.status, out_size);
934 		return -EIO;
935 	}
936 
937 	return 0;
938 }
939 
940 int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
941 {
942 	struct hinic_rss_template_key temp_key;
943 	u16 out_size = sizeof(temp_key);
944 	int err;
945 
946 	if (!hwdev || !temp) {
947 		PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
948 		return -EINVAL;
949 	}
950 
951 	memset(&temp_key, 0, sizeof(temp_key));
952 	temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
953 	temp_key.func_id = hinic_global_func_id(hwdev);
954 	temp_key.template_id = (u8)tmpl_idx;
955 
956 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
957 				     &temp_key, sizeof(temp_key),
958 				     &temp_key, &out_size);
959 	if (err || !out_size || temp_key.mgmt_msg_head.status) {
960 		PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x",
961 			err, temp_key.mgmt_msg_head.status, out_size);
962 		return -EIO;
963 	}
964 
965 	memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
966 
967 	return 0;
968 }
969 
970 /**
971  * hinic_rss_set_hash_engine - Init rss hash function.
972  *
973  * @param hwdev
974  *   The hardware interface of a nic device.
975  * @param tmpl_idx
976  *   Index of rss template from NIC.
977  * @param type
978  *   Hash function, such as Toeplitz or XOR.
979  *
980  * @return
981  *   0 on success.
982  *   negative error value otherwise.
983  */
984 int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
985 {
986 	struct hinic_rss_engine_type hash_type;
987 	u16 out_size = sizeof(hash_type);
988 	int err;
989 
990 	if (!hwdev) {
991 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
992 		return -EINVAL;
993 	}
994 
995 	memset(&hash_type, 0, sizeof(hash_type));
996 	hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
997 	hash_type.func_id = hinic_global_func_id(hwdev);
998 	hash_type.hash_engine = type;
999 	hash_type.template_id = tmpl_idx;
1000 
1001 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
1002 				     &hash_type, sizeof(hash_type),
1003 				     &hash_type, &out_size);
1004 	if (err || !out_size || hash_type.mgmt_msg_head.status) {
1005 		PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x",
1006 			err, hash_type.mgmt_msg_head.status, out_size);
1007 		return -EIO;
1008 	}
1009 
1010 	return 0;
1011 }
1012 
1013 int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
1014 {
1015 	struct nic_rss_indirect_tbl *indir_tbl;
1016 	struct hinic_cmd_buf *cmd_buf;
1017 	int i;
1018 	u32 *temp;
1019 	u32 indir_size;
1020 	u64 out_param;
1021 	int err;
1022 
1023 	if (!hwdev || !indir_table) {
1024 		PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
1025 		return -EINVAL;
1026 	}
1027 
1028 	cmd_buf = hinic_alloc_cmd_buf(hwdev);
1029 	if (!cmd_buf) {
1030 		PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
1031 		return -ENOMEM;
1032 	}
1033 
1034 	cmd_buf->size = sizeof(struct nic_rss_indirect_tbl);
1035 	indir_tbl = cmd_buf->buf;
1036 	indir_tbl->group_index = cpu_to_be32(tmpl_idx);
1037 
1038 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
1039 		indir_tbl->entry[i] = (u8)(*(indir_table + i));
1040 
1041 		if (0x3 == (i & 0x3)) {
1042 			temp = (u32 *)&indir_tbl->entry[i - 3];
1043 			*temp = cpu_to_be32(*temp);
1044 		}
1045 	}
1046 
1047 	/* configure the rss indirect table by command queue */
1048 	indir_size = HINIC_RSS_INDIR_SIZE / 2;
1049 	indir_tbl->offset = 0;
1050 	indir_tbl->size = cpu_to_be32(indir_size);
1051 
1052 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
1053 				     HINIC_MOD_L2NIC,
1054 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
1055 				     cmd_buf, &out_param, 0);
1056 	if (err || out_param != 0) {
1057 		PMD_DRV_LOG(ERR, "Failed to set rss indir table");
1058 		err = -EIO;
1059 		goto free_buf;
1060 	}
1061 
1062 	indir_tbl->offset = cpu_to_be32(indir_size);
1063 	indir_tbl->size = cpu_to_be32(indir_size);
1064 	memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size);
1065 
1066 	err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
1067 				     HINIC_MOD_L2NIC,
1068 				     HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
1069 				     cmd_buf, &out_param, 0);
1070 	if (err || out_param != 0) {
1071 		PMD_DRV_LOG(ERR, "Failed to set rss indir table");
1072 		err = -EIO;
1073 	}
1074 
1075 free_buf:
1076 	hinic_free_cmd_buf(hwdev, cmd_buf);
1077 
1078 	return err;
1079 }
1080 
1081 int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
1082 {
1083 	struct hinic_rss_indir_table rss_cfg;
1084 	u16 out_size = sizeof(rss_cfg);
1085 	int err = 0, i;
1086 
1087 	if (!hwdev || !indir_table) {
1088 		PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
1089 		return -EINVAL;
1090 	}
1091 
1092 	memset(&rss_cfg, 0, sizeof(rss_cfg));
1093 	rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1094 	rss_cfg.func_id = hinic_global_func_id(hwdev);
1095 	rss_cfg.template_id = (u8)tmpl_idx;
1096 
1097 	err = l2nic_msg_to_mgmt_sync(hwdev,
1098 				     HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
1099 				     &rss_cfg, sizeof(rss_cfg), &rss_cfg,
1100 				     &out_size);
1101 	if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
1102 		PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x",
1103 			err, rss_cfg.mgmt_msg_head.status, out_size);
1104 		return -EIO;
1105 	}
1106 
1107 	hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
1108 	for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
1109 		indir_table[i] = rss_cfg.indir[i];
1110 
1111 	return 0;
1112 }
1113 
1114 int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc)
1115 {
1116 	struct hinic_rss_config rss_cfg;
1117 	u16 out_size = sizeof(rss_cfg);
1118 	int err;
1119 
1120 	/* micro code required: number of TC should be power of 2 */
1121 	if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) {
1122 		PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2",
1123 			tc_num);
1124 		return -EINVAL;
1125 	}
1126 
1127 	memset(&rss_cfg, 0, sizeof(rss_cfg));
1128 	rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1129 	rss_cfg.func_id = hinic_global_func_id(hwdev);
1130 	rss_cfg.rss_en = rss_en;
1131 	rss_cfg.template_id = tmpl_idx;
1132 	rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
1133 
1134 	memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX);
1135 
1136 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG,
1137 				     &rss_cfg, sizeof(rss_cfg), &rss_cfg,
1138 				     &out_size);
1139 	if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
1140 		PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x",
1141 			err, rss_cfg.mgmt_msg_head.status, out_size);
1142 		return -EIO;
1143 	}
1144 
1145 	return 0;
1146 }
1147 
1148 /**
1149  * hinic_rss_template_alloc - Get rss template id from the chip,
1150  * all functions share 96 templates.
1151  *
1152  * @param hwdev
1153  *   The hardware interface of a nic device.
1154  * @param tmpl_idx
1155  *   Index of rss template from chip.
1156  *
1157  * @return
1158  *   0 on success.
1159  *   negative error value otherwise.
1160  */
1161 int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
1162 {
1163 	struct hinic_rss_template_mgmt template_mgmt;
1164 	u16 out_size = sizeof(template_mgmt);
1165 	int err;
1166 
1167 	if (!hwdev || !tmpl_idx) {
1168 		PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL");
1169 		return -EINVAL;
1170 	}
1171 
1172 	memset(&template_mgmt, 0, sizeof(template_mgmt));
1173 	template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1174 	template_mgmt.func_id = hinic_global_func_id(hwdev);
1175 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
1176 
1177 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
1178 				     &template_mgmt, sizeof(template_mgmt),
1179 				     &template_mgmt, &out_size);
1180 	if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
1181 		PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x",
1182 			err, template_mgmt.mgmt_msg_head.status, out_size);
1183 		return -EIO;
1184 	}
1185 
1186 	*tmpl_idx = template_mgmt.template_id;
1187 
1188 	return 0;
1189 }
1190 
1191 /**
1192  * hinic_rss_template_free - Free rss template id to the chip.
1193  *
1194  * @param hwdev
1195  *   The hardware interface of a nic device.
1196  * @param tmpl_idx
1197  *   Index of rss template from chip.
1198  *
1199  * @return
1200  *   0 on success.
1201  *   negative error value otherwise.
1202  */
1203 int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
1204 {
1205 	struct hinic_rss_template_mgmt template_mgmt;
1206 	u16 out_size = sizeof(template_mgmt);
1207 	int err;
1208 
1209 	if (!hwdev) {
1210 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1211 		return -EINVAL;
1212 	}
1213 
1214 	memset(&template_mgmt, 0, sizeof(template_mgmt));
1215 	template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1216 	template_mgmt.func_id = hinic_global_func_id(hwdev);
1217 	template_mgmt.template_id = tmpl_idx;
1218 	template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
1219 
1220 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
1221 				     &template_mgmt, sizeof(template_mgmt),
1222 				     &template_mgmt, &out_size);
1223 	if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
1224 		PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x",
1225 			err, template_mgmt.mgmt_msg_head.status, out_size);
1226 		return -EIO;
1227 	}
1228 
1229 	return 0;
1230 }
1231 
1232 /**
1233  * hinic_set_rx_vhd_mode - Change rx buffer size after initialization.
1234  *
1235  * @param hwdev
1236  *   The hardware interface of a nic device.
1237  * @param vhd_mode
1238  *   Not needed.
1239  * @param rx_buf_sz
1240  *   receive buffer size.
1241  *
1242  * @return
1243  *   0 on success.
1244  *   negative error value otherwise.
1245  */
1246 int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
1247 {
1248 	struct hinic_set_vhd_mode vhd_mode_cfg;
1249 	u16 out_size = sizeof(vhd_mode_cfg);
1250 	int err;
1251 
1252 	if (!hwdev) {
1253 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1254 		return -EINVAL;
1255 	}
1256 
1257 	memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg));
1258 
1259 	vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1260 	vhd_mode_cfg.func_id = hinic_global_func_id(hwdev);
1261 	vhd_mode_cfg.vhd_type = vhd_mode;
1262 	vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz;
1263 
1264 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG,
1265 				     &vhd_mode_cfg, sizeof(vhd_mode_cfg),
1266 				     &vhd_mode_cfg, &out_size);
1267 	if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) {
1268 		PMD_DRV_LOG(ERR,
1269 			"Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
1270 			err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
1271 		return -EIO;
1272 	}
1273 
1274 	return 0;
1275 }
1276 
1277 int hinic_set_rx_mode(void *hwdev, u32 enable)
1278 {
1279 	struct hinic_rx_mode_config rx_mode_cfg;
1280 	u16 out_size = sizeof(rx_mode_cfg);
1281 	int err;
1282 
1283 	if (!hwdev) {
1284 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1285 		return -EINVAL;
1286 	}
1287 
1288 	memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
1289 	rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1290 	rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
1291 	rx_mode_cfg.rx_mode = enable;
1292 
1293 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
1294 				     &rx_mode_cfg, sizeof(rx_mode_cfg),
1295 				     &rx_mode_cfg, &out_size);
1296 	if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) {
1297 		PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x",
1298 			err, rx_mode_cfg.mgmt_msg_head.status, out_size);
1299 		return -EIO;
1300 	}
1301 
1302 	return 0;
1303 }
1304 
1305 /**
1306  * hinic_get_mgmt_version - Get mgmt module version from chip.
1307  *
1308  * @param hwdev
1309  *   The hardware interface of a nic device.
1310  * @param fw
1311  *   Firmware version.
1312  *
1313  * @return
1314  *   0 on success.
1315  *   negative error value otherwise.
1316  */
1317 int hinic_get_mgmt_version(void *hwdev, char *fw)
1318 {
1319 	struct hinic_version_info fw_ver;
1320 	u16 out_size = sizeof(fw_ver);
1321 	int err;
1322 
1323 	if (!hwdev || !fw) {
1324 		PMD_DRV_LOG(ERR, "Hwdev or fw is NULL");
1325 		return -EINVAL;
1326 	}
1327 
1328 	memset(&fw_ver, 0, sizeof(fw_ver));
1329 	fw_ver.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1330 
1331 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MGMT_VERSION,
1332 				     &fw_ver, sizeof(fw_ver), &fw_ver,
1333 				     &out_size);
1334 	if (err || !out_size || fw_ver.mgmt_msg_head.status) {
1335 		PMD_DRV_LOG(ERR, "Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x\n",
1336 			err, fw_ver.mgmt_msg_head.status, out_size);
1337 		return -EIO;
1338 	}
1339 
1340 	snprintf(fw, HINIC_MGMT_VERSION_MAX_LEN, "%s", fw_ver.ver);
1341 
1342 	return 0;
1343 }
1344 
1345 int hinic_set_rx_csum_offload(void *hwdev, u32 en)
1346 {
1347 	struct hinic_checksum_offload rx_csum_cfg;
1348 	u16 out_size = sizeof(rx_csum_cfg);
1349 	int err;
1350 
1351 	if (!hwdev) {
1352 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1353 		return -EINVAL;
1354 	}
1355 
1356 	memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg));
1357 	rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1358 	rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
1359 	rx_csum_cfg.rx_csum_offload = en;
1360 
1361 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
1362 				     &rx_csum_cfg, sizeof(rx_csum_cfg),
1363 				     &rx_csum_cfg, &out_size);
1364 	if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) {
1365 		PMD_DRV_LOG(ERR,
1366 			"Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x",
1367 			err, rx_csum_cfg.mgmt_msg_head.status, out_size);
1368 		return -EIO;
1369 	}
1370 
1371 	return 0;
1372 }
1373 
1374 int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num)
1375 {
1376 	struct hinic_lro_config lro_cfg;
1377 	u16 out_size = sizeof(lro_cfg);
1378 	int err;
1379 
1380 	if (!hwdev) {
1381 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1382 		return -EINVAL;
1383 	}
1384 
1385 	memset(&lro_cfg, 0, sizeof(lro_cfg));
1386 	lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1387 	lro_cfg.func_id = hinic_global_func_id(hwdev);
1388 	lro_cfg.lro_ipv4_en = ipv4_en;
1389 	lro_cfg.lro_ipv6_en = ipv6_en;
1390 	lro_cfg.lro_max_wqe_num = max_wqe_num;
1391 
1392 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO,
1393 				     &lro_cfg, sizeof(lro_cfg), &lro_cfg,
1394 				     &out_size);
1395 	if (err || !out_size || lro_cfg.mgmt_msg_head.status) {
1396 		PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x",
1397 			err, lro_cfg.mgmt_msg_head.status, out_size);
1398 		return -EIO;
1399 	}
1400 
1401 	return 0;
1402 }
1403 
1404 int hinic_set_anti_attack(void *hwdev, bool enable)
1405 {
1406 	struct hinic_port_anti_attack_rate rate;
1407 	u16 out_size = sizeof(rate);
1408 	int err;
1409 
1410 	if (!hwdev) {
1411 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1412 		return -EINVAL;
1413 	}
1414 
1415 	memset(&rate, 0, sizeof(rate));
1416 	rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1417 	rate.func_id = hinic_global_func_id(hwdev);
1418 	rate.enable = enable;
1419 	rate.cir = ANTI_ATTACK_DEFAULT_CIR;
1420 	rate.xir = ANTI_ATTACK_DEFAULT_XIR;
1421 	rate.cbs = ANTI_ATTACK_DEFAULT_CBS;
1422 	rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
1423 
1424 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
1425 				     &rate, sizeof(rate), &rate, &out_size);
1426 	if (err || !out_size || rate.mgmt_msg_head.status) {
1427 		PMD_DRV_LOG(ERR, "Can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
1428 			(enable ? "enable" : "disable"), err,
1429 			rate.mgmt_msg_head.status, out_size);
1430 		return -EIO;
1431 	}
1432 
1433 	return 0;
1434 }
1435 
1436 /* Set autoneg status and restart port link status */
1437 int hinic_reset_port_link_cfg(void *hwdev)
1438 {
1439 	struct hinic_reset_link_cfg reset_cfg;
1440 	u16 out_size = sizeof(reset_cfg);
1441 	int err;
1442 
1443 	memset(&reset_cfg, 0, sizeof(reset_cfg));
1444 	reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1445 	reset_cfg.func_id = hinic_global_func_id(hwdev);
1446 
1447 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
1448 				     &reset_cfg, sizeof(reset_cfg),
1449 				     &reset_cfg, &out_size);
1450 	if (err || !out_size || reset_cfg.mgmt_msg_head.status) {
1451 		PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x",
1452 			err, reset_cfg.mgmt_msg_head.status, out_size);
1453 		return -EIO;
1454 	}
1455 
1456 	return 0;
1457 }
1458 
1459 /**
1460  * hinic_vf_func_init - Register VF to PF.
1461  *
1462  * @param hwdev
1463  *   The hardware interface of a nic device.
1464  *
1465  * @return
1466  *   0 on success.
1467  *   negative error value otherwise.
1468  */
1469 int hinic_vf_func_init(struct hinic_hwdev *hwdev)
1470 {
1471 	int err, state = 0;
1472 
1473 	if (!HINIC_IS_VF(hwdev))
1474 		return 0;
1475 
1476 	err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1477 			HINIC_PORT_CMD_VF_REGISTER, &state, sizeof(state),
1478 			NULL, NULL, 0);
1479 	if (err) {
1480 		PMD_DRV_LOG(ERR, "Fail to register vf");
1481 		return err;
1482 	}
1483 
1484 	return 0;
1485 }
1486 
1487 /**
1488  * hinic_vf_func_free - Unregister VF from PF.
1489  *
1490  * @param hwdev
1491  *   The hardware interface of a nic device.
1492  */
1493 void hinic_vf_func_free(struct hinic_hwdev *hwdev)
1494 {
1495 	int err;
1496 
1497 	if (hinic_func_type(hwdev) != TYPE_VF)
1498 		return;
1499 
1500 	err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1501 				HINIC_PORT_CMD_VF_UNREGISTER, &err, sizeof(err),
1502 				NULL, NULL, 0);
1503 	if (err)
1504 		PMD_DRV_LOG(ERR, "Fail to unregister VF, err: %d", err);
1505 }
1506 
1507 int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
1508 {
1509 	struct hinic_fast_recycled_mode fast_recycled_mode;
1510 	u16 out_size = sizeof(fast_recycled_mode);
1511 	int err;
1512 
1513 	if (!hwdev) {
1514 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1515 		return -EINVAL;
1516 	}
1517 
1518 	memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode));
1519 	fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1520 	fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
1521 	fast_recycled_mode.fast_recycled_mode = mode;
1522 
1523 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1524 				     HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET,
1525 				     &fast_recycled_mode,
1526 				     sizeof(fast_recycled_mode),
1527 				     &fast_recycled_mode, &out_size, 0);
1528 	if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
1529 		PMD_DRV_LOG(ERR, "Failed to set recycle mode, err: %d, status: 0x%x, out size: 0x%x",
1530 			err, fast_recycled_mode.mgmt_msg_head.status, out_size);
1531 		return -EIO;
1532 	}
1533 
1534 	return 0;
1535 }
1536 
1537 int hinic_clear_vport_stats(struct hinic_hwdev *hwdev)
1538 {
1539 	struct hinic_clear_vport_stats clear_vport_stats;
1540 	u16 out_size = sizeof(clear_vport_stats);
1541 	int err;
1542 
1543 	if (!hwdev) {
1544 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1545 		return -EINVAL;
1546 	}
1547 
1548 	memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
1549 	clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1550 	clear_vport_stats.func_id = hinic_global_func_id(hwdev);
1551 
1552 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT,
1553 				     &clear_vport_stats,
1554 				     sizeof(clear_vport_stats),
1555 				     &clear_vport_stats, &out_size);
1556 	if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) {
1557 		PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x",
1558 			err, clear_vport_stats.mgmt_msg_head.status, out_size);
1559 		return -EIO;
1560 	}
1561 
1562 	return 0;
1563 }
1564 
1565 int hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev)
1566 {
1567 	struct hinic_clear_port_stats clear_phy_port_stats;
1568 	u16 out_size = sizeof(clear_phy_port_stats);
1569 	int err;
1570 
1571 	if (!hwdev) {
1572 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1573 		return -EINVAL;
1574 	}
1575 
1576 	memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats));
1577 	clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1578 	clear_phy_port_stats.func_id = hinic_global_func_id(hwdev);
1579 
1580 	err = l2nic_msg_to_mgmt_sync(hwdev,
1581 				     HINIC_PORT_CMD_CLEAR_PORT_STATISTICS,
1582 				     &clear_phy_port_stats,
1583 				     sizeof(clear_phy_port_stats),
1584 				     &clear_phy_port_stats, &out_size);
1585 	if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) {
1586 		PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x",
1587 			err, clear_phy_port_stats.mgmt_msg_head.status,
1588 			out_size);
1589 		return -EIO;
1590 	}
1591 
1592 	return 0;
1593 }
1594 
1595 int hinic_set_link_status_follow(void *hwdev,
1596 				 enum hinic_link_follow_status status)
1597 {
1598 	struct hinic_set_link_follow follow;
1599 	u16 out_size = sizeof(follow);
1600 	int err;
1601 
1602 	if (!hwdev)
1603 		return -EINVAL;
1604 
1605 	if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
1606 		return 0;
1607 
1608 	if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) {
1609 		PMD_DRV_LOG(ERR, "Invalid link follow status: %d", status);
1610 		return -EINVAL;
1611 	}
1612 
1613 	memset(&follow, 0, sizeof(follow));
1614 	follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1615 	follow.func_id = hinic_global_func_id(hwdev);
1616 	follow.follow_status = status;
1617 
1618 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
1619 				     &follow, sizeof(follow),
1620 				     &follow, &out_size);
1621 	if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
1622 	     follow.mgmt_msg_head.status) || err || !out_size) {
1623 		PMD_DRV_LOG(ERR,
1624 			"Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x",
1625 			err, follow.mgmt_msg_head.status, out_size);
1626 		return -EIO;
1627 	}
1628 
1629 	return follow.mgmt_msg_head.status;
1630 }
1631 
1632 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
1633 {
1634 	struct hinic_link_mode_cmd link_mode;
1635 	u16 out_size = sizeof(link_mode);
1636 	int err;
1637 
1638 	if (!hwdev || !supported || !advertised)
1639 		return -EINVAL;
1640 
1641 	memset(&link_mode, 0, sizeof(link_mode));
1642 	link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1643 	link_mode.func_id = hinic_global_func_id(hwdev);
1644 
1645 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
1646 				     &link_mode, sizeof(link_mode),
1647 				     &link_mode, &out_size);
1648 	if (err || !out_size || link_mode.mgmt_msg_head.status) {
1649 		PMD_DRV_LOG(ERR,
1650 			"Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x",
1651 			err, link_mode.mgmt_msg_head.status, out_size);
1652 		return -EIO;
1653 	}
1654 
1655 	*supported = link_mode.supported;
1656 	*advertised = link_mode.advertised;
1657 
1658 	return 0;
1659 }
1660 
1661 /**
1662  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport
1663  * fake failed when device start.
1664  *
1665  * @param hwdev
1666  *   The hardware interface of a nic device.
1667  *
1668  * @return
1669  *   0 on success.
1670  *   negative error value otherwise.
1671  */
1672 int hinic_flush_qp_res(void *hwdev)
1673 {
1674 	struct hinic_clear_qp_resource qp_res;
1675 	u16 out_size = sizeof(qp_res);
1676 	int err;
1677 
1678 	memset(&qp_res, 0, sizeof(qp_res));
1679 	qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1680 	qp_res.func_id = hinic_global_func_id(hwdev);
1681 
1682 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES,
1683 				     &qp_res, sizeof(qp_res), &qp_res,
1684 				     &out_size);
1685 	if (err || !out_size || qp_res.mgmt_msg_head.status) {
1686 		PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x",
1687 			err, qp_res.mgmt_msg_head.status, out_size);
1688 		return -EIO;
1689 	}
1690 
1691 	return 0;
1692 }
1693 
1694 /**
1695  * hinic_vf_get_default_cos - Get default cos of VF.
1696  *
1697  * @param hwdev
1698  *   The hardware interface of a nic device.
1699  * @param cos_id
1700  *   Cos value.
1701  *
1702  * @return
1703  *   0 on success.
1704  *   negative error value otherwise.
1705  */
1706 int hinic_vf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
1707 {
1708 	struct hinic_vf_default_cos vf_cos;
1709 	u16 out_size = sizeof(vf_cos);
1710 	int err;
1711 
1712 	memset(&vf_cos, 0, sizeof(vf_cos));
1713 	vf_cos.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1714 
1715 	err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
1716 				     HINIC_PORT_CMD_GET_VF_COS, &vf_cos,
1717 				     sizeof(vf_cos), &vf_cos, &out_size, 0);
1718 	if (err || !out_size || vf_cos.mgmt_msg_head.status) {
1719 		PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d, status: 0x%x, out size: 0x%x",
1720 			err, vf_cos.mgmt_msg_head.status, out_size);
1721 		return -EIO;
1722 	}
1723 	*cos_id = vf_cos.state.default_cos;
1724 
1725 	return 0;
1726 }
1727 
1728 /**
1729  * hinic_set_fdir_filter - Set fdir filter for control path
1730  * packet to notify firmware.
1731  *
1732  * @param hwdev
1733  *   The hardware interface of a nic device.
1734  * @param filter_type
1735  *   Packet type to filter.
1736  * @param qid
1737  *   Rx qid to filter.
1738  * @param type_enable
1739  *   The status of pkt type filter.
1740  * @param enable
1741  *   Fdir function Enable or Disable.
1742  * @return
1743  *   0 on success,
1744  *   negative error value otherwise.
1745  */
1746 int hinic_set_fdir_filter(void *hwdev, u8 filter_type, u8 qid, u8 type_enable,
1747 			  bool enable)
1748 {
1749 	struct hinic_port_qfilter_info port_filer_cmd;
1750 	u16 out_size = sizeof(port_filer_cmd);
1751 	int err;
1752 
1753 	if (!hwdev)
1754 		return -EINVAL;
1755 
1756 	memset(&port_filer_cmd, 0, sizeof(port_filer_cmd));
1757 	port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1758 	port_filer_cmd.func_id = hinic_global_func_id(hwdev);
1759 	port_filer_cmd.filter_enable = (u8)enable;
1760 	port_filer_cmd.filter_type = filter_type;
1761 	port_filer_cmd.qid = qid;
1762 	port_filer_cmd.filter_type_enable = type_enable;
1763 	port_filer_cmd.fdir_flag = 0;
1764 
1765 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER,
1766 			&port_filer_cmd, sizeof(port_filer_cmd),
1767 			&port_filer_cmd, &out_size);
1768 	if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) {
1769 		PMD_DRV_LOG(ERR, "Set port Q filter failed, err: %d, status: 0x%x, out size: 0x%x, type: 0x%x,"
1770 			" enable: 0x%x, qid: 0x%x, filter_type_enable: 0x%x\n",
1771 			err, port_filer_cmd.mgmt_msg_head.status, out_size,
1772 			filter_type, enable, qid, type_enable);
1773 		return -EIO;
1774 	}
1775 
1776 	return 0;
1777 }
1778 
1779 /**
1780  * hinic_set_normal_filter - Set fdir filter for IO path packet.
1781  *
1782  * @param hwdev
1783  *   The hardware interface of a nic device.
1784  * @param qid
1785  *   Rx qid to filter.
1786  * @param normal_type_enable
1787  *   IO path packet function Enable or Disable
1788  * @param key
1789  *   IO path packet filter key value, such as DIP from pkt.
1790  * @param enable
1791  *   Fdir function Enable or Disable.
1792  * @param flag
1793  *   Filter flag, such as dip or others.
1794  * @return
1795  *   0 on success,
1796  *   negative error value otherwise.
1797  */
1798 int hinic_set_normal_filter(void *hwdev, u8 qid, u8 normal_type_enable,
1799 				u32 key, bool enable, u8 flag)
1800 {
1801 	struct hinic_port_qfilter_info port_filer_cmd;
1802 	u16 out_size = sizeof(port_filer_cmd);
1803 	int err;
1804 
1805 	if (!hwdev)
1806 		return -EINVAL;
1807 
1808 	memset(&port_filer_cmd, 0, sizeof(port_filer_cmd));
1809 	port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1810 	port_filer_cmd.func_id = hinic_global_func_id(hwdev);
1811 	port_filer_cmd.filter_enable = (u8)enable;
1812 	port_filer_cmd.qid = qid;
1813 	port_filer_cmd.normal_type_enable = normal_type_enable;
1814 	port_filer_cmd.fdir_flag = flag; /* fdir flag: support dip */
1815 	port_filer_cmd.key = key;
1816 
1817 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER,
1818 			&port_filer_cmd, sizeof(port_filer_cmd),
1819 			&port_filer_cmd, &out_size);
1820 	if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) {
1821 		PMD_DRV_LOG(ERR, "Set normal filter failed, err: %d, status: 0x%x, out size: 0x%x, fdir_flag: 0x%x,"
1822 			" enable: 0x%x, qid: 0x%x, normal_type_enable: 0x%x, key:0x%x\n",
1823 			err, port_filer_cmd.mgmt_msg_head.status, out_size,
1824 			flag, enable, qid, normal_type_enable, key);
1825 		return -EIO;
1826 	}
1827 
1828 	return 0;
1829 }
1830 
1831 /**
1832  * hinic_set_fdir_tcam - Set fdir filter for control packet
1833  * by tcam table to notify hardware.
1834  *
1835  * @param hwdev
1836  *   The hardware interface of a nic device.
1837  * @param type_mask
1838  *   Index of TCAM.
1839  * @param filter_rule
1840  *   TCAM rule for control packet, such as lacp or bgp.
1841  * @param filter_action
1842  *   TCAM action for control packet, such as accept or drop.
1843  * @return
1844  *   0 on success,
1845  *   negative error value otherwise.
1846  */
1847 int hinic_set_fdir_tcam(void *hwdev, u16 type_mask,
1848 			struct tag_pa_rule *filter_rule,
1849 			struct tag_pa_action *filter_action)
1850 {
1851 	struct hinic_fdir_tcam_info port_tcam_cmd;
1852 	u16 out_size = sizeof(port_tcam_cmd);
1853 	int err;
1854 
1855 	if (!hwdev)
1856 		return -EINVAL;
1857 
1858 	memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
1859 	port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1860 	port_tcam_cmd.tcam_index = type_mask;
1861 	port_tcam_cmd.flag = TCAM_SET;
1862 	memcpy((void *)&port_tcam_cmd.filter_rule,
1863 		(void *)filter_rule, sizeof(struct tag_pa_rule));
1864 	memcpy((void *)&port_tcam_cmd.filter_action,
1865 		(void *)filter_action, sizeof(struct tag_pa_action));
1866 
1867 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER,
1868 			&port_tcam_cmd, sizeof(port_tcam_cmd),
1869 			&port_tcam_cmd, &out_size);
1870 	if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) {
1871 		PMD_DRV_LOG(ERR, "Set tcam table failed, err: %d, status: 0x%x, out size: 0x%x",
1872 			err, port_tcam_cmd.mgmt_msg_head.status, out_size);
1873 		return -EIO;
1874 	}
1875 
1876 	return 0;
1877 }
1878 
1879 /**
1880  * hinic_clear_fdir_tcam - Clear fdir filter TCAM table for control packet.
1881  *
1882  * @param hwdev
1883  *   The hardware interface of a nic device.
1884  * @param type_mask
1885  *   Index of TCAM.
1886  * @return
1887  *   0 on success,
1888  *   negative error value otherwise.
1889  */
1890 int hinic_clear_fdir_tcam(void *hwdev, u16 type_mask)
1891 {
1892 	struct hinic_fdir_tcam_info port_tcam_cmd;
1893 	u16 out_size = sizeof(port_tcam_cmd);
1894 	int err;
1895 
1896 	if (!hwdev)
1897 		return -EINVAL;
1898 
1899 	memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
1900 	port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1901 	port_tcam_cmd.tcam_index = type_mask;
1902 	port_tcam_cmd.flag = TCAM_CLEAR;
1903 
1904 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER,
1905 			&port_tcam_cmd, sizeof(port_tcam_cmd),
1906 			&port_tcam_cmd, &out_size);
1907 	if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) {
1908 		PMD_DRV_LOG(ERR, "Clear tcam table failed, err: %d, status: 0x%x, out size: 0x%x",
1909 			err, port_tcam_cmd.mgmt_msg_head.status, out_size);
1910 		return -EIO;
1911 	}
1912 
1913 	return 0;
1914 }
1915 
1916 int hinic_add_tcam_rule(void *hwdev, struct tag_tcam_cfg_rule *tcam_rule)
1917 {
1918 	u16 out_size = sizeof(struct tag_fdir_add_rule_cmd);
1919 	struct tag_fdir_add_rule_cmd tcam_cmd;
1920 	int err;
1921 
1922 	if (!hwdev) {
1923 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1924 		return -EINVAL;
1925 	}
1926 
1927 	if (tcam_rule->index >= HINIC_MAX_TCAM_RULES_NUM) {
1928 		PMD_DRV_LOG(ERR, "Tcam rules num to add is invalid");
1929 		return -EINVAL;
1930 	}
1931 
1932 	memset(&tcam_cmd, 0, sizeof(struct tag_fdir_add_rule_cmd));
1933 	tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1934 	memcpy((void *)&tcam_cmd.rule, (void *)tcam_rule,
1935 		sizeof(struct tag_tcam_cfg_rule));
1936 
1937 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ADD_FLOW,
1938 				&tcam_cmd, sizeof(tcam_cmd),
1939 				&tcam_cmd, &out_size);
1940 	if (err || tcam_cmd.mgmt_msg_head.status || !out_size) {
1941 		PMD_DRV_LOG(ERR,
1942 			"Add tcam rule failed, err: %d, status: 0x%x, out size: 0x%x",
1943 			err, tcam_cmd.mgmt_msg_head.status, out_size);
1944 		return -EIO;
1945 	}
1946 
1947 	return 0;
1948 }
1949 
1950 int hinic_del_tcam_rule(void *hwdev, u32 index)
1951 {
1952 	u16 out_size = sizeof(struct tag_fdir_del_rule_cmd);
1953 	struct tag_fdir_del_rule_cmd tcam_cmd;
1954 	int err;
1955 
1956 	if (!hwdev) {
1957 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1958 		return -EINVAL;
1959 	}
1960 
1961 	if (index >= HINIC_MAX_TCAM_RULES_NUM) {
1962 		PMD_DRV_LOG(ERR, "Tcam rules num to del is invalid");
1963 		return -EINVAL;
1964 	}
1965 
1966 	memset(&tcam_cmd, 0, sizeof(struct tag_fdir_del_rule_cmd));
1967 	tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1968 	tcam_cmd.index_start = index;
1969 	tcam_cmd.index_num = 1;
1970 
1971 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_DEL_FLOW,
1972 				&tcam_cmd, sizeof(tcam_cmd),
1973 				&tcam_cmd, &out_size);
1974 	if (err || tcam_cmd.mgmt_msg_head.status || !out_size) {
1975 		PMD_DRV_LOG(ERR,
1976 			"Del tcam rule failed, err: %d, status: 0x%x, out size: 0x%x",
1977 			err, tcam_cmd.mgmt_msg_head.status, out_size);
1978 		return -EIO;
1979 	}
1980 
1981 	return 0;
1982 }
1983 
1984 static int hinic_mgmt_tcam_block(void *hwdev, u8 alloc_en,
1985 				u8 block_type, u16 *index)
1986 {
1987 	struct hinic_cmd_ctrl_tcam_block tcam_block_info;
1988 	u16 out_size = sizeof(struct hinic_cmd_ctrl_tcam_block);
1989 	struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
1990 	int err;
1991 
1992 	if (!hwdev) {
1993 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
1994 		return -EINVAL;
1995 	}
1996 
1997 	memset(&tcam_block_info, 0, sizeof(struct hinic_cmd_ctrl_tcam_block));
1998 	tcam_block_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1999 	tcam_block_info.func_id = hinic_global_func_id(hwdev);
2000 	tcam_block_info.alloc_en = alloc_en;
2001 	tcam_block_info.tcam_type = block_type;
2002 	tcam_block_info.tcam_block_index = *index;
2003 
2004 	err = l2nic_msg_to_mgmt_sync(hwdev,
2005 				HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK,
2006 				&tcam_block_info, sizeof(tcam_block_info),
2007 				&tcam_block_info, &out_size);
2008 	if (tcam_block_info.mgmt_msg_head.status ==
2009 		HINIC_MGMT_CMD_UNSUPPORTED) {
2010 		err = HINIC_MGMT_CMD_UNSUPPORTED;
2011 		PMD_DRV_LOG(INFO, "Firmware/uP doesn't support alloc or del tcam block");
2012 		return err;
2013 	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
2014 			(HINIC_IS_VF(nic_hwdev))) {
2015 		err = HINIC_MGMT_CMD_UNSUPPORTED;
2016 		PMD_DRV_LOG(INFO, "VF doesn't support alloc and del tcam block.");
2017 		return err;
2018 	} else if (err || (!out_size) || tcam_block_info.mgmt_msg_head.status) {
2019 		PMD_DRV_LOG(ERR,
2020 			"Set tcam block failed, err: %d, status: 0x%x, out size: 0x%x",
2021 			err, tcam_block_info.mgmt_msg_head.status, out_size);
2022 		return -EIO;
2023 	}
2024 
2025 	if (alloc_en)
2026 		*index = tcam_block_info.tcam_block_index;
2027 
2028 	return 0;
2029 }
2030 
2031 int hinic_alloc_tcam_block(void *hwdev, u8 block_type, u16 *index)
2032 {
2033 	return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_ENABLE,
2034 				block_type, index);
2035 }
2036 
2037 int hinic_free_tcam_block(void *hwdev, u8 block_type, u16 *index)
2038 {
2039 	return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_DISABLE,
2040 				block_type, index);
2041 }
2042 
2043 int hinic_flush_tcam_rule(void *hwdev)
2044 {
2045 	struct hinic_cmd_flush_tcam_rules tcam_flush;
2046 	u16 out_size = sizeof(struct hinic_cmd_flush_tcam_rules);
2047 	struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
2048 	int err;
2049 
2050 	if (!hwdev) {
2051 		PMD_DRV_LOG(ERR, "Hwdev is NULL");
2052 		return -EINVAL;
2053 	}
2054 
2055 	memset(&tcam_flush, 0, sizeof(struct hinic_cmd_flush_tcam_rules));
2056 	tcam_flush.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
2057 	tcam_flush.func_id = hinic_global_func_id(hwdev);
2058 
2059 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_FLUSH_TCAM,
2060 			&tcam_flush, sizeof(struct hinic_cmd_flush_tcam_rules),
2061 			&tcam_flush, &out_size);
2062 	if (tcam_flush.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
2063 		err = HINIC_MGMT_CMD_UNSUPPORTED;
2064 		PMD_DRV_LOG(INFO, "Firmware/uP doesn't support flush tcam fdir");
2065 	} else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
2066 			(HINIC_IS_VF(nic_hwdev))) {
2067 		err = HINIC_MGMT_CMD_UNSUPPORTED;
2068 		PMD_DRV_LOG(INFO, "VF doesn't support flush tcam fdir");
2069 	} else if (err || (!out_size) || tcam_flush.mgmt_msg_head.status) {
2070 		PMD_DRV_LOG(ERR,
2071 			"Flush tcam fdir rules failed, err: %d, status: 0x%x, out size: 0x%x",
2072 			err, tcam_flush.mgmt_msg_head.status, out_size);
2073 		err = -EIO;
2074 	}
2075 
2076 	return err;
2077 }
2078 
2079 int hinic_set_fdir_tcam_rule_filter(void *hwdev, bool enable)
2080 {
2081 	struct hinic_port_tcam_info port_tcam_cmd;
2082 	u16 out_size = sizeof(port_tcam_cmd);
2083 	int err;
2084 
2085 	if (!hwdev)
2086 		return -EINVAL;
2087 
2088 	memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd));
2089 	port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
2090 	port_tcam_cmd.func_id = hinic_global_func_id(hwdev);
2091 	port_tcam_cmd.tcam_enable = (u8)enable;
2092 
2093 	err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ENABLE,
2094 			&port_tcam_cmd, sizeof(port_tcam_cmd),
2095 			&port_tcam_cmd, &out_size);
2096 	if ((port_tcam_cmd.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
2097 		port_tcam_cmd.mgmt_msg_head.status) || err || !out_size) {
2098 		if (err == HINIC_MBOX_VF_CMD_ERROR &&
2099 			HINIC_IS_VF((struct hinic_hwdev *)hwdev)) {
2100 			err = HINIC_MGMT_CMD_UNSUPPORTED;
2101 			PMD_DRV_LOG(WARNING, "VF doesn't support setting fdir tcam filter");
2102 			return err;
2103 		}
2104 		PMD_DRV_LOG(ERR, "Set fdir tcam filter failed, err: %d, "
2105 			"status: 0x%x, out size: 0x%x, enable: 0x%x",
2106 			err, port_tcam_cmd.mgmt_msg_head.status, out_size,
2107 			enable);
2108 		return -EIO;
2109 	}
2110 
2111 	if (port_tcam_cmd.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
2112 		err = HINIC_MGMT_CMD_UNSUPPORTED;
2113 		PMD_DRV_LOG(WARNING, "Fw doesn't support setting fdir tcam filter");
2114 	}
2115 
2116 	return err;
2117 }
2118 
2119 
2120