xref: /freebsd/sys/dev/ixl/i40e_lan_hmc.c (revision f247dc252337766d1a423ce46d43879a62a742fa)
161ae650dSJack F Vogel /******************************************************************************
261ae650dSJack F Vogel 
361ae650dSJack F Vogel   Copyright (c) 2013-2014, Intel Corporation
461ae650dSJack F Vogel   All rights reserved.
561ae650dSJack F Vogel 
661ae650dSJack F Vogel   Redistribution and use in source and binary forms, with or without
761ae650dSJack F Vogel   modification, are permitted provided that the following conditions are met:
861ae650dSJack F Vogel 
961ae650dSJack F Vogel    1. Redistributions of source code must retain the above copyright notice,
1061ae650dSJack F Vogel       this list of conditions and the following disclaimer.
1161ae650dSJack F Vogel 
1261ae650dSJack F Vogel    2. Redistributions in binary form must reproduce the above copyright
1361ae650dSJack F Vogel       notice, this list of conditions and the following disclaimer in the
1461ae650dSJack F Vogel       documentation and/or other materials provided with the distribution.
1561ae650dSJack F Vogel 
1661ae650dSJack F Vogel    3. Neither the name of the Intel Corporation nor the names of its
1761ae650dSJack F Vogel       contributors may be used to endorse or promote products derived from
1861ae650dSJack F Vogel       this software without specific prior written permission.
1961ae650dSJack F Vogel 
2061ae650dSJack F Vogel   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2161ae650dSJack F Vogel   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2261ae650dSJack F Vogel   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2361ae650dSJack F Vogel   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2461ae650dSJack F Vogel   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2561ae650dSJack F Vogel   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2661ae650dSJack F Vogel   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2761ae650dSJack F Vogel   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2861ae650dSJack F Vogel   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2961ae650dSJack F Vogel   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3061ae650dSJack F Vogel   POSSIBILITY OF SUCH DAMAGE.
3161ae650dSJack F Vogel 
3261ae650dSJack F Vogel ******************************************************************************/
3361ae650dSJack F Vogel /*$FreeBSD$*/
3461ae650dSJack F Vogel 
3561ae650dSJack F Vogel #include "i40e_osdep.h"
3661ae650dSJack F Vogel #include "i40e_register.h"
3761ae650dSJack F Vogel #include "i40e_type.h"
3861ae650dSJack F Vogel #include "i40e_hmc.h"
3961ae650dSJack F Vogel #include "i40e_lan_hmc.h"
4061ae650dSJack F Vogel #include "i40e_prototype.h"
4161ae650dSJack F Vogel 
4261ae650dSJack F Vogel /* lan specific interface functions */
4361ae650dSJack F Vogel 
4461ae650dSJack F Vogel /**
4561ae650dSJack F Vogel  * i40e_align_l2obj_base - aligns base object pointer to 512 bytes
4661ae650dSJack F Vogel  * @offset: base address offset needing alignment
4761ae650dSJack F Vogel  *
4861ae650dSJack F Vogel  * Aligns the layer 2 function private memory so it's 512-byte aligned.
4961ae650dSJack F Vogel  **/
5061ae650dSJack F Vogel static u64 i40e_align_l2obj_base(u64 offset)
5161ae650dSJack F Vogel {
5261ae650dSJack F Vogel 	u64 aligned_offset = offset;
5361ae650dSJack F Vogel 
5461ae650dSJack F Vogel 	if ((offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT) > 0)
5561ae650dSJack F Vogel 		aligned_offset += (I40E_HMC_L2OBJ_BASE_ALIGNMENT -
5661ae650dSJack F Vogel 				   (offset % I40E_HMC_L2OBJ_BASE_ALIGNMENT));
5761ae650dSJack F Vogel 
5861ae650dSJack F Vogel 	return aligned_offset;
5961ae650dSJack F Vogel }
6061ae650dSJack F Vogel 
6161ae650dSJack F Vogel /**
6261ae650dSJack F Vogel  * i40e_calculate_l2fpm_size - calculates layer 2 FPM memory size
6361ae650dSJack F Vogel  * @txq_num: number of Tx queues needing backing context
6461ae650dSJack F Vogel  * @rxq_num: number of Rx queues needing backing context
6561ae650dSJack F Vogel  * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context
6661ae650dSJack F Vogel  * @fcoe_filt_num: number of FCoE filters needing backing context
6761ae650dSJack F Vogel  *
6861ae650dSJack F Vogel  * Calculates the maximum amount of memory for the function required, based
6961ae650dSJack F Vogel  * on the number of resources it must provide context for.
7061ae650dSJack F Vogel  **/
7161ae650dSJack F Vogel u64 i40e_calculate_l2fpm_size(u32 txq_num, u32 rxq_num,
7261ae650dSJack F Vogel 			      u32 fcoe_cntx_num, u32 fcoe_filt_num)
7361ae650dSJack F Vogel {
7461ae650dSJack F Vogel 	u64 fpm_size = 0;
7561ae650dSJack F Vogel 
7661ae650dSJack F Vogel 	fpm_size = txq_num * I40E_HMC_OBJ_SIZE_TXQ;
7761ae650dSJack F Vogel 	fpm_size = i40e_align_l2obj_base(fpm_size);
7861ae650dSJack F Vogel 
7961ae650dSJack F Vogel 	fpm_size += (rxq_num * I40E_HMC_OBJ_SIZE_RXQ);
8061ae650dSJack F Vogel 	fpm_size = i40e_align_l2obj_base(fpm_size);
8161ae650dSJack F Vogel 
8261ae650dSJack F Vogel 	fpm_size += (fcoe_cntx_num * I40E_HMC_OBJ_SIZE_FCOE_CNTX);
8361ae650dSJack F Vogel 	fpm_size = i40e_align_l2obj_base(fpm_size);
8461ae650dSJack F Vogel 
8561ae650dSJack F Vogel 	fpm_size += (fcoe_filt_num * I40E_HMC_OBJ_SIZE_FCOE_FILT);
8661ae650dSJack F Vogel 	fpm_size = i40e_align_l2obj_base(fpm_size);
8761ae650dSJack F Vogel 
8861ae650dSJack F Vogel 	return fpm_size;
8961ae650dSJack F Vogel }
9061ae650dSJack F Vogel 
9161ae650dSJack F Vogel /**
9261ae650dSJack F Vogel  * i40e_init_lan_hmc - initialize i40e_hmc_info struct
9361ae650dSJack F Vogel  * @hw: pointer to the HW structure
9461ae650dSJack F Vogel  * @txq_num: number of Tx queues needing backing context
9561ae650dSJack F Vogel  * @rxq_num: number of Rx queues needing backing context
9661ae650dSJack F Vogel  * @fcoe_cntx_num: amount of FCoE statefull contexts needing backing context
9761ae650dSJack F Vogel  * @fcoe_filt_num: number of FCoE filters needing backing context
9861ae650dSJack F Vogel  *
9961ae650dSJack F Vogel  * This function will be called once per physical function initialization.
10061ae650dSJack F Vogel  * It will fill out the i40e_hmc_obj_info structure for LAN objects based on
10161ae650dSJack F Vogel  * the driver's provided input, as well as information from the HMC itself
10261ae650dSJack F Vogel  * loaded from NVRAM.
10361ae650dSJack F Vogel  *
10461ae650dSJack F Vogel  * Assumptions:
10561ae650dSJack F Vogel  *   - HMC Resource Profile has been selected before calling this function.
10661ae650dSJack F Vogel  **/
10761ae650dSJack F Vogel enum i40e_status_code i40e_init_lan_hmc(struct i40e_hw *hw, u32 txq_num,
10861ae650dSJack F Vogel 					u32 rxq_num, u32 fcoe_cntx_num,
10961ae650dSJack F Vogel 					u32 fcoe_filt_num)
11061ae650dSJack F Vogel {
11161ae650dSJack F Vogel 	struct i40e_hmc_obj_info *obj, *full_obj;
11261ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
11361ae650dSJack F Vogel 	u64 l2fpm_size;
11461ae650dSJack F Vogel 	u32 size_exp;
11561ae650dSJack F Vogel 
11661ae650dSJack F Vogel 	hw->hmc.signature = I40E_HMC_INFO_SIGNATURE;
11761ae650dSJack F Vogel 	hw->hmc.hmc_fn_id = hw->pf_id;
11861ae650dSJack F Vogel 
11961ae650dSJack F Vogel 	/* allocate memory for hmc_obj */
12061ae650dSJack F Vogel 	ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem,
12161ae650dSJack F Vogel 			sizeof(struct i40e_hmc_obj_info) * I40E_HMC_LAN_MAX);
12261ae650dSJack F Vogel 	if (ret_code)
12361ae650dSJack F Vogel 		goto init_lan_hmc_out;
12461ae650dSJack F Vogel 	hw->hmc.hmc_obj = (struct i40e_hmc_obj_info *)
12561ae650dSJack F Vogel 			  hw->hmc.hmc_obj_virt_mem.va;
12661ae650dSJack F Vogel 
12761ae650dSJack F Vogel 	/* The full object will be used to create the LAN HMC SD */
12861ae650dSJack F Vogel 	full_obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_FULL];
12961ae650dSJack F Vogel 	full_obj->max_cnt = 0;
13061ae650dSJack F Vogel 	full_obj->cnt = 0;
13161ae650dSJack F Vogel 	full_obj->base = 0;
13261ae650dSJack F Vogel 	full_obj->size = 0;
13361ae650dSJack F Vogel 
13461ae650dSJack F Vogel 	/* Tx queue context information */
13561ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX];
13661ae650dSJack F Vogel 	obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX);
13761ae650dSJack F Vogel 	obj->cnt = txq_num;
13861ae650dSJack F Vogel 	obj->base = 0;
13961ae650dSJack F Vogel 	size_exp = rd32(hw, I40E_GLHMC_LANTXOBJSZ);
14061ae650dSJack F Vogel 	obj->size = (u64)1 << size_exp;
14161ae650dSJack F Vogel 
14261ae650dSJack F Vogel 	/* validate values requested by driver don't exceed HMC capacity */
14361ae650dSJack F Vogel 	if (txq_num > obj->max_cnt) {
14461ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
14561ae650dSJack F Vogel 		DEBUGOUT3("i40e_init_lan_hmc: Tx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
14661ae650dSJack F Vogel 			  txq_num, obj->max_cnt, ret_code);
14761ae650dSJack F Vogel 		goto init_lan_hmc_out;
14861ae650dSJack F Vogel 	}
14961ae650dSJack F Vogel 
15061ae650dSJack F Vogel 	/* aggregate values into the full LAN object for later */
15161ae650dSJack F Vogel 	full_obj->max_cnt += obj->max_cnt;
15261ae650dSJack F Vogel 	full_obj->cnt += obj->cnt;
15361ae650dSJack F Vogel 
15461ae650dSJack F Vogel 	/* Rx queue context information */
15561ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX];
15661ae650dSJack F Vogel 	obj->max_cnt = rd32(hw, I40E_GLHMC_LANQMAX);
15761ae650dSJack F Vogel 	obj->cnt = rxq_num;
15861ae650dSJack F Vogel 	obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_TX].base +
15961ae650dSJack F Vogel 		    (hw->hmc.hmc_obj[I40E_HMC_LAN_TX].cnt *
16061ae650dSJack F Vogel 		     hw->hmc.hmc_obj[I40E_HMC_LAN_TX].size);
16161ae650dSJack F Vogel 	obj->base = i40e_align_l2obj_base(obj->base);
16261ae650dSJack F Vogel 	size_exp = rd32(hw, I40E_GLHMC_LANRXOBJSZ);
16361ae650dSJack F Vogel 	obj->size = (u64)1 << size_exp;
16461ae650dSJack F Vogel 
16561ae650dSJack F Vogel 	/* validate values requested by driver don't exceed HMC capacity */
16661ae650dSJack F Vogel 	if (rxq_num > obj->max_cnt) {
16761ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
16861ae650dSJack F Vogel 		DEBUGOUT3("i40e_init_lan_hmc: Rx context: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
16961ae650dSJack F Vogel 			  rxq_num, obj->max_cnt, ret_code);
17061ae650dSJack F Vogel 		goto init_lan_hmc_out;
17161ae650dSJack F Vogel 	}
17261ae650dSJack F Vogel 
17361ae650dSJack F Vogel 	/* aggregate values into the full LAN object for later */
17461ae650dSJack F Vogel 	full_obj->max_cnt += obj->max_cnt;
17561ae650dSJack F Vogel 	full_obj->cnt += obj->cnt;
17661ae650dSJack F Vogel 
17761ae650dSJack F Vogel 	/* FCoE context information */
17861ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX];
17961ae650dSJack F Vogel 	obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEMAX);
18061ae650dSJack F Vogel 	obj->cnt = fcoe_cntx_num;
18161ae650dSJack F Vogel 	obj->base = hw->hmc.hmc_obj[I40E_HMC_LAN_RX].base +
18261ae650dSJack F Vogel 		    (hw->hmc.hmc_obj[I40E_HMC_LAN_RX].cnt *
18361ae650dSJack F Vogel 		     hw->hmc.hmc_obj[I40E_HMC_LAN_RX].size);
18461ae650dSJack F Vogel 	obj->base = i40e_align_l2obj_base(obj->base);
18561ae650dSJack F Vogel 	size_exp = rd32(hw, I40E_GLHMC_FCOEDDPOBJSZ);
18661ae650dSJack F Vogel 	obj->size = (u64)1 << size_exp;
18761ae650dSJack F Vogel 
18861ae650dSJack F Vogel 	/* validate values requested by driver don't exceed HMC capacity */
18961ae650dSJack F Vogel 	if (fcoe_cntx_num > obj->max_cnt) {
19061ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
19161ae650dSJack F Vogel 		DEBUGOUT3("i40e_init_lan_hmc: FCoE context: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
19261ae650dSJack F Vogel 			  fcoe_cntx_num, obj->max_cnt, ret_code);
19361ae650dSJack F Vogel 		goto init_lan_hmc_out;
19461ae650dSJack F Vogel 	}
19561ae650dSJack F Vogel 
19661ae650dSJack F Vogel 	/* aggregate values into the full LAN object for later */
19761ae650dSJack F Vogel 	full_obj->max_cnt += obj->max_cnt;
19861ae650dSJack F Vogel 	full_obj->cnt += obj->cnt;
19961ae650dSJack F Vogel 
20061ae650dSJack F Vogel 	/* FCoE filter information */
20161ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT];
20261ae650dSJack F Vogel 	obj->max_cnt = rd32(hw, I40E_GLHMC_FCOEFMAX);
20361ae650dSJack F Vogel 	obj->cnt = fcoe_filt_num;
20461ae650dSJack F Vogel 	obj->base = hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].base +
20561ae650dSJack F Vogel 		    (hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].cnt *
20661ae650dSJack F Vogel 		     hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX].size);
20761ae650dSJack F Vogel 	obj->base = i40e_align_l2obj_base(obj->base);
20861ae650dSJack F Vogel 	size_exp = rd32(hw, I40E_GLHMC_FCOEFOBJSZ);
20961ae650dSJack F Vogel 	obj->size = (u64)1 << size_exp;
21061ae650dSJack F Vogel 
21161ae650dSJack F Vogel 	/* validate values requested by driver don't exceed HMC capacity */
21261ae650dSJack F Vogel 	if (fcoe_filt_num > obj->max_cnt) {
21361ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
21461ae650dSJack F Vogel 		DEBUGOUT3("i40e_init_lan_hmc: FCoE filter: asks for 0x%x but max allowed is 0x%x, returns error %d\n",
21561ae650dSJack F Vogel 			  fcoe_filt_num, obj->max_cnt, ret_code);
21661ae650dSJack F Vogel 		goto init_lan_hmc_out;
21761ae650dSJack F Vogel 	}
21861ae650dSJack F Vogel 
21961ae650dSJack F Vogel 	/* aggregate values into the full LAN object for later */
22061ae650dSJack F Vogel 	full_obj->max_cnt += obj->max_cnt;
22161ae650dSJack F Vogel 	full_obj->cnt += obj->cnt;
22261ae650dSJack F Vogel 
22361ae650dSJack F Vogel 	hw->hmc.first_sd_index = 0;
22461ae650dSJack F Vogel 	hw->hmc.sd_table.ref_cnt = 0;
22561ae650dSJack F Vogel 	l2fpm_size = i40e_calculate_l2fpm_size(txq_num, rxq_num, fcoe_cntx_num,
22661ae650dSJack F Vogel 					       fcoe_filt_num);
22761ae650dSJack F Vogel 	if (NULL == hw->hmc.sd_table.sd_entry) {
22861ae650dSJack F Vogel 		hw->hmc.sd_table.sd_cnt = (u32)
22961ae650dSJack F Vogel 				   (l2fpm_size + I40E_HMC_DIRECT_BP_SIZE - 1) /
23061ae650dSJack F Vogel 				   I40E_HMC_DIRECT_BP_SIZE;
23161ae650dSJack F Vogel 
23261ae650dSJack F Vogel 		/* allocate the sd_entry members in the sd_table */
23361ae650dSJack F Vogel 		ret_code = i40e_allocate_virt_mem(hw, &hw->hmc.sd_table.addr,
23461ae650dSJack F Vogel 					  (sizeof(struct i40e_hmc_sd_entry) *
23561ae650dSJack F Vogel 					  hw->hmc.sd_table.sd_cnt));
23661ae650dSJack F Vogel 		if (ret_code)
23761ae650dSJack F Vogel 			goto init_lan_hmc_out;
23861ae650dSJack F Vogel 		hw->hmc.sd_table.sd_entry =
23961ae650dSJack F Vogel 			(struct i40e_hmc_sd_entry *)hw->hmc.sd_table.addr.va;
24061ae650dSJack F Vogel 	}
24161ae650dSJack F Vogel 	/* store in the LAN full object for later */
24261ae650dSJack F Vogel 	full_obj->size = l2fpm_size;
24361ae650dSJack F Vogel 
24461ae650dSJack F Vogel init_lan_hmc_out:
24561ae650dSJack F Vogel 	return ret_code;
24661ae650dSJack F Vogel }
24761ae650dSJack F Vogel 
24861ae650dSJack F Vogel /**
24961ae650dSJack F Vogel  * i40e_remove_pd_page - Remove a page from the page descriptor table
25061ae650dSJack F Vogel  * @hw: pointer to the HW structure
25161ae650dSJack F Vogel  * @hmc_info: pointer to the HMC configuration information structure
25261ae650dSJack F Vogel  * @idx: segment descriptor index to find the relevant page descriptor
25361ae650dSJack F Vogel  *
25461ae650dSJack F Vogel  * This function:
25561ae650dSJack F Vogel  *	1. Marks the entry in pd table (for paged address mode) invalid
25661ae650dSJack F Vogel  *	2. write to register PMPDINV to invalidate the backing page in FV cache
25761ae650dSJack F Vogel  *	3. Decrement the ref count for  pd_entry
25861ae650dSJack F Vogel  * assumptions:
25961ae650dSJack F Vogel  *	1. caller can deallocate the memory used by pd after this function
26061ae650dSJack F Vogel  *	   returns.
26161ae650dSJack F Vogel  **/
26261ae650dSJack F Vogel static enum i40e_status_code i40e_remove_pd_page(struct i40e_hw *hw,
26361ae650dSJack F Vogel 						 struct i40e_hmc_info *hmc_info,
26461ae650dSJack F Vogel 						 u32 idx)
26561ae650dSJack F Vogel {
26661ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
26761ae650dSJack F Vogel 
26861ae650dSJack F Vogel 	if (i40e_prep_remove_pd_page(hmc_info, idx) == I40E_SUCCESS)
26961ae650dSJack F Vogel 		ret_code = i40e_remove_pd_page_new(hw, hmc_info, idx, TRUE);
27061ae650dSJack F Vogel 
27161ae650dSJack F Vogel 	return ret_code;
27261ae650dSJack F Vogel }
27361ae650dSJack F Vogel 
27461ae650dSJack F Vogel /**
27561ae650dSJack F Vogel  * i40e_remove_sd_bp - remove a backing page from a segment descriptor
27661ae650dSJack F Vogel  * @hw: pointer to our HW structure
27761ae650dSJack F Vogel  * @hmc_info: pointer to the HMC configuration information structure
27861ae650dSJack F Vogel  * @idx: the page index
27961ae650dSJack F Vogel  *
28061ae650dSJack F Vogel  * This function:
28161ae650dSJack F Vogel  *	1. Marks the entry in sd table (for direct address mode) invalid
28261ae650dSJack F Vogel  *	2. write to register PMSDCMD, PMSDDATALOW(PMSDDATALOW.PMSDVALID set
28361ae650dSJack F Vogel  *	   to 0) and PMSDDATAHIGH to invalidate the sd page
28461ae650dSJack F Vogel  *	3. Decrement the ref count for the sd_entry
28561ae650dSJack F Vogel  * assumptions:
28661ae650dSJack F Vogel  *	1. caller can deallocate the memory used by backing storage after this
28761ae650dSJack F Vogel  *	   function returns.
28861ae650dSJack F Vogel  **/
28961ae650dSJack F Vogel static enum i40e_status_code i40e_remove_sd_bp(struct i40e_hw *hw,
29061ae650dSJack F Vogel 					       struct i40e_hmc_info *hmc_info,
29161ae650dSJack F Vogel 					       u32 idx)
29261ae650dSJack F Vogel {
29361ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
29461ae650dSJack F Vogel 
29561ae650dSJack F Vogel 	if (i40e_prep_remove_sd_bp(hmc_info, idx) == I40E_SUCCESS)
29661ae650dSJack F Vogel 		ret_code = i40e_remove_sd_bp_new(hw, hmc_info, idx, TRUE);
29761ae650dSJack F Vogel 
29861ae650dSJack F Vogel 	return ret_code;
29961ae650dSJack F Vogel }
30061ae650dSJack F Vogel 
30161ae650dSJack F Vogel /**
30261ae650dSJack F Vogel  * i40e_create_lan_hmc_object - allocate backing store for hmc objects
30361ae650dSJack F Vogel  * @hw: pointer to the HW structure
30461ae650dSJack F Vogel  * @info: pointer to i40e_hmc_create_obj_info struct
30561ae650dSJack F Vogel  *
30661ae650dSJack F Vogel  * This will allocate memory for PDs and backing pages and populate
30761ae650dSJack F Vogel  * the sd and pd entries.
30861ae650dSJack F Vogel  **/
30961ae650dSJack F Vogel enum i40e_status_code i40e_create_lan_hmc_object(struct i40e_hw *hw,
31061ae650dSJack F Vogel 				struct i40e_hmc_lan_create_obj_info *info)
31161ae650dSJack F Vogel {
31261ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
31361ae650dSJack F Vogel 	struct i40e_hmc_sd_entry *sd_entry;
31461ae650dSJack F Vogel 	u32 pd_idx1 = 0, pd_lmt1 = 0;
31561ae650dSJack F Vogel 	u32 pd_idx = 0, pd_lmt = 0;
31661ae650dSJack F Vogel 	bool pd_error = FALSE;
31761ae650dSJack F Vogel 	u32 sd_idx, sd_lmt;
31861ae650dSJack F Vogel 	u64 sd_size;
31961ae650dSJack F Vogel 	u32 i, j;
32061ae650dSJack F Vogel 
32161ae650dSJack F Vogel 	if (NULL == info) {
32261ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
32361ae650dSJack F Vogel 		DEBUGOUT("i40e_create_lan_hmc_object: bad info ptr\n");
32461ae650dSJack F Vogel 		goto exit;
32561ae650dSJack F Vogel 	}
32661ae650dSJack F Vogel 	if (NULL == info->hmc_info) {
32761ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
32861ae650dSJack F Vogel 		DEBUGOUT("i40e_create_lan_hmc_object: bad hmc_info ptr\n");
32961ae650dSJack F Vogel 		goto exit;
33061ae650dSJack F Vogel 	}
33161ae650dSJack F Vogel 	if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) {
33261ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
33361ae650dSJack F Vogel 		DEBUGOUT("i40e_create_lan_hmc_object: bad signature\n");
33461ae650dSJack F Vogel 		goto exit;
33561ae650dSJack F Vogel 	}
33661ae650dSJack F Vogel 
33761ae650dSJack F Vogel 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
33861ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
33961ae650dSJack F Vogel 		DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n",
34061ae650dSJack F Vogel 			  ret_code);
34161ae650dSJack F Vogel 		goto exit;
34261ae650dSJack F Vogel 	}
34361ae650dSJack F Vogel 	if ((info->start_idx + info->count) >
34461ae650dSJack F Vogel 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
34561ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
34661ae650dSJack F Vogel 		DEBUGOUT1("i40e_create_lan_hmc_object: returns error %d\n",
34761ae650dSJack F Vogel 			  ret_code);
34861ae650dSJack F Vogel 		goto exit;
34961ae650dSJack F Vogel 	}
35061ae650dSJack F Vogel 
35161ae650dSJack F Vogel 	/* find sd index and limit */
35261ae650dSJack F Vogel 	I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
35361ae650dSJack F Vogel 				 info->start_idx, info->count,
35461ae650dSJack F Vogel 				 &sd_idx, &sd_lmt);
35561ae650dSJack F Vogel 	if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
35661ae650dSJack F Vogel 	    sd_lmt > info->hmc_info->sd_table.sd_cnt) {
35761ae650dSJack F Vogel 			ret_code = I40E_ERR_INVALID_SD_INDEX;
35861ae650dSJack F Vogel 			goto exit;
35961ae650dSJack F Vogel 	}
36061ae650dSJack F Vogel 	/* find pd index */
36161ae650dSJack F Vogel 	I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
36261ae650dSJack F Vogel 				 info->start_idx, info->count, &pd_idx,
36361ae650dSJack F Vogel 				 &pd_lmt);
36461ae650dSJack F Vogel 
36561ae650dSJack F Vogel 	/* This is to cover for cases where you may not want to have an SD with
36661ae650dSJack F Vogel 	 * the full 2M memory but something smaller. By not filling out any
36761ae650dSJack F Vogel 	 * size, the function will default the SD size to be 2M.
36861ae650dSJack F Vogel 	 */
36961ae650dSJack F Vogel 	if (info->direct_mode_sz == 0)
37061ae650dSJack F Vogel 		sd_size = I40E_HMC_DIRECT_BP_SIZE;
37161ae650dSJack F Vogel 	else
37261ae650dSJack F Vogel 		sd_size = info->direct_mode_sz;
37361ae650dSJack F Vogel 
37461ae650dSJack F Vogel 	/* check if all the sds are valid. If not, allocate a page and
37561ae650dSJack F Vogel 	 * initialize it.
37661ae650dSJack F Vogel 	 */
37761ae650dSJack F Vogel 	for (j = sd_idx; j < sd_lmt; j++) {
37861ae650dSJack F Vogel 		/* update the sd table entry */
37961ae650dSJack F Vogel 		ret_code = i40e_add_sd_table_entry(hw, info->hmc_info, j,
38061ae650dSJack F Vogel 						   info->entry_type,
38161ae650dSJack F Vogel 						   sd_size);
38261ae650dSJack F Vogel 		if (I40E_SUCCESS != ret_code)
38361ae650dSJack F Vogel 			goto exit_sd_error;
38461ae650dSJack F Vogel 		sd_entry = &info->hmc_info->sd_table.sd_entry[j];
38561ae650dSJack F Vogel 		if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) {
38661ae650dSJack F Vogel 			/* check if all the pds in this sd are valid. If not,
38761ae650dSJack F Vogel 			 * allocate a page and initialize it.
38861ae650dSJack F Vogel 			 */
38961ae650dSJack F Vogel 
39061ae650dSJack F Vogel 			/* find pd_idx and pd_lmt in this sd */
39161ae650dSJack F Vogel 			pd_idx1 = max(pd_idx, (j * I40E_HMC_MAX_BP_COUNT));
39261ae650dSJack F Vogel 			pd_lmt1 = min(pd_lmt,
39361ae650dSJack F Vogel 				      ((j + 1) * I40E_HMC_MAX_BP_COUNT));
39461ae650dSJack F Vogel 			for (i = pd_idx1; i < pd_lmt1; i++) {
39561ae650dSJack F Vogel 				/* update the pd table entry */
39661ae650dSJack F Vogel 				ret_code = i40e_add_pd_table_entry(hw,
39761ae650dSJack F Vogel 								info->hmc_info,
39861ae650dSJack F Vogel 								i);
39961ae650dSJack F Vogel 				if (I40E_SUCCESS != ret_code) {
40061ae650dSJack F Vogel 					pd_error = TRUE;
40161ae650dSJack F Vogel 					break;
40261ae650dSJack F Vogel 				}
40361ae650dSJack F Vogel 			}
40461ae650dSJack F Vogel 			if (pd_error) {
40561ae650dSJack F Vogel 				/* remove the backing pages from pd_idx1 to i */
40661ae650dSJack F Vogel 				while (i && (i > pd_idx1)) {
40761ae650dSJack F Vogel 					i40e_remove_pd_bp(hw, info->hmc_info,
40861ae650dSJack F Vogel 							  (i - 1));
40961ae650dSJack F Vogel 					i--;
41061ae650dSJack F Vogel 				}
41161ae650dSJack F Vogel 			}
41261ae650dSJack F Vogel 		}
41361ae650dSJack F Vogel 		if (!sd_entry->valid) {
41461ae650dSJack F Vogel 			sd_entry->valid = TRUE;
41561ae650dSJack F Vogel 			switch (sd_entry->entry_type) {
41661ae650dSJack F Vogel 			case I40E_SD_TYPE_PAGED:
41761ae650dSJack F Vogel 				I40E_SET_PF_SD_ENTRY(hw,
41861ae650dSJack F Vogel 					sd_entry->u.pd_table.pd_page_addr.pa,
41961ae650dSJack F Vogel 					j, sd_entry->entry_type);
42061ae650dSJack F Vogel 				break;
42161ae650dSJack F Vogel 			case I40E_SD_TYPE_DIRECT:
42261ae650dSJack F Vogel 				I40E_SET_PF_SD_ENTRY(hw, sd_entry->u.bp.addr.pa,
42361ae650dSJack F Vogel 						     j, sd_entry->entry_type);
42461ae650dSJack F Vogel 				break;
42561ae650dSJack F Vogel 			default:
42661ae650dSJack F Vogel 				ret_code = I40E_ERR_INVALID_SD_TYPE;
42761ae650dSJack F Vogel 				goto exit;
42861ae650dSJack F Vogel 			}
42961ae650dSJack F Vogel 		}
43061ae650dSJack F Vogel 	}
43161ae650dSJack F Vogel 	goto exit;
43261ae650dSJack F Vogel 
43361ae650dSJack F Vogel exit_sd_error:
43461ae650dSJack F Vogel 	/* cleanup for sd entries from j to sd_idx */
43561ae650dSJack F Vogel 	while (j && (j > sd_idx)) {
43661ae650dSJack F Vogel 		sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1];
43761ae650dSJack F Vogel 		switch (sd_entry->entry_type) {
43861ae650dSJack F Vogel 		case I40E_SD_TYPE_PAGED:
43961ae650dSJack F Vogel 			pd_idx1 = max(pd_idx,
44061ae650dSJack F Vogel 				      ((j - 1) * I40E_HMC_MAX_BP_COUNT));
44161ae650dSJack F Vogel 			pd_lmt1 = min(pd_lmt, (j * I40E_HMC_MAX_BP_COUNT));
44261ae650dSJack F Vogel 			for (i = pd_idx1; i < pd_lmt1; i++) {
44361ae650dSJack F Vogel 				i40e_remove_pd_bp(hw, info->hmc_info, i);
44461ae650dSJack F Vogel 			}
44561ae650dSJack F Vogel 			i40e_remove_pd_page(hw, info->hmc_info, (j - 1));
44661ae650dSJack F Vogel 			break;
44761ae650dSJack F Vogel 		case I40E_SD_TYPE_DIRECT:
44861ae650dSJack F Vogel 			i40e_remove_sd_bp(hw, info->hmc_info, (j - 1));
44961ae650dSJack F Vogel 			break;
45061ae650dSJack F Vogel 		default:
45161ae650dSJack F Vogel 			ret_code = I40E_ERR_INVALID_SD_TYPE;
45261ae650dSJack F Vogel 			break;
45361ae650dSJack F Vogel 		}
45461ae650dSJack F Vogel 		j--;
45561ae650dSJack F Vogel 	}
45661ae650dSJack F Vogel exit:
45761ae650dSJack F Vogel 	return ret_code;
45861ae650dSJack F Vogel }
45961ae650dSJack F Vogel 
46061ae650dSJack F Vogel /**
46161ae650dSJack F Vogel  * i40e_configure_lan_hmc - prepare the HMC backing store
46261ae650dSJack F Vogel  * @hw: pointer to the hw structure
46361ae650dSJack F Vogel  * @model: the model for the layout of the SD/PD tables
46461ae650dSJack F Vogel  *
46561ae650dSJack F Vogel  * - This function will be called once per physical function initialization.
46661ae650dSJack F Vogel  * - This function will be called after i40e_init_lan_hmc() and before
46761ae650dSJack F Vogel  *   any LAN/FCoE HMC objects can be created.
46861ae650dSJack F Vogel  **/
46961ae650dSJack F Vogel enum i40e_status_code i40e_configure_lan_hmc(struct i40e_hw *hw,
47061ae650dSJack F Vogel 					     enum i40e_hmc_model model)
47161ae650dSJack F Vogel {
47261ae650dSJack F Vogel 	struct i40e_hmc_lan_create_obj_info info;
47361ae650dSJack F Vogel 	u8 hmc_fn_id = hw->hmc.hmc_fn_id;
47461ae650dSJack F Vogel 	struct i40e_hmc_obj_info *obj;
47561ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
47661ae650dSJack F Vogel 
47761ae650dSJack F Vogel 	/* Initialize part of the create object info struct */
47861ae650dSJack F Vogel 	info.hmc_info = &hw->hmc;
47961ae650dSJack F Vogel 	info.rsrc_type = I40E_HMC_LAN_FULL;
48061ae650dSJack F Vogel 	info.start_idx = 0;
48161ae650dSJack F Vogel 	info.direct_mode_sz = hw->hmc.hmc_obj[I40E_HMC_LAN_FULL].size;
48261ae650dSJack F Vogel 
48361ae650dSJack F Vogel 	/* Build the SD entry for the LAN objects */
48461ae650dSJack F Vogel 	switch (model) {
48561ae650dSJack F Vogel 	case I40E_HMC_MODEL_DIRECT_PREFERRED:
48661ae650dSJack F Vogel 	case I40E_HMC_MODEL_DIRECT_ONLY:
48761ae650dSJack F Vogel 		info.entry_type = I40E_SD_TYPE_DIRECT;
48861ae650dSJack F Vogel 		/* Make one big object, a single SD */
48961ae650dSJack F Vogel 		info.count = 1;
49061ae650dSJack F Vogel 		ret_code = i40e_create_lan_hmc_object(hw, &info);
49161ae650dSJack F Vogel 		if ((ret_code != I40E_SUCCESS) && (model == I40E_HMC_MODEL_DIRECT_PREFERRED))
49261ae650dSJack F Vogel 			goto try_type_paged;
49361ae650dSJack F Vogel 		else if (ret_code != I40E_SUCCESS)
49461ae650dSJack F Vogel 			goto configure_lan_hmc_out;
49561ae650dSJack F Vogel 		/* else clause falls through the break */
49661ae650dSJack F Vogel 		break;
49761ae650dSJack F Vogel 	case I40E_HMC_MODEL_PAGED_ONLY:
49861ae650dSJack F Vogel try_type_paged:
49961ae650dSJack F Vogel 		info.entry_type = I40E_SD_TYPE_PAGED;
50061ae650dSJack F Vogel 		/* Make one big object in the PD table */
50161ae650dSJack F Vogel 		info.count = 1;
50261ae650dSJack F Vogel 		ret_code = i40e_create_lan_hmc_object(hw, &info);
50361ae650dSJack F Vogel 		if (ret_code != I40E_SUCCESS)
50461ae650dSJack F Vogel 			goto configure_lan_hmc_out;
50561ae650dSJack F Vogel 		break;
50661ae650dSJack F Vogel 	default:
50761ae650dSJack F Vogel 		/* unsupported type */
50861ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_SD_TYPE;
50961ae650dSJack F Vogel 		DEBUGOUT1("i40e_configure_lan_hmc: Unknown SD type: %d\n",
51061ae650dSJack F Vogel 			  ret_code);
51161ae650dSJack F Vogel 		goto configure_lan_hmc_out;
51261ae650dSJack F Vogel 	}
51361ae650dSJack F Vogel 
51461ae650dSJack F Vogel 	/* Configure and program the FPM registers so objects can be created */
51561ae650dSJack F Vogel 
51661ae650dSJack F Vogel 	/* Tx contexts */
51761ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX];
51861ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANTXBASE(hmc_fn_id),
51961ae650dSJack F Vogel 	     (u32)((obj->base & I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK) / 512));
52061ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANTXCNT(hmc_fn_id), obj->cnt);
52161ae650dSJack F Vogel 
52261ae650dSJack F Vogel 	/* Rx contexts */
52361ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX];
52461ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANRXBASE(hmc_fn_id),
52561ae650dSJack F Vogel 	     (u32)((obj->base & I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK) / 512));
52661ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANRXCNT(hmc_fn_id), obj->cnt);
52761ae650dSJack F Vogel 
52861ae650dSJack F Vogel 	/* FCoE contexts */
52961ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX];
53061ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEDDPBASE(hmc_fn_id),
53161ae650dSJack F Vogel 	 (u32)((obj->base & I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK) / 512));
53261ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEDDPCNT(hmc_fn_id), obj->cnt);
53361ae650dSJack F Vogel 
53461ae650dSJack F Vogel 	/* FCoE filters */
53561ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT];
53661ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEFBASE(hmc_fn_id),
53761ae650dSJack F Vogel 	     (u32)((obj->base & I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK) / 512));
53861ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEFCNT(hmc_fn_id), obj->cnt);
53961ae650dSJack F Vogel 
54061ae650dSJack F Vogel configure_lan_hmc_out:
54161ae650dSJack F Vogel 	return ret_code;
54261ae650dSJack F Vogel }
54361ae650dSJack F Vogel 
54461ae650dSJack F Vogel /**
54561ae650dSJack F Vogel  * i40e_delete_hmc_object - remove hmc objects
54661ae650dSJack F Vogel  * @hw: pointer to the HW structure
54761ae650dSJack F Vogel  * @info: pointer to i40e_hmc_delete_obj_info struct
54861ae650dSJack F Vogel  *
54961ae650dSJack F Vogel  * This will de-populate the SDs and PDs.  It frees
55061ae650dSJack F Vogel  * the memory for PDS and backing storage.  After this function is returned,
55161ae650dSJack F Vogel  * caller should deallocate memory allocated previously for
55261ae650dSJack F Vogel  * book-keeping information about PDs and backing storage.
55361ae650dSJack F Vogel  **/
55461ae650dSJack F Vogel enum i40e_status_code i40e_delete_lan_hmc_object(struct i40e_hw *hw,
55561ae650dSJack F Vogel 				struct i40e_hmc_lan_delete_obj_info *info)
55661ae650dSJack F Vogel {
55761ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
55861ae650dSJack F Vogel 	struct i40e_hmc_pd_table *pd_table;
55961ae650dSJack F Vogel 	u32 pd_idx, pd_lmt, rel_pd_idx;
56061ae650dSJack F Vogel 	u32 sd_idx, sd_lmt;
56161ae650dSJack F Vogel 	u32 i, j;
56261ae650dSJack F Vogel 
56361ae650dSJack F Vogel 	if (NULL == info) {
56461ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
56561ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad info ptr\n");
56661ae650dSJack F Vogel 		goto exit;
56761ae650dSJack F Vogel 	}
56861ae650dSJack F Vogel 	if (NULL == info->hmc_info) {
56961ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
57061ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad info->hmc_info ptr\n");
57161ae650dSJack F Vogel 		goto exit;
57261ae650dSJack F Vogel 	}
57361ae650dSJack F Vogel 	if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) {
57461ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
57561ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->signature\n");
57661ae650dSJack F Vogel 		goto exit;
57761ae650dSJack F Vogel 	}
57861ae650dSJack F Vogel 
57961ae650dSJack F Vogel 	if (NULL == info->hmc_info->sd_table.sd_entry) {
58061ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
58161ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad sd_entry\n");
58261ae650dSJack F Vogel 		goto exit;
58361ae650dSJack F Vogel 	}
58461ae650dSJack F Vogel 
58561ae650dSJack F Vogel 	if (NULL == info->hmc_info->hmc_obj) {
58661ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
58761ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->hmc_obj\n");
58861ae650dSJack F Vogel 		goto exit;
58961ae650dSJack F Vogel 	}
59061ae650dSJack F Vogel 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
59161ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
59261ae650dSJack F Vogel 		DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n",
59361ae650dSJack F Vogel 			  ret_code);
59461ae650dSJack F Vogel 		goto exit;
59561ae650dSJack F Vogel 	}
59661ae650dSJack F Vogel 
59761ae650dSJack F Vogel 	if ((info->start_idx + info->count) >
59861ae650dSJack F Vogel 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
59961ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
60061ae650dSJack F Vogel 		DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n",
60161ae650dSJack F Vogel 			  ret_code);
60261ae650dSJack F Vogel 		goto exit;
60361ae650dSJack F Vogel 	}
60461ae650dSJack F Vogel 
60561ae650dSJack F Vogel 	I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
60661ae650dSJack F Vogel 				 info->start_idx, info->count, &pd_idx,
60761ae650dSJack F Vogel 				 &pd_lmt);
60861ae650dSJack F Vogel 
60961ae650dSJack F Vogel 	for (j = pd_idx; j < pd_lmt; j++) {
61061ae650dSJack F Vogel 		sd_idx = j / I40E_HMC_PD_CNT_IN_SD;
61161ae650dSJack F Vogel 
61261ae650dSJack F Vogel 		if (I40E_SD_TYPE_PAGED !=
61361ae650dSJack F Vogel 		    info->hmc_info->sd_table.sd_entry[sd_idx].entry_type)
61461ae650dSJack F Vogel 			continue;
61561ae650dSJack F Vogel 
61661ae650dSJack F Vogel 		rel_pd_idx = j % I40E_HMC_PD_CNT_IN_SD;
61761ae650dSJack F Vogel 
61861ae650dSJack F Vogel 		pd_table =
61961ae650dSJack F Vogel 			&info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
62061ae650dSJack F Vogel 		if (pd_table->pd_entry[rel_pd_idx].valid) {
62161ae650dSJack F Vogel 			ret_code = i40e_remove_pd_bp(hw, info->hmc_info, j);
62261ae650dSJack F Vogel 			if (I40E_SUCCESS != ret_code)
62361ae650dSJack F Vogel 				goto exit;
62461ae650dSJack F Vogel 		}
62561ae650dSJack F Vogel 	}
62661ae650dSJack F Vogel 
62761ae650dSJack F Vogel 	/* find sd index and limit */
62861ae650dSJack F Vogel 	I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
62961ae650dSJack F Vogel 				 info->start_idx, info->count,
63061ae650dSJack F Vogel 				 &sd_idx, &sd_lmt);
63161ae650dSJack F Vogel 	if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
63261ae650dSJack F Vogel 	    sd_lmt > info->hmc_info->sd_table.sd_cnt) {
63361ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_SD_INDEX;
63461ae650dSJack F Vogel 		goto exit;
63561ae650dSJack F Vogel 	}
63661ae650dSJack F Vogel 
63761ae650dSJack F Vogel 	for (i = sd_idx; i < sd_lmt; i++) {
63861ae650dSJack F Vogel 		if (!info->hmc_info->sd_table.sd_entry[i].valid)
63961ae650dSJack F Vogel 			continue;
64061ae650dSJack F Vogel 		switch (info->hmc_info->sd_table.sd_entry[i].entry_type) {
64161ae650dSJack F Vogel 		case I40E_SD_TYPE_DIRECT:
64261ae650dSJack F Vogel 			ret_code = i40e_remove_sd_bp(hw, info->hmc_info, i);
64361ae650dSJack F Vogel 			if (I40E_SUCCESS != ret_code)
64461ae650dSJack F Vogel 				goto exit;
64561ae650dSJack F Vogel 			break;
64661ae650dSJack F Vogel 		case I40E_SD_TYPE_PAGED:
64761ae650dSJack F Vogel 			ret_code = i40e_remove_pd_page(hw, info->hmc_info, i);
64861ae650dSJack F Vogel 			if (I40E_SUCCESS != ret_code)
64961ae650dSJack F Vogel 				goto exit;
65061ae650dSJack F Vogel 			break;
65161ae650dSJack F Vogel 		default:
65261ae650dSJack F Vogel 			break;
65361ae650dSJack F Vogel 		}
65461ae650dSJack F Vogel 	}
65561ae650dSJack F Vogel exit:
65661ae650dSJack F Vogel 	return ret_code;
65761ae650dSJack F Vogel }
65861ae650dSJack F Vogel 
65961ae650dSJack F Vogel /**
66061ae650dSJack F Vogel  * i40e_shutdown_lan_hmc - Remove HMC backing store, free allocated memory
66161ae650dSJack F Vogel  * @hw: pointer to the hw structure
66261ae650dSJack F Vogel  *
66361ae650dSJack F Vogel  * This must be called by drivers as they are shutting down and being
66461ae650dSJack F Vogel  * removed from the OS.
66561ae650dSJack F Vogel  **/
66661ae650dSJack F Vogel enum i40e_status_code i40e_shutdown_lan_hmc(struct i40e_hw *hw)
66761ae650dSJack F Vogel {
66861ae650dSJack F Vogel 	struct i40e_hmc_lan_delete_obj_info info;
66961ae650dSJack F Vogel 	enum i40e_status_code ret_code;
67061ae650dSJack F Vogel 
67161ae650dSJack F Vogel 	info.hmc_info = &hw->hmc;
67261ae650dSJack F Vogel 	info.rsrc_type = I40E_HMC_LAN_FULL;
67361ae650dSJack F Vogel 	info.start_idx = 0;
67461ae650dSJack F Vogel 	info.count = 1;
67561ae650dSJack F Vogel 
67661ae650dSJack F Vogel 	/* delete the object */
67761ae650dSJack F Vogel 	ret_code = i40e_delete_lan_hmc_object(hw, &info);
67861ae650dSJack F Vogel 
67961ae650dSJack F Vogel 	/* free the SD table entry for LAN */
68061ae650dSJack F Vogel 	i40e_free_virt_mem(hw, &hw->hmc.sd_table.addr);
68161ae650dSJack F Vogel 	hw->hmc.sd_table.sd_cnt = 0;
68261ae650dSJack F Vogel 	hw->hmc.sd_table.sd_entry = NULL;
68361ae650dSJack F Vogel 
68461ae650dSJack F Vogel 	/* free memory used for hmc_obj */
68561ae650dSJack F Vogel 	i40e_free_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem);
68661ae650dSJack F Vogel 	hw->hmc.hmc_obj = NULL;
68761ae650dSJack F Vogel 
68861ae650dSJack F Vogel 	return ret_code;
68961ae650dSJack F Vogel }
69061ae650dSJack F Vogel 
69161ae650dSJack F Vogel #define I40E_HMC_STORE(_struct, _ele)		\
69261ae650dSJack F Vogel 	offsetof(struct _struct, _ele),		\
69361ae650dSJack F Vogel 	FIELD_SIZEOF(struct _struct, _ele)
69461ae650dSJack F Vogel 
69561ae650dSJack F Vogel struct i40e_context_ele {
69661ae650dSJack F Vogel 	u16 offset;
69761ae650dSJack F Vogel 	u16 size_of;
69861ae650dSJack F Vogel 	u16 width;
69961ae650dSJack F Vogel 	u16 lsb;
70061ae650dSJack F Vogel };
70161ae650dSJack F Vogel 
70261ae650dSJack F Vogel /* LAN Tx Queue Context */
70361ae650dSJack F Vogel static struct i40e_context_ele i40e_hmc_txq_ce_info[] = {
70461ae650dSJack F Vogel 					     /* Field      Width    LSB */
70561ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, head),           13,      0 },
70661ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, new_context),     1,     30 },
70761ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, base),           57,     32 },
70861ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, fc_ena),          1,     89 },
70961ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, timesync_ena),    1,     90 },
71061ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, fd_ena),          1,     91 },
71161ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, alt_vlan_ena),    1,     92 },
71261ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, cpuid),           8,     96 },
71361ae650dSJack F Vogel /* line 1 */
71461ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, thead_wb),       13,  0 + 128 },
71561ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_ena),     1, 32 + 128 },
71661ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, qlen),           13, 33 + 128 },
71761ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, tphrdesc_ena),    1, 46 + 128 },
71861ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, tphrpacket_ena),  1, 47 + 128 },
71961ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, tphwdesc_ena),    1, 48 + 128 },
72061ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_addr),   64, 64 + 128 },
72161ae650dSJack F Vogel /* line 7 */
72261ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, crc),            32,  0 + (7 * 128) },
72361ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist),        10, 84 + (7 * 128) },
72461ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist_act),     1, 94 + (7 * 128) },
72561ae650dSJack F Vogel 	{ 0 }
72661ae650dSJack F Vogel };
72761ae650dSJack F Vogel 
72861ae650dSJack F Vogel /* LAN Rx Queue Context */
72961ae650dSJack F Vogel static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = {
73061ae650dSJack F Vogel 					 /* Field      Width    LSB */
73161ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, head),        13,	0   },
73261ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, cpuid),        8,	13  },
73361ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, base),        57,	32  },
73461ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, qlen),        13,	89  },
73561ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, dbuff),        7,	102 },
73661ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, hbuff),        5,	109 },
73761ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, dtype),        2,	114 },
73861ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, dsize),        1,	116 },
73961ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, crcstrip),     1,	117 },
74061ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, fc_ena),       1,	118 },
74161ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, l2tsel),       1,	119 },
74261ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_0),     4,	120 },
74361ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_1),     2,	124 },
74461ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, showiv),       1,	127 },
74561ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, rxmax),       14,	174 },
74661ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphrdesc_ena), 1,	193 },
74761ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphwdesc_ena), 1,	194 },
74861ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphdata_ena),  1,	195 },
74961ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphhead_ena),  1,	196 },
75061ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, lrxqthresh),   3,	198 },
75161ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, prefena),      1,	201 },
75261ae650dSJack F Vogel 	{ 0 }
75361ae650dSJack F Vogel };
75461ae650dSJack F Vogel 
75561ae650dSJack F Vogel /**
75661ae650dSJack F Vogel  * i40e_write_byte - replace HMC context byte
75761ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
75861ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
75961ae650dSJack F Vogel  * @src: the struct to be read from
76061ae650dSJack F Vogel  **/
76161ae650dSJack F Vogel static void i40e_write_byte(u8 *hmc_bits,
76261ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
76361ae650dSJack F Vogel 			    u8 *src)
76461ae650dSJack F Vogel {
76561ae650dSJack F Vogel 	u8 src_byte, dest_byte, mask;
76661ae650dSJack F Vogel 	u8 *from, *dest;
76761ae650dSJack F Vogel 	u16 shift_width;
76861ae650dSJack F Vogel 
76961ae650dSJack F Vogel 	/* copy from the next struct field */
77061ae650dSJack F Vogel 	from = src + ce_info->offset;
77161ae650dSJack F Vogel 
77261ae650dSJack F Vogel 	/* prepare the bits and mask */
77361ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
77461ae650dSJack F Vogel 	mask = ((u8)1 << ce_info->width) - 1;
77561ae650dSJack F Vogel 
77661ae650dSJack F Vogel 	src_byte = *from;
77761ae650dSJack F Vogel 	src_byte &= mask;
77861ae650dSJack F Vogel 
77961ae650dSJack F Vogel 	/* shift to correct alignment */
78061ae650dSJack F Vogel 	mask <<= shift_width;
78161ae650dSJack F Vogel 	src_byte <<= shift_width;
78261ae650dSJack F Vogel 
78361ae650dSJack F Vogel 	/* get the current bits from the target bit string */
78461ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
78561ae650dSJack F Vogel 
78661ae650dSJack F Vogel 	i40e_memcpy(&dest_byte, dest, sizeof(dest_byte), I40E_DMA_TO_NONDMA);
78761ae650dSJack F Vogel 
78861ae650dSJack F Vogel 	dest_byte &= ~mask;	/* get the bits not changing */
78961ae650dSJack F Vogel 	dest_byte |= src_byte;	/* add in the new bits */
79061ae650dSJack F Vogel 
79161ae650dSJack F Vogel 	/* put it all back */
79261ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA);
79361ae650dSJack F Vogel }
79461ae650dSJack F Vogel 
79561ae650dSJack F Vogel /**
79661ae650dSJack F Vogel  * i40e_write_word - replace HMC context word
79761ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
79861ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
79961ae650dSJack F Vogel  * @src: the struct to be read from
80061ae650dSJack F Vogel  **/
80161ae650dSJack F Vogel static void i40e_write_word(u8 *hmc_bits,
80261ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
80361ae650dSJack F Vogel 			    u8 *src)
80461ae650dSJack F Vogel {
80561ae650dSJack F Vogel 	u16 src_word, mask;
80661ae650dSJack F Vogel 	u8 *from, *dest;
80761ae650dSJack F Vogel 	u16 shift_width;
80861ae650dSJack F Vogel 	__le16 dest_word;
80961ae650dSJack F Vogel 
81061ae650dSJack F Vogel 	/* copy from the next struct field */
81161ae650dSJack F Vogel 	from = src + ce_info->offset;
81261ae650dSJack F Vogel 
81361ae650dSJack F Vogel 	/* prepare the bits and mask */
81461ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
81561ae650dSJack F Vogel 	mask = ((u16)1 << ce_info->width) - 1;
81661ae650dSJack F Vogel 
81761ae650dSJack F Vogel 	/* don't swizzle the bits until after the mask because the mask bits
81861ae650dSJack F Vogel 	 * will be in a different bit position on big endian machines
81961ae650dSJack F Vogel 	 */
82061ae650dSJack F Vogel 	src_word = *(u16 *)from;
82161ae650dSJack F Vogel 	src_word &= mask;
82261ae650dSJack F Vogel 
82361ae650dSJack F Vogel 	/* shift to correct alignment */
82461ae650dSJack F Vogel 	mask <<= shift_width;
82561ae650dSJack F Vogel 	src_word <<= shift_width;
82661ae650dSJack F Vogel 
82761ae650dSJack F Vogel 	/* get the current bits from the target bit string */
82861ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
82961ae650dSJack F Vogel 
83061ae650dSJack F Vogel 	i40e_memcpy(&dest_word, dest, sizeof(dest_word), I40E_DMA_TO_NONDMA);
83161ae650dSJack F Vogel 
83261ae650dSJack F Vogel 	dest_word &= ~(CPU_TO_LE16(mask));	/* get the bits not changing */
83361ae650dSJack F Vogel 	dest_word |= CPU_TO_LE16(src_word);	/* add in the new bits */
83461ae650dSJack F Vogel 
83561ae650dSJack F Vogel 	/* put it all back */
83661ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA);
83761ae650dSJack F Vogel }
83861ae650dSJack F Vogel 
83961ae650dSJack F Vogel /**
84061ae650dSJack F Vogel  * i40e_write_dword - replace HMC context dword
84161ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
84261ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
84361ae650dSJack F Vogel  * @src: the struct to be read from
84461ae650dSJack F Vogel  **/
84561ae650dSJack F Vogel static void i40e_write_dword(u8 *hmc_bits,
84661ae650dSJack F Vogel 			     struct i40e_context_ele *ce_info,
84761ae650dSJack F Vogel 			     u8 *src)
84861ae650dSJack F Vogel {
84961ae650dSJack F Vogel 	u32 src_dword, mask;
85061ae650dSJack F Vogel 	u8 *from, *dest;
85161ae650dSJack F Vogel 	u16 shift_width;
85261ae650dSJack F Vogel 	__le32 dest_dword;
85361ae650dSJack F Vogel 
85461ae650dSJack F Vogel 	/* copy from the next struct field */
85561ae650dSJack F Vogel 	from = src + ce_info->offset;
85661ae650dSJack F Vogel 
85761ae650dSJack F Vogel 	/* prepare the bits and mask */
85861ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
85961ae650dSJack F Vogel 
86061ae650dSJack F Vogel 	/* if the field width is exactly 32 on an x86 machine, then the shift
86161ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
86261ae650dSJack F Vogel 	 * to 5 bits so the shift will do nothing
86361ae650dSJack F Vogel 	 */
86461ae650dSJack F Vogel 	if (ce_info->width < 32)
86561ae650dSJack F Vogel 		mask = ((u32)1 << ce_info->width) - 1;
86661ae650dSJack F Vogel 	else
867*f247dc25SJack F Vogel 		mask = ~(u32)0;
86861ae650dSJack F Vogel 
86961ae650dSJack F Vogel 	/* don't swizzle the bits until after the mask because the mask bits
87061ae650dSJack F Vogel 	 * will be in a different bit position on big endian machines
87161ae650dSJack F Vogel 	 */
87261ae650dSJack F Vogel 	src_dword = *(u32 *)from;
87361ae650dSJack F Vogel 	src_dword &= mask;
87461ae650dSJack F Vogel 
87561ae650dSJack F Vogel 	/* shift to correct alignment */
87661ae650dSJack F Vogel 	mask <<= shift_width;
87761ae650dSJack F Vogel 	src_dword <<= shift_width;
87861ae650dSJack F Vogel 
87961ae650dSJack F Vogel 	/* get the current bits from the target bit string */
88061ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
88161ae650dSJack F Vogel 
88261ae650dSJack F Vogel 	i40e_memcpy(&dest_dword, dest, sizeof(dest_dword), I40E_DMA_TO_NONDMA);
88361ae650dSJack F Vogel 
88461ae650dSJack F Vogel 	dest_dword &= ~(CPU_TO_LE32(mask));	/* get the bits not changing */
88561ae650dSJack F Vogel 	dest_dword |= CPU_TO_LE32(src_dword);	/* add in the new bits */
88661ae650dSJack F Vogel 
88761ae650dSJack F Vogel 	/* put it all back */
88861ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_dword, sizeof(dest_dword), I40E_NONDMA_TO_DMA);
88961ae650dSJack F Vogel }
89061ae650dSJack F Vogel 
89161ae650dSJack F Vogel /**
89261ae650dSJack F Vogel  * i40e_write_qword - replace HMC context qword
89361ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
89461ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
89561ae650dSJack F Vogel  * @src: the struct to be read from
89661ae650dSJack F Vogel  **/
89761ae650dSJack F Vogel static void i40e_write_qword(u8 *hmc_bits,
89861ae650dSJack F Vogel 			     struct i40e_context_ele *ce_info,
89961ae650dSJack F Vogel 			     u8 *src)
90061ae650dSJack F Vogel {
90161ae650dSJack F Vogel 	u64 src_qword, mask;
90261ae650dSJack F Vogel 	u8 *from, *dest;
90361ae650dSJack F Vogel 	u16 shift_width;
90461ae650dSJack F Vogel 	__le64 dest_qword;
90561ae650dSJack F Vogel 
90661ae650dSJack F Vogel 	/* copy from the next struct field */
90761ae650dSJack F Vogel 	from = src + ce_info->offset;
90861ae650dSJack F Vogel 
90961ae650dSJack F Vogel 	/* prepare the bits and mask */
91061ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
91161ae650dSJack F Vogel 
91261ae650dSJack F Vogel 	/* if the field width is exactly 64 on an x86 machine, then the shift
91361ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
91461ae650dSJack F Vogel 	 * to 6 bits so the shift will do nothing
91561ae650dSJack F Vogel 	 */
91661ae650dSJack F Vogel 	if (ce_info->width < 64)
91761ae650dSJack F Vogel 		mask = ((u64)1 << ce_info->width) - 1;
91861ae650dSJack F Vogel 	else
919*f247dc25SJack F Vogel 		mask = ~(u64)0;
92061ae650dSJack F Vogel 
92161ae650dSJack F Vogel 	/* don't swizzle the bits until after the mask because the mask bits
92261ae650dSJack F Vogel 	 * will be in a different bit position on big endian machines
92361ae650dSJack F Vogel 	 */
92461ae650dSJack F Vogel 	src_qword = *(u64 *)from;
92561ae650dSJack F Vogel 	src_qword &= mask;
92661ae650dSJack F Vogel 
92761ae650dSJack F Vogel 	/* shift to correct alignment */
92861ae650dSJack F Vogel 	mask <<= shift_width;
92961ae650dSJack F Vogel 	src_qword <<= shift_width;
93061ae650dSJack F Vogel 
93161ae650dSJack F Vogel 	/* get the current bits from the target bit string */
93261ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
93361ae650dSJack F Vogel 
93461ae650dSJack F Vogel 	i40e_memcpy(&dest_qword, dest, sizeof(dest_qword), I40E_DMA_TO_NONDMA);
93561ae650dSJack F Vogel 
93661ae650dSJack F Vogel 	dest_qword &= ~(CPU_TO_LE64(mask));	/* get the bits not changing */
93761ae650dSJack F Vogel 	dest_qword |= CPU_TO_LE64(src_qword);	/* add in the new bits */
93861ae650dSJack F Vogel 
93961ae650dSJack F Vogel 	/* put it all back */
94061ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_qword, sizeof(dest_qword), I40E_NONDMA_TO_DMA);
94161ae650dSJack F Vogel }
94261ae650dSJack F Vogel 
94361ae650dSJack F Vogel /**
94461ae650dSJack F Vogel  * i40e_read_byte - read HMC context byte into struct
94561ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
94661ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
94761ae650dSJack F Vogel  * @dest: the struct to be filled
94861ae650dSJack F Vogel  **/
94961ae650dSJack F Vogel static void i40e_read_byte(u8 *hmc_bits,
95061ae650dSJack F Vogel 			   struct i40e_context_ele *ce_info,
95161ae650dSJack F Vogel 			   u8 *dest)
95261ae650dSJack F Vogel {
95361ae650dSJack F Vogel 	u8 dest_byte, mask;
95461ae650dSJack F Vogel 	u8 *src, *target;
95561ae650dSJack F Vogel 	u16 shift_width;
95661ae650dSJack F Vogel 
95761ae650dSJack F Vogel 	/* prepare the bits and mask */
95861ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
95961ae650dSJack F Vogel 	mask = ((u8)1 << ce_info->width) - 1;
96061ae650dSJack F Vogel 
96161ae650dSJack F Vogel 	/* shift to correct alignment */
96261ae650dSJack F Vogel 	mask <<= shift_width;
96361ae650dSJack F Vogel 
96461ae650dSJack F Vogel 	/* get the current bits from the src bit string */
96561ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
96661ae650dSJack F Vogel 
96761ae650dSJack F Vogel 	i40e_memcpy(&dest_byte, src, sizeof(dest_byte), I40E_DMA_TO_NONDMA);
96861ae650dSJack F Vogel 
96961ae650dSJack F Vogel 	dest_byte &= ~(mask);
97061ae650dSJack F Vogel 
97161ae650dSJack F Vogel 	dest_byte >>= shift_width;
97261ae650dSJack F Vogel 
97361ae650dSJack F Vogel 	/* get the address from the struct field */
97461ae650dSJack F Vogel 	target = dest + ce_info->offset;
97561ae650dSJack F Vogel 
97661ae650dSJack F Vogel 	/* put it back in the struct */
97761ae650dSJack F Vogel 	i40e_memcpy(target, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA);
97861ae650dSJack F Vogel }
97961ae650dSJack F Vogel 
98061ae650dSJack F Vogel /**
98161ae650dSJack F Vogel  * i40e_read_word - read HMC context word into struct
98261ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
98361ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
98461ae650dSJack F Vogel  * @dest: the struct to be filled
98561ae650dSJack F Vogel  **/
98661ae650dSJack F Vogel static void i40e_read_word(u8 *hmc_bits,
98761ae650dSJack F Vogel 			   struct i40e_context_ele *ce_info,
98861ae650dSJack F Vogel 			   u8 *dest)
98961ae650dSJack F Vogel {
99061ae650dSJack F Vogel 	u16 dest_word, mask;
99161ae650dSJack F Vogel 	u8 *src, *target;
99261ae650dSJack F Vogel 	u16 shift_width;
99361ae650dSJack F Vogel 	__le16 src_word;
99461ae650dSJack F Vogel 
99561ae650dSJack F Vogel 	/* prepare the bits and mask */
99661ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
99761ae650dSJack F Vogel 	mask = ((u16)1 << ce_info->width) - 1;
99861ae650dSJack F Vogel 
99961ae650dSJack F Vogel 	/* shift to correct alignment */
100061ae650dSJack F Vogel 	mask <<= shift_width;
100161ae650dSJack F Vogel 
100261ae650dSJack F Vogel 	/* get the current bits from the src bit string */
100361ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
100461ae650dSJack F Vogel 
100561ae650dSJack F Vogel 	i40e_memcpy(&src_word, src, sizeof(src_word), I40E_DMA_TO_NONDMA);
100661ae650dSJack F Vogel 
100761ae650dSJack F Vogel 	/* the data in the memory is stored as little endian so mask it
100861ae650dSJack F Vogel 	 * correctly
100961ae650dSJack F Vogel 	 */
101061ae650dSJack F Vogel 	src_word &= ~(CPU_TO_LE16(mask));
101161ae650dSJack F Vogel 
101261ae650dSJack F Vogel 	/* get the data back into host order before shifting */
101361ae650dSJack F Vogel 	dest_word = LE16_TO_CPU(src_word);
101461ae650dSJack F Vogel 
101561ae650dSJack F Vogel 	dest_word >>= shift_width;
101661ae650dSJack F Vogel 
101761ae650dSJack F Vogel 	/* get the address from the struct field */
101861ae650dSJack F Vogel 	target = dest + ce_info->offset;
101961ae650dSJack F Vogel 
102061ae650dSJack F Vogel 	/* put it back in the struct */
102161ae650dSJack F Vogel 	i40e_memcpy(target, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA);
102261ae650dSJack F Vogel }
102361ae650dSJack F Vogel 
102461ae650dSJack F Vogel /**
102561ae650dSJack F Vogel  * i40e_read_dword - read HMC context dword into struct
102661ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
102761ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
102861ae650dSJack F Vogel  * @dest: the struct to be filled
102961ae650dSJack F Vogel  **/
103061ae650dSJack F Vogel static void i40e_read_dword(u8 *hmc_bits,
103161ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
103261ae650dSJack F Vogel 			    u8 *dest)
103361ae650dSJack F Vogel {
103461ae650dSJack F Vogel 	u32 dest_dword, mask;
103561ae650dSJack F Vogel 	u8 *src, *target;
103661ae650dSJack F Vogel 	u16 shift_width;
103761ae650dSJack F Vogel 	__le32 src_dword;
103861ae650dSJack F Vogel 
103961ae650dSJack F Vogel 	/* prepare the bits and mask */
104061ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
104161ae650dSJack F Vogel 
104261ae650dSJack F Vogel 	/* if the field width is exactly 32 on an x86 machine, then the shift
104361ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
104461ae650dSJack F Vogel 	 * to 5 bits so the shift will do nothing
104561ae650dSJack F Vogel 	 */
104661ae650dSJack F Vogel 	if (ce_info->width < 32)
104761ae650dSJack F Vogel 		mask = ((u32)1 << ce_info->width) - 1;
104861ae650dSJack F Vogel 	else
1049*f247dc25SJack F Vogel 		mask = ~(u32)0;
105061ae650dSJack F Vogel 
105161ae650dSJack F Vogel 	/* shift to correct alignment */
105261ae650dSJack F Vogel 	mask <<= shift_width;
105361ae650dSJack F Vogel 
105461ae650dSJack F Vogel 	/* get the current bits from the src bit string */
105561ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
105661ae650dSJack F Vogel 
105761ae650dSJack F Vogel 	i40e_memcpy(&src_dword, src, sizeof(src_dword), I40E_DMA_TO_NONDMA);
105861ae650dSJack F Vogel 
105961ae650dSJack F Vogel 	/* the data in the memory is stored as little endian so mask it
106061ae650dSJack F Vogel 	 * correctly
106161ae650dSJack F Vogel 	 */
106261ae650dSJack F Vogel 	src_dword &= ~(CPU_TO_LE32(mask));
106361ae650dSJack F Vogel 
106461ae650dSJack F Vogel 	/* get the data back into host order before shifting */
106561ae650dSJack F Vogel 	dest_dword = LE32_TO_CPU(src_dword);
106661ae650dSJack F Vogel 
106761ae650dSJack F Vogel 	dest_dword >>= shift_width;
106861ae650dSJack F Vogel 
106961ae650dSJack F Vogel 	/* get the address from the struct field */
107061ae650dSJack F Vogel 	target = dest + ce_info->offset;
107161ae650dSJack F Vogel 
107261ae650dSJack F Vogel 	/* put it back in the struct */
107361ae650dSJack F Vogel 	i40e_memcpy(target, &dest_dword, sizeof(dest_dword),
107461ae650dSJack F Vogel 		    I40E_NONDMA_TO_DMA);
107561ae650dSJack F Vogel }
107661ae650dSJack F Vogel 
107761ae650dSJack F Vogel /**
107861ae650dSJack F Vogel  * i40e_read_qword - read HMC context qword into struct
107961ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
108061ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
108161ae650dSJack F Vogel  * @dest: the struct to be filled
108261ae650dSJack F Vogel  **/
108361ae650dSJack F Vogel static void i40e_read_qword(u8 *hmc_bits,
108461ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
108561ae650dSJack F Vogel 			    u8 *dest)
108661ae650dSJack F Vogel {
108761ae650dSJack F Vogel 	u64 dest_qword, mask;
108861ae650dSJack F Vogel 	u8 *src, *target;
108961ae650dSJack F Vogel 	u16 shift_width;
109061ae650dSJack F Vogel 	__le64 src_qword;
109161ae650dSJack F Vogel 
109261ae650dSJack F Vogel 	/* prepare the bits and mask */
109361ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
109461ae650dSJack F Vogel 
109561ae650dSJack F Vogel 	/* if the field width is exactly 64 on an x86 machine, then the shift
109661ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
109761ae650dSJack F Vogel 	 * to 6 bits so the shift will do nothing
109861ae650dSJack F Vogel 	 */
109961ae650dSJack F Vogel 	if (ce_info->width < 64)
110061ae650dSJack F Vogel 		mask = ((u64)1 << ce_info->width) - 1;
110161ae650dSJack F Vogel 	else
1102*f247dc25SJack F Vogel 		mask = ~(u64)0;
110361ae650dSJack F Vogel 
110461ae650dSJack F Vogel 	/* shift to correct alignment */
110561ae650dSJack F Vogel 	mask <<= shift_width;
110661ae650dSJack F Vogel 
110761ae650dSJack F Vogel 	/* get the current bits from the src bit string */
110861ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
110961ae650dSJack F Vogel 
111061ae650dSJack F Vogel 	i40e_memcpy(&src_qword, src, sizeof(src_qword), I40E_DMA_TO_NONDMA);
111161ae650dSJack F Vogel 
111261ae650dSJack F Vogel 	/* the data in the memory is stored as little endian so mask it
111361ae650dSJack F Vogel 	 * correctly
111461ae650dSJack F Vogel 	 */
111561ae650dSJack F Vogel 	src_qword &= ~(CPU_TO_LE64(mask));
111661ae650dSJack F Vogel 
111761ae650dSJack F Vogel 	/* get the data back into host order before shifting */
111861ae650dSJack F Vogel 	dest_qword = LE64_TO_CPU(src_qword);
111961ae650dSJack F Vogel 
112061ae650dSJack F Vogel 	dest_qword >>= shift_width;
112161ae650dSJack F Vogel 
112261ae650dSJack F Vogel 	/* get the address from the struct field */
112361ae650dSJack F Vogel 	target = dest + ce_info->offset;
112461ae650dSJack F Vogel 
112561ae650dSJack F Vogel 	/* put it back in the struct */
112661ae650dSJack F Vogel 	i40e_memcpy(target, &dest_qword, sizeof(dest_qword),
112761ae650dSJack F Vogel 		    I40E_NONDMA_TO_DMA);
112861ae650dSJack F Vogel }
112961ae650dSJack F Vogel 
113061ae650dSJack F Vogel /**
113161ae650dSJack F Vogel  * i40e_get_hmc_context - extract HMC context bits
113261ae650dSJack F Vogel  * @context_bytes: pointer to the context bit array
113361ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
113461ae650dSJack F Vogel  * @dest: the struct to be filled
113561ae650dSJack F Vogel  **/
113661ae650dSJack F Vogel static enum i40e_status_code i40e_get_hmc_context(u8 *context_bytes,
113761ae650dSJack F Vogel 					struct i40e_context_ele *ce_info,
113861ae650dSJack F Vogel 					u8 *dest)
113961ae650dSJack F Vogel {
114061ae650dSJack F Vogel 	int f;
114161ae650dSJack F Vogel 
114261ae650dSJack F Vogel 	for (f = 0; ce_info[f].width != 0; f++) {
114361ae650dSJack F Vogel 		switch (ce_info[f].size_of) {
114461ae650dSJack F Vogel 		case 1:
114561ae650dSJack F Vogel 			i40e_read_byte(context_bytes, &ce_info[f], dest);
114661ae650dSJack F Vogel 			break;
114761ae650dSJack F Vogel 		case 2:
114861ae650dSJack F Vogel 			i40e_read_word(context_bytes, &ce_info[f], dest);
114961ae650dSJack F Vogel 			break;
115061ae650dSJack F Vogel 		case 4:
115161ae650dSJack F Vogel 			i40e_read_dword(context_bytes, &ce_info[f], dest);
115261ae650dSJack F Vogel 			break;
115361ae650dSJack F Vogel 		case 8:
115461ae650dSJack F Vogel 			i40e_read_qword(context_bytes, &ce_info[f], dest);
115561ae650dSJack F Vogel 			break;
115661ae650dSJack F Vogel 		default:
115761ae650dSJack F Vogel 			/* nothing to do, just keep going */
115861ae650dSJack F Vogel 			break;
115961ae650dSJack F Vogel 		}
116061ae650dSJack F Vogel 	}
116161ae650dSJack F Vogel 
116261ae650dSJack F Vogel 	return I40E_SUCCESS;
116361ae650dSJack F Vogel }
116461ae650dSJack F Vogel 
116561ae650dSJack F Vogel /**
116661ae650dSJack F Vogel  * i40e_clear_hmc_context - zero out the HMC context bits
116761ae650dSJack F Vogel  * @hw:       the hardware struct
116861ae650dSJack F Vogel  * @context_bytes: pointer to the context bit array (DMA memory)
116961ae650dSJack F Vogel  * @hmc_type: the type of HMC resource
117061ae650dSJack F Vogel  **/
117161ae650dSJack F Vogel static enum i40e_status_code i40e_clear_hmc_context(struct i40e_hw *hw,
117261ae650dSJack F Vogel 					u8 *context_bytes,
117361ae650dSJack F Vogel 					enum i40e_hmc_lan_rsrc_type hmc_type)
117461ae650dSJack F Vogel {
117561ae650dSJack F Vogel 	/* clean the bit array */
117661ae650dSJack F Vogel 	i40e_memset(context_bytes, 0, (u32)hw->hmc.hmc_obj[hmc_type].size,
117761ae650dSJack F Vogel 		    I40E_DMA_MEM);
117861ae650dSJack F Vogel 
117961ae650dSJack F Vogel 	return I40E_SUCCESS;
118061ae650dSJack F Vogel }
118161ae650dSJack F Vogel 
118261ae650dSJack F Vogel /**
118361ae650dSJack F Vogel  * i40e_set_hmc_context - replace HMC context bits
118461ae650dSJack F Vogel  * @context_bytes: pointer to the context bit array
118561ae650dSJack F Vogel  * @ce_info:  a description of the struct to be filled
118661ae650dSJack F Vogel  * @dest:     the struct to be filled
118761ae650dSJack F Vogel  **/
118861ae650dSJack F Vogel static enum i40e_status_code i40e_set_hmc_context(u8 *context_bytes,
118961ae650dSJack F Vogel 					struct i40e_context_ele *ce_info,
119061ae650dSJack F Vogel 					u8 *dest)
119161ae650dSJack F Vogel {
119261ae650dSJack F Vogel 	int f;
119361ae650dSJack F Vogel 
119461ae650dSJack F Vogel 	for (f = 0; ce_info[f].width != 0; f++) {
119561ae650dSJack F Vogel 
119661ae650dSJack F Vogel 		/* we have to deal with each element of the HMC using the
119761ae650dSJack F Vogel 		 * correct size so that we are correct regardless of the
119861ae650dSJack F Vogel 		 * endianness of the machine
119961ae650dSJack F Vogel 		 */
120061ae650dSJack F Vogel 		switch (ce_info[f].size_of) {
120161ae650dSJack F Vogel 		case 1:
120261ae650dSJack F Vogel 			i40e_write_byte(context_bytes, &ce_info[f], dest);
120361ae650dSJack F Vogel 			break;
120461ae650dSJack F Vogel 		case 2:
120561ae650dSJack F Vogel 			i40e_write_word(context_bytes, &ce_info[f], dest);
120661ae650dSJack F Vogel 			break;
120761ae650dSJack F Vogel 		case 4:
120861ae650dSJack F Vogel 			i40e_write_dword(context_bytes, &ce_info[f], dest);
120961ae650dSJack F Vogel 			break;
121061ae650dSJack F Vogel 		case 8:
121161ae650dSJack F Vogel 			i40e_write_qword(context_bytes, &ce_info[f], dest);
121261ae650dSJack F Vogel 			break;
121361ae650dSJack F Vogel 		}
121461ae650dSJack F Vogel 	}
121561ae650dSJack F Vogel 
121661ae650dSJack F Vogel 	return I40E_SUCCESS;
121761ae650dSJack F Vogel }
121861ae650dSJack F Vogel 
121961ae650dSJack F Vogel /**
122061ae650dSJack F Vogel  * i40e_hmc_get_object_va - retrieves an object's virtual address
122161ae650dSJack F Vogel  * @hmc_info: pointer to i40e_hmc_info struct
122261ae650dSJack F Vogel  * @object_base: pointer to u64 to get the va
122361ae650dSJack F Vogel  * @rsrc_type: the hmc resource type
122461ae650dSJack F Vogel  * @obj_idx: hmc object index
122561ae650dSJack F Vogel  *
122661ae650dSJack F Vogel  * This function retrieves the object's virtual address from the object
122761ae650dSJack F Vogel  * base pointer.  This function is used for LAN Queue contexts.
122861ae650dSJack F Vogel  **/
122961ae650dSJack F Vogel static
123061ae650dSJack F Vogel enum i40e_status_code i40e_hmc_get_object_va(struct i40e_hmc_info *hmc_info,
123161ae650dSJack F Vogel 					u8 **object_base,
123261ae650dSJack F Vogel 					enum i40e_hmc_lan_rsrc_type rsrc_type,
123361ae650dSJack F Vogel 					u32 obj_idx)
123461ae650dSJack F Vogel {
123561ae650dSJack F Vogel 	u32 obj_offset_in_sd, obj_offset_in_pd;
123661ae650dSJack F Vogel 	struct i40e_hmc_sd_entry *sd_entry;
123761ae650dSJack F Vogel 	struct i40e_hmc_pd_entry *pd_entry;
123861ae650dSJack F Vogel 	u32 pd_idx, pd_lmt, rel_pd_idx;
123961ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
124061ae650dSJack F Vogel 	u64 obj_offset_in_fpm;
124161ae650dSJack F Vogel 	u32 sd_idx, sd_lmt;
124261ae650dSJack F Vogel 
124361ae650dSJack F Vogel 	if (NULL == hmc_info) {
124461ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
124561ae650dSJack F Vogel 		DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info ptr\n");
124661ae650dSJack F Vogel 		goto exit;
124761ae650dSJack F Vogel 	}
124861ae650dSJack F Vogel 	if (NULL == hmc_info->hmc_obj) {
124961ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
125061ae650dSJack F Vogel 		DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n");
125161ae650dSJack F Vogel 		goto exit;
125261ae650dSJack F Vogel 	}
125361ae650dSJack F Vogel 	if (NULL == object_base) {
125461ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
125561ae650dSJack F Vogel 		DEBUGOUT("i40e_hmc_get_object_va: bad object_base ptr\n");
125661ae650dSJack F Vogel 		goto exit;
125761ae650dSJack F Vogel 	}
125861ae650dSJack F Vogel 	if (I40E_HMC_INFO_SIGNATURE != hmc_info->signature) {
125961ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
126061ae650dSJack F Vogel 		DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->signature\n");
126161ae650dSJack F Vogel 		goto exit;
126261ae650dSJack F Vogel 	}
126361ae650dSJack F Vogel 	if (obj_idx >= hmc_info->hmc_obj[rsrc_type].cnt) {
126461ae650dSJack F Vogel 		DEBUGOUT1("i40e_hmc_get_object_va: returns error %d\n",
126561ae650dSJack F Vogel 			  ret_code);
126661ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
126761ae650dSJack F Vogel 		goto exit;
126861ae650dSJack F Vogel 	}
126961ae650dSJack F Vogel 	/* find sd index and limit */
127061ae650dSJack F Vogel 	I40E_FIND_SD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1,
127161ae650dSJack F Vogel 				 &sd_idx, &sd_lmt);
127261ae650dSJack F Vogel 
127361ae650dSJack F Vogel 	sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
127461ae650dSJack F Vogel 	obj_offset_in_fpm = hmc_info->hmc_obj[rsrc_type].base +
127561ae650dSJack F Vogel 			    hmc_info->hmc_obj[rsrc_type].size * obj_idx;
127661ae650dSJack F Vogel 
127761ae650dSJack F Vogel 	if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) {
127861ae650dSJack F Vogel 		I40E_FIND_PD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1,
127961ae650dSJack F Vogel 					 &pd_idx, &pd_lmt);
128061ae650dSJack F Vogel 		rel_pd_idx = pd_idx % I40E_HMC_PD_CNT_IN_SD;
128161ae650dSJack F Vogel 		pd_entry = &sd_entry->u.pd_table.pd_entry[rel_pd_idx];
128261ae650dSJack F Vogel 		obj_offset_in_pd = (u32)(obj_offset_in_fpm %
128361ae650dSJack F Vogel 					 I40E_HMC_PAGED_BP_SIZE);
128461ae650dSJack F Vogel 		*object_base = (u8 *)pd_entry->bp.addr.va + obj_offset_in_pd;
128561ae650dSJack F Vogel 	} else {
128661ae650dSJack F Vogel 		obj_offset_in_sd = (u32)(obj_offset_in_fpm %
128761ae650dSJack F Vogel 					 I40E_HMC_DIRECT_BP_SIZE);
128861ae650dSJack F Vogel 		*object_base = (u8 *)sd_entry->u.bp.addr.va + obj_offset_in_sd;
128961ae650dSJack F Vogel 	}
129061ae650dSJack F Vogel exit:
129161ae650dSJack F Vogel 	return ret_code;
129261ae650dSJack F Vogel }
129361ae650dSJack F Vogel 
129461ae650dSJack F Vogel /**
129561ae650dSJack F Vogel  * i40e_get_lan_tx_queue_context - return the HMC context for the queue
129661ae650dSJack F Vogel  * @hw:    the hardware struct
129761ae650dSJack F Vogel  * @queue: the queue we care about
129861ae650dSJack F Vogel  * @s:     the struct to be filled
129961ae650dSJack F Vogel  **/
130061ae650dSJack F Vogel enum i40e_status_code i40e_get_lan_tx_queue_context(struct i40e_hw *hw,
130161ae650dSJack F Vogel 						    u16 queue,
130261ae650dSJack F Vogel 						    struct i40e_hmc_obj_txq *s)
130361ae650dSJack F Vogel {
130461ae650dSJack F Vogel 	enum i40e_status_code err;
130561ae650dSJack F Vogel 	u8 *context_bytes;
130661ae650dSJack F Vogel 
130761ae650dSJack F Vogel 	err = i40e_hmc_get_object_va(&hw->hmc, &context_bytes,
130861ae650dSJack F Vogel 				     I40E_HMC_LAN_TX, queue);
130961ae650dSJack F Vogel 	if (err < 0)
131061ae650dSJack F Vogel 		return err;
131161ae650dSJack F Vogel 
131261ae650dSJack F Vogel 	return i40e_get_hmc_context(context_bytes,
131361ae650dSJack F Vogel 				    i40e_hmc_txq_ce_info, (u8 *)s);
131461ae650dSJack F Vogel }
131561ae650dSJack F Vogel 
131661ae650dSJack F Vogel /**
131761ae650dSJack F Vogel  * i40e_clear_lan_tx_queue_context - clear the HMC context for the queue
131861ae650dSJack F Vogel  * @hw:    the hardware struct
131961ae650dSJack F Vogel  * @queue: the queue we care about
132061ae650dSJack F Vogel  **/
132161ae650dSJack F Vogel enum i40e_status_code i40e_clear_lan_tx_queue_context(struct i40e_hw *hw,
132261ae650dSJack F Vogel 						      u16 queue)
132361ae650dSJack F Vogel {
132461ae650dSJack F Vogel 	enum i40e_status_code err;
132561ae650dSJack F Vogel 	u8 *context_bytes;
132661ae650dSJack F Vogel 
132761ae650dSJack F Vogel 	err = i40e_hmc_get_object_va(&hw->hmc, &context_bytes,
132861ae650dSJack F Vogel 				     I40E_HMC_LAN_TX, queue);
132961ae650dSJack F Vogel 	if (err < 0)
133061ae650dSJack F Vogel 		return err;
133161ae650dSJack F Vogel 
133261ae650dSJack F Vogel 	return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_TX);
133361ae650dSJack F Vogel }
133461ae650dSJack F Vogel 
133561ae650dSJack F Vogel /**
133661ae650dSJack F Vogel  * i40e_set_lan_tx_queue_context - set the HMC context for the queue
133761ae650dSJack F Vogel  * @hw:    the hardware struct
133861ae650dSJack F Vogel  * @queue: the queue we care about
133961ae650dSJack F Vogel  * @s:     the struct to be filled
134061ae650dSJack F Vogel  **/
134161ae650dSJack F Vogel enum i40e_status_code i40e_set_lan_tx_queue_context(struct i40e_hw *hw,
134261ae650dSJack F Vogel 						    u16 queue,
134361ae650dSJack F Vogel 						    struct i40e_hmc_obj_txq *s)
134461ae650dSJack F Vogel {
134561ae650dSJack F Vogel 	enum i40e_status_code err;
134661ae650dSJack F Vogel 	u8 *context_bytes;
134761ae650dSJack F Vogel 
134861ae650dSJack F Vogel 	err = i40e_hmc_get_object_va(&hw->hmc, &context_bytes,
134961ae650dSJack F Vogel 				     I40E_HMC_LAN_TX, queue);
135061ae650dSJack F Vogel 	if (err < 0)
135161ae650dSJack F Vogel 		return err;
135261ae650dSJack F Vogel 
135361ae650dSJack F Vogel 	return i40e_set_hmc_context(context_bytes,
135461ae650dSJack F Vogel 				    i40e_hmc_txq_ce_info, (u8 *)s);
135561ae650dSJack F Vogel }
135661ae650dSJack F Vogel 
135761ae650dSJack F Vogel /**
135861ae650dSJack F Vogel  * i40e_get_lan_rx_queue_context - return the HMC context for the queue
135961ae650dSJack F Vogel  * @hw:    the hardware struct
136061ae650dSJack F Vogel  * @queue: the queue we care about
136161ae650dSJack F Vogel  * @s:     the struct to be filled
136261ae650dSJack F Vogel  **/
136361ae650dSJack F Vogel enum i40e_status_code i40e_get_lan_rx_queue_context(struct i40e_hw *hw,
136461ae650dSJack F Vogel 						    u16 queue,
136561ae650dSJack F Vogel 						    struct i40e_hmc_obj_rxq *s)
136661ae650dSJack F Vogel {
136761ae650dSJack F Vogel 	enum i40e_status_code err;
136861ae650dSJack F Vogel 	u8 *context_bytes;
136961ae650dSJack F Vogel 
137061ae650dSJack F Vogel 	err = i40e_hmc_get_object_va(&hw->hmc, &context_bytes,
137161ae650dSJack F Vogel 				     I40E_HMC_LAN_RX, queue);
137261ae650dSJack F Vogel 	if (err < 0)
137361ae650dSJack F Vogel 		return err;
137461ae650dSJack F Vogel 
137561ae650dSJack F Vogel 	return i40e_get_hmc_context(context_bytes,
137661ae650dSJack F Vogel 				    i40e_hmc_rxq_ce_info, (u8 *)s);
137761ae650dSJack F Vogel }
137861ae650dSJack F Vogel 
137961ae650dSJack F Vogel /**
138061ae650dSJack F Vogel  * i40e_clear_lan_rx_queue_context - clear the HMC context for the queue
138161ae650dSJack F Vogel  * @hw:    the hardware struct
138261ae650dSJack F Vogel  * @queue: the queue we care about
138361ae650dSJack F Vogel  **/
138461ae650dSJack F Vogel enum i40e_status_code i40e_clear_lan_rx_queue_context(struct i40e_hw *hw,
138561ae650dSJack F Vogel 						      u16 queue)
138661ae650dSJack F Vogel {
138761ae650dSJack F Vogel 	enum i40e_status_code err;
138861ae650dSJack F Vogel 	u8 *context_bytes;
138961ae650dSJack F Vogel 
139061ae650dSJack F Vogel 	err = i40e_hmc_get_object_va(&hw->hmc, &context_bytes,
139161ae650dSJack F Vogel 				     I40E_HMC_LAN_RX, queue);
139261ae650dSJack F Vogel 	if (err < 0)
139361ae650dSJack F Vogel 		return err;
139461ae650dSJack F Vogel 
139561ae650dSJack F Vogel 	return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_RX);
139661ae650dSJack F Vogel }
139761ae650dSJack F Vogel 
139861ae650dSJack F Vogel /**
139961ae650dSJack F Vogel  * i40e_set_lan_rx_queue_context - set the HMC context for the queue
140061ae650dSJack F Vogel  * @hw:    the hardware struct
140161ae650dSJack F Vogel  * @queue: the queue we care about
140261ae650dSJack F Vogel  * @s:     the struct to be filled
140361ae650dSJack F Vogel  **/
140461ae650dSJack F Vogel enum i40e_status_code i40e_set_lan_rx_queue_context(struct i40e_hw *hw,
140561ae650dSJack F Vogel 						    u16 queue,
140661ae650dSJack F Vogel 						    struct i40e_hmc_obj_rxq *s)
140761ae650dSJack F Vogel {
140861ae650dSJack F Vogel 	enum i40e_status_code err;
140961ae650dSJack F Vogel 	u8 *context_bytes;
141061ae650dSJack F Vogel 
141161ae650dSJack F Vogel 	err = i40e_hmc_get_object_va(&hw->hmc, &context_bytes,
141261ae650dSJack F Vogel 				     I40E_HMC_LAN_RX, queue);
141361ae650dSJack F Vogel 	if (err < 0)
141461ae650dSJack F Vogel 		return err;
141561ae650dSJack F Vogel 
141661ae650dSJack F Vogel 	return i40e_set_hmc_context(context_bytes,
141761ae650dSJack F Vogel 				    i40e_hmc_rxq_ce_info, (u8 *)s);
141861ae650dSJack F Vogel }
1419