xref: /illumos-gate/usr/src/uts/common/io/i40e/core/i40e_lan_hmc.c (revision 3d75a287b67b9092b2820a0d7c3be218f843066b)
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