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