18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* Copyright(c) 2013 - 2019 Intel Corporation. */ 38c2ecf20Sopenharmony_ci 48c2ecf20Sopenharmony_ci#include "fm10k_pf.h" 58c2ecf20Sopenharmony_ci#include "fm10k_vf.h" 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci/** 88c2ecf20Sopenharmony_ci * fm10k_reset_hw_pf - PF hardware reset 98c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci * This function should return the hardware to a state similar to the 128c2ecf20Sopenharmony_ci * one it is in after being powered on. 138c2ecf20Sopenharmony_ci **/ 148c2ecf20Sopenharmony_cistatic s32 fm10k_reset_hw_pf(struct fm10k_hw *hw) 158c2ecf20Sopenharmony_ci{ 168c2ecf20Sopenharmony_ci s32 err; 178c2ecf20Sopenharmony_ci u32 reg; 188c2ecf20Sopenharmony_ci u16 i; 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci /* Disable interrupts */ 218c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_EIMR, FM10K_EIMR_DISABLE(ALL)); 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ci /* Lock ITR2 reg 0 into itself and disable interrupt moderation */ 248c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(0), 0); 258c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_INT_CTRL, 0); 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_ci /* We assume here Tx and Rx queue 0 are owned by the PF */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci /* Shut off VF access to their queues forcing them to queue 0 */ 308c2ecf20Sopenharmony_ci for (i = 0; i < FM10K_TQMAP_TABLE_SIZE; i++) { 318c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(i), 0); 328c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RQMAP(i), 0); 338c2ecf20Sopenharmony_ci } 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* shut down all rings */ 368c2ecf20Sopenharmony_ci err = fm10k_disable_queues_generic(hw, FM10K_MAX_QUEUES); 378c2ecf20Sopenharmony_ci if (err == FM10K_ERR_REQUESTS_PENDING) { 388c2ecf20Sopenharmony_ci hw->mac.reset_while_pending++; 398c2ecf20Sopenharmony_ci goto force_reset; 408c2ecf20Sopenharmony_ci } else if (err) { 418c2ecf20Sopenharmony_ci return err; 428c2ecf20Sopenharmony_ci } 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci /* Verify that DMA is no longer active */ 458c2ecf20Sopenharmony_ci reg = fm10k_read_reg(hw, FM10K_DMA_CTRL); 468c2ecf20Sopenharmony_ci if (reg & (FM10K_DMA_CTRL_TX_ACTIVE | FM10K_DMA_CTRL_RX_ACTIVE)) 478c2ecf20Sopenharmony_ci return FM10K_ERR_DMA_PENDING; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ciforce_reset: 508c2ecf20Sopenharmony_ci /* Inititate data path reset */ 518c2ecf20Sopenharmony_ci reg = FM10K_DMA_CTRL_DATAPATH_RESET; 528c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DMA_CTRL, reg); 538c2ecf20Sopenharmony_ci 548c2ecf20Sopenharmony_ci /* Flush write and allow 100us for reset to complete */ 558c2ecf20Sopenharmony_ci fm10k_write_flush(hw); 568c2ecf20Sopenharmony_ci udelay(FM10K_RESET_TIMEOUT); 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci /* Verify we made it out of reset */ 598c2ecf20Sopenharmony_ci reg = fm10k_read_reg(hw, FM10K_IP); 608c2ecf20Sopenharmony_ci if (!(reg & FM10K_IP_NOTINRESET)) 618c2ecf20Sopenharmony_ci return FM10K_ERR_RESET_FAILED; 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci return 0; 648c2ecf20Sopenharmony_ci} 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci/** 678c2ecf20Sopenharmony_ci * fm10k_is_ari_hierarchy_pf - Indicate ARI hierarchy support 688c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 698c2ecf20Sopenharmony_ci * 708c2ecf20Sopenharmony_ci * Looks at the ARI hierarchy bit to determine whether ARI is supported or not. 718c2ecf20Sopenharmony_ci **/ 728c2ecf20Sopenharmony_cistatic bool fm10k_is_ari_hierarchy_pf(struct fm10k_hw *hw) 738c2ecf20Sopenharmony_ci{ 748c2ecf20Sopenharmony_ci u16 sriov_ctrl = fm10k_read_pci_cfg_word(hw, FM10K_PCIE_SRIOV_CTRL); 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci return !!(sriov_ctrl & FM10K_PCIE_SRIOV_CTRL_VFARI); 778c2ecf20Sopenharmony_ci} 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci/** 808c2ecf20Sopenharmony_ci * fm10k_init_hw_pf - PF hardware initialization 818c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 828c2ecf20Sopenharmony_ci * 838c2ecf20Sopenharmony_ci **/ 848c2ecf20Sopenharmony_cistatic s32 fm10k_init_hw_pf(struct fm10k_hw *hw) 858c2ecf20Sopenharmony_ci{ 868c2ecf20Sopenharmony_ci u32 dma_ctrl, txqctl; 878c2ecf20Sopenharmony_ci u16 i; 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* Establish default VSI as valid */ 908c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DGLORTDEC(fm10k_dglort_default), 0); 918c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DGLORTMAP(fm10k_dglort_default), 928c2ecf20Sopenharmony_ci FM10K_DGLORTMAP_ANY); 938c2ecf20Sopenharmony_ci 948c2ecf20Sopenharmony_ci /* Invalidate all other GLORT entries */ 958c2ecf20Sopenharmony_ci for (i = 1; i < FM10K_DGLORT_COUNT; i++) 968c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DGLORTMAP(i), FM10K_DGLORTMAP_NONE); 978c2ecf20Sopenharmony_ci 988c2ecf20Sopenharmony_ci /* reset ITR2(0) to point to itself */ 998c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(0), 0); 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci /* reset VF ITR2(0) to point to 0 avoid PF registers */ 1028c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), 0); 1038c2ecf20Sopenharmony_ci 1048c2ecf20Sopenharmony_ci /* loop through all PF ITR2 registers pointing them to the previous */ 1058c2ecf20Sopenharmony_ci for (i = 1; i < FM10K_ITR_REG_COUNT_PF; i++) 1068c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(i), i - 1); 1078c2ecf20Sopenharmony_ci 1088c2ecf20Sopenharmony_ci /* Enable interrupt moderator if not already enabled */ 1098c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR); 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* compute the default txqctl configuration */ 1128c2ecf20Sopenharmony_ci txqctl = FM10K_TXQCTL_PF | FM10K_TXQCTL_UNLIMITED_BW | 1138c2ecf20Sopenharmony_ci (hw->mac.default_vid << FM10K_TXQCTL_VID_SHIFT); 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci for (i = 0; i < FM10K_MAX_QUEUES; i++) { 1168c2ecf20Sopenharmony_ci /* configure rings for 256 Queue / 32 Descriptor cache mode */ 1178c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQDLOC(i), 1188c2ecf20Sopenharmony_ci (i * FM10K_TQDLOC_BASE_32_DESC) | 1198c2ecf20Sopenharmony_ci FM10K_TQDLOC_SIZE_32_DESC); 1208c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXQCTL(i), txqctl); 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci /* configure rings to provide TPH processing hints */ 1238c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TPH_TXCTRL(i), 1248c2ecf20Sopenharmony_ci FM10K_TPH_TXCTRL_DESC_TPHEN | 1258c2ecf20Sopenharmony_ci FM10K_TPH_TXCTRL_DESC_RROEN | 1268c2ecf20Sopenharmony_ci FM10K_TPH_TXCTRL_DESC_WROEN | 1278c2ecf20Sopenharmony_ci FM10K_TPH_TXCTRL_DATA_RROEN); 1288c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TPH_RXCTRL(i), 1298c2ecf20Sopenharmony_ci FM10K_TPH_RXCTRL_DESC_TPHEN | 1308c2ecf20Sopenharmony_ci FM10K_TPH_RXCTRL_DESC_RROEN | 1318c2ecf20Sopenharmony_ci FM10K_TPH_RXCTRL_DATA_WROEN | 1328c2ecf20Sopenharmony_ci FM10K_TPH_RXCTRL_HDR_WROEN); 1338c2ecf20Sopenharmony_ci } 1348c2ecf20Sopenharmony_ci 1358c2ecf20Sopenharmony_ci /* set max hold interval to align with 1.024 usec in all modes and 1368c2ecf20Sopenharmony_ci * store ITR scale 1378c2ecf20Sopenharmony_ci */ 1388c2ecf20Sopenharmony_ci switch (hw->bus.speed) { 1398c2ecf20Sopenharmony_ci case fm10k_bus_speed_2500: 1408c2ecf20Sopenharmony_ci dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN1; 1418c2ecf20Sopenharmony_ci hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN1; 1428c2ecf20Sopenharmony_ci break; 1438c2ecf20Sopenharmony_ci case fm10k_bus_speed_5000: 1448c2ecf20Sopenharmony_ci dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN2; 1458c2ecf20Sopenharmony_ci hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN2; 1468c2ecf20Sopenharmony_ci break; 1478c2ecf20Sopenharmony_ci case fm10k_bus_speed_8000: 1488c2ecf20Sopenharmony_ci dma_ctrl = FM10K_DMA_CTRL_MAX_HOLD_1US_GEN3; 1498c2ecf20Sopenharmony_ci hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3; 1508c2ecf20Sopenharmony_ci break; 1518c2ecf20Sopenharmony_ci default: 1528c2ecf20Sopenharmony_ci dma_ctrl = 0; 1538c2ecf20Sopenharmony_ci /* just in case, assume Gen3 ITR scale */ 1548c2ecf20Sopenharmony_ci hw->mac.itr_scale = FM10K_TDLEN_ITR_SCALE_GEN3; 1558c2ecf20Sopenharmony_ci break; 1568c2ecf20Sopenharmony_ci } 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci /* Configure TSO flags */ 1598c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DTXTCPFLGL, FM10K_TSO_FLAGS_LOW); 1608c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DTXTCPFLGH, FM10K_TSO_FLAGS_HI); 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci /* Enable DMA engine 1638c2ecf20Sopenharmony_ci * Set Rx Descriptor size to 32 1648c2ecf20Sopenharmony_ci * Set Minimum MSS to 64 1658c2ecf20Sopenharmony_ci * Set Maximum number of Rx queues to 256 / 32 Descriptor 1668c2ecf20Sopenharmony_ci */ 1678c2ecf20Sopenharmony_ci dma_ctrl |= FM10K_DMA_CTRL_TX_ENABLE | FM10K_DMA_CTRL_RX_ENABLE | 1688c2ecf20Sopenharmony_ci FM10K_DMA_CTRL_RX_DESC_SIZE | FM10K_DMA_CTRL_MINMSS_64 | 1698c2ecf20Sopenharmony_ci FM10K_DMA_CTRL_32_DESC; 1708c2ecf20Sopenharmony_ci 1718c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DMA_CTRL, dma_ctrl); 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci /* record maximum queue count, we limit ourselves to 128 */ 1748c2ecf20Sopenharmony_ci hw->mac.max_queues = FM10K_MAX_QUEUES_PF; 1758c2ecf20Sopenharmony_ci 1768c2ecf20Sopenharmony_ci /* We support either 64 VFs or 7 VFs depending on if we have ARI */ 1778c2ecf20Sopenharmony_ci hw->iov.total_vfs = fm10k_is_ari_hierarchy_pf(hw) ? 64 : 7; 1788c2ecf20Sopenharmony_ci 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci/** 1838c2ecf20Sopenharmony_ci * fm10k_update_vlan_pf - Update status of VLAN ID in VLAN filter table 1848c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 1858c2ecf20Sopenharmony_ci * @vid: VLAN ID to add to table 1868c2ecf20Sopenharmony_ci * @vsi: Index indicating VF ID or PF ID in table 1878c2ecf20Sopenharmony_ci * @set: Indicates if this is a set or clear operation 1888c2ecf20Sopenharmony_ci * 1898c2ecf20Sopenharmony_ci * This function adds or removes the corresponding VLAN ID from the VLAN 1908c2ecf20Sopenharmony_ci * filter table for the corresponding function. In addition to the 1918c2ecf20Sopenharmony_ci * standard set/clear that supports one bit a multi-bit write is 1928c2ecf20Sopenharmony_ci * supported to set 64 bits at a time. 1938c2ecf20Sopenharmony_ci **/ 1948c2ecf20Sopenharmony_cistatic s32 fm10k_update_vlan_pf(struct fm10k_hw *hw, u32 vid, u8 vsi, bool set) 1958c2ecf20Sopenharmony_ci{ 1968c2ecf20Sopenharmony_ci u32 vlan_table, reg, mask, bit, len; 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci /* verify the VSI index is valid */ 1998c2ecf20Sopenharmony_ci if (vsi > FM10K_VLAN_TABLE_VSI_MAX) 2008c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci /* VLAN multi-bit write: 2038c2ecf20Sopenharmony_ci * The multi-bit write has several parts to it. 2048c2ecf20Sopenharmony_ci * 24 16 8 0 2058c2ecf20Sopenharmony_ci * 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 2068c2ecf20Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2078c2ecf20Sopenharmony_ci * | RSVD0 | Length |C|RSVD0| VLAN ID | 2088c2ecf20Sopenharmony_ci * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ 2098c2ecf20Sopenharmony_ci * 2108c2ecf20Sopenharmony_ci * VLAN ID: Vlan Starting value 2118c2ecf20Sopenharmony_ci * RSVD0: Reserved section, must be 0 2128c2ecf20Sopenharmony_ci * C: Flag field, 0 is set, 1 is clear (Used in VF VLAN message) 2138c2ecf20Sopenharmony_ci * Length: Number of times to repeat the bit being set 2148c2ecf20Sopenharmony_ci */ 2158c2ecf20Sopenharmony_ci len = vid >> 16; 2168c2ecf20Sopenharmony_ci vid = (vid << 17) >> 17; 2178c2ecf20Sopenharmony_ci 2188c2ecf20Sopenharmony_ci /* verify the reserved 0 fields are 0 */ 2198c2ecf20Sopenharmony_ci if (len >= FM10K_VLAN_TABLE_VID_MAX || vid >= FM10K_VLAN_TABLE_VID_MAX) 2208c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* Loop through the table updating all required VLANs */ 2238c2ecf20Sopenharmony_ci for (reg = FM10K_VLAN_TABLE(vsi, vid / 32), bit = vid % 32; 2248c2ecf20Sopenharmony_ci len < FM10K_VLAN_TABLE_VID_MAX; 2258c2ecf20Sopenharmony_ci len -= 32 - bit, reg++, bit = 0) { 2268c2ecf20Sopenharmony_ci /* record the initial state of the register */ 2278c2ecf20Sopenharmony_ci vlan_table = fm10k_read_reg(hw, reg); 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci /* truncate mask if we are at the start or end of the run */ 2308c2ecf20Sopenharmony_ci mask = (~(u32)0 >> ((len < 31) ? 31 - len : 0)) << bit; 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci /* make necessary modifications to the register */ 2338c2ecf20Sopenharmony_ci mask &= set ? ~vlan_table : vlan_table; 2348c2ecf20Sopenharmony_ci if (mask) 2358c2ecf20Sopenharmony_ci fm10k_write_reg(hw, reg, vlan_table ^ mask); 2368c2ecf20Sopenharmony_ci } 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci return 0; 2398c2ecf20Sopenharmony_ci} 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci/** 2428c2ecf20Sopenharmony_ci * fm10k_read_mac_addr_pf - Read device MAC address 2438c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 2448c2ecf20Sopenharmony_ci * 2458c2ecf20Sopenharmony_ci * Reads the device MAC address from the SM_AREA and stores the value. 2468c2ecf20Sopenharmony_ci **/ 2478c2ecf20Sopenharmony_cistatic s32 fm10k_read_mac_addr_pf(struct fm10k_hw *hw) 2488c2ecf20Sopenharmony_ci{ 2498c2ecf20Sopenharmony_ci u8 perm_addr[ETH_ALEN]; 2508c2ecf20Sopenharmony_ci u32 serial_num; 2518c2ecf20Sopenharmony_ci 2528c2ecf20Sopenharmony_ci serial_num = fm10k_read_reg(hw, FM10K_SM_AREA(1)); 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* last byte should be all 1's */ 2558c2ecf20Sopenharmony_ci if ((~serial_num) << 24) 2568c2ecf20Sopenharmony_ci return FM10K_ERR_INVALID_MAC_ADDR; 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci perm_addr[0] = (u8)(serial_num >> 24); 2598c2ecf20Sopenharmony_ci perm_addr[1] = (u8)(serial_num >> 16); 2608c2ecf20Sopenharmony_ci perm_addr[2] = (u8)(serial_num >> 8); 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci serial_num = fm10k_read_reg(hw, FM10K_SM_AREA(0)); 2638c2ecf20Sopenharmony_ci 2648c2ecf20Sopenharmony_ci /* first byte should be all 1's */ 2658c2ecf20Sopenharmony_ci if ((~serial_num) >> 24) 2668c2ecf20Sopenharmony_ci return FM10K_ERR_INVALID_MAC_ADDR; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci perm_addr[3] = (u8)(serial_num >> 16); 2698c2ecf20Sopenharmony_ci perm_addr[4] = (u8)(serial_num >> 8); 2708c2ecf20Sopenharmony_ci perm_addr[5] = (u8)(serial_num); 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci ether_addr_copy(hw->mac.perm_addr, perm_addr); 2738c2ecf20Sopenharmony_ci ether_addr_copy(hw->mac.addr, perm_addr); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ci return 0; 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_ci/** 2798c2ecf20Sopenharmony_ci * fm10k_glort_valid_pf - Validate that the provided glort is valid 2808c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 2818c2ecf20Sopenharmony_ci * @glort: base glort to be validated 2828c2ecf20Sopenharmony_ci * 2838c2ecf20Sopenharmony_ci * This function will return an error if the provided glort is invalid 2848c2ecf20Sopenharmony_ci **/ 2858c2ecf20Sopenharmony_cibool fm10k_glort_valid_pf(struct fm10k_hw *hw, u16 glort) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci glort &= hw->mac.dglort_map >> FM10K_DGLORTMAP_MASK_SHIFT; 2888c2ecf20Sopenharmony_ci 2898c2ecf20Sopenharmony_ci return glort == (hw->mac.dglort_map & FM10K_DGLORTMAP_NONE); 2908c2ecf20Sopenharmony_ci} 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci/** 2938c2ecf20Sopenharmony_ci * fm10k_update_xc_addr_pf - Update device addresses 2948c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 2958c2ecf20Sopenharmony_ci * @glort: base resource tag for this request 2968c2ecf20Sopenharmony_ci * @mac: MAC address to add/remove from table 2978c2ecf20Sopenharmony_ci * @vid: VLAN ID to add/remove from table 2988c2ecf20Sopenharmony_ci * @add: Indicates if this is an add or remove operation 2998c2ecf20Sopenharmony_ci * @flags: flags field to indicate add and secure 3008c2ecf20Sopenharmony_ci * 3018c2ecf20Sopenharmony_ci * This function generates a message to the Switch API requesting 3028c2ecf20Sopenharmony_ci * that the given logical port add/remove the given L2 MAC/VLAN address. 3038c2ecf20Sopenharmony_ci **/ 3048c2ecf20Sopenharmony_cistatic s32 fm10k_update_xc_addr_pf(struct fm10k_hw *hw, u16 glort, 3058c2ecf20Sopenharmony_ci const u8 *mac, u16 vid, bool add, u8 flags) 3068c2ecf20Sopenharmony_ci{ 3078c2ecf20Sopenharmony_ci struct fm10k_mbx_info *mbx = &hw->mbx; 3088c2ecf20Sopenharmony_ci struct fm10k_mac_update mac_update; 3098c2ecf20Sopenharmony_ci u32 msg[5]; 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci /* clear set bit from VLAN ID */ 3128c2ecf20Sopenharmony_ci vid &= ~FM10K_VLAN_CLEAR; 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci /* if glort or VLAN are not valid return error */ 3158c2ecf20Sopenharmony_ci if (!fm10k_glort_valid_pf(hw, glort) || vid >= FM10K_VLAN_TABLE_VID_MAX) 3168c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci /* record fields */ 3198c2ecf20Sopenharmony_ci mac_update.mac_lower = cpu_to_le32(((u32)mac[2] << 24) | 3208c2ecf20Sopenharmony_ci ((u32)mac[3] << 16) | 3218c2ecf20Sopenharmony_ci ((u32)mac[4] << 8) | 3228c2ecf20Sopenharmony_ci ((u32)mac[5])); 3238c2ecf20Sopenharmony_ci mac_update.mac_upper = cpu_to_le16(((u16)mac[0] << 8) | 3248c2ecf20Sopenharmony_ci ((u16)mac[1])); 3258c2ecf20Sopenharmony_ci mac_update.vlan = cpu_to_le16(vid); 3268c2ecf20Sopenharmony_ci mac_update.glort = cpu_to_le16(glort); 3278c2ecf20Sopenharmony_ci mac_update.action = add ? 0 : 1; 3288c2ecf20Sopenharmony_ci mac_update.flags = flags; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci /* populate mac_update fields */ 3318c2ecf20Sopenharmony_ci fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_UPDATE_MAC_FWD_RULE); 3328c2ecf20Sopenharmony_ci fm10k_tlv_attr_put_le_struct(msg, FM10K_PF_ATTR_ID_MAC_UPDATE, 3338c2ecf20Sopenharmony_ci &mac_update, sizeof(mac_update)); 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_ci /* load onto outgoing mailbox */ 3368c2ecf20Sopenharmony_ci return mbx->ops.enqueue_tx(hw, mbx, msg); 3378c2ecf20Sopenharmony_ci} 3388c2ecf20Sopenharmony_ci 3398c2ecf20Sopenharmony_ci/** 3408c2ecf20Sopenharmony_ci * fm10k_update_uc_addr_pf - Update device unicast addresses 3418c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 3428c2ecf20Sopenharmony_ci * @glort: base resource tag for this request 3438c2ecf20Sopenharmony_ci * @mac: MAC address to add/remove from table 3448c2ecf20Sopenharmony_ci * @vid: VLAN ID to add/remove from table 3458c2ecf20Sopenharmony_ci * @add: Indicates if this is an add or remove operation 3468c2ecf20Sopenharmony_ci * @flags: flags field to indicate add and secure 3478c2ecf20Sopenharmony_ci * 3488c2ecf20Sopenharmony_ci * This function is used to add or remove unicast addresses for 3498c2ecf20Sopenharmony_ci * the PF. 3508c2ecf20Sopenharmony_ci **/ 3518c2ecf20Sopenharmony_cistatic s32 fm10k_update_uc_addr_pf(struct fm10k_hw *hw, u16 glort, 3528c2ecf20Sopenharmony_ci const u8 *mac, u16 vid, bool add, u8 flags) 3538c2ecf20Sopenharmony_ci{ 3548c2ecf20Sopenharmony_ci /* verify MAC address is valid */ 3558c2ecf20Sopenharmony_ci if (!is_valid_ether_addr(mac)) 3568c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, flags); 3598c2ecf20Sopenharmony_ci} 3608c2ecf20Sopenharmony_ci 3618c2ecf20Sopenharmony_ci/** 3628c2ecf20Sopenharmony_ci * fm10k_update_mc_addr_pf - Update device multicast addresses 3638c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 3648c2ecf20Sopenharmony_ci * @glort: base resource tag for this request 3658c2ecf20Sopenharmony_ci * @mac: MAC address to add/remove from table 3668c2ecf20Sopenharmony_ci * @vid: VLAN ID to add/remove from table 3678c2ecf20Sopenharmony_ci * @add: Indicates if this is an add or remove operation 3688c2ecf20Sopenharmony_ci * 3698c2ecf20Sopenharmony_ci * This function is used to add or remove multicast MAC addresses for 3708c2ecf20Sopenharmony_ci * the PF. 3718c2ecf20Sopenharmony_ci **/ 3728c2ecf20Sopenharmony_cistatic s32 fm10k_update_mc_addr_pf(struct fm10k_hw *hw, u16 glort, 3738c2ecf20Sopenharmony_ci const u8 *mac, u16 vid, bool add) 3748c2ecf20Sopenharmony_ci{ 3758c2ecf20Sopenharmony_ci /* verify multicast address is valid */ 3768c2ecf20Sopenharmony_ci if (!is_multicast_ether_addr(mac)) 3778c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 3788c2ecf20Sopenharmony_ci 3798c2ecf20Sopenharmony_ci return fm10k_update_xc_addr_pf(hw, glort, mac, vid, add, 0); 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_ci/** 3838c2ecf20Sopenharmony_ci * fm10k_update_xcast_mode_pf - Request update of multicast mode 3848c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 3858c2ecf20Sopenharmony_ci * @glort: base resource tag for this request 3868c2ecf20Sopenharmony_ci * @mode: integer value indicating mode being requested 3878c2ecf20Sopenharmony_ci * 3888c2ecf20Sopenharmony_ci * This function will attempt to request a higher mode for the port 3898c2ecf20Sopenharmony_ci * so that it can enable either multicast, multicast promiscuous, or 3908c2ecf20Sopenharmony_ci * promiscuous mode of operation. 3918c2ecf20Sopenharmony_ci **/ 3928c2ecf20Sopenharmony_cistatic s32 fm10k_update_xcast_mode_pf(struct fm10k_hw *hw, u16 glort, u8 mode) 3938c2ecf20Sopenharmony_ci{ 3948c2ecf20Sopenharmony_ci struct fm10k_mbx_info *mbx = &hw->mbx; 3958c2ecf20Sopenharmony_ci u32 msg[3], xcast_mode; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci if (mode > FM10K_XCAST_MODE_NONE) 3988c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 3998c2ecf20Sopenharmony_ci 4008c2ecf20Sopenharmony_ci /* if glort is not valid return error */ 4018c2ecf20Sopenharmony_ci if (!fm10k_glort_valid_pf(hw, glort)) 4028c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 4038c2ecf20Sopenharmony_ci 4048c2ecf20Sopenharmony_ci /* write xcast mode as a single u32 value, 4058c2ecf20Sopenharmony_ci * lower 16 bits: glort 4068c2ecf20Sopenharmony_ci * upper 16 bits: mode 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci xcast_mode = ((u32)mode << 16) | glort; 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci /* generate message requesting to change xcast mode */ 4118c2ecf20Sopenharmony_ci fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_XCAST_MODES); 4128c2ecf20Sopenharmony_ci fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_XCAST_MODE, xcast_mode); 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci /* load onto outgoing mailbox */ 4158c2ecf20Sopenharmony_ci return mbx->ops.enqueue_tx(hw, mbx, msg); 4168c2ecf20Sopenharmony_ci} 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci/** 4198c2ecf20Sopenharmony_ci * fm10k_update_int_moderator_pf - Update interrupt moderator linked list 4208c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 4218c2ecf20Sopenharmony_ci * 4228c2ecf20Sopenharmony_ci * This function walks through the MSI-X vector table to determine the 4238c2ecf20Sopenharmony_ci * number of active interrupts and based on that information updates the 4248c2ecf20Sopenharmony_ci * interrupt moderator linked list. 4258c2ecf20Sopenharmony_ci **/ 4268c2ecf20Sopenharmony_cistatic void fm10k_update_int_moderator_pf(struct fm10k_hw *hw) 4278c2ecf20Sopenharmony_ci{ 4288c2ecf20Sopenharmony_ci u32 i; 4298c2ecf20Sopenharmony_ci 4308c2ecf20Sopenharmony_ci /* Disable interrupt moderator */ 4318c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_INT_CTRL, 0); 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* loop through PF from last to first looking enabled vectors */ 4348c2ecf20Sopenharmony_ci for (i = FM10K_ITR_REG_COUNT_PF - 1; i; i--) { 4358c2ecf20Sopenharmony_ci if (!fm10k_read_reg(hw, FM10K_MSIX_VECTOR_MASK(i))) 4368c2ecf20Sopenharmony_ci break; 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci /* always reset VFITR2[0] to point to last enabled PF vector */ 4408c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(FM10K_ITR_REG_COUNT_PF), i); 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci /* reset ITR2[0] to point to last enabled PF vector */ 4438c2ecf20Sopenharmony_ci if (!hw->iov.num_vfs) 4448c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(0), i); 4458c2ecf20Sopenharmony_ci 4468c2ecf20Sopenharmony_ci /* Enable interrupt moderator */ 4478c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_INT_CTRL, FM10K_INT_CTRL_ENABLEMODERATOR); 4488c2ecf20Sopenharmony_ci} 4498c2ecf20Sopenharmony_ci 4508c2ecf20Sopenharmony_ci/** 4518c2ecf20Sopenharmony_ci * fm10k_update_lport_state_pf - Notify the switch of a change in port state 4528c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 4538c2ecf20Sopenharmony_ci * @glort: base resource tag for this request 4548c2ecf20Sopenharmony_ci * @count: number of logical ports being updated 4558c2ecf20Sopenharmony_ci * @enable: boolean value indicating enable or disable 4568c2ecf20Sopenharmony_ci * 4578c2ecf20Sopenharmony_ci * This function is used to add/remove a logical port from the switch. 4588c2ecf20Sopenharmony_ci **/ 4598c2ecf20Sopenharmony_cistatic s32 fm10k_update_lport_state_pf(struct fm10k_hw *hw, u16 glort, 4608c2ecf20Sopenharmony_ci u16 count, bool enable) 4618c2ecf20Sopenharmony_ci{ 4628c2ecf20Sopenharmony_ci struct fm10k_mbx_info *mbx = &hw->mbx; 4638c2ecf20Sopenharmony_ci u32 msg[3], lport_msg; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci /* do nothing if we are being asked to create or destroy 0 ports */ 4668c2ecf20Sopenharmony_ci if (!count) 4678c2ecf20Sopenharmony_ci return 0; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci /* if glort is not valid return error */ 4708c2ecf20Sopenharmony_ci if (!fm10k_glort_valid_pf(hw, glort)) 4718c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci /* reset multicast mode if deleting lport */ 4748c2ecf20Sopenharmony_ci if (!enable) 4758c2ecf20Sopenharmony_ci fm10k_update_xcast_mode_pf(hw, glort, FM10K_XCAST_MODE_NONE); 4768c2ecf20Sopenharmony_ci 4778c2ecf20Sopenharmony_ci /* construct the lport message from the 2 pieces of data we have */ 4788c2ecf20Sopenharmony_ci lport_msg = ((u32)count << 16) | glort; 4798c2ecf20Sopenharmony_ci 4808c2ecf20Sopenharmony_ci /* generate lport create/delete message */ 4818c2ecf20Sopenharmony_ci fm10k_tlv_msg_init(msg, enable ? FM10K_PF_MSG_ID_LPORT_CREATE : 4828c2ecf20Sopenharmony_ci FM10K_PF_MSG_ID_LPORT_DELETE); 4838c2ecf20Sopenharmony_ci fm10k_tlv_attr_put_u32(msg, FM10K_PF_ATTR_ID_PORT, lport_msg); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci /* load onto outgoing mailbox */ 4868c2ecf20Sopenharmony_ci return mbx->ops.enqueue_tx(hw, mbx, msg); 4878c2ecf20Sopenharmony_ci} 4888c2ecf20Sopenharmony_ci 4898c2ecf20Sopenharmony_ci/** 4908c2ecf20Sopenharmony_ci * fm10k_configure_dglort_map_pf - Configures GLORT entry and queues 4918c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 4928c2ecf20Sopenharmony_ci * @dglort: pointer to dglort configuration structure 4938c2ecf20Sopenharmony_ci * 4948c2ecf20Sopenharmony_ci * Reads the configuration structure contained in dglort_cfg and uses 4958c2ecf20Sopenharmony_ci * that information to then populate a DGLORTMAP/DEC entry and the queues 4968c2ecf20Sopenharmony_ci * to which it has been assigned. 4978c2ecf20Sopenharmony_ci **/ 4988c2ecf20Sopenharmony_cistatic s32 fm10k_configure_dglort_map_pf(struct fm10k_hw *hw, 4998c2ecf20Sopenharmony_ci struct fm10k_dglort_cfg *dglort) 5008c2ecf20Sopenharmony_ci{ 5018c2ecf20Sopenharmony_ci u16 glort, queue_count, vsi_count, pc_count; 5028c2ecf20Sopenharmony_ci u16 vsi, queue, pc, q_idx; 5038c2ecf20Sopenharmony_ci u32 txqctl, dglortdec, dglortmap; 5048c2ecf20Sopenharmony_ci 5058c2ecf20Sopenharmony_ci /* verify the dglort pointer */ 5068c2ecf20Sopenharmony_ci if (!dglort) 5078c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci /* verify the dglort values */ 5108c2ecf20Sopenharmony_ci if ((dglort->idx > 7) || (dglort->rss_l > 7) || (dglort->pc_l > 3) || 5118c2ecf20Sopenharmony_ci (dglort->vsi_l > 6) || (dglort->vsi_b > 64) || 5128c2ecf20Sopenharmony_ci (dglort->queue_l > 8) || (dglort->queue_b >= 256)) 5138c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 5148c2ecf20Sopenharmony_ci 5158c2ecf20Sopenharmony_ci /* determine count of VSIs and queues */ 5168c2ecf20Sopenharmony_ci queue_count = BIT(dglort->rss_l + dglort->pc_l); 5178c2ecf20Sopenharmony_ci vsi_count = BIT(dglort->vsi_l + dglort->queue_l); 5188c2ecf20Sopenharmony_ci glort = dglort->glort; 5198c2ecf20Sopenharmony_ci q_idx = dglort->queue_b; 5208c2ecf20Sopenharmony_ci 5218c2ecf20Sopenharmony_ci /* configure SGLORT for queues */ 5228c2ecf20Sopenharmony_ci for (vsi = 0; vsi < vsi_count; vsi++, glort++) { 5238c2ecf20Sopenharmony_ci for (queue = 0; queue < queue_count; queue++, q_idx++) { 5248c2ecf20Sopenharmony_ci if (q_idx >= FM10K_MAX_QUEUES) 5258c2ecf20Sopenharmony_ci break; 5268c2ecf20Sopenharmony_ci 5278c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TX_SGLORT(q_idx), glort); 5288c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RX_SGLORT(q_idx), glort); 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci } 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci /* determine count of PCs and queues */ 5338c2ecf20Sopenharmony_ci queue_count = BIT(dglort->queue_l + dglort->rss_l + dglort->vsi_l); 5348c2ecf20Sopenharmony_ci pc_count = BIT(dglort->pc_l); 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci /* configure PC for Tx queues */ 5378c2ecf20Sopenharmony_ci for (pc = 0; pc < pc_count; pc++) { 5388c2ecf20Sopenharmony_ci q_idx = pc + dglort->queue_b; 5398c2ecf20Sopenharmony_ci for (queue = 0; queue < queue_count; queue++) { 5408c2ecf20Sopenharmony_ci if (q_idx >= FM10K_MAX_QUEUES) 5418c2ecf20Sopenharmony_ci break; 5428c2ecf20Sopenharmony_ci 5438c2ecf20Sopenharmony_ci txqctl = fm10k_read_reg(hw, FM10K_TXQCTL(q_idx)); 5448c2ecf20Sopenharmony_ci txqctl &= ~FM10K_TXQCTL_PC_MASK; 5458c2ecf20Sopenharmony_ci txqctl |= pc << FM10K_TXQCTL_PC_SHIFT; 5468c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXQCTL(q_idx), txqctl); 5478c2ecf20Sopenharmony_ci 5488c2ecf20Sopenharmony_ci q_idx += pc_count; 5498c2ecf20Sopenharmony_ci } 5508c2ecf20Sopenharmony_ci } 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci /* configure DGLORTDEC */ 5538c2ecf20Sopenharmony_ci dglortdec = ((u32)(dglort->rss_l) << FM10K_DGLORTDEC_RSSLENGTH_SHIFT) | 5548c2ecf20Sopenharmony_ci ((u32)(dglort->queue_b) << FM10K_DGLORTDEC_QBASE_SHIFT) | 5558c2ecf20Sopenharmony_ci ((u32)(dglort->pc_l) << FM10K_DGLORTDEC_PCLENGTH_SHIFT) | 5568c2ecf20Sopenharmony_ci ((u32)(dglort->vsi_b) << FM10K_DGLORTDEC_VSIBASE_SHIFT) | 5578c2ecf20Sopenharmony_ci ((u32)(dglort->vsi_l) << FM10K_DGLORTDEC_VSILENGTH_SHIFT) | 5588c2ecf20Sopenharmony_ci ((u32)(dglort->queue_l)); 5598c2ecf20Sopenharmony_ci if (dglort->inner_rss) 5608c2ecf20Sopenharmony_ci dglortdec |= FM10K_DGLORTDEC_INNERRSS_ENABLE; 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci /* configure DGLORTMAP */ 5638c2ecf20Sopenharmony_ci dglortmap = (dglort->idx == fm10k_dglort_default) ? 5648c2ecf20Sopenharmony_ci FM10K_DGLORTMAP_ANY : FM10K_DGLORTMAP_ZERO; 5658c2ecf20Sopenharmony_ci dglortmap <<= dglort->vsi_l + dglort->queue_l + dglort->shared_l; 5668c2ecf20Sopenharmony_ci dglortmap |= dglort->glort; 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci /* write values to hardware */ 5698c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DGLORTDEC(dglort->idx), dglortdec); 5708c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_DGLORTMAP(dglort->idx), dglortmap); 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci return 0; 5738c2ecf20Sopenharmony_ci} 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ciu16 fm10k_queues_per_pool(struct fm10k_hw *hw) 5768c2ecf20Sopenharmony_ci{ 5778c2ecf20Sopenharmony_ci u16 num_pools = hw->iov.num_pools; 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci return (num_pools > 32) ? 2 : (num_pools > 16) ? 4 : (num_pools > 8) ? 5808c2ecf20Sopenharmony_ci 8 : FM10K_MAX_QUEUES_POOL; 5818c2ecf20Sopenharmony_ci} 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ciu16 fm10k_vf_queue_index(struct fm10k_hw *hw, u16 vf_idx) 5848c2ecf20Sopenharmony_ci{ 5858c2ecf20Sopenharmony_ci u16 num_vfs = hw->iov.num_vfs; 5868c2ecf20Sopenharmony_ci u16 vf_q_idx = FM10K_MAX_QUEUES; 5878c2ecf20Sopenharmony_ci 5888c2ecf20Sopenharmony_ci vf_q_idx -= fm10k_queues_per_pool(hw) * (num_vfs - vf_idx); 5898c2ecf20Sopenharmony_ci 5908c2ecf20Sopenharmony_ci return vf_q_idx; 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_cistatic u16 fm10k_vectors_per_pool(struct fm10k_hw *hw) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci u16 num_pools = hw->iov.num_pools; 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_ci return (num_pools > 32) ? 8 : (num_pools > 16) ? 16 : 5988c2ecf20Sopenharmony_ci FM10K_MAX_VECTORS_POOL; 5998c2ecf20Sopenharmony_ci} 6008c2ecf20Sopenharmony_ci 6018c2ecf20Sopenharmony_cistatic u16 fm10k_vf_vector_index(struct fm10k_hw *hw, u16 vf_idx) 6028c2ecf20Sopenharmony_ci{ 6038c2ecf20Sopenharmony_ci u16 vf_v_idx = FM10K_MAX_VECTORS_PF; 6048c2ecf20Sopenharmony_ci 6058c2ecf20Sopenharmony_ci vf_v_idx += fm10k_vectors_per_pool(hw) * vf_idx; 6068c2ecf20Sopenharmony_ci 6078c2ecf20Sopenharmony_ci return vf_v_idx; 6088c2ecf20Sopenharmony_ci} 6098c2ecf20Sopenharmony_ci 6108c2ecf20Sopenharmony_ci/** 6118c2ecf20Sopenharmony_ci * fm10k_iov_assign_resources_pf - Assign pool resources for virtualization 6128c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 6138c2ecf20Sopenharmony_ci * @num_vfs: number of VFs to be allocated 6148c2ecf20Sopenharmony_ci * @num_pools: number of virtualization pools to be allocated 6158c2ecf20Sopenharmony_ci * 6168c2ecf20Sopenharmony_ci * Allocates queues and traffic classes to virtualization entities to prepare 6178c2ecf20Sopenharmony_ci * the PF for SR-IOV and VMDq 6188c2ecf20Sopenharmony_ci **/ 6198c2ecf20Sopenharmony_cistatic s32 fm10k_iov_assign_resources_pf(struct fm10k_hw *hw, u16 num_vfs, 6208c2ecf20Sopenharmony_ci u16 num_pools) 6218c2ecf20Sopenharmony_ci{ 6228c2ecf20Sopenharmony_ci u16 qmap_stride, qpp, vpp, vf_q_idx, vf_q_idx0, qmap_idx; 6238c2ecf20Sopenharmony_ci u32 vid = hw->mac.default_vid << FM10K_TXQCTL_VID_SHIFT; 6248c2ecf20Sopenharmony_ci int i, j; 6258c2ecf20Sopenharmony_ci 6268c2ecf20Sopenharmony_ci /* hardware only supports up to 64 pools */ 6278c2ecf20Sopenharmony_ci if (num_pools > 64) 6288c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_ci /* the number of VFs cannot exceed the number of pools */ 6318c2ecf20Sopenharmony_ci if ((num_vfs > num_pools) || (num_vfs > hw->iov.total_vfs)) 6328c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 6338c2ecf20Sopenharmony_ci 6348c2ecf20Sopenharmony_ci /* record number of virtualization entities */ 6358c2ecf20Sopenharmony_ci hw->iov.num_vfs = num_vfs; 6368c2ecf20Sopenharmony_ci hw->iov.num_pools = num_pools; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci /* determine qmap offsets and counts */ 6398c2ecf20Sopenharmony_ci qmap_stride = (num_vfs > 8) ? 32 : 256; 6408c2ecf20Sopenharmony_ci qpp = fm10k_queues_per_pool(hw); 6418c2ecf20Sopenharmony_ci vpp = fm10k_vectors_per_pool(hw); 6428c2ecf20Sopenharmony_ci 6438c2ecf20Sopenharmony_ci /* calculate starting index for queues */ 6448c2ecf20Sopenharmony_ci vf_q_idx = fm10k_vf_queue_index(hw, 0); 6458c2ecf20Sopenharmony_ci qmap_idx = 0; 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* establish TCs with -1 credits and no quanta to prevent transmit */ 6488c2ecf20Sopenharmony_ci for (i = 0; i < num_vfs; i++) { 6498c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_MAXCREDIT(i), 0); 6508c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_RATE(i), 0); 6518c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_CREDIT(i), 6528c2ecf20Sopenharmony_ci FM10K_TC_CREDIT_CREDIT_MASK); 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci /* zero out all mbmem registers */ 6568c2ecf20Sopenharmony_ci for (i = FM10K_VFMBMEM_LEN * num_vfs; i--;) 6578c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_MBMEM(i), 0); 6588c2ecf20Sopenharmony_ci 6598c2ecf20Sopenharmony_ci /* clear event notification of VF FLR */ 6608c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_PFVFLREC(0), ~0); 6618c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_PFVFLREC(1), ~0); 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ci /* loop through unallocated rings assigning them back to PF */ 6648c2ecf20Sopenharmony_ci for (i = FM10K_MAX_QUEUES_PF; i < vf_q_idx; i++) { 6658c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXDCTL(i), 0); 6668c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXQCTL(i), FM10K_TXQCTL_PF | 6678c2ecf20Sopenharmony_ci FM10K_TXQCTL_UNLIMITED_BW | vid); 6688c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RXQCTL(i), FM10K_RXQCTL_PF); 6698c2ecf20Sopenharmony_ci } 6708c2ecf20Sopenharmony_ci 6718c2ecf20Sopenharmony_ci /* PF should have already updated VFITR2[0] */ 6728c2ecf20Sopenharmony_ci 6738c2ecf20Sopenharmony_ci /* update all ITR registers to flow to VFITR2[0] */ 6748c2ecf20Sopenharmony_ci for (i = FM10K_ITR_REG_COUNT_PF + 1; i < FM10K_ITR_REG_COUNT; i++) { 6758c2ecf20Sopenharmony_ci if (!(i & (vpp - 1))) 6768c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(i), i - vpp); 6778c2ecf20Sopenharmony_ci else 6788c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(i), i - 1); 6798c2ecf20Sopenharmony_ci } 6808c2ecf20Sopenharmony_ci 6818c2ecf20Sopenharmony_ci /* update PF ITR2[0] to reference the last vector */ 6828c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(0), 6838c2ecf20Sopenharmony_ci fm10k_vf_vector_index(hw, num_vfs - 1)); 6848c2ecf20Sopenharmony_ci 6858c2ecf20Sopenharmony_ci /* loop through rings populating rings and TCs */ 6868c2ecf20Sopenharmony_ci for (i = 0; i < num_vfs; i++) { 6878c2ecf20Sopenharmony_ci /* record index for VF queue 0 for use in end of loop */ 6888c2ecf20Sopenharmony_ci vf_q_idx0 = vf_q_idx; 6898c2ecf20Sopenharmony_ci 6908c2ecf20Sopenharmony_ci for (j = 0; j < qpp; j++, qmap_idx++, vf_q_idx++) { 6918c2ecf20Sopenharmony_ci /* assign VF and locked TC to queues */ 6928c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXDCTL(vf_q_idx), 0); 6938c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXQCTL(vf_q_idx), 6948c2ecf20Sopenharmony_ci (i << FM10K_TXQCTL_TC_SHIFT) | i | 6958c2ecf20Sopenharmony_ci FM10K_TXQCTL_VF | vid); 6968c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RXDCTL(vf_q_idx), 6978c2ecf20Sopenharmony_ci FM10K_RXDCTL_WRITE_BACK_MIN_DELAY | 6988c2ecf20Sopenharmony_ci FM10K_RXDCTL_DROP_ON_EMPTY); 6998c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RXQCTL(vf_q_idx), 7008c2ecf20Sopenharmony_ci (i << FM10K_RXQCTL_VF_SHIFT) | 7018c2ecf20Sopenharmony_ci FM10K_RXQCTL_VF); 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci /* map queue pair to VF */ 7048c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), vf_q_idx); 7058c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx), vf_q_idx); 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci /* repeat the first ring for all of the remaining VF rings */ 7098c2ecf20Sopenharmony_ci for (; j < qmap_stride; j++, qmap_idx++) { 7108c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), vf_q_idx0); 7118c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx), vf_q_idx0); 7128c2ecf20Sopenharmony_ci } 7138c2ecf20Sopenharmony_ci } 7148c2ecf20Sopenharmony_ci 7158c2ecf20Sopenharmony_ci /* loop through remaining indexes assigning all to queue 0 */ 7168c2ecf20Sopenharmony_ci while (qmap_idx < FM10K_TQMAP_TABLE_SIZE) { 7178c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), 0); 7188c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx), 0); 7198c2ecf20Sopenharmony_ci qmap_idx++; 7208c2ecf20Sopenharmony_ci } 7218c2ecf20Sopenharmony_ci 7228c2ecf20Sopenharmony_ci return 0; 7238c2ecf20Sopenharmony_ci} 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci/** 7268c2ecf20Sopenharmony_ci * fm10k_iov_configure_tc_pf - Configure the shaping group for VF 7278c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 7288c2ecf20Sopenharmony_ci * @vf_idx: index of VF receiving GLORT 7298c2ecf20Sopenharmony_ci * @rate: Rate indicated in Mb/s 7308c2ecf20Sopenharmony_ci * 7318c2ecf20Sopenharmony_ci * Configured the TC for a given VF to allow only up to a given number 7328c2ecf20Sopenharmony_ci * of Mb/s of outgoing Tx throughput. 7338c2ecf20Sopenharmony_ci **/ 7348c2ecf20Sopenharmony_cistatic s32 fm10k_iov_configure_tc_pf(struct fm10k_hw *hw, u16 vf_idx, int rate) 7358c2ecf20Sopenharmony_ci{ 7368c2ecf20Sopenharmony_ci /* configure defaults */ 7378c2ecf20Sopenharmony_ci u32 interval = FM10K_TC_RATE_INTERVAL_4US_GEN3; 7388c2ecf20Sopenharmony_ci u32 tc_rate = FM10K_TC_RATE_QUANTA_MASK; 7398c2ecf20Sopenharmony_ci 7408c2ecf20Sopenharmony_ci /* verify vf is in range */ 7418c2ecf20Sopenharmony_ci if (vf_idx >= hw->iov.num_vfs) 7428c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_ci /* set interval to align with 4.096 usec in all modes */ 7458c2ecf20Sopenharmony_ci switch (hw->bus.speed) { 7468c2ecf20Sopenharmony_ci case fm10k_bus_speed_2500: 7478c2ecf20Sopenharmony_ci interval = FM10K_TC_RATE_INTERVAL_4US_GEN1; 7488c2ecf20Sopenharmony_ci break; 7498c2ecf20Sopenharmony_ci case fm10k_bus_speed_5000: 7508c2ecf20Sopenharmony_ci interval = FM10K_TC_RATE_INTERVAL_4US_GEN2; 7518c2ecf20Sopenharmony_ci break; 7528c2ecf20Sopenharmony_ci default: 7538c2ecf20Sopenharmony_ci break; 7548c2ecf20Sopenharmony_ci } 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci if (rate) { 7578c2ecf20Sopenharmony_ci if (rate > FM10K_VF_TC_MAX || rate < FM10K_VF_TC_MIN) 7588c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 7598c2ecf20Sopenharmony_ci 7608c2ecf20Sopenharmony_ci /* The quanta is measured in Bytes per 4.096 or 8.192 usec 7618c2ecf20Sopenharmony_ci * The rate is provided in Mbits per second 7628c2ecf20Sopenharmony_ci * To tralslate from rate to quanta we need to multiply the 7638c2ecf20Sopenharmony_ci * rate by 8.192 usec and divide by 8 bits/byte. To avoid 7648c2ecf20Sopenharmony_ci * dealing with floating point we can round the values up 7658c2ecf20Sopenharmony_ci * to the nearest whole number ratio which gives us 128 / 125. 7668c2ecf20Sopenharmony_ci */ 7678c2ecf20Sopenharmony_ci tc_rate = (rate * 128) / 125; 7688c2ecf20Sopenharmony_ci 7698c2ecf20Sopenharmony_ci /* try to keep the rate limiting accurate by increasing 7708c2ecf20Sopenharmony_ci * the number of credits and interval for rates less than 4Gb/s 7718c2ecf20Sopenharmony_ci */ 7728c2ecf20Sopenharmony_ci if (rate < 4000) 7738c2ecf20Sopenharmony_ci interval <<= 1; 7748c2ecf20Sopenharmony_ci else 7758c2ecf20Sopenharmony_ci tc_rate >>= 1; 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci 7788c2ecf20Sopenharmony_ci /* update rate limiter with new values */ 7798c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_RATE(vf_idx), tc_rate | interval); 7808c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_MAXCREDIT(vf_idx), FM10K_TC_MAXCREDIT_64K); 7818c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_CREDIT(vf_idx), FM10K_TC_MAXCREDIT_64K); 7828c2ecf20Sopenharmony_ci 7838c2ecf20Sopenharmony_ci return 0; 7848c2ecf20Sopenharmony_ci} 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci/** 7878c2ecf20Sopenharmony_ci * fm10k_iov_assign_int_moderator_pf - Add VF interrupts to moderator list 7888c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 7898c2ecf20Sopenharmony_ci * @vf_idx: index of VF receiving GLORT 7908c2ecf20Sopenharmony_ci * 7918c2ecf20Sopenharmony_ci * Update the interrupt moderator linked list to include any MSI-X 7928c2ecf20Sopenharmony_ci * interrupts which the VF has enabled in the MSI-X vector table. 7938c2ecf20Sopenharmony_ci **/ 7948c2ecf20Sopenharmony_cistatic s32 fm10k_iov_assign_int_moderator_pf(struct fm10k_hw *hw, u16 vf_idx) 7958c2ecf20Sopenharmony_ci{ 7968c2ecf20Sopenharmony_ci u16 vf_v_idx, vf_v_limit, i; 7978c2ecf20Sopenharmony_ci 7988c2ecf20Sopenharmony_ci /* verify vf is in range */ 7998c2ecf20Sopenharmony_ci if (vf_idx >= hw->iov.num_vfs) 8008c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 8018c2ecf20Sopenharmony_ci 8028c2ecf20Sopenharmony_ci /* determine vector offset and count */ 8038c2ecf20Sopenharmony_ci vf_v_idx = fm10k_vf_vector_index(hw, vf_idx); 8048c2ecf20Sopenharmony_ci vf_v_limit = vf_v_idx + fm10k_vectors_per_pool(hw); 8058c2ecf20Sopenharmony_ci 8068c2ecf20Sopenharmony_ci /* search for first vector that is not masked */ 8078c2ecf20Sopenharmony_ci for (i = vf_v_limit - 1; i > vf_v_idx; i--) { 8088c2ecf20Sopenharmony_ci if (!fm10k_read_reg(hw, FM10K_MSIX_VECTOR_MASK(i))) 8098c2ecf20Sopenharmony_ci break; 8108c2ecf20Sopenharmony_ci } 8118c2ecf20Sopenharmony_ci 8128c2ecf20Sopenharmony_ci /* reset linked list so it now includes our active vectors */ 8138c2ecf20Sopenharmony_ci if (vf_idx == (hw->iov.num_vfs - 1)) 8148c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(0), i); 8158c2ecf20Sopenharmony_ci else 8168c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(vf_v_limit), i); 8178c2ecf20Sopenharmony_ci 8188c2ecf20Sopenharmony_ci return 0; 8198c2ecf20Sopenharmony_ci} 8208c2ecf20Sopenharmony_ci 8218c2ecf20Sopenharmony_ci/** 8228c2ecf20Sopenharmony_ci * fm10k_iov_assign_default_mac_vlan_pf - Assign a MAC and VLAN to VF 8238c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 8248c2ecf20Sopenharmony_ci * @vf_info: pointer to VF information structure 8258c2ecf20Sopenharmony_ci * 8268c2ecf20Sopenharmony_ci * Assign a MAC address and default VLAN to a VF and notify it of the update 8278c2ecf20Sopenharmony_ci **/ 8288c2ecf20Sopenharmony_cistatic s32 fm10k_iov_assign_default_mac_vlan_pf(struct fm10k_hw *hw, 8298c2ecf20Sopenharmony_ci struct fm10k_vf_info *vf_info) 8308c2ecf20Sopenharmony_ci{ 8318c2ecf20Sopenharmony_ci u16 qmap_stride, queues_per_pool, vf_q_idx, timeout, qmap_idx, i; 8328c2ecf20Sopenharmony_ci u32 msg[4], txdctl, txqctl, tdbal = 0, tdbah = 0; 8338c2ecf20Sopenharmony_ci s32 err = 0; 8348c2ecf20Sopenharmony_ci u16 vf_idx, vf_vid; 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci /* verify vf is in range */ 8378c2ecf20Sopenharmony_ci if (!vf_info || vf_info->vf_idx >= hw->iov.num_vfs) 8388c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci /* determine qmap offsets and counts */ 8418c2ecf20Sopenharmony_ci qmap_stride = (hw->iov.num_vfs > 8) ? 32 : 256; 8428c2ecf20Sopenharmony_ci queues_per_pool = fm10k_queues_per_pool(hw); 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci /* calculate starting index for queues */ 8458c2ecf20Sopenharmony_ci vf_idx = vf_info->vf_idx; 8468c2ecf20Sopenharmony_ci vf_q_idx = fm10k_vf_queue_index(hw, vf_idx); 8478c2ecf20Sopenharmony_ci qmap_idx = qmap_stride * vf_idx; 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci /* Determine correct default VLAN ID. The FM10K_VLAN_OVERRIDE bit is 8508c2ecf20Sopenharmony_ci * used here to indicate to the VF that it will not have privilege to 8518c2ecf20Sopenharmony_ci * write VLAN_TABLE. All policy is enforced on the PF but this allows 8528c2ecf20Sopenharmony_ci * the VF to correctly report errors to userspace requests. 8538c2ecf20Sopenharmony_ci */ 8548c2ecf20Sopenharmony_ci if (vf_info->pf_vid) 8558c2ecf20Sopenharmony_ci vf_vid = vf_info->pf_vid | FM10K_VLAN_OVERRIDE; 8568c2ecf20Sopenharmony_ci else 8578c2ecf20Sopenharmony_ci vf_vid = vf_info->sw_vid; 8588c2ecf20Sopenharmony_ci 8598c2ecf20Sopenharmony_ci /* generate MAC_ADDR request */ 8608c2ecf20Sopenharmony_ci fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_MAC_VLAN); 8618c2ecf20Sopenharmony_ci fm10k_tlv_attr_put_mac_vlan(msg, FM10K_MAC_VLAN_MSG_DEFAULT_MAC, 8628c2ecf20Sopenharmony_ci vf_info->mac, vf_vid); 8638c2ecf20Sopenharmony_ci 8648c2ecf20Sopenharmony_ci /* Configure Queue control register with new VLAN ID. The TXQCTL 8658c2ecf20Sopenharmony_ci * register is RO from the VF, so the PF must do this even in the 8668c2ecf20Sopenharmony_ci * case of notifying the VF of a new VID via the mailbox. 8678c2ecf20Sopenharmony_ci */ 8688c2ecf20Sopenharmony_ci txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) & 8698c2ecf20Sopenharmony_ci FM10K_TXQCTL_VID_MASK; 8708c2ecf20Sopenharmony_ci txqctl |= (vf_idx << FM10K_TXQCTL_TC_SHIFT) | 8718c2ecf20Sopenharmony_ci FM10K_TXQCTL_VF | vf_idx; 8728c2ecf20Sopenharmony_ci 8738c2ecf20Sopenharmony_ci for (i = 0; i < queues_per_pool; i++) 8748c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXQCTL(vf_q_idx + i), txqctl); 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci /* try loading a message onto outgoing mailbox first */ 8778c2ecf20Sopenharmony_ci if (vf_info->mbx.ops.enqueue_tx) { 8788c2ecf20Sopenharmony_ci err = vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); 8798c2ecf20Sopenharmony_ci if (err != FM10K_MBX_ERR_NO_MBX) 8808c2ecf20Sopenharmony_ci return err; 8818c2ecf20Sopenharmony_ci err = 0; 8828c2ecf20Sopenharmony_ci } 8838c2ecf20Sopenharmony_ci 8848c2ecf20Sopenharmony_ci /* If we aren't connected to a mailbox, this is most likely because 8858c2ecf20Sopenharmony_ci * the VF driver is not running. It should thus be safe to re-map 8868c2ecf20Sopenharmony_ci * queues and use the registers to pass the MAC address so that the VF 8878c2ecf20Sopenharmony_ci * driver gets correct information during its initialization. 8888c2ecf20Sopenharmony_ci */ 8898c2ecf20Sopenharmony_ci 8908c2ecf20Sopenharmony_ci /* MAP Tx queue back to 0 temporarily, and disable it */ 8918c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), 0); 8928c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXDCTL(vf_q_idx), 0); 8938c2ecf20Sopenharmony_ci 8948c2ecf20Sopenharmony_ci /* verify ring has disabled before modifying base address registers */ 8958c2ecf20Sopenharmony_ci txdctl = fm10k_read_reg(hw, FM10K_TXDCTL(vf_q_idx)); 8968c2ecf20Sopenharmony_ci for (timeout = 0; txdctl & FM10K_TXDCTL_ENABLE; timeout++) { 8978c2ecf20Sopenharmony_ci /* limit ourselves to a 1ms timeout */ 8988c2ecf20Sopenharmony_ci if (timeout == 10) { 8998c2ecf20Sopenharmony_ci err = FM10K_ERR_DMA_PENDING; 9008c2ecf20Sopenharmony_ci goto err_out; 9018c2ecf20Sopenharmony_ci } 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci usleep_range(100, 200); 9048c2ecf20Sopenharmony_ci txdctl = fm10k_read_reg(hw, FM10K_TXDCTL(vf_q_idx)); 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci /* Update base address registers to contain MAC address */ 9088c2ecf20Sopenharmony_ci if (is_valid_ether_addr(vf_info->mac)) { 9098c2ecf20Sopenharmony_ci tdbal = (((u32)vf_info->mac[3]) << 24) | 9108c2ecf20Sopenharmony_ci (((u32)vf_info->mac[4]) << 16) | 9118c2ecf20Sopenharmony_ci (((u32)vf_info->mac[5]) << 8); 9128c2ecf20Sopenharmony_ci 9138c2ecf20Sopenharmony_ci tdbah = (((u32)0xFF) << 24) | 9148c2ecf20Sopenharmony_ci (((u32)vf_info->mac[0]) << 16) | 9158c2ecf20Sopenharmony_ci (((u32)vf_info->mac[1]) << 8) | 9168c2ecf20Sopenharmony_ci ((u32)vf_info->mac[2]); 9178c2ecf20Sopenharmony_ci } 9188c2ecf20Sopenharmony_ci 9198c2ecf20Sopenharmony_ci /* Record the base address into queue 0 */ 9208c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx), tdbal); 9218c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx), tdbah); 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci /* Provide the VF the ITR scale, using software-defined fields in TDLEN 9248c2ecf20Sopenharmony_ci * to pass the information during VF initialization. See definition of 9258c2ecf20Sopenharmony_ci * FM10K_TDLEN_ITR_SCALE_SHIFT for more details. 9268c2ecf20Sopenharmony_ci */ 9278c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TDLEN(vf_q_idx), hw->mac.itr_scale << 9288c2ecf20Sopenharmony_ci FM10K_TDLEN_ITR_SCALE_SHIFT); 9298c2ecf20Sopenharmony_ci 9308c2ecf20Sopenharmony_cierr_out: 9318c2ecf20Sopenharmony_ci /* restore the queue back to VF ownership */ 9328c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx), vf_q_idx); 9338c2ecf20Sopenharmony_ci return err; 9348c2ecf20Sopenharmony_ci} 9358c2ecf20Sopenharmony_ci 9368c2ecf20Sopenharmony_ci/** 9378c2ecf20Sopenharmony_ci * fm10k_iov_reset_resources_pf - Reassign queues and interrupts to a VF 9388c2ecf20Sopenharmony_ci * @hw: pointer to the HW structure 9398c2ecf20Sopenharmony_ci * @vf_info: pointer to VF information structure 9408c2ecf20Sopenharmony_ci * 9418c2ecf20Sopenharmony_ci * Reassign the interrupts and queues to a VF following an FLR 9428c2ecf20Sopenharmony_ci **/ 9438c2ecf20Sopenharmony_cistatic s32 fm10k_iov_reset_resources_pf(struct fm10k_hw *hw, 9448c2ecf20Sopenharmony_ci struct fm10k_vf_info *vf_info) 9458c2ecf20Sopenharmony_ci{ 9468c2ecf20Sopenharmony_ci u16 qmap_stride, queues_per_pool, vf_q_idx, qmap_idx; 9478c2ecf20Sopenharmony_ci u32 tdbal = 0, tdbah = 0, txqctl, rxqctl; 9488c2ecf20Sopenharmony_ci u16 vf_v_idx, vf_v_limit, vf_vid; 9498c2ecf20Sopenharmony_ci u8 vf_idx = vf_info->vf_idx; 9508c2ecf20Sopenharmony_ci int i; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci /* verify vf is in range */ 9538c2ecf20Sopenharmony_ci if (vf_idx >= hw->iov.num_vfs) 9548c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 9558c2ecf20Sopenharmony_ci 9568c2ecf20Sopenharmony_ci /* clear event notification of VF FLR */ 9578c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_PFVFLREC(vf_idx / 32), BIT(vf_idx % 32)); 9588c2ecf20Sopenharmony_ci 9598c2ecf20Sopenharmony_ci /* force timeout and then disconnect the mailbox */ 9608c2ecf20Sopenharmony_ci vf_info->mbx.timeout = 0; 9618c2ecf20Sopenharmony_ci if (vf_info->mbx.ops.disconnect) 9628c2ecf20Sopenharmony_ci vf_info->mbx.ops.disconnect(hw, &vf_info->mbx); 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci /* determine vector offset and count */ 9658c2ecf20Sopenharmony_ci vf_v_idx = fm10k_vf_vector_index(hw, vf_idx); 9668c2ecf20Sopenharmony_ci vf_v_limit = vf_v_idx + fm10k_vectors_per_pool(hw); 9678c2ecf20Sopenharmony_ci 9688c2ecf20Sopenharmony_ci /* determine qmap offsets and counts */ 9698c2ecf20Sopenharmony_ci qmap_stride = (hw->iov.num_vfs > 8) ? 32 : 256; 9708c2ecf20Sopenharmony_ci queues_per_pool = fm10k_queues_per_pool(hw); 9718c2ecf20Sopenharmony_ci qmap_idx = qmap_stride * vf_idx; 9728c2ecf20Sopenharmony_ci 9738c2ecf20Sopenharmony_ci /* make all the queues inaccessible to the VF */ 9748c2ecf20Sopenharmony_ci for (i = qmap_idx; i < (qmap_idx + qmap_stride); i++) { 9758c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(i), 0); 9768c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RQMAP(i), 0); 9778c2ecf20Sopenharmony_ci } 9788c2ecf20Sopenharmony_ci 9798c2ecf20Sopenharmony_ci /* calculate starting index for queues */ 9808c2ecf20Sopenharmony_ci vf_q_idx = fm10k_vf_queue_index(hw, vf_idx); 9818c2ecf20Sopenharmony_ci 9828c2ecf20Sopenharmony_ci /* determine correct default VLAN ID */ 9838c2ecf20Sopenharmony_ci if (vf_info->pf_vid) 9848c2ecf20Sopenharmony_ci vf_vid = vf_info->pf_vid; 9858c2ecf20Sopenharmony_ci else 9868c2ecf20Sopenharmony_ci vf_vid = vf_info->sw_vid; 9878c2ecf20Sopenharmony_ci 9888c2ecf20Sopenharmony_ci /* configure Queue control register */ 9898c2ecf20Sopenharmony_ci txqctl = ((u32)vf_vid << FM10K_TXQCTL_VID_SHIFT) | 9908c2ecf20Sopenharmony_ci (vf_idx << FM10K_TXQCTL_TC_SHIFT) | 9918c2ecf20Sopenharmony_ci FM10K_TXQCTL_VF | vf_idx; 9928c2ecf20Sopenharmony_ci rxqctl = (vf_idx << FM10K_RXQCTL_VF_SHIFT) | FM10K_RXQCTL_VF; 9938c2ecf20Sopenharmony_ci 9948c2ecf20Sopenharmony_ci /* stop further DMA and reset queue ownership back to VF */ 9958c2ecf20Sopenharmony_ci for (i = vf_q_idx; i < (queues_per_pool + vf_q_idx); i++) { 9968c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXDCTL(i), 0); 9978c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TXQCTL(i), txqctl); 9988c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RXDCTL(i), 9998c2ecf20Sopenharmony_ci FM10K_RXDCTL_WRITE_BACK_MIN_DELAY | 10008c2ecf20Sopenharmony_ci FM10K_RXDCTL_DROP_ON_EMPTY); 10018c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RXQCTL(i), rxqctl); 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci 10048c2ecf20Sopenharmony_ci /* reset TC with -1 credits and no quanta to prevent transmit */ 10058c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_MAXCREDIT(vf_idx), 0); 10068c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_RATE(vf_idx), 0); 10078c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TC_CREDIT(vf_idx), 10088c2ecf20Sopenharmony_ci FM10K_TC_CREDIT_CREDIT_MASK); 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci /* update our first entry in the table based on previous VF */ 10118c2ecf20Sopenharmony_ci if (!vf_idx) 10128c2ecf20Sopenharmony_ci hw->mac.ops.update_int_moderator(hw); 10138c2ecf20Sopenharmony_ci else 10148c2ecf20Sopenharmony_ci hw->iov.ops.assign_int_moderator(hw, vf_idx - 1); 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci /* reset linked list so it now includes our active vectors */ 10178c2ecf20Sopenharmony_ci if (vf_idx == (hw->iov.num_vfs - 1)) 10188c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(0), vf_v_idx); 10198c2ecf20Sopenharmony_ci else 10208c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(vf_v_limit), vf_v_idx); 10218c2ecf20Sopenharmony_ci 10228c2ecf20Sopenharmony_ci /* link remaining vectors so that next points to previous */ 10238c2ecf20Sopenharmony_ci for (vf_v_idx++; vf_v_idx < vf_v_limit; vf_v_idx++) 10248c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_ITR2(vf_v_idx), vf_v_idx - 1); 10258c2ecf20Sopenharmony_ci 10268c2ecf20Sopenharmony_ci /* zero out MBMEM, VLAN_TABLE, RETA, RSSRK, and MRQC registers */ 10278c2ecf20Sopenharmony_ci for (i = FM10K_VFMBMEM_LEN; i--;) 10288c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_MBMEM_VF(vf_idx, i), 0); 10298c2ecf20Sopenharmony_ci for (i = FM10K_VLAN_TABLE_SIZE; i--;) 10308c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_VLAN_TABLE(vf_info->vsi, i), 0); 10318c2ecf20Sopenharmony_ci for (i = FM10K_RETA_SIZE; i--;) 10328c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RETA(vf_info->vsi, i), 0); 10338c2ecf20Sopenharmony_ci for (i = FM10K_RSSRK_SIZE; i--;) 10348c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RSSRK(vf_info->vsi, i), 0); 10358c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_MRQC(vf_info->vsi), 0); 10368c2ecf20Sopenharmony_ci 10378c2ecf20Sopenharmony_ci /* Update base address registers to contain MAC address */ 10388c2ecf20Sopenharmony_ci if (is_valid_ether_addr(vf_info->mac)) { 10398c2ecf20Sopenharmony_ci tdbal = (((u32)vf_info->mac[3]) << 24) | 10408c2ecf20Sopenharmony_ci (((u32)vf_info->mac[4]) << 16) | 10418c2ecf20Sopenharmony_ci (((u32)vf_info->mac[5]) << 8); 10428c2ecf20Sopenharmony_ci tdbah = (((u32)0xFF) << 24) | 10438c2ecf20Sopenharmony_ci (((u32)vf_info->mac[0]) << 16) | 10448c2ecf20Sopenharmony_ci (((u32)vf_info->mac[1]) << 8) | 10458c2ecf20Sopenharmony_ci ((u32)vf_info->mac[2]); 10468c2ecf20Sopenharmony_ci } 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_ci /* map queue pairs back to VF from last to first */ 10498c2ecf20Sopenharmony_ci for (i = queues_per_pool; i--;) { 10508c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TDBAL(vf_q_idx + i), tdbal); 10518c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TDBAH(vf_q_idx + i), tdbah); 10528c2ecf20Sopenharmony_ci /* See definition of FM10K_TDLEN_ITR_SCALE_SHIFT for an 10538c2ecf20Sopenharmony_ci * explanation of how TDLEN is used. 10548c2ecf20Sopenharmony_ci */ 10558c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TDLEN(vf_q_idx + i), 10568c2ecf20Sopenharmony_ci hw->mac.itr_scale << 10578c2ecf20Sopenharmony_ci FM10K_TDLEN_ITR_SCALE_SHIFT); 10588c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx + i); 10598c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx + i); 10608c2ecf20Sopenharmony_ci } 10618c2ecf20Sopenharmony_ci 10628c2ecf20Sopenharmony_ci /* repeat the first ring for all the remaining VF rings */ 10638c2ecf20Sopenharmony_ci for (i = queues_per_pool; i < qmap_stride; i++) { 10648c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_TQMAP(qmap_idx + i), vf_q_idx); 10658c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_RQMAP(qmap_idx + i), vf_q_idx); 10668c2ecf20Sopenharmony_ci } 10678c2ecf20Sopenharmony_ci 10688c2ecf20Sopenharmony_ci return 0; 10698c2ecf20Sopenharmony_ci} 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci/** 10728c2ecf20Sopenharmony_ci * fm10k_iov_set_lport_pf - Assign and enable a logical port for a given VF 10738c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 10748c2ecf20Sopenharmony_ci * @vf_info: pointer to VF information structure 10758c2ecf20Sopenharmony_ci * @lport_idx: Logical port offset from the hardware glort 10768c2ecf20Sopenharmony_ci * @flags: Set of capability flags to extend port beyond basic functionality 10778c2ecf20Sopenharmony_ci * 10788c2ecf20Sopenharmony_ci * This function allows enabling a VF port by assigning it a GLORT and 10798c2ecf20Sopenharmony_ci * setting the flags so that it can enable an Rx mode. 10808c2ecf20Sopenharmony_ci **/ 10818c2ecf20Sopenharmony_cistatic s32 fm10k_iov_set_lport_pf(struct fm10k_hw *hw, 10828c2ecf20Sopenharmony_ci struct fm10k_vf_info *vf_info, 10838c2ecf20Sopenharmony_ci u16 lport_idx, u8 flags) 10848c2ecf20Sopenharmony_ci{ 10858c2ecf20Sopenharmony_ci u16 glort = (hw->mac.dglort_map + lport_idx) & FM10K_DGLORTMAP_NONE; 10868c2ecf20Sopenharmony_ci 10878c2ecf20Sopenharmony_ci /* if glort is not valid return error */ 10888c2ecf20Sopenharmony_ci if (!fm10k_glort_valid_pf(hw, glort)) 10898c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 10908c2ecf20Sopenharmony_ci 10918c2ecf20Sopenharmony_ci vf_info->vf_flags = flags | FM10K_VF_FLAG_NONE_CAPABLE; 10928c2ecf20Sopenharmony_ci vf_info->glort = glort; 10938c2ecf20Sopenharmony_ci 10948c2ecf20Sopenharmony_ci return 0; 10958c2ecf20Sopenharmony_ci} 10968c2ecf20Sopenharmony_ci 10978c2ecf20Sopenharmony_ci/** 10988c2ecf20Sopenharmony_ci * fm10k_iov_reset_lport_pf - Disable a logical port for a given VF 10998c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 11008c2ecf20Sopenharmony_ci * @vf_info: pointer to VF information structure 11018c2ecf20Sopenharmony_ci * 11028c2ecf20Sopenharmony_ci * This function disables a VF port by stripping it of a GLORT and 11038c2ecf20Sopenharmony_ci * setting the flags so that it cannot enable any Rx mode. 11048c2ecf20Sopenharmony_ci **/ 11058c2ecf20Sopenharmony_cistatic void fm10k_iov_reset_lport_pf(struct fm10k_hw *hw, 11068c2ecf20Sopenharmony_ci struct fm10k_vf_info *vf_info) 11078c2ecf20Sopenharmony_ci{ 11088c2ecf20Sopenharmony_ci u32 msg[1]; 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ci /* need to disable the port if it is already enabled */ 11118c2ecf20Sopenharmony_ci if (FM10K_VF_FLAG_ENABLED(vf_info)) { 11128c2ecf20Sopenharmony_ci /* notify switch that this port has been disabled */ 11138c2ecf20Sopenharmony_ci fm10k_update_lport_state_pf(hw, vf_info->glort, 1, false); 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_ci /* generate port state response to notify VF it is not ready */ 11168c2ecf20Sopenharmony_ci fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); 11178c2ecf20Sopenharmony_ci vf_info->mbx.ops.enqueue_tx(hw, &vf_info->mbx, msg); 11188c2ecf20Sopenharmony_ci } 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* clear flags and glort if it exists */ 11218c2ecf20Sopenharmony_ci vf_info->vf_flags = 0; 11228c2ecf20Sopenharmony_ci vf_info->glort = 0; 11238c2ecf20Sopenharmony_ci} 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci/** 11268c2ecf20Sopenharmony_ci * fm10k_iov_update_stats_pf - Updates hardware related statistics for VFs 11278c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 11288c2ecf20Sopenharmony_ci * @q: stats for all queues of a VF 11298c2ecf20Sopenharmony_ci * @vf_idx: index of VF 11308c2ecf20Sopenharmony_ci * 11318c2ecf20Sopenharmony_ci * This function collects queue stats for VFs. 11328c2ecf20Sopenharmony_ci **/ 11338c2ecf20Sopenharmony_cistatic void fm10k_iov_update_stats_pf(struct fm10k_hw *hw, 11348c2ecf20Sopenharmony_ci struct fm10k_hw_stats_q *q, 11358c2ecf20Sopenharmony_ci u16 vf_idx) 11368c2ecf20Sopenharmony_ci{ 11378c2ecf20Sopenharmony_ci u32 idx, qpp; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci /* get stats for all of the queues */ 11408c2ecf20Sopenharmony_ci qpp = fm10k_queues_per_pool(hw); 11418c2ecf20Sopenharmony_ci idx = fm10k_vf_queue_index(hw, vf_idx); 11428c2ecf20Sopenharmony_ci fm10k_update_hw_stats_q(hw, q, idx, qpp); 11438c2ecf20Sopenharmony_ci} 11448c2ecf20Sopenharmony_ci 11458c2ecf20Sopenharmony_ci/** 11468c2ecf20Sopenharmony_ci * fm10k_iov_msg_msix_pf - Message handler for MSI-X request from VF 11478c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 11488c2ecf20Sopenharmony_ci * @results: Pointer array to message, results[0] is pointer to message 11498c2ecf20Sopenharmony_ci * @mbx: Pointer to mailbox information structure 11508c2ecf20Sopenharmony_ci * 11518c2ecf20Sopenharmony_ci * This function is a default handler for MSI-X requests from the VF. The 11528c2ecf20Sopenharmony_ci * assumption is that in this case it is acceptable to just directly 11538c2ecf20Sopenharmony_ci * hand off the message from the VF to the underlying shared code. 11548c2ecf20Sopenharmony_ci **/ 11558c2ecf20Sopenharmony_cis32 fm10k_iov_msg_msix_pf(struct fm10k_hw *hw, u32 __always_unused **results, 11568c2ecf20Sopenharmony_ci struct fm10k_mbx_info *mbx) 11578c2ecf20Sopenharmony_ci{ 11588c2ecf20Sopenharmony_ci struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; 11598c2ecf20Sopenharmony_ci u8 vf_idx = vf_info->vf_idx; 11608c2ecf20Sopenharmony_ci 11618c2ecf20Sopenharmony_ci return hw->iov.ops.assign_int_moderator(hw, vf_idx); 11628c2ecf20Sopenharmony_ci} 11638c2ecf20Sopenharmony_ci 11648c2ecf20Sopenharmony_ci/** 11658c2ecf20Sopenharmony_ci * fm10k_iov_select_vid - Select correct default VLAN ID 11668c2ecf20Sopenharmony_ci * @vf_info: pointer to VF information structure 11678c2ecf20Sopenharmony_ci * @vid: VLAN ID to correct 11688c2ecf20Sopenharmony_ci * 11698c2ecf20Sopenharmony_ci * Will report an error if the VLAN ID is out of range. For VID = 0, it will 11708c2ecf20Sopenharmony_ci * return either the pf_vid or sw_vid depending on which one is set. 11718c2ecf20Sopenharmony_ci */ 11728c2ecf20Sopenharmony_cis32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid) 11738c2ecf20Sopenharmony_ci{ 11748c2ecf20Sopenharmony_ci if (!vid) 11758c2ecf20Sopenharmony_ci return vf_info->pf_vid ? vf_info->pf_vid : vf_info->sw_vid; 11768c2ecf20Sopenharmony_ci else if (vf_info->pf_vid && vid != vf_info->pf_vid) 11778c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 11788c2ecf20Sopenharmony_ci else 11798c2ecf20Sopenharmony_ci return vid; 11808c2ecf20Sopenharmony_ci} 11818c2ecf20Sopenharmony_ci 11828c2ecf20Sopenharmony_ci/** 11838c2ecf20Sopenharmony_ci * fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF 11848c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 11858c2ecf20Sopenharmony_ci * @results: Pointer array to message, results[0] is pointer to message 11868c2ecf20Sopenharmony_ci * @mbx: Pointer to mailbox information structure 11878c2ecf20Sopenharmony_ci * 11888c2ecf20Sopenharmony_ci * This function is a default handler for MAC/VLAN requests from the VF. 11898c2ecf20Sopenharmony_ci * The assumption is that in this case it is acceptable to just directly 11908c2ecf20Sopenharmony_ci * hand off the message from the VF to the underlying shared code. 11918c2ecf20Sopenharmony_ci **/ 11928c2ecf20Sopenharmony_cis32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results, 11938c2ecf20Sopenharmony_ci struct fm10k_mbx_info *mbx) 11948c2ecf20Sopenharmony_ci{ 11958c2ecf20Sopenharmony_ci struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; 11968c2ecf20Sopenharmony_ci u8 mac[ETH_ALEN]; 11978c2ecf20Sopenharmony_ci u32 *result; 11988c2ecf20Sopenharmony_ci int err = 0; 11998c2ecf20Sopenharmony_ci bool set; 12008c2ecf20Sopenharmony_ci u16 vlan; 12018c2ecf20Sopenharmony_ci u32 vid; 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci /* we shouldn't be updating rules on a disabled interface */ 12048c2ecf20Sopenharmony_ci if (!FM10K_VF_FLAG_ENABLED(vf_info)) 12058c2ecf20Sopenharmony_ci err = FM10K_ERR_PARAM; 12068c2ecf20Sopenharmony_ci 12078c2ecf20Sopenharmony_ci if (!err && !!results[FM10K_MAC_VLAN_MSG_VLAN]) { 12088c2ecf20Sopenharmony_ci result = results[FM10K_MAC_VLAN_MSG_VLAN]; 12098c2ecf20Sopenharmony_ci 12108c2ecf20Sopenharmony_ci /* record VLAN id requested */ 12118c2ecf20Sopenharmony_ci err = fm10k_tlv_attr_get_u32(result, &vid); 12128c2ecf20Sopenharmony_ci if (err) 12138c2ecf20Sopenharmony_ci return err; 12148c2ecf20Sopenharmony_ci 12158c2ecf20Sopenharmony_ci set = !(vid & FM10K_VLAN_CLEAR); 12168c2ecf20Sopenharmony_ci vid &= ~FM10K_VLAN_CLEAR; 12178c2ecf20Sopenharmony_ci 12188c2ecf20Sopenharmony_ci /* if the length field has been set, this is a multi-bit 12198c2ecf20Sopenharmony_ci * update request. For multi-bit requests, simply disallow 12208c2ecf20Sopenharmony_ci * them when the pf_vid has been set. In this case, the PF 12218c2ecf20Sopenharmony_ci * should have already cleared the VLAN_TABLE, and if we 12228c2ecf20Sopenharmony_ci * allowed them, it could allow a rogue VF to receive traffic 12238c2ecf20Sopenharmony_ci * on a VLAN it was not assigned. In the single-bit case, we 12248c2ecf20Sopenharmony_ci * need to modify requests for VLAN 0 to use the default PF or 12258c2ecf20Sopenharmony_ci * SW vid when assigned. 12268c2ecf20Sopenharmony_ci */ 12278c2ecf20Sopenharmony_ci 12288c2ecf20Sopenharmony_ci if (vid >> 16) { 12298c2ecf20Sopenharmony_ci /* prevent multi-bit requests when PF has 12308c2ecf20Sopenharmony_ci * administratively set the VLAN for this VF 12318c2ecf20Sopenharmony_ci */ 12328c2ecf20Sopenharmony_ci if (vf_info->pf_vid) 12338c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 12348c2ecf20Sopenharmony_ci } else { 12358c2ecf20Sopenharmony_ci err = fm10k_iov_select_vid(vf_info, (u16)vid); 12368c2ecf20Sopenharmony_ci if (err < 0) 12378c2ecf20Sopenharmony_ci return err; 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_ci vid = err; 12408c2ecf20Sopenharmony_ci } 12418c2ecf20Sopenharmony_ci 12428c2ecf20Sopenharmony_ci /* update VSI info for VF in regards to VLAN table */ 12438c2ecf20Sopenharmony_ci err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set); 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci 12468c2ecf20Sopenharmony_ci if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) { 12478c2ecf20Sopenharmony_ci result = results[FM10K_MAC_VLAN_MSG_MAC]; 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_ci /* record unicast MAC address requested */ 12508c2ecf20Sopenharmony_ci err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan); 12518c2ecf20Sopenharmony_ci if (err) 12528c2ecf20Sopenharmony_ci return err; 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci /* block attempts to set MAC for a locked device */ 12558c2ecf20Sopenharmony_ci if (is_valid_ether_addr(vf_info->mac) && 12568c2ecf20Sopenharmony_ci !ether_addr_equal(mac, vf_info->mac)) 12578c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 12588c2ecf20Sopenharmony_ci 12598c2ecf20Sopenharmony_ci set = !(vlan & FM10K_VLAN_CLEAR); 12608c2ecf20Sopenharmony_ci vlan &= ~FM10K_VLAN_CLEAR; 12618c2ecf20Sopenharmony_ci 12628c2ecf20Sopenharmony_ci err = fm10k_iov_select_vid(vf_info, vlan); 12638c2ecf20Sopenharmony_ci if (err < 0) 12648c2ecf20Sopenharmony_ci return err; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci vlan = (u16)err; 12678c2ecf20Sopenharmony_ci 12688c2ecf20Sopenharmony_ci /* notify switch of request for new unicast address */ 12698c2ecf20Sopenharmony_ci err = hw->mac.ops.update_uc_addr(hw, vf_info->glort, 12708c2ecf20Sopenharmony_ci mac, vlan, set, 0); 12718c2ecf20Sopenharmony_ci } 12728c2ecf20Sopenharmony_ci 12738c2ecf20Sopenharmony_ci if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) { 12748c2ecf20Sopenharmony_ci result = results[FM10K_MAC_VLAN_MSG_MULTICAST]; 12758c2ecf20Sopenharmony_ci 12768c2ecf20Sopenharmony_ci /* record multicast MAC address requested */ 12778c2ecf20Sopenharmony_ci err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan); 12788c2ecf20Sopenharmony_ci if (err) 12798c2ecf20Sopenharmony_ci return err; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci /* verify that the VF is allowed to request multicast */ 12828c2ecf20Sopenharmony_ci if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED)) 12838c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci set = !(vlan & FM10K_VLAN_CLEAR); 12868c2ecf20Sopenharmony_ci vlan &= ~FM10K_VLAN_CLEAR; 12878c2ecf20Sopenharmony_ci 12888c2ecf20Sopenharmony_ci err = fm10k_iov_select_vid(vf_info, vlan); 12898c2ecf20Sopenharmony_ci if (err < 0) 12908c2ecf20Sopenharmony_ci return err; 12918c2ecf20Sopenharmony_ci 12928c2ecf20Sopenharmony_ci vlan = (u16)err; 12938c2ecf20Sopenharmony_ci 12948c2ecf20Sopenharmony_ci /* notify switch of request for new multicast address */ 12958c2ecf20Sopenharmony_ci err = hw->mac.ops.update_mc_addr(hw, vf_info->glort, 12968c2ecf20Sopenharmony_ci mac, vlan, set); 12978c2ecf20Sopenharmony_ci } 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci return err; 13008c2ecf20Sopenharmony_ci} 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci/** 13038c2ecf20Sopenharmony_ci * fm10k_iov_supported_xcast_mode_pf - Determine best match for xcast mode 13048c2ecf20Sopenharmony_ci * @vf_info: VF info structure containing capability flags 13058c2ecf20Sopenharmony_ci * @mode: Requested xcast mode 13068c2ecf20Sopenharmony_ci * 13078c2ecf20Sopenharmony_ci * This function outputs the mode that most closely matches the requested 13088c2ecf20Sopenharmony_ci * mode. If not modes match it will request we disable the port 13098c2ecf20Sopenharmony_ci **/ 13108c2ecf20Sopenharmony_cistatic u8 fm10k_iov_supported_xcast_mode_pf(struct fm10k_vf_info *vf_info, 13118c2ecf20Sopenharmony_ci u8 mode) 13128c2ecf20Sopenharmony_ci{ 13138c2ecf20Sopenharmony_ci u8 vf_flags = vf_info->vf_flags; 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci /* match up mode to capabilities as best as possible */ 13168c2ecf20Sopenharmony_ci switch (mode) { 13178c2ecf20Sopenharmony_ci case FM10K_XCAST_MODE_PROMISC: 13188c2ecf20Sopenharmony_ci if (vf_flags & FM10K_VF_FLAG_PROMISC_CAPABLE) 13198c2ecf20Sopenharmony_ci return FM10K_XCAST_MODE_PROMISC; 13208c2ecf20Sopenharmony_ci fallthrough; 13218c2ecf20Sopenharmony_ci case FM10K_XCAST_MODE_ALLMULTI: 13228c2ecf20Sopenharmony_ci if (vf_flags & FM10K_VF_FLAG_ALLMULTI_CAPABLE) 13238c2ecf20Sopenharmony_ci return FM10K_XCAST_MODE_ALLMULTI; 13248c2ecf20Sopenharmony_ci fallthrough; 13258c2ecf20Sopenharmony_ci case FM10K_XCAST_MODE_MULTI: 13268c2ecf20Sopenharmony_ci if (vf_flags & FM10K_VF_FLAG_MULTI_CAPABLE) 13278c2ecf20Sopenharmony_ci return FM10K_XCAST_MODE_MULTI; 13288c2ecf20Sopenharmony_ci fallthrough; 13298c2ecf20Sopenharmony_ci case FM10K_XCAST_MODE_NONE: 13308c2ecf20Sopenharmony_ci if (vf_flags & FM10K_VF_FLAG_NONE_CAPABLE) 13318c2ecf20Sopenharmony_ci return FM10K_XCAST_MODE_NONE; 13328c2ecf20Sopenharmony_ci fallthrough; 13338c2ecf20Sopenharmony_ci default: 13348c2ecf20Sopenharmony_ci break; 13358c2ecf20Sopenharmony_ci } 13368c2ecf20Sopenharmony_ci 13378c2ecf20Sopenharmony_ci /* disable interface as it should not be able to request any */ 13388c2ecf20Sopenharmony_ci return FM10K_XCAST_MODE_DISABLE; 13398c2ecf20Sopenharmony_ci} 13408c2ecf20Sopenharmony_ci 13418c2ecf20Sopenharmony_ci/** 13428c2ecf20Sopenharmony_ci * fm10k_iov_msg_lport_state_pf - Message handler for port state requests 13438c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 13448c2ecf20Sopenharmony_ci * @results: Pointer array to message, results[0] is pointer to message 13458c2ecf20Sopenharmony_ci * @mbx: Pointer to mailbox information structure 13468c2ecf20Sopenharmony_ci * 13478c2ecf20Sopenharmony_ci * This function is a default handler for port state requests. The port 13488c2ecf20Sopenharmony_ci * state requests for now are basic and consist of enabling or disabling 13498c2ecf20Sopenharmony_ci * the port. 13508c2ecf20Sopenharmony_ci **/ 13518c2ecf20Sopenharmony_cis32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *hw, u32 **results, 13528c2ecf20Sopenharmony_ci struct fm10k_mbx_info *mbx) 13538c2ecf20Sopenharmony_ci{ 13548c2ecf20Sopenharmony_ci struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx; 13558c2ecf20Sopenharmony_ci s32 err = 0; 13568c2ecf20Sopenharmony_ci u32 msg[2]; 13578c2ecf20Sopenharmony_ci u8 mode = 0; 13588c2ecf20Sopenharmony_ci 13598c2ecf20Sopenharmony_ci /* verify VF is allowed to enable even minimal mode */ 13608c2ecf20Sopenharmony_ci if (!(vf_info->vf_flags & FM10K_VF_FLAG_NONE_CAPABLE)) 13618c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci if (!!results[FM10K_LPORT_STATE_MSG_XCAST_MODE]) { 13648c2ecf20Sopenharmony_ci u32 *result = results[FM10K_LPORT_STATE_MSG_XCAST_MODE]; 13658c2ecf20Sopenharmony_ci 13668c2ecf20Sopenharmony_ci /* XCAST mode update requested */ 13678c2ecf20Sopenharmony_ci err = fm10k_tlv_attr_get_u8(result, &mode); 13688c2ecf20Sopenharmony_ci if (err) 13698c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 13708c2ecf20Sopenharmony_ci 13718c2ecf20Sopenharmony_ci /* prep for possible demotion depending on capabilities */ 13728c2ecf20Sopenharmony_ci mode = fm10k_iov_supported_xcast_mode_pf(vf_info, mode); 13738c2ecf20Sopenharmony_ci 13748c2ecf20Sopenharmony_ci /* if mode is not currently enabled, enable it */ 13758c2ecf20Sopenharmony_ci if (!(FM10K_VF_FLAG_ENABLED(vf_info) & BIT(mode))) 13768c2ecf20Sopenharmony_ci fm10k_update_xcast_mode_pf(hw, vf_info->glort, mode); 13778c2ecf20Sopenharmony_ci 13788c2ecf20Sopenharmony_ci /* swap mode back to a bit flag */ 13798c2ecf20Sopenharmony_ci mode = FM10K_VF_FLAG_SET_MODE(mode); 13808c2ecf20Sopenharmony_ci } else if (!results[FM10K_LPORT_STATE_MSG_DISABLE]) { 13818c2ecf20Sopenharmony_ci /* need to disable the port if it is already enabled */ 13828c2ecf20Sopenharmony_ci if (FM10K_VF_FLAG_ENABLED(vf_info)) 13838c2ecf20Sopenharmony_ci err = fm10k_update_lport_state_pf(hw, vf_info->glort, 13848c2ecf20Sopenharmony_ci 1, false); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci /* we need to clear VF_FLAG_ENABLED flags in order to ensure 13878c2ecf20Sopenharmony_ci * that we actually re-enable the LPORT state below. Note that 13888c2ecf20Sopenharmony_ci * this has no impact if the VF is already disabled, as the 13898c2ecf20Sopenharmony_ci * flags are already cleared. 13908c2ecf20Sopenharmony_ci */ 13918c2ecf20Sopenharmony_ci if (!err) 13928c2ecf20Sopenharmony_ci vf_info->vf_flags = FM10K_VF_FLAG_CAPABLE(vf_info); 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci /* when enabling the port we should reset the rate limiters */ 13958c2ecf20Sopenharmony_ci hw->iov.ops.configure_tc(hw, vf_info->vf_idx, vf_info->rate); 13968c2ecf20Sopenharmony_ci 13978c2ecf20Sopenharmony_ci /* set mode for minimal functionality */ 13988c2ecf20Sopenharmony_ci mode = FM10K_VF_FLAG_SET_MODE_NONE; 13998c2ecf20Sopenharmony_ci 14008c2ecf20Sopenharmony_ci /* generate port state response to notify VF it is ready */ 14018c2ecf20Sopenharmony_ci fm10k_tlv_msg_init(msg, FM10K_VF_MSG_ID_LPORT_STATE); 14028c2ecf20Sopenharmony_ci fm10k_tlv_attr_put_bool(msg, FM10K_LPORT_STATE_MSG_READY); 14038c2ecf20Sopenharmony_ci mbx->ops.enqueue_tx(hw, mbx, msg); 14048c2ecf20Sopenharmony_ci } 14058c2ecf20Sopenharmony_ci 14068c2ecf20Sopenharmony_ci /* if enable state toggled note the update */ 14078c2ecf20Sopenharmony_ci if (!err && (!FM10K_VF_FLAG_ENABLED(vf_info) != !mode)) 14088c2ecf20Sopenharmony_ci err = fm10k_update_lport_state_pf(hw, vf_info->glort, 1, 14098c2ecf20Sopenharmony_ci !!mode); 14108c2ecf20Sopenharmony_ci 14118c2ecf20Sopenharmony_ci /* if state change succeeded, then update our stored state */ 14128c2ecf20Sopenharmony_ci mode |= FM10K_VF_FLAG_CAPABLE(vf_info); 14138c2ecf20Sopenharmony_ci if (!err) 14148c2ecf20Sopenharmony_ci vf_info->vf_flags = mode; 14158c2ecf20Sopenharmony_ci 14168c2ecf20Sopenharmony_ci return err; 14178c2ecf20Sopenharmony_ci} 14188c2ecf20Sopenharmony_ci 14198c2ecf20Sopenharmony_ci/** 14208c2ecf20Sopenharmony_ci * fm10k_update_stats_hw_pf - Updates hardware related statistics of PF 14218c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 14228c2ecf20Sopenharmony_ci * @stats: pointer to the stats structure to update 14238c2ecf20Sopenharmony_ci * 14248c2ecf20Sopenharmony_ci * This function collects and aggregates global and per queue hardware 14258c2ecf20Sopenharmony_ci * statistics. 14268c2ecf20Sopenharmony_ci **/ 14278c2ecf20Sopenharmony_cistatic void fm10k_update_hw_stats_pf(struct fm10k_hw *hw, 14288c2ecf20Sopenharmony_ci struct fm10k_hw_stats *stats) 14298c2ecf20Sopenharmony_ci{ 14308c2ecf20Sopenharmony_ci u32 timeout, ur, ca, um, xec, vlan_drop, loopback_drop, nodesc_drop; 14318c2ecf20Sopenharmony_ci u32 id, id_prev; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci /* Use Tx queue 0 as a canary to detect a reset */ 14348c2ecf20Sopenharmony_ci id = fm10k_read_reg(hw, FM10K_TXQCTL(0)); 14358c2ecf20Sopenharmony_ci 14368c2ecf20Sopenharmony_ci /* Read Global Statistics */ 14378c2ecf20Sopenharmony_ci do { 14388c2ecf20Sopenharmony_ci timeout = fm10k_read_hw_stats_32b(hw, FM10K_STATS_TIMEOUT, 14398c2ecf20Sopenharmony_ci &stats->timeout); 14408c2ecf20Sopenharmony_ci ur = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UR, &stats->ur); 14418c2ecf20Sopenharmony_ci ca = fm10k_read_hw_stats_32b(hw, FM10K_STATS_CA, &stats->ca); 14428c2ecf20Sopenharmony_ci um = fm10k_read_hw_stats_32b(hw, FM10K_STATS_UM, &stats->um); 14438c2ecf20Sopenharmony_ci xec = fm10k_read_hw_stats_32b(hw, FM10K_STATS_XEC, &stats->xec); 14448c2ecf20Sopenharmony_ci vlan_drop = fm10k_read_hw_stats_32b(hw, FM10K_STATS_VLAN_DROP, 14458c2ecf20Sopenharmony_ci &stats->vlan_drop); 14468c2ecf20Sopenharmony_ci loopback_drop = 14478c2ecf20Sopenharmony_ci fm10k_read_hw_stats_32b(hw, 14488c2ecf20Sopenharmony_ci FM10K_STATS_LOOPBACK_DROP, 14498c2ecf20Sopenharmony_ci &stats->loopback_drop); 14508c2ecf20Sopenharmony_ci nodesc_drop = fm10k_read_hw_stats_32b(hw, 14518c2ecf20Sopenharmony_ci FM10K_STATS_NODESC_DROP, 14528c2ecf20Sopenharmony_ci &stats->nodesc_drop); 14538c2ecf20Sopenharmony_ci 14548c2ecf20Sopenharmony_ci /* if value has not changed then we have consistent data */ 14558c2ecf20Sopenharmony_ci id_prev = id; 14568c2ecf20Sopenharmony_ci id = fm10k_read_reg(hw, FM10K_TXQCTL(0)); 14578c2ecf20Sopenharmony_ci } while ((id ^ id_prev) & FM10K_TXQCTL_ID_MASK); 14588c2ecf20Sopenharmony_ci 14598c2ecf20Sopenharmony_ci /* drop non-ID bits and set VALID ID bit */ 14608c2ecf20Sopenharmony_ci id &= FM10K_TXQCTL_ID_MASK; 14618c2ecf20Sopenharmony_ci id |= FM10K_STAT_VALID; 14628c2ecf20Sopenharmony_ci 14638c2ecf20Sopenharmony_ci /* Update Global Statistics */ 14648c2ecf20Sopenharmony_ci if (stats->stats_idx == id) { 14658c2ecf20Sopenharmony_ci stats->timeout.count += timeout; 14668c2ecf20Sopenharmony_ci stats->ur.count += ur; 14678c2ecf20Sopenharmony_ci stats->ca.count += ca; 14688c2ecf20Sopenharmony_ci stats->um.count += um; 14698c2ecf20Sopenharmony_ci stats->xec.count += xec; 14708c2ecf20Sopenharmony_ci stats->vlan_drop.count += vlan_drop; 14718c2ecf20Sopenharmony_ci stats->loopback_drop.count += loopback_drop; 14728c2ecf20Sopenharmony_ci stats->nodesc_drop.count += nodesc_drop; 14738c2ecf20Sopenharmony_ci } 14748c2ecf20Sopenharmony_ci 14758c2ecf20Sopenharmony_ci /* Update bases and record current PF id */ 14768c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->timeout, timeout); 14778c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->ur, ur); 14788c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->ca, ca); 14798c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->um, um); 14808c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->xec, xec); 14818c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->vlan_drop, vlan_drop); 14828c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->loopback_drop, loopback_drop); 14838c2ecf20Sopenharmony_ci fm10k_update_hw_base_32b(&stats->nodesc_drop, nodesc_drop); 14848c2ecf20Sopenharmony_ci stats->stats_idx = id; 14858c2ecf20Sopenharmony_ci 14868c2ecf20Sopenharmony_ci /* Update Queue Statistics */ 14878c2ecf20Sopenharmony_ci fm10k_update_hw_stats_q(hw, stats->q, 0, hw->mac.max_queues); 14888c2ecf20Sopenharmony_ci} 14898c2ecf20Sopenharmony_ci 14908c2ecf20Sopenharmony_ci/** 14918c2ecf20Sopenharmony_ci * fm10k_rebind_hw_stats_pf - Resets base for hardware statistics of PF 14928c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 14938c2ecf20Sopenharmony_ci * @stats: pointer to the stats structure to update 14948c2ecf20Sopenharmony_ci * 14958c2ecf20Sopenharmony_ci * This function resets the base for global and per queue hardware 14968c2ecf20Sopenharmony_ci * statistics. 14978c2ecf20Sopenharmony_ci **/ 14988c2ecf20Sopenharmony_cistatic void fm10k_rebind_hw_stats_pf(struct fm10k_hw *hw, 14998c2ecf20Sopenharmony_ci struct fm10k_hw_stats *stats) 15008c2ecf20Sopenharmony_ci{ 15018c2ecf20Sopenharmony_ci /* Unbind Global Statistics */ 15028c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->timeout); 15038c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->ur); 15048c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->ca); 15058c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->um); 15068c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->xec); 15078c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->vlan_drop); 15088c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->loopback_drop); 15098c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_32b(&stats->nodesc_drop); 15108c2ecf20Sopenharmony_ci 15118c2ecf20Sopenharmony_ci /* Unbind Queue Statistics */ 15128c2ecf20Sopenharmony_ci fm10k_unbind_hw_stats_q(stats->q, 0, hw->mac.max_queues); 15138c2ecf20Sopenharmony_ci 15148c2ecf20Sopenharmony_ci /* Reinitialize bases for all stats */ 15158c2ecf20Sopenharmony_ci fm10k_update_hw_stats_pf(hw, stats); 15168c2ecf20Sopenharmony_ci} 15178c2ecf20Sopenharmony_ci 15188c2ecf20Sopenharmony_ci/** 15198c2ecf20Sopenharmony_ci * fm10k_set_dma_mask_pf - Configures PhyAddrSpace to limit DMA to system 15208c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 15218c2ecf20Sopenharmony_ci * @dma_mask: 64 bit DMA mask required for platform 15228c2ecf20Sopenharmony_ci * 15238c2ecf20Sopenharmony_ci * This function sets the PHYADDR.PhyAddrSpace bits for the endpoint in order 15248c2ecf20Sopenharmony_ci * to limit the access to memory beyond what is physically in the system. 15258c2ecf20Sopenharmony_ci **/ 15268c2ecf20Sopenharmony_cistatic void fm10k_set_dma_mask_pf(struct fm10k_hw *hw, u64 dma_mask) 15278c2ecf20Sopenharmony_ci{ 15288c2ecf20Sopenharmony_ci /* we need to write the upper 32 bits of DMA mask to PhyAddrSpace */ 15298c2ecf20Sopenharmony_ci u32 phyaddr = (u32)(dma_mask >> 32); 15308c2ecf20Sopenharmony_ci 15318c2ecf20Sopenharmony_ci fm10k_write_reg(hw, FM10K_PHYADDR, phyaddr); 15328c2ecf20Sopenharmony_ci} 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_ci/** 15358c2ecf20Sopenharmony_ci * fm10k_get_fault_pf - Record a fault in one of the interface units 15368c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 15378c2ecf20Sopenharmony_ci * @type: pointer to fault type register offset 15388c2ecf20Sopenharmony_ci * @fault: pointer to memory location to record the fault 15398c2ecf20Sopenharmony_ci * 15408c2ecf20Sopenharmony_ci * Record the fault register contents to the fault data structure and 15418c2ecf20Sopenharmony_ci * clear the entry from the register. 15428c2ecf20Sopenharmony_ci * 15438c2ecf20Sopenharmony_ci * Returns ERR_PARAM if invalid register is specified or no error is present. 15448c2ecf20Sopenharmony_ci **/ 15458c2ecf20Sopenharmony_cistatic s32 fm10k_get_fault_pf(struct fm10k_hw *hw, int type, 15468c2ecf20Sopenharmony_ci struct fm10k_fault *fault) 15478c2ecf20Sopenharmony_ci{ 15488c2ecf20Sopenharmony_ci u32 func; 15498c2ecf20Sopenharmony_ci 15508c2ecf20Sopenharmony_ci /* verify the fault register is in range and is aligned */ 15518c2ecf20Sopenharmony_ci switch (type) { 15528c2ecf20Sopenharmony_ci case FM10K_PCA_FAULT: 15538c2ecf20Sopenharmony_ci case FM10K_THI_FAULT: 15548c2ecf20Sopenharmony_ci case FM10K_FUM_FAULT: 15558c2ecf20Sopenharmony_ci break; 15568c2ecf20Sopenharmony_ci default: 15578c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 15588c2ecf20Sopenharmony_ci } 15598c2ecf20Sopenharmony_ci 15608c2ecf20Sopenharmony_ci /* only service faults that are valid */ 15618c2ecf20Sopenharmony_ci func = fm10k_read_reg(hw, type + FM10K_FAULT_FUNC); 15628c2ecf20Sopenharmony_ci if (!(func & FM10K_FAULT_FUNC_VALID)) 15638c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 15648c2ecf20Sopenharmony_ci 15658c2ecf20Sopenharmony_ci /* read remaining fields */ 15668c2ecf20Sopenharmony_ci fault->address = fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_HI); 15678c2ecf20Sopenharmony_ci fault->address <<= 32; 15688c2ecf20Sopenharmony_ci fault->address |= fm10k_read_reg(hw, type + FM10K_FAULT_ADDR_LO); 15698c2ecf20Sopenharmony_ci fault->specinfo = fm10k_read_reg(hw, type + FM10K_FAULT_SPECINFO); 15708c2ecf20Sopenharmony_ci 15718c2ecf20Sopenharmony_ci /* clear valid bit to allow for next error */ 15728c2ecf20Sopenharmony_ci fm10k_write_reg(hw, type + FM10K_FAULT_FUNC, FM10K_FAULT_FUNC_VALID); 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci /* Record which function triggered the error */ 15758c2ecf20Sopenharmony_ci if (func & FM10K_FAULT_FUNC_PF) 15768c2ecf20Sopenharmony_ci fault->func = 0; 15778c2ecf20Sopenharmony_ci else 15788c2ecf20Sopenharmony_ci fault->func = 1 + ((func & FM10K_FAULT_FUNC_VF_MASK) >> 15798c2ecf20Sopenharmony_ci FM10K_FAULT_FUNC_VF_SHIFT); 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ci /* record fault type */ 15828c2ecf20Sopenharmony_ci fault->type = func & FM10K_FAULT_FUNC_TYPE_MASK; 15838c2ecf20Sopenharmony_ci 15848c2ecf20Sopenharmony_ci return 0; 15858c2ecf20Sopenharmony_ci} 15868c2ecf20Sopenharmony_ci 15878c2ecf20Sopenharmony_ci/** 15888c2ecf20Sopenharmony_ci * fm10k_request_lport_map_pf - Request LPORT map from the switch API 15898c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 15908c2ecf20Sopenharmony_ci * 15918c2ecf20Sopenharmony_ci **/ 15928c2ecf20Sopenharmony_cistatic s32 fm10k_request_lport_map_pf(struct fm10k_hw *hw) 15938c2ecf20Sopenharmony_ci{ 15948c2ecf20Sopenharmony_ci struct fm10k_mbx_info *mbx = &hw->mbx; 15958c2ecf20Sopenharmony_ci u32 msg[1]; 15968c2ecf20Sopenharmony_ci 15978c2ecf20Sopenharmony_ci /* issue request asking for LPORT map */ 15988c2ecf20Sopenharmony_ci fm10k_tlv_msg_init(msg, FM10K_PF_MSG_ID_LPORT_MAP); 15998c2ecf20Sopenharmony_ci 16008c2ecf20Sopenharmony_ci /* load onto outgoing mailbox */ 16018c2ecf20Sopenharmony_ci return mbx->ops.enqueue_tx(hw, mbx, msg); 16028c2ecf20Sopenharmony_ci} 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci/** 16058c2ecf20Sopenharmony_ci * fm10k_get_host_state_pf - Returns the state of the switch and mailbox 16068c2ecf20Sopenharmony_ci * @hw: pointer to hardware structure 16078c2ecf20Sopenharmony_ci * @switch_ready: pointer to boolean value that will record switch state 16088c2ecf20Sopenharmony_ci * 16098c2ecf20Sopenharmony_ci * This function will check the DMA_CTRL2 register and mailbox in order 16108c2ecf20Sopenharmony_ci * to determine if the switch is ready for the PF to begin requesting 16118c2ecf20Sopenharmony_ci * addresses and mapping traffic to the local interface. 16128c2ecf20Sopenharmony_ci **/ 16138c2ecf20Sopenharmony_cistatic s32 fm10k_get_host_state_pf(struct fm10k_hw *hw, bool *switch_ready) 16148c2ecf20Sopenharmony_ci{ 16158c2ecf20Sopenharmony_ci u32 dma_ctrl2; 16168c2ecf20Sopenharmony_ci 16178c2ecf20Sopenharmony_ci /* verify the switch is ready for interaction */ 16188c2ecf20Sopenharmony_ci dma_ctrl2 = fm10k_read_reg(hw, FM10K_DMA_CTRL2); 16198c2ecf20Sopenharmony_ci if (!(dma_ctrl2 & FM10K_DMA_CTRL2_SWITCH_READY)) 16208c2ecf20Sopenharmony_ci return 0; 16218c2ecf20Sopenharmony_ci 16228c2ecf20Sopenharmony_ci /* retrieve generic host state info */ 16238c2ecf20Sopenharmony_ci return fm10k_get_host_state_generic(hw, switch_ready); 16248c2ecf20Sopenharmony_ci} 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci/* This structure defines the attibutes to be parsed below */ 16278c2ecf20Sopenharmony_ciconst struct fm10k_tlv_attr fm10k_lport_map_msg_attr[] = { 16288c2ecf20Sopenharmony_ci FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR, 16298c2ecf20Sopenharmony_ci sizeof(struct fm10k_swapi_error)), 16308c2ecf20Sopenharmony_ci FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_LPORT_MAP), 16318c2ecf20Sopenharmony_ci FM10K_TLV_ATTR_LAST 16328c2ecf20Sopenharmony_ci}; 16338c2ecf20Sopenharmony_ci 16348c2ecf20Sopenharmony_ci/** 16358c2ecf20Sopenharmony_ci * fm10k_msg_lport_map_pf - Message handler for lport_map message from SM 16368c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 16378c2ecf20Sopenharmony_ci * @results: pointer array containing parsed data 16388c2ecf20Sopenharmony_ci * @mbx: Pointer to mailbox information structure 16398c2ecf20Sopenharmony_ci * 16408c2ecf20Sopenharmony_ci * This handler configures the lport mapping based on the reply from the 16418c2ecf20Sopenharmony_ci * switch API. 16428c2ecf20Sopenharmony_ci **/ 16438c2ecf20Sopenharmony_cis32 fm10k_msg_lport_map_pf(struct fm10k_hw *hw, u32 **results, 16448c2ecf20Sopenharmony_ci struct fm10k_mbx_info __always_unused *mbx) 16458c2ecf20Sopenharmony_ci{ 16468c2ecf20Sopenharmony_ci u16 glort, mask; 16478c2ecf20Sopenharmony_ci u32 dglort_map; 16488c2ecf20Sopenharmony_ci s32 err; 16498c2ecf20Sopenharmony_ci 16508c2ecf20Sopenharmony_ci err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_LPORT_MAP], 16518c2ecf20Sopenharmony_ci &dglort_map); 16528c2ecf20Sopenharmony_ci if (err) 16538c2ecf20Sopenharmony_ci return err; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci /* extract values out of the header */ 16568c2ecf20Sopenharmony_ci glort = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_GLORT); 16578c2ecf20Sopenharmony_ci mask = FM10K_MSG_HDR_FIELD_GET(dglort_map, LPORT_MAP_MASK); 16588c2ecf20Sopenharmony_ci 16598c2ecf20Sopenharmony_ci /* verify mask is set and none of the masked bits in glort are set */ 16608c2ecf20Sopenharmony_ci if (!mask || (glort & ~mask)) 16618c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 16628c2ecf20Sopenharmony_ci 16638c2ecf20Sopenharmony_ci /* verify the mask is contiguous, and that it is 1's followed by 0's */ 16648c2ecf20Sopenharmony_ci if (((~(mask - 1) & mask) + mask) & FM10K_DGLORTMAP_NONE) 16658c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 16668c2ecf20Sopenharmony_ci 16678c2ecf20Sopenharmony_ci /* record the glort, mask, and port count */ 16688c2ecf20Sopenharmony_ci hw->mac.dglort_map = dglort_map; 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci return 0; 16718c2ecf20Sopenharmony_ci} 16728c2ecf20Sopenharmony_ci 16738c2ecf20Sopenharmony_ciconst struct fm10k_tlv_attr fm10k_update_pvid_msg_attr[] = { 16748c2ecf20Sopenharmony_ci FM10K_TLV_ATTR_U32(FM10K_PF_ATTR_ID_UPDATE_PVID), 16758c2ecf20Sopenharmony_ci FM10K_TLV_ATTR_LAST 16768c2ecf20Sopenharmony_ci}; 16778c2ecf20Sopenharmony_ci 16788c2ecf20Sopenharmony_ci/** 16798c2ecf20Sopenharmony_ci * fm10k_msg_update_pvid_pf - Message handler for port VLAN message from SM 16808c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 16818c2ecf20Sopenharmony_ci * @results: pointer array containing parsed data 16828c2ecf20Sopenharmony_ci * @mbx: Pointer to mailbox information structure 16838c2ecf20Sopenharmony_ci * 16848c2ecf20Sopenharmony_ci * This handler configures the default VLAN for the PF 16858c2ecf20Sopenharmony_ci **/ 16868c2ecf20Sopenharmony_cistatic s32 fm10k_msg_update_pvid_pf(struct fm10k_hw *hw, u32 **results, 16878c2ecf20Sopenharmony_ci struct fm10k_mbx_info __always_unused *mbx) 16888c2ecf20Sopenharmony_ci{ 16898c2ecf20Sopenharmony_ci u16 glort, pvid; 16908c2ecf20Sopenharmony_ci u32 pvid_update; 16918c2ecf20Sopenharmony_ci s32 err; 16928c2ecf20Sopenharmony_ci 16938c2ecf20Sopenharmony_ci err = fm10k_tlv_attr_get_u32(results[FM10K_PF_ATTR_ID_UPDATE_PVID], 16948c2ecf20Sopenharmony_ci &pvid_update); 16958c2ecf20Sopenharmony_ci if (err) 16968c2ecf20Sopenharmony_ci return err; 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_ci /* extract values from the pvid update */ 16998c2ecf20Sopenharmony_ci glort = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_GLORT); 17008c2ecf20Sopenharmony_ci pvid = FM10K_MSG_HDR_FIELD_GET(pvid_update, UPDATE_PVID_PVID); 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci /* if glort is not valid return error */ 17038c2ecf20Sopenharmony_ci if (!fm10k_glort_valid_pf(hw, glort)) 17048c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 17058c2ecf20Sopenharmony_ci 17068c2ecf20Sopenharmony_ci /* verify VLAN ID is valid */ 17078c2ecf20Sopenharmony_ci if (pvid >= FM10K_VLAN_TABLE_VID_MAX) 17088c2ecf20Sopenharmony_ci return FM10K_ERR_PARAM; 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci /* record the port VLAN ID value */ 17118c2ecf20Sopenharmony_ci hw->mac.default_vid = pvid; 17128c2ecf20Sopenharmony_ci 17138c2ecf20Sopenharmony_ci return 0; 17148c2ecf20Sopenharmony_ci} 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci/** 17178c2ecf20Sopenharmony_ci * fm10k_record_global_table_data - Move global table data to swapi table info 17188c2ecf20Sopenharmony_ci * @from: pointer to source table data structure 17198c2ecf20Sopenharmony_ci * @to: pointer to destination table info structure 17208c2ecf20Sopenharmony_ci * 17218c2ecf20Sopenharmony_ci * This function is will copy table_data to the table_info contained in 17228c2ecf20Sopenharmony_ci * the hw struct. 17238c2ecf20Sopenharmony_ci **/ 17248c2ecf20Sopenharmony_cistatic void fm10k_record_global_table_data(struct fm10k_global_table_data *from, 17258c2ecf20Sopenharmony_ci struct fm10k_swapi_table_info *to) 17268c2ecf20Sopenharmony_ci{ 17278c2ecf20Sopenharmony_ci /* convert from le32 struct to CPU byte ordered values */ 17288c2ecf20Sopenharmony_ci to->used = le32_to_cpu(from->used); 17298c2ecf20Sopenharmony_ci to->avail = le32_to_cpu(from->avail); 17308c2ecf20Sopenharmony_ci} 17318c2ecf20Sopenharmony_ci 17328c2ecf20Sopenharmony_ciconst struct fm10k_tlv_attr fm10k_err_msg_attr[] = { 17338c2ecf20Sopenharmony_ci FM10K_TLV_ATTR_LE_STRUCT(FM10K_PF_ATTR_ID_ERR, 17348c2ecf20Sopenharmony_ci sizeof(struct fm10k_swapi_error)), 17358c2ecf20Sopenharmony_ci FM10K_TLV_ATTR_LAST 17368c2ecf20Sopenharmony_ci}; 17378c2ecf20Sopenharmony_ci 17388c2ecf20Sopenharmony_ci/** 17398c2ecf20Sopenharmony_ci * fm10k_msg_err_pf - Message handler for error reply 17408c2ecf20Sopenharmony_ci * @hw: Pointer to hardware structure 17418c2ecf20Sopenharmony_ci * @results: pointer array containing parsed data 17428c2ecf20Sopenharmony_ci * @mbx: Pointer to mailbox information structure 17438c2ecf20Sopenharmony_ci * 17448c2ecf20Sopenharmony_ci * This handler will capture the data for any error replies to previous 17458c2ecf20Sopenharmony_ci * messages that the PF has sent. 17468c2ecf20Sopenharmony_ci **/ 17478c2ecf20Sopenharmony_cis32 fm10k_msg_err_pf(struct fm10k_hw *hw, u32 **results, 17488c2ecf20Sopenharmony_ci struct fm10k_mbx_info __always_unused *mbx) 17498c2ecf20Sopenharmony_ci{ 17508c2ecf20Sopenharmony_ci struct fm10k_swapi_error err_msg; 17518c2ecf20Sopenharmony_ci s32 err; 17528c2ecf20Sopenharmony_ci 17538c2ecf20Sopenharmony_ci /* extract structure from message */ 17548c2ecf20Sopenharmony_ci err = fm10k_tlv_attr_get_le_struct(results[FM10K_PF_ATTR_ID_ERR], 17558c2ecf20Sopenharmony_ci &err_msg, sizeof(err_msg)); 17568c2ecf20Sopenharmony_ci if (err) 17578c2ecf20Sopenharmony_ci return err; 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci /* record table status */ 17608c2ecf20Sopenharmony_ci fm10k_record_global_table_data(&err_msg.mac, &hw->swapi.mac); 17618c2ecf20Sopenharmony_ci fm10k_record_global_table_data(&err_msg.nexthop, &hw->swapi.nexthop); 17628c2ecf20Sopenharmony_ci fm10k_record_global_table_data(&err_msg.ffu, &hw->swapi.ffu); 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_ci /* record SW API status value */ 17658c2ecf20Sopenharmony_ci hw->swapi.status = le32_to_cpu(err_msg.status); 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_ci return 0; 17688c2ecf20Sopenharmony_ci} 17698c2ecf20Sopenharmony_ci 17708c2ecf20Sopenharmony_cistatic const struct fm10k_msg_data fm10k_msg_data_pf[] = { 17718c2ecf20Sopenharmony_ci FM10K_PF_MSG_ERR_HANDLER(XCAST_MODES, fm10k_msg_err_pf), 17728c2ecf20Sopenharmony_ci FM10K_PF_MSG_ERR_HANDLER(UPDATE_MAC_FWD_RULE, fm10k_msg_err_pf), 17738c2ecf20Sopenharmony_ci FM10K_PF_MSG_LPORT_MAP_HANDLER(fm10k_msg_lport_map_pf), 17748c2ecf20Sopenharmony_ci FM10K_PF_MSG_ERR_HANDLER(LPORT_CREATE, fm10k_msg_err_pf), 17758c2ecf20Sopenharmony_ci FM10K_PF_MSG_ERR_HANDLER(LPORT_DELETE, fm10k_msg_err_pf), 17768c2ecf20Sopenharmony_ci FM10K_PF_MSG_UPDATE_PVID_HANDLER(fm10k_msg_update_pvid_pf), 17778c2ecf20Sopenharmony_ci FM10K_TLV_MSG_ERROR_HANDLER(fm10k_tlv_msg_error), 17788c2ecf20Sopenharmony_ci}; 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_cistatic const struct fm10k_mac_ops mac_ops_pf = { 17818c2ecf20Sopenharmony_ci .get_bus_info = fm10k_get_bus_info_generic, 17828c2ecf20Sopenharmony_ci .reset_hw = fm10k_reset_hw_pf, 17838c2ecf20Sopenharmony_ci .init_hw = fm10k_init_hw_pf, 17848c2ecf20Sopenharmony_ci .start_hw = fm10k_start_hw_generic, 17858c2ecf20Sopenharmony_ci .stop_hw = fm10k_stop_hw_generic, 17868c2ecf20Sopenharmony_ci .update_vlan = fm10k_update_vlan_pf, 17878c2ecf20Sopenharmony_ci .read_mac_addr = fm10k_read_mac_addr_pf, 17888c2ecf20Sopenharmony_ci .update_uc_addr = fm10k_update_uc_addr_pf, 17898c2ecf20Sopenharmony_ci .update_mc_addr = fm10k_update_mc_addr_pf, 17908c2ecf20Sopenharmony_ci .update_xcast_mode = fm10k_update_xcast_mode_pf, 17918c2ecf20Sopenharmony_ci .update_int_moderator = fm10k_update_int_moderator_pf, 17928c2ecf20Sopenharmony_ci .update_lport_state = fm10k_update_lport_state_pf, 17938c2ecf20Sopenharmony_ci .update_hw_stats = fm10k_update_hw_stats_pf, 17948c2ecf20Sopenharmony_ci .rebind_hw_stats = fm10k_rebind_hw_stats_pf, 17958c2ecf20Sopenharmony_ci .configure_dglort_map = fm10k_configure_dglort_map_pf, 17968c2ecf20Sopenharmony_ci .set_dma_mask = fm10k_set_dma_mask_pf, 17978c2ecf20Sopenharmony_ci .get_fault = fm10k_get_fault_pf, 17988c2ecf20Sopenharmony_ci .get_host_state = fm10k_get_host_state_pf, 17998c2ecf20Sopenharmony_ci .request_lport_map = fm10k_request_lport_map_pf, 18008c2ecf20Sopenharmony_ci}; 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_cistatic const struct fm10k_iov_ops iov_ops_pf = { 18038c2ecf20Sopenharmony_ci .assign_resources = fm10k_iov_assign_resources_pf, 18048c2ecf20Sopenharmony_ci .configure_tc = fm10k_iov_configure_tc_pf, 18058c2ecf20Sopenharmony_ci .assign_int_moderator = fm10k_iov_assign_int_moderator_pf, 18068c2ecf20Sopenharmony_ci .assign_default_mac_vlan = fm10k_iov_assign_default_mac_vlan_pf, 18078c2ecf20Sopenharmony_ci .reset_resources = fm10k_iov_reset_resources_pf, 18088c2ecf20Sopenharmony_ci .set_lport = fm10k_iov_set_lport_pf, 18098c2ecf20Sopenharmony_ci .reset_lport = fm10k_iov_reset_lport_pf, 18108c2ecf20Sopenharmony_ci .update_stats = fm10k_iov_update_stats_pf, 18118c2ecf20Sopenharmony_ci}; 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_cistatic s32 fm10k_get_invariants_pf(struct fm10k_hw *hw) 18148c2ecf20Sopenharmony_ci{ 18158c2ecf20Sopenharmony_ci fm10k_get_invariants_generic(hw); 18168c2ecf20Sopenharmony_ci 18178c2ecf20Sopenharmony_ci return fm10k_sm_mbx_init(hw, &hw->mbx, fm10k_msg_data_pf); 18188c2ecf20Sopenharmony_ci} 18198c2ecf20Sopenharmony_ci 18208c2ecf20Sopenharmony_ciconst struct fm10k_info fm10k_pf_info = { 18218c2ecf20Sopenharmony_ci .mac = fm10k_mac_pf, 18228c2ecf20Sopenharmony_ci .get_invariants = fm10k_get_invariants_pf, 18238c2ecf20Sopenharmony_ci .mac_ops = &mac_ops_pf, 18248c2ecf20Sopenharmony_ci .iov_ops = &iov_ops_pf, 18258c2ecf20Sopenharmony_ci}; 1826