8bd7ed65d2084cb1d259f2c72802da5cd1f9779a
[dpdk.git] / drivers / net / hinic / base / hinic_pmd_niccfg.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(c) 2017 Huawei Technologies Co., Ltd
3  */
4
5 #include "hinic_compat.h"
6 #include "hinic_pmd_hwdev.h"
7 #include "hinic_pmd_hwif.h"
8 #include "hinic_pmd_eqs.h"
9 #include "hinic_pmd_wq.h"
10 #include "hinic_pmd_mgmt.h"
11 #include "hinic_pmd_cmdq.h"
12 #include "hinic_pmd_niccfg.h"
13 #include "hinic_pmd_mbox.h"
14
15 #define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in,              \
16                                in_size, buf_out, out_size)      \
17         hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, cmd,     \
18                         buf_in, in_size,                        \
19                         buf_out, out_size, 0)
20
21 /**
22  * hinic_init_function_table - Initialize function table.
23  *
24  * @param hwdev
25  *   The hardware interface of a nic device.
26  * @param rx_buf_sz
27  *   Receive buffer size.
28  *
29  * @return
30  *   0 on success.
31  *   negative error value otherwise.
32  */
33 int hinic_init_function_table(void *hwdev, u16 rx_buf_sz)
34 {
35         struct hinic_function_table function_table;
36         u16 out_size = sizeof(function_table);
37         int err;
38
39         if (!hwdev) {
40                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
41                 return -EINVAL;
42         }
43
44         memset(&function_table, 0, sizeof(function_table));
45         function_table.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
46         function_table.func_id = hinic_global_func_id(hwdev);
47         function_table.mtu = 0x3FFF;    /* default, max mtu */
48         function_table.rx_wqe_buf_size = rx_buf_sz;
49
50         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
51                                      HINIC_PORT_CMD_INIT_FUNC,
52                                      &function_table, sizeof(function_table),
53                                      &function_table, &out_size, 0);
54         if (err || function_table.mgmt_msg_head.status || !out_size) {
55                 PMD_DRV_LOG(ERR,
56                         "Failed to init func table, err: %d, status: 0x%x, out size: 0x%x",
57                         err, function_table.mgmt_msg_head.status, out_size);
58                 return -EFAULT;
59         }
60
61         return 0;
62 }
63
64 /**
65  * hinic_get_base_qpn - Get global queue number.
66  *
67  * @param hwdev
68  *   The hardware interface of a nic device.
69  * @param global_qpn
70  *   Global queue number.
71  *
72  * @return
73  *   0 on success.
74  *   negative error value otherwise.
75  */
76 int hinic_get_base_qpn(void *hwdev, u16 *global_qpn)
77 {
78         struct hinic_cmd_qpn cmd_qpn;
79         u16 out_size = sizeof(cmd_qpn);
80         int err;
81
82         if (!hwdev || !global_qpn) {
83                 PMD_DRV_LOG(ERR, "Hwdev or global_qpn is NULL");
84                 return -EINVAL;
85         }
86
87         memset(&cmd_qpn, 0, sizeof(cmd_qpn));
88         cmd_qpn.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
89         cmd_qpn.func_id = hinic_global_func_id(hwdev);
90
91         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
92                                      HINIC_PORT_CMD_GET_GLOBAL_QPN,
93                                      &cmd_qpn, sizeof(cmd_qpn), &cmd_qpn,
94                                      &out_size, 0);
95         if (err || !out_size || cmd_qpn.mgmt_msg_head.status) {
96                 PMD_DRV_LOG(ERR,
97                         "Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x",
98                         err, cmd_qpn.mgmt_msg_head.status, out_size);
99                 return -EINVAL;
100         }
101
102         *global_qpn = cmd_qpn.base_qpn;
103
104         return 0;
105 }
106
107 /**
108  * hinic_set_mac - Init mac_vlan table in NIC.
109  *
110  * @param hwdev
111  *   The hardware interface of a nic device.
112  * @param mac_addr
113  *   MAC address.
114  * @param vlan_id
115  *   Set 0 for mac_vlan table initialization.
116  * @param func_id
117  *   Global function id of NIC.
118  *
119  * @return
120  *   0 on success.
121  *   negative error value otherwise.
122  */
123 int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
124 {
125         struct hinic_port_mac_set mac_info;
126         u16 out_size = sizeof(mac_info);
127         int err;
128
129         if (!hwdev || !mac_addr) {
130                 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
131                 return -EINVAL;
132         }
133
134         memset(&mac_info, 0, sizeof(mac_info));
135         mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
136         mac_info.func_id = func_id;
137         mac_info.vlan_id = vlan_id;
138         memmove(mac_info.mac, mac_addr, ETH_ALEN);
139
140         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
141                                      sizeof(mac_info), &mac_info, &out_size);
142         if (err || !out_size || (mac_info.mgmt_msg_head.status &&
143             mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
144                 PMD_DRV_LOG(ERR, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x",
145                         err, mac_info.mgmt_msg_head.status, out_size);
146                 return -EINVAL;
147         }
148
149         if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
150                 PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore set operation.");
151                 return HINIC_PF_SET_VF_ALREADY;
152         }
153
154         return 0;
155 }
156
157 /**
158  * hinic_del_mac - Uninit mac_vlan table in NIC.
159  *
160  * @param hwdev
161  *   The hardware interface of a nic device.
162  * @param mac_addr
163  *   MAC address.
164  * @param vlan_id
165  *   Set 0 for mac_vlan table initialization.
166  * @param func_id
167  *   Global function id of NIC.
168  *
169  * @return
170  *   0 on success.
171  *   negative error value otherwise.
172  */
173 int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
174 {
175         struct hinic_port_mac_set mac_info;
176         u16 out_size = sizeof(mac_info);
177         int err;
178
179         if (!hwdev || !mac_addr) {
180                 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
181                 return -EINVAL;
182         }
183
184         if (vlan_id >= VLAN_N_VID) {
185                 PMD_DRV_LOG(ERR, "Invalid VLAN number");
186                 return -EINVAL;
187         }
188
189         memset(&mac_info, 0, sizeof(mac_info));
190         mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
191         mac_info.func_id = func_id;
192         mac_info.vlan_id = vlan_id;
193         memmove(mac_info.mac, mac_addr, ETH_ALEN);
194
195         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_DEL_MAC, &mac_info,
196                                      sizeof(mac_info), &mac_info, &out_size);
197         if (err || !out_size || (mac_info.mgmt_msg_head.status &&
198                 mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
199                 PMD_DRV_LOG(ERR, "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x",
200                         err, mac_info.mgmt_msg_head.status, out_size);
201                 return -EINVAL;
202         }
203         if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
204                 PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore delete operation.");
205                 return HINIC_PF_SET_VF_ALREADY;
206         }
207
208         return 0;
209 }
210
211 /**
212  * hinic_get_default_mac - Get default mac address from hardware.
213  *
214  * @param hwdev
215  *   The hardware interface of a nic device.
216  * @param mac_addr
217  *   MAC address.
218  *
219  * @return
220  *   0 on success.
221  *   negative error value otherwise.
222  */
223 int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
224 {
225         struct hinic_port_mac_set mac_info;
226         u16 out_size = sizeof(mac_info);
227         int err;
228
229         if (!hwdev || !mac_addr) {
230                 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
231                 return -EINVAL;
232         }
233
234         memset(&mac_info, 0, sizeof(mac_info));
235         mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
236         mac_info.func_id = hinic_global_func_id(hwdev);
237
238         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MAC,
239                                      &mac_info, sizeof(mac_info),
240                                      &mac_info, &out_size);
241         if (err || !out_size || mac_info.mgmt_msg_head.status) {
242                 PMD_DRV_LOG(ERR, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x",
243                         err, mac_info.mgmt_msg_head.status, out_size);
244                 return -EINVAL;
245         }
246
247         memmove(mac_addr, mac_info.mac, ETH_ALEN);
248
249         return 0;
250 }
251
252 /**
253  * hinic_set_port_mtu -  Set MTU to port.
254  *
255  * @param hwdev
256  *   The hardware interface of a nic device.
257  * @param new_mtu
258  *   MTU size.
259  *
260  * @return
261  *   0 on success.
262  *   negative error value otherwise.
263  */
264 int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
265 {
266         struct hinic_mtu mtu_info;
267         u16 out_size = sizeof(mtu_info);
268         int err;
269
270         if (!hwdev) {
271                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
272                 return -EINVAL;
273         }
274
275         memset(&mtu_info, 0, sizeof(mtu_info));
276         mtu_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
277         mtu_info.func_id = hinic_global_func_id(hwdev);
278         mtu_info.mtu = new_mtu;
279
280         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
281                                      &mtu_info, sizeof(mtu_info),
282                                      &mtu_info, &out_size);
283         if (err || !out_size || mtu_info.mgmt_msg_head.status) {
284                 PMD_DRV_LOG(ERR, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x",
285                         err, mtu_info.mgmt_msg_head.status, out_size);
286                 return -EINVAL;
287         }
288
289         return 0;
290 }
291
292 /**
293  * hinic_add_remove_vlan - Add or remove vlan id to vlan elb table.
294  *
295  * @param hwdev
296  *   The hardware interface of a nic device.
297  * @param vlan_id
298  *   Vlan id.
299  * @param func_id
300  *   Global function id of NIC.
301  * @param add
302  *   Add or remove operation.
303  *
304  * @return
305  *   0 on success.
306  *   negative error value otherwise.
307  */
308 int hinic_add_remove_vlan(void *hwdev, u16 vlan_id, u16 func_id, bool add)
309 {
310         struct hinic_vlan_config vlan_info;
311         u16 out_size = sizeof(vlan_info);
312         u8 cmd;
313         int err;
314
315         if (!hwdev) {
316                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
317                 return -EINVAL;
318         }
319
320         cmd = add ? HINIC_PORT_CMD_ADD_VLAN : HINIC_PORT_CMD_DEL_VLAN;
321
322         memset(&vlan_info, 0, sizeof(vlan_info));
323         vlan_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
324         vlan_info.func_id = func_id;
325         vlan_info.vlan_id = vlan_id;
326
327         err = l2nic_msg_to_mgmt_sync(hwdev, cmd, &vlan_info,
328                                      sizeof(vlan_info), &vlan_info,
329                                      &out_size);
330         if (err || !out_size || vlan_info.mgmt_msg_head.status) {
331                 PMD_DRV_LOG(ERR,
332                         "Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x\n",
333                         add ? "add" : "remove", err,
334                         vlan_info.mgmt_msg_head.status, out_size);
335                 return -EINVAL;
336         }
337
338         return 0;
339 }
340
341 /**
342  * hinic_config_vlan_filter - Enable or Disable vlan filter.
343  *
344  * @param hwdev
345  *   The hardware interface of a nic device.
346  * @param vlan_filter_ctrl
347  *   Enable or Disable.
348  *
349  * @return
350  *   0 on success.
351  *   negative error value otherwise.
352  */
353 int hinic_config_vlan_filter(void *hwdev, u32 vlan_filter_ctrl)
354 {
355         struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev;
356         struct hinic_vlan_filter vlan_filter;
357         u16 out_size = sizeof(vlan_filter);
358         int err;
359
360         if (!hwdev)
361                 return -EINVAL;
362
363         memset(&vlan_filter, 0, sizeof(vlan_filter));
364         vlan_filter.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
365         vlan_filter.func_id = hinic_global_func_id(nic_hwdev);
366         vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl;
367
368         err = l2nic_msg_to_mgmt_sync(nic_hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER,
369                                      &vlan_filter, sizeof(vlan_filter),
370                                      &vlan_filter, &out_size);
371         if (vlan_filter.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) {
372                 err = HINIC_MGMT_CMD_UNSUPPORTED;
373         } else if ((err == HINIC_MBOX_VF_CMD_ERROR) &&
374                 (HINIC_IS_VF(nic_hwdev))) {
375                 err = HINIC_MGMT_CMD_UNSUPPORTED;
376         } else if (err || !out_size || vlan_filter.mgmt_msg_head.status) {
377                 PMD_DRV_LOG(ERR,
378                         "Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x\n",
379                         vlan_filter_ctrl, err,
380                         vlan_filter.mgmt_msg_head.status, out_size);
381                 err = -EINVAL;
382         }
383
384         return err;
385 }
386
387 /**
388  * hinic_set_rx_vlan_offload - Enable or Disable vlan offload.
389  *
390  * @param hwdev
391  *   The hardware interface of a nic device.
392  * @param en
393  *   Enable or Disable.
394  *
395  * @return
396  *   0 on success.
397  *   negative error value otherwise.
398  */
399 int hinic_set_rx_vlan_offload(void *hwdev, u8 en)
400 {
401         struct hinic_vlan_offload vlan_cfg;
402         u16 out_size = sizeof(vlan_cfg);
403         int err;
404
405         if (!hwdev) {
406                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
407                 return -EINVAL;
408         }
409
410         memset(&vlan_cfg, 0, sizeof(vlan_cfg));
411         vlan_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
412         vlan_cfg.func_id = hinic_global_func_id(hwdev);
413         vlan_cfg.vlan_rx_offload = en;
414
415         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD,
416                                         &vlan_cfg, sizeof(vlan_cfg),
417                                         &vlan_cfg, &out_size);
418         if (err || !out_size || vlan_cfg.mgmt_msg_head.status) {
419                 PMD_DRV_LOG(ERR,
420                         "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x\n",
421                         err, vlan_cfg.mgmt_msg_head.status, out_size);
422                 return -EINVAL;
423         }
424
425         return 0;
426 }
427
428 /**
429  * hinic_get_link_status - Get link status from hardware.
430  *
431  * @param hwdev
432  *   The hardware interface of a nic device.
433  * @param link_state
434  *   Link status.
435  *
436  * @return
437  *   0 on success.
438  *   negative error value otherwise.
439  */
440 int hinic_get_link_status(void *hwdev, u8 *link_state)
441 {
442         struct hinic_get_link get_link;
443         u16 out_size = sizeof(get_link);
444         int err;
445
446         if (!hwdev || !link_state) {
447                 PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL");
448                 return -EINVAL;
449         }
450
451         memset(&get_link, 0, sizeof(get_link));
452         get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
453         get_link.func_id = hinic_global_func_id(hwdev);
454
455         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
456                                      &get_link, sizeof(get_link),
457                                      &get_link, &out_size);
458         if (err || !out_size || get_link.mgmt_msg_head.status) {
459                 PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x",
460                         err, get_link.mgmt_msg_head.status, out_size);
461                 return -EINVAL;
462         }
463
464         *link_state = get_link.link_status;
465
466         return 0;
467 }
468
469 /**
470  * hinic_set_vport_enable - Notify firmware that driver is ready or not.
471  *
472  * @param hwdev
473  *   The hardware interface of a nic device.
474  * @param enable
475  *   1: driver is ready; 0: driver is not ok.
476  *
477  * @return
478  *   0 on success.
479  *   negative error value otherwise.
480  */
481 int hinic_set_vport_enable(void *hwdev, bool enable)
482 {
483         struct hinic_vport_state en_state;
484         u16 out_size = sizeof(en_state);
485         int err;
486
487         if (!hwdev) {
488                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
489                 return -EINVAL;
490         }
491
492         memset(&en_state, 0, sizeof(en_state));
493         en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
494         en_state.func_id = hinic_global_func_id(hwdev);
495         en_state.state = (enable ? 1 : 0);
496
497         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
498                                      &en_state, sizeof(en_state),
499                                      &en_state, &out_size);
500         if (err || !out_size || en_state.mgmt_msg_head.status) {
501                 PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x",
502                         err, en_state.mgmt_msg_head.status, out_size);
503                 return -EINVAL;
504         }
505
506         return 0;
507 }
508
509 /**
510  * hinic_set_port_enable - Open MAG to receive packets.
511  *
512  * @param hwdev
513  *   The hardware interface of a nic device.
514  * @param enable
515  *   1: open MAG; 0: close MAG.
516  *
517  * @return
518  *   0 on success.
519  *   negative error value otherwise.
520  */
521 int hinic_set_port_enable(void *hwdev, bool enable)
522 {
523         struct hinic_port_state en_state;
524         u16 out_size = sizeof(en_state);
525         int err;
526
527         if (!hwdev) {
528                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
529                 return -EINVAL;
530         }
531
532         if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
533                 return 0;
534
535         memset(&en_state, 0, sizeof(en_state));
536         en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
537         en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE);
538
539         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
540                                      &en_state, sizeof(en_state),
541                                      &en_state, &out_size);
542         if (err || !out_size || en_state.mgmt_msg_head.status) {
543                 PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x",
544                         err, en_state.mgmt_msg_head.status, out_size);
545                 return -EINVAL;
546         }
547
548         return 0;
549 }
550
551 int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
552 {
553         struct hinic_port_info port_msg;
554         u16 out_size = sizeof(port_msg);
555         int err;
556
557         if (!hwdev || !port_info) {
558                 PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL");
559                 return -EINVAL;
560         }
561
562         memset(&port_msg, 0, sizeof(port_msg));
563         port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
564         port_msg.func_id = hinic_global_func_id(hwdev);
565
566         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
567                                      &port_msg, sizeof(port_msg),
568                                      &port_msg, &out_size);
569         if (err || !out_size || port_msg.mgmt_msg_head.status) {
570                 PMD_DRV_LOG(ERR,
571                         "Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
572                         err, port_msg.mgmt_msg_head.status, out_size);
573                 return err;
574         }
575
576         port_info->autoneg_cap = port_msg.autoneg_cap;
577         port_info->autoneg_state = port_msg.autoneg_state;
578         port_info->duplex = port_msg.duplex;
579         port_info->port_type = port_msg.port_type;
580         port_info->speed = port_msg.speed;
581
582         return 0;
583 }
584
585 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
586 {
587         struct hinic_pause_config pause_info;
588         u16 out_size = sizeof(pause_info);
589         int err;
590
591         if (!hwdev) {
592                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
593                 return -EINVAL;
594         }
595
596         memset(&pause_info, 0, sizeof(pause_info));
597         pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
598         pause_info.func_id = hinic_global_func_id(hwdev);
599         pause_info.auto_neg = nic_pause.auto_neg;
600         pause_info.rx_pause = nic_pause.rx_pause;
601         pause_info.tx_pause = nic_pause.tx_pause;
602
603         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
604                                      &pause_info, sizeof(pause_info),
605                                      &pause_info, &out_size);
606         if (err || !out_size || pause_info.mgmt_msg_head.status) {
607                 PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x",
608                         err, pause_info.mgmt_msg_head.status, out_size);
609                 return -EINVAL;
610         }
611
612         return 0;
613 }
614
615 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
616                       u8 *pgid, u8 *up_bw, u8 *prio)
617 {
618         struct hinic_up_ets_cfg ets;
619         u16 out_size = sizeof(ets);
620         u16 up_bw_t = 0;
621         u8 pg_bw_t = 0;
622         int i, err;
623
624         if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) {
625                 PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL");
626                 return -EINVAL;
627         }
628
629         for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
630                 up_bw_t += *(up_bw + i);
631                 pg_bw_t += *(pg_bw + i);
632
633                 if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
634                         PMD_DRV_LOG(ERR,
635                                 "Invalid up %d mapping tc: %d", i,
636                                 *(up_tc + i));
637                         return -EINVAL;
638                 }
639         }
640
641         if (pg_bw_t != 100 || (up_bw_t % 100) != 0) {
642                 PMD_DRV_LOG(ERR,
643                         "Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t);
644                 return -EINVAL;
645         }
646
647         memset(&ets, 0, sizeof(ets));
648         ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
649         ets.port_id = 0;        /* reserved */
650         memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX);
651         memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX);
652         memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX);
653         memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX);
654         memcpy(ets.prio, prio, HINIC_DCB_UP_MAX);
655
656         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS,
657                                      &ets, sizeof(ets), &ets, &out_size);
658         if (err || ets.mgmt_msg_head.status || !out_size) {
659                 PMD_DRV_LOG(ERR,
660                         "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x",
661                         err, ets.mgmt_msg_head.status, out_size);
662                 return -EINVAL;
663         }
664
665         return 0;
666 }
667
668 int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats)
669 {
670         struct hinic_port_stats_info vport_stats_cmd;
671         struct hinic_cmd_vport_stats vport_stats_rsp;
672         u16 out_size = sizeof(vport_stats_rsp);
673         int err;
674
675         if (!hwdev || !stats) {
676                 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
677                 return -EINVAL;
678         }
679
680         memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp));
681         memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd));
682         vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
683         vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
684         vport_stats_cmd.func_id = hinic_global_func_id(hwdev);
685         vport_stats_cmd.stats_size = sizeof(vport_stats_rsp);
686
687         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
688                                      &vport_stats_cmd, sizeof(vport_stats_cmd),
689                                      &vport_stats_rsp, &out_size);
690         if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) {
691                 PMD_DRV_LOG(ERR,
692                         "Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x",
693                         err, vport_stats_rsp.mgmt_msg_head.status, out_size);
694                 return -EFAULT;
695         }
696
697         memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats));
698
699         return 0;
700 }
701
702 int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats)
703 {
704         struct hinic_port_stats_info port_stats_cmd;
705         struct hinic_port_stats port_stats_rsp;
706         u16 out_size = sizeof(port_stats_rsp);
707         int err;
708
709         if (!hwdev || !stats) {
710                 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
711                 return -EINVAL;
712         }
713
714         memset(&port_stats_rsp, 0, sizeof(port_stats_rsp));
715         memset(&port_stats_cmd, 0, sizeof(port_stats_cmd));
716         port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
717         port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
718         port_stats_cmd.stats_size = sizeof(port_stats_rsp);
719
720         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
721                                      &port_stats_cmd, sizeof(port_stats_cmd),
722                                      &port_stats_rsp, &out_size);
723         if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) {
724                 PMD_DRV_LOG(ERR,
725                         "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x",
726                         err, port_stats_rsp.mgmt_msg_head.status, out_size);
727                 return -EFAULT;
728         }
729
730         memcpy(stats, &port_stats_rsp.stats, sizeof(*stats));
731
732         return 0;
733 }
734
735 int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type)
736 {
737         struct nic_rss_context_tbl *ctx_tbl;
738         struct hinic_cmd_buf *cmd_buf;
739         u32 ctx = 0;
740         u64 out_param;
741         int err;
742
743         if (!hwdev) {
744                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
745                 return -EINVAL;
746         }
747
748         cmd_buf = hinic_alloc_cmd_buf(hwdev);
749         if (!cmd_buf) {
750                 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
751                 return -ENOMEM;
752         }
753
754         ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
755                 HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
756                 HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
757                 HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
758                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
759                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
760                 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
761                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
762                 HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
763
764         cmd_buf->size = sizeof(struct nic_rss_context_tbl);
765
766         ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf;
767         ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
768         ctx_tbl->offset = 0;
769         ctx_tbl->size = sizeof(u32);
770         ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
771         ctx_tbl->rsvd = 0;
772         ctx_tbl->ctx = cpu_to_be32(ctx);
773
774         /* cfg the rss context table by command queue */
775         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
776                                      HINIC_MOD_L2NIC,
777                                      HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
778                                      cmd_buf, &out_param, 0);
779
780         hinic_free_cmd_buf(hwdev, cmd_buf);
781
782         if (err || out_param != 0) {
783                 PMD_DRV_LOG(ERR, "Failed to set rss context table");
784                 return -EFAULT;
785         }
786
787         return 0;
788 }
789
790 int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type)
791 {
792         struct hinic_rss_context_table ctx_tbl;
793         u16 out_size = sizeof(ctx_tbl);
794         int err;
795
796         if (!hwdev || !rss_type) {
797                 PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL");
798                 return -EINVAL;
799         }
800
801         ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
802         ctx_tbl.func_id = hinic_global_func_id(hwdev);
803         ctx_tbl.template_id = (u8)tmpl_idx;
804
805         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
806                                      &ctx_tbl, sizeof(ctx_tbl),
807                                      &ctx_tbl, &out_size);
808         if (err || !out_size || ctx_tbl.mgmt_msg_head.status) {
809                 PMD_DRV_LOG(ERR,
810                         "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x",
811                         err, ctx_tbl.mgmt_msg_head.status, out_size);
812                 return -EINVAL;
813         }
814
815         rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
816         rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
817         rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
818         rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
819         rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
820         rss_type->tcp_ipv6_ext =
821                         HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT);
822         rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
823         rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
824
825         return 0;
826 }
827
828 int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
829 {
830         struct hinic_rss_template_key temp_key;
831         u16 out_size = sizeof(temp_key);
832         int err;
833
834         if (!hwdev || !temp) {
835                 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
836                 return -EINVAL;
837         }
838
839         memset(&temp_key, 0, sizeof(temp_key));
840         temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
841         temp_key.func_id = hinic_global_func_id(hwdev);
842         temp_key.template_id = (u8)tmpl_idx;
843         memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
844
845         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
846                                      &temp_key, sizeof(temp_key),
847                                      &temp_key, &out_size);
848         if (err || !out_size || temp_key.mgmt_msg_head.status) {
849                 PMD_DRV_LOG(ERR,
850                         "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x",
851                         err, temp_key.mgmt_msg_head.status, out_size);
852                 return -EINVAL;
853         }
854
855         return 0;
856 }
857
858 int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
859 {
860         struct hinic_rss_template_key temp_key;
861         u16 out_size = sizeof(temp_key);
862         int err;
863
864         if (!hwdev || !temp) {
865                 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
866                 return -EINVAL;
867         }
868
869         memset(&temp_key, 0, sizeof(temp_key));
870         temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
871         temp_key.func_id = hinic_global_func_id(hwdev);
872         temp_key.template_id = (u8)tmpl_idx;
873
874         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
875                                      &temp_key, sizeof(temp_key),
876                                      &temp_key, &out_size);
877         if (err || !out_size || temp_key.mgmt_msg_head.status) {
878                 PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x",
879                         err, temp_key.mgmt_msg_head.status, out_size);
880                 return -EINVAL;
881         }
882
883         memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
884
885         return 0;
886 }
887
888 /**
889  * hinic_rss_set_hash_engine - Init rss hash function.
890  *
891  * @param hwdev
892  *   The hardware interface of a nic device.
893  * @param tmpl_idx
894  *   Index of rss template from NIC.
895  * @param type
896  *   Hash function, such as Toeplitz or XOR.
897  *
898  * @return
899  *   0 on success.
900  *   negative error value otherwise.
901  */
902 int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
903 {
904         struct hinic_rss_engine_type hash_type;
905         u16 out_size = sizeof(hash_type);
906         int err;
907
908         if (!hwdev) {
909                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
910                 return -EINVAL;
911         }
912
913         memset(&hash_type, 0, sizeof(hash_type));
914         hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
915         hash_type.func_id = hinic_global_func_id(hwdev);
916         hash_type.hash_engine = type;
917         hash_type.template_id = tmpl_idx;
918
919         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
920                                      &hash_type, sizeof(hash_type),
921                                      &hash_type, &out_size);
922         if (err || !out_size || hash_type.mgmt_msg_head.status) {
923                 PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x",
924                         err, hash_type.mgmt_msg_head.status, out_size);
925                 return -EINVAL;
926         }
927
928         return 0;
929 }
930
931 int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
932 {
933         struct nic_rss_indirect_tbl *indir_tbl;
934         struct hinic_cmd_buf *cmd_buf;
935         int i;
936         u32 *temp;
937         u32 indir_size;
938         u64 out_param;
939         int err;
940
941         if (!hwdev || !indir_table) {
942                 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
943                 return -EINVAL;
944         }
945
946         cmd_buf = hinic_alloc_cmd_buf(hwdev);
947         if (!cmd_buf) {
948                 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
949                 return -ENOMEM;
950         }
951
952         cmd_buf->size = sizeof(struct nic_rss_indirect_tbl);
953         indir_tbl = cmd_buf->buf;
954         indir_tbl->group_index = cpu_to_be32(tmpl_idx);
955
956         for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
957                 indir_tbl->entry[i] = (u8)(*(indir_table + i));
958
959                 if (0x3 == (i & 0x3)) {
960                         temp = (u32 *)&indir_tbl->entry[i - 3];
961                         *temp = cpu_to_be32(*temp);
962                 }
963         }
964
965         /* configure the rss indirect table by command queue */
966         indir_size = HINIC_RSS_INDIR_SIZE / 2;
967         indir_tbl->offset = 0;
968         indir_tbl->size = cpu_to_be32(indir_size);
969
970         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
971                                      HINIC_MOD_L2NIC,
972                                      HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
973                                      cmd_buf, &out_param, 0);
974         if (err || out_param != 0) {
975                 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
976                 err = -EFAULT;
977                 goto free_buf;
978         }
979
980         indir_tbl->offset = cpu_to_be32(indir_size);
981         indir_tbl->size = cpu_to_be32(indir_size);
982         memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size);
983
984         err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
985                                      HINIC_MOD_L2NIC,
986                                      HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
987                                      cmd_buf, &out_param, 0);
988         if (err || out_param != 0) {
989                 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
990                 err = -EFAULT;
991         }
992
993 free_buf:
994         hinic_free_cmd_buf(hwdev, cmd_buf);
995
996         return err;
997 }
998
999 int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
1000 {
1001         struct hinic_rss_indir_table rss_cfg;
1002         u16 out_size = sizeof(rss_cfg);
1003         int err = 0, i;
1004
1005         if (!hwdev || !indir_table) {
1006                 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
1007                 return -EINVAL;
1008         }
1009
1010         memset(&rss_cfg, 0, sizeof(rss_cfg));
1011         rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1012         rss_cfg.func_id = hinic_global_func_id(hwdev);
1013         rss_cfg.template_id = (u8)tmpl_idx;
1014
1015         err = l2nic_msg_to_mgmt_sync(hwdev,
1016                                      HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
1017                                      &rss_cfg, sizeof(rss_cfg), &rss_cfg,
1018                                      &out_size);
1019         if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
1020                 PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x",
1021                         err, rss_cfg.mgmt_msg_head.status, out_size);
1022                 return -EINVAL;
1023         }
1024
1025         hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
1026         for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
1027                 indir_table[i] = rss_cfg.indir[i];
1028
1029         return 0;
1030 }
1031
1032 int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc)
1033 {
1034         struct hinic_rss_config rss_cfg;
1035         u16 out_size = sizeof(rss_cfg);
1036         int err;
1037
1038         /* micro code required: number of TC should be power of 2 */
1039         if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) {
1040                 PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2",
1041                         tc_num);
1042                 return -EINVAL;
1043         }
1044
1045         memset(&rss_cfg, 0, sizeof(rss_cfg));
1046         rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1047         rss_cfg.func_id = hinic_global_func_id(hwdev);
1048         rss_cfg.rss_en = rss_en;
1049         rss_cfg.template_id = tmpl_idx;
1050         rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
1051
1052         memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX);
1053
1054         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG,
1055                                      &rss_cfg, sizeof(rss_cfg), &rss_cfg,
1056                                      &out_size);
1057         if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
1058                 PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x",
1059                         err, rss_cfg.mgmt_msg_head.status, out_size);
1060                 return -EINVAL;
1061         }
1062
1063         return 0;
1064 }
1065
1066 /**
1067  * hinic_rss_template_alloc - Get rss template id from the chip,
1068  * all functions share 96 templates.
1069  *
1070  * @param hwdev
1071  *   The hardware interface of a nic device.
1072  * @param tmpl_idx
1073  *   Index of rss template from chip.
1074  *
1075  * @return
1076  *   0 on success.
1077  *   negative error value otherwise.
1078  */
1079 int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
1080 {
1081         struct hinic_rss_template_mgmt template_mgmt;
1082         u16 out_size = sizeof(template_mgmt);
1083         int err;
1084
1085         if (!hwdev || !tmpl_idx) {
1086                 PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL");
1087                 return -EINVAL;
1088         }
1089
1090         memset(&template_mgmt, 0, sizeof(template_mgmt));
1091         template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1092         template_mgmt.func_id = hinic_global_func_id(hwdev);
1093         template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
1094
1095         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
1096                                      &template_mgmt, sizeof(template_mgmt),
1097                                      &template_mgmt, &out_size);
1098         if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
1099                 PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x",
1100                         err, template_mgmt.mgmt_msg_head.status, out_size);
1101                 return -EINVAL;
1102         }
1103
1104         *tmpl_idx = template_mgmt.template_id;
1105
1106         return 0;
1107 }
1108
1109 /**
1110  * hinic_rss_template_free - Free rss template id to the chip.
1111  *
1112  * @param hwdev
1113  *   The hardware interface of a nic device.
1114  * @param tmpl_idx
1115  *   Index of rss template from chip.
1116  *
1117  * @return
1118  *   0 on success.
1119  *   negative error value otherwise.
1120  */
1121 int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
1122 {
1123         struct hinic_rss_template_mgmt template_mgmt;
1124         u16 out_size = sizeof(template_mgmt);
1125         int err;
1126
1127         if (!hwdev) {
1128                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1129                 return -EINVAL;
1130         }
1131
1132         memset(&template_mgmt, 0, sizeof(template_mgmt));
1133         template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1134         template_mgmt.func_id = hinic_global_func_id(hwdev);
1135         template_mgmt.template_id = tmpl_idx;
1136         template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
1137
1138         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
1139                                      &template_mgmt, sizeof(template_mgmt),
1140                                      &template_mgmt, &out_size);
1141         if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
1142                 PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x",
1143                         err, template_mgmt.mgmt_msg_head.status, out_size);
1144                 return -EINVAL;
1145         }
1146
1147         return 0;
1148 }
1149
1150 /**
1151  * hinic_set_rx_vhd_mode - Change rx buffer size after initialization.
1152  *
1153  * @param hwdev
1154  *   The hardware interface of a nic device.
1155  * @param vhd_mode
1156  *   Not needed.
1157  * @param rx_buf_sz
1158  *   receive buffer size.
1159  *
1160  * @return
1161  *   0 on success.
1162  *   negative error value otherwise.
1163  */
1164 int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
1165 {
1166         struct hinic_set_vhd_mode vhd_mode_cfg;
1167         u16 out_size = sizeof(vhd_mode_cfg);
1168         int err;
1169
1170         if (!hwdev) {
1171                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1172                 return -EINVAL;
1173         }
1174
1175         memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg));
1176
1177         vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1178         vhd_mode_cfg.func_id = hinic_global_func_id(hwdev);
1179         vhd_mode_cfg.vhd_type = vhd_mode;
1180         vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz;
1181
1182         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG,
1183                                      &vhd_mode_cfg, sizeof(vhd_mode_cfg),
1184                                      &vhd_mode_cfg, &out_size);
1185         if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) {
1186                 PMD_DRV_LOG(ERR,
1187                         "Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
1188                         err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
1189
1190                 return -EIO;
1191         }
1192
1193         return 0;
1194 }
1195
1196 int hinic_set_rx_mode(void *hwdev, u32 enable)
1197 {
1198         struct hinic_rx_mode_config rx_mode_cfg;
1199         u16 out_size = sizeof(rx_mode_cfg);
1200         int err;
1201
1202         if (!hwdev) {
1203                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1204                 return -EINVAL;
1205         }
1206
1207         memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
1208         rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1209         rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
1210         rx_mode_cfg.rx_mode = enable;
1211
1212         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
1213                                      &rx_mode_cfg, sizeof(rx_mode_cfg),
1214                                      &rx_mode_cfg, &out_size);
1215         if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) {
1216                 PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x",
1217                         err, rx_mode_cfg.mgmt_msg_head.status, out_size);
1218                 return -EINVAL;
1219         }
1220
1221         return 0;
1222 }
1223
1224 int hinic_set_rx_csum_offload(void *hwdev, u32 en)
1225 {
1226         struct hinic_checksum_offload rx_csum_cfg;
1227         u16 out_size = sizeof(rx_csum_cfg);
1228         int err;
1229
1230         if (!hwdev) {
1231                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1232                 return -EINVAL;
1233         }
1234
1235         memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg));
1236         rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1237         rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
1238         rx_csum_cfg.rx_csum_offload = en;
1239
1240         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
1241                                      &rx_csum_cfg, sizeof(rx_csum_cfg),
1242                                      &rx_csum_cfg, &out_size);
1243         if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) {
1244                 PMD_DRV_LOG(ERR,
1245                         "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x",
1246                         err, rx_csum_cfg.mgmt_msg_head.status, out_size);
1247                 return -EINVAL;
1248         }
1249
1250         return 0;
1251 }
1252
1253 int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num)
1254 {
1255         struct hinic_lro_config lro_cfg;
1256         u16 out_size = sizeof(lro_cfg);
1257         int err;
1258
1259         if (!hwdev) {
1260                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1261                 return -EINVAL;
1262         }
1263
1264         memset(&lro_cfg, 0, sizeof(lro_cfg));
1265         lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1266         lro_cfg.func_id = hinic_global_func_id(hwdev);
1267         lro_cfg.lro_ipv4_en = ipv4_en;
1268         lro_cfg.lro_ipv6_en = ipv6_en;
1269         lro_cfg.lro_max_wqe_num = max_wqe_num;
1270
1271         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO,
1272                                      &lro_cfg, sizeof(lro_cfg), &lro_cfg,
1273                                      &out_size);
1274         if (err || !out_size || lro_cfg.mgmt_msg_head.status) {
1275                 PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x",
1276                         err, lro_cfg.mgmt_msg_head.status, out_size);
1277                 return -EINVAL;
1278         }
1279
1280         return 0;
1281 }
1282
1283 int hinic_set_anti_attack(void *hwdev, bool enable)
1284 {
1285         struct hinic_port_anti_attack_rate rate;
1286         u16 out_size = sizeof(rate);
1287         int err;
1288
1289         if (!hwdev) {
1290                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1291                 return -EINVAL;
1292         }
1293
1294         memset(&rate, 0, sizeof(rate));
1295         rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1296         rate.func_id = hinic_global_func_id(hwdev);
1297         rate.enable = enable;
1298         rate.cir = ANTI_ATTACK_DEFAULT_CIR;
1299         rate.xir = ANTI_ATTACK_DEFAULT_XIR;
1300         rate.cbs = ANTI_ATTACK_DEFAULT_CBS;
1301         rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
1302
1303         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
1304                                      &rate, sizeof(rate), &rate,
1305                                      &out_size);
1306         if (err || !out_size || rate.mgmt_msg_head.status) {
1307                 PMD_DRV_LOG(ERR, "can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
1308                         (enable ? "enable" : "disable"), err,
1309                         rate.mgmt_msg_head.status, out_size);
1310                 return -EINVAL;
1311         }
1312
1313         return 0;
1314 }
1315
1316 /* Set autoneg status and restart port link status */
1317 int hinic_reset_port_link_cfg(void *hwdev)
1318 {
1319         struct hinic_reset_link_cfg reset_cfg;
1320         u16 out_size = sizeof(reset_cfg);
1321         int err;
1322
1323         memset(&reset_cfg, 0, sizeof(reset_cfg));
1324         reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1325         reset_cfg.func_id = hinic_global_func_id(hwdev);
1326
1327         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
1328                                      &reset_cfg, sizeof(reset_cfg),
1329                                      &reset_cfg, &out_size);
1330         if (err || !out_size || reset_cfg.mgmt_msg_head.status) {
1331                 PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x",
1332                         err, reset_cfg.mgmt_msg_head.status, out_size);
1333                 return -EFAULT;
1334         }
1335
1336         return 0;
1337 }
1338
1339 /**
1340  * hinic_vf_func_init - Register VF to PF.
1341  *
1342  * @param hwdev
1343  *   The hardware interface of a nic device.
1344  *
1345  * @return
1346  *   0 on success.
1347  *   negative error value otherwise.
1348  */
1349 int hinic_vf_func_init(struct hinic_hwdev *hwdev)
1350 {
1351         int err, state = 0;
1352
1353         if (!HINIC_IS_VF(hwdev))
1354                 return 0;
1355
1356         err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1357                         HINIC_PORT_CMD_VF_REGISTER, &state, sizeof(state),
1358                         NULL, NULL, 0);
1359         if (err) {
1360                 PMD_DRV_LOG(ERR, "Fail to register vf");
1361                 return err;
1362         }
1363
1364         return 0;
1365 }
1366
1367 /**
1368  * hinic_vf_func_free - Unregister VF from PF.
1369  *
1370  * @param hwdev
1371  *   The hardware interface of a nic device.
1372  */
1373 void hinic_vf_func_free(struct hinic_hwdev *hwdev)
1374 {
1375         int err;
1376
1377         if (hinic_func_type(hwdev) != TYPE_VF)
1378                 return;
1379
1380         err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
1381                                 HINIC_PORT_CMD_VF_UNREGISTER, &err, sizeof(err),
1382                                 NULL, NULL, 0);
1383         if (err)
1384                 PMD_DRV_LOG(ERR, "Fail to unregister VF, err: %d", err);
1385 }
1386
1387 int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
1388 {
1389         struct hinic_fast_recycled_mode fast_recycled_mode;
1390         u16 out_size = sizeof(fast_recycled_mode);
1391         int err;
1392
1393         if (!hwdev) {
1394                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1395                 return -EINVAL;
1396         }
1397
1398         memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode));
1399         fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1400         fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
1401         fast_recycled_mode.fast_recycled_mode = mode;
1402
1403         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1404                                      HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET,
1405                                      &fast_recycled_mode,
1406                                      sizeof(fast_recycled_mode),
1407                                      &fast_recycled_mode, &out_size, 0);
1408         if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
1409                 PMD_DRV_LOG(ERR,
1410                         "Failed to set recycle mode, ret = %d",
1411                         fast_recycled_mode.mgmt_msg_head.status);
1412                 return -EFAULT;
1413         }
1414
1415         return 0;
1416 }
1417
1418 int hinic_clear_vport_stats(struct hinic_hwdev *hwdev)
1419 {
1420         struct hinic_clear_vport_stats clear_vport_stats;
1421         u16 out_size = sizeof(clear_vport_stats);
1422         int err;
1423
1424         if (!hwdev) {
1425                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1426                 return -EINVAL;
1427         }
1428
1429         memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
1430         clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1431         clear_vport_stats.func_id = hinic_global_func_id(hwdev);
1432
1433         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT,
1434                                      &clear_vport_stats,
1435                                      sizeof(clear_vport_stats),
1436                                      &clear_vport_stats, &out_size);
1437         if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) {
1438                 PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x",
1439                         err, clear_vport_stats.mgmt_msg_head.status, out_size);
1440                 return -EINVAL;
1441         }
1442
1443         return 0;
1444 }
1445
1446 int hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev)
1447 {
1448         struct hinic_clear_port_stats clear_phy_port_stats;
1449         u16 out_size = sizeof(clear_phy_port_stats);
1450         int err;
1451
1452         if (!hwdev) {
1453                 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1454                 return -EINVAL;
1455         }
1456
1457         memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats));
1458         clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1459         clear_phy_port_stats.func_id = hinic_global_func_id(hwdev);
1460
1461         err = l2nic_msg_to_mgmt_sync(hwdev,
1462                                      HINIC_PORT_CMD_CLEAR_PORT_STATISTICS,
1463                                      &clear_phy_port_stats,
1464                                      sizeof(clear_phy_port_stats),
1465                                      &clear_phy_port_stats, &out_size);
1466         if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) {
1467                 PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x",
1468                         err, clear_phy_port_stats.mgmt_msg_head.status,
1469                         out_size);
1470                 return -EINVAL;
1471         }
1472
1473         return 0;
1474 }
1475
1476 int hinic_set_link_status_follow(void *hwdev,
1477                                  enum hinic_link_follow_status status)
1478 {
1479         struct hinic_set_link_follow follow;
1480         u16 out_size = sizeof(follow);
1481         int err;
1482
1483         if (!hwdev)
1484                 return -EINVAL;
1485
1486         if (HINIC_IS_VF((struct hinic_hwdev *)hwdev))
1487                 return 0;
1488
1489         if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) {
1490                 PMD_DRV_LOG(ERR,
1491                         "Invalid link follow status: %d", status);
1492                 return -EINVAL;
1493         }
1494
1495         memset(&follow, 0, sizeof(follow));
1496         follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1497         follow.func_id = hinic_global_func_id(hwdev);
1498         follow.follow_status = status;
1499
1500         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
1501                                      &follow, sizeof(follow),
1502                                      &follow, &out_size);
1503         if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
1504              follow.mgmt_msg_head.status) || err || !out_size) {
1505                 PMD_DRV_LOG(ERR,
1506                         "Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x",
1507                         err, follow.mgmt_msg_head.status, out_size);
1508                 return -EFAULT;
1509         }
1510
1511         return follow.mgmt_msg_head.status;
1512 }
1513
1514 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
1515 {
1516         struct hinic_link_mode_cmd link_mode;
1517         u16 out_size = sizeof(link_mode);
1518         int err;
1519
1520         if (!hwdev || !supported || !advertised)
1521                 return -EINVAL;
1522
1523         memset(&link_mode, 0, sizeof(link_mode));
1524         link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1525         link_mode.func_id = hinic_global_func_id(hwdev);
1526
1527         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
1528                                      &link_mode, sizeof(link_mode),
1529                                      &link_mode, &out_size);
1530         if (err || !out_size || link_mode.mgmt_msg_head.status) {
1531                 PMD_DRV_LOG(ERR,
1532                         "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x",
1533                         err, link_mode.mgmt_msg_head.status, out_size);
1534                 return -EINVAL;
1535         }
1536
1537         *supported = link_mode.supported;
1538         *advertised = link_mode.advertised;
1539
1540         return 0;
1541 }
1542
1543 /**
1544  * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport
1545  * fake failed when device start.
1546  *
1547  * @param hwdev
1548  *   The hardware interface of a nic device.
1549  *
1550  * @return
1551  *   0 on success.
1552  *   negative error value otherwise.
1553  */
1554 int hinic_flush_qp_res(void *hwdev)
1555 {
1556         struct hinic_clear_qp_resource qp_res;
1557         u16 out_size = sizeof(qp_res);
1558         int err;
1559
1560         memset(&qp_res, 0, sizeof(qp_res));
1561         qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1562         qp_res.func_id = hinic_global_func_id(hwdev);
1563
1564         err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES,
1565                                      &qp_res, sizeof(qp_res), &qp_res,
1566                                      &out_size);
1567         if (err || !out_size || qp_res.mgmt_msg_head.status) {
1568                 PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x",
1569                         err, qp_res.mgmt_msg_head.status, out_size);
1570                 return -EINVAL;
1571         }
1572
1573         return 0;
1574 }
1575
1576 /**
1577  * hinic_vf_get_default_cos - Get default cos of VF.
1578  *
1579  * @param hwdev
1580  *   The hardware interface of a nic device.
1581  * @param cos_id
1582  *   Cos value.
1583  *
1584  * @return
1585  *   0 on success.
1586  *   negative error value otherwise.
1587  */
1588 int hinic_vf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id)
1589 {
1590         struct hinic_vf_default_cos vf_cos;
1591         u16 out_size = sizeof(vf_cos);
1592         int err;
1593
1594         memset(&vf_cos, 0, sizeof(vf_cos));
1595         vf_cos.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1596
1597         err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
1598                                      HINIC_PORT_CMD_GET_VF_COS, &vf_cos,
1599                                      sizeof(vf_cos), &vf_cos,
1600                                      &out_size, 0);
1601         if (err || !out_size || vf_cos.mgmt_msg_head.status) {
1602                 PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d, status: 0x%x, out size: 0x%x",
1603                         err, vf_cos.mgmt_msg_head.status, out_size);
1604                 return -EFAULT;
1605         }
1606         *cos_id = vf_cos.state.default_cos;
1607
1608         return 0;
1609 }