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