19d26e4fcSRobert Mustacchi /****************************************************************************** 29d26e4fcSRobert Mustacchi 39d26e4fcSRobert Mustacchi Copyright (c) 2013-2015, Intel Corporation 49d26e4fcSRobert Mustacchi All rights reserved. 59d26e4fcSRobert Mustacchi 69d26e4fcSRobert Mustacchi Redistribution and use in source and binary forms, with or without 79d26e4fcSRobert Mustacchi modification, are permitted provided that the following conditions are met: 89d26e4fcSRobert Mustacchi 99d26e4fcSRobert Mustacchi 1. Redistributions of source code must retain the above copyright notice, 109d26e4fcSRobert Mustacchi this list of conditions and the following disclaimer. 119d26e4fcSRobert Mustacchi 129d26e4fcSRobert Mustacchi 2. Redistributions in binary form must reproduce the above copyright 139d26e4fcSRobert Mustacchi notice, this list of conditions and the following disclaimer in the 149d26e4fcSRobert Mustacchi documentation and/or other materials provided with the distribution. 159d26e4fcSRobert Mustacchi 169d26e4fcSRobert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its 179d26e4fcSRobert Mustacchi contributors may be used to endorse or promote products derived from 189d26e4fcSRobert Mustacchi this software without specific prior written permission. 199d26e4fcSRobert Mustacchi 209d26e4fcSRobert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 219d26e4fcSRobert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 229d26e4fcSRobert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 239d26e4fcSRobert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 249d26e4fcSRobert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 259d26e4fcSRobert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 269d26e4fcSRobert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 279d26e4fcSRobert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 289d26e4fcSRobert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 299d26e4fcSRobert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 309d26e4fcSRobert Mustacchi POSSIBILITY OF SUCH DAMAGE. 319d26e4fcSRobert Mustacchi 329d26e4fcSRobert Mustacchi ******************************************************************************/ 33*3d75a287SRobert Mustacchi /*$FreeBSD$*/ 349d26e4fcSRobert Mustacchi 359d26e4fcSRobert Mustacchi #include "i40e_osdep.h" 369d26e4fcSRobert Mustacchi #include "i40e_register.h" 379d26e4fcSRobert Mustacchi #include "i40e_type.h" 389d26e4fcSRobert Mustacchi #include "i40e_hmc.h" 399d26e4fcSRobert Mustacchi #include "i40e_lan_hmc.h" 409d26e4fcSRobert Mustacchi #include "i40e_prototype.h" 419d26e4fcSRobert Mustacchi 429d26e4fcSRobert Mustacchi /* lan specific interface functions */ 439d26e4fcSRobert Mustacchi 449d26e4fcSRobert Mustacchi /** 459d26e4fcSRobert Mustacchi * i40e_align_l2obj_base - aligns base object pointer to 512 bytes 469d26e4fcSRobert Mustacchi * @offset: base address offset needing alignment 479d26e4fcSRobert Mustacchi * 489d26e4fcSRobert Mustacchi * Aligns the layer 2 function private memory so it's 512-byte aligned. 499d26e4fcSRobert Mustacchi **/ 509d26e4fcSRobert Mustacchi static u64 i40e_align_l2obj_base(u64 offset) 519d26e4fcSRobert Mustacchi { 529d26e4fcSRobert Mustacchi u64 aligned_offset = offset; 539d26e4fcSRobert Mustacchi 549d26e4fcSRobert Mustacchi if ((offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT) > 0) 559d26e4fcSRobert Mustacchi aligned_offset += (I40E_HMC_L2OBJ_BASE_ALIGNMENT - 569d26e4fcSRobert Mustacchi (offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT)); 579d26e4fcSRobert Mustacchi 589d26e4fcSRobert Mustacchi return aligned_offset; 599d26e4fcSRobert Mustacchi } 609d26e4fcSRobert Mustacchi 619d26e4fcSRobert Mustacchi /** 629d26e4fcSRobert Mustacchi * i40e_calculate_l2fpm_size - calculates layer 2 FPM memory size 639d26e4fcSRobert Mustacchi * @txq_num: number of Tx queues needing backing context 649d26e4fcSRobert Mustacchi * @rxq_num: number of Rx queues needing backing context 659d26e4fcSRobert Mustacchi * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context 669d26e4fcSRobert Mustacchi * @fcoe_filt_num: number of FCoE filters needing backing context 679d26e4fcSRobert Mustacchi * 689d26e4fcSRobert Mustacchi * Calculates the maximum amount of memory for the function required, based 699d26e4fcSRobert Mustacchi * on the number of resources it must provide context for. 709d26e4fcSRobert Mustacchi **/ 719d26e4fcSRobert Mustacchi u64 i40e_calculate_l2fpm_size(u32 txq_num, u32 rxq_num, 729d26e4fcSRobert Mustacchi u32 fcoe_cntx_num, u32 fcoe_filt_num) 739d26e4fcSRobert Mustacchi { 749d26e4fcSRobert Mustacchi u64 fpm_size = 0; 759d26e4fcSRobert Mustacchi 769d26e4fcSRobert Mustacchi fpm_size = txq_num * I40E_HMC_OBJ_SIZE_TXQ; 779d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 789d26e4fcSRobert Mustacchi 799d26e4fcSRobert Mustacchi fpm_size += (rxq_num * I40E_HMC_OBJ_SIZE_RXQ); 809d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 819d26e4fcSRobert Mustacchi 829d26e4fcSRobert Mustacchi fpm_size += (fcoe_cntx_num * I40E_HMC_OBJ_SIZE_FCOE_CNTX); 839d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 849d26e4fcSRobert Mustacchi 859d26e4fcSRobert Mustacchi fpm_size += (fcoe_filt_num * I40E_HMC_OBJ_SIZE_FCOE_FILT); 869d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 879d26e4fcSRobert Mustacchi 889d26e4fcSRobert Mustacchi return fpm_size; 899d26e4fcSRobert Mustacchi } 909d26e4fcSRobert Mustacchi 919d26e4fcSRobert Mustacchi /** 929d26e4fcSRobert Mustacchi * i40e_init_lan_hmc - initialize i40e_hmc_info struct 939d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 949d26e4fcSRobert Mustacchi * @txq_num: number of Tx queues needing backing context 959d26e4fcSRobert Mustacchi * @rxq_num: number of Rx queues needing backing context 969d26e4fcSRobert Mustacchi * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context 979d26e4fcSRobert Mustacchi * @fcoe_filt_num: number of FCoE filters needing backing context 989d26e4fcSRobert Mustacchi * 999d26e4fcSRobert Mustacchi * This function will be called once per physical function initialization. 1009d26e4fcSRobert Mustacchi * It will fill out the i40e_hmc_obj_info structure for LAN objects based on 1019d26e4fcSRobert Mustacchi * the driver's provided input, as well as information from the HMC itself 1029d26e4fcSRobert Mustacchi * loaded from NVRAM. 1039d26e4fcSRobert Mustacchi * 1049d26e4fcSRobert Mustacchi * Assumptions: 1059d26e4fcSRobert Mustacchi * - HMC Resource Profile has been selected before calling this function. 1069d26e4fcSRobert Mustacchi **/ 1079d26e4fcSRobert Mustacchi enum i40e_status_code i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, 1089d26e4fcSRobert Mustacchi u32 rxq_num, u32 fcoe_cntx_num, 1099d26e4fcSRobert Mustacchi u32 fcoe_filt_num) 1109d26e4fcSRobert Mustacchi { 1119d26e4fcSRobert Mustacchi struct i40e_hmc_obj_info *obj, *full_obj; 1129d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 1139d26e4fcSRobert Mustacchi u64 l2fpm_size; 1149d26e4fcSRobert Mustacchi u32 size_exp; 1159d26e4fcSRobert Mustacchi 1169d26e4fcSRobert Mustacchi hw->hmc.signature = I40E_HMC_INFO_SIGNATURE; 1179d26e4fcSRobert Mustacchi hw->hmc.hmc_fn_id = hw->pf_id; 1189d26e4fcSRobert Mustacchi 1199d26e4fcSRobert Mustacchi /* allocate memory for hmc_obj */ 1209d26e4fcSRobert Mustacchi ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem, 1219d26e4fcSRobert Mustacchi sizeof(struct i40e_hmc_obj_info) * I40E_HMC_LAN_MAX); 1229d26e4fcSRobert Mustacchi if (ret_code) 1239d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 1249d26e4fcSRobert Mustacchi hw->hmc.hmc_obj = (struct i40e_hmc_obj_info *) 1259d26e4fcSRobert Mustacchi hw->hmc.hmc_obj_virt_mem.va; 1269d26e4fcSRobert Mustacchi 1279d26e4fcSRobert Mustacchi /* The full object will be used to create the LAN HMC SD */ 1289d26e4fcSRobert Mustacchi full_obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_FULL]; 1299d26e4fcSRobert Mustacchi full_obj->max_cnt = 0; 1309d26e4fcSRobert Mustacchi full_obj->cnt = 0; 1319d26e4fcSRobert Mustacchi full_obj->base = 0; 1329d26e4fcSRobert Mustacchi full_obj->size = 0; 1339d26e4fcSRobert Mustacchi 1349d26e4fcSRobert Mustacchi /* Tx queue context information */ 1359d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX]; 1369d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX); 1379d26e4fcSRobert Mustacchi obj->cnt = txq_num; 1389d26e4fcSRobert Mustacchi obj->base = 0; 1399d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_LANTXOBJSZ); 1409d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 1419d26e4fcSRobert Mustacchi 1429d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 1439d26e4fcSRobert Mustacchi if (txq_num > obj->max_cnt) { 1449d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 1459d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: Tx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 1469d26e4fcSRobert Mustacchi txq_num, obj->max_cnt, ret_code); 1479d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 1489d26e4fcSRobert Mustacchi } 1499d26e4fcSRobert Mustacchi 1509d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 1519d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 1529d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 1539d26e4fcSRobert Mustacchi 1549d26e4fcSRobert Mustacchi /* Rx queue context information */ 1559d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX]; 1569d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX); 1579d26e4fcSRobert Mustacchi obj->cnt = rxq_num; 1589d26e4fcSRobert Mustacchi obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_TX].base + 1599d26e4fcSRobert Mustacchi (hw->hmc.hmc_obj[I40E_HMC_LAN_TX].cnt * 1609d26e4fcSRobert Mustacchi hw->hmc.hmc_obj[I40E_HMC_LAN_TX].size); 1619d26e4fcSRobert Mustacchi obj->base = i40e_align_l2obj_base(obj->base); 1629d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_LANRXOBJSZ); 1639d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 1649d26e4fcSRobert Mustacchi 1659d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 1669d26e4fcSRobert Mustacchi if (rxq_num > obj->max_cnt) { 1679d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 1689d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: Rx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 1699d26e4fcSRobert Mustacchi rxq_num, obj->max_cnt, ret_code); 1709d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 1719d26e4fcSRobert Mustacchi } 1729d26e4fcSRobert Mustacchi 1739d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 1749d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 1759d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 1769d26e4fcSRobert Mustacchi 1779d26e4fcSRobert Mustacchi /* FCoE context information */ 1789d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX]; 1799d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEMAX); 1809d26e4fcSRobert Mustacchi obj->cnt = fcoe_cntx_num; 1819d26e4fcSRobert Mustacchi obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_RX].base + 1829d26e4fcSRobert Mustacchi (hw->hmc.hmc_obj[I40E_HMC_LAN_RX].cnt * 1839d26e4fcSRobert Mustacchi hw->hmc.hmc_obj[I40E_HMC_LAN_RX].size); 1849d26e4fcSRobert Mustacchi obj->base = i40e_align_l2obj_base(obj->base); 1859d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_FCOEDDPOBJSZ); 1869d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 1879d26e4fcSRobert Mustacchi 1889d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 1899d26e4fcSRobert Mustacchi if (fcoe_cntx_num > obj->max_cnt) { 1909d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 1919d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: FCoE context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 1929d26e4fcSRobert Mustacchi fcoe_cntx_num, obj->max_cnt, ret_code); 1939d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 1949d26e4fcSRobert Mustacchi } 1959d26e4fcSRobert Mustacchi 1969d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 1979d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 1989d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 1999d26e4fcSRobert Mustacchi 2009d26e4fcSRobert Mustacchi /* FCoE filter information */ 2019d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT]; 2029d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEFMAX); 2039d26e4fcSRobert Mustacchi obj->cnt = fcoe_filt_num; 2049d26e4fcSRobert Mustacchi obj->base = hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].base + 2059d26e4fcSRobert Mustacchi (hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].cnt * 2069d26e4fcSRobert Mustacchi hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].size); 2079d26e4fcSRobert Mustacchi obj->base = i40e_align_l2obj_base(obj->base); 2089d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_FCOEFOBJSZ); 2099d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 2109d26e4fcSRobert Mustacchi 2119d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 2129d26e4fcSRobert Mustacchi if (fcoe_filt_num > obj->max_cnt) { 2139d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 2149d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: FCoE filter: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 2159d26e4fcSRobert Mustacchi fcoe_filt_num, obj->max_cnt, ret_code); 2169d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 2179d26e4fcSRobert Mustacchi } 2189d26e4fcSRobert Mustacchi 2199d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 2209d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 2219d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 2229d26e4fcSRobert Mustacchi 2239d26e4fcSRobert Mustacchi hw->hmc.first_sd_index = 0; 2249d26e4fcSRobert Mustacchi hw->hmc.sd_table.ref_cnt = 0; 2259d26e4fcSRobert Mustacchi l2fpm_size = i40e_calculate_l2fpm_size(txq_num, rxq_num, fcoe_cntx_num, 2269d26e4fcSRobert Mustacchi fcoe_filt_num); 2279d26e4fcSRobert Mustacchi if (NULL == hw->hmc.sd_table.sd_entry) { 2289d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_cnt = (u32) 2299d26e4fcSRobert Mustacchi (l2fpm_size + I40E_HMC_DIRECT_BP_SIZE - 1) / 2309d26e4fcSRobert Mustacchi I40E_HMC_DIRECT_BP_SIZE; 2319d26e4fcSRobert Mustacchi 2329d26e4fcSRobert Mustacchi /* allocate the sd_entry members in the sd_table */ 2339d26e4fcSRobert Mustacchi ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.sd_table.addr, 2349d26e4fcSRobert Mustacchi (sizeof(struct i40e_hmc_sd_entry) * 2359d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_cnt)); 2369d26e4fcSRobert Mustacchi if (ret_code) 2379d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 2389d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_entry = 2399d26e4fcSRobert Mustacchi (struct i40e_hmc_sd_entry *)hw->hmc.sd_table.addr.va; 2409d26e4fcSRobert Mustacchi } 2419d26e4fcSRobert Mustacchi /* store in the LAN full object for later */ 2429d26e4fcSRobert Mustacchi full_obj->size = l2fpm_size; 2439d26e4fcSRobert Mustacchi 2449d26e4fcSRobert Mustacchi init_lan_hmc_out: 2459d26e4fcSRobert Mustacchi return ret_code; 2469d26e4fcSRobert Mustacchi } 2479d26e4fcSRobert Mustacchi 2489d26e4fcSRobert Mustacchi /** 2499d26e4fcSRobert Mustacchi * i40e_remove_pd_page - Remove a page from the page descriptor table 2509d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 2519d26e4fcSRobert Mustacchi * @hmc_info: pointer to the HMC configuration information structure 2529d26e4fcSRobert Mustacchi * @idx: segment descriptor index to find the relevant page descriptor 2539d26e4fcSRobert Mustacchi * 2549d26e4fcSRobert Mustacchi * This function: 2559d26e4fcSRobert Mustacchi * 1. Marks the entry in pd table (for paged address mode) invalid 2569d26e4fcSRobert Mustacchi * 2. write to register PMPDINV to invalidate the backing page in FV cache 2579d26e4fcSRobert Mustacchi * 3. Decrement the ref count for pd_entry 2589d26e4fcSRobert Mustacchi * assumptions: 2599d26e4fcSRobert Mustacchi * 1. caller can deallocate the memory used by pd after this function 2609d26e4fcSRobert Mustacchi * returns. 2619d26e4fcSRobert Mustacchi **/ 2629d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_remove_pd_page(struct i40e_hw *hw, 2639d26e4fcSRobert Mustacchi struct i40e_hmc_info *hmc_info, 2649d26e4fcSRobert Mustacchi u32 idx) 2659d26e4fcSRobert Mustacchi { 2669d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 2679d26e4fcSRobert Mustacchi 2689d26e4fcSRobert Mustacchi if (i40e_prep_remove_pd_page(hmc_info, idx) == I40E_SUCCESS) 2699d26e4fcSRobert Mustacchi ret_code = i40e_remove_pd_page_new(hw, hmc_info, idx, TRUE); 2709d26e4fcSRobert Mustacchi 2719d26e4fcSRobert Mustacchi return ret_code; 2729d26e4fcSRobert Mustacchi } 2739d26e4fcSRobert Mustacchi 2749d26e4fcSRobert Mustacchi /** 2759d26e4fcSRobert Mustacchi * i40e_remove_sd_bp - remove a backing page from a segment descriptor 2769d26e4fcSRobert Mustacchi * @hw: pointer to our HW structure 2779d26e4fcSRobert Mustacchi * @hmc_info: pointer to the HMC configuration information structure 2789d26e4fcSRobert Mustacchi * @idx: the page index 2799d26e4fcSRobert Mustacchi * 2809d26e4fcSRobert Mustacchi * This function: 2819d26e4fcSRobert Mustacchi * 1. Marks the entry in sd table (for direct address mode) invalid 2829d26e4fcSRobert Mustacchi * 2. write to register PMSDCMD, PMSDDATALOW(PMSDDATALOW.PMSDVALID set 2839d26e4fcSRobert Mustacchi * to 0) and PMSDDATAHIGH to invalidate the sd page 2849d26e4fcSRobert Mustacchi * 3. Decrement the ref count for the sd_entry 2859d26e4fcSRobert Mustacchi * assumptions: 2869d26e4fcSRobert Mustacchi * 1. caller can deallocate the memory used by backing storage after this 2879d26e4fcSRobert Mustacchi * function returns. 2889d26e4fcSRobert Mustacchi **/ 2899d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_remove_sd_bp(struct i40e_hw *hw, 2909d26e4fcSRobert Mustacchi struct i40e_hmc_info *hmc_info, 2919d26e4fcSRobert Mustacchi u32 idx) 2929d26e4fcSRobert Mustacchi { 2939d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 2949d26e4fcSRobert Mustacchi 2959d26e4fcSRobert Mustacchi if (i40e_prep_remove_sd_bp(hmc_info, idx) == I40E_SUCCESS) 2969d26e4fcSRobert Mustacchi ret_code = i40e_remove_sd_bp_new(hw, hmc_info, idx, TRUE); 2979d26e4fcSRobert Mustacchi 2989d26e4fcSRobert Mustacchi return ret_code; 2999d26e4fcSRobert Mustacchi } 3009d26e4fcSRobert Mustacchi 3019d26e4fcSRobert Mustacchi /** 3029d26e4fcSRobert Mustacchi * i40e_create_lan_hmc_object - allocate backing store for hmc objects 3039d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 3049d26e4fcSRobert Mustacchi * @info: pointer to i40e_hmc_create_obj_info struct 3059d26e4fcSRobert Mustacchi * 3069d26e4fcSRobert Mustacchi * This will allocate memory for PDs and backing pages and populate 3079d26e4fcSRobert Mustacchi * the sd and pd entries. 3089d26e4fcSRobert Mustacchi **/ 3099d26e4fcSRobert Mustacchi enum i40e_status_code i40e_create_lan_hmc_object(struct i40e_hw *hw, 3109d26e4fcSRobert Mustacchi struct i40e_hmc_lan_create_obj_info *info) 3119d26e4fcSRobert Mustacchi { 3129d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 3139d26e4fcSRobert Mustacchi struct i40e_hmc_sd_entry *sd_entry; 3149d26e4fcSRobert Mustacchi u32 pd_idx1 = 0, pd_lmt1 = 0; 3159d26e4fcSRobert Mustacchi u32 pd_idx = 0, pd_lmt = 0; 3169d26e4fcSRobert Mustacchi bool pd_error = FALSE; 3179d26e4fcSRobert Mustacchi u32 sd_idx, sd_lmt; 3189d26e4fcSRobert Mustacchi u64 sd_size; 3199d26e4fcSRobert Mustacchi u32 i, j; 3209d26e4fcSRobert Mustacchi 3219d26e4fcSRobert Mustacchi if (NULL == info) { 3229d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 3239d26e4fcSRobert Mustacchi DEBUGOUT("i40e_create_lan_hmc_object: bad info ptr\n"); 3249d26e4fcSRobert Mustacchi goto exit; 3259d26e4fcSRobert Mustacchi } 3269d26e4fcSRobert Mustacchi if (NULL == info->hmc_info) { 3279d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 3289d26e4fcSRobert Mustacchi DEBUGOUT("i40e_create_lan_hmc_object: bad hmc_info ptr\n"); 3299d26e4fcSRobert Mustacchi goto exit; 3309d26e4fcSRobert Mustacchi } 3319d26e4fcSRobert Mustacchi if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { 3329d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 3339d26e4fcSRobert Mustacchi DEBUGOUT("i40e_create_lan_hmc_object: bad signature\n"); 3349d26e4fcSRobert Mustacchi goto exit; 3359d26e4fcSRobert Mustacchi } 3369d26e4fcSRobert Mustacchi 3379d26e4fcSRobert Mustacchi if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 3389d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; 3399d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n", 3409d26e4fcSRobert Mustacchi ret_code); 3419d26e4fcSRobert Mustacchi goto exit; 3429d26e4fcSRobert Mustacchi } 3439d26e4fcSRobert Mustacchi if ((info->start_idx + info->count) > 3449d26e4fcSRobert Mustacchi info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 3459d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 3469d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n", 3479d26e4fcSRobert Mustacchi ret_code); 3489d26e4fcSRobert Mustacchi goto exit; 3499d26e4fcSRobert Mustacchi } 3509d26e4fcSRobert Mustacchi 3519d26e4fcSRobert Mustacchi /* find sd index and limit */ 3529d26e4fcSRobert Mustacchi I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 3539d26e4fcSRobert Mustacchi info->start_idx, info->count, 3549d26e4fcSRobert Mustacchi &sd_idx, &sd_lmt); 3559d26e4fcSRobert Mustacchi if (sd_idx >= info->hmc_info->sd_table.sd_cnt || 3569d26e4fcSRobert Mustacchi sd_lmt > info->hmc_info->sd_table.sd_cnt) { 3579d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_INDEX; 3589d26e4fcSRobert Mustacchi goto exit; 3599d26e4fcSRobert Mustacchi } 3609d26e4fcSRobert Mustacchi /* find pd index */ 3619d26e4fcSRobert Mustacchi I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 3629d26e4fcSRobert Mustacchi info->start_idx, info->count, &pd_idx, 3639d26e4fcSRobert Mustacchi &pd_lmt); 3649d26e4fcSRobert Mustacchi 3659d26e4fcSRobert Mustacchi /* This is to cover for cases where you may not want to have an SD with 3669d26e4fcSRobert Mustacchi * the full 2M memory but something smaller. By not filling out any 3679d26e4fcSRobert Mustacchi * size, the function will default the SD size to be 2M. 3689d26e4fcSRobert Mustacchi */ 3699d26e4fcSRobert Mustacchi if (info->direct_mode_sz == 0) 3709d26e4fcSRobert Mustacchi sd_size = I40E_HMC_DIRECT_BP_SIZE; 3719d26e4fcSRobert Mustacchi else 3729d26e4fcSRobert Mustacchi sd_size = info->direct_mode_sz; 3739d26e4fcSRobert Mustacchi 3749d26e4fcSRobert Mustacchi /* check if all the sds are valid. If not, allocate a page and 3759d26e4fcSRobert Mustacchi * initialize it. 3769d26e4fcSRobert Mustacchi */ 3779d26e4fcSRobert Mustacchi for (j = sd_idx; j < sd_lmt; j++) { 3789d26e4fcSRobert Mustacchi /* update the sd table entry */ 3799d26e4fcSRobert Mustacchi ret_code = i40e_add_sd_table_entry(hw, info->hmc_info, j, 3809d26e4fcSRobert Mustacchi info->entry_type, 3819d26e4fcSRobert Mustacchi sd_size); 3829d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 3839d26e4fcSRobert Mustacchi goto exit_sd_error; 3849d26e4fcSRobert Mustacchi sd_entry = &info->hmc_info->sd_table.sd_entry[j]; 3859d26e4fcSRobert Mustacchi if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) { 3869d26e4fcSRobert Mustacchi /* check if all the pds in this sd are valid. If not, 3879d26e4fcSRobert Mustacchi * allocate a page and initialize it. 3889d26e4fcSRobert Mustacchi */ 3899d26e4fcSRobert Mustacchi 3909d26e4fcSRobert Mustacchi /* find pd_idx and pd_lmt in this sd */ 3919d26e4fcSRobert Mustacchi pd_idx1 = max(pd_idx, (j * I40E_HMC_MAX_BP_COUNT)); 3929d26e4fcSRobert Mustacchi pd_lmt1 = min(pd_lmt, 3939d26e4fcSRobert Mustacchi ((j + 1) * I40E_HMC_MAX_BP_COUNT)); 3949d26e4fcSRobert Mustacchi for (i = pd_idx1; i < pd_lmt1; i++) { 3959d26e4fcSRobert Mustacchi /* update the pd table entry */ 3969d26e4fcSRobert Mustacchi ret_code = i40e_add_pd_table_entry(hw, 3979d26e4fcSRobert Mustacchi info->hmc_info, 3989d26e4fcSRobert Mustacchi i, NULL); 3999d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) { 4009d26e4fcSRobert Mustacchi pd_error = TRUE; 4019d26e4fcSRobert Mustacchi break; 4029d26e4fcSRobert Mustacchi } 4039d26e4fcSRobert Mustacchi } 4049d26e4fcSRobert Mustacchi if (pd_error) { 4059d26e4fcSRobert Mustacchi /* remove the backing pages from pd_idx1 to i */ 4069d26e4fcSRobert Mustacchi while (i && (i > pd_idx1)) { 4079d26e4fcSRobert Mustacchi i40e_remove_pd_bp(hw, info->hmc_info, 4089d26e4fcSRobert Mustacchi (i - 1)); 4099d26e4fcSRobert Mustacchi i--; 4109d26e4fcSRobert Mustacchi } 4119d26e4fcSRobert Mustacchi } 4129d26e4fcSRobert Mustacchi } 4139d26e4fcSRobert Mustacchi if (!sd_entry->valid) { 4149d26e4fcSRobert Mustacchi sd_entry->valid = TRUE; 4159d26e4fcSRobert Mustacchi switch (sd_entry->entry_type) { 4169d26e4fcSRobert Mustacchi case I40E_SD_TYPE_PAGED: 4179d26e4fcSRobert Mustacchi I40E_SET_PF_SD_ENTRY(hw, 4189d26e4fcSRobert Mustacchi sd_entry->u.pd_table.pd_page_addr.pa, 4199d26e4fcSRobert Mustacchi j, sd_entry->entry_type); 4209d26e4fcSRobert Mustacchi break; 4219d26e4fcSRobert Mustacchi case I40E_SD_TYPE_DIRECT: 4229d26e4fcSRobert Mustacchi I40E_SET_PF_SD_ENTRY(hw, sd_entry->u.bp.addr.pa, 4239d26e4fcSRobert Mustacchi j, sd_entry->entry_type); 4249d26e4fcSRobert Mustacchi break; 4259d26e4fcSRobert Mustacchi default: 4269d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_TYPE; 4279d26e4fcSRobert Mustacchi goto exit; 4289d26e4fcSRobert Mustacchi } 4299d26e4fcSRobert Mustacchi } 4309d26e4fcSRobert Mustacchi } 4319d26e4fcSRobert Mustacchi goto exit; 4329d26e4fcSRobert Mustacchi 4339d26e4fcSRobert Mustacchi exit_sd_error: 4349d26e4fcSRobert Mustacchi /* cleanup for sd entries from j to sd_idx */ 4359d26e4fcSRobert Mustacchi while (j && (j > sd_idx)) { 4369d26e4fcSRobert Mustacchi sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1]; 4379d26e4fcSRobert Mustacchi switch (sd_entry->entry_type) { 4389d26e4fcSRobert Mustacchi case I40E_SD_TYPE_PAGED: 4399d26e4fcSRobert Mustacchi pd_idx1 = max(pd_idx, 4409d26e4fcSRobert Mustacchi ((j - 1) * I40E_HMC_MAX_BP_COUNT)); 4419d26e4fcSRobert Mustacchi pd_lmt1 = min(pd_lmt, (j * I40E_HMC_MAX_BP_COUNT)); 4429d26e4fcSRobert Mustacchi for (i = pd_idx1; i < pd_lmt1; i++) 4439d26e4fcSRobert Mustacchi i40e_remove_pd_bp(hw, info->hmc_info, i); 4449d26e4fcSRobert Mustacchi i40e_remove_pd_page(hw, info->hmc_info, (j - 1)); 4459d26e4fcSRobert Mustacchi break; 4469d26e4fcSRobert Mustacchi case I40E_SD_TYPE_DIRECT: 4479d26e4fcSRobert Mustacchi i40e_remove_sd_bp(hw, info->hmc_info, (j - 1)); 4489d26e4fcSRobert Mustacchi break; 4499d26e4fcSRobert Mustacchi default: 4509d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_TYPE; 4519d26e4fcSRobert Mustacchi break; 4529d26e4fcSRobert Mustacchi } 4539d26e4fcSRobert Mustacchi j--; 4549d26e4fcSRobert Mustacchi } 4559d26e4fcSRobert Mustacchi exit: 4569d26e4fcSRobert Mustacchi return ret_code; 4579d26e4fcSRobert Mustacchi } 4589d26e4fcSRobert Mustacchi 4599d26e4fcSRobert Mustacchi /** 4609d26e4fcSRobert Mustacchi * i40e_configure_lan_hmc - prepare the HMC backing store 4619d26e4fcSRobert Mustacchi * @hw: pointer to the hw structure 4629d26e4fcSRobert Mustacchi * @model: the model for the layout of the SD/PD tables 4639d26e4fcSRobert Mustacchi * 4649d26e4fcSRobert Mustacchi * - This function will be called once per physical function initialization. 4659d26e4fcSRobert Mustacchi * - This function will be called after i40e_init_lan_hmc() and before 4669d26e4fcSRobert Mustacchi * any LAN/FCoE HMC objects can be created. 4679d26e4fcSRobert Mustacchi **/ 4689d26e4fcSRobert Mustacchi enum i40e_status_code i40e_configure_lan_hmc(struct i40e_hw *hw, 4699d26e4fcSRobert Mustacchi enum i40e_hmc_model model) 4709d26e4fcSRobert Mustacchi { 4719d26e4fcSRobert Mustacchi struct i40e_hmc_lan_create_obj_info info; 4729d26e4fcSRobert Mustacchi u8 hmc_fn_id = hw->hmc.hmc_fn_id; 4739d26e4fcSRobert Mustacchi struct i40e_hmc_obj_info *obj; 4749d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 4759d26e4fcSRobert Mustacchi 4769d26e4fcSRobert Mustacchi /* Initialize part of the create object info struct */ 4779d26e4fcSRobert Mustacchi info.hmc_info = &hw->hmc; 4789d26e4fcSRobert Mustacchi info.rsrc_type = I40E_HMC_LAN_FULL; 4799d26e4fcSRobert Mustacchi info.start_idx = 0; 4809d26e4fcSRobert Mustacchi info.direct_mode_sz = hw->hmc.hmc_obj[I40E_HMC_LAN_FULL].size; 4819d26e4fcSRobert Mustacchi 4829d26e4fcSRobert Mustacchi /* Build the SD entry for the LAN objects */ 4839d26e4fcSRobert Mustacchi switch (model) { 4849d26e4fcSRobert Mustacchi case I40E_HMC_MODEL_DIRECT_PREFERRED: 4859d26e4fcSRobert Mustacchi case I40E_HMC_MODEL_DIRECT_ONLY: 4869d26e4fcSRobert Mustacchi info.entry_type = I40E_SD_TYPE_DIRECT; 4879d26e4fcSRobert Mustacchi /* Make one big object, a single SD */ 4889d26e4fcSRobert Mustacchi info.count = 1; 4899d26e4fcSRobert Mustacchi ret_code = i40e_create_lan_hmc_object(hw, &info); 4909d26e4fcSRobert Mustacchi if ((ret_code != I40E_SUCCESS) && (model == I40E_HMC_MODEL_DIRECT_PREFERRED)) 4919d26e4fcSRobert Mustacchi goto try_type_paged; 4929d26e4fcSRobert Mustacchi else if (ret_code != I40E_SUCCESS) 4939d26e4fcSRobert Mustacchi goto configure_lan_hmc_out; 4949d26e4fcSRobert Mustacchi /* else clause falls through the break */ 4959d26e4fcSRobert Mustacchi break; 4969d26e4fcSRobert Mustacchi case I40E_HMC_MODEL_PAGED_ONLY: 4979d26e4fcSRobert Mustacchi try_type_paged: 4989d26e4fcSRobert Mustacchi info.entry_type = I40E_SD_TYPE_PAGED; 4999d26e4fcSRobert Mustacchi /* Make one big object in the PD table */ 5009d26e4fcSRobert Mustacchi info.count = 1; 5019d26e4fcSRobert Mustacchi ret_code = i40e_create_lan_hmc_object(hw, &info); 5029d26e4fcSRobert Mustacchi if (ret_code != I40E_SUCCESS) 5039d26e4fcSRobert Mustacchi goto configure_lan_hmc_out; 5049d26e4fcSRobert Mustacchi break; 5059d26e4fcSRobert Mustacchi default: 5069d26e4fcSRobert Mustacchi /* unsupported type */ 5079d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_TYPE; 5089d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_configure_lan_hmc: Unknown SD type: %d\n", 5099d26e4fcSRobert Mustacchi ret_code); 5109d26e4fcSRobert Mustacchi goto configure_lan_hmc_out; 5119d26e4fcSRobert Mustacchi } 5129d26e4fcSRobert Mustacchi 5139d26e4fcSRobert Mustacchi /* Configure and program the FPM registers so objects can be created */ 5149d26e4fcSRobert Mustacchi 5159d26e4fcSRobert Mustacchi /* Tx contexts */ 5169d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX]; 5179d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANTXBASE(hmc_fn_id), 5189d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK) / 512)); 5199d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANTXCNT(hmc_fn_id), obj->cnt); 5209d26e4fcSRobert Mustacchi 5219d26e4fcSRobert Mustacchi /* Rx contexts */ 5229d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX]; 5239d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANRXBASE(hmc_fn_id), 5249d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK) / 512)); 5259d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANRXCNT(hmc_fn_id), obj->cnt); 5269d26e4fcSRobert Mustacchi 5279d26e4fcSRobert Mustacchi /* FCoE contexts */ 5289d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX]; 5299d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEDDPBASE(hmc_fn_id), 5309d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK) / 512)); 5319d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEDDPCNT(hmc_fn_id), obj->cnt); 5329d26e4fcSRobert Mustacchi 5339d26e4fcSRobert Mustacchi /* FCoE filters */ 5349d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT]; 5359d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEFBASE(hmc_fn_id), 5369d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK) / 512)); 5379d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEFCNT(hmc_fn_id), obj->cnt); 5389d26e4fcSRobert Mustacchi 5399d26e4fcSRobert Mustacchi configure_lan_hmc_out: 5409d26e4fcSRobert Mustacchi return ret_code; 5419d26e4fcSRobert Mustacchi } 5429d26e4fcSRobert Mustacchi 5439d26e4fcSRobert Mustacchi /** 5449d26e4fcSRobert Mustacchi * i40e_delete_hmc_object - remove hmc objects 5459d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 5469d26e4fcSRobert Mustacchi * @info: pointer to i40e_hmc_delete_obj_info struct 5479d26e4fcSRobert Mustacchi * 5489d26e4fcSRobert Mustacchi * This will de-populate the SDs and PDs. It frees 5499d26e4fcSRobert Mustacchi * the memory for PDS and backing storage. After this function is returned, 5509d26e4fcSRobert Mustacchi * caller should deallocate memory allocated previously for 5519d26e4fcSRobert Mustacchi * book-keeping information about PDs and backing storage. 5529d26e4fcSRobert Mustacchi **/ 5539d26e4fcSRobert Mustacchi enum i40e_status_code i40e_delete_lan_hmc_object(struct i40e_hw *hw, 5549d26e4fcSRobert Mustacchi struct i40e_hmc_lan_delete_obj_info *info) 5559d26e4fcSRobert Mustacchi { 5569d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 5579d26e4fcSRobert Mustacchi struct i40e_hmc_pd_table *pd_table; 5589d26e4fcSRobert Mustacchi u32 pd_idx, pd_lmt, rel_pd_idx; 5599d26e4fcSRobert Mustacchi u32 sd_idx, sd_lmt; 5609d26e4fcSRobert Mustacchi u32 i, j; 5619d26e4fcSRobert Mustacchi 5629d26e4fcSRobert Mustacchi if (NULL == info) { 5639d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 5649d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad info ptr\n"); 5659d26e4fcSRobert Mustacchi goto exit; 5669d26e4fcSRobert Mustacchi } 5679d26e4fcSRobert Mustacchi if (NULL == info->hmc_info) { 5689d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 5699d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad info->hmc_info ptr\n"); 5709d26e4fcSRobert Mustacchi goto exit; 5719d26e4fcSRobert Mustacchi } 5729d26e4fcSRobert Mustacchi if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { 5739d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 5749d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->signature\n"); 5759d26e4fcSRobert Mustacchi goto exit; 5769d26e4fcSRobert Mustacchi } 5779d26e4fcSRobert Mustacchi 5789d26e4fcSRobert Mustacchi if (NULL == info->hmc_info->sd_table.sd_entry) { 5799d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 5809d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad sd_entry\n"); 5819d26e4fcSRobert Mustacchi goto exit; 5829d26e4fcSRobert Mustacchi } 5839d26e4fcSRobert Mustacchi 5849d26e4fcSRobert Mustacchi if (NULL == info->hmc_info->hmc_obj) { 5859d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 5869d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->hmc_obj\n"); 5879d26e4fcSRobert Mustacchi goto exit; 5889d26e4fcSRobert Mustacchi } 5899d26e4fcSRobert Mustacchi if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 5909d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; 5919d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n", 5929d26e4fcSRobert Mustacchi ret_code); 5939d26e4fcSRobert Mustacchi goto exit; 5949d26e4fcSRobert Mustacchi } 5959d26e4fcSRobert Mustacchi 5969d26e4fcSRobert Mustacchi if ((info->start_idx + info->count) > 5979d26e4fcSRobert Mustacchi info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 5989d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 5999d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n", 6009d26e4fcSRobert Mustacchi ret_code); 6019d26e4fcSRobert Mustacchi goto exit; 6029d26e4fcSRobert Mustacchi } 6039d26e4fcSRobert Mustacchi 6049d26e4fcSRobert Mustacchi I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 6059d26e4fcSRobert Mustacchi info->start_idx, info->count, &pd_idx, 6069d26e4fcSRobert Mustacchi &pd_lmt); 6079d26e4fcSRobert Mustacchi 6089d26e4fcSRobert Mustacchi for (j = pd_idx; j < pd_lmt; j++) { 6099d26e4fcSRobert Mustacchi sd_idx = j / I40E_HMC_PD_CNT_IN_SD; 6109d26e4fcSRobert Mustacchi 6119d26e4fcSRobert Mustacchi if (I40E_SD_TYPE_PAGED != 6129d26e4fcSRobert Mustacchi info->hmc_info->sd_table.sd_entry[sd_idx].entry_type) 6139d26e4fcSRobert Mustacchi continue; 6149d26e4fcSRobert Mustacchi 6159d26e4fcSRobert Mustacchi rel_pd_idx = j % I40E_HMC_PD_CNT_IN_SD; 6169d26e4fcSRobert Mustacchi 6179d26e4fcSRobert Mustacchi pd_table = 6189d26e4fcSRobert Mustacchi &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; 6199d26e4fcSRobert Mustacchi if (pd_table->pd_entry[rel_pd_idx].valid) { 6209d26e4fcSRobert Mustacchi ret_code = i40e_remove_pd_bp(hw, info->hmc_info, j); 6219d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 6229d26e4fcSRobert Mustacchi goto exit; 6239d26e4fcSRobert Mustacchi } 6249d26e4fcSRobert Mustacchi } 6259d26e4fcSRobert Mustacchi 6269d26e4fcSRobert Mustacchi /* find sd index and limit */ 6279d26e4fcSRobert Mustacchi I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 6289d26e4fcSRobert Mustacchi info->start_idx, info->count, 6299d26e4fcSRobert Mustacchi &sd_idx, &sd_lmt); 6309d26e4fcSRobert Mustacchi if (sd_idx >= info->hmc_info->sd_table.sd_cnt || 6319d26e4fcSRobert Mustacchi sd_lmt > info->hmc_info->sd_table.sd_cnt) { 6329d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_INDEX; 6339d26e4fcSRobert Mustacchi goto exit; 6349d26e4fcSRobert Mustacchi } 6359d26e4fcSRobert Mustacchi 6369d26e4fcSRobert Mustacchi for (i = sd_idx; i < sd_lmt; i++) { 6379d26e4fcSRobert Mustacchi if (!info->hmc_info->sd_table.sd_entry[i].valid) 6389d26e4fcSRobert Mustacchi continue; 6399d26e4fcSRobert Mustacchi switch (info->hmc_info->sd_table.sd_entry[i].entry_type) { 6409d26e4fcSRobert Mustacchi case I40E_SD_TYPE_DIRECT: 6419d26e4fcSRobert Mustacchi ret_code = i40e_remove_sd_bp(hw, info->hmc_info, i); 6429d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 6439d26e4fcSRobert Mustacchi goto exit; 6449d26e4fcSRobert Mustacchi break; 6459d26e4fcSRobert Mustacchi case I40E_SD_TYPE_PAGED: 6469d26e4fcSRobert Mustacchi ret_code = i40e_remove_pd_page(hw, info->hmc_info, i); 6479d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 6489d26e4fcSRobert Mustacchi goto exit; 6499d26e4fcSRobert Mustacchi break; 6509d26e4fcSRobert Mustacchi default: 6519d26e4fcSRobert Mustacchi break; 6529d26e4fcSRobert Mustacchi } 6539d26e4fcSRobert Mustacchi } 6549d26e4fcSRobert Mustacchi exit: 6559d26e4fcSRobert Mustacchi return ret_code; 6569d26e4fcSRobert Mustacchi } 6579d26e4fcSRobert Mustacchi 6589d26e4fcSRobert Mustacchi /** 6599d26e4fcSRobert Mustacchi * i40e_shutdown_lan_hmc - Remove HMC backing store, free allocated memory 6609d26e4fcSRobert Mustacchi * @hw: pointer to the hw structure 6619d26e4fcSRobert Mustacchi * 6629d26e4fcSRobert Mustacchi * This must be called by drivers as they are shutting down and being 6639d26e4fcSRobert Mustacchi * removed from the OS. 6649d26e4fcSRobert Mustacchi **/ 6659d26e4fcSRobert Mustacchi enum i40e_status_code i40e_shutdown_lan_hmc(struct i40e_hw *hw) 6669d26e4fcSRobert Mustacchi { 6679d26e4fcSRobert Mustacchi struct i40e_hmc_lan_delete_obj_info info; 6689d26e4fcSRobert Mustacchi enum i40e_status_code ret_code; 6699d26e4fcSRobert Mustacchi 6709d26e4fcSRobert Mustacchi info.hmc_info = &hw->hmc; 6719d26e4fcSRobert Mustacchi info.rsrc_type = I40E_HMC_LAN_FULL; 6729d26e4fcSRobert Mustacchi info.start_idx = 0; 6739d26e4fcSRobert Mustacchi info.count = 1; 6749d26e4fcSRobert Mustacchi 6759d26e4fcSRobert Mustacchi /* delete the object */ 6769d26e4fcSRobert Mustacchi ret_code = i40e_delete_lan_hmc_object(hw, &info); 6779d26e4fcSRobert Mustacchi 6789d26e4fcSRobert Mustacchi /* free the SD table entry for LAN */ 6799d26e4fcSRobert Mustacchi i40e_free_virt_mem(hw, &hw->hmc.sd_table.addr); 6809d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_cnt = 0; 6819d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_entry = NULL; 6829d26e4fcSRobert Mustacchi 6839d26e4fcSRobert Mustacchi /* free memory used for hmc_obj */ 6849d26e4fcSRobert Mustacchi i40e_free_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem); 6859d26e4fcSRobert Mustacchi hw->hmc.hmc_obj = NULL; 6869d26e4fcSRobert Mustacchi 6879d26e4fcSRobert Mustacchi return ret_code; 6889d26e4fcSRobert Mustacchi } 6899d26e4fcSRobert Mustacchi 6909d26e4fcSRobert Mustacchi #define I40E_HMC_STORE(_struct, _ele) \ 6919d26e4fcSRobert Mustacchi offsetof(struct _struct, _ele), \ 6929d26e4fcSRobert Mustacchi FIELD_SIZEOF(struct _struct, _ele) 6939d26e4fcSRobert Mustacchi 6949d26e4fcSRobert Mustacchi struct i40e_context_ele { 6959d26e4fcSRobert Mustacchi u16 offset; 6969d26e4fcSRobert Mustacchi u16 size_of; 6979d26e4fcSRobert Mustacchi u16 width; 6989d26e4fcSRobert Mustacchi u16 lsb; 6999d26e4fcSRobert Mustacchi }; 7009d26e4fcSRobert Mustacchi 7019d26e4fcSRobert Mustacchi /* LAN Tx Queue Context */ 7029d26e4fcSRobert Mustacchi static struct i40e_context_ele i40e_hmc_txq_ce_info[] = { 7039d26e4fcSRobert Mustacchi /* Field Width LSB */ 7049d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, head), 13, 0 }, 7059d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, new_context), 1, 30 }, 7069d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, base), 57, 32 }, 7079d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, fc_ena), 1, 89 }, 7089d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, timesync_ena), 1, 90 }, 7099d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, fd_ena), 1, 91 }, 7109d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, alt_vlan_ena), 1, 92 }, 7119d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, cpuid), 8, 96 }, 7129d26e4fcSRobert Mustacchi /* line 1 */ 7139d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, thead_wb), 13, 0 + 128 }, 7149d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_ena), 1, 32 + 128 }, 7159d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, qlen), 13, 33 + 128 }, 7169d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrdesc_ena), 1, 46 + 128 }, 7179d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrpacket_ena), 1, 47 + 128 }, 7189d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, tphwdesc_ena), 1, 48 + 128 }, 7199d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_addr), 64, 64 + 128 }, 7209d26e4fcSRobert Mustacchi /* line 7 */ 7219d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, crc), 32, 0 + (7 * 128) }, 7229d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist), 10, 84 + (7 * 128) }, 7239d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist_act), 1, 94 + (7 * 128) }, 7249d26e4fcSRobert Mustacchi { 0 } 7259d26e4fcSRobert Mustacchi }; 7269d26e4fcSRobert Mustacchi 7279d26e4fcSRobert Mustacchi /* LAN Rx Queue Context */ 7289d26e4fcSRobert Mustacchi static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = { 7299d26e4fcSRobert Mustacchi /* Field Width LSB */ 7309d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, head), 13, 0 }, 7319d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, cpuid), 8, 13 }, 7329d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, base), 57, 32 }, 7339d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, qlen), 13, 89 }, 7349d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, dbuff), 7, 102 }, 7359d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, hbuff), 5, 109 }, 7369d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, dtype), 2, 114 }, 7379d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, dsize), 1, 116 }, 7389d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, crcstrip), 1, 117 }, 7399d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, fc_ena), 1, 118 }, 7409d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, l2tsel), 1, 119 }, 7419d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_0), 4, 120 }, 7429d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_1), 2, 124 }, 7439d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, showiv), 1, 127 }, 7449d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, rxmax), 14, 174 }, 7459d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphrdesc_ena), 1, 193 }, 7469d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphwdesc_ena), 1, 194 }, 7479d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphdata_ena), 1, 195 }, 7489d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphhead_ena), 1, 196 }, 7499d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, lrxqthresh), 3, 198 }, 7509d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, prefena), 1, 201 }, 7519d26e4fcSRobert Mustacchi { 0 } 7529d26e4fcSRobert Mustacchi }; 7539d26e4fcSRobert Mustacchi 7549d26e4fcSRobert Mustacchi /** 7559d26e4fcSRobert Mustacchi * i40e_write_byte - replace HMC context byte 7569d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 7579d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 7589d26e4fcSRobert Mustacchi * @src: the struct to be read from 7599d26e4fcSRobert Mustacchi **/ 7609d26e4fcSRobert Mustacchi static void i40e_write_byte(u8 *hmc_bits, 7619d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 7629d26e4fcSRobert Mustacchi u8 *src) 7639d26e4fcSRobert Mustacchi { 7649d26e4fcSRobert Mustacchi u8 src_byte, dest_byte, mask; 7659d26e4fcSRobert Mustacchi u8 *from, *dest; 7669d26e4fcSRobert Mustacchi u16 shift_width; 7679d26e4fcSRobert Mustacchi 7689d26e4fcSRobert Mustacchi /* copy from the next struct field */ 7699d26e4fcSRobert Mustacchi from = src + ce_info->offset; 7709d26e4fcSRobert Mustacchi 7719d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 7729d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 773*3d75a287SRobert Mustacchi mask = (u8)(BIT(ce_info->width) - 1); 7749d26e4fcSRobert Mustacchi 7759d26e4fcSRobert Mustacchi src_byte = *from; 7769d26e4fcSRobert Mustacchi src_byte &= mask; 7779d26e4fcSRobert Mustacchi 7789d26e4fcSRobert Mustacchi /* shift to correct alignment */ 7799d26e4fcSRobert Mustacchi mask <<= shift_width; 7809d26e4fcSRobert Mustacchi src_byte <<= shift_width; 7819d26e4fcSRobert Mustacchi 7829d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 7839d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 7849d26e4fcSRobert Mustacchi 7859d26e4fcSRobert Mustacchi i40e_memcpy(&dest_byte, dest, sizeof(dest_byte), I40E_DMA_TO_NONDMA); 7869d26e4fcSRobert Mustacchi 7879d26e4fcSRobert Mustacchi dest_byte &= ~mask; /* get the bits not changing */ 7889d26e4fcSRobert Mustacchi dest_byte |= src_byte; /* add in the new bits */ 7899d26e4fcSRobert Mustacchi 7909d26e4fcSRobert Mustacchi /* put it all back */ 7919d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA); 7929d26e4fcSRobert Mustacchi } 7939d26e4fcSRobert Mustacchi 7949d26e4fcSRobert Mustacchi /** 7959d26e4fcSRobert Mustacchi * i40e_write_word - replace HMC context word 7969d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 7979d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 7989d26e4fcSRobert Mustacchi * @src: the struct to be read from 7999d26e4fcSRobert Mustacchi **/ 8009d26e4fcSRobert Mustacchi static void i40e_write_word(u8 *hmc_bits, 8019d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 8029d26e4fcSRobert Mustacchi u8 *src) 8039d26e4fcSRobert Mustacchi { 8049d26e4fcSRobert Mustacchi u16 src_word, mask; 8059d26e4fcSRobert Mustacchi u8 *from, *dest; 8069d26e4fcSRobert Mustacchi u16 shift_width; 8079d26e4fcSRobert Mustacchi __le16 dest_word; 8089d26e4fcSRobert Mustacchi 8099d26e4fcSRobert Mustacchi /* copy from the next struct field */ 8109d26e4fcSRobert Mustacchi from = src + ce_info->offset; 8119d26e4fcSRobert Mustacchi 8129d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 8139d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 8149d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 8159d26e4fcSRobert Mustacchi 8169d26e4fcSRobert Mustacchi /* don't swizzle the bits until after the mask because the mask bits 8179d26e4fcSRobert Mustacchi * will be in a different bit position on big endian machines 8189d26e4fcSRobert Mustacchi */ 8199d26e4fcSRobert Mustacchi src_word = *(u16 *)from; 8209d26e4fcSRobert Mustacchi src_word &= mask; 8219d26e4fcSRobert Mustacchi 8229d26e4fcSRobert Mustacchi /* shift to correct alignment */ 8239d26e4fcSRobert Mustacchi mask <<= shift_width; 8249d26e4fcSRobert Mustacchi src_word <<= shift_width; 8259d26e4fcSRobert Mustacchi 8269d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 8279d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 8289d26e4fcSRobert Mustacchi 8299d26e4fcSRobert Mustacchi i40e_memcpy(&dest_word, dest, sizeof(dest_word), I40E_DMA_TO_NONDMA); 8309d26e4fcSRobert Mustacchi 8319d26e4fcSRobert Mustacchi dest_word &= ~(CPU_TO_LE16(mask)); /* get the bits not changing */ 8329d26e4fcSRobert Mustacchi dest_word |= CPU_TO_LE16(src_word); /* add in the new bits */ 8339d26e4fcSRobert Mustacchi 8349d26e4fcSRobert Mustacchi /* put it all back */ 8359d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA); 8369d26e4fcSRobert Mustacchi } 8379d26e4fcSRobert Mustacchi 8389d26e4fcSRobert Mustacchi /** 8399d26e4fcSRobert Mustacchi * i40e_write_dword - replace HMC context dword 8409d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 8419d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 8429d26e4fcSRobert Mustacchi * @src: the struct to be read from 8439d26e4fcSRobert Mustacchi **/ 8449d26e4fcSRobert Mustacchi static void i40e_write_dword(u8 *hmc_bits, 8459d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 8469d26e4fcSRobert Mustacchi u8 *src) 8479d26e4fcSRobert Mustacchi { 8489d26e4fcSRobert Mustacchi u32 src_dword, mask; 8499d26e4fcSRobert Mustacchi u8 *from, *dest; 8509d26e4fcSRobert Mustacchi u16 shift_width; 8519d26e4fcSRobert Mustacchi __le32 dest_dword; 8529d26e4fcSRobert Mustacchi 8539d26e4fcSRobert Mustacchi /* copy from the next struct field */ 8549d26e4fcSRobert Mustacchi from = src + ce_info->offset; 8559d26e4fcSRobert Mustacchi 8569d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 8579d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 8589d26e4fcSRobert Mustacchi 8599d26e4fcSRobert Mustacchi /* if the field width is exactly 32 on an x86 machine, then the shift 8609d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 8619d26e4fcSRobert Mustacchi * to 5 bits so the shift will do nothing 8629d26e4fcSRobert Mustacchi */ 8639d26e4fcSRobert Mustacchi if (ce_info->width < 32) 8649d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 8659d26e4fcSRobert Mustacchi else 8669d26e4fcSRobert Mustacchi mask = ~(u32)0; 8679d26e4fcSRobert Mustacchi 8689d26e4fcSRobert Mustacchi /* don't swizzle the bits until after the mask because the mask bits 8699d26e4fcSRobert Mustacchi * will be in a different bit position on big endian machines 8709d26e4fcSRobert Mustacchi */ 8719d26e4fcSRobert Mustacchi src_dword = *(u32 *)from; 8729d26e4fcSRobert Mustacchi src_dword &= mask; 8739d26e4fcSRobert Mustacchi 8749d26e4fcSRobert Mustacchi /* shift to correct alignment */ 8759d26e4fcSRobert Mustacchi mask <<= shift_width; 8769d26e4fcSRobert Mustacchi src_dword <<= shift_width; 8779d26e4fcSRobert Mustacchi 8789d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 8799d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 8809d26e4fcSRobert Mustacchi 8819d26e4fcSRobert Mustacchi i40e_memcpy(&dest_dword, dest, sizeof(dest_dword), I40E_DMA_TO_NONDMA); 8829d26e4fcSRobert Mustacchi 8839d26e4fcSRobert Mustacchi dest_dword &= ~(CPU_TO_LE32(mask)); /* get the bits not changing */ 8849d26e4fcSRobert Mustacchi dest_dword |= CPU_TO_LE32(src_dword); /* add in the new bits */ 8859d26e4fcSRobert Mustacchi 8869d26e4fcSRobert Mustacchi /* put it all back */ 8879d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_dword, sizeof(dest_dword), I40E_NONDMA_TO_DMA); 8889d26e4fcSRobert Mustacchi } 8899d26e4fcSRobert Mustacchi 8909d26e4fcSRobert Mustacchi /** 8919d26e4fcSRobert Mustacchi * i40e_write_qword - replace HMC context qword 8929d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 8939d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 8949d26e4fcSRobert Mustacchi * @src: the struct to be read from 8959d26e4fcSRobert Mustacchi **/ 8969d26e4fcSRobert Mustacchi static void i40e_write_qword(u8 *hmc_bits, 8979d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 8989d26e4fcSRobert Mustacchi u8 *src) 8999d26e4fcSRobert Mustacchi { 9009d26e4fcSRobert Mustacchi u64 src_qword, mask; 9019d26e4fcSRobert Mustacchi u8 *from, *dest; 9029d26e4fcSRobert Mustacchi u16 shift_width; 9039d26e4fcSRobert Mustacchi __le64 dest_qword; 9049d26e4fcSRobert Mustacchi 9059d26e4fcSRobert Mustacchi /* copy from the next struct field */ 9069d26e4fcSRobert Mustacchi from = src + ce_info->offset; 9079d26e4fcSRobert Mustacchi 9089d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 9099d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 9109d26e4fcSRobert Mustacchi 9119d26e4fcSRobert Mustacchi /* if the field width is exactly 64 on an x86 machine, then the shift 9129d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 9139d26e4fcSRobert Mustacchi * to 6 bits so the shift will do nothing 9149d26e4fcSRobert Mustacchi */ 9159d26e4fcSRobert Mustacchi if (ce_info->width < 64) 9169d26e4fcSRobert Mustacchi mask = BIT_ULL(ce_info->width) - 1; 9179d26e4fcSRobert Mustacchi else 9189d26e4fcSRobert Mustacchi mask = ~(u64)0; 9199d26e4fcSRobert Mustacchi 9209d26e4fcSRobert Mustacchi /* don't swizzle the bits until after the mask because the mask bits 9219d26e4fcSRobert Mustacchi * will be in a different bit position on big endian machines 9229d26e4fcSRobert Mustacchi */ 9239d26e4fcSRobert Mustacchi src_qword = *(u64 *)from; 9249d26e4fcSRobert Mustacchi src_qword &= mask; 9259d26e4fcSRobert Mustacchi 9269d26e4fcSRobert Mustacchi /* shift to correct alignment */ 9279d26e4fcSRobert Mustacchi mask <<= shift_width; 9289d26e4fcSRobert Mustacchi src_qword <<= shift_width; 9299d26e4fcSRobert Mustacchi 9309d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 9319d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 9329d26e4fcSRobert Mustacchi 9339d26e4fcSRobert Mustacchi i40e_memcpy(&dest_qword, dest, sizeof(dest_qword), I40E_DMA_TO_NONDMA); 9349d26e4fcSRobert Mustacchi 9359d26e4fcSRobert Mustacchi dest_qword &= ~(CPU_TO_LE64(mask)); /* get the bits not changing */ 9369d26e4fcSRobert Mustacchi dest_qword |= CPU_TO_LE64(src_qword); /* add in the new bits */ 9379d26e4fcSRobert Mustacchi 9389d26e4fcSRobert Mustacchi /* put it all back */ 9399d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_qword, sizeof(dest_qword), I40E_NONDMA_TO_DMA); 9409d26e4fcSRobert Mustacchi } 9419d26e4fcSRobert Mustacchi 9429d26e4fcSRobert Mustacchi /** 9439d26e4fcSRobert Mustacchi * i40e_read_byte - read HMC context byte into struct 9449d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 9459d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 9469d26e4fcSRobert Mustacchi * @dest: the struct to be filled 9479d26e4fcSRobert Mustacchi **/ 9489d26e4fcSRobert Mustacchi static void i40e_read_byte(u8 *hmc_bits, 9499d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 9509d26e4fcSRobert Mustacchi u8 *dest) 9519d26e4fcSRobert Mustacchi { 9529d26e4fcSRobert Mustacchi u8 dest_byte, mask; 9539d26e4fcSRobert Mustacchi u8 *src, *target; 9549d26e4fcSRobert Mustacchi u16 shift_width; 9559d26e4fcSRobert Mustacchi 9569d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 9579d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 958*3d75a287SRobert Mustacchi mask = (u8)(BIT(ce_info->width) - 1); 9599d26e4fcSRobert Mustacchi 9609d26e4fcSRobert Mustacchi /* shift to correct alignment */ 9619d26e4fcSRobert Mustacchi mask <<= shift_width; 9629d26e4fcSRobert Mustacchi 9639d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 9649d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 9659d26e4fcSRobert Mustacchi 9669d26e4fcSRobert Mustacchi i40e_memcpy(&dest_byte, src, sizeof(dest_byte), I40E_DMA_TO_NONDMA); 9679d26e4fcSRobert Mustacchi 9689d26e4fcSRobert Mustacchi dest_byte &= ~(mask); 9699d26e4fcSRobert Mustacchi 9709d26e4fcSRobert Mustacchi dest_byte >>= shift_width; 9719d26e4fcSRobert Mustacchi 9729d26e4fcSRobert Mustacchi /* get the address from the struct field */ 9739d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 9749d26e4fcSRobert Mustacchi 9759d26e4fcSRobert Mustacchi /* put it back in the struct */ 9769d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA); 9779d26e4fcSRobert Mustacchi } 9789d26e4fcSRobert Mustacchi 9799d26e4fcSRobert Mustacchi /** 9809d26e4fcSRobert Mustacchi * i40e_read_word - read HMC context word into struct 9819d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 9829d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 9839d26e4fcSRobert Mustacchi * @dest: the struct to be filled 9849d26e4fcSRobert Mustacchi **/ 9859d26e4fcSRobert Mustacchi static void i40e_read_word(u8 *hmc_bits, 9869d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 9879d26e4fcSRobert Mustacchi u8 *dest) 9889d26e4fcSRobert Mustacchi { 9899d26e4fcSRobert Mustacchi u16 dest_word, mask; 9909d26e4fcSRobert Mustacchi u8 *src, *target; 9919d26e4fcSRobert Mustacchi u16 shift_width; 9929d26e4fcSRobert Mustacchi __le16 src_word; 9939d26e4fcSRobert Mustacchi 9949d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 9959d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 9969d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 9979d26e4fcSRobert Mustacchi 9989d26e4fcSRobert Mustacchi /* shift to correct alignment */ 9999d26e4fcSRobert Mustacchi mask <<= shift_width; 10009d26e4fcSRobert Mustacchi 10019d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 10029d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 10039d26e4fcSRobert Mustacchi 10049d26e4fcSRobert Mustacchi i40e_memcpy(&src_word, src, sizeof(src_word), I40E_DMA_TO_NONDMA); 10059d26e4fcSRobert Mustacchi 10069d26e4fcSRobert Mustacchi /* the data in the memory is stored as little endian so mask it 10079d26e4fcSRobert Mustacchi * correctly 10089d26e4fcSRobert Mustacchi */ 10099d26e4fcSRobert Mustacchi src_word &= ~(CPU_TO_LE16(mask)); 10109d26e4fcSRobert Mustacchi 10119d26e4fcSRobert Mustacchi /* get the data back into host order before shifting */ 10129d26e4fcSRobert Mustacchi dest_word = LE16_TO_CPU(src_word); 10139d26e4fcSRobert Mustacchi 10149d26e4fcSRobert Mustacchi dest_word >>= shift_width; 10159d26e4fcSRobert Mustacchi 10169d26e4fcSRobert Mustacchi /* get the address from the struct field */ 10179d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 10189d26e4fcSRobert Mustacchi 10199d26e4fcSRobert Mustacchi /* put it back in the struct */ 10209d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA); 10219d26e4fcSRobert Mustacchi } 10229d26e4fcSRobert Mustacchi 10239d26e4fcSRobert Mustacchi /** 10249d26e4fcSRobert Mustacchi * i40e_read_dword - read HMC context dword into struct 10259d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 10269d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 10279d26e4fcSRobert Mustacchi * @dest: the struct to be filled 10289d26e4fcSRobert Mustacchi **/ 10299d26e4fcSRobert Mustacchi static void i40e_read_dword(u8 *hmc_bits, 10309d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 10319d26e4fcSRobert Mustacchi u8 *dest) 10329d26e4fcSRobert Mustacchi { 10339d26e4fcSRobert Mustacchi u32 dest_dword, mask; 10349d26e4fcSRobert Mustacchi u8 *src, *target; 10359d26e4fcSRobert Mustacchi u16 shift_width; 10369d26e4fcSRobert Mustacchi __le32 src_dword; 10379d26e4fcSRobert Mustacchi 10389d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 10399d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 10409d26e4fcSRobert Mustacchi 10419d26e4fcSRobert Mustacchi /* if the field width is exactly 32 on an x86 machine, then the shift 10429d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 10439d26e4fcSRobert Mustacchi * to 5 bits so the shift will do nothing 10449d26e4fcSRobert Mustacchi */ 10459d26e4fcSRobert Mustacchi if (ce_info->width < 32) 10469d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 10479d26e4fcSRobert Mustacchi else 10489d26e4fcSRobert Mustacchi mask = ~(u32)0; 10499d26e4fcSRobert Mustacchi 10509d26e4fcSRobert Mustacchi /* shift to correct alignment */ 10519d26e4fcSRobert Mustacchi mask <<= shift_width; 10529d26e4fcSRobert Mustacchi 10539d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 10549d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 10559d26e4fcSRobert Mustacchi 10569d26e4fcSRobert Mustacchi i40e_memcpy(&src_dword, src, sizeof(src_dword), I40E_DMA_TO_NONDMA); 10579d26e4fcSRobert Mustacchi 10589d26e4fcSRobert Mustacchi /* the data in the memory is stored as little endian so mask it 10599d26e4fcSRobert Mustacchi * correctly 10609d26e4fcSRobert Mustacchi */ 10619d26e4fcSRobert Mustacchi src_dword &= ~(CPU_TO_LE32(mask)); 10629d26e4fcSRobert Mustacchi 10639d26e4fcSRobert Mustacchi /* get the data back into host order before shifting */ 10649d26e4fcSRobert Mustacchi dest_dword = LE32_TO_CPU(src_dword); 10659d26e4fcSRobert Mustacchi 10669d26e4fcSRobert Mustacchi dest_dword >>= shift_width; 10679d26e4fcSRobert Mustacchi 10689d26e4fcSRobert Mustacchi /* get the address from the struct field */ 10699d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 10709d26e4fcSRobert Mustacchi 10719d26e4fcSRobert Mustacchi /* put it back in the struct */ 10729d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_dword, sizeof(dest_dword), 10739d26e4fcSRobert Mustacchi I40E_NONDMA_TO_DMA); 10749d26e4fcSRobert Mustacchi } 10759d26e4fcSRobert Mustacchi 10769d26e4fcSRobert Mustacchi /** 10779d26e4fcSRobert Mustacchi * i40e_read_qword - read HMC context qword into struct 10789d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 10799d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 10809d26e4fcSRobert Mustacchi * @dest: the struct to be filled 10819d26e4fcSRobert Mustacchi **/ 10829d26e4fcSRobert Mustacchi static void i40e_read_qword(u8 *hmc_bits, 10839d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 10849d26e4fcSRobert Mustacchi u8 *dest) 10859d26e4fcSRobert Mustacchi { 10869d26e4fcSRobert Mustacchi u64 dest_qword, mask; 10879d26e4fcSRobert Mustacchi u8 *src, *target; 10889d26e4fcSRobert Mustacchi u16 shift_width; 10899d26e4fcSRobert Mustacchi __le64 src_qword; 10909d26e4fcSRobert Mustacchi 10919d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 10929d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 10939d26e4fcSRobert Mustacchi 10949d26e4fcSRobert Mustacchi /* if the field width is exactly 64 on an x86 machine, then the shift 10959d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 10969d26e4fcSRobert Mustacchi * to 6 bits so the shift will do nothing 10979d26e4fcSRobert Mustacchi */ 10989d26e4fcSRobert Mustacchi if (ce_info->width < 64) 10999d26e4fcSRobert Mustacchi mask = BIT_ULL(ce_info->width) - 1; 11009d26e4fcSRobert Mustacchi else 11019d26e4fcSRobert Mustacchi mask = ~(u64)0; 11029d26e4fcSRobert Mustacchi 11039d26e4fcSRobert Mustacchi /* shift to correct alignment */ 11049d26e4fcSRobert Mustacchi mask <<= shift_width; 11059d26e4fcSRobert Mustacchi 11069d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 11079d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 11089d26e4fcSRobert Mustacchi 11099d26e4fcSRobert Mustacchi i40e_memcpy(&src_qword, src, sizeof(src_qword), I40E_DMA_TO_NONDMA); 11109d26e4fcSRobert Mustacchi 11119d26e4fcSRobert Mustacchi /* the data in the memory is stored as little endian so mask it 11129d26e4fcSRobert Mustacchi * correctly 11139d26e4fcSRobert Mustacchi */ 11149d26e4fcSRobert Mustacchi src_qword &= ~(CPU_TO_LE64(mask)); 11159d26e4fcSRobert Mustacchi 11169d26e4fcSRobert Mustacchi /* get the data back into host order before shifting */ 11179d26e4fcSRobert Mustacchi dest_qword = LE64_TO_CPU(src_qword); 11189d26e4fcSRobert Mustacchi 11199d26e4fcSRobert Mustacchi dest_qword >>= shift_width; 11209d26e4fcSRobert Mustacchi 11219d26e4fcSRobert Mustacchi /* get the address from the struct field */ 11229d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 11239d26e4fcSRobert Mustacchi 11249d26e4fcSRobert Mustacchi /* put it back in the struct */ 11259d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_qword, sizeof(dest_qword), 11269d26e4fcSRobert Mustacchi I40E_NONDMA_TO_DMA); 11279d26e4fcSRobert Mustacchi } 11289d26e4fcSRobert Mustacchi 11299d26e4fcSRobert Mustacchi /** 11309d26e4fcSRobert Mustacchi * i40e_get_hmc_context - extract HMC context bits 11319d26e4fcSRobert Mustacchi * @context_bytes: pointer to the context bit array 11329d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 11339d26e4fcSRobert Mustacchi * @dest: the struct to be filled 11349d26e4fcSRobert Mustacchi **/ 11359d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_get_hmc_context(u8 *context_bytes, 11369d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 11379d26e4fcSRobert Mustacchi u8 *dest) 11389d26e4fcSRobert Mustacchi { 11399d26e4fcSRobert Mustacchi int f; 11409d26e4fcSRobert Mustacchi 11419d26e4fcSRobert Mustacchi for (f = 0; ce_info[f].width != 0; f++) { 11429d26e4fcSRobert Mustacchi switch (ce_info[f].size_of) { 11439d26e4fcSRobert Mustacchi case 1: 11449d26e4fcSRobert Mustacchi i40e_read_byte(context_bytes, &ce_info[f], dest); 11459d26e4fcSRobert Mustacchi break; 11469d26e4fcSRobert Mustacchi case 2: 11479d26e4fcSRobert Mustacchi i40e_read_word(context_bytes, &ce_info[f], dest); 11489d26e4fcSRobert Mustacchi break; 11499d26e4fcSRobert Mustacchi case 4: 11509d26e4fcSRobert Mustacchi i40e_read_dword(context_bytes, &ce_info[f], dest); 11519d26e4fcSRobert Mustacchi break; 11529d26e4fcSRobert Mustacchi case 8: 11539d26e4fcSRobert Mustacchi i40e_read_qword(context_bytes, &ce_info[f], dest); 11549d26e4fcSRobert Mustacchi break; 11559d26e4fcSRobert Mustacchi default: 11569d26e4fcSRobert Mustacchi /* nothing to do, just keep going */ 11579d26e4fcSRobert Mustacchi break; 11589d26e4fcSRobert Mustacchi } 11599d26e4fcSRobert Mustacchi } 11609d26e4fcSRobert Mustacchi 11619d26e4fcSRobert Mustacchi return I40E_SUCCESS; 11629d26e4fcSRobert Mustacchi } 11639d26e4fcSRobert Mustacchi 11649d26e4fcSRobert Mustacchi /** 11659d26e4fcSRobert Mustacchi * i40e_clear_hmc_context - zero out the HMC context bits 11669d26e4fcSRobert Mustacchi * @hw: the hardware struct 11679d26e4fcSRobert Mustacchi * @context_bytes: pointer to the context bit array (DMA memory) 11689d26e4fcSRobert Mustacchi * @hmc_type: the type of HMC resource 11699d26e4fcSRobert Mustacchi **/ 11709d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_clear_hmc_context(struct i40e_hw *hw, 11719d26e4fcSRobert Mustacchi u8 *context_bytes, 11729d26e4fcSRobert Mustacchi enum i40e_hmc_lan_rsrc_type hmc_type) 11739d26e4fcSRobert Mustacchi { 11749d26e4fcSRobert Mustacchi /* clean the bit array */ 11759d26e4fcSRobert Mustacchi i40e_memset(context_bytes, 0, (u32)hw->hmc.hmc_obj[hmc_type].size, 11769d26e4fcSRobert Mustacchi I40E_DMA_MEM); 11779d26e4fcSRobert Mustacchi 11789d26e4fcSRobert Mustacchi return I40E_SUCCESS; 11799d26e4fcSRobert Mustacchi } 11809d26e4fcSRobert Mustacchi 11819d26e4fcSRobert Mustacchi /** 11829d26e4fcSRobert Mustacchi * i40e_set_hmc_context - replace HMC context bits 11839d26e4fcSRobert Mustacchi * @context_bytes: pointer to the context bit array 11849d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 11859d26e4fcSRobert Mustacchi * @dest: the struct to be filled 11869d26e4fcSRobert Mustacchi **/ 11879d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_set_hmc_context(u8 *context_bytes, 11889d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 11899d26e4fcSRobert Mustacchi u8 *dest) 11909d26e4fcSRobert Mustacchi { 11919d26e4fcSRobert Mustacchi int f; 11929d26e4fcSRobert Mustacchi 11939d26e4fcSRobert Mustacchi for (f = 0; ce_info[f].width != 0; f++) { 11949d26e4fcSRobert Mustacchi 11959d26e4fcSRobert Mustacchi /* we have to deal with each element of the HMC using the 11969d26e4fcSRobert Mustacchi * correct size so that we are correct regardless of the 11979d26e4fcSRobert Mustacchi * endianness of the machine 11989d26e4fcSRobert Mustacchi */ 11999d26e4fcSRobert Mustacchi switch (ce_info[f].size_of) { 12009d26e4fcSRobert Mustacchi case 1: 12019d26e4fcSRobert Mustacchi i40e_write_byte(context_bytes, &ce_info[f], dest); 12029d26e4fcSRobert Mustacchi break; 12039d26e4fcSRobert Mustacchi case 2: 12049d26e4fcSRobert Mustacchi i40e_write_word(context_bytes, &ce_info[f], dest); 12059d26e4fcSRobert Mustacchi break; 12069d26e4fcSRobert Mustacchi case 4: 12079d26e4fcSRobert Mustacchi i40e_write_dword(context_bytes, &ce_info[f], dest); 12089d26e4fcSRobert Mustacchi break; 12099d26e4fcSRobert Mustacchi case 8: 12109d26e4fcSRobert Mustacchi i40e_write_qword(context_bytes, &ce_info[f], dest); 12119d26e4fcSRobert Mustacchi break; 12129d26e4fcSRobert Mustacchi } 12139d26e4fcSRobert Mustacchi } 12149d26e4fcSRobert Mustacchi 12159d26e4fcSRobert Mustacchi return I40E_SUCCESS; 12169d26e4fcSRobert Mustacchi } 12179d26e4fcSRobert Mustacchi 12189d26e4fcSRobert Mustacchi /** 12199d26e4fcSRobert Mustacchi * i40e_hmc_get_object_va - retrieves an object's virtual address 12209d26e4fcSRobert Mustacchi * @hw: pointer to the hw structure 12219d26e4fcSRobert Mustacchi * @object_base: pointer to u64 to get the va 12229d26e4fcSRobert Mustacchi * @rsrc_type: the hmc resource type 12239d26e4fcSRobert Mustacchi * @obj_idx: hmc object index 12249d26e4fcSRobert Mustacchi * 12259d26e4fcSRobert Mustacchi * This function retrieves the object's virtual address from the object 12269d26e4fcSRobert Mustacchi * base pointer. This function is used for LAN Queue contexts. 12279d26e4fcSRobert Mustacchi **/ 12289d26e4fcSRobert Mustacchi static 12299d26e4fcSRobert Mustacchi enum i40e_status_code i40e_hmc_get_object_va(struct i40e_hw *hw, 12309d26e4fcSRobert Mustacchi u8 **object_base, 12319d26e4fcSRobert Mustacchi enum i40e_hmc_lan_rsrc_type rsrc_type, 12329d26e4fcSRobert Mustacchi u32 obj_idx) 12339d26e4fcSRobert Mustacchi { 12349d26e4fcSRobert Mustacchi u32 obj_offset_in_sd, obj_offset_in_pd; 12359d26e4fcSRobert Mustacchi struct i40e_hmc_info *hmc_info = &hw->hmc; 12369d26e4fcSRobert Mustacchi struct i40e_hmc_sd_entry *sd_entry; 12379d26e4fcSRobert Mustacchi struct i40e_hmc_pd_entry *pd_entry; 12389d26e4fcSRobert Mustacchi u32 pd_idx, pd_lmt, rel_pd_idx; 12399d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 12409d26e4fcSRobert Mustacchi u64 obj_offset_in_fpm; 12419d26e4fcSRobert Mustacchi u32 sd_idx, sd_lmt; 12429d26e4fcSRobert Mustacchi 12439d26e4fcSRobert Mustacchi if (NULL == hmc_info->hmc_obj) { 12449d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 12459d26e4fcSRobert Mustacchi DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n"); 12469d26e4fcSRobert Mustacchi goto exit; 12479d26e4fcSRobert Mustacchi } 12489d26e4fcSRobert Mustacchi if (NULL == object_base) { 12499d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 12509d26e4fcSRobert Mustacchi DEBUGOUT("i40e_hmc_get_object_va: bad object_base ptr\n"); 12519d26e4fcSRobert Mustacchi goto exit; 12529d26e4fcSRobert Mustacchi } 12539d26e4fcSRobert Mustacchi if (I40E_HMC_INFO_SIGNATURE != hmc_info->signature) { 12549d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 12559d26e4fcSRobert Mustacchi DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->signature\n"); 12569d26e4fcSRobert Mustacchi goto exit; 12579d26e4fcSRobert Mustacchi } 12589d26e4fcSRobert Mustacchi if (obj_idx >= hmc_info->hmc_obj[rsrc_type].cnt) { 12599d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_hmc_get_object_va: returns error %d\n", 12609d26e4fcSRobert Mustacchi ret_code); 12619d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; 12629d26e4fcSRobert Mustacchi goto exit; 12639d26e4fcSRobert Mustacchi } 12649d26e4fcSRobert Mustacchi /* find sd index and limit */ 12659d26e4fcSRobert Mustacchi I40E_FIND_SD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1, 12669d26e4fcSRobert Mustacchi &sd_idx, &sd_lmt); 12679d26e4fcSRobert Mustacchi 12689d26e4fcSRobert Mustacchi sd_entry = &hmc_info->sd_table.sd_entry[sd_idx]; 12699d26e4fcSRobert Mustacchi obj_offset_in_fpm = hmc_info->hmc_obj[rsrc_type].base + 12709d26e4fcSRobert Mustacchi hmc_info->hmc_obj[rsrc_type].size * obj_idx; 12719d26e4fcSRobert Mustacchi 12729d26e4fcSRobert Mustacchi if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) { 12739d26e4fcSRobert Mustacchi I40E_FIND_PD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1, 12749d26e4fcSRobert Mustacchi &pd_idx, &pd_lmt); 12759d26e4fcSRobert Mustacchi rel_pd_idx = pd_idx % I40E_HMC_PD_CNT_IN_SD; 12769d26e4fcSRobert Mustacchi pd_entry = &sd_entry->u.pd_table.pd_entry[rel_pd_idx]; 12779d26e4fcSRobert Mustacchi obj_offset_in_pd = (u32)(obj_offset_in_fpm % 12789d26e4fcSRobert Mustacchi I40E_HMC_PAGED_BP_SIZE); 12799d26e4fcSRobert Mustacchi *object_base = (u8 *)pd_entry->bp.addr.va + obj_offset_in_pd; 12809d26e4fcSRobert Mustacchi } else { 12819d26e4fcSRobert Mustacchi obj_offset_in_sd = (u32)(obj_offset_in_fpm % 12829d26e4fcSRobert Mustacchi I40E_HMC_DIRECT_BP_SIZE); 12839d26e4fcSRobert Mustacchi *object_base = (u8 *)sd_entry->u.bp.addr.va + obj_offset_in_sd; 12849d26e4fcSRobert Mustacchi } 12859d26e4fcSRobert Mustacchi exit: 12869d26e4fcSRobert Mustacchi return ret_code; 12879d26e4fcSRobert Mustacchi } 12889d26e4fcSRobert Mustacchi 12899d26e4fcSRobert Mustacchi /** 12909d26e4fcSRobert Mustacchi * i40e_get_lan_tx_queue_context - return the HMC context for the queue 12919d26e4fcSRobert Mustacchi * @hw: the hardware struct 12929d26e4fcSRobert Mustacchi * @queue: the queue we care about 12939d26e4fcSRobert Mustacchi * @s: the struct to be filled 12949d26e4fcSRobert Mustacchi **/ 12959d26e4fcSRobert Mustacchi enum i40e_status_code i40e_get_lan_tx_queue_context(struct i40e_hw *hw, 12969d26e4fcSRobert Mustacchi u16 queue, 12979d26e4fcSRobert Mustacchi struct i40e_hmc_obj_txq *s) 12989d26e4fcSRobert Mustacchi { 12999d26e4fcSRobert Mustacchi enum i40e_status_code err; 13009d26e4fcSRobert Mustacchi u8 *context_bytes; 13019d26e4fcSRobert Mustacchi 13029d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); 13039d26e4fcSRobert Mustacchi if (err < 0) 13049d26e4fcSRobert Mustacchi return err; 13059d26e4fcSRobert Mustacchi 13069d26e4fcSRobert Mustacchi return i40e_get_hmc_context(context_bytes, 13079d26e4fcSRobert Mustacchi i40e_hmc_txq_ce_info, (u8 *)s); 13089d26e4fcSRobert Mustacchi } 13099d26e4fcSRobert Mustacchi 13109d26e4fcSRobert Mustacchi /** 13119d26e4fcSRobert Mustacchi * i40e_clear_lan_tx_queue_context - clear the HMC context for the queue 13129d26e4fcSRobert Mustacchi * @hw: the hardware struct 13139d26e4fcSRobert Mustacchi * @queue: the queue we care about 13149d26e4fcSRobert Mustacchi **/ 13159d26e4fcSRobert Mustacchi enum i40e_status_code i40e_clear_lan_tx_queue_context(struct i40e_hw *hw, 13169d26e4fcSRobert Mustacchi u16 queue) 13179d26e4fcSRobert Mustacchi { 13189d26e4fcSRobert Mustacchi enum i40e_status_code err; 13199d26e4fcSRobert Mustacchi u8 *context_bytes; 13209d26e4fcSRobert Mustacchi 13219d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); 13229d26e4fcSRobert Mustacchi if (err < 0) 13239d26e4fcSRobert Mustacchi return err; 13249d26e4fcSRobert Mustacchi 13259d26e4fcSRobert Mustacchi return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_TX); 13269d26e4fcSRobert Mustacchi } 13279d26e4fcSRobert Mustacchi 13289d26e4fcSRobert Mustacchi /** 13299d26e4fcSRobert Mustacchi * i40e_set_lan_tx_queue_context - set the HMC context for the queue 13309d26e4fcSRobert Mustacchi * @hw: the hardware struct 13319d26e4fcSRobert Mustacchi * @queue: the queue we care about 13329d26e4fcSRobert Mustacchi * @s: the struct to be filled 13339d26e4fcSRobert Mustacchi **/ 13349d26e4fcSRobert Mustacchi enum i40e_status_code i40e_set_lan_tx_queue_context(struct i40e_hw *hw, 13359d26e4fcSRobert Mustacchi u16 queue, 13369d26e4fcSRobert Mustacchi struct i40e_hmc_obj_txq *s) 13379d26e4fcSRobert Mustacchi { 13389d26e4fcSRobert Mustacchi enum i40e_status_code err; 13399d26e4fcSRobert Mustacchi u8 *context_bytes; 13409d26e4fcSRobert Mustacchi 13419d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); 13429d26e4fcSRobert Mustacchi if (err < 0) 13439d26e4fcSRobert Mustacchi return err; 13449d26e4fcSRobert Mustacchi 13459d26e4fcSRobert Mustacchi return i40e_set_hmc_context(context_bytes, 13469d26e4fcSRobert Mustacchi i40e_hmc_txq_ce_info, (u8 *)s); 13479d26e4fcSRobert Mustacchi } 13489d26e4fcSRobert Mustacchi 13499d26e4fcSRobert Mustacchi /** 13509d26e4fcSRobert Mustacchi * i40e_get_lan_rx_queue_context - return the HMC context for the queue 13519d26e4fcSRobert Mustacchi * @hw: the hardware struct 13529d26e4fcSRobert Mustacchi * @queue: the queue we care about 13539d26e4fcSRobert Mustacchi * @s: the struct to be filled 13549d26e4fcSRobert Mustacchi **/ 13559d26e4fcSRobert Mustacchi enum i40e_status_code i40e_get_lan_rx_queue_context(struct i40e_hw *hw, 13569d26e4fcSRobert Mustacchi u16 queue, 13579d26e4fcSRobert Mustacchi struct i40e_hmc_obj_rxq *s) 13589d26e4fcSRobert Mustacchi { 13599d26e4fcSRobert Mustacchi enum i40e_status_code err; 13609d26e4fcSRobert Mustacchi u8 *context_bytes; 13619d26e4fcSRobert Mustacchi 13629d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); 13639d26e4fcSRobert Mustacchi if (err < 0) 13649d26e4fcSRobert Mustacchi return err; 13659d26e4fcSRobert Mustacchi 13669d26e4fcSRobert Mustacchi return i40e_get_hmc_context(context_bytes, 13679d26e4fcSRobert Mustacchi i40e_hmc_rxq_ce_info, (u8 *)s); 13689d26e4fcSRobert Mustacchi } 13699d26e4fcSRobert Mustacchi 13709d26e4fcSRobert Mustacchi /** 13719d26e4fcSRobert Mustacchi * i40e_clear_lan_rx_queue_context - clear the HMC context for the queue 13729d26e4fcSRobert Mustacchi * @hw: the hardware struct 13739d26e4fcSRobert Mustacchi * @queue: the queue we care about 13749d26e4fcSRobert Mustacchi **/ 13759d26e4fcSRobert Mustacchi enum i40e_status_code i40e_clear_lan_rx_queue_context(struct i40e_hw *hw, 13769d26e4fcSRobert Mustacchi u16 queue) 13779d26e4fcSRobert Mustacchi { 13789d26e4fcSRobert Mustacchi enum i40e_status_code err; 13799d26e4fcSRobert Mustacchi u8 *context_bytes; 13809d26e4fcSRobert Mustacchi 13819d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); 13829d26e4fcSRobert Mustacchi if (err < 0) 13839d26e4fcSRobert Mustacchi return err; 13849d26e4fcSRobert Mustacchi 13859d26e4fcSRobert Mustacchi return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_RX); 13869d26e4fcSRobert Mustacchi } 13879d26e4fcSRobert Mustacchi 13889d26e4fcSRobert Mustacchi /** 13899d26e4fcSRobert Mustacchi * i40e_set_lan_rx_queue_context - set the HMC context for the queue 13909d26e4fcSRobert Mustacchi * @hw: the hardware struct 13919d26e4fcSRobert Mustacchi * @queue: the queue we care about 13929d26e4fcSRobert Mustacchi * @s: the struct to be filled 13939d26e4fcSRobert Mustacchi **/ 13949d26e4fcSRobert Mustacchi enum i40e_status_code i40e_set_lan_rx_queue_context(struct i40e_hw *hw, 13959d26e4fcSRobert Mustacchi u16 queue, 13969d26e4fcSRobert Mustacchi struct i40e_hmc_obj_rxq *s) 13979d26e4fcSRobert Mustacchi { 13989d26e4fcSRobert Mustacchi enum i40e_status_code err; 13999d26e4fcSRobert Mustacchi u8 *context_bytes; 14009d26e4fcSRobert Mustacchi 14019d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); 14029d26e4fcSRobert Mustacchi if (err < 0) 14039d26e4fcSRobert Mustacchi return err; 14049d26e4fcSRobert Mustacchi 14059d26e4fcSRobert Mustacchi return i40e_set_hmc_context(context_bytes, 14069d26e4fcSRobert Mustacchi i40e_hmc_rxq_ce_info, (u8 *)s); 14079d26e4fcSRobert Mustacchi } 1408