1*9d26e4fcSRobert Mustacchi /****************************************************************************** 2*9d26e4fcSRobert Mustacchi 3*9d26e4fcSRobert Mustacchi Copyright (c) 2013-2015, Intel Corporation 4*9d26e4fcSRobert Mustacchi All rights reserved. 5*9d26e4fcSRobert Mustacchi 6*9d26e4fcSRobert Mustacchi Redistribution and use in source and binary forms, with or without 7*9d26e4fcSRobert Mustacchi modification, are permitted provided that the following conditions are met: 8*9d26e4fcSRobert Mustacchi 9*9d26e4fcSRobert Mustacchi 1. Redistributions of source code must retain the above copyright notice, 10*9d26e4fcSRobert Mustacchi this list of conditions and the following disclaimer. 11*9d26e4fcSRobert Mustacchi 12*9d26e4fcSRobert Mustacchi 2. Redistributions in binary form must reproduce the above copyright 13*9d26e4fcSRobert Mustacchi notice, this list of conditions and the following disclaimer in the 14*9d26e4fcSRobert Mustacchi documentation and/or other materials provided with the distribution. 15*9d26e4fcSRobert Mustacchi 16*9d26e4fcSRobert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its 17*9d26e4fcSRobert Mustacchi contributors may be used to endorse or promote products derived from 18*9d26e4fcSRobert Mustacchi this software without specific prior written permission. 19*9d26e4fcSRobert Mustacchi 20*9d26e4fcSRobert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 21*9d26e4fcSRobert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22*9d26e4fcSRobert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23*9d26e4fcSRobert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 24*9d26e4fcSRobert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 25*9d26e4fcSRobert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 26*9d26e4fcSRobert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 27*9d26e4fcSRobert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 28*9d26e4fcSRobert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 29*9d26e4fcSRobert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 30*9d26e4fcSRobert Mustacchi POSSIBILITY OF SUCH DAMAGE. 31*9d26e4fcSRobert Mustacchi 32*9d26e4fcSRobert Mustacchi ******************************************************************************/ 33*9d26e4fcSRobert Mustacchi /*$FreeBSD: head/sys/dev/ixl/i40e_lan_hmc.c 284049 2015-06-05 22:52:42Z jfv $*/ 34*9d26e4fcSRobert Mustacchi 35*9d26e4fcSRobert Mustacchi #include "i40e_osdep.h" 36*9d26e4fcSRobert Mustacchi #include "i40e_register.h" 37*9d26e4fcSRobert Mustacchi #include "i40e_type.h" 38*9d26e4fcSRobert Mustacchi #include "i40e_hmc.h" 39*9d26e4fcSRobert Mustacchi #include "i40e_lan_hmc.h" 40*9d26e4fcSRobert Mustacchi #include "i40e_prototype.h" 41*9d26e4fcSRobert Mustacchi 42*9d26e4fcSRobert Mustacchi /* lan specific interface functions */ 43*9d26e4fcSRobert Mustacchi 44*9d26e4fcSRobert Mustacchi /** 45*9d26e4fcSRobert Mustacchi * i40e_align_l2obj_base - aligns base object pointer to 512 bytes 46*9d26e4fcSRobert Mustacchi * @offset: base address offset needing alignment 47*9d26e4fcSRobert Mustacchi * 48*9d26e4fcSRobert Mustacchi * Aligns the layer 2 function private memory so it's 512-byte aligned. 49*9d26e4fcSRobert Mustacchi **/ 50*9d26e4fcSRobert Mustacchi static u64 i40e_align_l2obj_base(u64 offset) 51*9d26e4fcSRobert Mustacchi { 52*9d26e4fcSRobert Mustacchi u64 aligned_offset = offset; 53*9d26e4fcSRobert Mustacchi 54*9d26e4fcSRobert Mustacchi if ((offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT) > 0) 55*9d26e4fcSRobert Mustacchi aligned_offset += (I40E_HMC_L2OBJ_BASE_ALIGNMENT - 56*9d26e4fcSRobert Mustacchi (offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT)); 57*9d26e4fcSRobert Mustacchi 58*9d26e4fcSRobert Mustacchi return aligned_offset; 59*9d26e4fcSRobert Mustacchi } 60*9d26e4fcSRobert Mustacchi 61*9d26e4fcSRobert Mustacchi /** 62*9d26e4fcSRobert Mustacchi * i40e_calculate_l2fpm_size - calculates layer 2 FPM memory size 63*9d26e4fcSRobert Mustacchi * @txq_num: number of Tx queues needing backing context 64*9d26e4fcSRobert Mustacchi * @rxq_num: number of Rx queues needing backing context 65*9d26e4fcSRobert Mustacchi * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context 66*9d26e4fcSRobert Mustacchi * @fcoe_filt_num: number of FCoE filters needing backing context 67*9d26e4fcSRobert Mustacchi * 68*9d26e4fcSRobert Mustacchi * Calculates the maximum amount of memory for the function required, based 69*9d26e4fcSRobert Mustacchi * on the number of resources it must provide context for. 70*9d26e4fcSRobert Mustacchi **/ 71*9d26e4fcSRobert Mustacchi u64 i40e_calculate_l2fpm_size(u32 txq_num, u32 rxq_num, 72*9d26e4fcSRobert Mustacchi u32 fcoe_cntx_num, u32 fcoe_filt_num) 73*9d26e4fcSRobert Mustacchi { 74*9d26e4fcSRobert Mustacchi u64 fpm_size = 0; 75*9d26e4fcSRobert Mustacchi 76*9d26e4fcSRobert Mustacchi fpm_size = txq_num * I40E_HMC_OBJ_SIZE_TXQ; 77*9d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 78*9d26e4fcSRobert Mustacchi 79*9d26e4fcSRobert Mustacchi fpm_size += (rxq_num * I40E_HMC_OBJ_SIZE_RXQ); 80*9d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 81*9d26e4fcSRobert Mustacchi 82*9d26e4fcSRobert Mustacchi fpm_size += (fcoe_cntx_num * I40E_HMC_OBJ_SIZE_FCOE_CNTX); 83*9d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 84*9d26e4fcSRobert Mustacchi 85*9d26e4fcSRobert Mustacchi fpm_size += (fcoe_filt_num * I40E_HMC_OBJ_SIZE_FCOE_FILT); 86*9d26e4fcSRobert Mustacchi fpm_size = i40e_align_l2obj_base(fpm_size); 87*9d26e4fcSRobert Mustacchi 88*9d26e4fcSRobert Mustacchi return fpm_size; 89*9d26e4fcSRobert Mustacchi } 90*9d26e4fcSRobert Mustacchi 91*9d26e4fcSRobert Mustacchi /** 92*9d26e4fcSRobert Mustacchi * i40e_init_lan_hmc - initialize i40e_hmc_info struct 93*9d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 94*9d26e4fcSRobert Mustacchi * @txq_num: number of Tx queues needing backing context 95*9d26e4fcSRobert Mustacchi * @rxq_num: number of Rx queues needing backing context 96*9d26e4fcSRobert Mustacchi * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context 97*9d26e4fcSRobert Mustacchi * @fcoe_filt_num: number of FCoE filters needing backing context 98*9d26e4fcSRobert Mustacchi * 99*9d26e4fcSRobert Mustacchi * This function will be called once per physical function initialization. 100*9d26e4fcSRobert Mustacchi * It will fill out the i40e_hmc_obj_info structure for LAN objects based on 101*9d26e4fcSRobert Mustacchi * the driver's provided input, as well as information from the HMC itself 102*9d26e4fcSRobert Mustacchi * loaded from NVRAM. 103*9d26e4fcSRobert Mustacchi * 104*9d26e4fcSRobert Mustacchi * Assumptions: 105*9d26e4fcSRobert Mustacchi * - HMC Resource Profile has been selected before calling this function. 106*9d26e4fcSRobert Mustacchi **/ 107*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num, 108*9d26e4fcSRobert Mustacchi u32 rxq_num, u32 fcoe_cntx_num, 109*9d26e4fcSRobert Mustacchi u32 fcoe_filt_num) 110*9d26e4fcSRobert Mustacchi { 111*9d26e4fcSRobert Mustacchi struct i40e_hmc_obj_info *obj, *full_obj; 112*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 113*9d26e4fcSRobert Mustacchi u64 l2fpm_size; 114*9d26e4fcSRobert Mustacchi u32 size_exp; 115*9d26e4fcSRobert Mustacchi 116*9d26e4fcSRobert Mustacchi hw->hmc.signature = I40E_HMC_INFO_SIGNATURE; 117*9d26e4fcSRobert Mustacchi hw->hmc.hmc_fn_id = hw->pf_id; 118*9d26e4fcSRobert Mustacchi 119*9d26e4fcSRobert Mustacchi /* allocate memory for hmc_obj */ 120*9d26e4fcSRobert Mustacchi ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem, 121*9d26e4fcSRobert Mustacchi sizeof(struct i40e_hmc_obj_info) * I40E_HMC_LAN_MAX); 122*9d26e4fcSRobert Mustacchi if (ret_code) 123*9d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 124*9d26e4fcSRobert Mustacchi hw->hmc.hmc_obj = (struct i40e_hmc_obj_info *) 125*9d26e4fcSRobert Mustacchi hw->hmc.hmc_obj_virt_mem.va; 126*9d26e4fcSRobert Mustacchi 127*9d26e4fcSRobert Mustacchi /* The full object will be used to create the LAN HMC SD */ 128*9d26e4fcSRobert Mustacchi full_obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_FULL]; 129*9d26e4fcSRobert Mustacchi full_obj->max_cnt = 0; 130*9d26e4fcSRobert Mustacchi full_obj->cnt = 0; 131*9d26e4fcSRobert Mustacchi full_obj->base = 0; 132*9d26e4fcSRobert Mustacchi full_obj->size = 0; 133*9d26e4fcSRobert Mustacchi 134*9d26e4fcSRobert Mustacchi /* Tx queue context information */ 135*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX]; 136*9d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX); 137*9d26e4fcSRobert Mustacchi obj->cnt = txq_num; 138*9d26e4fcSRobert Mustacchi obj->base = 0; 139*9d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_LANTXOBJSZ); 140*9d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 141*9d26e4fcSRobert Mustacchi 142*9d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 143*9d26e4fcSRobert Mustacchi if (txq_num > obj->max_cnt) { 144*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 145*9d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: Tx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 146*9d26e4fcSRobert Mustacchi txq_num, obj->max_cnt, ret_code); 147*9d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 148*9d26e4fcSRobert Mustacchi } 149*9d26e4fcSRobert Mustacchi 150*9d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 151*9d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 152*9d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 153*9d26e4fcSRobert Mustacchi 154*9d26e4fcSRobert Mustacchi /* Rx queue context information */ 155*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX]; 156*9d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX); 157*9d26e4fcSRobert Mustacchi obj->cnt = rxq_num; 158*9d26e4fcSRobert Mustacchi obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_TX].base + 159*9d26e4fcSRobert Mustacchi (hw->hmc.hmc_obj[I40E_HMC_LAN_TX].cnt * 160*9d26e4fcSRobert Mustacchi hw->hmc.hmc_obj[I40E_HMC_LAN_TX].size); 161*9d26e4fcSRobert Mustacchi obj->base = i40e_align_l2obj_base(obj->base); 162*9d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_LANRXOBJSZ); 163*9d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 164*9d26e4fcSRobert Mustacchi 165*9d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 166*9d26e4fcSRobert Mustacchi if (rxq_num > obj->max_cnt) { 167*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 168*9d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: Rx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 169*9d26e4fcSRobert Mustacchi rxq_num, obj->max_cnt, ret_code); 170*9d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 171*9d26e4fcSRobert Mustacchi } 172*9d26e4fcSRobert Mustacchi 173*9d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 174*9d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 175*9d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 176*9d26e4fcSRobert Mustacchi 177*9d26e4fcSRobert Mustacchi /* FCoE context information */ 178*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX]; 179*9d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEMAX); 180*9d26e4fcSRobert Mustacchi obj->cnt = fcoe_cntx_num; 181*9d26e4fcSRobert Mustacchi obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_RX].base + 182*9d26e4fcSRobert Mustacchi (hw->hmc.hmc_obj[I40E_HMC_LAN_RX].cnt * 183*9d26e4fcSRobert Mustacchi hw->hmc.hmc_obj[I40E_HMC_LAN_RX].size); 184*9d26e4fcSRobert Mustacchi obj->base = i40e_align_l2obj_base(obj->base); 185*9d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_FCOEDDPOBJSZ); 186*9d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 187*9d26e4fcSRobert Mustacchi 188*9d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 189*9d26e4fcSRobert Mustacchi if (fcoe_cntx_num > obj->max_cnt) { 190*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 191*9d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: FCoE context: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 192*9d26e4fcSRobert Mustacchi fcoe_cntx_num, obj->max_cnt, ret_code); 193*9d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 194*9d26e4fcSRobert Mustacchi } 195*9d26e4fcSRobert Mustacchi 196*9d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 197*9d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 198*9d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 199*9d26e4fcSRobert Mustacchi 200*9d26e4fcSRobert Mustacchi /* FCoE filter information */ 201*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT]; 202*9d26e4fcSRobert Mustacchi obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEFMAX); 203*9d26e4fcSRobert Mustacchi obj->cnt = fcoe_filt_num; 204*9d26e4fcSRobert Mustacchi obj->base = hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].base + 205*9d26e4fcSRobert Mustacchi (hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].cnt * 206*9d26e4fcSRobert Mustacchi hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].size); 207*9d26e4fcSRobert Mustacchi obj->base = i40e_align_l2obj_base(obj->base); 208*9d26e4fcSRobert Mustacchi size_exp = rd32(hw, I40E_GLHMC_FCOEFOBJSZ); 209*9d26e4fcSRobert Mustacchi obj->size = BIT_ULL(size_exp); 210*9d26e4fcSRobert Mustacchi 211*9d26e4fcSRobert Mustacchi /* validate values requested by driver don't exceed HMC capacity */ 212*9d26e4fcSRobert Mustacchi if (fcoe_filt_num > obj->max_cnt) { 213*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 214*9d26e4fcSRobert Mustacchi DEBUGOUT3("i40e_init_lan_hmc: FCoE filter: asks for 0x%x but max allowed is 0x%x, returns error %d\n", 215*9d26e4fcSRobert Mustacchi fcoe_filt_num, obj->max_cnt, ret_code); 216*9d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 217*9d26e4fcSRobert Mustacchi } 218*9d26e4fcSRobert Mustacchi 219*9d26e4fcSRobert Mustacchi /* aggregate values into the full LAN object for later */ 220*9d26e4fcSRobert Mustacchi full_obj->max_cnt += obj->max_cnt; 221*9d26e4fcSRobert Mustacchi full_obj->cnt += obj->cnt; 222*9d26e4fcSRobert Mustacchi 223*9d26e4fcSRobert Mustacchi hw->hmc.first_sd_index = 0; 224*9d26e4fcSRobert Mustacchi hw->hmc.sd_table.ref_cnt = 0; 225*9d26e4fcSRobert Mustacchi l2fpm_size = i40e_calculate_l2fpm_size(txq_num, rxq_num, fcoe_cntx_num, 226*9d26e4fcSRobert Mustacchi fcoe_filt_num); 227*9d26e4fcSRobert Mustacchi if (NULL == hw->hmc.sd_table.sd_entry) { 228*9d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_cnt = (u32) 229*9d26e4fcSRobert Mustacchi (l2fpm_size + I40E_HMC_DIRECT_BP_SIZE - 1) / 230*9d26e4fcSRobert Mustacchi I40E_HMC_DIRECT_BP_SIZE; 231*9d26e4fcSRobert Mustacchi 232*9d26e4fcSRobert Mustacchi /* allocate the sd_entry members in the sd_table */ 233*9d26e4fcSRobert Mustacchi ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.sd_table.addr, 234*9d26e4fcSRobert Mustacchi (sizeof(struct i40e_hmc_sd_entry) * 235*9d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_cnt)); 236*9d26e4fcSRobert Mustacchi if (ret_code) 237*9d26e4fcSRobert Mustacchi goto init_lan_hmc_out; 238*9d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_entry = 239*9d26e4fcSRobert Mustacchi (struct i40e_hmc_sd_entry *)hw->hmc.sd_table.addr.va; 240*9d26e4fcSRobert Mustacchi } 241*9d26e4fcSRobert Mustacchi /* store in the LAN full object for later */ 242*9d26e4fcSRobert Mustacchi full_obj->size = l2fpm_size; 243*9d26e4fcSRobert Mustacchi 244*9d26e4fcSRobert Mustacchi init_lan_hmc_out: 245*9d26e4fcSRobert Mustacchi return ret_code; 246*9d26e4fcSRobert Mustacchi } 247*9d26e4fcSRobert Mustacchi 248*9d26e4fcSRobert Mustacchi /** 249*9d26e4fcSRobert Mustacchi * i40e_remove_pd_page - Remove a page from the page descriptor table 250*9d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 251*9d26e4fcSRobert Mustacchi * @hmc_info: pointer to the HMC configuration information structure 252*9d26e4fcSRobert Mustacchi * @idx: segment descriptor index to find the relevant page descriptor 253*9d26e4fcSRobert Mustacchi * 254*9d26e4fcSRobert Mustacchi * This function: 255*9d26e4fcSRobert Mustacchi * 1. Marks the entry in pd table (for paged address mode) invalid 256*9d26e4fcSRobert Mustacchi * 2. write to register PMPDINV to invalidate the backing page in FV cache 257*9d26e4fcSRobert Mustacchi * 3. Decrement the ref count for pd_entry 258*9d26e4fcSRobert Mustacchi * assumptions: 259*9d26e4fcSRobert Mustacchi * 1. caller can deallocate the memory used by pd after this function 260*9d26e4fcSRobert Mustacchi * returns. 261*9d26e4fcSRobert Mustacchi **/ 262*9d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_remove_pd_page(struct i40e_hw *hw, 263*9d26e4fcSRobert Mustacchi struct i40e_hmc_info *hmc_info, 264*9d26e4fcSRobert Mustacchi u32 idx) 265*9d26e4fcSRobert Mustacchi { 266*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 267*9d26e4fcSRobert Mustacchi 268*9d26e4fcSRobert Mustacchi if (i40e_prep_remove_pd_page(hmc_info, idx) == I40E_SUCCESS) 269*9d26e4fcSRobert Mustacchi ret_code = i40e_remove_pd_page_new(hw, hmc_info, idx, TRUE); 270*9d26e4fcSRobert Mustacchi 271*9d26e4fcSRobert Mustacchi return ret_code; 272*9d26e4fcSRobert Mustacchi } 273*9d26e4fcSRobert Mustacchi 274*9d26e4fcSRobert Mustacchi /** 275*9d26e4fcSRobert Mustacchi * i40e_remove_sd_bp - remove a backing page from a segment descriptor 276*9d26e4fcSRobert Mustacchi * @hw: pointer to our HW structure 277*9d26e4fcSRobert Mustacchi * @hmc_info: pointer to the HMC configuration information structure 278*9d26e4fcSRobert Mustacchi * @idx: the page index 279*9d26e4fcSRobert Mustacchi * 280*9d26e4fcSRobert Mustacchi * This function: 281*9d26e4fcSRobert Mustacchi * 1. Marks the entry in sd table (for direct address mode) invalid 282*9d26e4fcSRobert Mustacchi * 2. write to register PMSDCMD, PMSDDATALOW(PMSDDATALOW.PMSDVALID set 283*9d26e4fcSRobert Mustacchi * to 0) and PMSDDATAHIGH to invalidate the sd page 284*9d26e4fcSRobert Mustacchi * 3. Decrement the ref count for the sd_entry 285*9d26e4fcSRobert Mustacchi * assumptions: 286*9d26e4fcSRobert Mustacchi * 1. caller can deallocate the memory used by backing storage after this 287*9d26e4fcSRobert Mustacchi * function returns. 288*9d26e4fcSRobert Mustacchi **/ 289*9d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_remove_sd_bp(struct i40e_hw *hw, 290*9d26e4fcSRobert Mustacchi struct i40e_hmc_info *hmc_info, 291*9d26e4fcSRobert Mustacchi u32 idx) 292*9d26e4fcSRobert Mustacchi { 293*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 294*9d26e4fcSRobert Mustacchi 295*9d26e4fcSRobert Mustacchi if (i40e_prep_remove_sd_bp(hmc_info, idx) == I40E_SUCCESS) 296*9d26e4fcSRobert Mustacchi ret_code = i40e_remove_sd_bp_new(hw, hmc_info, idx, TRUE); 297*9d26e4fcSRobert Mustacchi 298*9d26e4fcSRobert Mustacchi return ret_code; 299*9d26e4fcSRobert Mustacchi } 300*9d26e4fcSRobert Mustacchi 301*9d26e4fcSRobert Mustacchi /** 302*9d26e4fcSRobert Mustacchi * i40e_create_lan_hmc_object - allocate backing store for hmc objects 303*9d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 304*9d26e4fcSRobert Mustacchi * @info: pointer to i40e_hmc_create_obj_info struct 305*9d26e4fcSRobert Mustacchi * 306*9d26e4fcSRobert Mustacchi * This will allocate memory for PDs and backing pages and populate 307*9d26e4fcSRobert Mustacchi * the sd and pd entries. 308*9d26e4fcSRobert Mustacchi **/ 309*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_create_lan_hmc_object(struct i40e_hw *hw, 310*9d26e4fcSRobert Mustacchi struct i40e_hmc_lan_create_obj_info *info) 311*9d26e4fcSRobert Mustacchi { 312*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 313*9d26e4fcSRobert Mustacchi struct i40e_hmc_sd_entry *sd_entry; 314*9d26e4fcSRobert Mustacchi u32 pd_idx1 = 0, pd_lmt1 = 0; 315*9d26e4fcSRobert Mustacchi u32 pd_idx = 0, pd_lmt = 0; 316*9d26e4fcSRobert Mustacchi bool pd_error = FALSE; 317*9d26e4fcSRobert Mustacchi u32 sd_idx, sd_lmt; 318*9d26e4fcSRobert Mustacchi u64 sd_size; 319*9d26e4fcSRobert Mustacchi u32 i, j; 320*9d26e4fcSRobert Mustacchi 321*9d26e4fcSRobert Mustacchi if (NULL == info) { 322*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 323*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_create_lan_hmc_object: bad info ptr\n"); 324*9d26e4fcSRobert Mustacchi goto exit; 325*9d26e4fcSRobert Mustacchi } 326*9d26e4fcSRobert Mustacchi if (NULL == info->hmc_info) { 327*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 328*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_create_lan_hmc_object: bad hmc_info ptr\n"); 329*9d26e4fcSRobert Mustacchi goto exit; 330*9d26e4fcSRobert Mustacchi } 331*9d26e4fcSRobert Mustacchi if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { 332*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 333*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_create_lan_hmc_object: bad signature\n"); 334*9d26e4fcSRobert Mustacchi goto exit; 335*9d26e4fcSRobert Mustacchi } 336*9d26e4fcSRobert Mustacchi 337*9d26e4fcSRobert Mustacchi if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 338*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; 339*9d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n", 340*9d26e4fcSRobert Mustacchi ret_code); 341*9d26e4fcSRobert Mustacchi goto exit; 342*9d26e4fcSRobert Mustacchi } 343*9d26e4fcSRobert Mustacchi if ((info->start_idx + info->count) > 344*9d26e4fcSRobert Mustacchi info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 345*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 346*9d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n", 347*9d26e4fcSRobert Mustacchi ret_code); 348*9d26e4fcSRobert Mustacchi goto exit; 349*9d26e4fcSRobert Mustacchi } 350*9d26e4fcSRobert Mustacchi 351*9d26e4fcSRobert Mustacchi /* find sd index and limit */ 352*9d26e4fcSRobert Mustacchi I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 353*9d26e4fcSRobert Mustacchi info->start_idx, info->count, 354*9d26e4fcSRobert Mustacchi &sd_idx, &sd_lmt); 355*9d26e4fcSRobert Mustacchi if (sd_idx >= info->hmc_info->sd_table.sd_cnt || 356*9d26e4fcSRobert Mustacchi sd_lmt > info->hmc_info->sd_table.sd_cnt) { 357*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_INDEX; 358*9d26e4fcSRobert Mustacchi goto exit; 359*9d26e4fcSRobert Mustacchi } 360*9d26e4fcSRobert Mustacchi /* find pd index */ 361*9d26e4fcSRobert Mustacchi I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 362*9d26e4fcSRobert Mustacchi info->start_idx, info->count, &pd_idx, 363*9d26e4fcSRobert Mustacchi &pd_lmt); 364*9d26e4fcSRobert Mustacchi 365*9d26e4fcSRobert Mustacchi /* This is to cover for cases where you may not want to have an SD with 366*9d26e4fcSRobert Mustacchi * the full 2M memory but something smaller. By not filling out any 367*9d26e4fcSRobert Mustacchi * size, the function will default the SD size to be 2M. 368*9d26e4fcSRobert Mustacchi */ 369*9d26e4fcSRobert Mustacchi if (info->direct_mode_sz == 0) 370*9d26e4fcSRobert Mustacchi sd_size = I40E_HMC_DIRECT_BP_SIZE; 371*9d26e4fcSRobert Mustacchi else 372*9d26e4fcSRobert Mustacchi sd_size = info->direct_mode_sz; 373*9d26e4fcSRobert Mustacchi 374*9d26e4fcSRobert Mustacchi /* check if all the sds are valid. If not, allocate a page and 375*9d26e4fcSRobert Mustacchi * initialize it. 376*9d26e4fcSRobert Mustacchi */ 377*9d26e4fcSRobert Mustacchi for (j = sd_idx; j < sd_lmt; j++) { 378*9d26e4fcSRobert Mustacchi /* update the sd table entry */ 379*9d26e4fcSRobert Mustacchi ret_code = i40e_add_sd_table_entry(hw, info->hmc_info, j, 380*9d26e4fcSRobert Mustacchi info->entry_type, 381*9d26e4fcSRobert Mustacchi sd_size); 382*9d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 383*9d26e4fcSRobert Mustacchi goto exit_sd_error; 384*9d26e4fcSRobert Mustacchi sd_entry = &info->hmc_info->sd_table.sd_entry[j]; 385*9d26e4fcSRobert Mustacchi if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) { 386*9d26e4fcSRobert Mustacchi /* check if all the pds in this sd are valid. If not, 387*9d26e4fcSRobert Mustacchi * allocate a page and initialize it. 388*9d26e4fcSRobert Mustacchi */ 389*9d26e4fcSRobert Mustacchi 390*9d26e4fcSRobert Mustacchi /* find pd_idx and pd_lmt in this sd */ 391*9d26e4fcSRobert Mustacchi pd_idx1 = max(pd_idx, (j * I40E_HMC_MAX_BP_COUNT)); 392*9d26e4fcSRobert Mustacchi pd_lmt1 = min(pd_lmt, 393*9d26e4fcSRobert Mustacchi ((j + 1) * I40E_HMC_MAX_BP_COUNT)); 394*9d26e4fcSRobert Mustacchi for (i = pd_idx1; i < pd_lmt1; i++) { 395*9d26e4fcSRobert Mustacchi /* update the pd table entry */ 396*9d26e4fcSRobert Mustacchi ret_code = i40e_add_pd_table_entry(hw, 397*9d26e4fcSRobert Mustacchi info->hmc_info, 398*9d26e4fcSRobert Mustacchi i, NULL); 399*9d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) { 400*9d26e4fcSRobert Mustacchi pd_error = TRUE; 401*9d26e4fcSRobert Mustacchi break; 402*9d26e4fcSRobert Mustacchi } 403*9d26e4fcSRobert Mustacchi } 404*9d26e4fcSRobert Mustacchi if (pd_error) { 405*9d26e4fcSRobert Mustacchi /* remove the backing pages from pd_idx1 to i */ 406*9d26e4fcSRobert Mustacchi while (i && (i > pd_idx1)) { 407*9d26e4fcSRobert Mustacchi i40e_remove_pd_bp(hw, info->hmc_info, 408*9d26e4fcSRobert Mustacchi (i - 1)); 409*9d26e4fcSRobert Mustacchi i--; 410*9d26e4fcSRobert Mustacchi } 411*9d26e4fcSRobert Mustacchi } 412*9d26e4fcSRobert Mustacchi } 413*9d26e4fcSRobert Mustacchi if (!sd_entry->valid) { 414*9d26e4fcSRobert Mustacchi sd_entry->valid = TRUE; 415*9d26e4fcSRobert Mustacchi switch (sd_entry->entry_type) { 416*9d26e4fcSRobert Mustacchi case I40E_SD_TYPE_PAGED: 417*9d26e4fcSRobert Mustacchi I40E_SET_PF_SD_ENTRY(hw, 418*9d26e4fcSRobert Mustacchi sd_entry->u.pd_table.pd_page_addr.pa, 419*9d26e4fcSRobert Mustacchi j, sd_entry->entry_type); 420*9d26e4fcSRobert Mustacchi break; 421*9d26e4fcSRobert Mustacchi case I40E_SD_TYPE_DIRECT: 422*9d26e4fcSRobert Mustacchi I40E_SET_PF_SD_ENTRY(hw, sd_entry->u.bp.addr.pa, 423*9d26e4fcSRobert Mustacchi j, sd_entry->entry_type); 424*9d26e4fcSRobert Mustacchi break; 425*9d26e4fcSRobert Mustacchi default: 426*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_TYPE; 427*9d26e4fcSRobert Mustacchi goto exit; 428*9d26e4fcSRobert Mustacchi } 429*9d26e4fcSRobert Mustacchi } 430*9d26e4fcSRobert Mustacchi } 431*9d26e4fcSRobert Mustacchi goto exit; 432*9d26e4fcSRobert Mustacchi 433*9d26e4fcSRobert Mustacchi exit_sd_error: 434*9d26e4fcSRobert Mustacchi /* cleanup for sd entries from j to sd_idx */ 435*9d26e4fcSRobert Mustacchi while (j && (j > sd_idx)) { 436*9d26e4fcSRobert Mustacchi sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1]; 437*9d26e4fcSRobert Mustacchi switch (sd_entry->entry_type) { 438*9d26e4fcSRobert Mustacchi case I40E_SD_TYPE_PAGED: 439*9d26e4fcSRobert Mustacchi pd_idx1 = max(pd_idx, 440*9d26e4fcSRobert Mustacchi ((j - 1) * I40E_HMC_MAX_BP_COUNT)); 441*9d26e4fcSRobert Mustacchi pd_lmt1 = min(pd_lmt, (j * I40E_HMC_MAX_BP_COUNT)); 442*9d26e4fcSRobert Mustacchi for (i = pd_idx1; i < pd_lmt1; i++) 443*9d26e4fcSRobert Mustacchi i40e_remove_pd_bp(hw, info->hmc_info, i); 444*9d26e4fcSRobert Mustacchi i40e_remove_pd_page(hw, info->hmc_info, (j - 1)); 445*9d26e4fcSRobert Mustacchi break; 446*9d26e4fcSRobert Mustacchi case I40E_SD_TYPE_DIRECT: 447*9d26e4fcSRobert Mustacchi i40e_remove_sd_bp(hw, info->hmc_info, (j - 1)); 448*9d26e4fcSRobert Mustacchi break; 449*9d26e4fcSRobert Mustacchi default: 450*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_TYPE; 451*9d26e4fcSRobert Mustacchi break; 452*9d26e4fcSRobert Mustacchi } 453*9d26e4fcSRobert Mustacchi j--; 454*9d26e4fcSRobert Mustacchi } 455*9d26e4fcSRobert Mustacchi exit: 456*9d26e4fcSRobert Mustacchi return ret_code; 457*9d26e4fcSRobert Mustacchi } 458*9d26e4fcSRobert Mustacchi 459*9d26e4fcSRobert Mustacchi /** 460*9d26e4fcSRobert Mustacchi * i40e_configure_lan_hmc - prepare the HMC backing store 461*9d26e4fcSRobert Mustacchi * @hw: pointer to the hw structure 462*9d26e4fcSRobert Mustacchi * @model: the model for the layout of the SD/PD tables 463*9d26e4fcSRobert Mustacchi * 464*9d26e4fcSRobert Mustacchi * - This function will be called once per physical function initialization. 465*9d26e4fcSRobert Mustacchi * - This function will be called after i40e_init_lan_hmc() and before 466*9d26e4fcSRobert Mustacchi * any LAN/FCoE HMC objects can be created. 467*9d26e4fcSRobert Mustacchi **/ 468*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_configure_lan_hmc(struct i40e_hw *hw, 469*9d26e4fcSRobert Mustacchi enum i40e_hmc_model model) 470*9d26e4fcSRobert Mustacchi { 471*9d26e4fcSRobert Mustacchi struct i40e_hmc_lan_create_obj_info info; 472*9d26e4fcSRobert Mustacchi u8 hmc_fn_id = hw->hmc.hmc_fn_id; 473*9d26e4fcSRobert Mustacchi struct i40e_hmc_obj_info *obj; 474*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 475*9d26e4fcSRobert Mustacchi 476*9d26e4fcSRobert Mustacchi /* Initialize part of the create object info struct */ 477*9d26e4fcSRobert Mustacchi info.hmc_info = &hw->hmc; 478*9d26e4fcSRobert Mustacchi info.rsrc_type = I40E_HMC_LAN_FULL; 479*9d26e4fcSRobert Mustacchi info.start_idx = 0; 480*9d26e4fcSRobert Mustacchi info.direct_mode_sz = hw->hmc.hmc_obj[I40E_HMC_LAN_FULL].size; 481*9d26e4fcSRobert Mustacchi 482*9d26e4fcSRobert Mustacchi /* Build the SD entry for the LAN objects */ 483*9d26e4fcSRobert Mustacchi switch (model) { 484*9d26e4fcSRobert Mustacchi case I40E_HMC_MODEL_DIRECT_PREFERRED: 485*9d26e4fcSRobert Mustacchi case I40E_HMC_MODEL_DIRECT_ONLY: 486*9d26e4fcSRobert Mustacchi info.entry_type = I40E_SD_TYPE_DIRECT; 487*9d26e4fcSRobert Mustacchi /* Make one big object, a single SD */ 488*9d26e4fcSRobert Mustacchi info.count = 1; 489*9d26e4fcSRobert Mustacchi ret_code = i40e_create_lan_hmc_object(hw, &info); 490*9d26e4fcSRobert Mustacchi if ((ret_code != I40E_SUCCESS) && (model == I40E_HMC_MODEL_DIRECT_PREFERRED)) 491*9d26e4fcSRobert Mustacchi goto try_type_paged; 492*9d26e4fcSRobert Mustacchi else if (ret_code != I40E_SUCCESS) 493*9d26e4fcSRobert Mustacchi goto configure_lan_hmc_out; 494*9d26e4fcSRobert Mustacchi /* else clause falls through the break */ 495*9d26e4fcSRobert Mustacchi break; 496*9d26e4fcSRobert Mustacchi case I40E_HMC_MODEL_PAGED_ONLY: 497*9d26e4fcSRobert Mustacchi try_type_paged: 498*9d26e4fcSRobert Mustacchi info.entry_type = I40E_SD_TYPE_PAGED; 499*9d26e4fcSRobert Mustacchi /* Make one big object in the PD table */ 500*9d26e4fcSRobert Mustacchi info.count = 1; 501*9d26e4fcSRobert Mustacchi ret_code = i40e_create_lan_hmc_object(hw, &info); 502*9d26e4fcSRobert Mustacchi if (ret_code != I40E_SUCCESS) 503*9d26e4fcSRobert Mustacchi goto configure_lan_hmc_out; 504*9d26e4fcSRobert Mustacchi break; 505*9d26e4fcSRobert Mustacchi default: 506*9d26e4fcSRobert Mustacchi /* unsupported type */ 507*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_TYPE; 508*9d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_configure_lan_hmc: Unknown SD type: %d\n", 509*9d26e4fcSRobert Mustacchi ret_code); 510*9d26e4fcSRobert Mustacchi goto configure_lan_hmc_out; 511*9d26e4fcSRobert Mustacchi } 512*9d26e4fcSRobert Mustacchi 513*9d26e4fcSRobert Mustacchi /* Configure and program the FPM registers so objects can be created */ 514*9d26e4fcSRobert Mustacchi 515*9d26e4fcSRobert Mustacchi /* Tx contexts */ 516*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX]; 517*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANTXBASE(hmc_fn_id), 518*9d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK) / 512)); 519*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANTXCNT(hmc_fn_id), obj->cnt); 520*9d26e4fcSRobert Mustacchi 521*9d26e4fcSRobert Mustacchi /* Rx contexts */ 522*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX]; 523*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANRXBASE(hmc_fn_id), 524*9d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK) / 512)); 525*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_LANRXCNT(hmc_fn_id), obj->cnt); 526*9d26e4fcSRobert Mustacchi 527*9d26e4fcSRobert Mustacchi /* FCoE contexts */ 528*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX]; 529*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEDDPBASE(hmc_fn_id), 530*9d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK) / 512)); 531*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEDDPCNT(hmc_fn_id), obj->cnt); 532*9d26e4fcSRobert Mustacchi 533*9d26e4fcSRobert Mustacchi /* FCoE filters */ 534*9d26e4fcSRobert Mustacchi obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT]; 535*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEFBASE(hmc_fn_id), 536*9d26e4fcSRobert Mustacchi (u32)((obj->base & I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK) / 512)); 537*9d26e4fcSRobert Mustacchi wr32(hw, I40E_GLHMC_FCOEFCNT(hmc_fn_id), obj->cnt); 538*9d26e4fcSRobert Mustacchi 539*9d26e4fcSRobert Mustacchi configure_lan_hmc_out: 540*9d26e4fcSRobert Mustacchi return ret_code; 541*9d26e4fcSRobert Mustacchi } 542*9d26e4fcSRobert Mustacchi 543*9d26e4fcSRobert Mustacchi /** 544*9d26e4fcSRobert Mustacchi * i40e_delete_hmc_object - remove hmc objects 545*9d26e4fcSRobert Mustacchi * @hw: pointer to the HW structure 546*9d26e4fcSRobert Mustacchi * @info: pointer to i40e_hmc_delete_obj_info struct 547*9d26e4fcSRobert Mustacchi * 548*9d26e4fcSRobert Mustacchi * This will de-populate the SDs and PDs. It frees 549*9d26e4fcSRobert Mustacchi * the memory for PDS and backing storage. After this function is returned, 550*9d26e4fcSRobert Mustacchi * caller should deallocate memory allocated previously for 551*9d26e4fcSRobert Mustacchi * book-keeping information about PDs and backing storage. 552*9d26e4fcSRobert Mustacchi **/ 553*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_delete_lan_hmc_object(struct i40e_hw *hw, 554*9d26e4fcSRobert Mustacchi struct i40e_hmc_lan_delete_obj_info *info) 555*9d26e4fcSRobert Mustacchi { 556*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 557*9d26e4fcSRobert Mustacchi struct i40e_hmc_pd_table *pd_table; 558*9d26e4fcSRobert Mustacchi u32 pd_idx, pd_lmt, rel_pd_idx; 559*9d26e4fcSRobert Mustacchi u32 sd_idx, sd_lmt; 560*9d26e4fcSRobert Mustacchi u32 i, j; 561*9d26e4fcSRobert Mustacchi 562*9d26e4fcSRobert Mustacchi if (NULL == info) { 563*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 564*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad info ptr\n"); 565*9d26e4fcSRobert Mustacchi goto exit; 566*9d26e4fcSRobert Mustacchi } 567*9d26e4fcSRobert Mustacchi if (NULL == info->hmc_info) { 568*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 569*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad info->hmc_info ptr\n"); 570*9d26e4fcSRobert Mustacchi goto exit; 571*9d26e4fcSRobert Mustacchi } 572*9d26e4fcSRobert Mustacchi if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) { 573*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 574*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->signature\n"); 575*9d26e4fcSRobert Mustacchi goto exit; 576*9d26e4fcSRobert Mustacchi } 577*9d26e4fcSRobert Mustacchi 578*9d26e4fcSRobert Mustacchi if (NULL == info->hmc_info->sd_table.sd_entry) { 579*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 580*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad sd_entry\n"); 581*9d26e4fcSRobert Mustacchi goto exit; 582*9d26e4fcSRobert Mustacchi } 583*9d26e4fcSRobert Mustacchi 584*9d26e4fcSRobert Mustacchi if (NULL == info->hmc_info->hmc_obj) { 585*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 586*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->hmc_obj\n"); 587*9d26e4fcSRobert Mustacchi goto exit; 588*9d26e4fcSRobert Mustacchi } 589*9d26e4fcSRobert Mustacchi if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 590*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; 591*9d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n", 592*9d26e4fcSRobert Mustacchi ret_code); 593*9d26e4fcSRobert Mustacchi goto exit; 594*9d26e4fcSRobert Mustacchi } 595*9d26e4fcSRobert Mustacchi 596*9d26e4fcSRobert Mustacchi if ((info->start_idx + info->count) > 597*9d26e4fcSRobert Mustacchi info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 598*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT; 599*9d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n", 600*9d26e4fcSRobert Mustacchi ret_code); 601*9d26e4fcSRobert Mustacchi goto exit; 602*9d26e4fcSRobert Mustacchi } 603*9d26e4fcSRobert Mustacchi 604*9d26e4fcSRobert Mustacchi I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 605*9d26e4fcSRobert Mustacchi info->start_idx, info->count, &pd_idx, 606*9d26e4fcSRobert Mustacchi &pd_lmt); 607*9d26e4fcSRobert Mustacchi 608*9d26e4fcSRobert Mustacchi for (j = pd_idx; j < pd_lmt; j++) { 609*9d26e4fcSRobert Mustacchi sd_idx = j / I40E_HMC_PD_CNT_IN_SD; 610*9d26e4fcSRobert Mustacchi 611*9d26e4fcSRobert Mustacchi if (I40E_SD_TYPE_PAGED != 612*9d26e4fcSRobert Mustacchi info->hmc_info->sd_table.sd_entry[sd_idx].entry_type) 613*9d26e4fcSRobert Mustacchi continue; 614*9d26e4fcSRobert Mustacchi 615*9d26e4fcSRobert Mustacchi rel_pd_idx = j % I40E_HMC_PD_CNT_IN_SD; 616*9d26e4fcSRobert Mustacchi 617*9d26e4fcSRobert Mustacchi pd_table = 618*9d26e4fcSRobert Mustacchi &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; 619*9d26e4fcSRobert Mustacchi if (pd_table->pd_entry[rel_pd_idx].valid) { 620*9d26e4fcSRobert Mustacchi ret_code = i40e_remove_pd_bp(hw, info->hmc_info, j); 621*9d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 622*9d26e4fcSRobert Mustacchi goto exit; 623*9d26e4fcSRobert Mustacchi } 624*9d26e4fcSRobert Mustacchi } 625*9d26e4fcSRobert Mustacchi 626*9d26e4fcSRobert Mustacchi /* find sd index and limit */ 627*9d26e4fcSRobert Mustacchi I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type, 628*9d26e4fcSRobert Mustacchi info->start_idx, info->count, 629*9d26e4fcSRobert Mustacchi &sd_idx, &sd_lmt); 630*9d26e4fcSRobert Mustacchi if (sd_idx >= info->hmc_info->sd_table.sd_cnt || 631*9d26e4fcSRobert Mustacchi sd_lmt > info->hmc_info->sd_table.sd_cnt) { 632*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_SD_INDEX; 633*9d26e4fcSRobert Mustacchi goto exit; 634*9d26e4fcSRobert Mustacchi } 635*9d26e4fcSRobert Mustacchi 636*9d26e4fcSRobert Mustacchi for (i = sd_idx; i < sd_lmt; i++) { 637*9d26e4fcSRobert Mustacchi if (!info->hmc_info->sd_table.sd_entry[i].valid) 638*9d26e4fcSRobert Mustacchi continue; 639*9d26e4fcSRobert Mustacchi switch (info->hmc_info->sd_table.sd_entry[i].entry_type) { 640*9d26e4fcSRobert Mustacchi case I40E_SD_TYPE_DIRECT: 641*9d26e4fcSRobert Mustacchi ret_code = i40e_remove_sd_bp(hw, info->hmc_info, i); 642*9d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 643*9d26e4fcSRobert Mustacchi goto exit; 644*9d26e4fcSRobert Mustacchi break; 645*9d26e4fcSRobert Mustacchi case I40E_SD_TYPE_PAGED: 646*9d26e4fcSRobert Mustacchi ret_code = i40e_remove_pd_page(hw, info->hmc_info, i); 647*9d26e4fcSRobert Mustacchi if (I40E_SUCCESS != ret_code) 648*9d26e4fcSRobert Mustacchi goto exit; 649*9d26e4fcSRobert Mustacchi break; 650*9d26e4fcSRobert Mustacchi default: 651*9d26e4fcSRobert Mustacchi break; 652*9d26e4fcSRobert Mustacchi } 653*9d26e4fcSRobert Mustacchi } 654*9d26e4fcSRobert Mustacchi exit: 655*9d26e4fcSRobert Mustacchi return ret_code; 656*9d26e4fcSRobert Mustacchi } 657*9d26e4fcSRobert Mustacchi 658*9d26e4fcSRobert Mustacchi /** 659*9d26e4fcSRobert Mustacchi * i40e_shutdown_lan_hmc - Remove HMC backing store, free allocated memory 660*9d26e4fcSRobert Mustacchi * @hw: pointer to the hw structure 661*9d26e4fcSRobert Mustacchi * 662*9d26e4fcSRobert Mustacchi * This must be called by drivers as they are shutting down and being 663*9d26e4fcSRobert Mustacchi * removed from the OS. 664*9d26e4fcSRobert Mustacchi **/ 665*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_shutdown_lan_hmc(struct i40e_hw *hw) 666*9d26e4fcSRobert Mustacchi { 667*9d26e4fcSRobert Mustacchi struct i40e_hmc_lan_delete_obj_info info; 668*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code; 669*9d26e4fcSRobert Mustacchi 670*9d26e4fcSRobert Mustacchi info.hmc_info = &hw->hmc; 671*9d26e4fcSRobert Mustacchi info.rsrc_type = I40E_HMC_LAN_FULL; 672*9d26e4fcSRobert Mustacchi info.start_idx = 0; 673*9d26e4fcSRobert Mustacchi info.count = 1; 674*9d26e4fcSRobert Mustacchi 675*9d26e4fcSRobert Mustacchi /* delete the object */ 676*9d26e4fcSRobert Mustacchi ret_code = i40e_delete_lan_hmc_object(hw, &info); 677*9d26e4fcSRobert Mustacchi 678*9d26e4fcSRobert Mustacchi /* free the SD table entry for LAN */ 679*9d26e4fcSRobert Mustacchi i40e_free_virt_mem(hw, &hw->hmc.sd_table.addr); 680*9d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_cnt = 0; 681*9d26e4fcSRobert Mustacchi hw->hmc.sd_table.sd_entry = NULL; 682*9d26e4fcSRobert Mustacchi 683*9d26e4fcSRobert Mustacchi /* free memory used for hmc_obj */ 684*9d26e4fcSRobert Mustacchi i40e_free_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem); 685*9d26e4fcSRobert Mustacchi hw->hmc.hmc_obj = NULL; 686*9d26e4fcSRobert Mustacchi 687*9d26e4fcSRobert Mustacchi return ret_code; 688*9d26e4fcSRobert Mustacchi } 689*9d26e4fcSRobert Mustacchi 690*9d26e4fcSRobert Mustacchi #define I40E_HMC_STORE(_struct, _ele) \ 691*9d26e4fcSRobert Mustacchi offsetof(struct _struct, _ele), \ 692*9d26e4fcSRobert Mustacchi FIELD_SIZEOF(struct _struct, _ele) 693*9d26e4fcSRobert Mustacchi 694*9d26e4fcSRobert Mustacchi struct i40e_context_ele { 695*9d26e4fcSRobert Mustacchi u16 offset; 696*9d26e4fcSRobert Mustacchi u16 size_of; 697*9d26e4fcSRobert Mustacchi u16 width; 698*9d26e4fcSRobert Mustacchi u16 lsb; 699*9d26e4fcSRobert Mustacchi }; 700*9d26e4fcSRobert Mustacchi 701*9d26e4fcSRobert Mustacchi /* LAN Tx Queue Context */ 702*9d26e4fcSRobert Mustacchi static struct i40e_context_ele i40e_hmc_txq_ce_info[] = { 703*9d26e4fcSRobert Mustacchi /* Field Width LSB */ 704*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, head), 13, 0 }, 705*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, new_context), 1, 30 }, 706*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, base), 57, 32 }, 707*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, fc_ena), 1, 89 }, 708*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, timesync_ena), 1, 90 }, 709*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, fd_ena), 1, 91 }, 710*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, alt_vlan_ena), 1, 92 }, 711*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, cpuid), 8, 96 }, 712*9d26e4fcSRobert Mustacchi /* line 1 */ 713*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, thead_wb), 13, 0 + 128 }, 714*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_ena), 1, 32 + 128 }, 715*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, qlen), 13, 33 + 128 }, 716*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrdesc_ena), 1, 46 + 128 }, 717*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, tphrpacket_ena), 1, 47 + 128 }, 718*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, tphwdesc_ena), 1, 48 + 128 }, 719*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_addr), 64, 64 + 128 }, 720*9d26e4fcSRobert Mustacchi /* line 7 */ 721*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, crc), 32, 0 + (7 * 128) }, 722*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist), 10, 84 + (7 * 128) }, 723*9d26e4fcSRobert Mustacchi {I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist_act), 1, 94 + (7 * 128) }, 724*9d26e4fcSRobert Mustacchi { 0 } 725*9d26e4fcSRobert Mustacchi }; 726*9d26e4fcSRobert Mustacchi 727*9d26e4fcSRobert Mustacchi /* LAN Rx Queue Context */ 728*9d26e4fcSRobert Mustacchi static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = { 729*9d26e4fcSRobert Mustacchi /* Field Width LSB */ 730*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, head), 13, 0 }, 731*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, cpuid), 8, 13 }, 732*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, base), 57, 32 }, 733*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, qlen), 13, 89 }, 734*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, dbuff), 7, 102 }, 735*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, hbuff), 5, 109 }, 736*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, dtype), 2, 114 }, 737*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, dsize), 1, 116 }, 738*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, crcstrip), 1, 117 }, 739*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, fc_ena), 1, 118 }, 740*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, l2tsel), 1, 119 }, 741*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_0), 4, 120 }, 742*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_1), 2, 124 }, 743*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, showiv), 1, 127 }, 744*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, rxmax), 14, 174 }, 745*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphrdesc_ena), 1, 193 }, 746*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphwdesc_ena), 1, 194 }, 747*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphdata_ena), 1, 195 }, 748*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, tphhead_ena), 1, 196 }, 749*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, lrxqthresh), 3, 198 }, 750*9d26e4fcSRobert Mustacchi { I40E_HMC_STORE(i40e_hmc_obj_rxq, prefena), 1, 201 }, 751*9d26e4fcSRobert Mustacchi { 0 } 752*9d26e4fcSRobert Mustacchi }; 753*9d26e4fcSRobert Mustacchi 754*9d26e4fcSRobert Mustacchi /** 755*9d26e4fcSRobert Mustacchi * i40e_write_byte - replace HMC context byte 756*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 757*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 758*9d26e4fcSRobert Mustacchi * @src: the struct to be read from 759*9d26e4fcSRobert Mustacchi **/ 760*9d26e4fcSRobert Mustacchi static void i40e_write_byte(u8 *hmc_bits, 761*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 762*9d26e4fcSRobert Mustacchi u8 *src) 763*9d26e4fcSRobert Mustacchi { 764*9d26e4fcSRobert Mustacchi u8 src_byte, dest_byte, mask; 765*9d26e4fcSRobert Mustacchi u8 *from, *dest; 766*9d26e4fcSRobert Mustacchi u16 shift_width; 767*9d26e4fcSRobert Mustacchi 768*9d26e4fcSRobert Mustacchi /* copy from the next struct field */ 769*9d26e4fcSRobert Mustacchi from = src + ce_info->offset; 770*9d26e4fcSRobert Mustacchi 771*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 772*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 773*9d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 774*9d26e4fcSRobert Mustacchi 775*9d26e4fcSRobert Mustacchi src_byte = *from; 776*9d26e4fcSRobert Mustacchi src_byte &= mask; 777*9d26e4fcSRobert Mustacchi 778*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 779*9d26e4fcSRobert Mustacchi mask <<= shift_width; 780*9d26e4fcSRobert Mustacchi src_byte <<= shift_width; 781*9d26e4fcSRobert Mustacchi 782*9d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 783*9d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 784*9d26e4fcSRobert Mustacchi 785*9d26e4fcSRobert Mustacchi i40e_memcpy(&dest_byte, dest, sizeof(dest_byte), I40E_DMA_TO_NONDMA); 786*9d26e4fcSRobert Mustacchi 787*9d26e4fcSRobert Mustacchi dest_byte &= ~mask; /* get the bits not changing */ 788*9d26e4fcSRobert Mustacchi dest_byte |= src_byte; /* add in the new bits */ 789*9d26e4fcSRobert Mustacchi 790*9d26e4fcSRobert Mustacchi /* put it all back */ 791*9d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA); 792*9d26e4fcSRobert Mustacchi } 793*9d26e4fcSRobert Mustacchi 794*9d26e4fcSRobert Mustacchi /** 795*9d26e4fcSRobert Mustacchi * i40e_write_word - replace HMC context word 796*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 797*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 798*9d26e4fcSRobert Mustacchi * @src: the struct to be read from 799*9d26e4fcSRobert Mustacchi **/ 800*9d26e4fcSRobert Mustacchi static void i40e_write_word(u8 *hmc_bits, 801*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 802*9d26e4fcSRobert Mustacchi u8 *src) 803*9d26e4fcSRobert Mustacchi { 804*9d26e4fcSRobert Mustacchi u16 src_word, mask; 805*9d26e4fcSRobert Mustacchi u8 *from, *dest; 806*9d26e4fcSRobert Mustacchi u16 shift_width; 807*9d26e4fcSRobert Mustacchi __le16 dest_word; 808*9d26e4fcSRobert Mustacchi 809*9d26e4fcSRobert Mustacchi /* copy from the next struct field */ 810*9d26e4fcSRobert Mustacchi from = src + ce_info->offset; 811*9d26e4fcSRobert Mustacchi 812*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 813*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 814*9d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 815*9d26e4fcSRobert Mustacchi 816*9d26e4fcSRobert Mustacchi /* don't swizzle the bits until after the mask because the mask bits 817*9d26e4fcSRobert Mustacchi * will be in a different bit position on big endian machines 818*9d26e4fcSRobert Mustacchi */ 819*9d26e4fcSRobert Mustacchi src_word = *(u16 *)from; 820*9d26e4fcSRobert Mustacchi src_word &= mask; 821*9d26e4fcSRobert Mustacchi 822*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 823*9d26e4fcSRobert Mustacchi mask <<= shift_width; 824*9d26e4fcSRobert Mustacchi src_word <<= shift_width; 825*9d26e4fcSRobert Mustacchi 826*9d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 827*9d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 828*9d26e4fcSRobert Mustacchi 829*9d26e4fcSRobert Mustacchi i40e_memcpy(&dest_word, dest, sizeof(dest_word), I40E_DMA_TO_NONDMA); 830*9d26e4fcSRobert Mustacchi 831*9d26e4fcSRobert Mustacchi dest_word &= ~(CPU_TO_LE16(mask)); /* get the bits not changing */ 832*9d26e4fcSRobert Mustacchi dest_word |= CPU_TO_LE16(src_word); /* add in the new bits */ 833*9d26e4fcSRobert Mustacchi 834*9d26e4fcSRobert Mustacchi /* put it all back */ 835*9d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA); 836*9d26e4fcSRobert Mustacchi } 837*9d26e4fcSRobert Mustacchi 838*9d26e4fcSRobert Mustacchi /** 839*9d26e4fcSRobert Mustacchi * i40e_write_dword - replace HMC context dword 840*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 841*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 842*9d26e4fcSRobert Mustacchi * @src: the struct to be read from 843*9d26e4fcSRobert Mustacchi **/ 844*9d26e4fcSRobert Mustacchi static void i40e_write_dword(u8 *hmc_bits, 845*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 846*9d26e4fcSRobert Mustacchi u8 *src) 847*9d26e4fcSRobert Mustacchi { 848*9d26e4fcSRobert Mustacchi u32 src_dword, mask; 849*9d26e4fcSRobert Mustacchi u8 *from, *dest; 850*9d26e4fcSRobert Mustacchi u16 shift_width; 851*9d26e4fcSRobert Mustacchi __le32 dest_dword; 852*9d26e4fcSRobert Mustacchi 853*9d26e4fcSRobert Mustacchi /* copy from the next struct field */ 854*9d26e4fcSRobert Mustacchi from = src + ce_info->offset; 855*9d26e4fcSRobert Mustacchi 856*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 857*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 858*9d26e4fcSRobert Mustacchi 859*9d26e4fcSRobert Mustacchi /* if the field width is exactly 32 on an x86 machine, then the shift 860*9d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 861*9d26e4fcSRobert Mustacchi * to 5 bits so the shift will do nothing 862*9d26e4fcSRobert Mustacchi */ 863*9d26e4fcSRobert Mustacchi if (ce_info->width < 32) 864*9d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 865*9d26e4fcSRobert Mustacchi else 866*9d26e4fcSRobert Mustacchi mask = ~(u32)0; 867*9d26e4fcSRobert Mustacchi 868*9d26e4fcSRobert Mustacchi /* don't swizzle the bits until after the mask because the mask bits 869*9d26e4fcSRobert Mustacchi * will be in a different bit position on big endian machines 870*9d26e4fcSRobert Mustacchi */ 871*9d26e4fcSRobert Mustacchi src_dword = *(u32 *)from; 872*9d26e4fcSRobert Mustacchi src_dword &= mask; 873*9d26e4fcSRobert Mustacchi 874*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 875*9d26e4fcSRobert Mustacchi mask <<= shift_width; 876*9d26e4fcSRobert Mustacchi src_dword <<= shift_width; 877*9d26e4fcSRobert Mustacchi 878*9d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 879*9d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 880*9d26e4fcSRobert Mustacchi 881*9d26e4fcSRobert Mustacchi i40e_memcpy(&dest_dword, dest, sizeof(dest_dword), I40E_DMA_TO_NONDMA); 882*9d26e4fcSRobert Mustacchi 883*9d26e4fcSRobert Mustacchi dest_dword &= ~(CPU_TO_LE32(mask)); /* get the bits not changing */ 884*9d26e4fcSRobert Mustacchi dest_dword |= CPU_TO_LE32(src_dword); /* add in the new bits */ 885*9d26e4fcSRobert Mustacchi 886*9d26e4fcSRobert Mustacchi /* put it all back */ 887*9d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_dword, sizeof(dest_dword), I40E_NONDMA_TO_DMA); 888*9d26e4fcSRobert Mustacchi } 889*9d26e4fcSRobert Mustacchi 890*9d26e4fcSRobert Mustacchi /** 891*9d26e4fcSRobert Mustacchi * i40e_write_qword - replace HMC context qword 892*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 893*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be read from 894*9d26e4fcSRobert Mustacchi * @src: the struct to be read from 895*9d26e4fcSRobert Mustacchi **/ 896*9d26e4fcSRobert Mustacchi static void i40e_write_qword(u8 *hmc_bits, 897*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 898*9d26e4fcSRobert Mustacchi u8 *src) 899*9d26e4fcSRobert Mustacchi { 900*9d26e4fcSRobert Mustacchi u64 src_qword, mask; 901*9d26e4fcSRobert Mustacchi u8 *from, *dest; 902*9d26e4fcSRobert Mustacchi u16 shift_width; 903*9d26e4fcSRobert Mustacchi __le64 dest_qword; 904*9d26e4fcSRobert Mustacchi 905*9d26e4fcSRobert Mustacchi /* copy from the next struct field */ 906*9d26e4fcSRobert Mustacchi from = src + ce_info->offset; 907*9d26e4fcSRobert Mustacchi 908*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 909*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 910*9d26e4fcSRobert Mustacchi 911*9d26e4fcSRobert Mustacchi /* if the field width is exactly 64 on an x86 machine, then the shift 912*9d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 913*9d26e4fcSRobert Mustacchi * to 6 bits so the shift will do nothing 914*9d26e4fcSRobert Mustacchi */ 915*9d26e4fcSRobert Mustacchi if (ce_info->width < 64) 916*9d26e4fcSRobert Mustacchi mask = BIT_ULL(ce_info->width) - 1; 917*9d26e4fcSRobert Mustacchi else 918*9d26e4fcSRobert Mustacchi mask = ~(u64)0; 919*9d26e4fcSRobert Mustacchi 920*9d26e4fcSRobert Mustacchi /* don't swizzle the bits until after the mask because the mask bits 921*9d26e4fcSRobert Mustacchi * will be in a different bit position on big endian machines 922*9d26e4fcSRobert Mustacchi */ 923*9d26e4fcSRobert Mustacchi src_qword = *(u64 *)from; 924*9d26e4fcSRobert Mustacchi src_qword &= mask; 925*9d26e4fcSRobert Mustacchi 926*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 927*9d26e4fcSRobert Mustacchi mask <<= shift_width; 928*9d26e4fcSRobert Mustacchi src_qword <<= shift_width; 929*9d26e4fcSRobert Mustacchi 930*9d26e4fcSRobert Mustacchi /* get the current bits from the target bit string */ 931*9d26e4fcSRobert Mustacchi dest = hmc_bits + (ce_info->lsb / 8); 932*9d26e4fcSRobert Mustacchi 933*9d26e4fcSRobert Mustacchi i40e_memcpy(&dest_qword, dest, sizeof(dest_qword), I40E_DMA_TO_NONDMA); 934*9d26e4fcSRobert Mustacchi 935*9d26e4fcSRobert Mustacchi dest_qword &= ~(CPU_TO_LE64(mask)); /* get the bits not changing */ 936*9d26e4fcSRobert Mustacchi dest_qword |= CPU_TO_LE64(src_qword); /* add in the new bits */ 937*9d26e4fcSRobert Mustacchi 938*9d26e4fcSRobert Mustacchi /* put it all back */ 939*9d26e4fcSRobert Mustacchi i40e_memcpy(dest, &dest_qword, sizeof(dest_qword), I40E_NONDMA_TO_DMA); 940*9d26e4fcSRobert Mustacchi } 941*9d26e4fcSRobert Mustacchi 942*9d26e4fcSRobert Mustacchi /** 943*9d26e4fcSRobert Mustacchi * i40e_read_byte - read HMC context byte into struct 944*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 945*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 946*9d26e4fcSRobert Mustacchi * @dest: the struct to be filled 947*9d26e4fcSRobert Mustacchi **/ 948*9d26e4fcSRobert Mustacchi static void i40e_read_byte(u8 *hmc_bits, 949*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 950*9d26e4fcSRobert Mustacchi u8 *dest) 951*9d26e4fcSRobert Mustacchi { 952*9d26e4fcSRobert Mustacchi u8 dest_byte, mask; 953*9d26e4fcSRobert Mustacchi u8 *src, *target; 954*9d26e4fcSRobert Mustacchi u16 shift_width; 955*9d26e4fcSRobert Mustacchi 956*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 957*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 958*9d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 959*9d26e4fcSRobert Mustacchi 960*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 961*9d26e4fcSRobert Mustacchi mask <<= shift_width; 962*9d26e4fcSRobert Mustacchi 963*9d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 964*9d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 965*9d26e4fcSRobert Mustacchi 966*9d26e4fcSRobert Mustacchi i40e_memcpy(&dest_byte, src, sizeof(dest_byte), I40E_DMA_TO_NONDMA); 967*9d26e4fcSRobert Mustacchi 968*9d26e4fcSRobert Mustacchi dest_byte &= ~(mask); 969*9d26e4fcSRobert Mustacchi 970*9d26e4fcSRobert Mustacchi dest_byte >>= shift_width; 971*9d26e4fcSRobert Mustacchi 972*9d26e4fcSRobert Mustacchi /* get the address from the struct field */ 973*9d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 974*9d26e4fcSRobert Mustacchi 975*9d26e4fcSRobert Mustacchi /* put it back in the struct */ 976*9d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA); 977*9d26e4fcSRobert Mustacchi } 978*9d26e4fcSRobert Mustacchi 979*9d26e4fcSRobert Mustacchi /** 980*9d26e4fcSRobert Mustacchi * i40e_read_word - read HMC context word into struct 981*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 982*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 983*9d26e4fcSRobert Mustacchi * @dest: the struct to be filled 984*9d26e4fcSRobert Mustacchi **/ 985*9d26e4fcSRobert Mustacchi static void i40e_read_word(u8 *hmc_bits, 986*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 987*9d26e4fcSRobert Mustacchi u8 *dest) 988*9d26e4fcSRobert Mustacchi { 989*9d26e4fcSRobert Mustacchi u16 dest_word, mask; 990*9d26e4fcSRobert Mustacchi u8 *src, *target; 991*9d26e4fcSRobert Mustacchi u16 shift_width; 992*9d26e4fcSRobert Mustacchi __le16 src_word; 993*9d26e4fcSRobert Mustacchi 994*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 995*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 996*9d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 997*9d26e4fcSRobert Mustacchi 998*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 999*9d26e4fcSRobert Mustacchi mask <<= shift_width; 1000*9d26e4fcSRobert Mustacchi 1001*9d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 1002*9d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 1003*9d26e4fcSRobert Mustacchi 1004*9d26e4fcSRobert Mustacchi i40e_memcpy(&src_word, src, sizeof(src_word), I40E_DMA_TO_NONDMA); 1005*9d26e4fcSRobert Mustacchi 1006*9d26e4fcSRobert Mustacchi /* the data in the memory is stored as little endian so mask it 1007*9d26e4fcSRobert Mustacchi * correctly 1008*9d26e4fcSRobert Mustacchi */ 1009*9d26e4fcSRobert Mustacchi src_word &= ~(CPU_TO_LE16(mask)); 1010*9d26e4fcSRobert Mustacchi 1011*9d26e4fcSRobert Mustacchi /* get the data back into host order before shifting */ 1012*9d26e4fcSRobert Mustacchi dest_word = LE16_TO_CPU(src_word); 1013*9d26e4fcSRobert Mustacchi 1014*9d26e4fcSRobert Mustacchi dest_word >>= shift_width; 1015*9d26e4fcSRobert Mustacchi 1016*9d26e4fcSRobert Mustacchi /* get the address from the struct field */ 1017*9d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 1018*9d26e4fcSRobert Mustacchi 1019*9d26e4fcSRobert Mustacchi /* put it back in the struct */ 1020*9d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA); 1021*9d26e4fcSRobert Mustacchi } 1022*9d26e4fcSRobert Mustacchi 1023*9d26e4fcSRobert Mustacchi /** 1024*9d26e4fcSRobert Mustacchi * i40e_read_dword - read HMC context dword into struct 1025*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 1026*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 1027*9d26e4fcSRobert Mustacchi * @dest: the struct to be filled 1028*9d26e4fcSRobert Mustacchi **/ 1029*9d26e4fcSRobert Mustacchi static void i40e_read_dword(u8 *hmc_bits, 1030*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 1031*9d26e4fcSRobert Mustacchi u8 *dest) 1032*9d26e4fcSRobert Mustacchi { 1033*9d26e4fcSRobert Mustacchi u32 dest_dword, mask; 1034*9d26e4fcSRobert Mustacchi u8 *src, *target; 1035*9d26e4fcSRobert Mustacchi u16 shift_width; 1036*9d26e4fcSRobert Mustacchi __le32 src_dword; 1037*9d26e4fcSRobert Mustacchi 1038*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 1039*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 1040*9d26e4fcSRobert Mustacchi 1041*9d26e4fcSRobert Mustacchi /* if the field width is exactly 32 on an x86 machine, then the shift 1042*9d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 1043*9d26e4fcSRobert Mustacchi * to 5 bits so the shift will do nothing 1044*9d26e4fcSRobert Mustacchi */ 1045*9d26e4fcSRobert Mustacchi if (ce_info->width < 32) 1046*9d26e4fcSRobert Mustacchi mask = BIT(ce_info->width) - 1; 1047*9d26e4fcSRobert Mustacchi else 1048*9d26e4fcSRobert Mustacchi mask = ~(u32)0; 1049*9d26e4fcSRobert Mustacchi 1050*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 1051*9d26e4fcSRobert Mustacchi mask <<= shift_width; 1052*9d26e4fcSRobert Mustacchi 1053*9d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 1054*9d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 1055*9d26e4fcSRobert Mustacchi 1056*9d26e4fcSRobert Mustacchi i40e_memcpy(&src_dword, src, sizeof(src_dword), I40E_DMA_TO_NONDMA); 1057*9d26e4fcSRobert Mustacchi 1058*9d26e4fcSRobert Mustacchi /* the data in the memory is stored as little endian so mask it 1059*9d26e4fcSRobert Mustacchi * correctly 1060*9d26e4fcSRobert Mustacchi */ 1061*9d26e4fcSRobert Mustacchi src_dword &= ~(CPU_TO_LE32(mask)); 1062*9d26e4fcSRobert Mustacchi 1063*9d26e4fcSRobert Mustacchi /* get the data back into host order before shifting */ 1064*9d26e4fcSRobert Mustacchi dest_dword = LE32_TO_CPU(src_dword); 1065*9d26e4fcSRobert Mustacchi 1066*9d26e4fcSRobert Mustacchi dest_dword >>= shift_width; 1067*9d26e4fcSRobert Mustacchi 1068*9d26e4fcSRobert Mustacchi /* get the address from the struct field */ 1069*9d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 1070*9d26e4fcSRobert Mustacchi 1071*9d26e4fcSRobert Mustacchi /* put it back in the struct */ 1072*9d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_dword, sizeof(dest_dword), 1073*9d26e4fcSRobert Mustacchi I40E_NONDMA_TO_DMA); 1074*9d26e4fcSRobert Mustacchi } 1075*9d26e4fcSRobert Mustacchi 1076*9d26e4fcSRobert Mustacchi /** 1077*9d26e4fcSRobert Mustacchi * i40e_read_qword - read HMC context qword into struct 1078*9d26e4fcSRobert Mustacchi * @hmc_bits: pointer to the HMC memory 1079*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 1080*9d26e4fcSRobert Mustacchi * @dest: the struct to be filled 1081*9d26e4fcSRobert Mustacchi **/ 1082*9d26e4fcSRobert Mustacchi static void i40e_read_qword(u8 *hmc_bits, 1083*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 1084*9d26e4fcSRobert Mustacchi u8 *dest) 1085*9d26e4fcSRobert Mustacchi { 1086*9d26e4fcSRobert Mustacchi u64 dest_qword, mask; 1087*9d26e4fcSRobert Mustacchi u8 *src, *target; 1088*9d26e4fcSRobert Mustacchi u16 shift_width; 1089*9d26e4fcSRobert Mustacchi __le64 src_qword; 1090*9d26e4fcSRobert Mustacchi 1091*9d26e4fcSRobert Mustacchi /* prepare the bits and mask */ 1092*9d26e4fcSRobert Mustacchi shift_width = ce_info->lsb % 8; 1093*9d26e4fcSRobert Mustacchi 1094*9d26e4fcSRobert Mustacchi /* if the field width is exactly 64 on an x86 machine, then the shift 1095*9d26e4fcSRobert Mustacchi * operation will not work because the SHL instructions count is masked 1096*9d26e4fcSRobert Mustacchi * to 6 bits so the shift will do nothing 1097*9d26e4fcSRobert Mustacchi */ 1098*9d26e4fcSRobert Mustacchi if (ce_info->width < 64) 1099*9d26e4fcSRobert Mustacchi mask = BIT_ULL(ce_info->width) - 1; 1100*9d26e4fcSRobert Mustacchi else 1101*9d26e4fcSRobert Mustacchi mask = ~(u64)0; 1102*9d26e4fcSRobert Mustacchi 1103*9d26e4fcSRobert Mustacchi /* shift to correct alignment */ 1104*9d26e4fcSRobert Mustacchi mask <<= shift_width; 1105*9d26e4fcSRobert Mustacchi 1106*9d26e4fcSRobert Mustacchi /* get the current bits from the src bit string */ 1107*9d26e4fcSRobert Mustacchi src = hmc_bits + (ce_info->lsb / 8); 1108*9d26e4fcSRobert Mustacchi 1109*9d26e4fcSRobert Mustacchi i40e_memcpy(&src_qword, src, sizeof(src_qword), I40E_DMA_TO_NONDMA); 1110*9d26e4fcSRobert Mustacchi 1111*9d26e4fcSRobert Mustacchi /* the data in the memory is stored as little endian so mask it 1112*9d26e4fcSRobert Mustacchi * correctly 1113*9d26e4fcSRobert Mustacchi */ 1114*9d26e4fcSRobert Mustacchi src_qword &= ~(CPU_TO_LE64(mask)); 1115*9d26e4fcSRobert Mustacchi 1116*9d26e4fcSRobert Mustacchi /* get the data back into host order before shifting */ 1117*9d26e4fcSRobert Mustacchi dest_qword = LE64_TO_CPU(src_qword); 1118*9d26e4fcSRobert Mustacchi 1119*9d26e4fcSRobert Mustacchi dest_qword >>= shift_width; 1120*9d26e4fcSRobert Mustacchi 1121*9d26e4fcSRobert Mustacchi /* get the address from the struct field */ 1122*9d26e4fcSRobert Mustacchi target = dest + ce_info->offset; 1123*9d26e4fcSRobert Mustacchi 1124*9d26e4fcSRobert Mustacchi /* put it back in the struct */ 1125*9d26e4fcSRobert Mustacchi i40e_memcpy(target, &dest_qword, sizeof(dest_qword), 1126*9d26e4fcSRobert Mustacchi I40E_NONDMA_TO_DMA); 1127*9d26e4fcSRobert Mustacchi } 1128*9d26e4fcSRobert Mustacchi 1129*9d26e4fcSRobert Mustacchi /** 1130*9d26e4fcSRobert Mustacchi * i40e_get_hmc_context - extract HMC context bits 1131*9d26e4fcSRobert Mustacchi * @context_bytes: pointer to the context bit array 1132*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 1133*9d26e4fcSRobert Mustacchi * @dest: the struct to be filled 1134*9d26e4fcSRobert Mustacchi **/ 1135*9d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_get_hmc_context(u8 *context_bytes, 1136*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 1137*9d26e4fcSRobert Mustacchi u8 *dest) 1138*9d26e4fcSRobert Mustacchi { 1139*9d26e4fcSRobert Mustacchi int f; 1140*9d26e4fcSRobert Mustacchi 1141*9d26e4fcSRobert Mustacchi for (f = 0; ce_info[f].width != 0; f++) { 1142*9d26e4fcSRobert Mustacchi switch (ce_info[f].size_of) { 1143*9d26e4fcSRobert Mustacchi case 1: 1144*9d26e4fcSRobert Mustacchi i40e_read_byte(context_bytes, &ce_info[f], dest); 1145*9d26e4fcSRobert Mustacchi break; 1146*9d26e4fcSRobert Mustacchi case 2: 1147*9d26e4fcSRobert Mustacchi i40e_read_word(context_bytes, &ce_info[f], dest); 1148*9d26e4fcSRobert Mustacchi break; 1149*9d26e4fcSRobert Mustacchi case 4: 1150*9d26e4fcSRobert Mustacchi i40e_read_dword(context_bytes, &ce_info[f], dest); 1151*9d26e4fcSRobert Mustacchi break; 1152*9d26e4fcSRobert Mustacchi case 8: 1153*9d26e4fcSRobert Mustacchi i40e_read_qword(context_bytes, &ce_info[f], dest); 1154*9d26e4fcSRobert Mustacchi break; 1155*9d26e4fcSRobert Mustacchi default: 1156*9d26e4fcSRobert Mustacchi /* nothing to do, just keep going */ 1157*9d26e4fcSRobert Mustacchi break; 1158*9d26e4fcSRobert Mustacchi } 1159*9d26e4fcSRobert Mustacchi } 1160*9d26e4fcSRobert Mustacchi 1161*9d26e4fcSRobert Mustacchi return I40E_SUCCESS; 1162*9d26e4fcSRobert Mustacchi } 1163*9d26e4fcSRobert Mustacchi 1164*9d26e4fcSRobert Mustacchi /** 1165*9d26e4fcSRobert Mustacchi * i40e_clear_hmc_context - zero out the HMC context bits 1166*9d26e4fcSRobert Mustacchi * @hw: the hardware struct 1167*9d26e4fcSRobert Mustacchi * @context_bytes: pointer to the context bit array (DMA memory) 1168*9d26e4fcSRobert Mustacchi * @hmc_type: the type of HMC resource 1169*9d26e4fcSRobert Mustacchi **/ 1170*9d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_clear_hmc_context(struct i40e_hw *hw, 1171*9d26e4fcSRobert Mustacchi u8 *context_bytes, 1172*9d26e4fcSRobert Mustacchi enum i40e_hmc_lan_rsrc_type hmc_type) 1173*9d26e4fcSRobert Mustacchi { 1174*9d26e4fcSRobert Mustacchi /* clean the bit array */ 1175*9d26e4fcSRobert Mustacchi i40e_memset(context_bytes, 0, (u32)hw->hmc.hmc_obj[hmc_type].size, 1176*9d26e4fcSRobert Mustacchi I40E_DMA_MEM); 1177*9d26e4fcSRobert Mustacchi 1178*9d26e4fcSRobert Mustacchi return I40E_SUCCESS; 1179*9d26e4fcSRobert Mustacchi } 1180*9d26e4fcSRobert Mustacchi 1181*9d26e4fcSRobert Mustacchi /** 1182*9d26e4fcSRobert Mustacchi * i40e_set_hmc_context - replace HMC context bits 1183*9d26e4fcSRobert Mustacchi * @context_bytes: pointer to the context bit array 1184*9d26e4fcSRobert Mustacchi * @ce_info: a description of the struct to be filled 1185*9d26e4fcSRobert Mustacchi * @dest: the struct to be filled 1186*9d26e4fcSRobert Mustacchi **/ 1187*9d26e4fcSRobert Mustacchi static enum i40e_status_code i40e_set_hmc_context(u8 *context_bytes, 1188*9d26e4fcSRobert Mustacchi struct i40e_context_ele *ce_info, 1189*9d26e4fcSRobert Mustacchi u8 *dest) 1190*9d26e4fcSRobert Mustacchi { 1191*9d26e4fcSRobert Mustacchi int f; 1192*9d26e4fcSRobert Mustacchi 1193*9d26e4fcSRobert Mustacchi for (f = 0; ce_info[f].width != 0; f++) { 1194*9d26e4fcSRobert Mustacchi 1195*9d26e4fcSRobert Mustacchi /* we have to deal with each element of the HMC using the 1196*9d26e4fcSRobert Mustacchi * correct size so that we are correct regardless of the 1197*9d26e4fcSRobert Mustacchi * endianness of the machine 1198*9d26e4fcSRobert Mustacchi */ 1199*9d26e4fcSRobert Mustacchi switch (ce_info[f].size_of) { 1200*9d26e4fcSRobert Mustacchi case 1: 1201*9d26e4fcSRobert Mustacchi i40e_write_byte(context_bytes, &ce_info[f], dest); 1202*9d26e4fcSRobert Mustacchi break; 1203*9d26e4fcSRobert Mustacchi case 2: 1204*9d26e4fcSRobert Mustacchi i40e_write_word(context_bytes, &ce_info[f], dest); 1205*9d26e4fcSRobert Mustacchi break; 1206*9d26e4fcSRobert Mustacchi case 4: 1207*9d26e4fcSRobert Mustacchi i40e_write_dword(context_bytes, &ce_info[f], dest); 1208*9d26e4fcSRobert Mustacchi break; 1209*9d26e4fcSRobert Mustacchi case 8: 1210*9d26e4fcSRobert Mustacchi i40e_write_qword(context_bytes, &ce_info[f], dest); 1211*9d26e4fcSRobert Mustacchi break; 1212*9d26e4fcSRobert Mustacchi } 1213*9d26e4fcSRobert Mustacchi } 1214*9d26e4fcSRobert Mustacchi 1215*9d26e4fcSRobert Mustacchi return I40E_SUCCESS; 1216*9d26e4fcSRobert Mustacchi } 1217*9d26e4fcSRobert Mustacchi 1218*9d26e4fcSRobert Mustacchi /** 1219*9d26e4fcSRobert Mustacchi * i40e_hmc_get_object_va - retrieves an object's virtual address 1220*9d26e4fcSRobert Mustacchi * @hw: pointer to the hw structure 1221*9d26e4fcSRobert Mustacchi * @object_base: pointer to u64 to get the va 1222*9d26e4fcSRobert Mustacchi * @rsrc_type: the hmc resource type 1223*9d26e4fcSRobert Mustacchi * @obj_idx: hmc object index 1224*9d26e4fcSRobert Mustacchi * 1225*9d26e4fcSRobert Mustacchi * This function retrieves the object's virtual address from the object 1226*9d26e4fcSRobert Mustacchi * base pointer. This function is used for LAN Queue contexts. 1227*9d26e4fcSRobert Mustacchi **/ 1228*9d26e4fcSRobert Mustacchi static 1229*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_hmc_get_object_va(struct i40e_hw *hw, 1230*9d26e4fcSRobert Mustacchi u8 **object_base, 1231*9d26e4fcSRobert Mustacchi enum i40e_hmc_lan_rsrc_type rsrc_type, 1232*9d26e4fcSRobert Mustacchi u32 obj_idx) 1233*9d26e4fcSRobert Mustacchi { 1234*9d26e4fcSRobert Mustacchi u32 obj_offset_in_sd, obj_offset_in_pd; 1235*9d26e4fcSRobert Mustacchi struct i40e_hmc_info *hmc_info = &hw->hmc; 1236*9d26e4fcSRobert Mustacchi struct i40e_hmc_sd_entry *sd_entry; 1237*9d26e4fcSRobert Mustacchi struct i40e_hmc_pd_entry *pd_entry; 1238*9d26e4fcSRobert Mustacchi u32 pd_idx, pd_lmt, rel_pd_idx; 1239*9d26e4fcSRobert Mustacchi enum i40e_status_code ret_code = I40E_SUCCESS; 1240*9d26e4fcSRobert Mustacchi u64 obj_offset_in_fpm; 1241*9d26e4fcSRobert Mustacchi u32 sd_idx, sd_lmt; 1242*9d26e4fcSRobert Mustacchi 1243*9d26e4fcSRobert Mustacchi if (NULL == hmc_info) { 1244*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 1245*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info ptr\n"); 1246*9d26e4fcSRobert Mustacchi goto exit; 1247*9d26e4fcSRobert Mustacchi } 1248*9d26e4fcSRobert Mustacchi if (NULL == hmc_info->hmc_obj) { 1249*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 1250*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n"); 1251*9d26e4fcSRobert Mustacchi goto exit; 1252*9d26e4fcSRobert Mustacchi } 1253*9d26e4fcSRobert Mustacchi if (NULL == object_base) { 1254*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 1255*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_hmc_get_object_va: bad object_base ptr\n"); 1256*9d26e4fcSRobert Mustacchi goto exit; 1257*9d26e4fcSRobert Mustacchi } 1258*9d26e4fcSRobert Mustacchi if (I40E_HMC_INFO_SIGNATURE != hmc_info->signature) { 1259*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_BAD_PTR; 1260*9d26e4fcSRobert Mustacchi DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->signature\n"); 1261*9d26e4fcSRobert Mustacchi goto exit; 1262*9d26e4fcSRobert Mustacchi } 1263*9d26e4fcSRobert Mustacchi if (obj_idx >= hmc_info->hmc_obj[rsrc_type].cnt) { 1264*9d26e4fcSRobert Mustacchi DEBUGOUT1("i40e_hmc_get_object_va: returns error %d\n", 1265*9d26e4fcSRobert Mustacchi ret_code); 1266*9d26e4fcSRobert Mustacchi ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX; 1267*9d26e4fcSRobert Mustacchi goto exit; 1268*9d26e4fcSRobert Mustacchi } 1269*9d26e4fcSRobert Mustacchi /* find sd index and limit */ 1270*9d26e4fcSRobert Mustacchi I40E_FIND_SD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1, 1271*9d26e4fcSRobert Mustacchi &sd_idx, &sd_lmt); 1272*9d26e4fcSRobert Mustacchi 1273*9d26e4fcSRobert Mustacchi sd_entry = &hmc_info->sd_table.sd_entry[sd_idx]; 1274*9d26e4fcSRobert Mustacchi obj_offset_in_fpm = hmc_info->hmc_obj[rsrc_type].base + 1275*9d26e4fcSRobert Mustacchi hmc_info->hmc_obj[rsrc_type].size * obj_idx; 1276*9d26e4fcSRobert Mustacchi 1277*9d26e4fcSRobert Mustacchi if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) { 1278*9d26e4fcSRobert Mustacchi I40E_FIND_PD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1, 1279*9d26e4fcSRobert Mustacchi &pd_idx, &pd_lmt); 1280*9d26e4fcSRobert Mustacchi rel_pd_idx = pd_idx % I40E_HMC_PD_CNT_IN_SD; 1281*9d26e4fcSRobert Mustacchi pd_entry = &sd_entry->u.pd_table.pd_entry[rel_pd_idx]; 1282*9d26e4fcSRobert Mustacchi obj_offset_in_pd = (u32)(obj_offset_in_fpm % 1283*9d26e4fcSRobert Mustacchi I40E_HMC_PAGED_BP_SIZE); 1284*9d26e4fcSRobert Mustacchi *object_base = (u8 *)pd_entry->bp.addr.va + obj_offset_in_pd; 1285*9d26e4fcSRobert Mustacchi } else { 1286*9d26e4fcSRobert Mustacchi obj_offset_in_sd = (u32)(obj_offset_in_fpm % 1287*9d26e4fcSRobert Mustacchi I40E_HMC_DIRECT_BP_SIZE); 1288*9d26e4fcSRobert Mustacchi *object_base = (u8 *)sd_entry->u.bp.addr.va + obj_offset_in_sd; 1289*9d26e4fcSRobert Mustacchi } 1290*9d26e4fcSRobert Mustacchi exit: 1291*9d26e4fcSRobert Mustacchi return ret_code; 1292*9d26e4fcSRobert Mustacchi } 1293*9d26e4fcSRobert Mustacchi 1294*9d26e4fcSRobert Mustacchi /** 1295*9d26e4fcSRobert Mustacchi * i40e_get_lan_tx_queue_context - return the HMC context for the queue 1296*9d26e4fcSRobert Mustacchi * @hw: the hardware struct 1297*9d26e4fcSRobert Mustacchi * @queue: the queue we care about 1298*9d26e4fcSRobert Mustacchi * @s: the struct to be filled 1299*9d26e4fcSRobert Mustacchi **/ 1300*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_get_lan_tx_queue_context(struct i40e_hw *hw, 1301*9d26e4fcSRobert Mustacchi u16 queue, 1302*9d26e4fcSRobert Mustacchi struct i40e_hmc_obj_txq *s) 1303*9d26e4fcSRobert Mustacchi { 1304*9d26e4fcSRobert Mustacchi enum i40e_status_code err; 1305*9d26e4fcSRobert Mustacchi u8 *context_bytes; 1306*9d26e4fcSRobert Mustacchi 1307*9d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); 1308*9d26e4fcSRobert Mustacchi if (err < 0) 1309*9d26e4fcSRobert Mustacchi return err; 1310*9d26e4fcSRobert Mustacchi 1311*9d26e4fcSRobert Mustacchi return i40e_get_hmc_context(context_bytes, 1312*9d26e4fcSRobert Mustacchi i40e_hmc_txq_ce_info, (u8 *)s); 1313*9d26e4fcSRobert Mustacchi } 1314*9d26e4fcSRobert Mustacchi 1315*9d26e4fcSRobert Mustacchi /** 1316*9d26e4fcSRobert Mustacchi * i40e_clear_lan_tx_queue_context - clear the HMC context for the queue 1317*9d26e4fcSRobert Mustacchi * @hw: the hardware struct 1318*9d26e4fcSRobert Mustacchi * @queue: the queue we care about 1319*9d26e4fcSRobert Mustacchi **/ 1320*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_clear_lan_tx_queue_context(struct i40e_hw *hw, 1321*9d26e4fcSRobert Mustacchi u16 queue) 1322*9d26e4fcSRobert Mustacchi { 1323*9d26e4fcSRobert Mustacchi enum i40e_status_code err; 1324*9d26e4fcSRobert Mustacchi u8 *context_bytes; 1325*9d26e4fcSRobert Mustacchi 1326*9d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); 1327*9d26e4fcSRobert Mustacchi if (err < 0) 1328*9d26e4fcSRobert Mustacchi return err; 1329*9d26e4fcSRobert Mustacchi 1330*9d26e4fcSRobert Mustacchi return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_TX); 1331*9d26e4fcSRobert Mustacchi } 1332*9d26e4fcSRobert Mustacchi 1333*9d26e4fcSRobert Mustacchi /** 1334*9d26e4fcSRobert Mustacchi * i40e_set_lan_tx_queue_context - set the HMC context for the queue 1335*9d26e4fcSRobert Mustacchi * @hw: the hardware struct 1336*9d26e4fcSRobert Mustacchi * @queue: the queue we care about 1337*9d26e4fcSRobert Mustacchi * @s: the struct to be filled 1338*9d26e4fcSRobert Mustacchi **/ 1339*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_set_lan_tx_queue_context(struct i40e_hw *hw, 1340*9d26e4fcSRobert Mustacchi u16 queue, 1341*9d26e4fcSRobert Mustacchi struct i40e_hmc_obj_txq *s) 1342*9d26e4fcSRobert Mustacchi { 1343*9d26e4fcSRobert Mustacchi enum i40e_status_code err; 1344*9d26e4fcSRobert Mustacchi u8 *context_bytes; 1345*9d26e4fcSRobert Mustacchi 1346*9d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue); 1347*9d26e4fcSRobert Mustacchi if (err < 0) 1348*9d26e4fcSRobert Mustacchi return err; 1349*9d26e4fcSRobert Mustacchi 1350*9d26e4fcSRobert Mustacchi return i40e_set_hmc_context(context_bytes, 1351*9d26e4fcSRobert Mustacchi i40e_hmc_txq_ce_info, (u8 *)s); 1352*9d26e4fcSRobert Mustacchi } 1353*9d26e4fcSRobert Mustacchi 1354*9d26e4fcSRobert Mustacchi /** 1355*9d26e4fcSRobert Mustacchi * i40e_get_lan_rx_queue_context - return the HMC context for the queue 1356*9d26e4fcSRobert Mustacchi * @hw: the hardware struct 1357*9d26e4fcSRobert Mustacchi * @queue: the queue we care about 1358*9d26e4fcSRobert Mustacchi * @s: the struct to be filled 1359*9d26e4fcSRobert Mustacchi **/ 1360*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_get_lan_rx_queue_context(struct i40e_hw *hw, 1361*9d26e4fcSRobert Mustacchi u16 queue, 1362*9d26e4fcSRobert Mustacchi struct i40e_hmc_obj_rxq *s) 1363*9d26e4fcSRobert Mustacchi { 1364*9d26e4fcSRobert Mustacchi enum i40e_status_code err; 1365*9d26e4fcSRobert Mustacchi u8 *context_bytes; 1366*9d26e4fcSRobert Mustacchi 1367*9d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); 1368*9d26e4fcSRobert Mustacchi if (err < 0) 1369*9d26e4fcSRobert Mustacchi return err; 1370*9d26e4fcSRobert Mustacchi 1371*9d26e4fcSRobert Mustacchi return i40e_get_hmc_context(context_bytes, 1372*9d26e4fcSRobert Mustacchi i40e_hmc_rxq_ce_info, (u8 *)s); 1373*9d26e4fcSRobert Mustacchi } 1374*9d26e4fcSRobert Mustacchi 1375*9d26e4fcSRobert Mustacchi /** 1376*9d26e4fcSRobert Mustacchi * i40e_clear_lan_rx_queue_context - clear the HMC context for the queue 1377*9d26e4fcSRobert Mustacchi * @hw: the hardware struct 1378*9d26e4fcSRobert Mustacchi * @queue: the queue we care about 1379*9d26e4fcSRobert Mustacchi **/ 1380*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_clear_lan_rx_queue_context(struct i40e_hw *hw, 1381*9d26e4fcSRobert Mustacchi u16 queue) 1382*9d26e4fcSRobert Mustacchi { 1383*9d26e4fcSRobert Mustacchi enum i40e_status_code err; 1384*9d26e4fcSRobert Mustacchi u8 *context_bytes; 1385*9d26e4fcSRobert Mustacchi 1386*9d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); 1387*9d26e4fcSRobert Mustacchi if (err < 0) 1388*9d26e4fcSRobert Mustacchi return err; 1389*9d26e4fcSRobert Mustacchi 1390*9d26e4fcSRobert Mustacchi return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_RX); 1391*9d26e4fcSRobert Mustacchi } 1392*9d26e4fcSRobert Mustacchi 1393*9d26e4fcSRobert Mustacchi /** 1394*9d26e4fcSRobert Mustacchi * i40e_set_lan_rx_queue_context - set the HMC context for the queue 1395*9d26e4fcSRobert Mustacchi * @hw: the hardware struct 1396*9d26e4fcSRobert Mustacchi * @queue: the queue we care about 1397*9d26e4fcSRobert Mustacchi * @s: the struct to be filled 1398*9d26e4fcSRobert Mustacchi **/ 1399*9d26e4fcSRobert Mustacchi enum i40e_status_code i40e_set_lan_rx_queue_context(struct i40e_hw *hw, 1400*9d26e4fcSRobert Mustacchi u16 queue, 1401*9d26e4fcSRobert Mustacchi struct i40e_hmc_obj_rxq *s) 1402*9d26e4fcSRobert Mustacchi { 1403*9d26e4fcSRobert Mustacchi enum i40e_status_code err; 1404*9d26e4fcSRobert Mustacchi u8 *context_bytes; 1405*9d26e4fcSRobert Mustacchi 1406*9d26e4fcSRobert Mustacchi err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue); 1407*9d26e4fcSRobert Mustacchi if (err < 0) 1408*9d26e4fcSRobert Mustacchi return err; 1409*9d26e4fcSRobert Mustacchi 1410*9d26e4fcSRobert Mustacchi return i40e_set_hmc_context(context_bytes, 1411*9d26e4fcSRobert Mustacchi i40e_hmc_rxq_ce_info, (u8 *)s); 1412*9d26e4fcSRobert Mustacchi } 1413