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