1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2017 Huawei Technologies Co., Ltd
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"
14 #define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, \
15 in_size, buf_out, out_size) \
16 hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, cmd, \
20 int hinic_init_function_table(void *hwdev, u16 rx_buf_sz)
22 struct hinic_function_table function_table;
23 u16 out_size = sizeof(function_table);
27 PMD_DRV_LOG(ERR, "Hwdev is NULL");
31 memset(&function_table, 0, sizeof(function_table));
32 function_table.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
33 function_table.func_id = hinic_global_func_id(hwdev);
34 function_table.mtu = 0x3FFF; /* default, max mtu */
35 function_table.rx_wqe_buf_size = rx_buf_sz;
37 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
38 HINIC_PORT_CMD_INIT_FUNC,
39 &function_table, sizeof(function_table),
40 &function_table, &out_size, 0);
41 if (err || function_table.mgmt_msg_head.status || !out_size) {
43 "Failed to init func table, ret = %d",
44 function_table.mgmt_msg_head.status);
52 * hinic_get_base_qpn - get global number of queue
53 * @hwdev: the hardware interface of a nic device
54 * @global_qpn: vat page size
57 * negative error value otherwise.
59 int hinic_get_base_qpn(void *hwdev, u16 *global_qpn)
61 struct hinic_cmd_qpn cmd_qpn;
62 u16 out_size = sizeof(cmd_qpn);
65 if (!hwdev || !global_qpn) {
66 PMD_DRV_LOG(ERR, "Hwdev or global_qpn is NULL");
70 memset(&cmd_qpn, 0, sizeof(cmd_qpn));
71 cmd_qpn.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
72 cmd_qpn.func_id = hinic_global_func_id(hwdev);
74 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC,
75 HINIC_PORT_CMD_GET_GLOBAL_QPN,
76 &cmd_qpn, sizeof(cmd_qpn), &cmd_qpn,
78 if (err || !out_size || cmd_qpn.mgmt_msg_head.status) {
80 "Failed to get base qpn, status(%d)",
81 cmd_qpn.mgmt_msg_head.status);
85 *global_qpn = cmd_qpn.base_qpn;
91 * hinic_set_mac - Init mac_vlan table in NIC.
92 * @hwdev: the hardware interface of a nic device
93 * @mac_addr: mac address
94 * @vlan_id: set 0 for mac_vlan table initialization
95 * @func_id: global function id of NIC
97 * 0 on success and stats is filled,
98 * negative error value otherwise.
100 int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id)
102 struct hinic_port_mac_set mac_info;
103 u16 out_size = sizeof(mac_info);
106 if (!hwdev || !mac_addr) {
107 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
111 memset(&mac_info, 0, sizeof(mac_info));
112 mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
113 mac_info.func_id = func_id;
114 mac_info.vlan_id = vlan_id;
115 memmove(mac_info.mac, mac_addr, ETH_ALEN);
117 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
118 sizeof(mac_info), &mac_info, &out_size);
119 if (err || !out_size || (mac_info.mgmt_msg_head.status &&
120 mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
121 PMD_DRV_LOG(ERR, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x",
122 err, mac_info.mgmt_msg_head.status, out_size);
125 if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
126 PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore set operation.");
127 return HINIC_PF_SET_VF_ALREADY;
134 * hinic_del_mac - Uninit mac_vlan table in NIC.
135 * @hwdev: the hardware interface of a nic device
136 * @mac_addr: mac address
137 * @vlan_id: set 0 for mac_vlan table initialization
138 * @func_id: global function id of NIC
140 * 0 on success and stats is filled,
141 * negative error value otherwise.
143 int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id,
146 struct hinic_port_mac_set mac_info;
147 u16 out_size = sizeof(mac_info);
150 if (!hwdev || !mac_addr) {
151 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
155 if (vlan_id >= VLAN_N_VID) {
156 PMD_DRV_LOG(ERR, "Invalid VLAN number");
160 memset(&mac_info, 0, sizeof(mac_info));
161 mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
162 mac_info.func_id = func_id;
163 mac_info.vlan_id = vlan_id;
164 memmove(mac_info.mac, mac_addr, ETH_ALEN);
166 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_DEL_MAC, &mac_info,
167 sizeof(mac_info), &mac_info, &out_size);
168 if (err || !out_size || (mac_info.mgmt_msg_head.status &&
169 mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) {
170 PMD_DRV_LOG(ERR, "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x",
171 err, mac_info.mgmt_msg_head.status, out_size);
174 if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) {
175 PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore delete operation.");
176 return HINIC_PF_SET_VF_ALREADY;
182 int hinic_get_default_mac(void *hwdev, u8 *mac_addr)
184 struct hinic_port_mac_set mac_info;
185 u16 out_size = sizeof(mac_info);
188 if (!hwdev || !mac_addr) {
189 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL");
193 memset(&mac_info, 0, sizeof(mac_info));
194 mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
195 mac_info.func_id = hinic_global_func_id(hwdev);
197 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MAC,
198 &mac_info, sizeof(mac_info),
199 &mac_info, &out_size);
200 if (err || !out_size || mac_info.mgmt_msg_head.status) {
201 PMD_DRV_LOG(ERR, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x",
202 err, mac_info.mgmt_msg_head.status, out_size);
206 memmove(mac_addr, mac_info.mac, ETH_ALEN);
211 int hinic_set_port_mtu(void *hwdev, u32 new_mtu)
213 struct hinic_mtu mtu_info;
214 u16 out_size = sizeof(mtu_info);
218 PMD_DRV_LOG(ERR, "Hwdev is NULL");
222 memset(&mtu_info, 0, sizeof(mtu_info));
223 mtu_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
224 mtu_info.func_id = hinic_global_func_id(hwdev);
225 mtu_info.mtu = new_mtu;
227 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU,
228 &mtu_info, sizeof(mtu_info),
229 &mtu_info, &out_size);
230 if (err || !out_size || mtu_info.mgmt_msg_head.status) {
231 PMD_DRV_LOG(ERR, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x",
232 err, mtu_info.mgmt_msg_head.status, out_size);
239 int hinic_get_link_status(void *hwdev, u8 *link_state)
241 struct hinic_get_link get_link;
242 u16 out_size = sizeof(get_link);
245 if (!hwdev || !link_state) {
246 PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL");
250 memset(&get_link, 0, sizeof(get_link));
251 get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
252 get_link.func_id = hinic_global_func_id(hwdev);
254 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE,
255 &get_link, sizeof(get_link),
256 &get_link, &out_size);
257 if (err || !out_size || get_link.mgmt_msg_head.status) {
258 PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x",
259 err, get_link.mgmt_msg_head.status, out_size);
263 *link_state = get_link.link_status;
269 * hinic_set_vport_enable - Notify firmware that driver is ready or not.
270 * @hwdev: the hardware interface of a nic device
271 * @enable: 1: driver is ready; 0: driver is not ok.
272 * Return: 0 on success and state is filled, negative error value otherwise.
274 int hinic_set_vport_enable(void *hwdev, bool enable)
276 struct hinic_vport_state en_state;
277 u16 out_size = sizeof(en_state);
281 PMD_DRV_LOG(ERR, "Hwdev is NULL");
285 memset(&en_state, 0, sizeof(en_state));
286 en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
287 en_state.func_id = hinic_global_func_id(hwdev);
288 en_state.state = (enable ? 1 : 0);
290 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE,
291 &en_state, sizeof(en_state),
292 &en_state, &out_size);
293 if (err || !out_size || en_state.mgmt_msg_head.status) {
294 PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x",
295 err, en_state.mgmt_msg_head.status, out_size);
303 * hinic_set_port_enable - open MAG to receive packets.
304 * @hwdev: the hardware interface of a nic device
305 * @enable: 1: open MAG; 0: close MAG.
307 * 0 on success and stats is filled,
308 * negative error value otherwise.
310 int hinic_set_port_enable(void *hwdev, bool enable)
312 struct hinic_port_state en_state;
313 u16 out_size = sizeof(en_state);
317 PMD_DRV_LOG(ERR, "Hwdev is NULL");
321 memset(&en_state, 0, sizeof(en_state));
322 en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
323 en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE);
325 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE,
326 &en_state, sizeof(en_state),
327 &en_state, &out_size);
328 if (err || !out_size || en_state.mgmt_msg_head.status) {
329 PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x",
330 err, en_state.mgmt_msg_head.status, out_size);
337 int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info)
339 struct hinic_port_info port_msg;
340 u16 out_size = sizeof(port_msg);
343 if (!hwdev || !port_info) {
344 PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL");
348 memset(&port_msg, 0, sizeof(port_msg));
349 port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
350 port_msg.func_id = hinic_global_func_id(hwdev);
352 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO,
353 &port_msg, sizeof(port_msg),
354 &port_msg, &out_size);
355 if (err || !out_size || port_msg.mgmt_msg_head.status) {
357 "Failed to get port info, err: %d, status: 0x%x, out size: 0x%x",
358 err, port_msg.mgmt_msg_head.status, out_size);
362 port_info->autoneg_cap = port_msg.autoneg_cap;
363 port_info->autoneg_state = port_msg.autoneg_state;
364 port_info->duplex = port_msg.duplex;
365 port_info->port_type = port_msg.port_type;
366 port_info->speed = port_msg.speed;
371 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause)
373 struct hinic_pause_config pause_info;
374 u16 out_size = sizeof(pause_info);
378 PMD_DRV_LOG(ERR, "Hwdev is NULL");
382 memset(&pause_info, 0, sizeof(pause_info));
383 pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
384 pause_info.func_id = hinic_global_func_id(hwdev);
385 pause_info.auto_neg = nic_pause.auto_neg;
386 pause_info.rx_pause = nic_pause.rx_pause;
387 pause_info.tx_pause = nic_pause.tx_pause;
389 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO,
390 &pause_info, sizeof(pause_info),
391 &pause_info, &out_size);
392 if (err || !out_size || pause_info.mgmt_msg_head.status) {
393 PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x",
394 err, pause_info.mgmt_msg_head.status, out_size);
401 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw,
402 u8 *pgid, u8 *up_bw, u8 *prio)
404 struct hinic_up_ets_cfg ets;
405 u16 out_size = sizeof(ets);
410 if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) {
411 PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL");
415 for (i = 0; i < HINIC_DCB_TC_MAX; i++) {
416 up_bw_t += *(up_bw + i);
417 pg_bw_t += *(pg_bw + i);
419 if (*(up_tc + i) > HINIC_DCB_TC_MAX) {
421 "Invalid up %d mapping tc: %d", i,
427 if (pg_bw_t != 100 || (up_bw_t % 100) != 0) {
429 "Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t);
433 memset(&ets, 0, sizeof(ets));
434 ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
435 ets.port_id = 0; /* reserved */
436 memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX);
437 memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX);
438 memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX);
439 memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX);
440 memcpy(ets.prio, prio, HINIC_DCB_UP_MAX);
442 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS,
443 &ets, sizeof(ets), &ets, &out_size);
444 if (err || ets.mgmt_msg_head.status || !out_size) {
446 "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x",
447 err, ets.mgmt_msg_head.status, out_size);
454 int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats)
456 struct hinic_port_stats_info vport_stats_cmd;
457 struct hinic_cmd_vport_stats vport_stats_rsp;
458 u16 out_size = sizeof(vport_stats_rsp);
461 if (!hwdev || !stats) {
462 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
466 memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp));
467 memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd));
468 vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
469 vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
470 vport_stats_cmd.func_id = hinic_global_func_id(hwdev);
471 vport_stats_cmd.stats_size = sizeof(vport_stats_rsp);
473 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT,
474 &vport_stats_cmd, sizeof(vport_stats_cmd),
475 &vport_stats_rsp, &out_size);
476 if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) {
478 "Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x",
479 err, vport_stats_rsp.mgmt_msg_head.status, out_size);
483 memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats));
488 int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats)
490 struct hinic_port_stats_info port_stats_cmd;
491 struct hinic_port_stats port_stats_rsp;
492 u16 out_size = sizeof(port_stats_rsp);
495 if (!hwdev || !stats) {
496 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL");
500 memset(&port_stats_rsp, 0, sizeof(port_stats_rsp));
501 memset(&port_stats_cmd, 0, sizeof(port_stats_cmd));
502 port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
503 port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION;
504 port_stats_cmd.stats_size = sizeof(port_stats_rsp);
506 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS,
507 &port_stats_cmd, sizeof(port_stats_cmd),
508 &port_stats_rsp, &out_size);
509 if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) {
511 "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x",
512 err, port_stats_rsp.mgmt_msg_head.status, out_size);
516 memcpy(stats, &port_stats_rsp.stats, sizeof(*stats));
521 int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type)
523 struct nic_rss_context_tbl *ctx_tbl;
524 struct hinic_cmd_buf *cmd_buf;
530 PMD_DRV_LOG(ERR, "Hwdev is NULL");
534 cmd_buf = hinic_alloc_cmd_buf(hwdev);
536 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
540 ctx |= HINIC_RSS_TYPE_SET(1, VALID) |
541 HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) |
542 HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) |
543 HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) |
544 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) |
545 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) |
546 HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) |
547 HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) |
548 HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6);
550 cmd_buf->size = sizeof(struct nic_rss_context_tbl);
552 ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf;
553 ctx_tbl->group_index = cpu_to_be32(tmpl_idx);
555 ctx_tbl->size = sizeof(u32);
556 ctx_tbl->size = cpu_to_be32(ctx_tbl->size);
558 ctx_tbl->ctx = cpu_to_be32(ctx);
560 /* cfg the rss context table by command queue */
561 err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
563 HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE,
564 cmd_buf, &out_param, 0);
566 hinic_free_cmd_buf(hwdev, cmd_buf);
568 if (err || out_param != 0) {
569 PMD_DRV_LOG(ERR, "Failed to set rss context table");
576 int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type)
578 struct hinic_rss_context_table ctx_tbl;
579 u16 out_size = sizeof(ctx_tbl);
582 if (!hwdev || !rss_type) {
583 PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL");
587 ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
588 ctx_tbl.func_id = hinic_global_func_id(hwdev);
589 ctx_tbl.template_id = (u8)tmpl_idx;
591 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL,
592 &ctx_tbl, sizeof(ctx_tbl),
593 &ctx_tbl, &out_size);
594 if (err || !out_size || ctx_tbl.mgmt_msg_head.status) {
596 "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x",
597 err, ctx_tbl.mgmt_msg_head.status, out_size);
601 rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4);
602 rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6);
603 rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT);
604 rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4);
605 rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6);
606 rss_type->tcp_ipv6_ext =
607 HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT);
608 rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4);
609 rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6);
614 int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
616 struct hinic_rss_template_key temp_key;
617 u16 out_size = sizeof(temp_key);
620 if (!hwdev || !temp) {
621 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
625 memset(&temp_key, 0, sizeof(temp_key));
626 temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
627 temp_key.func_id = hinic_global_func_id(hwdev);
628 temp_key.template_id = (u8)tmpl_idx;
629 memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE);
631 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL,
632 &temp_key, sizeof(temp_key),
633 &temp_key, &out_size);
634 if (err || !out_size || temp_key.mgmt_msg_head.status) {
636 "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x",
637 err, temp_key.mgmt_msg_head.status, out_size);
644 int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp)
646 struct hinic_rss_template_key temp_key;
647 u16 out_size = sizeof(temp_key);
650 if (!hwdev || !temp) {
651 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL");
655 memset(&temp_key, 0, sizeof(temp_key));
656 temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
657 temp_key.func_id = hinic_global_func_id(hwdev);
658 temp_key.template_id = (u8)tmpl_idx;
660 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL,
661 &temp_key, sizeof(temp_key),
662 &temp_key, &out_size);
663 if (err || !out_size || temp_key.mgmt_msg_head.status) {
664 PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x",
665 err, temp_key.mgmt_msg_head.status, out_size);
669 memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE);
675 * hinic_rss_set_hash_engine - Init rss hash function .
676 * @hwdev: the hardware interface of a nic device
677 * @tmpl_idx: index of rss template from NIC.
678 * @type: hash function, such as Toeplitz or XOR.
680 * 0 on success and stats is filled,
681 * negative error value otherwise.
683 int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type)
685 struct hinic_rss_engine_type hash_type;
686 u16 out_size = sizeof(hash_type);
690 PMD_DRV_LOG(ERR, "Hwdev is NULL");
694 memset(&hash_type, 0, sizeof(hash_type));
695 hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
696 hash_type.func_id = hinic_global_func_id(hwdev);
697 hash_type.hash_engine = type;
698 hash_type.template_id = tmpl_idx;
700 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE,
701 &hash_type, sizeof(hash_type),
702 &hash_type, &out_size);
703 if (err || !out_size || hash_type.mgmt_msg_head.status) {
704 PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x",
705 err, hash_type.mgmt_msg_head.status, out_size);
712 int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
714 struct nic_rss_indirect_tbl *indir_tbl;
715 struct hinic_cmd_buf *cmd_buf;
722 if (!hwdev || !indir_table) {
723 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
727 cmd_buf = hinic_alloc_cmd_buf(hwdev);
729 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf");
733 cmd_buf->size = sizeof(struct nic_rss_indirect_tbl);
734 indir_tbl = cmd_buf->buf;
735 indir_tbl->group_index = cpu_to_be32(tmpl_idx);
737 for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) {
738 indir_tbl->entry[i] = (u8)(*(indir_table + i));
740 if (0x3 == (i & 0x3)) {
741 temp = (u32 *)&indir_tbl->entry[i - 3];
742 *temp = cpu_to_be32(*temp);
746 /* configure the rss indirect table by command queue */
747 indir_size = HINIC_RSS_INDIR_SIZE / 2;
748 indir_tbl->offset = 0;
749 indir_tbl->size = cpu_to_be32(indir_size);
751 err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
753 HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
754 cmd_buf, &out_param, 0);
755 if (err || out_param != 0) {
756 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
761 indir_tbl->offset = cpu_to_be32(indir_size);
762 indir_tbl->size = cpu_to_be32(indir_size);
763 memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size);
765 err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ,
767 HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE,
768 cmd_buf, &out_param, 0);
769 if (err || out_param != 0) {
770 PMD_DRV_LOG(ERR, "Failed to set rss indir table");
775 hinic_free_cmd_buf(hwdev, cmd_buf);
780 int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table)
782 struct hinic_rss_indir_table rss_cfg;
783 u16 out_size = sizeof(rss_cfg);
786 if (!hwdev || !indir_table) {
787 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL");
791 memset(&rss_cfg, 0, sizeof(rss_cfg));
792 rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
793 rss_cfg.func_id = hinic_global_func_id(hwdev);
794 rss_cfg.template_id = (u8)tmpl_idx;
796 err = l2nic_msg_to_mgmt_sync(hwdev,
797 HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
798 &rss_cfg, sizeof(rss_cfg), &rss_cfg,
800 if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
801 PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x",
802 err, rss_cfg.mgmt_msg_head.status, out_size);
806 hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE);
807 for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++)
808 indir_table[i] = rss_cfg.indir[i];
813 int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc)
815 struct hinic_rss_config rss_cfg;
816 u16 out_size = sizeof(rss_cfg);
819 /* micro code required: number of TC should be power of 2 */
820 if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) {
821 PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2",
826 memset(&rss_cfg, 0, sizeof(rss_cfg));
827 rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
828 rss_cfg.func_id = hinic_global_func_id(hwdev);
829 rss_cfg.rss_en = rss_en;
830 rss_cfg.template_id = tmpl_idx;
831 rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0;
833 memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX);
835 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG,
836 &rss_cfg, sizeof(rss_cfg), &rss_cfg,
838 if (err || !out_size || rss_cfg.mgmt_msg_head.status) {
839 PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x",
840 err, rss_cfg.mgmt_msg_head.status, out_size);
848 * hinic_rss_template_alloc - get rss template id from the chip,
849 * all functions share 96 templates.
850 * @hwdev: the pointer to the private hardware device object
851 * @tmpl_idx: index of rss template from chip.
852 * Return: 0 on success and stats is filled, negative error value otherwise.
854 int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx)
856 struct hinic_rss_template_mgmt template_mgmt;
857 u16 out_size = sizeof(template_mgmt);
860 if (!hwdev || !tmpl_idx) {
861 PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL");
865 memset(&template_mgmt, 0, sizeof(template_mgmt));
866 template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
867 template_mgmt.func_id = hinic_global_func_id(hwdev);
868 template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC;
870 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
871 &template_mgmt, sizeof(template_mgmt),
872 &template_mgmt, &out_size);
873 if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
874 PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x",
875 err, template_mgmt.mgmt_msg_head.status, out_size);
879 *tmpl_idx = template_mgmt.template_id;
885 * hinic_rss_template_alloc - free rss template id to the chip
886 * @hwdev: the hardware interface of a nic device
887 * @tmpl_idx: index of rss template from NIC.
888 * Return: 0 on success and stats is filled, negative error value otherwise.
890 int hinic_rss_template_free(void *hwdev, u8 tmpl_idx)
892 struct hinic_rss_template_mgmt template_mgmt;
893 u16 out_size = sizeof(template_mgmt);
897 PMD_DRV_LOG(ERR, "Hwdev is NULL");
901 memset(&template_mgmt, 0, sizeof(template_mgmt));
902 template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
903 template_mgmt.func_id = hinic_global_func_id(hwdev);
904 template_mgmt.template_id = tmpl_idx;
905 template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE;
907 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR,
908 &template_mgmt, sizeof(template_mgmt),
909 &template_mgmt, &out_size);
910 if (err || !out_size || template_mgmt.mgmt_msg_head.status) {
911 PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x",
912 err, template_mgmt.mgmt_msg_head.status, out_size);
920 * hinic_set_rx_vhd_mode - change rx buffer size after initialization,
921 * @hwdev: the hardware interface of a nic device
923 * @rx_buf_sz: receive buffer size.
925 * 0 on success and stats is filled,
926 * negative error value otherwise.
928 int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz)
930 struct hinic_set_vhd_mode vhd_mode_cfg;
931 u16 out_size = sizeof(vhd_mode_cfg);
935 PMD_DRV_LOG(ERR, "Hwdev is NULL");
939 memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg));
941 vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
942 vhd_mode_cfg.func_id = hinic_global_func_id(hwdev);
943 vhd_mode_cfg.vhd_type = vhd_mode;
944 vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz;
946 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG,
947 &vhd_mode_cfg, sizeof(vhd_mode_cfg),
948 &vhd_mode_cfg, &out_size);
949 if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) {
951 "Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x",
952 err, vhd_mode_cfg.mgmt_msg_head.status, out_size);
960 int hinic_set_rx_mode(void *hwdev, u32 enable)
962 struct hinic_rx_mode_config rx_mode_cfg;
963 u16 out_size = sizeof(rx_mode_cfg);
967 PMD_DRV_LOG(ERR, "Hwdev is NULL");
971 memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg));
972 rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
973 rx_mode_cfg.func_id = hinic_global_func_id(hwdev);
974 rx_mode_cfg.rx_mode = enable;
976 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE,
977 &rx_mode_cfg, sizeof(rx_mode_cfg),
978 &rx_mode_cfg, &out_size);
979 if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) {
980 PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x",
981 err, rx_mode_cfg.mgmt_msg_head.status, out_size);
988 int hinic_set_rx_csum_offload(void *hwdev, u32 en)
990 struct hinic_checksum_offload rx_csum_cfg;
991 u16 out_size = sizeof(rx_csum_cfg);
995 PMD_DRV_LOG(ERR, "Hwdev is NULL");
999 memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg));
1000 rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1001 rx_csum_cfg.func_id = hinic_global_func_id(hwdev);
1002 rx_csum_cfg.rx_csum_offload = en;
1004 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM,
1005 &rx_csum_cfg, sizeof(rx_csum_cfg),
1006 &rx_csum_cfg, &out_size);
1007 if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) {
1009 "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x",
1010 err, rx_csum_cfg.mgmt_msg_head.status, out_size);
1017 int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num)
1019 struct hinic_lro_config lro_cfg;
1020 u16 out_size = sizeof(lro_cfg);
1024 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1028 memset(&lro_cfg, 0, sizeof(lro_cfg));
1029 lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1030 lro_cfg.func_id = hinic_global_func_id(hwdev);
1031 lro_cfg.lro_ipv4_en = ipv4_en;
1032 lro_cfg.lro_ipv6_en = ipv6_en;
1033 lro_cfg.lro_max_wqe_num = max_wqe_num;
1035 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO,
1036 &lro_cfg, sizeof(lro_cfg), &lro_cfg,
1038 if (err || !out_size || lro_cfg.mgmt_msg_head.status) {
1039 PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x",
1040 err, lro_cfg.mgmt_msg_head.status, out_size);
1047 int hinic_set_anti_attack(void *hwdev, bool enable)
1049 struct hinic_port_anti_attack_rate rate;
1050 u16 out_size = sizeof(rate);
1054 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1058 memset(&rate, 0, sizeof(rate));
1059 rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1060 rate.func_id = hinic_global_func_id(hwdev);
1061 rate.enable = enable;
1062 rate.cir = ANTI_ATTACK_DEFAULT_CIR;
1063 rate.xir = ANTI_ATTACK_DEFAULT_XIR;
1064 rate.cbs = ANTI_ATTACK_DEFAULT_CBS;
1065 rate.xbs = ANTI_ATTACK_DEFAULT_XBS;
1067 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE,
1068 &rate, sizeof(rate), &rate,
1070 if (err || !out_size || rate.mgmt_msg_head.status) {
1071 PMD_DRV_LOG(ERR, "can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x",
1072 (enable ? "enable" : "disable"), err,
1073 rate.mgmt_msg_head.status, out_size);
1080 /* Set autoneg status and restart port link status */
1081 int hinic_reset_port_link_cfg(void *hwdev)
1083 struct hinic_reset_link_cfg reset_cfg;
1084 u16 out_size = sizeof(reset_cfg);
1087 memset(&reset_cfg, 0, sizeof(reset_cfg));
1088 reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1089 reset_cfg.func_id = hinic_global_func_id(hwdev);
1091 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG,
1092 &reset_cfg, sizeof(reset_cfg),
1093 &reset_cfg, &out_size);
1094 if (err || !out_size || reset_cfg.mgmt_msg_head.status) {
1095 PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x",
1096 err, reset_cfg.mgmt_msg_head.status, out_size);
1103 int hinic_set_fast_recycle_mode(void *hwdev, u8 mode)
1105 struct hinic_fast_recycled_mode fast_recycled_mode;
1106 u16 out_size = sizeof(fast_recycled_mode);
1110 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1114 memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode));
1115 fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1116 fast_recycled_mode.func_id = hinic_global_func_id(hwdev);
1117 fast_recycled_mode.fast_recycled_mode = mode;
1119 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM,
1120 HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET,
1121 &fast_recycled_mode,
1122 sizeof(fast_recycled_mode),
1123 &fast_recycled_mode, &out_size, 0);
1124 if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) {
1126 "Failed to set recycle mode, ret = %d",
1127 fast_recycled_mode.mgmt_msg_head.status);
1134 int hinic_clear_vport_stats(struct hinic_hwdev *hwdev)
1136 struct hinic_clear_vport_stats clear_vport_stats;
1137 u16 out_size = sizeof(clear_vport_stats);
1141 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1145 memset(&clear_vport_stats, 0, sizeof(clear_vport_stats));
1146 clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1147 clear_vport_stats.func_id = hinic_global_func_id(hwdev);
1149 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT,
1151 sizeof(clear_vport_stats),
1152 &clear_vport_stats, &out_size);
1153 if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) {
1154 PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x",
1155 err, clear_vport_stats.mgmt_msg_head.status, out_size);
1162 int hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev)
1164 struct hinic_clear_port_stats clear_phy_port_stats;
1165 u16 out_size = sizeof(clear_phy_port_stats);
1169 PMD_DRV_LOG(ERR, "Hwdev is NULL");
1173 memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats));
1174 clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1175 clear_phy_port_stats.func_id = hinic_global_func_id(hwdev);
1177 err = l2nic_msg_to_mgmt_sync(hwdev,
1178 HINIC_PORT_CMD_CLEAR_PORT_STATISTICS,
1179 &clear_phy_port_stats,
1180 sizeof(clear_phy_port_stats),
1181 &clear_phy_port_stats, &out_size);
1182 if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) {
1183 PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x",
1184 err, clear_phy_port_stats.mgmt_msg_head.status,
1192 int hinic_set_link_status_follow(void *hwdev,
1193 enum hinic_link_follow_status status)
1195 struct hinic_set_link_follow follow;
1196 u16 out_size = sizeof(follow);
1202 if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) {
1204 "Invalid link follow status: %d", status);
1208 memset(&follow, 0, sizeof(follow));
1209 follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1210 follow.func_id = hinic_global_func_id(hwdev);
1211 follow.follow_status = status;
1213 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW,
1214 &follow, sizeof(follow),
1215 &follow, &out_size);
1216 if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED &&
1217 follow.mgmt_msg_head.status) || err || !out_size) {
1219 "Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x",
1220 err, follow.mgmt_msg_head.status, out_size);
1224 return follow.mgmt_msg_head.status;
1227 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised)
1229 struct hinic_link_mode_cmd link_mode;
1230 u16 out_size = sizeof(link_mode);
1233 if (!hwdev || !supported || !advertised)
1236 memset(&link_mode, 0, sizeof(link_mode));
1237 link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1238 link_mode.func_id = hinic_global_func_id(hwdev);
1240 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE,
1241 &link_mode, sizeof(link_mode),
1242 &link_mode, &out_size);
1243 if (err || !out_size || link_mode.mgmt_msg_head.status) {
1245 "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x",
1246 err, link_mode.mgmt_msg_head.status, out_size);
1250 *supported = link_mode.supported;
1251 *advertised = link_mode.advertised;
1257 * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport fake
1258 * failed when device start.
1259 * @hwdev: the hardware interface of a nic device
1260 * Return: 0 on success, negative error value otherwise.
1262 int hinic_flush_qp_res(void *hwdev)
1264 struct hinic_clear_qp_resource qp_res;
1265 u16 out_size = sizeof(qp_res);
1268 memset(&qp_res, 0, sizeof(qp_res));
1269 qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1;
1270 qp_res.func_id = hinic_global_func_id(hwdev);
1272 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES,
1273 &qp_res, sizeof(qp_res), &qp_res,
1275 if (err || !out_size || qp_res.mgmt_msg_head.status) {
1276 PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x",
1277 err, qp_res.mgmt_msg_head.status, out_size);