d3bbc3d47276064374a93887aa3af614717acfd6
[dpdk.git] / drivers / net / hinic / base / hinic_pmd_niccfg.c
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 -EFAULT;
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 -EINVAL;
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 -EINVAL;
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 -EINVAL;
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 -EINVAL;
245         }
246
247         memmove(mac_addr, mac_info.mac, ETH_ALEN);
248
249         return 0;
250 }
251
252 /**
253  * hinic_set_port_mtu -  Set MTU to port.
254  *
255  * @param hwdev
256  *   The hardware interface of a nic device.
257  * @param new_mtu
258  *   MTU size.
259  *
260  * @return
261  *   0 on success.
262  *   negative error value otherwise.
263  */
264 int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
265 {
266         struct hinic_mtu mtu_info;
267         u16 out_size = sizeof(mtu_info);
268         int err;
269
270         if (!hwdev) {
271                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
272                 return -EINVAL;
273         }
274
275         memset(&mtu_info, 0, sizeof(mtu_info));
276         mtu_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
277         mtu_info.func_id = hinic_global_func_id(hwdev);
278         mtu_info.mtu = new_mtu;
279
280         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
281                                      &mtu_info, sizeof(mtu_info),
282                                      &mtu_info, &out_size);
283         if (err || !out_size || mtu_info.mgmt_msg_head.status) {
284                 PMD_DRV_LOG(ERR, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x",
285                         err, mtu_info.mgmt_msg_head.status, out_size);
286                 return -EINVAL;
287         }
288
289         return 0;
290 }
291
292 /**
293  * hinic_get_link_status - Get link status from hardware.
294  *
295  * @param hwdev
296  *   The hardware interface of a nic device.
297  * @param link_state
298  *   Link status.
299  *
300  * @return
301  *   0 on success.
302  *   negative error value otherwise.
303  */
304 int hinic_get_link_status(void *hwdev, u8 *link_state)
305 {
306         struct hinic_get_link get_link;
307         u16 out_size = sizeof(get_link);
308         int err;
309
310         if (!hwdev || !link_state) {
311                 PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL");
312                 return -EINVAL;
313         }
314
315         memset(&get_link, 0, sizeof(get_link));
316         get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
317         get_link.func_id = hinic_global_func_id(hwdev);
318
319         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
320                                      &get_link, sizeof(get_link),
321                                      &get_link, &out_size);
322         if (err || !out_size || get_link.mgmt_msg_head.status) {
323                 PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x",
324                         err, get_link.mgmt_msg_head.status, out_size);
325                 return -EINVAL;
326         }
327
328         *link_state = get_link.link_status;
329
330         return 0;
331 }
332
333 /**
334  * hinic_set_vport_enable - Notify firmware that driver is ready or not.
335  *
336  * @param hwdev
337  *   The hardware interface of a nic device.
338  * @param enable
339  *   1: driver is ready; 0: driver is not ok.
340  *
341  * @return
342  *   0 on success.
343  *   negative error value otherwise.
344  */
345 int hinic_set_vport_enable(void *hwdev, bool enable)
346 {
347         struct hinic_vport_state en_state;
348         u16 out_size = sizeof(en_state);
349         int err;
350
351         if (!hwdev) {
352                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
353                 return -EINVAL;
354         }
355
356         memset(&en_state, 0, sizeof(en_state));
357         en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
358         en_state.func_id = hinic_global_func_id(hwdev);
359         en_state.state = (enable ? 1 : 0);
360
361         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
362                                      &en_state, sizeof(en_state),
363                                      &en_state, &out_size);
364         if (err || !out_size || en_state.mgmt_msg_head.status) {
365                 PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x",
366                         err, en_state.mgmt_msg_head.status, out_size);
367                 return -EINVAL;
368         }
369
370         return 0;
371 }
372
373 /**
374  * hinic_set_port_enable - Open MAG to receive packets.
375  *
376  * @param hwdev
377  *   The hardware interface of a nic device.
378  * @param enable
379  *   1: open MAG; 0: close MAG.
380  *
381  * @return
382  *   0 on success.
383  *   negative error value otherwise.
384  */
385 int hinic_set_port_enable(void *hwdev, bool enable)
386 {
387         struct hinic_port_state en_state;
388         u16 out_size = sizeof(en_state);
389         int err;
390
391         if (!hwdev) {
392                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
393                 return -EINVAL;
394         }
395
396         if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
397                 return 0;
398
399         memset(&en_state, 0, sizeof(en_state));
400         en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
401         en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE);
402
403         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
404                                      &en_state, sizeof(en_state),
405                                      &en_state, &out_size);
406         if (err || !out_size || en_state.mgmt_msg_head.status) {
407                 PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x",
408                         err, en_state.mgmt_msg_head.status, out_size);
409                 return -EINVAL;
410         }
411
412         return 0;
413 }
414
415 int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
416 {
417         struct hinic_port_info port_msg;
418         u16 out_size = sizeof(port_msg);
419         int err;
420
421         if (!hwdev || !port_info) {
422                 PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL");
423                 return -EINVAL;
424         }
425
426         memset(&port_msg, 0, sizeof(port_msg));
427         port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
428         port_msg.func_id = hinic_global_func_id(hwdev);
429
430         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
431                                      &port_msg, sizeof(port_msg),
432                                      &port_msg, &out_size);
433         if (err || !out_size || port_msg.mgmt_msg_head.status) {
434                 PMD_DRV_LOG(ERR,
435                         "Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
436                         err, port_msg.mgmt_msg_head.status, out_size);
437                 return err;
438         }
439
440         port_info->autoneg_cap = port_msg.autoneg_cap;
441         port_info->autoneg_state = port_msg.autoneg_state;
442         port_info->duplex = port_msg.duplex;
443         port_info->port_type = port_msg.port_type;
444         port_info->speed = port_msg.speed;
445
446         return 0;
447 }
448
449 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
450 {
451         struct hinic_pause_config pause_info;
452         u16 out_size = sizeof(pause_info);
453         int err;
454
455         if (!hwdev) {
456                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
457                 return -EINVAL;
458         }
459
460         memset(&pause_info, 0, sizeof(pause_info));
461         pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
462         pause_info.func_id = hinic_global_func_id(hwdev);
463         pause_info.auto_neg = nic_pause.auto_neg;
464         pause_info.rx_pause = nic_pause.rx_pause;
465         pause_info.tx_pause = nic_pause.tx_pause;
466
467         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
468                                      &pause_info, sizeof(pause_info),
469                                      &pause_info, &out_size);
470         if (err || !out_size || pause_info.mgmt_msg_head.status) {
471                 PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x",
472                         err, pause_info.mgmt_msg_head.status, out_size);
473                 return -EINVAL;
474         }
475
476         return 0;
477 }
478
479 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
480                       u8 *pgid, u8 *up_bw, u8 *prio)
481 {
482         struct hinic_up_ets_cfg ets;
483         u16 out_size = sizeof(ets);
484         u16 up_bw_t = 0;
485         u8 pg_bw_t = 0;
486         int i, err;
487
488         if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) {
489                 PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL");
490                 return -EINVAL;
491         }
492
493         for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
494                 up_bw_t += *(up_bw + i);
495                 pg_bw_t += *(pg_bw + i);
496
497                 if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
498                         PMD_DRV_LOG(ERR,
499                                 "Invalid up %d mapping tc: %d", i,
500                                 *(up_tc + i));
501                         return -EINVAL;
502                 }
503         }
504
505         if (pg_bw_t != 100 || (up_bw_t % 100) != 0) {
506                 PMD_DRV_LOG(ERR,
507                         "Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t);
508                 return -EINVAL;
509         }
510
511         memset(&ets, 0, sizeof(ets));
512         ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
513         ets.port_id = 0;        /* reserved */
514         memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX);
515         memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX);
516         memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX);
517         memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX);
518         memcpy(ets.prio, prio, HINIC_DCB_UP_MAX);
519
520         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS,
521                                      &ets, sizeof(ets), &ets, &out_size);
522         if (err || ets.mgmt_msg_head.status || !out_size) {
523                 PMD_DRV_LOG(ERR,
524                         "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x",
525                         err, ets.mgmt_msg_head.status, out_size);
526                 return -EINVAL;
527         }
528
529         return 0;
530 }
531
532 int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats)
533 {
534         struct hinic_port_stats_info vport_stats_cmd;
535         struct hinic_cmd_vport_stats vport_stats_rsp;
536         u16 out_size = sizeof(vport_stats_rsp);
537         int err;
538
539         if (!hwdev || !stats) {
540                 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
541                 return -EINVAL;
542         }
543
544         memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp));
545         memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd));
546         vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
547         vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
548         vport_stats_cmd.func_id = hinic_global_func_id(hwdev);
549         vport_stats_cmd.stats_size = sizeof(vport_stats_rsp);
550
551         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
552                                      &vport_stats_cmd, sizeof(vport_stats_cmd),
553                                      &vport_stats_rsp, &out_size);
554         if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) {
555                 PMD_DRV_LOG(ERR,
556                         "Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x",
557                         err, vport_stats_rsp.mgmt_msg_head.status, out_size);
558                 return -EFAULT;
559         }
560
561         memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats));
562
563         return 0;
564 }
565
566 int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats)
567 {
568         struct hinic_port_stats_info port_stats_cmd;
569         struct hinic_port_stats port_stats_rsp;
570         u16 out_size = sizeof(port_stats_rsp);
571         int err;
572
573         if (!hwdev || !stats) {
574                 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
575                 return -EINVAL;
576         }
577
578         memset(&port_stats_rsp, 0, sizeof(port_stats_rsp));
579         memset(&port_stats_cmd, 0, sizeof(port_stats_cmd));
580         port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
581         port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
582         port_stats_cmd.stats_size = sizeof(port_stats_rsp);
583
584         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
585                                      &port_stats_cmd, sizeof(port_stats_cmd),
586                                      &port_stats_rsp, &out_size);
587         if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) {
588                 PMD_DRV_LOG(ERR,
589                         "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x",
590                         err, port_stats_rsp.mgmt_msg_head.status, out_size);
591                 return -EFAULT;
592         }
593
594         memcpy(stats, &port_stats_rsp.stats, sizeof(*stats));
595
596         return 0;
597 }
598
599 int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type)
600 {
601         struct nic_rss_context_tbl *ctx_tbl;
602         struct hinic_cmd_buf *cmd_buf;
603         u32 ctx = 0;
604         u64 out_param;
605         int err;
606
607         if (!hwdev) {
608                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
609                 return -EINVAL;
610         }
611
612         cmd_buf = hinic_alloc_cmd_buf(hwdev);
613         if (!cmd_buf) {
614                 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
615                 return -ENOMEM;
616         }
617
618         ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
619                 HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
620                 HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
621                 HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
622                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
623                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
624                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
625                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
626                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
627
628         cmd_buf->size = sizeof(struct nic_rss_context_tbl);
629
630         ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf;
631         ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
632         ctx_tbl->offset = 0;
633         ctx_tbl->size = sizeof(u32);
634         ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
635         ctx_tbl->rsvd = 0;
636         ctx_tbl->ctx = cpu_to_be32(ctx);
637
638         /* cfg the rss context table by command queue */
639         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
640                                      HINIC_MOD_L2NIC,
641                                      HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
642                                      cmd_buf, &out_param, 0);
643
644         hinic_free_cmd_buf(hwdev, cmd_buf);
645
646         if (err || out_param != 0) {
647                 PMD_DRV_LOG(ERR, "Failed to set rss context table");
648                 return -EFAULT;
649         }
650
651         return 0;
652 }
653
654 int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type)
655 {
656         struct hinic_rss_context_table ctx_tbl;
657         u16 out_size = sizeof(ctx_tbl);
658         int err;
659
660         if (!hwdev || !rss_type) {
661                 PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL");
662                 return -EINVAL;
663         }
664
665         ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
666         ctx_tbl.func_id = hinic_global_func_id(hwdev);
667         ctx_tbl.template_id = (u8)tmpl_idx;
668
669         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
670                                      &ctx_tbl, sizeof(ctx_tbl),
671                                      &ctx_tbl, &out_size);
672         if (err || !out_size || ctx_tbl.mgmt_msg_head.status) {
673                 PMD_DRV_LOG(ERR,
674                         "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x",
675                         err, ctx_tbl.mgmt_msg_head.status, out_size);
676                 return -EINVAL;
677         }
678
679         rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
680         rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
681         rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
682         rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
683         rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
684         rss_type->tcp_ipv6_ext =
685                         HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT);
686         rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
687         rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
688
689         return 0;
690 }
691
692 int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
693 {
694         struct hinic_rss_template_key temp_key;
695         u16 out_size = sizeof(temp_key);
696         int err;
697
698         if (!hwdev || !temp) {
699                 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
700                 return -EINVAL;
701         }
702
703         memset(&temp_key, 0, sizeof(temp_key));
704         temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
705         temp_key.func_id = hinic_global_func_id(hwdev);
706         temp_key.template_id = (u8)tmpl_idx;
707         memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
708
709         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
710                                      &temp_key, sizeof(temp_key),
711                                      &temp_key, &out_size);
712         if (err || !out_size || temp_key.mgmt_msg_head.status) {
713                 PMD_DRV_LOG(ERR,
714                         "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x",
715                         err, temp_key.mgmt_msg_head.status, out_size);
716                 return -EINVAL;
717         }
718
719         return 0;
720 }
721
722 int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
723 {
724         struct hinic_rss_template_key temp_key;
725         u16 out_size = sizeof(temp_key);
726         int err;
727
728         if (!hwdev || !temp) {
729                 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
730                 return -EINVAL;
731         }
732
733         memset(&temp_key, 0, sizeof(temp_key));
734         temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
735         temp_key.func_id = hinic_global_func_id(hwdev);
736         temp_key.template_id = (u8)tmpl_idx;
737
738         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
739                                      &temp_key, sizeof(temp_key),
740                                      &temp_key, &out_size);
741         if (err || !out_size || temp_key.mgmt_msg_head.status) {
742                 PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x",
743                         err, temp_key.mgmt_msg_head.status, out_size);
744                 return -EINVAL;
745         }
746
747         memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
748
749         return 0;
750 }
751
752 /**
753  * hinic_rss_set_hash_engine - Init rss hash function.
754  *
755  * @param hwdev
756  *   The hardware interface of a nic device.
757  * @param tmpl_idx
758  *   Index of rss template from NIC.
759  * @param type
760  *   Hash function, such as Toeplitz or XOR.
761  *
762  * @return
763  *   0 on success.
764  *   negative error value otherwise.
765  */
766 int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
767 {
768         struct hinic_rss_engine_type hash_type;
769         u16 out_size = sizeof(hash_type);
770         int err;
771
772         if (!hwdev) {
773                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
774                 return -EINVAL;
775         }
776
777         memset(&hash_type, 0, sizeof(hash_type));
778         hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
779         hash_type.func_id = hinic_global_func_id(hwdev);
780         hash_type.hash_engine = type;
781         hash_type.template_id = tmpl_idx;
782
783         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
784                                      &hash_type, sizeof(hash_type),
785                                      &hash_type, &out_size);
786         if (err || !out_size || hash_type.mgmt_msg_head.status) {
787                 PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x",
788                         err, hash_type.mgmt_msg_head.status, out_size);
789                 return -EINVAL;
790         }
791
792         return 0;
793 }
794
795 int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
796 {
797         struct nic_rss_indirect_tbl *indir_tbl;
798         struct hinic_cmd_buf *cmd_buf;
799         int i;
800         u32 *temp;
801         u32 indir_size;
802         u64 out_param;
803         int err;
804
805         if (!hwdev || !indir_table) {
806                 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
807                 return -EINVAL;
808         }
809
810         cmd_buf = hinic_alloc_cmd_buf(hwdev);
811         if (!cmd_buf) {
812                 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
813                 return -ENOMEM;
814         }
815
816         cmd_buf->size = sizeof(struct nic_rss_indirect_tbl);
817         indir_tbl = cmd_buf->buf;
818         indir_tbl->group_index = cpu_to_be32(tmpl_idx);
819
820         for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
821                 indir_tbl->entry[i] = (u8)(*(indir_table + i));
822
823                 if (0x3 == (i & 0x3)) {
824                         temp = (u32 *)&indir_tbl->entry[i - 3];
825                         *temp = cpu_to_be32(*temp);
826                 }
827         }
828
829         /* configure the rss indirect table by command queue */
830         indir_size = HINIC_RSS_INDIR_SIZE / 2;
831         indir_tbl->offset = 0;
832         indir_tbl->size = cpu_to_be32(indir_size);
833
834         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
835                                      HINIC_MOD_L2NIC,
836                                      HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
837                                      cmd_buf, &out_param, 0);
838         if (err || out_param != 0) {
839                 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
840                 err = -EFAULT;
841                 goto free_buf;
842         }
843
844         indir_tbl->offset = cpu_to_be32(indir_size);
845         indir_tbl->size = cpu_to_be32(indir_size);
846         memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size);
847
848         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
849                                      HINIC_MOD_L2NIC,
850                                      HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
851                                      cmd_buf, &out_param, 0);
852         if (err || out_param != 0) {
853                 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
854                 err = -EFAULT;
855         }
856
857 free_buf:
858         hinic_free_cmd_buf(hwdev, cmd_buf);
859
860         return err;
861 }
862
863 int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
864 {
865         struct hinic_rss_indir_table rss_cfg;
866         u16 out_size = sizeof(rss_cfg);
867         int err = 0, i;
868
869         if (!hwdev || !indir_table) {
870                 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
871                 return -EINVAL;
872         }
873
874         memset(&rss_cfg, 0, sizeof(rss_cfg));
875         rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
876         rss_cfg.func_id = hinic_global_func_id(hwdev);
877         rss_cfg.template_id = (u8)tmpl_idx;
878
879         err = l2nic_msg_to_mgmt_sync(hwdev,
880                                      HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
881                                      &rss_cfg, sizeof(rss_cfg), &rss_cfg,
882                                      &out_size);
883         if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
884                 PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x",
885                         err, rss_cfg.mgmt_msg_head.status, out_size);
886                 return -EINVAL;
887         }
888
889         hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
890         for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
891                 indir_table[i] = rss_cfg.indir[i];
892
893         return 0;
894 }
895
896 int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc)
897 {
898         struct hinic_rss_config rss_cfg;
899         u16 out_size = sizeof(rss_cfg);
900         int err;
901
902         /* micro code required: number of TC should be power of 2 */
903         if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) {
904                 PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2",
905                         tc_num);
906                 return -EINVAL;
907         }
908
909         memset(&rss_cfg, 0, sizeof(rss_cfg));
910         rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
911         rss_cfg.func_id = hinic_global_func_id(hwdev);
912         rss_cfg.rss_en = rss_en;
913         rss_cfg.template_id = tmpl_idx;
914         rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
915
916         memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX);
917
918         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG,
919                                      &rss_cfg, sizeof(rss_cfg), &rss_cfg,
920                                      &out_size);
921         if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
922                 PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x",
923                         err, rss_cfg.mgmt_msg_head.status, out_size);
924                 return -EINVAL;
925         }
926
927         return 0;
928 }
929
930 /**
931  * hinic_rss_template_alloc - Get rss template id from the chip,
932  * all functions share 96 templates.
933  *
934  * @param hwdev
935  *   The hardware interface of a nic device.
936  * @param tmpl_idx
937  *   Index of rss template from chip.
938  *
939  * @return
940  *   0 on success.
941  *   negative error value otherwise.
942  */
943 int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
944 {
945         struct hinic_rss_template_mgmt template_mgmt;
946         u16 out_size = sizeof(template_mgmt);
947         int err;
948
949         if (!hwdev || !tmpl_idx) {
950                 PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL");
951                 return -EINVAL;
952         }
953
954         memset(&template_mgmt, 0, sizeof(template_mgmt));
955         template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
956         template_mgmt.func_id = hinic_global_func_id(hwdev);
957         template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
958
959         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
960                                      &template_mgmt, sizeof(template_mgmt),
961                                      &template_mgmt, &out_size);
962         if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
963                 PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x",
964                         err, template_mgmt.mgmt_msg_head.status, out_size);
965                 return -EINVAL;
966         }
967
968         *tmpl_idx = template_mgmt.template_id;
969
970         return 0;
971 }
972
973 /**
974  * hinic_rss_template_free - Free rss template id to the chip.
975  *
976  * @param hwdev
977  *   The hardware interface of a nic device.
978  * @param tmpl_idx
979  *   Index of rss template from chip.
980  *
981  * @return
982  *   0 on success.
983  *   negative error value otherwise.
984  */
985 int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
986 {
987         struct hinic_rss_template_mgmt template_mgmt;
988         u16 out_size = sizeof(template_mgmt);
989         int err;
990
991         if (!hwdev) {
992                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
993                 return -EINVAL;
994         }
995
996         memset(&template_mgmt, 0, sizeof(template_mgmt));
997         template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
998         template_mgmt.func_id = hinic_global_func_id(hwdev);
999         template_mgmt.template_id = tmpl_idx;
1000         template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
1001
1002         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
1003                                      &template_mgmt, sizeof(template_mgmt),
1004                                      &template_mgmt, &out_size);
1005         if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
1006                 PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x",
1007                         err, template_mgmt.mgmt_msg_head.status, out_size);
1008                 return -EINVAL;
1009         }
1010
1011         return 0;
1012 }
1013
1014 /**
1015  * hinic_set_rx_vhd_mode - Change rx buffer size after initialization.
1016  *
1017  * @param hwdev
1018  *   The hardware interface of a nic device.
1019  * @param vhd_mode
1020  *   Not needed.
1021  * @param rx_buf_sz
1022  *   receive buffer size.
1023  *
1024  * @return
1025  *   0 on success.
1026  *   negative error value otherwise.
1027  */
1028 int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
1029 {
1030         struct hinic_set_vhd_mode vhd_mode_cfg;
1031         u16 out_size = sizeof(vhd_mode_cfg);
1032         int err;
1033
1034         if (!hwdev) {
1035                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1036                 return -EINVAL;
1037         }
1038
1039         memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg));
1040
1041         vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1042         vhd_mode_cfg.func_id = hinic_global_func_id(hwdev);
1043         vhd_mode_cfg.vhd_type = vhd_mode;
1044         vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz;
1045
1046         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG,
1047                                      &vhd_mode_cfg, sizeof(vhd_mode_cfg),
1048                                      &vhd_mode_cfg, &out_size);
1049         if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) {
1050                 PMD_DRV_LOG(ERR,
1051                         "Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
1052                         err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
1053
1054                 return -EIO;
1055         }
1056
1057         return 0;
1058 }
1059
1060 int hinic_set_rx_mode(void *hwdev, u32 enable)
1061 {
1062         struct hinic_rx_mode_config rx_mode_cfg;
1063         u16 out_size = sizeof(rx_mode_cfg);
1064         int err;
1065
1066         if (!hwdev) {
1067                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1068                 return -EINVAL;
1069         }
1070
1071         memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
1072         rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1073         rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
1074         rx_mode_cfg.rx_mode = enable;
1075
1076         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
1077                                      &rx_mode_cfg, sizeof(rx_mode_cfg),
1078                                      &rx_mode_cfg, &out_size);
1079         if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) {
1080                 PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x",
1081                         err, rx_mode_cfg.mgmt_msg_head.status, out_size);
1082                 return -EINVAL;
1083         }
1084
1085         return 0;
1086 }
1087
1088 int hinic_set_rx_csum_offload(void *hwdev, u32 en)
1089 {
1090         struct hinic_checksum_offload rx_csum_cfg;
1091         u16 out_size = sizeof(rx_csum_cfg);
1092         int err;
1093
1094         if (!hwdev) {
1095                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1096                 return -EINVAL;
1097         }
1098
1099         memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg));
1100         rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1101         rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
1102         rx_csum_cfg.rx_csum_offload = en;
1103
1104         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
1105                                      &rx_csum_cfg, sizeof(rx_csum_cfg),
1106                                      &rx_csum_cfg, &out_size);
1107         if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) {
1108                 PMD_DRV_LOG(ERR,
1109                         "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x",
1110                         err, rx_csum_cfg.mgmt_msg_head.status, out_size);
1111                 return -EINVAL;
1112         }
1113
1114         return 0;
1115 }
1116
1117 int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num)
1118 {
1119         struct hinic_lro_config lro_cfg;
1120         u16 out_size = sizeof(lro_cfg);
1121         int err;
1122
1123         if (!hwdev) {
1124                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1125                 return -EINVAL;
1126         }
1127
1128         memset(&lro_cfg, 0, sizeof(lro_cfg));
1129         lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1130         lro_cfg.func_id = hinic_global_func_id(hwdev);
1131         lro_cfg.lro_ipv4_en = ipv4_en;
1132         lro_cfg.lro_ipv6_en = ipv6_en;
1133         lro_cfg.lro_max_wqe_num = max_wqe_num;
1134
1135         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO,
1136                                      &lro_cfg, sizeof(lro_cfg), &lro_cfg,
1137                                      &out_size);
1138         if (err || !out_size || lro_cfg.mgmt_msg_head.status) {
1139                 PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x",
1140                         err, lro_cfg.mgmt_msg_head.status, out_size);
1141                 return -EINVAL;
1142         }
1143
1144         return 0;
1145 }
1146
1147 int hinic_set_anti_attack(void *hwdev, bool enable)
1148 {
1149         struct hinic_port_anti_attack_rate rate;
1150         u16 out_size = sizeof(rate);
1151         int err;
1152
1153         if (!hwdev) {
1154                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1155                 return -EINVAL;
1156         }
1157
1158         memset(&rate, 0, sizeof(rate));
1159         rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1160         rate.func_id = hinic_global_func_id(hwdev);
1161         rate.enable = enable;
1162         rate.cir = ANTI_ATTACK_DEFAULT_CIR;
1163         rate.xir = ANTI_ATTACK_DEFAULT_XIR;
1164         rate.cbs = ANTI_ATTACK_DEFAULT_CBS;
1165         rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
1166
1167         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
1168                                      &rate, sizeof(rate), &rate,
1169                                      &out_size);
1170         if (err || !out_size || rate.mgmt_msg_head.status) {
1171                 PMD_DRV_LOG(ERR, "can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
1172                         (enable ? "enable" : "disable"), err,
1173                         rate.mgmt_msg_head.status, out_size);
1174                 return -EINVAL;
1175         }
1176
1177         return 0;
1178 }
1179
1180 /* Set autoneg status and restart port link status */
1181 int hinic_reset_port_link_cfg(void *hwdev)
1182 {
1183         struct hinic_reset_link_cfg reset_cfg;
1184         u16 out_size = sizeof(reset_cfg);
1185         int err;
1186
1187         memset(&reset_cfg, 0, sizeof(reset_cfg));
1188         reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1189         reset_cfg.func_id = hinic_global_func_id(hwdev);
1190
1191         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
1192                                      &reset_cfg, sizeof(reset_cfg),
1193                                      &reset_cfg, &out_size);
1194         if (err || !out_size || reset_cfg.mgmt_msg_head.status) {
1195                 PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x",
1196                         err, reset_cfg.mgmt_msg_head.status, out_size);
1197                 return -EFAULT;
1198         }
1199
1200         return 0;
1201 }
1202
1203 /**
1204  * hinic_vf_func_init - Register VF to PF.
1205  *
1206  * @param hwdev
1207  *   The hardware interface of a nic device.
1208  *
1209  * @return
1210  *   0 on success.
1211  *   negative error value otherwise.
1212  */
1213 int hinic_vf_func_init(struct hinic_hwdev *hwdev)
1214 {
1215         int err, state = 0;
1216
1217         if (!HINIC_IS_VF(hwdev))
1218                 return 0;
1219
1220         err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1221                         HINIC_PORT_CMD_VF_REGISTER, &state, sizeof(state),
1222                         NULL, NULL, 0);
1223         if (err) {
1224                 PMD_DRV_LOG(ERR, "Fail to register vf");
1225                 return err;
1226         }
1227
1228         return 0;
1229 }
1230
1231 /**
1232  * hinic_vf_func_free - Unregister VF from PF.
1233  *
1234  * @param hwdev
1235  *   The hardware interface of a nic device.
1236  */
1237 void hinic_vf_func_free(struct hinic_hwdev *hwdev)
1238 {
1239         int err;
1240
1241         if (hinic_func_type(hwdev) != TYPE_VF)
1242                 return;
1243
1244         err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1245                                 HINIC_PORT_CMD_VF_UNREGISTER, &err, sizeof(err),
1246                                 NULL, NULL, 0);
1247         if (err)
1248                 PMD_DRV_LOG(ERR, "Fail to unregister VF, err: %d", err);
1249 }
1250
1251 int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
1252 {
1253         struct hinic_fast_recycled_mode fast_recycled_mode;
1254         u16 out_size = sizeof(fast_recycled_mode);
1255         int err;
1256
1257         if (!hwdev) {
1258                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1259                 return -EINVAL;
1260         }
1261
1262         memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode));
1263         fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1264         fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
1265         fast_recycled_mode.fast_recycled_mode = mode;
1266
1267         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1268                                      HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET,
1269                                      &fast_recycled_mode,
1270                                      sizeof(fast_recycled_mode),
1271                                      &fast_recycled_mode, &out_size, 0);
1272         if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
1273                 PMD_DRV_LOG(ERR,
1274                         "Failed to set recycle mode, ret = %d",
1275                         fast_recycled_mode.mgmt_msg_head.status);
1276                 return -EFAULT;
1277         }
1278
1279         return 0;
1280 }
1281
1282 int hinic_clear_vport_stats(struct hinic_hwdev *hwdev)
1283 {
1284         struct hinic_clear_vport_stats clear_vport_stats;
1285         u16 out_size = sizeof(clear_vport_stats);
1286         int err;
1287
1288         if (!hwdev) {
1289                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1290                 return -EINVAL;
1291         }
1292
1293         memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
1294         clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1295         clear_vport_stats.func_id = hinic_global_func_id(hwdev);
1296
1297         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT,
1298                                      &clear_vport_stats,
1299                                      sizeof(clear_vport_stats),
1300                                      &clear_vport_stats, &out_size);
1301         if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) {
1302                 PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x",
1303                         err, clear_vport_stats.mgmt_msg_head.status, out_size);
1304                 return -EINVAL;
1305         }
1306
1307         return 0;
1308 }
1309
1310 int hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev)
1311 {
1312         struct hinic_clear_port_stats clear_phy_port_stats;
1313         u16 out_size = sizeof(clear_phy_port_stats);
1314         int err;
1315
1316         if (!hwdev) {
1317                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1318                 return -EINVAL;
1319         }
1320
1321         memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats));
1322         clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1323         clear_phy_port_stats.func_id = hinic_global_func_id(hwdev);
1324
1325         err = l2nic_msg_to_mgmt_sync(hwdev,
1326                                      HINIC_PORT_CMD_CLEAR_PORT_STATISTICS,
1327                                      &clear_phy_port_stats,
1328                                      sizeof(clear_phy_port_stats),
1329                                      &clear_phy_port_stats, &out_size);
1330         if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) {
1331                 PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x",
1332                         err, clear_phy_port_stats.mgmt_msg_head.status,
1333                         out_size);
1334                 return -EINVAL;
1335         }
1336
1337         return 0;
1338 }
1339
1340 int hinic_set_link_status_follow(void *hwdev,
1341                                  enum hinic_link_follow_status status)
1342 {
1343         struct hinic_set_link_follow follow;
1344         u16 out_size = sizeof(follow);
1345         int err;
1346
1347         if (!hwdev)
1348                 return -EINVAL;
1349
1350         if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
1351                 return 0;
1352
1353         if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) {
1354                 PMD_DRV_LOG(ERR,
1355                         "Invalid link follow status: %d", status);
1356                 return -EINVAL;
1357         }
1358
1359         memset(&follow, 0, sizeof(follow));
1360         follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1361         follow.func_id = hinic_global_func_id(hwdev);
1362         follow.follow_status = status;
1363
1364         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
1365                                      &follow, sizeof(follow),
1366                                      &follow, &out_size);
1367         if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
1368              follow.mgmt_msg_head.status) || err || !out_size) {
1369                 PMD_DRV_LOG(ERR,
1370                         "Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x",
1371                         err, follow.mgmt_msg_head.status, out_size);
1372                 return -EFAULT;
1373         }
1374
1375         return follow.mgmt_msg_head.status;
1376 }
1377
1378 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
1379 {
1380         struct hinic_link_mode_cmd link_mode;
1381         u16 out_size = sizeof(link_mode);
1382         int err;
1383
1384         if (!hwdev || !supported || !advertised)
1385                 return -EINVAL;
1386
1387         memset(&link_mode, 0, sizeof(link_mode));
1388         link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1389         link_mode.func_id = hinic_global_func_id(hwdev);
1390
1391         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
1392                                      &link_mode, sizeof(link_mode),
1393                                      &link_mode, &out_size);
1394         if (err || !out_size || link_mode.mgmt_msg_head.status) {
1395                 PMD_DRV_LOG(ERR,
1396                         "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x",
1397                         err, link_mode.mgmt_msg_head.status, out_size);
1398                 return -EINVAL;
1399         }
1400
1401         *supported = link_mode.supported;
1402         *advertised = link_mode.advertised;
1403
1404         return 0;
1405 }
1406
1407 /**
1408  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport
1409  * fake failed when device start.
1410  *
1411  * @param hwdev
1412  *   The hardware interface of a nic device.
1413  *
1414  * @return
1415  *   0 on success.
1416  *   negative error value otherwise.
1417  */
1418 int hinic_flush_qp_res(void *hwdev)
1419 {
1420         struct hinic_clear_qp_resource qp_res;
1421         u16 out_size = sizeof(qp_res);
1422         int err;
1423
1424         memset(&qp_res, 0, sizeof(qp_res));
1425         qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1426         qp_res.func_id = hinic_global_func_id(hwdev);
1427
1428         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES,
1429                                      &qp_res, sizeof(qp_res), &qp_res,
1430                                      &out_size);
1431         if (err || !out_size || qp_res.mgmt_msg_head.status) {
1432                 PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x",
1433                         err, qp_res.mgmt_msg_head.status, out_size);
1434                 return -EINVAL;
1435         }
1436
1437         return 0;
1438 }