12d5fd101SZiyang Xuan /* SPDX-License-Identifier: BSD-3-Clause 22d5fd101SZiyang Xuan * Copyright(c) 2017 Huawei Technologies Co., Ltd 32d5fd101SZiyang Xuan */ 42d5fd101SZiyang Xuan 52d5fd101SZiyang Xuan #include "hinic_compat.h" 62d5fd101SZiyang Xuan #include "hinic_pmd_hwdev.h" 72d5fd101SZiyang Xuan #include "hinic_pmd_hwif.h" 82d5fd101SZiyang Xuan #include "hinic_pmd_eqs.h" 92d5fd101SZiyang Xuan #include "hinic_pmd_wq.h" 102d5fd101SZiyang Xuan #include "hinic_pmd_mgmt.h" 112d5fd101SZiyang Xuan #include "hinic_pmd_cmdq.h" 122d5fd101SZiyang Xuan #include "hinic_pmd_niccfg.h" 13b8582d05SXiaoyun Wang #include "hinic_pmd_mbox.h" 142d5fd101SZiyang Xuan 152d5fd101SZiyang Xuan #define l2nic_msg_to_mgmt_sync(hwdev, cmd, buf_in, \ 162d5fd101SZiyang Xuan in_size, buf_out, out_size) \ 172d5fd101SZiyang Xuan hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, cmd, \ 182d5fd101SZiyang Xuan buf_in, in_size, \ 192d5fd101SZiyang Xuan buf_out, out_size, 0) 202d5fd101SZiyang Xuan 21b8582d05SXiaoyun Wang /** 22b8582d05SXiaoyun Wang * hinic_init_function_table - Initialize function table. 23b8582d05SXiaoyun Wang * 24b8582d05SXiaoyun Wang * @param hwdev 25b8582d05SXiaoyun Wang * The hardware interface of a nic device. 26b8582d05SXiaoyun Wang * @param rx_buf_sz 27b8582d05SXiaoyun Wang * Receive buffer size. 28b8582d05SXiaoyun Wang * 29b8582d05SXiaoyun Wang * @return 30b8582d05SXiaoyun Wang * 0 on success. 31b8582d05SXiaoyun Wang * negative error value otherwise. 32b8582d05SXiaoyun Wang */ 332d5fd101SZiyang Xuan int hinic_init_function_table(void *hwdev, u16 rx_buf_sz) 342d5fd101SZiyang Xuan { 352d5fd101SZiyang Xuan struct hinic_function_table function_table; 362d5fd101SZiyang Xuan u16 out_size = sizeof(function_table); 372d5fd101SZiyang Xuan int err; 382d5fd101SZiyang Xuan 392d5fd101SZiyang Xuan if (!hwdev) { 402d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 412d5fd101SZiyang Xuan return -EINVAL; 422d5fd101SZiyang Xuan } 432d5fd101SZiyang Xuan 442d5fd101SZiyang Xuan memset(&function_table, 0, sizeof(function_table)); 452d5fd101SZiyang Xuan function_table.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 462d5fd101SZiyang Xuan function_table.func_id = hinic_global_func_id(hwdev); 472d5fd101SZiyang Xuan function_table.mtu = 0x3FFF; /* default, max mtu */ 482d5fd101SZiyang Xuan function_table.rx_wqe_buf_size = rx_buf_sz; 492d5fd101SZiyang Xuan 502d5fd101SZiyang Xuan err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, 512d5fd101SZiyang Xuan HINIC_PORT_CMD_INIT_FUNC, 522d5fd101SZiyang Xuan &function_table, sizeof(function_table), 532d5fd101SZiyang Xuan &function_table, &out_size, 0); 542d5fd101SZiyang Xuan if (err || function_table.mgmt_msg_head.status || !out_size) { 552d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 56b8582d05SXiaoyun Wang "Failed to init func table, err: %d, status: 0x%x, out size: 0x%x", 57b8582d05SXiaoyun Wang err, function_table.mgmt_msg_head.status, out_size); 582ae8e130SXiaoyun Wang return -EIO; 592d5fd101SZiyang Xuan } 602d5fd101SZiyang Xuan 612d5fd101SZiyang Xuan return 0; 622d5fd101SZiyang Xuan } 632d5fd101SZiyang Xuan 642d5fd101SZiyang Xuan /** 65b8582d05SXiaoyun Wang * hinic_get_base_qpn - Get global queue number. 66b8582d05SXiaoyun Wang * 67b8582d05SXiaoyun Wang * @param hwdev 68b8582d05SXiaoyun Wang * The hardware interface of a nic device. 69b8582d05SXiaoyun Wang * @param global_qpn 70b8582d05SXiaoyun Wang * Global queue number. 71b8582d05SXiaoyun Wang * 722d5fd101SZiyang Xuan * @return 73b8582d05SXiaoyun Wang * 0 on success. 742d5fd101SZiyang Xuan * negative error value otherwise. 75b8582d05SXiaoyun Wang */ 762d5fd101SZiyang Xuan int hinic_get_base_qpn(void *hwdev, u16 *global_qpn) 772d5fd101SZiyang Xuan { 782d5fd101SZiyang Xuan struct hinic_cmd_qpn cmd_qpn; 792d5fd101SZiyang Xuan u16 out_size = sizeof(cmd_qpn); 802d5fd101SZiyang Xuan int err; 812d5fd101SZiyang Xuan 822d5fd101SZiyang Xuan if (!hwdev || !global_qpn) { 832d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or global_qpn is NULL"); 842d5fd101SZiyang Xuan return -EINVAL; 852d5fd101SZiyang Xuan } 862d5fd101SZiyang Xuan 872d5fd101SZiyang Xuan memset(&cmd_qpn, 0, sizeof(cmd_qpn)); 882d5fd101SZiyang Xuan cmd_qpn.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 892d5fd101SZiyang Xuan cmd_qpn.func_id = hinic_global_func_id(hwdev); 902d5fd101SZiyang Xuan 912d5fd101SZiyang Xuan err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, 922d5fd101SZiyang Xuan HINIC_PORT_CMD_GET_GLOBAL_QPN, 932d5fd101SZiyang Xuan &cmd_qpn, sizeof(cmd_qpn), &cmd_qpn, 942d5fd101SZiyang Xuan &out_size, 0); 952d5fd101SZiyang Xuan if (err || !out_size || cmd_qpn.mgmt_msg_head.status) { 962d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 97b8582d05SXiaoyun Wang "Failed to get base qpn, err: %d, status: 0x%x, out size: 0x%x", 98b8582d05SXiaoyun Wang err, cmd_qpn.mgmt_msg_head.status, out_size); 992ae8e130SXiaoyun Wang return -EIO; 1002d5fd101SZiyang Xuan } 1012d5fd101SZiyang Xuan 1022d5fd101SZiyang Xuan *global_qpn = cmd_qpn.base_qpn; 1032d5fd101SZiyang Xuan 1042d5fd101SZiyang Xuan return 0; 1052d5fd101SZiyang Xuan } 1062d5fd101SZiyang Xuan 1072d5fd101SZiyang Xuan /** 1082d5fd101SZiyang Xuan * hinic_set_mac - Init mac_vlan table in NIC. 109b8582d05SXiaoyun Wang * 110b8582d05SXiaoyun Wang * @param hwdev 111b8582d05SXiaoyun Wang * The hardware interface of a nic device. 112b8582d05SXiaoyun Wang * @param mac_addr 113b8582d05SXiaoyun Wang * MAC address. 114b8582d05SXiaoyun Wang * @param vlan_id 115b8582d05SXiaoyun Wang * Set 0 for mac_vlan table initialization. 116b8582d05SXiaoyun Wang * @param func_id 117b8582d05SXiaoyun Wang * Global function id of NIC. 118b8582d05SXiaoyun Wang * 1192d5fd101SZiyang Xuan * @return 120b8582d05SXiaoyun Wang * 0 on success. 1212d5fd101SZiyang Xuan * negative error value otherwise. 1222d5fd101SZiyang Xuan */ 1232d5fd101SZiyang Xuan int hinic_set_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id) 1242d5fd101SZiyang Xuan { 1252d5fd101SZiyang Xuan struct hinic_port_mac_set mac_info; 1262d5fd101SZiyang Xuan u16 out_size = sizeof(mac_info); 1272d5fd101SZiyang Xuan int err; 1282d5fd101SZiyang Xuan 1292d5fd101SZiyang Xuan if (!hwdev || !mac_addr) { 1302d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL"); 1312d5fd101SZiyang Xuan return -EINVAL; 1322d5fd101SZiyang Xuan } 1332d5fd101SZiyang Xuan 1342d5fd101SZiyang Xuan memset(&mac_info, 0, sizeof(mac_info)); 1352d5fd101SZiyang Xuan mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1362d5fd101SZiyang Xuan mac_info.func_id = func_id; 1372d5fd101SZiyang Xuan mac_info.vlan_id = vlan_id; 1382d5fd101SZiyang Xuan memmove(mac_info.mac, mac_addr, ETH_ALEN); 1392d5fd101SZiyang Xuan 1402d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info, 1412d5fd101SZiyang Xuan sizeof(mac_info), &mac_info, &out_size); 1422d5fd101SZiyang Xuan if (err || !out_size || (mac_info.mgmt_msg_head.status && 1432d5fd101SZiyang Xuan mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) { 1442d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x", 1452d5fd101SZiyang Xuan err, mac_info.mgmt_msg_head.status, out_size); 1462ae8e130SXiaoyun Wang return -EIO; 1472d5fd101SZiyang Xuan } 148b8582d05SXiaoyun Wang 1492d5fd101SZiyang Xuan if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) { 1502d5fd101SZiyang Xuan PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore set operation."); 1512d5fd101SZiyang Xuan return HINIC_PF_SET_VF_ALREADY; 1522d5fd101SZiyang Xuan } 1532d5fd101SZiyang Xuan 1542d5fd101SZiyang Xuan return 0; 1552d5fd101SZiyang Xuan } 1562d5fd101SZiyang Xuan 1572d5fd101SZiyang Xuan /** 1582d5fd101SZiyang Xuan * hinic_del_mac - Uninit mac_vlan table in NIC. 159b8582d05SXiaoyun Wang * 160b8582d05SXiaoyun Wang * @param hwdev 161b8582d05SXiaoyun Wang * The hardware interface of a nic device. 162b8582d05SXiaoyun Wang * @param mac_addr 163b8582d05SXiaoyun Wang * MAC address. 164b8582d05SXiaoyun Wang * @param vlan_id 165b8582d05SXiaoyun Wang * Set 0 for mac_vlan table initialization. 166b8582d05SXiaoyun Wang * @param func_id 167b8582d05SXiaoyun Wang * Global function id of NIC. 168b8582d05SXiaoyun Wang * 1692d5fd101SZiyang Xuan * @return 170b8582d05SXiaoyun Wang * 0 on success. 1712d5fd101SZiyang Xuan * negative error value otherwise. 1722d5fd101SZiyang Xuan */ 173b8582d05SXiaoyun Wang int hinic_del_mac(void *hwdev, u8 *mac_addr, u16 vlan_id, u16 func_id) 1742d5fd101SZiyang Xuan { 1752d5fd101SZiyang Xuan struct hinic_port_mac_set mac_info; 1762d5fd101SZiyang Xuan u16 out_size = sizeof(mac_info); 1772d5fd101SZiyang Xuan int err; 1782d5fd101SZiyang Xuan 1792d5fd101SZiyang Xuan if (!hwdev || !mac_addr) { 1802d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL"); 1812d5fd101SZiyang Xuan return -EINVAL; 1822d5fd101SZiyang Xuan } 1832d5fd101SZiyang Xuan 1842d5fd101SZiyang Xuan if (vlan_id >= VLAN_N_VID) { 1852d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Invalid VLAN number"); 1862d5fd101SZiyang Xuan return -EINVAL; 1872d5fd101SZiyang Xuan } 1882d5fd101SZiyang Xuan 1892d5fd101SZiyang Xuan memset(&mac_info, 0, sizeof(mac_info)); 1902d5fd101SZiyang Xuan mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1912d5fd101SZiyang Xuan mac_info.func_id = func_id; 1922d5fd101SZiyang Xuan mac_info.vlan_id = vlan_id; 1932d5fd101SZiyang Xuan memmove(mac_info.mac, mac_addr, ETH_ALEN); 1942d5fd101SZiyang Xuan 1952d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_DEL_MAC, &mac_info, 1962d5fd101SZiyang Xuan sizeof(mac_info), &mac_info, &out_size); 1972d5fd101SZiyang Xuan if (err || !out_size || (mac_info.mgmt_msg_head.status && 1982d5fd101SZiyang Xuan mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) { 1992d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to delete MAC, err: %d, status: 0x%x, out size: 0x%x", 2002d5fd101SZiyang Xuan err, mac_info.mgmt_msg_head.status, out_size); 2012ae8e130SXiaoyun Wang return -EIO; 2022d5fd101SZiyang Xuan } 2032d5fd101SZiyang Xuan if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) { 2042d5fd101SZiyang Xuan PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore delete operation."); 2052d5fd101SZiyang Xuan return HINIC_PF_SET_VF_ALREADY; 2062d5fd101SZiyang Xuan } 2072d5fd101SZiyang Xuan 2082d5fd101SZiyang Xuan return 0; 2092d5fd101SZiyang Xuan } 2102d5fd101SZiyang Xuan 211b8582d05SXiaoyun Wang /** 212b8582d05SXiaoyun Wang * hinic_get_default_mac - Get default mac address from hardware. 213b8582d05SXiaoyun Wang * 214b8582d05SXiaoyun Wang * @param hwdev 215b8582d05SXiaoyun Wang * The hardware interface of a nic device. 216b8582d05SXiaoyun Wang * @param mac_addr 217b8582d05SXiaoyun Wang * MAC address. 218b8582d05SXiaoyun Wang * 219b8582d05SXiaoyun Wang * @return 220b8582d05SXiaoyun Wang * 0 on success. 221b8582d05SXiaoyun Wang * negative error value otherwise. 222b8582d05SXiaoyun Wang */ 2232d5fd101SZiyang Xuan int hinic_get_default_mac(void *hwdev, u8 *mac_addr) 2242d5fd101SZiyang Xuan { 2252d5fd101SZiyang Xuan struct hinic_port_mac_set mac_info; 2262d5fd101SZiyang Xuan u16 out_size = sizeof(mac_info); 2272d5fd101SZiyang Xuan int err; 2282d5fd101SZiyang Xuan 2292d5fd101SZiyang Xuan if (!hwdev || !mac_addr) { 2302d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or mac_addr is NULL"); 2312d5fd101SZiyang Xuan return -EINVAL; 2322d5fd101SZiyang Xuan } 2332d5fd101SZiyang Xuan 2342d5fd101SZiyang Xuan memset(&mac_info, 0, sizeof(mac_info)); 2352d5fd101SZiyang Xuan mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 2362d5fd101SZiyang Xuan mac_info.func_id = hinic_global_func_id(hwdev); 2372d5fd101SZiyang Xuan 2382d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MAC, 2392d5fd101SZiyang Xuan &mac_info, sizeof(mac_info), 2402d5fd101SZiyang Xuan &mac_info, &out_size); 2412d5fd101SZiyang Xuan if (err || !out_size || mac_info.mgmt_msg_head.status) { 2422d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to get mac, err: %d, status: 0x%x, out size: 0x%x", 2432d5fd101SZiyang Xuan err, mac_info.mgmt_msg_head.status, out_size); 2442ae8e130SXiaoyun Wang return -EIO; 2452d5fd101SZiyang Xuan } 2462d5fd101SZiyang Xuan 2472d5fd101SZiyang Xuan memmove(mac_addr, mac_info.mac, ETH_ALEN); 2482d5fd101SZiyang Xuan 2492d5fd101SZiyang Xuan return 0; 2502d5fd101SZiyang Xuan } 2512d5fd101SZiyang Xuan 252b8582d05SXiaoyun Wang /** 25300499a22SXiaoyun Wang * hinic_update_mac - Update mac address to hardware. 25400499a22SXiaoyun Wang * 25500499a22SXiaoyun Wang * @param hwdev 25600499a22SXiaoyun Wang * The hardware interface of a nic device. 25700499a22SXiaoyun Wang * @param old_mac 25800499a22SXiaoyun Wang * Old mac address. 25900499a22SXiaoyun Wang * @param new_mac 26000499a22SXiaoyun Wang * New mac address. 26100499a22SXiaoyun Wang * @param vlan_id 26200499a22SXiaoyun Wang * Set 0 for mac_vlan table initialization. 26300499a22SXiaoyun Wang * @param func_id 26400499a22SXiaoyun Wang * Global function id of NIC. 26500499a22SXiaoyun Wang * 26600499a22SXiaoyun Wang * @return 26700499a22SXiaoyun Wang * 0 on success. 26800499a22SXiaoyun Wang * negative error value otherwise. 26900499a22SXiaoyun Wang */ 27000499a22SXiaoyun Wang int hinic_update_mac(void *hwdev, u8 *old_mac, u8 *new_mac, u16 vlan_id, 27100499a22SXiaoyun Wang u16 func_id) 27200499a22SXiaoyun Wang { 27300499a22SXiaoyun Wang struct hinic_port_mac_update mac_info; 27400499a22SXiaoyun Wang u16 out_size = sizeof(mac_info); 27500499a22SXiaoyun Wang int err; 27600499a22SXiaoyun Wang 27700499a22SXiaoyun Wang if (!hwdev || !old_mac || !new_mac) { 2784f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev, old_mac or new_mac is NULL"); 27900499a22SXiaoyun Wang return -EINVAL; 28000499a22SXiaoyun Wang } 28100499a22SXiaoyun Wang 28200499a22SXiaoyun Wang memset(&mac_info, 0, sizeof(mac_info)); 28300499a22SXiaoyun Wang mac_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 28400499a22SXiaoyun Wang mac_info.func_id = func_id; 28500499a22SXiaoyun Wang mac_info.vlan_id = vlan_id; 28600499a22SXiaoyun Wang memcpy(mac_info.old_mac, old_mac, ETH_ALEN); 28700499a22SXiaoyun Wang memcpy(mac_info.new_mac, new_mac, ETH_ALEN); 28800499a22SXiaoyun Wang 28900499a22SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UPDATE_MAC, 29000499a22SXiaoyun Wang &mac_info, sizeof(mac_info), 29100499a22SXiaoyun Wang &mac_info, &out_size); 29200499a22SXiaoyun Wang if (err || !out_size || 29300499a22SXiaoyun Wang (mac_info.mgmt_msg_head.status && 29400499a22SXiaoyun Wang mac_info.mgmt_msg_head.status != HINIC_PF_SET_VF_ALREADY)) { 2954f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x", 29600499a22SXiaoyun Wang err, mac_info.mgmt_msg_head.status, out_size); 2972ae8e130SXiaoyun Wang return -EIO; 29800499a22SXiaoyun Wang } 29900499a22SXiaoyun Wang if (mac_info.mgmt_msg_head.status == HINIC_PF_SET_VF_ALREADY) { 3004f1af3cbSXiaoyun Wang PMD_DRV_LOG(WARNING, "PF has already set vf mac, Ignore update operation"); 30100499a22SXiaoyun Wang return HINIC_PF_SET_VF_ALREADY; 30200499a22SXiaoyun Wang } 30300499a22SXiaoyun Wang 30400499a22SXiaoyun Wang return 0; 30500499a22SXiaoyun Wang } 30600499a22SXiaoyun Wang 30700499a22SXiaoyun Wang /** 308b8582d05SXiaoyun Wang * hinic_set_port_mtu - Set MTU to port. 309b8582d05SXiaoyun Wang * 310b8582d05SXiaoyun Wang * @param hwdev 311b8582d05SXiaoyun Wang * The hardware interface of a nic device. 312b8582d05SXiaoyun Wang * @param new_mtu 313b8582d05SXiaoyun Wang * MTU size. 314b8582d05SXiaoyun Wang * 315b8582d05SXiaoyun Wang * @return 316b8582d05SXiaoyun Wang * 0 on success. 317b8582d05SXiaoyun Wang * negative error value otherwise. 318b8582d05SXiaoyun Wang */ 3192d5fd101SZiyang Xuan int hinic_set_port_mtu(void *hwdev, u32 new_mtu) 3202d5fd101SZiyang Xuan { 3212d5fd101SZiyang Xuan struct hinic_mtu mtu_info; 3222d5fd101SZiyang Xuan u16 out_size = sizeof(mtu_info); 3232d5fd101SZiyang Xuan int err; 3242d5fd101SZiyang Xuan 3252d5fd101SZiyang Xuan if (!hwdev) { 3262d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 3272d5fd101SZiyang Xuan return -EINVAL; 3282d5fd101SZiyang Xuan } 3292d5fd101SZiyang Xuan 3302d5fd101SZiyang Xuan memset(&mtu_info, 0, sizeof(mtu_info)); 3312d5fd101SZiyang Xuan mtu_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 3322d5fd101SZiyang Xuan mtu_info.func_id = hinic_global_func_id(hwdev); 3332d5fd101SZiyang Xuan mtu_info.mtu = new_mtu; 3342d5fd101SZiyang Xuan 3352d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CHANGE_MTU, 3362d5fd101SZiyang Xuan &mtu_info, sizeof(mtu_info), 3372d5fd101SZiyang Xuan &mtu_info, &out_size); 3382d5fd101SZiyang Xuan if (err || !out_size || mtu_info.mgmt_msg_head.status) { 3392d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set mtu, err: %d, status: 0x%x, out size: 0x%x", 3402d5fd101SZiyang Xuan err, mtu_info.mgmt_msg_head.status, out_size); 3412ae8e130SXiaoyun Wang return -EIO; 3422d5fd101SZiyang Xuan } 3432d5fd101SZiyang Xuan 3442d5fd101SZiyang Xuan return 0; 3452d5fd101SZiyang Xuan } 3462d5fd101SZiyang Xuan 347b8582d05SXiaoyun Wang /** 348fdba3bf1SXiaoyun Wang * hinic_add_remove_vlan - Add or remove vlan id to vlan elb table. 349fdba3bf1SXiaoyun Wang * 350fdba3bf1SXiaoyun Wang * @param hwdev 351fdba3bf1SXiaoyun Wang * The hardware interface of a nic device. 352fdba3bf1SXiaoyun Wang * @param vlan_id 353fdba3bf1SXiaoyun Wang * Vlan id. 354fdba3bf1SXiaoyun Wang * @param func_id 355fdba3bf1SXiaoyun Wang * Global function id of NIC. 356fdba3bf1SXiaoyun Wang * @param add 357fdba3bf1SXiaoyun Wang * Add or remove operation. 358fdba3bf1SXiaoyun Wang * 359fdba3bf1SXiaoyun Wang * @return 360fdba3bf1SXiaoyun Wang * 0 on success. 361fdba3bf1SXiaoyun Wang * negative error value otherwise. 362fdba3bf1SXiaoyun Wang */ 363fdba3bf1SXiaoyun Wang int hinic_add_remove_vlan(void *hwdev, u16 vlan_id, u16 func_id, bool add) 364fdba3bf1SXiaoyun Wang { 365fdba3bf1SXiaoyun Wang struct hinic_vlan_config vlan_info; 366fdba3bf1SXiaoyun Wang u16 out_size = sizeof(vlan_info); 367fdba3bf1SXiaoyun Wang u8 cmd; 368fdba3bf1SXiaoyun Wang int err; 369fdba3bf1SXiaoyun Wang 370fdba3bf1SXiaoyun Wang if (!hwdev) { 371fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev is NULL"); 372fdba3bf1SXiaoyun Wang return -EINVAL; 373fdba3bf1SXiaoyun Wang } 374fdba3bf1SXiaoyun Wang 375fdba3bf1SXiaoyun Wang cmd = add ? HINIC_PORT_CMD_ADD_VLAN : HINIC_PORT_CMD_DEL_VLAN; 376fdba3bf1SXiaoyun Wang 377fdba3bf1SXiaoyun Wang memset(&vlan_info, 0, sizeof(vlan_info)); 378fdba3bf1SXiaoyun Wang vlan_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 379fdba3bf1SXiaoyun Wang vlan_info.func_id = func_id; 380fdba3bf1SXiaoyun Wang vlan_info.vlan_id = vlan_id; 381fdba3bf1SXiaoyun Wang 382d807dd7dSXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, cmd, &vlan_info, sizeof(vlan_info), 383d807dd7dSXiaoyun Wang &vlan_info, &out_size); 384fdba3bf1SXiaoyun Wang if (err || !out_size || vlan_info.mgmt_msg_head.status) { 385fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, 3864f1af3cbSXiaoyun Wang "Failed to %s vlan, err: %d, status: 0x%x, out size: 0x%x", 387fdba3bf1SXiaoyun Wang add ? "add" : "remove", err, 388fdba3bf1SXiaoyun Wang vlan_info.mgmt_msg_head.status, out_size); 3892ae8e130SXiaoyun Wang return -EIO; 390fdba3bf1SXiaoyun Wang } 391fdba3bf1SXiaoyun Wang 392fdba3bf1SXiaoyun Wang return 0; 393fdba3bf1SXiaoyun Wang } 394fdba3bf1SXiaoyun Wang 395fdba3bf1SXiaoyun Wang /** 396fdba3bf1SXiaoyun Wang * hinic_config_vlan_filter - Enable or Disable vlan filter. 397fdba3bf1SXiaoyun Wang * 398fdba3bf1SXiaoyun Wang * @param hwdev 399fdba3bf1SXiaoyun Wang * The hardware interface of a nic device. 400fdba3bf1SXiaoyun Wang * @param vlan_filter_ctrl 401fdba3bf1SXiaoyun Wang * Enable or Disable. 402fdba3bf1SXiaoyun Wang * 403fdba3bf1SXiaoyun Wang * @return 404fdba3bf1SXiaoyun Wang * 0 on success. 405fdba3bf1SXiaoyun Wang * negative error value otherwise. 406fdba3bf1SXiaoyun Wang */ 407fdba3bf1SXiaoyun Wang int hinic_config_vlan_filter(void *hwdev, u32 vlan_filter_ctrl) 408fdba3bf1SXiaoyun Wang { 409fdba3bf1SXiaoyun Wang struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev; 410fdba3bf1SXiaoyun Wang struct hinic_vlan_filter vlan_filter; 411fdba3bf1SXiaoyun Wang u16 out_size = sizeof(vlan_filter); 412fdba3bf1SXiaoyun Wang int err; 413fdba3bf1SXiaoyun Wang 414fdba3bf1SXiaoyun Wang if (!hwdev) 415fdba3bf1SXiaoyun Wang return -EINVAL; 416fdba3bf1SXiaoyun Wang 417fdba3bf1SXiaoyun Wang memset(&vlan_filter, 0, sizeof(vlan_filter)); 418fdba3bf1SXiaoyun Wang vlan_filter.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 419fdba3bf1SXiaoyun Wang vlan_filter.func_id = hinic_global_func_id(nic_hwdev); 420fdba3bf1SXiaoyun Wang vlan_filter.vlan_filter_ctrl = vlan_filter_ctrl; 421fdba3bf1SXiaoyun Wang 422fdba3bf1SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(nic_hwdev, HINIC_PORT_CMD_SET_VLAN_FILTER, 423fdba3bf1SXiaoyun Wang &vlan_filter, sizeof(vlan_filter), 424fdba3bf1SXiaoyun Wang &vlan_filter, &out_size); 425fdba3bf1SXiaoyun Wang if (vlan_filter.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) { 426fdba3bf1SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 427fdba3bf1SXiaoyun Wang } else if ((err == HINIC_MBOX_VF_CMD_ERROR) && 428fdba3bf1SXiaoyun Wang (HINIC_IS_VF(nic_hwdev))) { 429fdba3bf1SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 430fdba3bf1SXiaoyun Wang } else if (err || !out_size || vlan_filter.mgmt_msg_head.status) { 431fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, 4324f1af3cbSXiaoyun Wang "Failed to config vlan filter, vlan_filter_ctrl: 0x%x, err: %d, status: 0x%x, out size: 0x%x", 433fdba3bf1SXiaoyun Wang vlan_filter_ctrl, err, 434fdba3bf1SXiaoyun Wang vlan_filter.mgmt_msg_head.status, out_size); 4352ae8e130SXiaoyun Wang err = -EIO; 436fdba3bf1SXiaoyun Wang } 437fdba3bf1SXiaoyun Wang 438fdba3bf1SXiaoyun Wang return err; 439fdba3bf1SXiaoyun Wang } 440fdba3bf1SXiaoyun Wang 441fdba3bf1SXiaoyun Wang /** 442fdba3bf1SXiaoyun Wang * hinic_set_rx_vlan_offload - Enable or Disable vlan offload. 443fdba3bf1SXiaoyun Wang * 444fdba3bf1SXiaoyun Wang * @param hwdev 445fdba3bf1SXiaoyun Wang * The hardware interface of a nic device. 446fdba3bf1SXiaoyun Wang * @param en 447fdba3bf1SXiaoyun Wang * Enable or Disable. 448fdba3bf1SXiaoyun Wang * 449fdba3bf1SXiaoyun Wang * @return 450fdba3bf1SXiaoyun Wang * 0 on success. 451fdba3bf1SXiaoyun Wang * negative error value otherwise. 452fdba3bf1SXiaoyun Wang */ 453fdba3bf1SXiaoyun Wang int hinic_set_rx_vlan_offload(void *hwdev, u8 en) 454fdba3bf1SXiaoyun Wang { 455fdba3bf1SXiaoyun Wang struct hinic_vlan_offload vlan_cfg; 456fdba3bf1SXiaoyun Wang u16 out_size = sizeof(vlan_cfg); 457fdba3bf1SXiaoyun Wang int err; 458fdba3bf1SXiaoyun Wang 459fdba3bf1SXiaoyun Wang if (!hwdev) { 460fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev is NULL"); 461fdba3bf1SXiaoyun Wang return -EINVAL; 462fdba3bf1SXiaoyun Wang } 463fdba3bf1SXiaoyun Wang 464fdba3bf1SXiaoyun Wang memset(&vlan_cfg, 0, sizeof(vlan_cfg)); 465fdba3bf1SXiaoyun Wang vlan_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 466fdba3bf1SXiaoyun Wang vlan_cfg.func_id = hinic_global_func_id(hwdev); 467fdba3bf1SXiaoyun Wang vlan_cfg.vlan_rx_offload = en; 468fdba3bf1SXiaoyun Wang 469fdba3bf1SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD, 470fdba3bf1SXiaoyun Wang &vlan_cfg, sizeof(vlan_cfg), 471fdba3bf1SXiaoyun Wang &vlan_cfg, &out_size); 472fdba3bf1SXiaoyun Wang if (err || !out_size || vlan_cfg.mgmt_msg_head.status) { 473fdba3bf1SXiaoyun Wang PMD_DRV_LOG(ERR, 4744f1af3cbSXiaoyun Wang "Failed to set rx vlan offload, err: %d, status: 0x%x, out size: 0x%x", 475fdba3bf1SXiaoyun Wang err, vlan_cfg.mgmt_msg_head.status, out_size); 4762ae8e130SXiaoyun Wang return -EIO; 477fdba3bf1SXiaoyun Wang } 478fdba3bf1SXiaoyun Wang 479fdba3bf1SXiaoyun Wang return 0; 480fdba3bf1SXiaoyun Wang } 481fdba3bf1SXiaoyun Wang 482fdba3bf1SXiaoyun Wang /** 483b8582d05SXiaoyun Wang * hinic_get_link_status - Get link status from hardware. 484b8582d05SXiaoyun Wang * 485b8582d05SXiaoyun Wang * @param hwdev 486b8582d05SXiaoyun Wang * The hardware interface of a nic device. 487b8582d05SXiaoyun Wang * @param link_state 488b8582d05SXiaoyun Wang * Link status. 489b8582d05SXiaoyun Wang * 490b8582d05SXiaoyun Wang * @return 491b8582d05SXiaoyun Wang * 0 on success. 492b8582d05SXiaoyun Wang * negative error value otherwise. 493b8582d05SXiaoyun Wang */ 4942d5fd101SZiyang Xuan int hinic_get_link_status(void *hwdev, u8 *link_state) 4952d5fd101SZiyang Xuan { 4962d5fd101SZiyang Xuan struct hinic_get_link get_link; 4972d5fd101SZiyang Xuan u16 out_size = sizeof(get_link); 4982d5fd101SZiyang Xuan int err; 4992d5fd101SZiyang Xuan 5002d5fd101SZiyang Xuan if (!hwdev || !link_state) { 5012d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or link_state is NULL"); 5022d5fd101SZiyang Xuan return -EINVAL; 5032d5fd101SZiyang Xuan } 5042d5fd101SZiyang Xuan 5052d5fd101SZiyang Xuan memset(&get_link, 0, sizeof(get_link)); 5062d5fd101SZiyang Xuan get_link.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 5072d5fd101SZiyang Xuan get_link.func_id = hinic_global_func_id(hwdev); 5082d5fd101SZiyang Xuan 5092d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_STATE, 5102d5fd101SZiyang Xuan &get_link, sizeof(get_link), 5112d5fd101SZiyang Xuan &get_link, &out_size); 5122d5fd101SZiyang Xuan if (err || !out_size || get_link.mgmt_msg_head.status) { 5132d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to get link state, err: %d, status: 0x%x, out size: 0x%x", 5142d5fd101SZiyang Xuan err, get_link.mgmt_msg_head.status, out_size); 5152ae8e130SXiaoyun Wang return -EIO; 5162d5fd101SZiyang Xuan } 5172d5fd101SZiyang Xuan 5182d5fd101SZiyang Xuan *link_state = get_link.link_status; 5192d5fd101SZiyang Xuan 5202d5fd101SZiyang Xuan return 0; 5212d5fd101SZiyang Xuan } 5222d5fd101SZiyang Xuan 5232d5fd101SZiyang Xuan /** 5242d5fd101SZiyang Xuan * hinic_set_vport_enable - Notify firmware that driver is ready or not. 525b8582d05SXiaoyun Wang * 526b8582d05SXiaoyun Wang * @param hwdev 527b8582d05SXiaoyun Wang * The hardware interface of a nic device. 528b8582d05SXiaoyun Wang * @param enable 529b8582d05SXiaoyun Wang * 1: driver is ready; 0: driver is not ok. 530b8582d05SXiaoyun Wang * 531b8582d05SXiaoyun Wang * @return 532b8582d05SXiaoyun Wang * 0 on success. 533b8582d05SXiaoyun Wang * negative error value otherwise. 534b8582d05SXiaoyun Wang */ 5352d5fd101SZiyang Xuan int hinic_set_vport_enable(void *hwdev, bool enable) 5362d5fd101SZiyang Xuan { 5372d5fd101SZiyang Xuan struct hinic_vport_state en_state; 5382d5fd101SZiyang Xuan u16 out_size = sizeof(en_state); 5392d5fd101SZiyang Xuan int err; 5402d5fd101SZiyang Xuan 5412d5fd101SZiyang Xuan if (!hwdev) { 5422d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 5432d5fd101SZiyang Xuan return -EINVAL; 5442d5fd101SZiyang Xuan } 5452d5fd101SZiyang Xuan 5462d5fd101SZiyang Xuan memset(&en_state, 0, sizeof(en_state)); 5472d5fd101SZiyang Xuan en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 5482d5fd101SZiyang Xuan en_state.func_id = hinic_global_func_id(hwdev); 5492d5fd101SZiyang Xuan en_state.state = (enable ? 1 : 0); 5502d5fd101SZiyang Xuan 5512d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VPORT_ENABLE, 5522d5fd101SZiyang Xuan &en_state, sizeof(en_state), 5532d5fd101SZiyang Xuan &en_state, &out_size); 5542d5fd101SZiyang Xuan if (err || !out_size || en_state.mgmt_msg_head.status) { 5552d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set vport state, err: %d, status: 0x%x, out size: 0x%x", 5562d5fd101SZiyang Xuan err, en_state.mgmt_msg_head.status, out_size); 5572ae8e130SXiaoyun Wang return -EIO; 5582d5fd101SZiyang Xuan } 5592d5fd101SZiyang Xuan 5602d5fd101SZiyang Xuan return 0; 5612d5fd101SZiyang Xuan } 5622d5fd101SZiyang Xuan 5632d5fd101SZiyang Xuan /** 564b8582d05SXiaoyun Wang * hinic_set_port_enable - Open MAG to receive packets. 565b8582d05SXiaoyun Wang * 566b8582d05SXiaoyun Wang * @param hwdev 567b8582d05SXiaoyun Wang * The hardware interface of a nic device. 568b8582d05SXiaoyun Wang * @param enable 569b8582d05SXiaoyun Wang * 1: open MAG; 0: close MAG. 570b8582d05SXiaoyun Wang * 5712d5fd101SZiyang Xuan * @return 572b8582d05SXiaoyun Wang * 0 on success. 5732d5fd101SZiyang Xuan * negative error value otherwise. 5742d5fd101SZiyang Xuan */ 5752d5fd101SZiyang Xuan int hinic_set_port_enable(void *hwdev, bool enable) 5762d5fd101SZiyang Xuan { 5772d5fd101SZiyang Xuan struct hinic_port_state en_state; 5782d5fd101SZiyang Xuan u16 out_size = sizeof(en_state); 5792d5fd101SZiyang Xuan int err; 5802d5fd101SZiyang Xuan 5812d5fd101SZiyang Xuan if (!hwdev) { 5822d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 5832d5fd101SZiyang Xuan return -EINVAL; 5842d5fd101SZiyang Xuan } 5852d5fd101SZiyang Xuan 586b8582d05SXiaoyun Wang if (HINIC_IS_VF((struct hinic_hwdev *)hwdev)) 587b8582d05SXiaoyun Wang return 0; 588b8582d05SXiaoyun Wang 5892d5fd101SZiyang Xuan memset(&en_state, 0, sizeof(en_state)); 5902d5fd101SZiyang Xuan en_state.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 5912d5fd101SZiyang Xuan en_state.state = (enable ? HINIC_PORT_ENABLE : HINIC_PORT_DISABLE); 5922d5fd101SZiyang Xuan 5932d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PORT_ENABLE, 5942d5fd101SZiyang Xuan &en_state, sizeof(en_state), 5952d5fd101SZiyang Xuan &en_state, &out_size); 5962d5fd101SZiyang Xuan if (err || !out_size || en_state.mgmt_msg_head.status) { 5972d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set phy port state, err: %d, status: 0x%x, out size: 0x%x", 5982d5fd101SZiyang Xuan err, en_state.mgmt_msg_head.status, out_size); 5992ae8e130SXiaoyun Wang return -EIO; 6002d5fd101SZiyang Xuan } 6012d5fd101SZiyang Xuan 6022d5fd101SZiyang Xuan return 0; 6032d5fd101SZiyang Xuan } 6042d5fd101SZiyang Xuan 6052d5fd101SZiyang Xuan int hinic_get_port_info(void *hwdev, struct nic_port_info *port_info) 6062d5fd101SZiyang Xuan { 6072d5fd101SZiyang Xuan struct hinic_port_info port_msg; 6082d5fd101SZiyang Xuan u16 out_size = sizeof(port_msg); 6092d5fd101SZiyang Xuan int err; 6102d5fd101SZiyang Xuan 6112d5fd101SZiyang Xuan if (!hwdev || !port_info) { 6122d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or port_info is NULL"); 6132d5fd101SZiyang Xuan return -EINVAL; 6142d5fd101SZiyang Xuan } 6152d5fd101SZiyang Xuan 6162d5fd101SZiyang Xuan memset(&port_msg, 0, sizeof(port_msg)); 6172d5fd101SZiyang Xuan port_msg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 6182d5fd101SZiyang Xuan port_msg.func_id = hinic_global_func_id(hwdev); 6192d5fd101SZiyang Xuan 6202d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_INFO, 6212d5fd101SZiyang Xuan &port_msg, sizeof(port_msg), 6222d5fd101SZiyang Xuan &port_msg, &out_size); 6232d5fd101SZiyang Xuan if (err || !out_size || port_msg.mgmt_msg_head.status) { 6242d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 6252d5fd101SZiyang Xuan "Failed to get port info, err: %d, status: 0x%x, out size: 0x%x", 6262d5fd101SZiyang Xuan err, port_msg.mgmt_msg_head.status, out_size); 627d807dd7dSXiaoyun Wang return -EIO; 6282d5fd101SZiyang Xuan } 6292d5fd101SZiyang Xuan 6302d5fd101SZiyang Xuan port_info->autoneg_cap = port_msg.autoneg_cap; 6312d5fd101SZiyang Xuan port_info->autoneg_state = port_msg.autoneg_state; 6322d5fd101SZiyang Xuan port_info->duplex = port_msg.duplex; 6332d5fd101SZiyang Xuan port_info->port_type = port_msg.port_type; 6342d5fd101SZiyang Xuan port_info->speed = port_msg.speed; 6352d5fd101SZiyang Xuan 6362d5fd101SZiyang Xuan return 0; 6372d5fd101SZiyang Xuan } 6382d5fd101SZiyang Xuan 6392d5fd101SZiyang Xuan int hinic_set_pause_config(void *hwdev, struct nic_pause_config nic_pause) 6402d5fd101SZiyang Xuan { 6412d5fd101SZiyang Xuan struct hinic_pause_config pause_info; 6422d5fd101SZiyang Xuan u16 out_size = sizeof(pause_info); 6432d5fd101SZiyang Xuan int err; 6442d5fd101SZiyang Xuan 6452d5fd101SZiyang Xuan if (!hwdev) { 6462d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 6472d5fd101SZiyang Xuan return -EINVAL; 6482d5fd101SZiyang Xuan } 6492d5fd101SZiyang Xuan 6502d5fd101SZiyang Xuan memset(&pause_info, 0, sizeof(pause_info)); 6512d5fd101SZiyang Xuan pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 6522d5fd101SZiyang Xuan pause_info.func_id = hinic_global_func_id(hwdev); 6532d5fd101SZiyang Xuan pause_info.auto_neg = nic_pause.auto_neg; 6542d5fd101SZiyang Xuan pause_info.rx_pause = nic_pause.rx_pause; 6552d5fd101SZiyang Xuan pause_info.tx_pause = nic_pause.tx_pause; 6562d5fd101SZiyang Xuan 6572d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_PAUSE_INFO, 6582d5fd101SZiyang Xuan &pause_info, sizeof(pause_info), 6592d5fd101SZiyang Xuan &pause_info, &out_size); 6602d5fd101SZiyang Xuan if (err || !out_size || pause_info.mgmt_msg_head.status) { 6612d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set pause info, err: %d, status: 0x%x, out size: 0x%x", 6622d5fd101SZiyang Xuan err, pause_info.mgmt_msg_head.status, out_size); 6632ae8e130SXiaoyun Wang return -EIO; 6642d5fd101SZiyang Xuan } 6652d5fd101SZiyang Xuan 6662d5fd101SZiyang Xuan return 0; 6672d5fd101SZiyang Xuan } 6682d5fd101SZiyang Xuan 669ef6f2f5cSXiaoyun Wang int hinic_get_pause_info(void *hwdev, struct nic_pause_config *nic_pause) 670ef6f2f5cSXiaoyun Wang { 671ef6f2f5cSXiaoyun Wang struct hinic_pause_config pause_info; 672ef6f2f5cSXiaoyun Wang u16 out_size = sizeof(pause_info); 673ef6f2f5cSXiaoyun Wang int err; 674ef6f2f5cSXiaoyun Wang 675ef6f2f5cSXiaoyun Wang if (!hwdev || !nic_pause) 676ef6f2f5cSXiaoyun Wang return -EINVAL; 677ef6f2f5cSXiaoyun Wang 678ef6f2f5cSXiaoyun Wang memset(&pause_info, 0, sizeof(pause_info)); 679ef6f2f5cSXiaoyun Wang pause_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 680ef6f2f5cSXiaoyun Wang pause_info.func_id = hinic_global_func_id(hwdev); 681ef6f2f5cSXiaoyun Wang 682ef6f2f5cSXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PAUSE_INFO, 683ef6f2f5cSXiaoyun Wang &pause_info, sizeof(pause_info), 684ef6f2f5cSXiaoyun Wang &pause_info, &out_size); 685ef6f2f5cSXiaoyun Wang if (err || !out_size || pause_info.mgmt_msg_head.status) { 686*f665790aSDavid Marchand PMD_DRV_LOG(ERR, "Failed to get pause info, err: %d, status: 0x%x, out size: 0x%x", 687ef6f2f5cSXiaoyun Wang err, pause_info.mgmt_msg_head.status, out_size); 6882ae8e130SXiaoyun Wang return -EIO; 689ef6f2f5cSXiaoyun Wang } 690ef6f2f5cSXiaoyun Wang 691ef6f2f5cSXiaoyun Wang nic_pause->auto_neg = pause_info.auto_neg; 692ef6f2f5cSXiaoyun Wang nic_pause->rx_pause = pause_info.rx_pause; 693ef6f2f5cSXiaoyun Wang nic_pause->tx_pause = pause_info.tx_pause; 694ef6f2f5cSXiaoyun Wang 695ef6f2f5cSXiaoyun Wang return 0; 696ef6f2f5cSXiaoyun Wang } 697ef6f2f5cSXiaoyun Wang 6982d5fd101SZiyang Xuan int hinic_dcb_set_ets(void *hwdev, u8 *up_tc, u8 *pg_bw, 6992d5fd101SZiyang Xuan u8 *pgid, u8 *up_bw, u8 *prio) 7002d5fd101SZiyang Xuan { 7012d5fd101SZiyang Xuan struct hinic_up_ets_cfg ets; 7022d5fd101SZiyang Xuan u16 out_size = sizeof(ets); 7032d5fd101SZiyang Xuan u16 up_bw_t = 0; 7042d5fd101SZiyang Xuan u8 pg_bw_t = 0; 7052d5fd101SZiyang Xuan int i, err; 7062d5fd101SZiyang Xuan 7072d5fd101SZiyang Xuan if (!hwdev || !up_tc || !pg_bw || !pgid || !up_bw || !prio) { 7082d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev, up_tc, pg_bw, pgid, up_bw or prio is NULL"); 7092d5fd101SZiyang Xuan return -EINVAL; 7102d5fd101SZiyang Xuan } 7112d5fd101SZiyang Xuan 7122d5fd101SZiyang Xuan for (i = 0; i < HINIC_DCB_TC_MAX; i++) { 7132d5fd101SZiyang Xuan up_bw_t += *(up_bw + i); 7142d5fd101SZiyang Xuan pg_bw_t += *(pg_bw + i); 7152d5fd101SZiyang Xuan 7162d5fd101SZiyang Xuan if (*(up_tc + i) > HINIC_DCB_TC_MAX) { 7174f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Invalid up %d mapping tc: %d", i, 7182d5fd101SZiyang Xuan *(up_tc + i)); 7192d5fd101SZiyang Xuan return -EINVAL; 7202d5fd101SZiyang Xuan } 7212d5fd101SZiyang Xuan } 7222d5fd101SZiyang Xuan 7232d5fd101SZiyang Xuan if (pg_bw_t != 100 || (up_bw_t % 100) != 0) { 7242d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 7252d5fd101SZiyang Xuan "Invalid pg_bw: %d or up_bw: %d", pg_bw_t, up_bw_t); 7262d5fd101SZiyang Xuan return -EINVAL; 7272d5fd101SZiyang Xuan } 7282d5fd101SZiyang Xuan 7292d5fd101SZiyang Xuan memset(&ets, 0, sizeof(ets)); 7302d5fd101SZiyang Xuan ets.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 7312d5fd101SZiyang Xuan ets.port_id = 0; /* reserved */ 7322d5fd101SZiyang Xuan memcpy(ets.up_tc, up_tc, HINIC_DCB_TC_MAX); 7332d5fd101SZiyang Xuan memcpy(ets.pg_bw, pg_bw, HINIC_DCB_UP_MAX); 7342d5fd101SZiyang Xuan memcpy(ets.pgid, pgid, HINIC_DCB_UP_MAX); 7352d5fd101SZiyang Xuan memcpy(ets.up_bw, up_bw, HINIC_DCB_UP_MAX); 7362d5fd101SZiyang Xuan memcpy(ets.prio, prio, HINIC_DCB_UP_MAX); 7372d5fd101SZiyang Xuan 7382d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ETS, 7392d5fd101SZiyang Xuan &ets, sizeof(ets), &ets, &out_size); 7402d5fd101SZiyang Xuan if (err || ets.mgmt_msg_head.status || !out_size) { 7412d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 7422d5fd101SZiyang Xuan "Failed to set ets, err: %d, status: 0x%x, out size: 0x%x", 7432d5fd101SZiyang Xuan err, ets.mgmt_msg_head.status, out_size); 7442ae8e130SXiaoyun Wang return -EIO; 7452d5fd101SZiyang Xuan } 7462d5fd101SZiyang Xuan 7472d5fd101SZiyang Xuan return 0; 7482d5fd101SZiyang Xuan } 7492d5fd101SZiyang Xuan 7502d5fd101SZiyang Xuan int hinic_get_vport_stats(void *hwdev, struct hinic_vport_stats *stats) 7512d5fd101SZiyang Xuan { 7522d5fd101SZiyang Xuan struct hinic_port_stats_info vport_stats_cmd; 7532d5fd101SZiyang Xuan struct hinic_cmd_vport_stats vport_stats_rsp; 7542d5fd101SZiyang Xuan u16 out_size = sizeof(vport_stats_rsp); 7552d5fd101SZiyang Xuan int err; 7562d5fd101SZiyang Xuan 7572d5fd101SZiyang Xuan if (!hwdev || !stats) { 7582d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or stats is NULL"); 7592d5fd101SZiyang Xuan return -EINVAL; 7602d5fd101SZiyang Xuan } 7612d5fd101SZiyang Xuan 7622d5fd101SZiyang Xuan memset(&vport_stats_rsp, 0, sizeof(vport_stats_rsp)); 7632d5fd101SZiyang Xuan memset(&vport_stats_cmd, 0, sizeof(vport_stats_cmd)); 7642d5fd101SZiyang Xuan vport_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 7652d5fd101SZiyang Xuan vport_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION; 7662d5fd101SZiyang Xuan vport_stats_cmd.func_id = hinic_global_func_id(hwdev); 7672d5fd101SZiyang Xuan vport_stats_cmd.stats_size = sizeof(vport_stats_rsp); 7682d5fd101SZiyang Xuan 7692d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_VPORT_STAT, 7702d5fd101SZiyang Xuan &vport_stats_cmd, sizeof(vport_stats_cmd), 7712d5fd101SZiyang Xuan &vport_stats_rsp, &out_size); 7722d5fd101SZiyang Xuan if (err || !out_size || vport_stats_rsp.mgmt_msg_head.status) { 7732d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 7742d5fd101SZiyang Xuan "Get vport stats from fw failed, err: %d, status: 0x%x, out size: 0x%x", 7752d5fd101SZiyang Xuan err, vport_stats_rsp.mgmt_msg_head.status, out_size); 7762ae8e130SXiaoyun Wang return -EIO; 7772d5fd101SZiyang Xuan } 7782d5fd101SZiyang Xuan 7792d5fd101SZiyang Xuan memcpy(stats, &vport_stats_rsp.stats, sizeof(*stats)); 7802d5fd101SZiyang Xuan 7812d5fd101SZiyang Xuan return 0; 7822d5fd101SZiyang Xuan } 7832d5fd101SZiyang Xuan 7842d5fd101SZiyang Xuan int hinic_get_phy_port_stats(void *hwdev, struct hinic_phy_port_stats *stats) 7852d5fd101SZiyang Xuan { 7862d5fd101SZiyang Xuan struct hinic_port_stats_info port_stats_cmd; 7872d5fd101SZiyang Xuan struct hinic_port_stats port_stats_rsp; 7882d5fd101SZiyang Xuan u16 out_size = sizeof(port_stats_rsp); 7892d5fd101SZiyang Xuan int err; 7902d5fd101SZiyang Xuan 7912d5fd101SZiyang Xuan if (!hwdev || !stats) { 7922d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or stats is NULL"); 7932d5fd101SZiyang Xuan return -EINVAL; 7942d5fd101SZiyang Xuan } 7952d5fd101SZiyang Xuan 7962d5fd101SZiyang Xuan memset(&port_stats_rsp, 0, sizeof(port_stats_rsp)); 7972d5fd101SZiyang Xuan memset(&port_stats_cmd, 0, sizeof(port_stats_cmd)); 7982d5fd101SZiyang Xuan port_stats_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 7992d5fd101SZiyang Xuan port_stats_cmd.stats_version = HINIC_PORT_STATS_VERSION; 8002d5fd101SZiyang Xuan port_stats_cmd.stats_size = sizeof(port_stats_rsp); 8012d5fd101SZiyang Xuan 8022d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_PORT_STATISTICS, 8032d5fd101SZiyang Xuan &port_stats_cmd, sizeof(port_stats_cmd), 8042d5fd101SZiyang Xuan &port_stats_rsp, &out_size); 8052d5fd101SZiyang Xuan if (err || !out_size || port_stats_rsp.mgmt_msg_head.status) { 8062d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 8072d5fd101SZiyang Xuan "Failed to get port statistics, err: %d, status: 0x%x, out size: 0x%x", 8082d5fd101SZiyang Xuan err, port_stats_rsp.mgmt_msg_head.status, out_size); 8092ae8e130SXiaoyun Wang return -EIO; 8102d5fd101SZiyang Xuan } 8112d5fd101SZiyang Xuan 8122d5fd101SZiyang Xuan memcpy(stats, &port_stats_rsp.stats, sizeof(*stats)); 8132d5fd101SZiyang Xuan 8142d5fd101SZiyang Xuan return 0; 8152d5fd101SZiyang Xuan } 8162d5fd101SZiyang Xuan 8172d5fd101SZiyang Xuan int hinic_set_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type rss_type) 8182d5fd101SZiyang Xuan { 8192d5fd101SZiyang Xuan struct nic_rss_context_tbl *ctx_tbl; 8202d5fd101SZiyang Xuan struct hinic_cmd_buf *cmd_buf; 8212d5fd101SZiyang Xuan u32 ctx = 0; 8222d5fd101SZiyang Xuan u64 out_param; 8232d5fd101SZiyang Xuan int err; 8242d5fd101SZiyang Xuan 8252d5fd101SZiyang Xuan if (!hwdev) { 8262d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 8272d5fd101SZiyang Xuan return -EINVAL; 8282d5fd101SZiyang Xuan } 8292d5fd101SZiyang Xuan 8302d5fd101SZiyang Xuan cmd_buf = hinic_alloc_cmd_buf(hwdev); 8312d5fd101SZiyang Xuan if (!cmd_buf) { 8322d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to allocate cmd buf"); 8332d5fd101SZiyang Xuan return -ENOMEM; 8342d5fd101SZiyang Xuan } 8352d5fd101SZiyang Xuan 8362d5fd101SZiyang Xuan ctx |= HINIC_RSS_TYPE_SET(1, VALID) | 8372d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.ipv4, IPV4) | 8382d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.ipv6, IPV6) | 8392d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.ipv6_ext, IPV6_EXT) | 8402d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.tcp_ipv4, TCP_IPV4) | 8412d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6, TCP_IPV6) | 8422d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.tcp_ipv6_ext, TCP_IPV6_EXT) | 8432d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.udp_ipv4, UDP_IPV4) | 8442d5fd101SZiyang Xuan HINIC_RSS_TYPE_SET(rss_type.udp_ipv6, UDP_IPV6); 8452d5fd101SZiyang Xuan 8462d5fd101SZiyang Xuan cmd_buf->size = sizeof(struct nic_rss_context_tbl); 8472d5fd101SZiyang Xuan 8482d5fd101SZiyang Xuan ctx_tbl = (struct nic_rss_context_tbl *)cmd_buf->buf; 8492d5fd101SZiyang Xuan ctx_tbl->group_index = cpu_to_be32(tmpl_idx); 8502d5fd101SZiyang Xuan ctx_tbl->offset = 0; 8512d5fd101SZiyang Xuan ctx_tbl->size = sizeof(u32); 8522d5fd101SZiyang Xuan ctx_tbl->size = cpu_to_be32(ctx_tbl->size); 8532d5fd101SZiyang Xuan ctx_tbl->rsvd = 0; 8542d5fd101SZiyang Xuan ctx_tbl->ctx = cpu_to_be32(ctx); 8552d5fd101SZiyang Xuan 8562d5fd101SZiyang Xuan /* cfg the rss context table by command queue */ 8572d5fd101SZiyang Xuan err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ, 8582d5fd101SZiyang Xuan HINIC_MOD_L2NIC, 8592d5fd101SZiyang Xuan HINIC_UCODE_CMD_SET_RSS_CONTEXT_TABLE, 8602d5fd101SZiyang Xuan cmd_buf, &out_param, 0); 8612d5fd101SZiyang Xuan 8622d5fd101SZiyang Xuan hinic_free_cmd_buf(hwdev, cmd_buf); 8632d5fd101SZiyang Xuan 8642d5fd101SZiyang Xuan if (err || out_param != 0) { 8652d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set rss context table"); 8662ae8e130SXiaoyun Wang return -EIO; 8672d5fd101SZiyang Xuan } 8682d5fd101SZiyang Xuan 8692d5fd101SZiyang Xuan return 0; 8702d5fd101SZiyang Xuan } 8712d5fd101SZiyang Xuan 8722d5fd101SZiyang Xuan int hinic_get_rss_type(void *hwdev, u32 tmpl_idx, struct nic_rss_type *rss_type) 8732d5fd101SZiyang Xuan { 8742d5fd101SZiyang Xuan struct hinic_rss_context_table ctx_tbl; 8752d5fd101SZiyang Xuan u16 out_size = sizeof(ctx_tbl); 8762d5fd101SZiyang Xuan int err; 8772d5fd101SZiyang Xuan 8782d5fd101SZiyang Xuan if (!hwdev || !rss_type) { 8792d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or rss_type is NULL"); 8802d5fd101SZiyang Xuan return -EINVAL; 8812d5fd101SZiyang Xuan } 8822d5fd101SZiyang Xuan 8832d5fd101SZiyang Xuan ctx_tbl.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 8842d5fd101SZiyang Xuan ctx_tbl.func_id = hinic_global_func_id(hwdev); 8852d5fd101SZiyang Xuan ctx_tbl.template_id = (u8)tmpl_idx; 8862d5fd101SZiyang Xuan 8872d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_CTX_TBL, 8882d5fd101SZiyang Xuan &ctx_tbl, sizeof(ctx_tbl), 8892d5fd101SZiyang Xuan &ctx_tbl, &out_size); 8902d5fd101SZiyang Xuan if (err || !out_size || ctx_tbl.mgmt_msg_head.status) { 8912d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 8922d5fd101SZiyang Xuan "Failed to get hash type, err: %d, status: 0x%x, out size: 0x%x", 8932d5fd101SZiyang Xuan err, ctx_tbl.mgmt_msg_head.status, out_size); 8942ae8e130SXiaoyun Wang return -EIO; 8952d5fd101SZiyang Xuan } 8962d5fd101SZiyang Xuan 8972d5fd101SZiyang Xuan rss_type->ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV4); 8982d5fd101SZiyang Xuan rss_type->ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6); 8992d5fd101SZiyang Xuan rss_type->ipv6_ext = HINIC_RSS_TYPE_GET(ctx_tbl.context, IPV6_EXT); 9002d5fd101SZiyang Xuan rss_type->tcp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV4); 9012d5fd101SZiyang Xuan rss_type->tcp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6); 9022d5fd101SZiyang Xuan rss_type->tcp_ipv6_ext = 9032d5fd101SZiyang Xuan HINIC_RSS_TYPE_GET(ctx_tbl.context, TCP_IPV6_EXT); 9042d5fd101SZiyang Xuan rss_type->udp_ipv4 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV4); 9052d5fd101SZiyang Xuan rss_type->udp_ipv6 = HINIC_RSS_TYPE_GET(ctx_tbl.context, UDP_IPV6); 9062d5fd101SZiyang Xuan 9072d5fd101SZiyang Xuan return 0; 9082d5fd101SZiyang Xuan } 9092d5fd101SZiyang Xuan 9102d5fd101SZiyang Xuan int hinic_rss_set_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp) 9112d5fd101SZiyang Xuan { 9122d5fd101SZiyang Xuan struct hinic_rss_template_key temp_key; 9132d5fd101SZiyang Xuan u16 out_size = sizeof(temp_key); 9142d5fd101SZiyang Xuan int err; 9152d5fd101SZiyang Xuan 9162d5fd101SZiyang Xuan if (!hwdev || !temp) { 9172d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or temp is NULL"); 9182d5fd101SZiyang Xuan return -EINVAL; 9192d5fd101SZiyang Xuan } 9202d5fd101SZiyang Xuan 9212d5fd101SZiyang Xuan memset(&temp_key, 0, sizeof(temp_key)); 9222d5fd101SZiyang Xuan temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 9232d5fd101SZiyang Xuan temp_key.func_id = hinic_global_func_id(hwdev); 9242d5fd101SZiyang Xuan temp_key.template_id = (u8)tmpl_idx; 9252d5fd101SZiyang Xuan memcpy(temp_key.key, temp, HINIC_RSS_KEY_SIZE); 9262d5fd101SZiyang Xuan 9272d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL, 9282d5fd101SZiyang Xuan &temp_key, sizeof(temp_key), 9292d5fd101SZiyang Xuan &temp_key, &out_size); 9302d5fd101SZiyang Xuan if (err || !out_size || temp_key.mgmt_msg_head.status) { 9312d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 9322d5fd101SZiyang Xuan "Failed to set hash key, err: %d, status: 0x%x, out size: 0x%x", 9332d5fd101SZiyang Xuan err, temp_key.mgmt_msg_head.status, out_size); 9342ae8e130SXiaoyun Wang return -EIO; 9352d5fd101SZiyang Xuan } 9362d5fd101SZiyang Xuan 9372d5fd101SZiyang Xuan return 0; 9382d5fd101SZiyang Xuan } 9392d5fd101SZiyang Xuan 9402d5fd101SZiyang Xuan int hinic_rss_get_template_tbl(void *hwdev, u32 tmpl_idx, u8 *temp) 9412d5fd101SZiyang Xuan { 9422d5fd101SZiyang Xuan struct hinic_rss_template_key temp_key; 9432d5fd101SZiyang Xuan u16 out_size = sizeof(temp_key); 9442d5fd101SZiyang Xuan int err; 9452d5fd101SZiyang Xuan 9462d5fd101SZiyang Xuan if (!hwdev || !temp) { 9472d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or temp is NULL"); 9482d5fd101SZiyang Xuan return -EINVAL; 9492d5fd101SZiyang Xuan } 9502d5fd101SZiyang Xuan 9512d5fd101SZiyang Xuan memset(&temp_key, 0, sizeof(temp_key)); 9522d5fd101SZiyang Xuan temp_key.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 9532d5fd101SZiyang Xuan temp_key.func_id = hinic_global_func_id(hwdev); 9542d5fd101SZiyang Xuan temp_key.template_id = (u8)tmpl_idx; 9552d5fd101SZiyang Xuan 9562d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL, 9572d5fd101SZiyang Xuan &temp_key, sizeof(temp_key), 9582d5fd101SZiyang Xuan &temp_key, &out_size); 9592d5fd101SZiyang Xuan if (err || !out_size || temp_key.mgmt_msg_head.status) { 9602d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to get hash key, err: %d, status: 0x%x, out size: 0x%x", 9612d5fd101SZiyang Xuan err, temp_key.mgmt_msg_head.status, out_size); 9622ae8e130SXiaoyun Wang return -EIO; 9632d5fd101SZiyang Xuan } 9642d5fd101SZiyang Xuan 9652d5fd101SZiyang Xuan memcpy(temp, temp_key.key, HINIC_RSS_KEY_SIZE); 9662d5fd101SZiyang Xuan 9672d5fd101SZiyang Xuan return 0; 9682d5fd101SZiyang Xuan } 9692d5fd101SZiyang Xuan 9702d5fd101SZiyang Xuan /** 9712d5fd101SZiyang Xuan * hinic_rss_set_hash_engine - Init rss hash function. 972b8582d05SXiaoyun Wang * 973b8582d05SXiaoyun Wang * @param hwdev 974b8582d05SXiaoyun Wang * The hardware interface of a nic device. 975b8582d05SXiaoyun Wang * @param tmpl_idx 976b8582d05SXiaoyun Wang * Index of rss template from NIC. 977b8582d05SXiaoyun Wang * @param type 978b8582d05SXiaoyun Wang * Hash function, such as Toeplitz or XOR. 979b8582d05SXiaoyun Wang * 9802d5fd101SZiyang Xuan * @return 981b8582d05SXiaoyun Wang * 0 on success. 9822d5fd101SZiyang Xuan * negative error value otherwise. 9832d5fd101SZiyang Xuan */ 9842d5fd101SZiyang Xuan int hinic_rss_set_hash_engine(void *hwdev, u8 tmpl_idx, u8 type) 9852d5fd101SZiyang Xuan { 9862d5fd101SZiyang Xuan struct hinic_rss_engine_type hash_type; 9872d5fd101SZiyang Xuan u16 out_size = sizeof(hash_type); 9882d5fd101SZiyang Xuan int err; 9892d5fd101SZiyang Xuan 9902d5fd101SZiyang Xuan if (!hwdev) { 9912d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 9922d5fd101SZiyang Xuan return -EINVAL; 9932d5fd101SZiyang Xuan } 9942d5fd101SZiyang Xuan 9952d5fd101SZiyang Xuan memset(&hash_type, 0, sizeof(hash_type)); 9962d5fd101SZiyang Xuan hash_type.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 9972d5fd101SZiyang Xuan hash_type.func_id = hinic_global_func_id(hwdev); 9982d5fd101SZiyang Xuan hash_type.hash_engine = type; 9992d5fd101SZiyang Xuan hash_type.template_id = tmpl_idx; 10002d5fd101SZiyang Xuan 10012d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RSS_HASH_ENGINE, 10022d5fd101SZiyang Xuan &hash_type, sizeof(hash_type), 10032d5fd101SZiyang Xuan &hash_type, &out_size); 10042d5fd101SZiyang Xuan if (err || !out_size || hash_type.mgmt_msg_head.status) { 10052d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to get hash engine, err: %d, status: 0x%x, out size: 0x%x", 10062d5fd101SZiyang Xuan err, hash_type.mgmt_msg_head.status, out_size); 10072ae8e130SXiaoyun Wang return -EIO; 10082d5fd101SZiyang Xuan } 10092d5fd101SZiyang Xuan 10102d5fd101SZiyang Xuan return 0; 10112d5fd101SZiyang Xuan } 10122d5fd101SZiyang Xuan 10132d5fd101SZiyang Xuan int hinic_rss_set_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table) 10142d5fd101SZiyang Xuan { 10152d5fd101SZiyang Xuan struct nic_rss_indirect_tbl *indir_tbl; 10162d5fd101SZiyang Xuan struct hinic_cmd_buf *cmd_buf; 10172d5fd101SZiyang Xuan int i; 10182d5fd101SZiyang Xuan u32 *temp; 10192d5fd101SZiyang Xuan u32 indir_size; 10202d5fd101SZiyang Xuan u64 out_param; 10212d5fd101SZiyang Xuan int err; 10222d5fd101SZiyang Xuan 10232d5fd101SZiyang Xuan if (!hwdev || !indir_table) { 10242d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL"); 10252d5fd101SZiyang Xuan return -EINVAL; 10262d5fd101SZiyang Xuan } 10272d5fd101SZiyang Xuan 10282d5fd101SZiyang Xuan cmd_buf = hinic_alloc_cmd_buf(hwdev); 10292d5fd101SZiyang Xuan if (!cmd_buf) { 10302d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to allocate cmd buf"); 10312d5fd101SZiyang Xuan return -ENOMEM; 10322d5fd101SZiyang Xuan } 10332d5fd101SZiyang Xuan 10342d5fd101SZiyang Xuan cmd_buf->size = sizeof(struct nic_rss_indirect_tbl); 10352d5fd101SZiyang Xuan indir_tbl = cmd_buf->buf; 10362d5fd101SZiyang Xuan indir_tbl->group_index = cpu_to_be32(tmpl_idx); 10372d5fd101SZiyang Xuan 10382d5fd101SZiyang Xuan for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) { 10392d5fd101SZiyang Xuan indir_tbl->entry[i] = (u8)(*(indir_table + i)); 10402d5fd101SZiyang Xuan 10412d5fd101SZiyang Xuan if (0x3 == (i & 0x3)) { 10422d5fd101SZiyang Xuan temp = (u32 *)&indir_tbl->entry[i - 3]; 10432d5fd101SZiyang Xuan *temp = cpu_to_be32(*temp); 10442d5fd101SZiyang Xuan } 10452d5fd101SZiyang Xuan } 10462d5fd101SZiyang Xuan 10472d5fd101SZiyang Xuan /* configure the rss indirect table by command queue */ 10482d5fd101SZiyang Xuan indir_size = HINIC_RSS_INDIR_SIZE / 2; 10492d5fd101SZiyang Xuan indir_tbl->offset = 0; 10502d5fd101SZiyang Xuan indir_tbl->size = cpu_to_be32(indir_size); 10512d5fd101SZiyang Xuan 10522d5fd101SZiyang Xuan err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ, 10532d5fd101SZiyang Xuan HINIC_MOD_L2NIC, 10542d5fd101SZiyang Xuan HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE, 10552d5fd101SZiyang Xuan cmd_buf, &out_param, 0); 10562d5fd101SZiyang Xuan if (err || out_param != 0) { 10572d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set rss indir table"); 10582ae8e130SXiaoyun Wang err = -EIO; 10592d5fd101SZiyang Xuan goto free_buf; 10602d5fd101SZiyang Xuan } 10612d5fd101SZiyang Xuan 10622d5fd101SZiyang Xuan indir_tbl->offset = cpu_to_be32(indir_size); 10632d5fd101SZiyang Xuan indir_tbl->size = cpu_to_be32(indir_size); 10642d5fd101SZiyang Xuan memcpy(indir_tbl->entry, &indir_tbl->entry[indir_size], indir_size); 10652d5fd101SZiyang Xuan 10662d5fd101SZiyang Xuan err = hinic_cmdq_direct_resp(hwdev, HINIC_ACK_TYPE_CMDQ, 10672d5fd101SZiyang Xuan HINIC_MOD_L2NIC, 10682d5fd101SZiyang Xuan HINIC_UCODE_CMD_SET_RSS_INDIR_TABLE, 10692d5fd101SZiyang Xuan cmd_buf, &out_param, 0); 10702d5fd101SZiyang Xuan if (err || out_param != 0) { 10712d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set rss indir table"); 10722ae8e130SXiaoyun Wang err = -EIO; 10732d5fd101SZiyang Xuan } 10742d5fd101SZiyang Xuan 10752d5fd101SZiyang Xuan free_buf: 10762d5fd101SZiyang Xuan hinic_free_cmd_buf(hwdev, cmd_buf); 10772d5fd101SZiyang Xuan 10782d5fd101SZiyang Xuan return err; 10792d5fd101SZiyang Xuan } 10802d5fd101SZiyang Xuan 10812d5fd101SZiyang Xuan int hinic_rss_get_indir_tbl(void *hwdev, u32 tmpl_idx, u32 *indir_table) 10822d5fd101SZiyang Xuan { 10832d5fd101SZiyang Xuan struct hinic_rss_indir_table rss_cfg; 10842d5fd101SZiyang Xuan u16 out_size = sizeof(rss_cfg); 10852d5fd101SZiyang Xuan int err = 0, i; 10862d5fd101SZiyang Xuan 10872d5fd101SZiyang Xuan if (!hwdev || !indir_table) { 10882d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or indir_table is NULL"); 10892d5fd101SZiyang Xuan return -EINVAL; 10902d5fd101SZiyang Xuan } 10912d5fd101SZiyang Xuan 10922d5fd101SZiyang Xuan memset(&rss_cfg, 0, sizeof(rss_cfg)); 10932d5fd101SZiyang Xuan rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 10942d5fd101SZiyang Xuan rss_cfg.func_id = hinic_global_func_id(hwdev); 10952d5fd101SZiyang Xuan rss_cfg.template_id = (u8)tmpl_idx; 10962d5fd101SZiyang Xuan 10972d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, 10982d5fd101SZiyang Xuan HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL, 10992d5fd101SZiyang Xuan &rss_cfg, sizeof(rss_cfg), &rss_cfg, 11002d5fd101SZiyang Xuan &out_size); 11012d5fd101SZiyang Xuan if (err || !out_size || rss_cfg.mgmt_msg_head.status) { 11022d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to get indir table, err: %d, status: 0x%x, out size: 0x%x", 11032d5fd101SZiyang Xuan err, rss_cfg.mgmt_msg_head.status, out_size); 11042ae8e130SXiaoyun Wang return -EIO; 11052d5fd101SZiyang Xuan } 11062d5fd101SZiyang Xuan 11072d5fd101SZiyang Xuan hinic_be32_to_cpu(rss_cfg.indir, HINIC_RSS_INDIR_SIZE); 11082d5fd101SZiyang Xuan for (i = 0; i < HINIC_RSS_INDIR_SIZE; i++) 11092d5fd101SZiyang Xuan indir_table[i] = rss_cfg.indir[i]; 11102d5fd101SZiyang Xuan 11112d5fd101SZiyang Xuan return 0; 11122d5fd101SZiyang Xuan } 11132d5fd101SZiyang Xuan 11142d5fd101SZiyang Xuan int hinic_rss_cfg(void *hwdev, u8 rss_en, u8 tmpl_idx, u8 tc_num, u8 *prio_tc) 11152d5fd101SZiyang Xuan { 11162d5fd101SZiyang Xuan struct hinic_rss_config rss_cfg; 11172d5fd101SZiyang Xuan u16 out_size = sizeof(rss_cfg); 11182d5fd101SZiyang Xuan int err; 11192d5fd101SZiyang Xuan 11202d5fd101SZiyang Xuan /* micro code required: number of TC should be power of 2 */ 11212d5fd101SZiyang Xuan if (!hwdev || !prio_tc || (tc_num & (tc_num - 1))) { 11222d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or prio_tc is NULL, or tc_num: %u Not power of 2", 11232d5fd101SZiyang Xuan tc_num); 11242d5fd101SZiyang Xuan return -EINVAL; 11252d5fd101SZiyang Xuan } 11262d5fd101SZiyang Xuan 11272d5fd101SZiyang Xuan memset(&rss_cfg, 0, sizeof(rss_cfg)); 11282d5fd101SZiyang Xuan rss_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 11292d5fd101SZiyang Xuan rss_cfg.func_id = hinic_global_func_id(hwdev); 11302d5fd101SZiyang Xuan rss_cfg.rss_en = rss_en; 11312d5fd101SZiyang Xuan rss_cfg.template_id = tmpl_idx; 11322d5fd101SZiyang Xuan rss_cfg.rq_priority_number = tc_num ? (u8)ilog2(tc_num) : 0; 11332d5fd101SZiyang Xuan 11342d5fd101SZiyang Xuan memcpy(rss_cfg.prio_tc, prio_tc, HINIC_DCB_UP_MAX); 11352d5fd101SZiyang Xuan 11362d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_CFG, 11372d5fd101SZiyang Xuan &rss_cfg, sizeof(rss_cfg), &rss_cfg, 11382d5fd101SZiyang Xuan &out_size); 11392d5fd101SZiyang Xuan if (err || !out_size || rss_cfg.mgmt_msg_head.status) { 11402d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set rss cfg, err: %d, status: 0x%x, out size: 0x%x", 11412d5fd101SZiyang Xuan err, rss_cfg.mgmt_msg_head.status, out_size); 11422ae8e130SXiaoyun Wang return -EIO; 11432d5fd101SZiyang Xuan } 11442d5fd101SZiyang Xuan 11452d5fd101SZiyang Xuan return 0; 11462d5fd101SZiyang Xuan } 11472d5fd101SZiyang Xuan 11482d5fd101SZiyang Xuan /** 1149b8582d05SXiaoyun Wang * hinic_rss_template_alloc - Get rss template id from the chip, 11502d5fd101SZiyang Xuan * all functions share 96 templates. 1151b8582d05SXiaoyun Wang * 1152b8582d05SXiaoyun Wang * @param hwdev 1153b8582d05SXiaoyun Wang * The hardware interface of a nic device. 1154b8582d05SXiaoyun Wang * @param tmpl_idx 1155b8582d05SXiaoyun Wang * Index of rss template from chip. 1156b8582d05SXiaoyun Wang * 1157b8582d05SXiaoyun Wang * @return 1158b8582d05SXiaoyun Wang * 0 on success. 1159b8582d05SXiaoyun Wang * negative error value otherwise. 1160b8582d05SXiaoyun Wang */ 11612d5fd101SZiyang Xuan int hinic_rss_template_alloc(void *hwdev, u8 *tmpl_idx) 11622d5fd101SZiyang Xuan { 11632d5fd101SZiyang Xuan struct hinic_rss_template_mgmt template_mgmt; 11642d5fd101SZiyang Xuan u16 out_size = sizeof(template_mgmt); 11652d5fd101SZiyang Xuan int err; 11662d5fd101SZiyang Xuan 11672d5fd101SZiyang Xuan if (!hwdev || !tmpl_idx) { 11682d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev or tmpl_idx is NULL"); 11692d5fd101SZiyang Xuan return -EINVAL; 11702d5fd101SZiyang Xuan } 11712d5fd101SZiyang Xuan 11722d5fd101SZiyang Xuan memset(&template_mgmt, 0, sizeof(template_mgmt)); 11732d5fd101SZiyang Xuan template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 11742d5fd101SZiyang Xuan template_mgmt.func_id = hinic_global_func_id(hwdev); 11752d5fd101SZiyang Xuan template_mgmt.cmd = NIC_RSS_CMD_TEMP_ALLOC; 11762d5fd101SZiyang Xuan 11772d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR, 11782d5fd101SZiyang Xuan &template_mgmt, sizeof(template_mgmt), 11792d5fd101SZiyang Xuan &template_mgmt, &out_size); 11802d5fd101SZiyang Xuan if (err || !out_size || template_mgmt.mgmt_msg_head.status) { 11812d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to alloc rss template, err: %d, status: 0x%x, out size: 0x%x", 11822d5fd101SZiyang Xuan err, template_mgmt.mgmt_msg_head.status, out_size); 11832ae8e130SXiaoyun Wang return -EIO; 11842d5fd101SZiyang Xuan } 11852d5fd101SZiyang Xuan 11862d5fd101SZiyang Xuan *tmpl_idx = template_mgmt.template_id; 11872d5fd101SZiyang Xuan 11882d5fd101SZiyang Xuan return 0; 11892d5fd101SZiyang Xuan } 11902d5fd101SZiyang Xuan 11912d5fd101SZiyang Xuan /** 1192b8582d05SXiaoyun Wang * hinic_rss_template_free - Free rss template id to the chip. 1193b8582d05SXiaoyun Wang * 1194b8582d05SXiaoyun Wang * @param hwdev 1195b8582d05SXiaoyun Wang * The hardware interface of a nic device. 1196b8582d05SXiaoyun Wang * @param tmpl_idx 1197b8582d05SXiaoyun Wang * Index of rss template from chip. 1198b8582d05SXiaoyun Wang * 1199b8582d05SXiaoyun Wang * @return 1200b8582d05SXiaoyun Wang * 0 on success. 1201b8582d05SXiaoyun Wang * negative error value otherwise. 1202b8582d05SXiaoyun Wang */ 12032d5fd101SZiyang Xuan int hinic_rss_template_free(void *hwdev, u8 tmpl_idx) 12042d5fd101SZiyang Xuan { 12052d5fd101SZiyang Xuan struct hinic_rss_template_mgmt template_mgmt; 12062d5fd101SZiyang Xuan u16 out_size = sizeof(template_mgmt); 12072d5fd101SZiyang Xuan int err; 12082d5fd101SZiyang Xuan 12092d5fd101SZiyang Xuan if (!hwdev) { 12102d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 12112d5fd101SZiyang Xuan return -EINVAL; 12122d5fd101SZiyang Xuan } 12132d5fd101SZiyang Xuan 12142d5fd101SZiyang Xuan memset(&template_mgmt, 0, sizeof(template_mgmt)); 12152d5fd101SZiyang Xuan template_mgmt.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 12162d5fd101SZiyang Xuan template_mgmt.func_id = hinic_global_func_id(hwdev); 12172d5fd101SZiyang Xuan template_mgmt.template_id = tmpl_idx; 12182d5fd101SZiyang Xuan template_mgmt.cmd = NIC_RSS_CMD_TEMP_FREE; 12192d5fd101SZiyang Xuan 12202d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RSS_TEMP_MGR, 12212d5fd101SZiyang Xuan &template_mgmt, sizeof(template_mgmt), 12222d5fd101SZiyang Xuan &template_mgmt, &out_size); 12232d5fd101SZiyang Xuan if (err || !out_size || template_mgmt.mgmt_msg_head.status) { 12242d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to free rss template, err: %d, status: 0x%x, out size: 0x%x", 12252d5fd101SZiyang Xuan err, template_mgmt.mgmt_msg_head.status, out_size); 12262ae8e130SXiaoyun Wang return -EIO; 12272d5fd101SZiyang Xuan } 12282d5fd101SZiyang Xuan 12292d5fd101SZiyang Xuan return 0; 12302d5fd101SZiyang Xuan } 12312d5fd101SZiyang Xuan 12322d5fd101SZiyang Xuan /** 1233b8582d05SXiaoyun Wang * hinic_set_rx_vhd_mode - Change rx buffer size after initialization. 1234b8582d05SXiaoyun Wang * 1235b8582d05SXiaoyun Wang * @param hwdev 1236b8582d05SXiaoyun Wang * The hardware interface of a nic device. 1237b8582d05SXiaoyun Wang * @param vhd_mode 1238b8582d05SXiaoyun Wang * Not needed. 1239b8582d05SXiaoyun Wang * @param rx_buf_sz 1240b8582d05SXiaoyun Wang * receive buffer size. 1241b8582d05SXiaoyun Wang * 12422d5fd101SZiyang Xuan * @return 1243b8582d05SXiaoyun Wang * 0 on success. 12442d5fd101SZiyang Xuan * negative error value otherwise. 12452d5fd101SZiyang Xuan */ 12462d5fd101SZiyang Xuan int hinic_set_rx_vhd_mode(void *hwdev, u16 vhd_mode, u16 rx_buf_sz) 12472d5fd101SZiyang Xuan { 12482d5fd101SZiyang Xuan struct hinic_set_vhd_mode vhd_mode_cfg; 12492d5fd101SZiyang Xuan u16 out_size = sizeof(vhd_mode_cfg); 12502d5fd101SZiyang Xuan int err; 12512d5fd101SZiyang Xuan 12522d5fd101SZiyang Xuan if (!hwdev) { 12532d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 12542d5fd101SZiyang Xuan return -EINVAL; 12552d5fd101SZiyang Xuan } 12562d5fd101SZiyang Xuan 12572d5fd101SZiyang Xuan memset(&vhd_mode_cfg, 0, sizeof(vhd_mode_cfg)); 12582d5fd101SZiyang Xuan 12592d5fd101SZiyang Xuan vhd_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 12602d5fd101SZiyang Xuan vhd_mode_cfg.func_id = hinic_global_func_id(hwdev); 12612d5fd101SZiyang Xuan vhd_mode_cfg.vhd_type = vhd_mode; 12622d5fd101SZiyang Xuan vhd_mode_cfg.rx_wqe_buffer_size = rx_buf_sz; 12632d5fd101SZiyang Xuan 12642d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_VHD_CFG, 12652d5fd101SZiyang Xuan &vhd_mode_cfg, sizeof(vhd_mode_cfg), 12662d5fd101SZiyang Xuan &vhd_mode_cfg, &out_size); 12672d5fd101SZiyang Xuan if (err || !out_size || vhd_mode_cfg.mgmt_msg_head.status) { 12682d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 12692d5fd101SZiyang Xuan "Failed to set vhd mode, err: %d, status: 0x%x, out size: 0x%x", 12702d5fd101SZiyang Xuan err, vhd_mode_cfg.mgmt_msg_head.status, out_size); 12712d5fd101SZiyang Xuan return -EIO; 12722d5fd101SZiyang Xuan } 12732d5fd101SZiyang Xuan 12742d5fd101SZiyang Xuan return 0; 12752d5fd101SZiyang Xuan } 12762d5fd101SZiyang Xuan 12772d5fd101SZiyang Xuan int hinic_set_rx_mode(void *hwdev, u32 enable) 12782d5fd101SZiyang Xuan { 12792d5fd101SZiyang Xuan struct hinic_rx_mode_config rx_mode_cfg; 12802d5fd101SZiyang Xuan u16 out_size = sizeof(rx_mode_cfg); 12812d5fd101SZiyang Xuan int err; 12822d5fd101SZiyang Xuan 12832d5fd101SZiyang Xuan if (!hwdev) { 12842d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 12852d5fd101SZiyang Xuan return -EINVAL; 12862d5fd101SZiyang Xuan } 12872d5fd101SZiyang Xuan 12882d5fd101SZiyang Xuan memset(&rx_mode_cfg, 0, sizeof(rx_mode_cfg)); 12892d5fd101SZiyang Xuan rx_mode_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 12902d5fd101SZiyang Xuan rx_mode_cfg.func_id = hinic_global_func_id(hwdev); 12912d5fd101SZiyang Xuan rx_mode_cfg.rx_mode = enable; 12922d5fd101SZiyang Xuan 12932d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_MODE, 12942d5fd101SZiyang Xuan &rx_mode_cfg, sizeof(rx_mode_cfg), 12952d5fd101SZiyang Xuan &rx_mode_cfg, &out_size); 12962d5fd101SZiyang Xuan if (err || !out_size || rx_mode_cfg.mgmt_msg_head.status) { 12972d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set rx mode, err: %d, status: 0x%x, out size: 0x%x", 12982d5fd101SZiyang Xuan err, rx_mode_cfg.mgmt_msg_head.status, out_size); 12992ae8e130SXiaoyun Wang return -EIO; 13002d5fd101SZiyang Xuan } 13012d5fd101SZiyang Xuan 13022d5fd101SZiyang Xuan return 0; 13032d5fd101SZiyang Xuan } 13042d5fd101SZiyang Xuan 1305dbf524abSXiaoyun Wang /** 1306dbf524abSXiaoyun Wang * hinic_get_mgmt_version - Get mgmt module version from chip. 1307dbf524abSXiaoyun Wang * 1308dbf524abSXiaoyun Wang * @param hwdev 1309dbf524abSXiaoyun Wang * The hardware interface of a nic device. 1310dbf524abSXiaoyun Wang * @param fw 1311dbf524abSXiaoyun Wang * Firmware version. 1312dbf524abSXiaoyun Wang * 1313dbf524abSXiaoyun Wang * @return 1314dbf524abSXiaoyun Wang * 0 on success. 1315dbf524abSXiaoyun Wang * negative error value otherwise. 1316dbf524abSXiaoyun Wang */ 1317dbf524abSXiaoyun Wang int hinic_get_mgmt_version(void *hwdev, char *fw) 1318dbf524abSXiaoyun Wang { 1319dbf524abSXiaoyun Wang struct hinic_version_info fw_ver; 1320dbf524abSXiaoyun Wang u16 out_size = sizeof(fw_ver); 1321dbf524abSXiaoyun Wang int err; 1322dbf524abSXiaoyun Wang 1323dbf524abSXiaoyun Wang if (!hwdev || !fw) { 1324dbf524abSXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev or fw is NULL"); 1325dbf524abSXiaoyun Wang return -EINVAL; 1326dbf524abSXiaoyun Wang } 1327dbf524abSXiaoyun Wang 1328dbf524abSXiaoyun Wang memset(&fw_ver, 0, sizeof(fw_ver)); 1329dbf524abSXiaoyun Wang fw_ver.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1330dbf524abSXiaoyun Wang 1331dbf524abSXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_MGMT_VERSION, 1332dbf524abSXiaoyun Wang &fw_ver, sizeof(fw_ver), &fw_ver, 1333dbf524abSXiaoyun Wang &out_size); 1334dbf524abSXiaoyun Wang if (err || !out_size || fw_ver.mgmt_msg_head.status) { 1335*f665790aSDavid Marchand PMD_DRV_LOG(ERR, "Failed to get mgmt version, err: %d, status: 0x%x, out size: 0x%x", 1336dbf524abSXiaoyun Wang err, fw_ver.mgmt_msg_head.status, out_size); 13372ae8e130SXiaoyun Wang return -EIO; 1338dbf524abSXiaoyun Wang } 1339dbf524abSXiaoyun Wang 1340dbf524abSXiaoyun Wang snprintf(fw, HINIC_MGMT_VERSION_MAX_LEN, "%s", fw_ver.ver); 1341dbf524abSXiaoyun Wang 1342dbf524abSXiaoyun Wang return 0; 1343dbf524abSXiaoyun Wang } 1344dbf524abSXiaoyun Wang 13452d5fd101SZiyang Xuan int hinic_set_rx_csum_offload(void *hwdev, u32 en) 13462d5fd101SZiyang Xuan { 13472d5fd101SZiyang Xuan struct hinic_checksum_offload rx_csum_cfg; 13482d5fd101SZiyang Xuan u16 out_size = sizeof(rx_csum_cfg); 13492d5fd101SZiyang Xuan int err; 13502d5fd101SZiyang Xuan 13512d5fd101SZiyang Xuan if (!hwdev) { 13522d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 13532d5fd101SZiyang Xuan return -EINVAL; 13542d5fd101SZiyang Xuan } 13552d5fd101SZiyang Xuan 13562d5fd101SZiyang Xuan memset(&rx_csum_cfg, 0, sizeof(rx_csum_cfg)); 13572d5fd101SZiyang Xuan rx_csum_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 13582d5fd101SZiyang Xuan rx_csum_cfg.func_id = hinic_global_func_id(hwdev); 13592d5fd101SZiyang Xuan rx_csum_cfg.rx_csum_offload = en; 13602d5fd101SZiyang Xuan 13612d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_RX_CSUM, 13622d5fd101SZiyang Xuan &rx_csum_cfg, sizeof(rx_csum_cfg), 13632d5fd101SZiyang Xuan &rx_csum_cfg, &out_size); 13642d5fd101SZiyang Xuan if (err || !out_size || rx_csum_cfg.mgmt_msg_head.status) { 13652d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 13662d5fd101SZiyang Xuan "Failed to set rx csum offload, err: %d, status: 0x%x, out size: 0x%x", 13672d5fd101SZiyang Xuan err, rx_csum_cfg.mgmt_msg_head.status, out_size); 13682ae8e130SXiaoyun Wang return -EIO; 13692d5fd101SZiyang Xuan } 13702d5fd101SZiyang Xuan 13712d5fd101SZiyang Xuan return 0; 13722d5fd101SZiyang Xuan } 13732d5fd101SZiyang Xuan 13742d5fd101SZiyang Xuan int hinic_set_rx_lro(void *hwdev, u8 ipv4_en, u8 ipv6_en, u8 max_wqe_num) 13752d5fd101SZiyang Xuan { 13762d5fd101SZiyang Xuan struct hinic_lro_config lro_cfg; 13772d5fd101SZiyang Xuan u16 out_size = sizeof(lro_cfg); 13782d5fd101SZiyang Xuan int err; 13792d5fd101SZiyang Xuan 13802d5fd101SZiyang Xuan if (!hwdev) { 13812d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 13822d5fd101SZiyang Xuan return -EINVAL; 13832d5fd101SZiyang Xuan } 13842d5fd101SZiyang Xuan 13852d5fd101SZiyang Xuan memset(&lro_cfg, 0, sizeof(lro_cfg)); 13862d5fd101SZiyang Xuan lro_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 13872d5fd101SZiyang Xuan lro_cfg.func_id = hinic_global_func_id(hwdev); 13882d5fd101SZiyang Xuan lro_cfg.lro_ipv4_en = ipv4_en; 13892d5fd101SZiyang Xuan lro_cfg.lro_ipv6_en = ipv6_en; 13902d5fd101SZiyang Xuan lro_cfg.lro_max_wqe_num = max_wqe_num; 13912d5fd101SZiyang Xuan 13922d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LRO, 13932d5fd101SZiyang Xuan &lro_cfg, sizeof(lro_cfg), &lro_cfg, 13942d5fd101SZiyang Xuan &out_size); 13952d5fd101SZiyang Xuan if (err || !out_size || lro_cfg.mgmt_msg_head.status) { 13962d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to set lro offload, err: %d, status: 0x%x, out size: 0x%x", 13972d5fd101SZiyang Xuan err, lro_cfg.mgmt_msg_head.status, out_size); 13982ae8e130SXiaoyun Wang return -EIO; 13992d5fd101SZiyang Xuan } 14002d5fd101SZiyang Xuan 14012d5fd101SZiyang Xuan return 0; 14022d5fd101SZiyang Xuan } 14032d5fd101SZiyang Xuan 14042d5fd101SZiyang Xuan int hinic_set_anti_attack(void *hwdev, bool enable) 14052d5fd101SZiyang Xuan { 14062d5fd101SZiyang Xuan struct hinic_port_anti_attack_rate rate; 14072d5fd101SZiyang Xuan u16 out_size = sizeof(rate); 14082d5fd101SZiyang Xuan int err; 14092d5fd101SZiyang Xuan 14102d5fd101SZiyang Xuan if (!hwdev) { 14112d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 14122d5fd101SZiyang Xuan return -EINVAL; 14132d5fd101SZiyang Xuan } 14142d5fd101SZiyang Xuan 14152d5fd101SZiyang Xuan memset(&rate, 0, sizeof(rate)); 14162d5fd101SZiyang Xuan rate.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 14172d5fd101SZiyang Xuan rate.func_id = hinic_global_func_id(hwdev); 14182d5fd101SZiyang Xuan rate.enable = enable; 14192d5fd101SZiyang Xuan rate.cir = ANTI_ATTACK_DEFAULT_CIR; 14202d5fd101SZiyang Xuan rate.xir = ANTI_ATTACK_DEFAULT_XIR; 14212d5fd101SZiyang Xuan rate.cbs = ANTI_ATTACK_DEFAULT_CBS; 14222d5fd101SZiyang Xuan rate.xbs = ANTI_ATTACK_DEFAULT_XBS; 14232d5fd101SZiyang Xuan 14242d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE, 1425d807dd7dSXiaoyun Wang &rate, sizeof(rate), &rate, &out_size); 14262d5fd101SZiyang Xuan if (err || !out_size || rate.mgmt_msg_head.status) { 14274f1af3cbSXiaoyun Wang PMD_DRV_LOG(ERR, "Can't %s port Anti-Attack rate limit, err: %d, status: 0x%x, out size: 0x%x", 14282d5fd101SZiyang Xuan (enable ? "enable" : "disable"), err, 14292d5fd101SZiyang Xuan rate.mgmt_msg_head.status, out_size); 14302ae8e130SXiaoyun Wang return -EIO; 14312d5fd101SZiyang Xuan } 14322d5fd101SZiyang Xuan 14332d5fd101SZiyang Xuan return 0; 14342d5fd101SZiyang Xuan } 14352d5fd101SZiyang Xuan 14362d5fd101SZiyang Xuan /* Set autoneg status and restart port link status */ 14372d5fd101SZiyang Xuan int hinic_reset_port_link_cfg(void *hwdev) 14382d5fd101SZiyang Xuan { 14392d5fd101SZiyang Xuan struct hinic_reset_link_cfg reset_cfg; 14402d5fd101SZiyang Xuan u16 out_size = sizeof(reset_cfg); 14412d5fd101SZiyang Xuan int err; 14422d5fd101SZiyang Xuan 14432d5fd101SZiyang Xuan memset(&reset_cfg, 0, sizeof(reset_cfg)); 14442d5fd101SZiyang Xuan reset_cfg.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 14452d5fd101SZiyang Xuan reset_cfg.func_id = hinic_global_func_id(hwdev); 14462d5fd101SZiyang Xuan 14472d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_RESET_LINK_CFG, 14482d5fd101SZiyang Xuan &reset_cfg, sizeof(reset_cfg), 14492d5fd101SZiyang Xuan &reset_cfg, &out_size); 14502d5fd101SZiyang Xuan if (err || !out_size || reset_cfg.mgmt_msg_head.status) { 14512d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Reset port link configure failed, err: %d, status: 0x%x, out size: 0x%x", 14522d5fd101SZiyang Xuan err, reset_cfg.mgmt_msg_head.status, out_size); 14532ae8e130SXiaoyun Wang return -EIO; 14542d5fd101SZiyang Xuan } 14552d5fd101SZiyang Xuan 14562d5fd101SZiyang Xuan return 0; 14572d5fd101SZiyang Xuan } 14582d5fd101SZiyang Xuan 1459b8582d05SXiaoyun Wang /** 1460b8582d05SXiaoyun Wang * hinic_vf_func_init - Register VF to PF. 1461b8582d05SXiaoyun Wang * 1462b8582d05SXiaoyun Wang * @param hwdev 1463b8582d05SXiaoyun Wang * The hardware interface of a nic device. 1464b8582d05SXiaoyun Wang * 1465b8582d05SXiaoyun Wang * @return 1466b8582d05SXiaoyun Wang * 0 on success. 1467b8582d05SXiaoyun Wang * negative error value otherwise. 1468b8582d05SXiaoyun Wang */ 1469b8582d05SXiaoyun Wang int hinic_vf_func_init(struct hinic_hwdev *hwdev) 1470b8582d05SXiaoyun Wang { 1471b8582d05SXiaoyun Wang int err, state = 0; 1472b8582d05SXiaoyun Wang 1473b8582d05SXiaoyun Wang if (!HINIC_IS_VF(hwdev)) 1474b8582d05SXiaoyun Wang return 0; 1475b8582d05SXiaoyun Wang 1476b8582d05SXiaoyun Wang err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC, 1477b8582d05SXiaoyun Wang HINIC_PORT_CMD_VF_REGISTER, &state, sizeof(state), 1478b8582d05SXiaoyun Wang NULL, NULL, 0); 1479b8582d05SXiaoyun Wang if (err) { 1480b8582d05SXiaoyun Wang PMD_DRV_LOG(ERR, "Fail to register vf"); 1481b8582d05SXiaoyun Wang return err; 1482b8582d05SXiaoyun Wang } 1483b8582d05SXiaoyun Wang 1484b8582d05SXiaoyun Wang return 0; 1485b8582d05SXiaoyun Wang } 1486b8582d05SXiaoyun Wang 1487b8582d05SXiaoyun Wang /** 1488b8582d05SXiaoyun Wang * hinic_vf_func_free - Unregister VF from PF. 1489b8582d05SXiaoyun Wang * 1490b8582d05SXiaoyun Wang * @param hwdev 1491b8582d05SXiaoyun Wang * The hardware interface of a nic device. 1492b8582d05SXiaoyun Wang */ 1493b8582d05SXiaoyun Wang void hinic_vf_func_free(struct hinic_hwdev *hwdev) 1494b8582d05SXiaoyun Wang { 1495b8582d05SXiaoyun Wang int err; 1496b8582d05SXiaoyun Wang 1497b8582d05SXiaoyun Wang if (hinic_func_type(hwdev) != TYPE_VF) 1498b8582d05SXiaoyun Wang return; 1499b8582d05SXiaoyun Wang 1500b8582d05SXiaoyun Wang err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC, 1501b8582d05SXiaoyun Wang HINIC_PORT_CMD_VF_UNREGISTER, &err, sizeof(err), 1502b8582d05SXiaoyun Wang NULL, NULL, 0); 1503b8582d05SXiaoyun Wang if (err) 1504b8582d05SXiaoyun Wang PMD_DRV_LOG(ERR, "Fail to unregister VF, err: %d", err); 1505b8582d05SXiaoyun Wang } 1506b8582d05SXiaoyun Wang 15072d5fd101SZiyang Xuan int hinic_set_fast_recycle_mode(void *hwdev, u8 mode) 15082d5fd101SZiyang Xuan { 15092d5fd101SZiyang Xuan struct hinic_fast_recycled_mode fast_recycled_mode; 15102d5fd101SZiyang Xuan u16 out_size = sizeof(fast_recycled_mode); 15112d5fd101SZiyang Xuan int err; 15122d5fd101SZiyang Xuan 15132d5fd101SZiyang Xuan if (!hwdev) { 15142d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 15152d5fd101SZiyang Xuan return -EINVAL; 15162d5fd101SZiyang Xuan } 15172d5fd101SZiyang Xuan 15182d5fd101SZiyang Xuan memset(&fast_recycled_mode, 0, sizeof(fast_recycled_mode)); 15192d5fd101SZiyang Xuan fast_recycled_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 15202d5fd101SZiyang Xuan fast_recycled_mode.func_id = hinic_global_func_id(hwdev); 15212d5fd101SZiyang Xuan fast_recycled_mode.fast_recycled_mode = mode; 15222d5fd101SZiyang Xuan 15232d5fd101SZiyang Xuan err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM, 15242d5fd101SZiyang Xuan HINIC_MGMT_CMD_FAST_RECYCLE_MODE_SET, 15252d5fd101SZiyang Xuan &fast_recycled_mode, 15262d5fd101SZiyang Xuan sizeof(fast_recycled_mode), 15272d5fd101SZiyang Xuan &fast_recycled_mode, &out_size, 0); 15282d5fd101SZiyang Xuan if (err || fast_recycled_mode.mgmt_msg_head.status || !out_size) { 1529d807dd7dSXiaoyun Wang PMD_DRV_LOG(ERR, "Failed to set recycle mode, err: %d, status: 0x%x, out size: 0x%x", 1530d807dd7dSXiaoyun Wang err, fast_recycled_mode.mgmt_msg_head.status, out_size); 1531d807dd7dSXiaoyun Wang return -EIO; 15322d5fd101SZiyang Xuan } 15332d5fd101SZiyang Xuan 15342d5fd101SZiyang Xuan return 0; 15352d5fd101SZiyang Xuan } 15362d5fd101SZiyang Xuan 15379970a9adSIgor Romanov int hinic_clear_vport_stats(struct hinic_hwdev *hwdev) 15382d5fd101SZiyang Xuan { 15392d5fd101SZiyang Xuan struct hinic_clear_vport_stats clear_vport_stats; 15402d5fd101SZiyang Xuan u16 out_size = sizeof(clear_vport_stats); 15412d5fd101SZiyang Xuan int err; 15422d5fd101SZiyang Xuan 15432d5fd101SZiyang Xuan if (!hwdev) { 15442d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 15459970a9adSIgor Romanov return -EINVAL; 15462d5fd101SZiyang Xuan } 15472d5fd101SZiyang Xuan 15482d5fd101SZiyang Xuan memset(&clear_vport_stats, 0, sizeof(clear_vport_stats)); 15492d5fd101SZiyang Xuan clear_vport_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 15502d5fd101SZiyang Xuan clear_vport_stats.func_id = hinic_global_func_id(hwdev); 15512d5fd101SZiyang Xuan 15522d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAN_VPORT_STAT, 15532d5fd101SZiyang Xuan &clear_vport_stats, 15542d5fd101SZiyang Xuan sizeof(clear_vport_stats), 15552d5fd101SZiyang Xuan &clear_vport_stats, &out_size); 15562d5fd101SZiyang Xuan if (err || !out_size || clear_vport_stats.mgmt_msg_head.status) { 15572d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to clear vport statistics, err: %d, status: 0x%x, out size: 0x%x", 15582d5fd101SZiyang Xuan err, clear_vport_stats.mgmt_msg_head.status, out_size); 15592ae8e130SXiaoyun Wang return -EIO; 15602d5fd101SZiyang Xuan } 15612d5fd101SZiyang Xuan 15629970a9adSIgor Romanov return 0; 15639970a9adSIgor Romanov } 15649970a9adSIgor Romanov 15659970a9adSIgor Romanov int hinic_clear_phy_port_stats(struct hinic_hwdev *hwdev) 15662d5fd101SZiyang Xuan { 15672d5fd101SZiyang Xuan struct hinic_clear_port_stats clear_phy_port_stats; 15682d5fd101SZiyang Xuan u16 out_size = sizeof(clear_phy_port_stats); 15692d5fd101SZiyang Xuan int err; 15702d5fd101SZiyang Xuan 15712d5fd101SZiyang Xuan if (!hwdev) { 15722d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Hwdev is NULL"); 15739970a9adSIgor Romanov return -EINVAL; 15742d5fd101SZiyang Xuan } 15752d5fd101SZiyang Xuan 15762d5fd101SZiyang Xuan memset(&clear_phy_port_stats, 0, sizeof(clear_phy_port_stats)); 15772d5fd101SZiyang Xuan clear_phy_port_stats.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 15782d5fd101SZiyang Xuan clear_phy_port_stats.func_id = hinic_global_func_id(hwdev); 15792d5fd101SZiyang Xuan 15802d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, 15812d5fd101SZiyang Xuan HINIC_PORT_CMD_CLEAR_PORT_STATISTICS, 15822d5fd101SZiyang Xuan &clear_phy_port_stats, 15832d5fd101SZiyang Xuan sizeof(clear_phy_port_stats), 15842d5fd101SZiyang Xuan &clear_phy_port_stats, &out_size); 15852d5fd101SZiyang Xuan if (err || !out_size || clear_phy_port_stats.mgmt_msg_head.status) { 15862d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to clear phy port statistics, err: %d, status: 0x%x, out size: 0x%x", 15872d5fd101SZiyang Xuan err, clear_phy_port_stats.mgmt_msg_head.status, 15882d5fd101SZiyang Xuan out_size); 15892ae8e130SXiaoyun Wang return -EIO; 15902d5fd101SZiyang Xuan } 15919970a9adSIgor Romanov 15929970a9adSIgor Romanov return 0; 15932d5fd101SZiyang Xuan } 15942d5fd101SZiyang Xuan 15952d5fd101SZiyang Xuan int hinic_set_link_status_follow(void *hwdev, 15962d5fd101SZiyang Xuan enum hinic_link_follow_status status) 15972d5fd101SZiyang Xuan { 15982d5fd101SZiyang Xuan struct hinic_set_link_follow follow; 15992d5fd101SZiyang Xuan u16 out_size = sizeof(follow); 16002d5fd101SZiyang Xuan int err; 16012d5fd101SZiyang Xuan 16022d5fd101SZiyang Xuan if (!hwdev) 16032d5fd101SZiyang Xuan return -EINVAL; 16042d5fd101SZiyang Xuan 1605b8582d05SXiaoyun Wang if (HINIC_IS_VF((struct hinic_hwdev *)hwdev)) 1606b8582d05SXiaoyun Wang return 0; 1607b8582d05SXiaoyun Wang 16082d5fd101SZiyang Xuan if (status >= HINIC_LINK_FOLLOW_STATUS_MAX) { 1609a528b671SXiaoyun Wang PMD_DRV_LOG(ERR, "Invalid link follow status: %d", status); 16102d5fd101SZiyang Xuan return -EINVAL; 16112d5fd101SZiyang Xuan } 16122d5fd101SZiyang Xuan 16132d5fd101SZiyang Xuan memset(&follow, 0, sizeof(follow)); 16142d5fd101SZiyang Xuan follow.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 16152d5fd101SZiyang Xuan follow.func_id = hinic_global_func_id(hwdev); 16162d5fd101SZiyang Xuan follow.follow_status = status; 16172d5fd101SZiyang Xuan 16182d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_SET_LINK_FOLLOW, 16192d5fd101SZiyang Xuan &follow, sizeof(follow), 16202d5fd101SZiyang Xuan &follow, &out_size); 16212d5fd101SZiyang Xuan if ((follow.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED && 16222d5fd101SZiyang Xuan follow.mgmt_msg_head.status) || err || !out_size) { 16232d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 16242d5fd101SZiyang Xuan "Failed to set link status follow phy port status, err: %d, status: 0x%x, out size: 0x%x", 16252d5fd101SZiyang Xuan err, follow.mgmt_msg_head.status, out_size); 16262ae8e130SXiaoyun Wang return -EIO; 16272d5fd101SZiyang Xuan } 16282d5fd101SZiyang Xuan 16292d5fd101SZiyang Xuan return follow.mgmt_msg_head.status; 16302d5fd101SZiyang Xuan } 16312d5fd101SZiyang Xuan 16322d5fd101SZiyang Xuan int hinic_get_link_mode(void *hwdev, u32 *supported, u32 *advertised) 16332d5fd101SZiyang Xuan { 16342d5fd101SZiyang Xuan struct hinic_link_mode_cmd link_mode; 16352d5fd101SZiyang Xuan u16 out_size = sizeof(link_mode); 16362d5fd101SZiyang Xuan int err; 16372d5fd101SZiyang Xuan 16382d5fd101SZiyang Xuan if (!hwdev || !supported || !advertised) 16392d5fd101SZiyang Xuan return -EINVAL; 16402d5fd101SZiyang Xuan 16412d5fd101SZiyang Xuan memset(&link_mode, 0, sizeof(link_mode)); 16422d5fd101SZiyang Xuan link_mode.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 16432d5fd101SZiyang Xuan link_mode.func_id = hinic_global_func_id(hwdev); 16442d5fd101SZiyang Xuan 16452d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_GET_LINK_MODE, 16462d5fd101SZiyang Xuan &link_mode, sizeof(link_mode), 16472d5fd101SZiyang Xuan &link_mode, &out_size); 16482d5fd101SZiyang Xuan if (err || !out_size || link_mode.mgmt_msg_head.status) { 16492d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, 16502d5fd101SZiyang Xuan "Failed to get link mode, err: %d, status: 0x%x, out size: 0x%x", 16512d5fd101SZiyang Xuan err, link_mode.mgmt_msg_head.status, out_size); 16522ae8e130SXiaoyun Wang return -EIO; 16532d5fd101SZiyang Xuan } 16542d5fd101SZiyang Xuan 16552d5fd101SZiyang Xuan *supported = link_mode.supported; 16562d5fd101SZiyang Xuan *advertised = link_mode.advertised; 16572d5fd101SZiyang Xuan 16582d5fd101SZiyang Xuan return 0; 16592d5fd101SZiyang Xuan } 16602d5fd101SZiyang Xuan 16612d5fd101SZiyang Xuan /** 1662b8582d05SXiaoyun Wang * hinic_flush_qp_res - Flush tx && rx chip resources in case of set vport 1663b8582d05SXiaoyun Wang * fake failed when device start. 1664b8582d05SXiaoyun Wang * 1665b8582d05SXiaoyun Wang * @param hwdev 1666b8582d05SXiaoyun Wang * The hardware interface of a nic device. 1667b8582d05SXiaoyun Wang * 1668b8582d05SXiaoyun Wang * @return 1669b8582d05SXiaoyun Wang * 0 on success. 1670b8582d05SXiaoyun Wang * negative error value otherwise. 1671b8582d05SXiaoyun Wang */ 16722d5fd101SZiyang Xuan int hinic_flush_qp_res(void *hwdev) 16732d5fd101SZiyang Xuan { 16742d5fd101SZiyang Xuan struct hinic_clear_qp_resource qp_res; 16752d5fd101SZiyang Xuan u16 out_size = sizeof(qp_res); 16762d5fd101SZiyang Xuan int err; 16772d5fd101SZiyang Xuan 16782d5fd101SZiyang Xuan memset(&qp_res, 0, sizeof(qp_res)); 16792d5fd101SZiyang Xuan qp_res.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 16802d5fd101SZiyang Xuan qp_res.func_id = hinic_global_func_id(hwdev); 16812d5fd101SZiyang Xuan 16822d5fd101SZiyang Xuan err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_CLEAR_QP_RES, 16832d5fd101SZiyang Xuan &qp_res, sizeof(qp_res), &qp_res, 16842d5fd101SZiyang Xuan &out_size); 16852d5fd101SZiyang Xuan if (err || !out_size || qp_res.mgmt_msg_head.status) { 16862d5fd101SZiyang Xuan PMD_DRV_LOG(ERR, "Failed to clear sq resources, err: %d, status: 0x%x, out size: 0x%x", 16872d5fd101SZiyang Xuan err, qp_res.mgmt_msg_head.status, out_size); 16882ae8e130SXiaoyun Wang return -EIO; 16892d5fd101SZiyang Xuan } 16902d5fd101SZiyang Xuan 16912d5fd101SZiyang Xuan return 0; 16922d5fd101SZiyang Xuan } 16936691acefSXiaoyun Wang 16946691acefSXiaoyun Wang /** 16956691acefSXiaoyun Wang * hinic_vf_get_default_cos - Get default cos of VF. 16966691acefSXiaoyun Wang * 16976691acefSXiaoyun Wang * @param hwdev 16986691acefSXiaoyun Wang * The hardware interface of a nic device. 16996691acefSXiaoyun Wang * @param cos_id 17006691acefSXiaoyun Wang * Cos value. 17016691acefSXiaoyun Wang * 17026691acefSXiaoyun Wang * @return 17036691acefSXiaoyun Wang * 0 on success. 17046691acefSXiaoyun Wang * negative error value otherwise. 17056691acefSXiaoyun Wang */ 17066691acefSXiaoyun Wang int hinic_vf_get_default_cos(struct hinic_hwdev *hwdev, u8 *cos_id) 17076691acefSXiaoyun Wang { 17086691acefSXiaoyun Wang struct hinic_vf_default_cos vf_cos; 17096691acefSXiaoyun Wang u16 out_size = sizeof(vf_cos); 17106691acefSXiaoyun Wang int err; 17116691acefSXiaoyun Wang 17126691acefSXiaoyun Wang memset(&vf_cos, 0, sizeof(vf_cos)); 17136691acefSXiaoyun Wang vf_cos.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 17146691acefSXiaoyun Wang 17156691acefSXiaoyun Wang err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, 17166691acefSXiaoyun Wang HINIC_PORT_CMD_GET_VF_COS, &vf_cos, 1717d807dd7dSXiaoyun Wang sizeof(vf_cos), &vf_cos, &out_size, 0); 17186691acefSXiaoyun Wang if (err || !out_size || vf_cos.mgmt_msg_head.status) { 17196691acefSXiaoyun Wang PMD_DRV_LOG(ERR, "Get VF default cos failed, err: %d, status: 0x%x, out size: 0x%x", 17206691acefSXiaoyun Wang err, vf_cos.mgmt_msg_head.status, out_size); 1721d807dd7dSXiaoyun Wang return -EIO; 17226691acefSXiaoyun Wang } 17236691acefSXiaoyun Wang *cos_id = vf_cos.state.default_cos; 17246691acefSXiaoyun Wang 17256691acefSXiaoyun Wang return 0; 17266691acefSXiaoyun Wang } 1727a5d668e6SXiaoyun Wang 1728a5d668e6SXiaoyun Wang /** 1729a5d668e6SXiaoyun Wang * hinic_set_fdir_filter - Set fdir filter for control path 1730a5d668e6SXiaoyun Wang * packet to notify firmware. 1731a5d668e6SXiaoyun Wang * 1732a5d668e6SXiaoyun Wang * @param hwdev 1733a5d668e6SXiaoyun Wang * The hardware interface of a nic device. 1734a5d668e6SXiaoyun Wang * @param filter_type 1735a5d668e6SXiaoyun Wang * Packet type to filter. 1736a5d668e6SXiaoyun Wang * @param qid 1737a5d668e6SXiaoyun Wang * Rx qid to filter. 1738a5d668e6SXiaoyun Wang * @param type_enable 1739a5d668e6SXiaoyun Wang * The status of pkt type filter. 1740a5d668e6SXiaoyun Wang * @param enable 1741a5d668e6SXiaoyun Wang * Fdir function Enable or Disable. 1742a5d668e6SXiaoyun Wang * @return 1743a5d668e6SXiaoyun Wang * 0 on success, 1744a5d668e6SXiaoyun Wang * negative error value otherwise. 1745a5d668e6SXiaoyun Wang */ 1746a5d668e6SXiaoyun Wang int hinic_set_fdir_filter(void *hwdev, u8 filter_type, u8 qid, u8 type_enable, 1747a5d668e6SXiaoyun Wang bool enable) 1748a5d668e6SXiaoyun Wang { 1749a5d668e6SXiaoyun Wang struct hinic_port_qfilter_info port_filer_cmd; 1750a5d668e6SXiaoyun Wang u16 out_size = sizeof(port_filer_cmd); 1751a5d668e6SXiaoyun Wang int err; 1752a5d668e6SXiaoyun Wang 1753a5d668e6SXiaoyun Wang if (!hwdev) 1754a5d668e6SXiaoyun Wang return -EINVAL; 1755a5d668e6SXiaoyun Wang 1756a5d668e6SXiaoyun Wang memset(&port_filer_cmd, 0, sizeof(port_filer_cmd)); 1757a5d668e6SXiaoyun Wang port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1758a5d668e6SXiaoyun Wang port_filer_cmd.func_id = hinic_global_func_id(hwdev); 1759a5d668e6SXiaoyun Wang port_filer_cmd.filter_enable = (u8)enable; 1760a5d668e6SXiaoyun Wang port_filer_cmd.filter_type = filter_type; 1761a5d668e6SXiaoyun Wang port_filer_cmd.qid = qid; 1762a5d668e6SXiaoyun Wang port_filer_cmd.filter_type_enable = type_enable; 1763a5d668e6SXiaoyun Wang port_filer_cmd.fdir_flag = 0; 1764a5d668e6SXiaoyun Wang 1765a5d668e6SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER, 1766a5d668e6SXiaoyun Wang &port_filer_cmd, sizeof(port_filer_cmd), 1767a5d668e6SXiaoyun Wang &port_filer_cmd, &out_size); 1768a5d668e6SXiaoyun Wang if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) { 1769a5d668e6SXiaoyun Wang PMD_DRV_LOG(ERR, "Set port Q filter failed, err: %d, status: 0x%x, out size: 0x%x, type: 0x%x," 1770*f665790aSDavid Marchand " enable: 0x%x, qid: 0x%x, filter_type_enable: 0x%x", 1771a5d668e6SXiaoyun Wang err, port_filer_cmd.mgmt_msg_head.status, out_size, 1772a5d668e6SXiaoyun Wang filter_type, enable, qid, type_enable); 17732ae8e130SXiaoyun Wang return -EIO; 1774a5d668e6SXiaoyun Wang } 1775a5d668e6SXiaoyun Wang 1776a5d668e6SXiaoyun Wang return 0; 1777a5d668e6SXiaoyun Wang } 1778a5d668e6SXiaoyun Wang 1779a5d668e6SXiaoyun Wang /** 1780a5d668e6SXiaoyun Wang * hinic_set_normal_filter - Set fdir filter for IO path packet. 1781a5d668e6SXiaoyun Wang * 1782a5d668e6SXiaoyun Wang * @param hwdev 1783a5d668e6SXiaoyun Wang * The hardware interface of a nic device. 1784a5d668e6SXiaoyun Wang * @param qid 1785a5d668e6SXiaoyun Wang * Rx qid to filter. 1786a5d668e6SXiaoyun Wang * @param normal_type_enable 1787a5d668e6SXiaoyun Wang * IO path packet function Enable or Disable 1788a5d668e6SXiaoyun Wang * @param key 1789a5d668e6SXiaoyun Wang * IO path packet filter key value, such as DIP from pkt. 1790a5d668e6SXiaoyun Wang * @param enable 1791a5d668e6SXiaoyun Wang * Fdir function Enable or Disable. 1792a5d668e6SXiaoyun Wang * @param flag 1793a5d668e6SXiaoyun Wang * Filter flag, such as dip or others. 1794a5d668e6SXiaoyun Wang * @return 1795a5d668e6SXiaoyun Wang * 0 on success, 1796a5d668e6SXiaoyun Wang * negative error value otherwise. 1797a5d668e6SXiaoyun Wang */ 1798a5d668e6SXiaoyun Wang int hinic_set_normal_filter(void *hwdev, u8 qid, u8 normal_type_enable, 1799a5d668e6SXiaoyun Wang u32 key, bool enable, u8 flag) 1800a5d668e6SXiaoyun Wang { 1801a5d668e6SXiaoyun Wang struct hinic_port_qfilter_info port_filer_cmd; 1802a5d668e6SXiaoyun Wang u16 out_size = sizeof(port_filer_cmd); 1803a5d668e6SXiaoyun Wang int err; 1804a5d668e6SXiaoyun Wang 1805a5d668e6SXiaoyun Wang if (!hwdev) 1806a5d668e6SXiaoyun Wang return -EINVAL; 1807a5d668e6SXiaoyun Wang 1808a5d668e6SXiaoyun Wang memset(&port_filer_cmd, 0, sizeof(port_filer_cmd)); 1809a5d668e6SXiaoyun Wang port_filer_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1810a5d668e6SXiaoyun Wang port_filer_cmd.func_id = hinic_global_func_id(hwdev); 1811a5d668e6SXiaoyun Wang port_filer_cmd.filter_enable = (u8)enable; 1812a5d668e6SXiaoyun Wang port_filer_cmd.qid = qid; 1813a5d668e6SXiaoyun Wang port_filer_cmd.normal_type_enable = normal_type_enable; 1814a5d668e6SXiaoyun Wang port_filer_cmd.fdir_flag = flag; /* fdir flag: support dip */ 1815a5d668e6SXiaoyun Wang port_filer_cmd.key = key; 1816a5d668e6SXiaoyun Wang 1817a5d668e6SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_Q_FILTER, 1818a5d668e6SXiaoyun Wang &port_filer_cmd, sizeof(port_filer_cmd), 1819a5d668e6SXiaoyun Wang &port_filer_cmd, &out_size); 1820a5d668e6SXiaoyun Wang if (err || !out_size || port_filer_cmd.mgmt_msg_head.status) { 1821a5d668e6SXiaoyun Wang PMD_DRV_LOG(ERR, "Set normal filter failed, err: %d, status: 0x%x, out size: 0x%x, fdir_flag: 0x%x," 1822*f665790aSDavid Marchand " enable: 0x%x, qid: 0x%x, normal_type_enable: 0x%x, key:0x%x", 1823a5d668e6SXiaoyun Wang err, port_filer_cmd.mgmt_msg_head.status, out_size, 1824a5d668e6SXiaoyun Wang flag, enable, qid, normal_type_enable, key); 18252ae8e130SXiaoyun Wang return -EIO; 1826a5d668e6SXiaoyun Wang } 1827a5d668e6SXiaoyun Wang 1828a5d668e6SXiaoyun Wang return 0; 1829a5d668e6SXiaoyun Wang } 1830a5d668e6SXiaoyun Wang 1831a5d668e6SXiaoyun Wang /** 1832a5d668e6SXiaoyun Wang * hinic_set_fdir_tcam - Set fdir filter for control packet 1833a5d668e6SXiaoyun Wang * by tcam table to notify hardware. 1834a5d668e6SXiaoyun Wang * 1835a5d668e6SXiaoyun Wang * @param hwdev 1836a5d668e6SXiaoyun Wang * The hardware interface of a nic device. 1837a5d668e6SXiaoyun Wang * @param type_mask 1838a5d668e6SXiaoyun Wang * Index of TCAM. 1839a5d668e6SXiaoyun Wang * @param filter_rule 1840a5d668e6SXiaoyun Wang * TCAM rule for control packet, such as lacp or bgp. 1841a5d668e6SXiaoyun Wang * @param filter_action 1842a5d668e6SXiaoyun Wang * TCAM action for control packet, such as accept or drop. 1843a5d668e6SXiaoyun Wang * @return 1844a5d668e6SXiaoyun Wang * 0 on success, 1845a5d668e6SXiaoyun Wang * negative error value otherwise. 1846a5d668e6SXiaoyun Wang */ 1847a5d668e6SXiaoyun Wang int hinic_set_fdir_tcam(void *hwdev, u16 type_mask, 1848a5d668e6SXiaoyun Wang struct tag_pa_rule *filter_rule, 1849a5d668e6SXiaoyun Wang struct tag_pa_action *filter_action) 1850a5d668e6SXiaoyun Wang { 1851a5d668e6SXiaoyun Wang struct hinic_fdir_tcam_info port_tcam_cmd; 1852a5d668e6SXiaoyun Wang u16 out_size = sizeof(port_tcam_cmd); 1853a5d668e6SXiaoyun Wang int err; 1854a5d668e6SXiaoyun Wang 1855a5d668e6SXiaoyun Wang if (!hwdev) 1856a5d668e6SXiaoyun Wang return -EINVAL; 1857a5d668e6SXiaoyun Wang 1858a5d668e6SXiaoyun Wang memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd)); 1859a5d668e6SXiaoyun Wang port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1860a5d668e6SXiaoyun Wang port_tcam_cmd.tcam_index = type_mask; 1861a5d668e6SXiaoyun Wang port_tcam_cmd.flag = TCAM_SET; 1862a5d668e6SXiaoyun Wang memcpy((void *)&port_tcam_cmd.filter_rule, 1863a5d668e6SXiaoyun Wang (void *)filter_rule, sizeof(struct tag_pa_rule)); 1864a5d668e6SXiaoyun Wang memcpy((void *)&port_tcam_cmd.filter_action, 1865a5d668e6SXiaoyun Wang (void *)filter_action, sizeof(struct tag_pa_action)); 1866a5d668e6SXiaoyun Wang 1867a5d668e6SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER, 1868a5d668e6SXiaoyun Wang &port_tcam_cmd, sizeof(port_tcam_cmd), 1869a5d668e6SXiaoyun Wang &port_tcam_cmd, &out_size); 1870a5d668e6SXiaoyun Wang if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) { 18711fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Set tcam table failed, err: %d, status: 0x%x, out size: 0x%x", 1872a5d668e6SXiaoyun Wang err, port_tcam_cmd.mgmt_msg_head.status, out_size); 18732ae8e130SXiaoyun Wang return -EIO; 1874a5d668e6SXiaoyun Wang } 1875a5d668e6SXiaoyun Wang 1876a5d668e6SXiaoyun Wang return 0; 1877a5d668e6SXiaoyun Wang } 1878a5d668e6SXiaoyun Wang 1879a5d668e6SXiaoyun Wang /** 1880a5d668e6SXiaoyun Wang * hinic_clear_fdir_tcam - Clear fdir filter TCAM table for control packet. 1881a5d668e6SXiaoyun Wang * 1882a5d668e6SXiaoyun Wang * @param hwdev 1883a5d668e6SXiaoyun Wang * The hardware interface of a nic device. 1884a5d668e6SXiaoyun Wang * @param type_mask 1885a5d668e6SXiaoyun Wang * Index of TCAM. 1886a5d668e6SXiaoyun Wang * @return 1887a5d668e6SXiaoyun Wang * 0 on success, 1888a5d668e6SXiaoyun Wang * negative error value otherwise. 1889a5d668e6SXiaoyun Wang */ 1890a5d668e6SXiaoyun Wang int hinic_clear_fdir_tcam(void *hwdev, u16 type_mask) 1891a5d668e6SXiaoyun Wang { 1892a5d668e6SXiaoyun Wang struct hinic_fdir_tcam_info port_tcam_cmd; 1893a5d668e6SXiaoyun Wang u16 out_size = sizeof(port_tcam_cmd); 1894a5d668e6SXiaoyun Wang int err; 1895a5d668e6SXiaoyun Wang 1896a5d668e6SXiaoyun Wang if (!hwdev) 1897a5d668e6SXiaoyun Wang return -EINVAL; 1898a5d668e6SXiaoyun Wang 1899a5d668e6SXiaoyun Wang memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd)); 1900a5d668e6SXiaoyun Wang port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 1901a5d668e6SXiaoyun Wang port_tcam_cmd.tcam_index = type_mask; 1902a5d668e6SXiaoyun Wang port_tcam_cmd.flag = TCAM_CLEAR; 1903a5d668e6SXiaoyun Wang 1904a5d668e6SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_TCAM_FILTER, 1905a5d668e6SXiaoyun Wang &port_tcam_cmd, sizeof(port_tcam_cmd), 1906a5d668e6SXiaoyun Wang &port_tcam_cmd, &out_size); 1907a5d668e6SXiaoyun Wang if (err || !out_size || port_tcam_cmd.mgmt_msg_head.status) { 19081fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Clear tcam table failed, err: %d, status: 0x%x, out size: 0x%x", 1909a5d668e6SXiaoyun Wang err, port_tcam_cmd.mgmt_msg_head.status, out_size); 19102ae8e130SXiaoyun Wang return -EIO; 1911a5d668e6SXiaoyun Wang } 1912a5d668e6SXiaoyun Wang 1913a5d668e6SXiaoyun Wang return 0; 1914a5d668e6SXiaoyun Wang } 19151fe89aa3SXiaoyun Wang 19161fe89aa3SXiaoyun Wang int hinic_add_tcam_rule(void *hwdev, struct tag_tcam_cfg_rule *tcam_rule) 19171fe89aa3SXiaoyun Wang { 19181fe89aa3SXiaoyun Wang u16 out_size = sizeof(struct tag_fdir_add_rule_cmd); 19191fe89aa3SXiaoyun Wang struct tag_fdir_add_rule_cmd tcam_cmd; 19201fe89aa3SXiaoyun Wang int err; 19211fe89aa3SXiaoyun Wang 19221fe89aa3SXiaoyun Wang if (!hwdev) { 19231fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev is NULL"); 19241fe89aa3SXiaoyun Wang return -EINVAL; 19251fe89aa3SXiaoyun Wang } 19261fe89aa3SXiaoyun Wang 19271fe89aa3SXiaoyun Wang if (tcam_rule->index >= HINIC_MAX_TCAM_RULES_NUM) { 19281fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Tcam rules num to add is invalid"); 19292ae8e130SXiaoyun Wang return -EINVAL; 19301fe89aa3SXiaoyun Wang } 19311fe89aa3SXiaoyun Wang 19321fe89aa3SXiaoyun Wang memset(&tcam_cmd, 0, sizeof(struct tag_fdir_add_rule_cmd)); 19331fe89aa3SXiaoyun Wang tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 19341fe89aa3SXiaoyun Wang memcpy((void *)&tcam_cmd.rule, (void *)tcam_rule, 19351fe89aa3SXiaoyun Wang sizeof(struct tag_tcam_cfg_rule)); 19361fe89aa3SXiaoyun Wang 19371fe89aa3SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ADD_FLOW, 19381fe89aa3SXiaoyun Wang &tcam_cmd, sizeof(tcam_cmd), 19391fe89aa3SXiaoyun Wang &tcam_cmd, &out_size); 19401fe89aa3SXiaoyun Wang if (err || tcam_cmd.mgmt_msg_head.status || !out_size) { 19411fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, 19421fe89aa3SXiaoyun Wang "Add tcam rule failed, err: %d, status: 0x%x, out size: 0x%x", 19431fe89aa3SXiaoyun Wang err, tcam_cmd.mgmt_msg_head.status, out_size); 19442ae8e130SXiaoyun Wang return -EIO; 19451fe89aa3SXiaoyun Wang } 19461fe89aa3SXiaoyun Wang 19471fe89aa3SXiaoyun Wang return 0; 19481fe89aa3SXiaoyun Wang } 19491fe89aa3SXiaoyun Wang 19501fe89aa3SXiaoyun Wang int hinic_del_tcam_rule(void *hwdev, u32 index) 19511fe89aa3SXiaoyun Wang { 19521fe89aa3SXiaoyun Wang u16 out_size = sizeof(struct tag_fdir_del_rule_cmd); 19531fe89aa3SXiaoyun Wang struct tag_fdir_del_rule_cmd tcam_cmd; 19541fe89aa3SXiaoyun Wang int err; 19551fe89aa3SXiaoyun Wang 19561fe89aa3SXiaoyun Wang if (!hwdev) { 19571fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev is NULL"); 19581fe89aa3SXiaoyun Wang return -EINVAL; 19591fe89aa3SXiaoyun Wang } 19601fe89aa3SXiaoyun Wang 19611fe89aa3SXiaoyun Wang if (index >= HINIC_MAX_TCAM_RULES_NUM) { 19621fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Tcam rules num to del is invalid"); 19632ae8e130SXiaoyun Wang return -EINVAL; 19641fe89aa3SXiaoyun Wang } 19651fe89aa3SXiaoyun Wang 19661fe89aa3SXiaoyun Wang memset(&tcam_cmd, 0, sizeof(struct tag_fdir_del_rule_cmd)); 19671fe89aa3SXiaoyun Wang tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 19681fe89aa3SXiaoyun Wang tcam_cmd.index_start = index; 19691fe89aa3SXiaoyun Wang tcam_cmd.index_num = 1; 19701fe89aa3SXiaoyun Wang 19711fe89aa3SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_DEL_FLOW, 19721fe89aa3SXiaoyun Wang &tcam_cmd, sizeof(tcam_cmd), 19731fe89aa3SXiaoyun Wang &tcam_cmd, &out_size); 19741fe89aa3SXiaoyun Wang if (err || tcam_cmd.mgmt_msg_head.status || !out_size) { 19751fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, 19761fe89aa3SXiaoyun Wang "Del tcam rule failed, err: %d, status: 0x%x, out size: 0x%x", 19771fe89aa3SXiaoyun Wang err, tcam_cmd.mgmt_msg_head.status, out_size); 19782ae8e130SXiaoyun Wang return -EIO; 19791fe89aa3SXiaoyun Wang } 19801fe89aa3SXiaoyun Wang 19811fe89aa3SXiaoyun Wang return 0; 19821fe89aa3SXiaoyun Wang } 19831fe89aa3SXiaoyun Wang 19841fe89aa3SXiaoyun Wang static int hinic_mgmt_tcam_block(void *hwdev, u8 alloc_en, 19851fe89aa3SXiaoyun Wang u8 block_type, u16 *index) 19861fe89aa3SXiaoyun Wang { 19871fe89aa3SXiaoyun Wang struct hinic_cmd_ctrl_tcam_block tcam_block_info; 19881fe89aa3SXiaoyun Wang u16 out_size = sizeof(struct hinic_cmd_ctrl_tcam_block); 19891fe89aa3SXiaoyun Wang struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev; 19901fe89aa3SXiaoyun Wang int err; 19911fe89aa3SXiaoyun Wang 19921fe89aa3SXiaoyun Wang if (!hwdev) { 19931fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev is NULL"); 19941fe89aa3SXiaoyun Wang return -EINVAL; 19951fe89aa3SXiaoyun Wang } 19961fe89aa3SXiaoyun Wang 19971fe89aa3SXiaoyun Wang memset(&tcam_block_info, 0, sizeof(struct hinic_cmd_ctrl_tcam_block)); 19981fe89aa3SXiaoyun Wang tcam_block_info.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 19991fe89aa3SXiaoyun Wang tcam_block_info.func_id = hinic_global_func_id(hwdev); 20001fe89aa3SXiaoyun Wang tcam_block_info.alloc_en = alloc_en; 20011fe89aa3SXiaoyun Wang tcam_block_info.tcam_type = block_type; 20021fe89aa3SXiaoyun Wang tcam_block_info.tcam_block_index = *index; 20031fe89aa3SXiaoyun Wang 20041fe89aa3SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, 20051fe89aa3SXiaoyun Wang HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK, 20061fe89aa3SXiaoyun Wang &tcam_block_info, sizeof(tcam_block_info), 20071fe89aa3SXiaoyun Wang &tcam_block_info, &out_size); 20081fe89aa3SXiaoyun Wang if (tcam_block_info.mgmt_msg_head.status == 20091fe89aa3SXiaoyun Wang HINIC_MGMT_CMD_UNSUPPORTED) { 20101fe89aa3SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 20111fe89aa3SXiaoyun Wang PMD_DRV_LOG(INFO, "Firmware/uP doesn't support alloc or del tcam block"); 20121fe89aa3SXiaoyun Wang return err; 20131fe89aa3SXiaoyun Wang } else if ((err == HINIC_MBOX_VF_CMD_ERROR) && 20141fe89aa3SXiaoyun Wang (HINIC_IS_VF(nic_hwdev))) { 20151fe89aa3SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 20161fe89aa3SXiaoyun Wang PMD_DRV_LOG(INFO, "VF doesn't support alloc and del tcam block."); 20171fe89aa3SXiaoyun Wang return err; 20181fe89aa3SXiaoyun Wang } else if (err || (!out_size) || tcam_block_info.mgmt_msg_head.status) { 20191fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, 20201fe89aa3SXiaoyun Wang "Set tcam block failed, err: %d, status: 0x%x, out size: 0x%x", 20211fe89aa3SXiaoyun Wang err, tcam_block_info.mgmt_msg_head.status, out_size); 20222ae8e130SXiaoyun Wang return -EIO; 20231fe89aa3SXiaoyun Wang } 20241fe89aa3SXiaoyun Wang 20251fe89aa3SXiaoyun Wang if (alloc_en) 20261fe89aa3SXiaoyun Wang *index = tcam_block_info.tcam_block_index; 20271fe89aa3SXiaoyun Wang 20281fe89aa3SXiaoyun Wang return 0; 20291fe89aa3SXiaoyun Wang } 20301fe89aa3SXiaoyun Wang 20311fe89aa3SXiaoyun Wang int hinic_alloc_tcam_block(void *hwdev, u8 block_type, u16 *index) 20321fe89aa3SXiaoyun Wang { 20331fe89aa3SXiaoyun Wang return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_ENABLE, 20341fe89aa3SXiaoyun Wang block_type, index); 20351fe89aa3SXiaoyun Wang } 20361fe89aa3SXiaoyun Wang 20371fe89aa3SXiaoyun Wang int hinic_free_tcam_block(void *hwdev, u8 block_type, u16 *index) 20381fe89aa3SXiaoyun Wang { 20391fe89aa3SXiaoyun Wang return hinic_mgmt_tcam_block(hwdev, HINIC_TCAM_BLOCK_DISABLE, 20401fe89aa3SXiaoyun Wang block_type, index); 20411fe89aa3SXiaoyun Wang } 20421fe89aa3SXiaoyun Wang 20431fe89aa3SXiaoyun Wang int hinic_flush_tcam_rule(void *hwdev) 20441fe89aa3SXiaoyun Wang { 20451fe89aa3SXiaoyun Wang struct hinic_cmd_flush_tcam_rules tcam_flush; 20461fe89aa3SXiaoyun Wang u16 out_size = sizeof(struct hinic_cmd_flush_tcam_rules); 20471fe89aa3SXiaoyun Wang struct hinic_hwdev *nic_hwdev = (struct hinic_hwdev *)hwdev; 20481fe89aa3SXiaoyun Wang int err; 20491fe89aa3SXiaoyun Wang 20501fe89aa3SXiaoyun Wang if (!hwdev) { 20511fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, "Hwdev is NULL"); 20521fe89aa3SXiaoyun Wang return -EINVAL; 20531fe89aa3SXiaoyun Wang } 20541fe89aa3SXiaoyun Wang 20551fe89aa3SXiaoyun Wang memset(&tcam_flush, 0, sizeof(struct hinic_cmd_flush_tcam_rules)); 20561fe89aa3SXiaoyun Wang tcam_flush.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 20571fe89aa3SXiaoyun Wang tcam_flush.func_id = hinic_global_func_id(hwdev); 20581fe89aa3SXiaoyun Wang 20591fe89aa3SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_FLUSH_TCAM, 20601fe89aa3SXiaoyun Wang &tcam_flush, sizeof(struct hinic_cmd_flush_tcam_rules), 20611fe89aa3SXiaoyun Wang &tcam_flush, &out_size); 20621fe89aa3SXiaoyun Wang if (tcam_flush.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) { 20631fe89aa3SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 20641fe89aa3SXiaoyun Wang PMD_DRV_LOG(INFO, "Firmware/uP doesn't support flush tcam fdir"); 20651fe89aa3SXiaoyun Wang } else if ((err == HINIC_MBOX_VF_CMD_ERROR) && 20661fe89aa3SXiaoyun Wang (HINIC_IS_VF(nic_hwdev))) { 20671fe89aa3SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 20681fe89aa3SXiaoyun Wang PMD_DRV_LOG(INFO, "VF doesn't support flush tcam fdir"); 20691fe89aa3SXiaoyun Wang } else if (err || (!out_size) || tcam_flush.mgmt_msg_head.status) { 20701fe89aa3SXiaoyun Wang PMD_DRV_LOG(ERR, 20711fe89aa3SXiaoyun Wang "Flush tcam fdir rules failed, err: %d, status: 0x%x, out size: 0x%x", 20721fe89aa3SXiaoyun Wang err, tcam_flush.mgmt_msg_head.status, out_size); 20732ae8e130SXiaoyun Wang err = -EIO; 20741fe89aa3SXiaoyun Wang } 20751fe89aa3SXiaoyun Wang 20761fe89aa3SXiaoyun Wang return err; 20771fe89aa3SXiaoyun Wang } 20781fe89aa3SXiaoyun Wang 20790023e525SXiaoyun Wang int hinic_set_fdir_tcam_rule_filter(void *hwdev, bool enable) 20800023e525SXiaoyun Wang { 20810023e525SXiaoyun Wang struct hinic_port_tcam_info port_tcam_cmd; 20820023e525SXiaoyun Wang u16 out_size = sizeof(port_tcam_cmd); 20830023e525SXiaoyun Wang int err; 20840023e525SXiaoyun Wang 20850023e525SXiaoyun Wang if (!hwdev) 20860023e525SXiaoyun Wang return -EINVAL; 20870023e525SXiaoyun Wang 20880023e525SXiaoyun Wang memset(&port_tcam_cmd, 0, sizeof(port_tcam_cmd)); 20890023e525SXiaoyun Wang port_tcam_cmd.mgmt_msg_head.resp_aeq_num = HINIC_AEQ1; 20900023e525SXiaoyun Wang port_tcam_cmd.func_id = hinic_global_func_id(hwdev); 20910023e525SXiaoyun Wang port_tcam_cmd.tcam_enable = (u8)enable; 20920023e525SXiaoyun Wang 20930023e525SXiaoyun Wang err = l2nic_msg_to_mgmt_sync(hwdev, HINIC_PORT_CMD_UP_TC_ENABLE, 20940023e525SXiaoyun Wang &port_tcam_cmd, sizeof(port_tcam_cmd), 20950023e525SXiaoyun Wang &port_tcam_cmd, &out_size); 20960023e525SXiaoyun Wang if ((port_tcam_cmd.mgmt_msg_head.status != HINIC_MGMT_CMD_UNSUPPORTED && 20970023e525SXiaoyun Wang port_tcam_cmd.mgmt_msg_head.status) || err || !out_size) { 20980023e525SXiaoyun Wang if (err == HINIC_MBOX_VF_CMD_ERROR && 20990023e525SXiaoyun Wang HINIC_IS_VF((struct hinic_hwdev *)hwdev)) { 21000023e525SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 21010023e525SXiaoyun Wang PMD_DRV_LOG(WARNING, "VF doesn't support setting fdir tcam filter"); 21020023e525SXiaoyun Wang return err; 21030023e525SXiaoyun Wang } 21040023e525SXiaoyun Wang PMD_DRV_LOG(ERR, "Set fdir tcam filter failed, err: %d, " 21050023e525SXiaoyun Wang "status: 0x%x, out size: 0x%x, enable: 0x%x", 21060023e525SXiaoyun Wang err, port_tcam_cmd.mgmt_msg_head.status, out_size, 21070023e525SXiaoyun Wang enable); 21082ae8e130SXiaoyun Wang return -EIO; 21090023e525SXiaoyun Wang } 21100023e525SXiaoyun Wang 21110023e525SXiaoyun Wang if (port_tcam_cmd.mgmt_msg_head.status == HINIC_MGMT_CMD_UNSUPPORTED) { 21120023e525SXiaoyun Wang err = HINIC_MGMT_CMD_UNSUPPORTED; 21130023e525SXiaoyun Wang PMD_DRV_LOG(WARNING, "Fw doesn't support setting fdir tcam filter"); 21140023e525SXiaoyun Wang } 21150023e525SXiaoyun Wang 21160023e525SXiaoyun Wang return err; 21170023e525SXiaoyun Wang } 21180023e525SXiaoyun Wang 21190023e525SXiaoyun Wang 2120