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 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, \ 17 buf_in, in_size, \ 18 buf_out, out_size, 0) 19 20 int hinic_init_function_table(void *hwdev, u16 rx_buf_sz) 21 { 22 struct hinic_function_table function_table; 23 u16 out_size = sizeof(function_table); 24 int err; 25 26 if (!hwdev) { 27 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 28 return -EINVAL; 29 } 30 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; 36 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) { 42 PMD_DRV_LOG(ERR, 43 "Failed to init func table, ret = %d", 44 function_table.mgmt_msg_head.status); 45 return -EFAULT; 46 } 47 48 return 0; 49 } 50 51 /** 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 55 * @return 56 * 0 on success, 57 * negative error value otherwise. 58 **/ 59 int hinic_get_base_qpn(void *hwdev, u16 *global_qpn) 60 { 61 struct hinic_cmd_qpn cmd_qpn; 62 u16 out_size = sizeof(cmd_qpn); 63 int err; 64 65 if (!hwdev || !global_qpn) { 66 PMD_DRV_LOG(ERR, "Hwdev or global_qpn is NULL"); 67 return -EINVAL; 68 } 69 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); 73 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, 77 &out_size, 0); 78 if (err || !out_size || cmd_qpn.mgmt_msg_head.status) { 79 PMD_DRV_LOG(ERR, 80 "Failed to get base qpn, status(%d)", 81 cmd_qpn.mgmt_msg_head.status); 82 return -EINVAL; 83 } 84 85 *global_qpn = cmd_qpn.base_qpn; 86 87 return 0; 88 } 89 90 /** 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 96 * @return 97 * 0 on success and stats is filled, 98 * negative error value otherwise. 99 */ 100 int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id) 101 { 102 struct hinic_port_mac_set mac_info; 103 u16 out_size = sizeof(mac_info); 104 int err; 105 106 if (!hwdev || !mac_addr) { 107 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL"); 108 return -EINVAL; 109 } 110 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); 116 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); 123 return -EINVAL; 124 } 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; 128 } 129 130 return 0; 131 } 132 133 /** 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 139 * @return 140 * 0 on success and stats is filled, 141 * negative error value otherwise. 142 */ 143 int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, 144 u16 func_id) 145 { 146 struct hinic_port_mac_set mac_info; 147 u16 out_size = sizeof(mac_info); 148 int err; 149 150 if (!hwdev || !mac_addr) { 151 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL"); 152 return -EINVAL; 153 } 154 155 if (vlan_id >= VLAN_N_VID) { 156 PMD_DRV_LOG(ERR, "Invalid VLAN number"); 157 return -EINVAL; 158 } 159 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); 165 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); 172 return -EINVAL; 173 } 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; 177 } 178 179 return 0; 180 } 181 182 int hinic_get_default_mac(void *hwdev, u8 *mac_addr) 183 { 184 struct hinic_port_mac_set mac_info; 185 u16 out_size = sizeof(mac_info); 186 int err; 187 188 if (!hwdev || !mac_addr) { 189 PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL"); 190 return -EINVAL; 191 } 192 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); 196 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); 203 return -EINVAL; 204 } 205 206 memmove(mac_addr, mac_info.mac, ETH_ALEN); 207 208 return 0; 209 } 210 211 int hinic_set_port_mtu(void *hwdev, u32 new_mtu) 212 { 213 struct hinic_mtu mtu_info; 214 u16 out_size = sizeof(mtu_info); 215 int err; 216 217 if (!hwdev) { 218 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 219 return -EINVAL; 220 } 221 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; 226 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); 233 return -EINVAL; 234 } 235 236 return 0; 237 } 238 239 int hinic_get_link_status(void *hwdev, u8 *link_state) 240 { 241 struct hinic_get_link get_link; 242 u16 out_size = sizeof(get_link); 243 int err; 244 245 if (!hwdev || !link_state) { 246 PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL"); 247 return -EINVAL; 248 } 249 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); 253 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); 260 return -EINVAL; 261 } 262 263 *link_state = get_link.link_status; 264 265 return 0; 266 } 267 268 /** 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. 273 **/ 274 int hinic_set_vport_enable(void *hwdev, bool enable) 275 { 276 struct hinic_vport_state en_state; 277 u16 out_size = sizeof(en_state); 278 int err; 279 280 if (!hwdev) { 281 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 282 return -EINVAL; 283 } 284 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); 289 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); 296 return -EINVAL; 297 } 298 299 return 0; 300 } 301 302 /** 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. 306 * @return 307 * 0 on success and stats is filled, 308 * negative error value otherwise. 309 */ 310 int hinic_set_port_enable(void *hwdev, bool enable) 311 { 312 struct hinic_port_state en_state; 313 u16 out_size = sizeof(en_state); 314 int err; 315 316 if (!hwdev) { 317 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 318 return -EINVAL; 319 } 320 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); 324 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); 331 return -EINVAL; 332 } 333 334 return 0; 335 } 336 337 int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info) 338 { 339 struct hinic_port_info port_msg; 340 u16 out_size = sizeof(port_msg); 341 int err; 342 343 if (!hwdev || !port_info) { 344 PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL"); 345 return -EINVAL; 346 } 347 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); 351 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) { 356 PMD_DRV_LOG(ERR, 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); 359 return err; 360 } 361 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; 367 368 return 0; 369 } 370 371 int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause) 372 { 373 struct hinic_pause_config pause_info; 374 u16 out_size = sizeof(pause_info); 375 int err; 376 377 if (!hwdev) { 378 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 379 return -EINVAL; 380 } 381 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; 388 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); 395 return -EINVAL; 396 } 397 398 return 0; 399 } 400 401 int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw, 402 u8 *pgid, u8 *up_bw, u8 *prio) 403 { 404 struct hinic_up_ets_cfg ets; 405 u16 out_size = sizeof(ets); 406 u16 up_bw_t = 0; 407 u8 pg_bw_t = 0; 408 int i, err; 409 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"); 412 return -EINVAL; 413 } 414 415 for (i = 0; i < HINIC_DCB_TC_MAX; i++) { 416 up_bw_t += *(up_bw + i); 417 pg_bw_t += *(pg_bw + i); 418 419 if (*(up_tc + i) > HINIC_DCB_TC_MAX) { 420 PMD_DRV_LOG(ERR, 421 "Invalid up %d mapping tc: %d", i, 422 *(up_tc + i)); 423 return -EINVAL; 424 } 425 } 426 427 if (pg_bw_t != 100 || (up_bw_t % 100) != 0) { 428 PMD_DRV_LOG(ERR, 429 "Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t); 430 return -EINVAL; 431 } 432 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); 441 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) { 445 PMD_DRV_LOG(ERR, 446 "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x", 447 err, ets.mgmt_msg_head.status, out_size); 448 return -EINVAL; 449 } 450 451 return 0; 452 } 453 454 int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats) 455 { 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); 459 int err; 460 461 if (!hwdev || !stats) { 462 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL"); 463 return -EINVAL; 464 } 465 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); 472 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) { 477 PMD_DRV_LOG(ERR, 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); 480 return -EFAULT; 481 } 482 483 memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats)); 484 485 return 0; 486 } 487 488 int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats) 489 { 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); 493 int err; 494 495 if (!hwdev || !stats) { 496 PMD_DRV_LOG(ERR, "Hwdev or stats is NULL"); 497 return -EINVAL; 498 } 499 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); 505 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) { 510 PMD_DRV_LOG(ERR, 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); 513 return -EFAULT; 514 } 515 516 memcpy(stats, &port_stats_rsp.stats, sizeof(*stats)); 517 518 return 0; 519 } 520 521 int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type) 522 { 523 struct nic_rss_context_tbl *ctx_tbl; 524 struct hinic_cmd_buf *cmd_buf; 525 u32 ctx = 0; 526 u64 out_param; 527 int err; 528 529 if (!hwdev) { 530 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 531 return -EINVAL; 532 } 533 534 cmd_buf = hinic_alloc_cmd_buf(hwdev); 535 if (!cmd_buf) { 536 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf"); 537 return -ENOMEM; 538 } 539 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); 549 550 cmd_buf->size = sizeof(struct nic_rss_context_tbl); 551 552 ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf; 553 ctx_tbl->group_index = cpu_to_be32(tmpl_idx); 554 ctx_tbl->offset = 0; 555 ctx_tbl->size = sizeof(u32); 556 ctx_tbl->size = cpu_to_be32(ctx_tbl->size); 557 ctx_tbl->rsvd = 0; 558 ctx_tbl->ctx = cpu_to_be32(ctx); 559 560 /* cfg the rss context table by command queue */ 561 err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ, 562 HINIC_MOD_L2NIC, 563 HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE, 564 cmd_buf, &out_param, 0); 565 566 hinic_free_cmd_buf(hwdev, cmd_buf); 567 568 if (err || out_param != 0) { 569 PMD_DRV_LOG(ERR, "Failed to set rss context table"); 570 return -EFAULT; 571 } 572 573 return 0; 574 } 575 576 int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type) 577 { 578 struct hinic_rss_context_table ctx_tbl; 579 u16 out_size = sizeof(ctx_tbl); 580 int err; 581 582 if (!hwdev || !rss_type) { 583 PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL"); 584 return -EINVAL; 585 } 586 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; 590 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) { 595 PMD_DRV_LOG(ERR, 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); 598 return -EINVAL; 599 } 600 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); 610 611 return 0; 612 } 613 614 int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp) 615 { 616 struct hinic_rss_template_key temp_key; 617 u16 out_size = sizeof(temp_key); 618 int err; 619 620 if (!hwdev || !temp) { 621 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL"); 622 return -EINVAL; 623 } 624 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); 630 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) { 635 PMD_DRV_LOG(ERR, 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); 638 return -EINVAL; 639 } 640 641 return 0; 642 } 643 644 int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp) 645 { 646 struct hinic_rss_template_key temp_key; 647 u16 out_size = sizeof(temp_key); 648 int err; 649 650 if (!hwdev || !temp) { 651 PMD_DRV_LOG(ERR, "Hwdev or temp is NULL"); 652 return -EINVAL; 653 } 654 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; 659 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); 666 return -EINVAL; 667 } 668 669 memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE); 670 671 return 0; 672 } 673 674 /** 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. 679 * @return 680 * 0 on success and stats is filled, 681 * negative error value otherwise. 682 */ 683 int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type) 684 { 685 struct hinic_rss_engine_type hash_type; 686 u16 out_size = sizeof(hash_type); 687 int err; 688 689 if (!hwdev) { 690 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 691 return -EINVAL; 692 } 693 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; 699 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); 706 return -EINVAL; 707 } 708 709 return 0; 710 } 711 712 int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table) 713 { 714 struct nic_rss_indirect_tbl *indir_tbl; 715 struct hinic_cmd_buf *cmd_buf; 716 int i; 717 u32 *temp; 718 u32 indir_size; 719 u64 out_param; 720 int err; 721 722 if (!hwdev || !indir_table) { 723 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL"); 724 return -EINVAL; 725 } 726 727 cmd_buf = hinic_alloc_cmd_buf(hwdev); 728 if (!cmd_buf) { 729 PMD_DRV_LOG(ERR, "Failed to allocate cmd buf"); 730 return -ENOMEM; 731 } 732 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); 736 737 for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) { 738 indir_tbl->entry[i] = (u8)(*(indir_table + i)); 739 740 if (0x3 == (i & 0x3)) { 741 temp = (u32 *)&indir_tbl->entry[i - 3]; 742 *temp = cpu_to_be32(*temp); 743 } 744 } 745 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); 750 751 err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ, 752 HINIC_MOD_L2NIC, 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"); 757 err = -EFAULT; 758 goto free_buf; 759 } 760 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); 764 765 err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ, 766 HINIC_MOD_L2NIC, 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"); 771 err = -EFAULT; 772 } 773 774 free_buf: 775 hinic_free_cmd_buf(hwdev, cmd_buf); 776 777 return err; 778 } 779 780 int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table) 781 { 782 struct hinic_rss_indir_table rss_cfg; 783 u16 out_size = sizeof(rss_cfg); 784 int err = 0, i; 785 786 if (!hwdev || !indir_table) { 787 PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL"); 788 return -EINVAL; 789 } 790 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; 795 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, 799 &out_size); 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); 803 return -EINVAL; 804 } 805 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]; 809 810 return 0; 811 } 812 813 int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc) 814 { 815 struct hinic_rss_config rss_cfg; 816 u16 out_size = sizeof(rss_cfg); 817 int err; 818 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", 822 tc_num); 823 return -EINVAL; 824 } 825 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; 832 833 memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX); 834 835 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG, 836 &rss_cfg, sizeof(rss_cfg), &rss_cfg, 837 &out_size); 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); 841 return -EINVAL; 842 } 843 844 return 0; 845 } 846 847 /** 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. 853 **/ 854 int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx) 855 { 856 struct hinic_rss_template_mgmt template_mgmt; 857 u16 out_size = sizeof(template_mgmt); 858 int err; 859 860 if (!hwdev || !tmpl_idx) { 861 PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL"); 862 return -EINVAL; 863 } 864 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; 869 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); 876 return -EINVAL; 877 } 878 879 *tmpl_idx = template_mgmt.template_id; 880 881 return 0; 882 } 883 884 /** 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. 889 **/ 890 int hinic_rss_template_free(void *hwdev, u8 tmpl_idx) 891 { 892 struct hinic_rss_template_mgmt template_mgmt; 893 u16 out_size = sizeof(template_mgmt); 894 int err; 895 896 if (!hwdev) { 897 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 898 return -EINVAL; 899 } 900 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; 906 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); 913 return -EINVAL; 914 } 915 916 return 0; 917 } 918 919 /** 920 * hinic_set_rx_vhd_mode - change rx buffer size after initialization, 921 * @hwdev: the hardware interface of a nic device 922 * @mode: not needed. 923 * @rx_buf_sz: receive buffer size. 924 * @return 925 * 0 on success and stats is filled, 926 * negative error value otherwise. 927 */ 928 int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz) 929 { 930 struct hinic_set_vhd_mode vhd_mode_cfg; 931 u16 out_size = sizeof(vhd_mode_cfg); 932 int err; 933 934 if (!hwdev) { 935 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 936 return -EINVAL; 937 } 938 939 memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg)); 940 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; 945 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) { 950 PMD_DRV_LOG(ERR, 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); 953 954 return -EIO; 955 } 956 957 return 0; 958 } 959 960 int hinic_set_rx_mode(void *hwdev, u32 enable) 961 { 962 struct hinic_rx_mode_config rx_mode_cfg; 963 u16 out_size = sizeof(rx_mode_cfg); 964 int err; 965 966 if (!hwdev) { 967 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 968 return -EINVAL; 969 } 970 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; 975 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); 982 return -EINVAL; 983 } 984 985 return 0; 986 } 987 988 int hinic_set_rx_csum_offload(void *hwdev, u32 en) 989 { 990 struct hinic_checksum_offload rx_csum_cfg; 991 u16 out_size = sizeof(rx_csum_cfg); 992 int err; 993 994 if (!hwdev) { 995 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 996 return -EINVAL; 997 } 998 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; 1003 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) { 1008 PMD_DRV_LOG(ERR, 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); 1011 return -EINVAL; 1012 } 1013 1014 return 0; 1015 } 1016 1017 int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num) 1018 { 1019 struct hinic_lro_config lro_cfg; 1020 u16 out_size = sizeof(lro_cfg); 1021 int err; 1022 1023 if (!hwdev) { 1024 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 1025 return -EINVAL; 1026 } 1027 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; 1034 1035 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO, 1036 &lro_cfg, sizeof(lro_cfg), &lro_cfg, 1037 &out_size); 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); 1041 return -EINVAL; 1042 } 1043 1044 return 0; 1045 } 1046 1047 int hinic_set_anti_attack(void *hwdev, bool enable) 1048 { 1049 struct hinic_port_anti_attack_rate rate; 1050 u16 out_size = sizeof(rate); 1051 int err; 1052 1053 if (!hwdev) { 1054 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 1055 return -EINVAL; 1056 } 1057 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; 1066 1067 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE, 1068 &rate, sizeof(rate), &rate, 1069 &out_size); 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); 1074 return -EINVAL; 1075 } 1076 1077 return 0; 1078 } 1079 1080 /* Set autoneg status and restart port link status */ 1081 int hinic_reset_port_link_cfg(void *hwdev) 1082 { 1083 struct hinic_reset_link_cfg reset_cfg; 1084 u16 out_size = sizeof(reset_cfg); 1085 int err; 1086 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); 1090 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); 1097 return -EFAULT; 1098 } 1099 1100 return 0; 1101 } 1102 1103 int hinic_set_fast_recycle_mode(void *hwdev, u8 mode) 1104 { 1105 struct hinic_fast_recycled_mode fast_recycled_mode; 1106 u16 out_size = sizeof(fast_recycled_mode); 1107 int err; 1108 1109 if (!hwdev) { 1110 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 1111 return -EINVAL; 1112 } 1113 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; 1118 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) { 1125 PMD_DRV_LOG(ERR, 1126 "Failed to set recycle mode, ret = %d", 1127 fast_recycled_mode.mgmt_msg_head.status); 1128 return -EFAULT; 1129 } 1130 1131 return 0; 1132 } 1133 1134 void hinic_clear_vport_stats(struct hinic_hwdev *hwdev) 1135 { 1136 struct hinic_clear_vport_stats clear_vport_stats; 1137 u16 out_size = sizeof(clear_vport_stats); 1138 int err; 1139 1140 if (!hwdev) { 1141 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 1142 return; 1143 } 1144 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); 1148 1149 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT, 1150 &clear_vport_stats, 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); 1156 } 1157 } 1158 1159 void hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev) 1160 { 1161 struct hinic_clear_port_stats clear_phy_port_stats; 1162 u16 out_size = sizeof(clear_phy_port_stats); 1163 int err; 1164 1165 if (!hwdev) { 1166 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 1167 return; 1168 } 1169 1170 memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats)); 1171 clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1172 clear_phy_port_stats.func_id = hinic_global_func_id(hwdev); 1173 1174 err = l2nic_msg_to_mgmt_sync(hwdev, 1175 HINIC_PORT_CMD_CLEAR_PORT_STATISTICS, 1176 &clear_phy_port_stats, 1177 sizeof(clear_phy_port_stats), 1178 &clear_phy_port_stats, &out_size); 1179 if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) { 1180 PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x", 1181 err, clear_phy_port_stats.mgmt_msg_head.status, 1182 out_size); 1183 } 1184 } 1185 1186 int hinic_set_link_status_follow(void *hwdev, 1187 enum hinic_link_follow_status status) 1188 { 1189 struct hinic_set_link_follow follow; 1190 u16 out_size = sizeof(follow); 1191 int err; 1192 1193 if (!hwdev) 1194 return -EINVAL; 1195 1196 if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) { 1197 PMD_DRV_LOG(ERR, 1198 "Invalid link follow status: %d", status); 1199 return -EINVAL; 1200 } 1201 1202 memset(&follow, 0, sizeof(follow)); 1203 follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1204 follow.func_id = hinic_global_func_id(hwdev); 1205 follow.follow_status = status; 1206 1207 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW, 1208 &follow, sizeof(follow), 1209 &follow, &out_size); 1210 if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED && 1211 follow.mgmt_msg_head.status) || err || !out_size) { 1212 PMD_DRV_LOG(ERR, 1213 "Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x", 1214 err, follow.mgmt_msg_head.status, out_size); 1215 return -EFAULT; 1216 } 1217 1218 return follow.mgmt_msg_head.status; 1219 } 1220 1221 int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised) 1222 { 1223 struct hinic_link_mode_cmd link_mode; 1224 u16 out_size = sizeof(link_mode); 1225 int err; 1226 1227 if (!hwdev || !supported || !advertised) 1228 return -EINVAL; 1229 1230 memset(&link_mode, 0, sizeof(link_mode)); 1231 link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1232 link_mode.func_id = hinic_global_func_id(hwdev); 1233 1234 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE, 1235 &link_mode, sizeof(link_mode), 1236 &link_mode, &out_size); 1237 if (err || !out_size || link_mode.mgmt_msg_head.status) { 1238 PMD_DRV_LOG(ERR, 1239 "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x", 1240 err, link_mode.mgmt_msg_head.status, out_size); 1241 return -EINVAL; 1242 } 1243 1244 *supported = link_mode.supported; 1245 *advertised = link_mode.advertised; 1246 1247 return 0; 1248 } 1249 1250 /** 1251 * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport fake 1252 * failed when device start. 1253 * @hwdev: the hardware interface of a nic device 1254 * Return: 0 on success, negative error value otherwise. 1255 **/ 1256 int hinic_flush_qp_res(void *hwdev) 1257 { 1258 struct hinic_clear_qp_resource qp_res; 1259 u16 out_size = sizeof(qp_res); 1260 int err; 1261 1262 memset(&qp_res, 0, sizeof(qp_res)); 1263 qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1264 qp_res.func_id = hinic_global_func_id(hwdev); 1265 1266 err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES, 1267 &qp_res, sizeof(qp_res), &qp_res, 1268 &out_size); 1269 if (err || !out_size || qp_res.mgmt_msg_head.status) { 1270 PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x", 1271 err, qp_res.mgmt_msg_head.status, out_size); 1272 return -EINVAL; 1273 } 1274 1275 return 0; 1276 } 1277