1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2017 Huawei Technologies Co., Ltd 3 */ 4 5 #include "hinic_compat.h" 6 #include "hinic_pmd_hwdev.h" 7 #include "hinic_pmd_hwif.h" 8 #include "hinic_pmd_eqs.h" 9 #include "hinic_pmd_wq.h" 10 #include "hinic_pmd_mgmt.h" 11 #include "hinic_pmd_cmdq.h" 12 #include "hinic_pmd_niccfg.h" 13 #include "hinic_pmd_mbox.h" 14 15 #define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, \ 16 in_size, buf_out, out_size) \ 17 hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, cmd, \ 18 buf_in, in_size, \ 19 buf_out, out_size, 0) 20 21 /** 22 * hinic_init_function_table - Initialize function table. 23 * 24 * @param hwdev 25 * The hardware interface of a nic device. 26 * @param rx_buf_sz 27 * Receive buffer size. 28 * 29 * @return 30 * 0 on success. 31 * negative error value otherwise. 32 */ 33 int hinic_init_function_table(void *hwdev, u16 rx_buf_sz) 34 { 35 struct hinic_function_table function_table; 36 u16 out_size = sizeof(function_table); 37 int err; 38 39 if (!hwdev) { 40 PMD_DRV_LOG(ERR, "Hwdev is NULL"); 41 return -EINVAL; 42 } 43 44 memset(&function_table, 0, sizeof(function_table)); 45 function_table.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 46 function_table.func_id = hinic_global_func_id(hwdev); 47 function_table.mtu = 0x3FFF; /* default, max mtu */ 48 function_table.rx_wqe_buf_size = rx_buf_sz; 49 50 err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, 51 HINIC_PORT_CMD_INIT_FUNC, 52 &function_table, sizeof(function_table), 53 &function_table, &out_size, 0); 54 if (err || function_table.mgmt_msg_head.status || !out_size) { 55 PMD_DRV_LOG(ERR, 56 "Failed to init func table, err: %d, status: 0x%x, out size: 0x%x", 57 err, function_table.mgmt_msg_head.status, out_size); 58 return -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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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 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 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 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 */ 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 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 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 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 */ 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 */ 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 */ 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 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 */ 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 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 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 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 */ 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 */ 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 */ 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 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 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 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 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