net/hinic: add unicast and multicast MAC set
[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\n");
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\n",
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.\n");
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,
383                                      sizeof(vlan_info), &vlan_info,
384                                      &out_size);
385         if (err || !out_size || vlan_info.mgmt_msg_head.status) {
386                 PMD_DRV_LOG(ERR,
387                         "Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x\n",
388                         add ? "add" : "remove", err,
389                         vlan_info.mgmt_msg_head.status, out_size);
390                 return -EINVAL;
391         }
392
393         return 0;
394 }
395
396 /**
397  * hinic_config_vlan_filter - Enable or Disable vlan filter.
398  *
399  * @param hwdev
400  *   The hardware interface of a nic device.
401  * @param vlan_filter_ctrl
402  *   Enable or Disable.
403  *
404  * @return
405  *   0 on success.
406  *   negative error value otherwise.
407  */
408 int hinic_config_vlan_filter(void *hwdev, u32 vlan_filter_ctrl)
409 {
410         struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
411         struct hinic_vlan_filter vlan_filter;
412         u16 out_size = sizeof(vlan_filter);
413         int err;
414
415         if (!hwdev)
416                 return -EINVAL;
417
418         memset(&vlan_filter, 0, sizeof(vlan_filter));
419         vlan_filter.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
420         vlan_filter.func_id = hinic_global_func_id(nic_hwdev);
421         vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl;
422
423         err = l2nic_msg_to_mgmt_sync(nic_hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,
424                                      &vlan_filter, sizeof(vlan_filter),
425                                      &vlan_filter, &out_size);
426         if (vlan_filter.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
427                 err = HINIC_MGMT_CMD_UNSUPPORTED;
428         } else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
429                 (HINIC_IS_VF(nic_hwdev))) {
430                 err = HINIC_MGMT_CMD_UNSUPPORTED;
431         } else if (err || !out_size || vlan_filter.mgmt_msg_head.status) {
432                 PMD_DRV_LOG(ERR,
433                         "Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x\n",
434                         vlan_filter_ctrl, err,
435                         vlan_filter.mgmt_msg_head.status, out_size);
436                 err = -EINVAL;
437         }
438
439         return err;
440 }
441
442 /**
443  * hinic_set_rx_vlan_offload - Enable or Disable vlan offload.
444  *
445  * @param hwdev
446  *   The hardware interface of a nic device.
447  * @param en
448  *   Enable or Disable.
449  *
450  * @return
451  *   0 on success.
452  *   negative error value otherwise.
453  */
454 int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
455 {
456         struct hinic_vlan_offload vlan_cfg;
457         u16 out_size = sizeof(vlan_cfg);
458         int err;
459
460         if (!hwdev) {
461                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
462                 return -EINVAL;
463         }
464
465         memset(&vlan_cfg, 0, sizeof(vlan_cfg));
466         vlan_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
467         vlan_cfg.func_id = hinic_global_func_id(hwdev);
468         vlan_cfg.vlan_rx_offload = en;
469
470         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
471                                         &vlan_cfg, sizeof(vlan_cfg),
472                                         &vlan_cfg, &out_size);
473         if (err || !out_size || vlan_cfg.mgmt_msg_head.status) {
474                 PMD_DRV_LOG(ERR,
475                         "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
476                         err, vlan_cfg.mgmt_msg_head.status, out_size);
477                 return -EINVAL;
478         }
479
480         return 0;
481 }
482
483 /**
484  * hinic_get_link_status - Get link status from hardware.
485  *
486  * @param hwdev
487  *   The hardware interface of a nic device.
488  * @param link_state
489  *   Link status.
490  *
491  * @return
492  *   0 on success.
493  *   negative error value otherwise.
494  */
495 int hinic_get_link_status(void *hwdev, u8 *link_state)
496 {
497         struct hinic_get_link get_link;
498         u16 out_size = sizeof(get_link);
499         int err;
500
501         if (!hwdev || !link_state) {
502                 PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL");
503                 return -EINVAL;
504         }
505
506         memset(&get_link, 0, sizeof(get_link));
507         get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
508         get_link.func_id = hinic_global_func_id(hwdev);
509
510         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
511                                      &get_link, sizeof(get_link),
512                                      &get_link, &out_size);
513         if (err || !out_size || get_link.mgmt_msg_head.status) {
514                 PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x",
515                         err, get_link.mgmt_msg_head.status, out_size);
516                 return -EINVAL;
517         }
518
519         *link_state = get_link.link_status;
520
521         return 0;
522 }
523
524 /**
525  * hinic_set_vport_enable - Notify firmware that driver is ready or not.
526  *
527  * @param hwdev
528  *   The hardware interface of a nic device.
529  * @param enable
530  *   1: driver is ready; 0: driver is not ok.
531  *
532  * @return
533  *   0 on success.
534  *   negative error value otherwise.
535  */
536 int hinic_set_vport_enable(void *hwdev, bool enable)
537 {
538         struct hinic_vport_state en_state;
539         u16 out_size = sizeof(en_state);
540         int err;
541
542         if (!hwdev) {
543                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
544                 return -EINVAL;
545         }
546
547         memset(&en_state, 0, sizeof(en_state));
548         en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
549         en_state.func_id = hinic_global_func_id(hwdev);
550         en_state.state = (enable ? 1 : 0);
551
552         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
553                                      &en_state, sizeof(en_state),
554                                      &en_state, &out_size);
555         if (err || !out_size || en_state.mgmt_msg_head.status) {
556                 PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x",
557                         err, en_state.mgmt_msg_head.status, out_size);
558                 return -EINVAL;
559         }
560
561         return 0;
562 }
563
564 /**
565  * hinic_set_port_enable - Open MAG to receive packets.
566  *
567  * @param hwdev
568  *   The hardware interface of a nic device.
569  * @param enable
570  *   1: open MAG; 0: close MAG.
571  *
572  * @return
573  *   0 on success.
574  *   negative error value otherwise.
575  */
576 int hinic_set_port_enable(void *hwdev, bool enable)
577 {
578         struct hinic_port_state en_state;
579         u16 out_size = sizeof(en_state);
580         int err;
581
582         if (!hwdev) {
583                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
584                 return -EINVAL;
585         }
586
587         if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
588                 return 0;
589
590         memset(&en_state, 0, sizeof(en_state));
591         en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
592         en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE);
593
594         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
595                                      &en_state, sizeof(en_state),
596                                      &en_state, &out_size);
597         if (err || !out_size || en_state.mgmt_msg_head.status) {
598                 PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x",
599                         err, en_state.mgmt_msg_head.status, out_size);
600                 return -EINVAL;
601         }
602
603         return 0;
604 }
605
606 int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
607 {
608         struct hinic_port_info port_msg;
609         u16 out_size = sizeof(port_msg);
610         int err;
611
612         if (!hwdev || !port_info) {
613                 PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL");
614                 return -EINVAL;
615         }
616
617         memset(&port_msg, 0, sizeof(port_msg));
618         port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
619         port_msg.func_id = hinic_global_func_id(hwdev);
620
621         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
622                                      &port_msg, sizeof(port_msg),
623                                      &port_msg, &out_size);
624         if (err || !out_size || port_msg.mgmt_msg_head.status) {
625                 PMD_DRV_LOG(ERR,
626                         "Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
627                         err, port_msg.mgmt_msg_head.status, out_size);
628                 return err;
629         }
630
631         port_info->autoneg_cap = port_msg.autoneg_cap;
632         port_info->autoneg_state = port_msg.autoneg_state;
633         port_info->duplex = port_msg.duplex;
634         port_info->port_type = port_msg.port_type;
635         port_info->speed = port_msg.speed;
636
637         return 0;
638 }
639
640 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
641 {
642         struct hinic_pause_config pause_info;
643         u16 out_size = sizeof(pause_info);
644         int err;
645
646         if (!hwdev) {
647                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
648                 return -EINVAL;
649         }
650
651         memset(&pause_info, 0, sizeof(pause_info));
652         pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
653         pause_info.func_id = hinic_global_func_id(hwdev);
654         pause_info.auto_neg = nic_pause.auto_neg;
655         pause_info.rx_pause = nic_pause.rx_pause;
656         pause_info.tx_pause = nic_pause.tx_pause;
657
658         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
659                                      &pause_info, sizeof(pause_info),
660                                      &pause_info, &out_size);
661         if (err || !out_size || pause_info.mgmt_msg_head.status) {
662                 PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x",
663                         err, pause_info.mgmt_msg_head.status, out_size);
664                 return -EINVAL;
665         }
666
667         return 0;
668 }
669
670 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
671                       u8 *pgid, u8 *up_bw, u8 *prio)
672 {
673         struct hinic_up_ets_cfg ets;
674         u16 out_size = sizeof(ets);
675         u16 up_bw_t = 0;
676         u8 pg_bw_t = 0;
677         int i, err;
678
679         if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) {
680                 PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL");
681                 return -EINVAL;
682         }
683
684         for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
685                 up_bw_t += *(up_bw + i);
686                 pg_bw_t += *(pg_bw + i);
687
688                 if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
689                         PMD_DRV_LOG(ERR,
690                                 "Invalid up %d mapping tc: %d", i,
691                                 *(up_tc + i));
692                         return -EINVAL;
693                 }
694         }
695
696         if (pg_bw_t != 100 || (up_bw_t % 100) != 0) {
697                 PMD_DRV_LOG(ERR,
698                         "Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t);
699                 return -EINVAL;
700         }
701
702         memset(&ets, 0, sizeof(ets));
703         ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
704         ets.port_id = 0;        /* reserved */
705         memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX);
706         memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX);
707         memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX);
708         memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX);
709         memcpy(ets.prio, prio, HINIC_DCB_UP_MAX);
710
711         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS,
712                                      &ets, sizeof(ets), &ets, &out_size);
713         if (err || ets.mgmt_msg_head.status || !out_size) {
714                 PMD_DRV_LOG(ERR,
715                         "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x",
716                         err, ets.mgmt_msg_head.status, out_size);
717                 return -EINVAL;
718         }
719
720         return 0;
721 }
722
723 int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats)
724 {
725         struct hinic_port_stats_info vport_stats_cmd;
726         struct hinic_cmd_vport_stats vport_stats_rsp;
727         u16 out_size = sizeof(vport_stats_rsp);
728         int err;
729
730         if (!hwdev || !stats) {
731                 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
732                 return -EINVAL;
733         }
734
735         memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp));
736         memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd));
737         vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
738         vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
739         vport_stats_cmd.func_id = hinic_global_func_id(hwdev);
740         vport_stats_cmd.stats_size = sizeof(vport_stats_rsp);
741
742         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
743                                      &vport_stats_cmd, sizeof(vport_stats_cmd),
744                                      &vport_stats_rsp, &out_size);
745         if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) {
746                 PMD_DRV_LOG(ERR,
747                         "Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x",
748                         err, vport_stats_rsp.mgmt_msg_head.status, out_size);
749                 return -EFAULT;
750         }
751
752         memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats));
753
754         return 0;
755 }
756
757 int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats)
758 {
759         struct hinic_port_stats_info port_stats_cmd;
760         struct hinic_port_stats port_stats_rsp;
761         u16 out_size = sizeof(port_stats_rsp);
762         int err;
763
764         if (!hwdev || !stats) {
765                 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
766                 return -EINVAL;
767         }
768
769         memset(&port_stats_rsp, 0, sizeof(port_stats_rsp));
770         memset(&port_stats_cmd, 0, sizeof(port_stats_cmd));
771         port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
772         port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
773         port_stats_cmd.stats_size = sizeof(port_stats_rsp);
774
775         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
776                                      &port_stats_cmd, sizeof(port_stats_cmd),
777                                      &port_stats_rsp, &out_size);
778         if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) {
779                 PMD_DRV_LOG(ERR,
780                         "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x",
781                         err, port_stats_rsp.mgmt_msg_head.status, out_size);
782                 return -EFAULT;
783         }
784
785         memcpy(stats, &port_stats_rsp.stats, sizeof(*stats));
786
787         return 0;
788 }
789
790 int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type)
791 {
792         struct nic_rss_context_tbl *ctx_tbl;
793         struct hinic_cmd_buf *cmd_buf;
794         u32 ctx = 0;
795         u64 out_param;
796         int err;
797
798         if (!hwdev) {
799                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
800                 return -EINVAL;
801         }
802
803         cmd_buf = hinic_alloc_cmd_buf(hwdev);
804         if (!cmd_buf) {
805                 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
806                 return -ENOMEM;
807         }
808
809         ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
810                 HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
811                 HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
812                 HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
813                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
814                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
815                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
816                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
817                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
818
819         cmd_buf->size = sizeof(struct nic_rss_context_tbl);
820
821         ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf;
822         ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
823         ctx_tbl->offset = 0;
824         ctx_tbl->size = sizeof(u32);
825         ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
826         ctx_tbl->rsvd = 0;
827         ctx_tbl->ctx = cpu_to_be32(ctx);
828
829         /* cfg the rss context table by command queue */
830         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
831                                      HINIC_MOD_L2NIC,
832                                      HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
833                                      cmd_buf, &out_param, 0);
834
835         hinic_free_cmd_buf(hwdev, cmd_buf);
836
837         if (err || out_param != 0) {
838                 PMD_DRV_LOG(ERR, "Failed to set rss context table");
839                 return -EFAULT;
840         }
841
842         return 0;
843 }
844
845 int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type)
846 {
847         struct hinic_rss_context_table ctx_tbl;
848         u16 out_size = sizeof(ctx_tbl);
849         int err;
850
851         if (!hwdev || !rss_type) {
852                 PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL");
853                 return -EINVAL;
854         }
855
856         ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
857         ctx_tbl.func_id = hinic_global_func_id(hwdev);
858         ctx_tbl.template_id = (u8)tmpl_idx;
859
860         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
861                                      &ctx_tbl, sizeof(ctx_tbl),
862                                      &ctx_tbl, &out_size);
863         if (err || !out_size || ctx_tbl.mgmt_msg_head.status) {
864                 PMD_DRV_LOG(ERR,
865                         "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x",
866                         err, ctx_tbl.mgmt_msg_head.status, out_size);
867                 return -EINVAL;
868         }
869
870         rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
871         rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
872         rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
873         rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
874         rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
875         rss_type->tcp_ipv6_ext =
876                         HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT);
877         rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
878         rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
879
880         return 0;
881 }
882
883 int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
884 {
885         struct hinic_rss_template_key temp_key;
886         u16 out_size = sizeof(temp_key);
887         int err;
888
889         if (!hwdev || !temp) {
890                 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
891                 return -EINVAL;
892         }
893
894         memset(&temp_key, 0, sizeof(temp_key));
895         temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
896         temp_key.func_id = hinic_global_func_id(hwdev);
897         temp_key.template_id = (u8)tmpl_idx;
898         memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
899
900         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
901                                      &temp_key, sizeof(temp_key),
902                                      &temp_key, &out_size);
903         if (err || !out_size || temp_key.mgmt_msg_head.status) {
904                 PMD_DRV_LOG(ERR,
905                         "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x",
906                         err, temp_key.mgmt_msg_head.status, out_size);
907                 return -EINVAL;
908         }
909
910         return 0;
911 }
912
913 int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
914 {
915         struct hinic_rss_template_key temp_key;
916         u16 out_size = sizeof(temp_key);
917         int err;
918
919         if (!hwdev || !temp) {
920                 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
921                 return -EINVAL;
922         }
923
924         memset(&temp_key, 0, sizeof(temp_key));
925         temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
926         temp_key.func_id = hinic_global_func_id(hwdev);
927         temp_key.template_id = (u8)tmpl_idx;
928
929         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
930                                      &temp_key, sizeof(temp_key),
931                                      &temp_key, &out_size);
932         if (err || !out_size || temp_key.mgmt_msg_head.status) {
933                 PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x",
934                         err, temp_key.mgmt_msg_head.status, out_size);
935                 return -EINVAL;
936         }
937
938         memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
939
940         return 0;
941 }
942
943 /**
944  * hinic_rss_set_hash_engine - Init rss hash function.
945  *
946  * @param hwdev
947  *   The hardware interface of a nic device.
948  * @param tmpl_idx
949  *   Index of rss template from NIC.
950  * @param type
951  *   Hash function, such as Toeplitz or XOR.
952  *
953  * @return
954  *   0 on success.
955  *   negative error value otherwise.
956  */
957 int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
958 {
959         struct hinic_rss_engine_type hash_type;
960         u16 out_size = sizeof(hash_type);
961         int err;
962
963         if (!hwdev) {
964                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
965                 return -EINVAL;
966         }
967
968         memset(&hash_type, 0, sizeof(hash_type));
969         hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
970         hash_type.func_id = hinic_global_func_id(hwdev);
971         hash_type.hash_engine = type;
972         hash_type.template_id = tmpl_idx;
973
974         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
975                                      &hash_type, sizeof(hash_type),
976                                      &hash_type, &out_size);
977         if (err || !out_size || hash_type.mgmt_msg_head.status) {
978                 PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x",
979                         err, hash_type.mgmt_msg_head.status, out_size);
980                 return -EINVAL;
981         }
982
983         return 0;
984 }
985
986 int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
987 {
988         struct nic_rss_indirect_tbl *indir_tbl;
989         struct hinic_cmd_buf *cmd_buf;
990         int i;
991         u32 *temp;
992         u32 indir_size;
993         u64 out_param;
994         int err;
995
996         if (!hwdev || !indir_table) {
997                 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
998                 return -EINVAL;
999         }
1000
1001         cmd_buf = hinic_alloc_cmd_buf(hwdev);
1002         if (!cmd_buf) {
1003                 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
1004                 return -ENOMEM;
1005         }
1006
1007         cmd_buf->size = sizeof(struct nic_rss_indirect_tbl);
1008         indir_tbl = cmd_buf->buf;
1009         indir_tbl->group_index = cpu_to_be32(tmpl_idx);
1010
1011         for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
1012                 indir_tbl->entry[i] = (u8)(*(indir_table + i));
1013
1014                 if (0x3 == (i & 0x3)) {
1015                         temp = (u32 *)&indir_tbl->entry[i - 3];
1016                         *temp = cpu_to_be32(*temp);
1017                 }
1018         }
1019
1020         /* configure the rss indirect table by command queue */
1021         indir_size = HINIC_RSS_INDIR_SIZE / 2;
1022         indir_tbl->offset = 0;
1023         indir_tbl->size = cpu_to_be32(indir_size);
1024
1025         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
1026                                      HINIC_MOD_L2NIC,
1027                                      HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
1028                                      cmd_buf, &out_param, 0);
1029         if (err || out_param != 0) {
1030                 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
1031                 err = -EFAULT;
1032                 goto free_buf;
1033         }
1034
1035         indir_tbl->offset = cpu_to_be32(indir_size);
1036         indir_tbl->size = cpu_to_be32(indir_size);
1037         memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size);
1038
1039         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
1040                                      HINIC_MOD_L2NIC,
1041                                      HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
1042                                      cmd_buf, &out_param, 0);
1043         if (err || out_param != 0) {
1044                 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
1045                 err = -EFAULT;
1046         }
1047
1048 free_buf:
1049         hinic_free_cmd_buf(hwdev, cmd_buf);
1050
1051         return err;
1052 }
1053
1054 int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
1055 {
1056         struct hinic_rss_indir_table rss_cfg;
1057         u16 out_size = sizeof(rss_cfg);
1058         int err = 0, i;
1059
1060         if (!hwdev || !indir_table) {
1061                 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
1062                 return -EINVAL;
1063         }
1064
1065         memset(&rss_cfg, 0, sizeof(rss_cfg));
1066         rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1067         rss_cfg.func_id = hinic_global_func_id(hwdev);
1068         rss_cfg.template_id = (u8)tmpl_idx;
1069
1070         err = l2nic_msg_to_mgmt_sync(hwdev,
1071                                      HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
1072                                      &rss_cfg, sizeof(rss_cfg), &rss_cfg,
1073                                      &out_size);
1074         if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
1075                 PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x",
1076                         err, rss_cfg.mgmt_msg_head.status, out_size);
1077                 return -EINVAL;
1078         }
1079
1080         hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
1081         for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
1082                 indir_table[i] = rss_cfg.indir[i];
1083
1084         return 0;
1085 }
1086
1087 int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc)
1088 {
1089         struct hinic_rss_config rss_cfg;
1090         u16 out_size = sizeof(rss_cfg);
1091         int err;
1092
1093         /* micro code required: number of TC should be power of 2 */
1094         if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) {
1095                 PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2",
1096                         tc_num);
1097                 return -EINVAL;
1098         }
1099
1100         memset(&rss_cfg, 0, sizeof(rss_cfg));
1101         rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1102         rss_cfg.func_id = hinic_global_func_id(hwdev);
1103         rss_cfg.rss_en = rss_en;
1104         rss_cfg.template_id = tmpl_idx;
1105         rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
1106
1107         memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX);
1108
1109         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG,
1110                                      &rss_cfg, sizeof(rss_cfg), &rss_cfg,
1111                                      &out_size);
1112         if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
1113                 PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x",
1114                         err, rss_cfg.mgmt_msg_head.status, out_size);
1115                 return -EINVAL;
1116         }
1117
1118         return 0;
1119 }
1120
1121 /**
1122  * hinic_rss_template_alloc - Get rss template id from the chip,
1123  * all functions share 96 templates.
1124  *
1125  * @param hwdev
1126  *   The hardware interface of a nic device.
1127  * @param tmpl_idx
1128  *   Index of rss template from chip.
1129  *
1130  * @return
1131  *   0 on success.
1132  *   negative error value otherwise.
1133  */
1134 int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
1135 {
1136         struct hinic_rss_template_mgmt template_mgmt;
1137         u16 out_size = sizeof(template_mgmt);
1138         int err;
1139
1140         if (!hwdev || !tmpl_idx) {
1141                 PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL");
1142                 return -EINVAL;
1143         }
1144
1145         memset(&template_mgmt, 0, sizeof(template_mgmt));
1146         template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1147         template_mgmt.func_id = hinic_global_func_id(hwdev);
1148         template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
1149
1150         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
1151                                      &template_mgmt, sizeof(template_mgmt),
1152                                      &template_mgmt, &out_size);
1153         if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
1154                 PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x",
1155                         err, template_mgmt.mgmt_msg_head.status, out_size);
1156                 return -EINVAL;
1157         }
1158
1159         *tmpl_idx = template_mgmt.template_id;
1160
1161         return 0;
1162 }
1163
1164 /**
1165  * hinic_rss_template_free - Free rss template id to the chip.
1166  *
1167  * @param hwdev
1168  *   The hardware interface of a nic device.
1169  * @param tmpl_idx
1170  *   Index of rss template from chip.
1171  *
1172  * @return
1173  *   0 on success.
1174  *   negative error value otherwise.
1175  */
1176 int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
1177 {
1178         struct hinic_rss_template_mgmt template_mgmt;
1179         u16 out_size = sizeof(template_mgmt);
1180         int err;
1181
1182         if (!hwdev) {
1183                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1184                 return -EINVAL;
1185         }
1186
1187         memset(&template_mgmt, 0, sizeof(template_mgmt));
1188         template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1189         template_mgmt.func_id = hinic_global_func_id(hwdev);
1190         template_mgmt.template_id = tmpl_idx;
1191         template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
1192
1193         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
1194                                      &template_mgmt, sizeof(template_mgmt),
1195                                      &template_mgmt, &out_size);
1196         if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
1197                 PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x",
1198                         err, template_mgmt.mgmt_msg_head.status, out_size);
1199                 return -EINVAL;
1200         }
1201
1202         return 0;
1203 }
1204
1205 /**
1206  * hinic_set_rx_vhd_mode - Change rx buffer size after initialization.
1207  *
1208  * @param hwdev
1209  *   The hardware interface of a nic device.
1210  * @param vhd_mode
1211  *   Not needed.
1212  * @param rx_buf_sz
1213  *   receive buffer size.
1214  *
1215  * @return
1216  *   0 on success.
1217  *   negative error value otherwise.
1218  */
1219 int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
1220 {
1221         struct hinic_set_vhd_mode vhd_mode_cfg;
1222         u16 out_size = sizeof(vhd_mode_cfg);
1223         int err;
1224
1225         if (!hwdev) {
1226                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1227                 return -EINVAL;
1228         }
1229
1230         memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg));
1231
1232         vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1233         vhd_mode_cfg.func_id = hinic_global_func_id(hwdev);
1234         vhd_mode_cfg.vhd_type = vhd_mode;
1235         vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz;
1236
1237         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG,
1238                                      &vhd_mode_cfg, sizeof(vhd_mode_cfg),
1239                                      &vhd_mode_cfg, &out_size);
1240         if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) {
1241                 PMD_DRV_LOG(ERR,
1242                         "Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
1243                         err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
1244
1245                 return -EIO;
1246         }
1247
1248         return 0;
1249 }
1250
1251 int hinic_set_rx_mode(void *hwdev, u32 enable)
1252 {
1253         struct hinic_rx_mode_config rx_mode_cfg;
1254         u16 out_size = sizeof(rx_mode_cfg);
1255         int err;
1256
1257         if (!hwdev) {
1258                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1259                 return -EINVAL;
1260         }
1261
1262         memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
1263         rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1264         rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
1265         rx_mode_cfg.rx_mode = enable;
1266
1267         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
1268                                      &rx_mode_cfg, sizeof(rx_mode_cfg),
1269                                      &rx_mode_cfg, &out_size);
1270         if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) {
1271                 PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x",
1272                         err, rx_mode_cfg.mgmt_msg_head.status, out_size);
1273                 return -EINVAL;
1274         }
1275
1276         return 0;
1277 }
1278
1279 int hinic_set_rx_csum_offload(void *hwdev, u32 en)
1280 {
1281         struct hinic_checksum_offload rx_csum_cfg;
1282         u16 out_size = sizeof(rx_csum_cfg);
1283         int err;
1284
1285         if (!hwdev) {
1286                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1287                 return -EINVAL;
1288         }
1289
1290         memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg));
1291         rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1292         rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
1293         rx_csum_cfg.rx_csum_offload = en;
1294
1295         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
1296                                      &rx_csum_cfg, sizeof(rx_csum_cfg),
1297                                      &rx_csum_cfg, &out_size);
1298         if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) {
1299                 PMD_DRV_LOG(ERR,
1300                         "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x",
1301                         err, rx_csum_cfg.mgmt_msg_head.status, out_size);
1302                 return -EINVAL;
1303         }
1304
1305         return 0;
1306 }
1307
1308 int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num)
1309 {
1310         struct hinic_lro_config lro_cfg;
1311         u16 out_size = sizeof(lro_cfg);
1312         int err;
1313
1314         if (!hwdev) {
1315                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1316                 return -EINVAL;
1317         }
1318
1319         memset(&lro_cfg, 0, sizeof(lro_cfg));
1320         lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1321         lro_cfg.func_id = hinic_global_func_id(hwdev);
1322         lro_cfg.lro_ipv4_en = ipv4_en;
1323         lro_cfg.lro_ipv6_en = ipv6_en;
1324         lro_cfg.lro_max_wqe_num = max_wqe_num;
1325
1326         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO,
1327                                      &lro_cfg, sizeof(lro_cfg), &lro_cfg,
1328                                      &out_size);
1329         if (err || !out_size || lro_cfg.mgmt_msg_head.status) {
1330                 PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x",
1331                         err, lro_cfg.mgmt_msg_head.status, out_size);
1332                 return -EINVAL;
1333         }
1334
1335         return 0;
1336 }
1337
1338 int hinic_set_anti_attack(void *hwdev, bool enable)
1339 {
1340         struct hinic_port_anti_attack_rate rate;
1341         u16 out_size = sizeof(rate);
1342         int err;
1343
1344         if (!hwdev) {
1345                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1346                 return -EINVAL;
1347         }
1348
1349         memset(&rate, 0, sizeof(rate));
1350         rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1351         rate.func_id = hinic_global_func_id(hwdev);
1352         rate.enable = enable;
1353         rate.cir = ANTI_ATTACK_DEFAULT_CIR;
1354         rate.xir = ANTI_ATTACK_DEFAULT_XIR;
1355         rate.cbs = ANTI_ATTACK_DEFAULT_CBS;
1356         rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
1357
1358         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
1359                                      &rate, sizeof(rate), &rate,
1360                                      &out_size);
1361         if (err || !out_size || rate.mgmt_msg_head.status) {
1362                 PMD_DRV_LOG(ERR, "can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
1363                         (enable ? "enable" : "disable"), err,
1364                         rate.mgmt_msg_head.status, out_size);
1365                 return -EINVAL;
1366         }
1367
1368         return 0;
1369 }
1370
1371 /* Set autoneg status and restart port link status */
1372 int hinic_reset_port_link_cfg(void *hwdev)
1373 {
1374         struct hinic_reset_link_cfg reset_cfg;
1375         u16 out_size = sizeof(reset_cfg);
1376         int err;
1377
1378         memset(&reset_cfg, 0, sizeof(reset_cfg));
1379         reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1380         reset_cfg.func_id = hinic_global_func_id(hwdev);
1381
1382         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
1383                                      &reset_cfg, sizeof(reset_cfg),
1384                                      &reset_cfg, &out_size);
1385         if (err || !out_size || reset_cfg.mgmt_msg_head.status) {
1386                 PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x",
1387                         err, reset_cfg.mgmt_msg_head.status, out_size);
1388                 return -EFAULT;
1389         }
1390
1391         return 0;
1392 }
1393
1394 /**
1395  * hinic_vf_func_init - Register VF to PF.
1396  *
1397  * @param hwdev
1398  *   The hardware interface of a nic device.
1399  *
1400  * @return
1401  *   0 on success.
1402  *   negative error value otherwise.
1403  */
1404 int hinic_vf_func_init(struct hinic_hwdev *hwdev)
1405 {
1406         int err, state = 0;
1407
1408         if (!HINIC_IS_VF(hwdev))
1409                 return 0;
1410
1411         err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1412                         HINIC_PORT_CMD_VF_REGISTER, &state, sizeof(state),
1413                         NULL, NULL, 0);
1414         if (err) {
1415                 PMD_DRV_LOG(ERR, "Fail to register vf");
1416                 return err;
1417         }
1418
1419         return 0;
1420 }
1421
1422 /**
1423  * hinic_vf_func_free - Unregister VF from PF.
1424  *
1425  * @param hwdev
1426  *   The hardware interface of a nic device.
1427  */
1428 void hinic_vf_func_free(struct hinic_hwdev *hwdev)
1429 {
1430         int err;
1431
1432         if (hinic_func_type(hwdev) != TYPE_VF)
1433                 return;
1434
1435         err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1436                                 HINIC_PORT_CMD_VF_UNREGISTER, &err, sizeof(err),
1437                                 NULL, NULL, 0);
1438         if (err)
1439                 PMD_DRV_LOG(ERR, "Fail to unregister VF, err: %d", err);
1440 }
1441
1442 int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
1443 {
1444         struct hinic_fast_recycled_mode fast_recycled_mode;
1445         u16 out_size = sizeof(fast_recycled_mode);
1446         int err;
1447
1448         if (!hwdev) {
1449                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1450                 return -EINVAL;
1451         }
1452
1453         memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode));
1454         fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1455         fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
1456         fast_recycled_mode.fast_recycled_mode = mode;
1457
1458         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1459                                      HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET,
1460                                      &fast_recycled_mode,
1461                                      sizeof(fast_recycled_mode),
1462                                      &fast_recycled_mode, &out_size, 0);
1463         if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
1464                 PMD_DRV_LOG(ERR,
1465                         "Failed to set recycle mode, ret = %d",
1466                         fast_recycled_mode.mgmt_msg_head.status);
1467                 return -EFAULT;
1468         }
1469
1470         return 0;
1471 }
1472
1473 int hinic_clear_vport_stats(struct hinic_hwdev *hwdev)
1474 {
1475         struct hinic_clear_vport_stats clear_vport_stats;
1476         u16 out_size = sizeof(clear_vport_stats);
1477         int err;
1478
1479         if (!hwdev) {
1480                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1481                 return -EINVAL;
1482         }
1483
1484         memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
1485         clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1486         clear_vport_stats.func_id = hinic_global_func_id(hwdev);
1487
1488         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT,
1489                                      &clear_vport_stats,
1490                                      sizeof(clear_vport_stats),
1491                                      &clear_vport_stats, &out_size);
1492         if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) {
1493                 PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x",
1494                         err, clear_vport_stats.mgmt_msg_head.status, out_size);
1495                 return -EINVAL;
1496         }
1497
1498         return 0;
1499 }
1500
1501 int hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev)
1502 {
1503         struct hinic_clear_port_stats clear_phy_port_stats;
1504         u16 out_size = sizeof(clear_phy_port_stats);
1505         int err;
1506
1507         if (!hwdev) {
1508                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1509                 return -EINVAL;
1510         }
1511
1512         memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats));
1513         clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1514         clear_phy_port_stats.func_id = hinic_global_func_id(hwdev);
1515
1516         err = l2nic_msg_to_mgmt_sync(hwdev,
1517                                      HINIC_PORT_CMD_CLEAR_PORT_STATISTICS,
1518                                      &clear_phy_port_stats,
1519                                      sizeof(clear_phy_port_stats),
1520                                      &clear_phy_port_stats, &out_size);
1521         if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) {
1522                 PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x",
1523                         err, clear_phy_port_stats.mgmt_msg_head.status,
1524                         out_size);
1525                 return -EINVAL;
1526         }
1527
1528         return 0;
1529 }
1530
1531 int hinic_set_link_status_follow(void *hwdev,
1532                                  enum hinic_link_follow_status status)
1533 {
1534         struct hinic_set_link_follow follow;
1535         u16 out_size = sizeof(follow);
1536         int err;
1537
1538         if (!hwdev)
1539                 return -EINVAL;
1540
1541         if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
1542                 return 0;
1543
1544         if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) {
1545                 PMD_DRV_LOG(ERR,
1546                         "Invalid link follow status: %d", status);
1547                 return -EINVAL;
1548         }
1549
1550         memset(&follow, 0, sizeof(follow));
1551         follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1552         follow.func_id = hinic_global_func_id(hwdev);
1553         follow.follow_status = status;
1554
1555         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
1556                                      &follow, sizeof(follow),
1557                                      &follow, &out_size);
1558         if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
1559              follow.mgmt_msg_head.status) || err || !out_size) {
1560                 PMD_DRV_LOG(ERR,
1561                         "Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x",
1562                         err, follow.mgmt_msg_head.status, out_size);
1563                 return -EFAULT;
1564         }
1565
1566         return follow.mgmt_msg_head.status;
1567 }
1568
1569 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
1570 {
1571         struct hinic_link_mode_cmd link_mode;
1572         u16 out_size = sizeof(link_mode);
1573         int err;
1574
1575         if (!hwdev || !supported || !advertised)
1576                 return -EINVAL;
1577
1578         memset(&link_mode, 0, sizeof(link_mode));
1579         link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1580         link_mode.func_id = hinic_global_func_id(hwdev);
1581
1582         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
1583                                      &link_mode, sizeof(link_mode),
1584                                      &link_mode, &out_size);
1585         if (err || !out_size || link_mode.mgmt_msg_head.status) {
1586                 PMD_DRV_LOG(ERR,
1587                         "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x",
1588                         err, link_mode.mgmt_msg_head.status, out_size);
1589                 return -EINVAL;
1590         }
1591
1592         *supported = link_mode.supported;
1593         *advertised = link_mode.advertised;
1594
1595         return 0;
1596 }
1597
1598 /**
1599  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport
1600  * fake failed when device start.
1601  *
1602  * @param hwdev
1603  *   The hardware interface of a nic device.
1604  *
1605  * @return
1606  *   0 on success.
1607  *   negative error value otherwise.
1608  */
1609 int hinic_flush_qp_res(void *hwdev)
1610 {
1611         struct hinic_clear_qp_resource qp_res;
1612         u16 out_size = sizeof(qp_res);
1613         int err;
1614
1615         memset(&qp_res, 0, sizeof(qp_res));
1616         qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1617         qp_res.func_id = hinic_global_func_id(hwdev);
1618
1619         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES,
1620                                      &qp_res, sizeof(qp_res), &qp_res,
1621                                      &out_size);
1622         if (err || !out_size || qp_res.mgmt_msg_head.status) {
1623                 PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x",
1624                         err, qp_res.mgmt_msg_head.status, out_size);
1625                 return -EINVAL;
1626         }
1627
1628         return 0;
1629 }
1630
1631 /**
1632  * hinic_vf_get_default_cos - Get default cos of VF.
1633  *
1634  * @param hwdev
1635  *   The hardware interface of a nic device.
1636  * @param cos_id
1637  *   Cos value.
1638  *
1639  * @return
1640  *   0 on success.
1641  *   negative error value otherwise.
1642  */
1643 int hinic_vf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
1644 {
1645         struct hinic_vf_default_cos vf_cos;
1646         u16 out_size = sizeof(vf_cos);
1647         int err;
1648
1649         memset(&vf_cos, 0, sizeof(vf_cos));
1650         vf_cos.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1651
1652         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
1653                                      HINIC_PORT_CMD_GET_VF_COS, &vf_cos,
1654                                      sizeof(vf_cos), &vf_cos,
1655                                      &out_size, 0);
1656         if (err || !out_size || vf_cos.mgmt_msg_head.status) {
1657                 PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d, status: 0x%x, out size: 0x%x",
1658                         err, vf_cos.mgmt_msg_head.status, out_size);
1659                 return -EFAULT;
1660         }
1661         *cos_id = vf_cos.state.default_cos;
1662
1663         return 0;
1664 }