xref: /freebsd/sys/dev/ixl/i40e_lan_hmc.c (revision f4cc2d1710068319774a27d5c5e7ff85856c9278)
161ae650dSJack F Vogel /******************************************************************************
261ae650dSJack F Vogel 
3*f4cc2d17SEric Joyner   Copyright (c) 2013-2018, 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);
140be771cdaSJack F Vogel 	obj->size = BIT_ULL(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);
163be771cdaSJack F Vogel 	obj->size = BIT_ULL(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);
186be771cdaSJack F Vogel 	obj->size = BIT_ULL(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);
209be771cdaSJack F Vogel 	obj->size = BIT_ULL(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,
398be771cdaSJack F Vogel 								i, NULL);
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));
442be771cdaSJack 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 			i40e_remove_pd_page(hw, info->hmc_info, (j - 1));
44561ae650dSJack F Vogel 			break;
44661ae650dSJack F Vogel 		case I40E_SD_TYPE_DIRECT:
44761ae650dSJack F Vogel 			i40e_remove_sd_bp(hw, info->hmc_info, (j - 1));
44861ae650dSJack F Vogel 			break;
44961ae650dSJack F Vogel 		default:
45061ae650dSJack F Vogel 			ret_code = I40E_ERR_INVALID_SD_TYPE;
45161ae650dSJack F Vogel 			break;
45261ae650dSJack F Vogel 		}
45361ae650dSJack F Vogel 		j--;
45461ae650dSJack F Vogel 	}
45561ae650dSJack F Vogel exit:
45661ae650dSJack F Vogel 	return ret_code;
45761ae650dSJack F Vogel }
45861ae650dSJack F Vogel 
45961ae650dSJack F Vogel /**
46061ae650dSJack F Vogel  * i40e_configure_lan_hmc - prepare the HMC backing store
46161ae650dSJack F Vogel  * @hw: pointer to the hw structure
46261ae650dSJack F Vogel  * @model: the model for the layout of the SD/PD tables
46361ae650dSJack F Vogel  *
46461ae650dSJack F Vogel  * - This function will be called once per physical function initialization.
46561ae650dSJack F Vogel  * - This function will be called after i40e_init_lan_hmc() and before
46661ae650dSJack F Vogel  *   any LAN/FCoE HMC objects can be created.
46761ae650dSJack F Vogel  **/
46861ae650dSJack F Vogel enum i40e_status_code i40e_configure_lan_hmc(struct i40e_hw *hw,
46961ae650dSJack F Vogel 					     enum i40e_hmc_model model)
47061ae650dSJack F Vogel {
47161ae650dSJack F Vogel 	struct i40e_hmc_lan_create_obj_info info;
47261ae650dSJack F Vogel 	u8 hmc_fn_id = hw->hmc.hmc_fn_id;
47361ae650dSJack F Vogel 	struct i40e_hmc_obj_info *obj;
47461ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
47561ae650dSJack F Vogel 
47661ae650dSJack F Vogel 	/* Initialize part of the create object info struct */
47761ae650dSJack F Vogel 	info.hmc_info = &hw->hmc;
47861ae650dSJack F Vogel 	info.rsrc_type = I40E_HMC_LAN_FULL;
47961ae650dSJack F Vogel 	info.start_idx = 0;
48061ae650dSJack F Vogel 	info.direct_mode_sz = hw->hmc.hmc_obj[I40E_HMC_LAN_FULL].size;
48161ae650dSJack F Vogel 
48261ae650dSJack F Vogel 	/* Build the SD entry for the LAN objects */
48361ae650dSJack F Vogel 	switch (model) {
48461ae650dSJack F Vogel 	case I40E_HMC_MODEL_DIRECT_PREFERRED:
48561ae650dSJack F Vogel 	case I40E_HMC_MODEL_DIRECT_ONLY:
48661ae650dSJack F Vogel 		info.entry_type = I40E_SD_TYPE_DIRECT;
48761ae650dSJack F Vogel 		/* Make one big object, a single SD */
48861ae650dSJack F Vogel 		info.count = 1;
48961ae650dSJack F Vogel 		ret_code = i40e_create_lan_hmc_object(hw, &info);
49061ae650dSJack F Vogel 		if ((ret_code != I40E_SUCCESS) && (model == I40E_HMC_MODEL_DIRECT_PREFERRED))
49161ae650dSJack F Vogel 			goto try_type_paged;
49261ae650dSJack F Vogel 		else if (ret_code != I40E_SUCCESS)
49361ae650dSJack F Vogel 			goto configure_lan_hmc_out;
49461ae650dSJack F Vogel 		/* else clause falls through the break */
49561ae650dSJack F Vogel 		break;
49661ae650dSJack F Vogel 	case I40E_HMC_MODEL_PAGED_ONLY:
49761ae650dSJack F Vogel try_type_paged:
49861ae650dSJack F Vogel 		info.entry_type = I40E_SD_TYPE_PAGED;
49961ae650dSJack F Vogel 		/* Make one big object in the PD table */
50061ae650dSJack F Vogel 		info.count = 1;
50161ae650dSJack F Vogel 		ret_code = i40e_create_lan_hmc_object(hw, &info);
50261ae650dSJack F Vogel 		if (ret_code != I40E_SUCCESS)
50361ae650dSJack F Vogel 			goto configure_lan_hmc_out;
50461ae650dSJack F Vogel 		break;
50561ae650dSJack F Vogel 	default:
50661ae650dSJack F Vogel 		/* unsupported type */
50761ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_SD_TYPE;
50861ae650dSJack F Vogel 		DEBUGOUT1("i40e_configure_lan_hmc: Unknown SD type: %d\n",
50961ae650dSJack F Vogel 			  ret_code);
51061ae650dSJack F Vogel 		goto configure_lan_hmc_out;
51161ae650dSJack F Vogel 	}
51261ae650dSJack F Vogel 
51361ae650dSJack F Vogel 	/* Configure and program the FPM registers so objects can be created */
51461ae650dSJack F Vogel 
51561ae650dSJack F Vogel 	/* Tx contexts */
51661ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_TX];
51761ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANTXBASE(hmc_fn_id),
51861ae650dSJack F Vogel 	     (u32)((obj->base & I40E_GLHMC_LANTXBASE_FPMLANTXBASE_MASK) / 512));
51961ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANTXCNT(hmc_fn_id), obj->cnt);
52061ae650dSJack F Vogel 
52161ae650dSJack F Vogel 	/* Rx contexts */
52261ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_LAN_RX];
52361ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANRXBASE(hmc_fn_id),
52461ae650dSJack F Vogel 	     (u32)((obj->base & I40E_GLHMC_LANRXBASE_FPMLANRXBASE_MASK) / 512));
52561ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_LANRXCNT(hmc_fn_id), obj->cnt);
52661ae650dSJack F Vogel 
52761ae650dSJack F Vogel 	/* FCoE contexts */
52861ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_CTX];
52961ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEDDPBASE(hmc_fn_id),
53061ae650dSJack F Vogel 	 (u32)((obj->base & I40E_GLHMC_FCOEDDPBASE_FPMFCOEDDPBASE_MASK) / 512));
53161ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEDDPCNT(hmc_fn_id), obj->cnt);
53261ae650dSJack F Vogel 
53361ae650dSJack F Vogel 	/* FCoE filters */
53461ae650dSJack F Vogel 	obj = &hw->hmc.hmc_obj[I40E_HMC_FCOE_FILT];
53561ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEFBASE(hmc_fn_id),
53661ae650dSJack F Vogel 	     (u32)((obj->base & I40E_GLHMC_FCOEFBASE_FPMFCOEFBASE_MASK) / 512));
53761ae650dSJack F Vogel 	wr32(hw, I40E_GLHMC_FCOEFCNT(hmc_fn_id), obj->cnt);
53861ae650dSJack F Vogel 
53961ae650dSJack F Vogel configure_lan_hmc_out:
54061ae650dSJack F Vogel 	return ret_code;
54161ae650dSJack F Vogel }
54261ae650dSJack F Vogel 
54361ae650dSJack F Vogel /**
54461ae650dSJack F Vogel  * i40e_delete_hmc_object - remove hmc objects
54561ae650dSJack F Vogel  * @hw: pointer to the HW structure
54661ae650dSJack F Vogel  * @info: pointer to i40e_hmc_delete_obj_info struct
54761ae650dSJack F Vogel  *
54861ae650dSJack F Vogel  * This will de-populate the SDs and PDs.  It frees
54961ae650dSJack F Vogel  * the memory for PDS and backing storage.  After this function is returned,
55061ae650dSJack F Vogel  * caller should deallocate memory allocated previously for
55161ae650dSJack F Vogel  * book-keeping information about PDs and backing storage.
55261ae650dSJack F Vogel  **/
55361ae650dSJack F Vogel enum i40e_status_code i40e_delete_lan_hmc_object(struct i40e_hw *hw,
55461ae650dSJack F Vogel 				struct i40e_hmc_lan_delete_obj_info *info)
55561ae650dSJack F Vogel {
55661ae650dSJack F Vogel 	enum i40e_status_code ret_code = I40E_SUCCESS;
55761ae650dSJack F Vogel 	struct i40e_hmc_pd_table *pd_table;
55861ae650dSJack F Vogel 	u32 pd_idx, pd_lmt, rel_pd_idx;
55961ae650dSJack F Vogel 	u32 sd_idx, sd_lmt;
56061ae650dSJack F Vogel 	u32 i, j;
56161ae650dSJack F Vogel 
56261ae650dSJack F Vogel 	if (NULL == info) {
56361ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
56461ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad info ptr\n");
56561ae650dSJack F Vogel 		goto exit;
56661ae650dSJack F Vogel 	}
56761ae650dSJack F Vogel 	if (NULL == info->hmc_info) {
56861ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
56961ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad info->hmc_info ptr\n");
57061ae650dSJack F Vogel 		goto exit;
57161ae650dSJack F Vogel 	}
57261ae650dSJack F Vogel 	if (I40E_HMC_INFO_SIGNATURE != info->hmc_info->signature) {
57361ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
57461ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->signature\n");
57561ae650dSJack F Vogel 		goto exit;
57661ae650dSJack F Vogel 	}
57761ae650dSJack F Vogel 
57861ae650dSJack F Vogel 	if (NULL == info->hmc_info->sd_table.sd_entry) {
57961ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
58061ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad sd_entry\n");
58161ae650dSJack F Vogel 		goto exit;
58261ae650dSJack F Vogel 	}
58361ae650dSJack F Vogel 
58461ae650dSJack F Vogel 	if (NULL == info->hmc_info->hmc_obj) {
58561ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
58661ae650dSJack F Vogel 		DEBUGOUT("i40e_delete_hmc_object: bad hmc_info->hmc_obj\n");
58761ae650dSJack F Vogel 		goto exit;
58861ae650dSJack F Vogel 	}
58961ae650dSJack F Vogel 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
59061ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
59161ae650dSJack F Vogel 		DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n",
59261ae650dSJack F Vogel 			  ret_code);
59361ae650dSJack F Vogel 		goto exit;
59461ae650dSJack F Vogel 	}
59561ae650dSJack F Vogel 
59661ae650dSJack F Vogel 	if ((info->start_idx + info->count) >
59761ae650dSJack F Vogel 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
59861ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_COUNT;
59961ae650dSJack F Vogel 		DEBUGOUT1("i40e_delete_hmc_object: returns error %d\n",
60061ae650dSJack F Vogel 			  ret_code);
60161ae650dSJack F Vogel 		goto exit;
60261ae650dSJack F Vogel 	}
60361ae650dSJack F Vogel 
60461ae650dSJack F Vogel 	I40E_FIND_PD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
60561ae650dSJack F Vogel 				 info->start_idx, info->count, &pd_idx,
60661ae650dSJack F Vogel 				 &pd_lmt);
60761ae650dSJack F Vogel 
60861ae650dSJack F Vogel 	for (j = pd_idx; j < pd_lmt; j++) {
60961ae650dSJack F Vogel 		sd_idx = j / I40E_HMC_PD_CNT_IN_SD;
61061ae650dSJack F Vogel 
61161ae650dSJack F Vogel 		if (I40E_SD_TYPE_PAGED !=
61261ae650dSJack F Vogel 		    info->hmc_info->sd_table.sd_entry[sd_idx].entry_type)
61361ae650dSJack F Vogel 			continue;
61461ae650dSJack F Vogel 
61561ae650dSJack F Vogel 		rel_pd_idx = j % I40E_HMC_PD_CNT_IN_SD;
61661ae650dSJack F Vogel 
61761ae650dSJack F Vogel 		pd_table =
61861ae650dSJack F Vogel 			&info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
61961ae650dSJack F Vogel 		if (pd_table->pd_entry[rel_pd_idx].valid) {
62061ae650dSJack F Vogel 			ret_code = i40e_remove_pd_bp(hw, info->hmc_info, j);
62161ae650dSJack F Vogel 			if (I40E_SUCCESS != ret_code)
62261ae650dSJack F Vogel 				goto exit;
62361ae650dSJack F Vogel 		}
62461ae650dSJack F Vogel 	}
62561ae650dSJack F Vogel 
62661ae650dSJack F Vogel 	/* find sd index and limit */
62761ae650dSJack F Vogel 	I40E_FIND_SD_INDEX_LIMIT(info->hmc_info, info->rsrc_type,
62861ae650dSJack F Vogel 				 info->start_idx, info->count,
62961ae650dSJack F Vogel 				 &sd_idx, &sd_lmt);
63061ae650dSJack F Vogel 	if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
63161ae650dSJack F Vogel 	    sd_lmt > info->hmc_info->sd_table.sd_cnt) {
63261ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_SD_INDEX;
63361ae650dSJack F Vogel 		goto exit;
63461ae650dSJack F Vogel 	}
63561ae650dSJack F Vogel 
63661ae650dSJack F Vogel 	for (i = sd_idx; i < sd_lmt; i++) {
63761ae650dSJack F Vogel 		if (!info->hmc_info->sd_table.sd_entry[i].valid)
63861ae650dSJack F Vogel 			continue;
63961ae650dSJack F Vogel 		switch (info->hmc_info->sd_table.sd_entry[i].entry_type) {
64061ae650dSJack F Vogel 		case I40E_SD_TYPE_DIRECT:
64161ae650dSJack F Vogel 			ret_code = i40e_remove_sd_bp(hw, info->hmc_info, i);
64261ae650dSJack F Vogel 			if (I40E_SUCCESS != ret_code)
64361ae650dSJack F Vogel 				goto exit;
64461ae650dSJack F Vogel 			break;
64561ae650dSJack F Vogel 		case I40E_SD_TYPE_PAGED:
64661ae650dSJack F Vogel 			ret_code = i40e_remove_pd_page(hw, info->hmc_info, i);
64761ae650dSJack F Vogel 			if (I40E_SUCCESS != ret_code)
64861ae650dSJack F Vogel 				goto exit;
64961ae650dSJack F Vogel 			break;
65061ae650dSJack F Vogel 		default:
65161ae650dSJack F Vogel 			break;
65261ae650dSJack F Vogel 		}
65361ae650dSJack F Vogel 	}
65461ae650dSJack F Vogel exit:
65561ae650dSJack F Vogel 	return ret_code;
65661ae650dSJack F Vogel }
65761ae650dSJack F Vogel 
65861ae650dSJack F Vogel /**
65961ae650dSJack F Vogel  * i40e_shutdown_lan_hmc - Remove HMC backing store, free allocated memory
66061ae650dSJack F Vogel  * @hw: pointer to the hw structure
66161ae650dSJack F Vogel  *
66261ae650dSJack F Vogel  * This must be called by drivers as they are shutting down and being
66361ae650dSJack F Vogel  * removed from the OS.
66461ae650dSJack F Vogel  **/
66561ae650dSJack F Vogel enum i40e_status_code i40e_shutdown_lan_hmc(struct i40e_hw *hw)
66661ae650dSJack F Vogel {
66761ae650dSJack F Vogel 	struct i40e_hmc_lan_delete_obj_info info;
66861ae650dSJack F Vogel 	enum i40e_status_code ret_code;
66961ae650dSJack F Vogel 
67061ae650dSJack F Vogel 	info.hmc_info = &hw->hmc;
67161ae650dSJack F Vogel 	info.rsrc_type = I40E_HMC_LAN_FULL;
67261ae650dSJack F Vogel 	info.start_idx = 0;
67361ae650dSJack F Vogel 	info.count = 1;
67461ae650dSJack F Vogel 
67561ae650dSJack F Vogel 	/* delete the object */
67661ae650dSJack F Vogel 	ret_code = i40e_delete_lan_hmc_object(hw, &info);
67761ae650dSJack F Vogel 
67861ae650dSJack F Vogel 	/* free the SD table entry for LAN */
67961ae650dSJack F Vogel 	i40e_free_virt_mem(hw, &hw->hmc.sd_table.addr);
68061ae650dSJack F Vogel 	hw->hmc.sd_table.sd_cnt = 0;
68161ae650dSJack F Vogel 	hw->hmc.sd_table.sd_entry = NULL;
68261ae650dSJack F Vogel 
68361ae650dSJack F Vogel 	/* free memory used for hmc_obj */
68461ae650dSJack F Vogel 	i40e_free_virt_mem(hw, &hw->hmc.hmc_obj_virt_mem);
68561ae650dSJack F Vogel 	hw->hmc.hmc_obj = NULL;
68661ae650dSJack F Vogel 
68761ae650dSJack F Vogel 	return ret_code;
68861ae650dSJack F Vogel }
68961ae650dSJack F Vogel 
69061ae650dSJack F Vogel #define I40E_HMC_STORE(_struct, _ele)		\
69161ae650dSJack F Vogel 	offsetof(struct _struct, _ele),		\
69261ae650dSJack F Vogel 	FIELD_SIZEOF(struct _struct, _ele)
69361ae650dSJack F Vogel 
69461ae650dSJack F Vogel struct i40e_context_ele {
69561ae650dSJack F Vogel 	u16 offset;
69661ae650dSJack F Vogel 	u16 size_of;
69761ae650dSJack F Vogel 	u16 width;
69861ae650dSJack F Vogel 	u16 lsb;
69961ae650dSJack F Vogel };
70061ae650dSJack F Vogel 
70161ae650dSJack F Vogel /* LAN Tx Queue Context */
70261ae650dSJack F Vogel static struct i40e_context_ele i40e_hmc_txq_ce_info[] = {
70361ae650dSJack F Vogel 					     /* Field      Width    LSB */
70461ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, head),           13,      0 },
70561ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, new_context),     1,     30 },
70661ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, base),           57,     32 },
70761ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, fc_ena),          1,     89 },
70861ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, timesync_ena),    1,     90 },
70961ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, fd_ena),          1,     91 },
71061ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, alt_vlan_ena),    1,     92 },
71161ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, cpuid),           8,     96 },
71261ae650dSJack F Vogel /* line 1 */
71361ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, thead_wb),       13,  0 + 128 },
71461ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_ena),     1, 32 + 128 },
71561ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, qlen),           13, 33 + 128 },
71661ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, tphrdesc_ena),    1, 46 + 128 },
71761ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, tphrpacket_ena),  1, 47 + 128 },
71861ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, tphwdesc_ena),    1, 48 + 128 },
71961ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, head_wb_addr),   64, 64 + 128 },
72061ae650dSJack F Vogel /* line 7 */
72161ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, crc),            32,  0 + (7 * 128) },
72261ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist),        10, 84 + (7 * 128) },
72361ae650dSJack F Vogel 	{I40E_HMC_STORE(i40e_hmc_obj_txq, rdylist_act),     1, 94 + (7 * 128) },
72461ae650dSJack F Vogel 	{ 0 }
72561ae650dSJack F Vogel };
72661ae650dSJack F Vogel 
72761ae650dSJack F Vogel /* LAN Rx Queue Context */
72861ae650dSJack F Vogel static struct i40e_context_ele i40e_hmc_rxq_ce_info[] = {
72961ae650dSJack F Vogel 					 /* Field      Width    LSB */
73061ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, head),        13,	0   },
73161ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, cpuid),        8,	13  },
73261ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, base),        57,	32  },
73361ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, qlen),        13,	89  },
73461ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, dbuff),        7,	102 },
73561ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, hbuff),        5,	109 },
73661ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, dtype),        2,	114 },
73761ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, dsize),        1,	116 },
73861ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, crcstrip),     1,	117 },
73961ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, fc_ena),       1,	118 },
74061ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, l2tsel),       1,	119 },
74161ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_0),     4,	120 },
74261ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, hsplit_1),     2,	124 },
74361ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, showiv),       1,	127 },
74461ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, rxmax),       14,	174 },
74561ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphrdesc_ena), 1,	193 },
74661ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphwdesc_ena), 1,	194 },
74761ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphdata_ena),  1,	195 },
74861ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, tphhead_ena),  1,	196 },
74961ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, lrxqthresh),   3,	198 },
75061ae650dSJack F Vogel 	{ I40E_HMC_STORE(i40e_hmc_obj_rxq, prefena),      1,	201 },
75161ae650dSJack F Vogel 	{ 0 }
75261ae650dSJack F Vogel };
75361ae650dSJack F Vogel 
75461ae650dSJack F Vogel /**
75561ae650dSJack F Vogel  * i40e_write_byte - replace HMC context byte
75661ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
75761ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
75861ae650dSJack F Vogel  * @src: the struct to be read from
75961ae650dSJack F Vogel  **/
76061ae650dSJack F Vogel static void i40e_write_byte(u8 *hmc_bits,
76161ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
76261ae650dSJack F Vogel 			    u8 *src)
76361ae650dSJack F Vogel {
76461ae650dSJack F Vogel 	u8 src_byte, dest_byte, mask;
76561ae650dSJack F Vogel 	u8 *from, *dest;
76661ae650dSJack F Vogel 	u16 shift_width;
76761ae650dSJack F Vogel 
76861ae650dSJack F Vogel 	/* copy from the next struct field */
76961ae650dSJack F Vogel 	from = src + ce_info->offset;
77061ae650dSJack F Vogel 
77161ae650dSJack F Vogel 	/* prepare the bits and mask */
77261ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
7737f70bec6SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
77461ae650dSJack F Vogel 
77561ae650dSJack F Vogel 	src_byte = *from;
77661ae650dSJack F Vogel 	src_byte &= mask;
77761ae650dSJack F Vogel 
77861ae650dSJack F Vogel 	/* shift to correct alignment */
77961ae650dSJack F Vogel 	mask <<= shift_width;
78061ae650dSJack F Vogel 	src_byte <<= shift_width;
78161ae650dSJack F Vogel 
78261ae650dSJack F Vogel 	/* get the current bits from the target bit string */
78361ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
78461ae650dSJack F Vogel 
78561ae650dSJack F Vogel 	i40e_memcpy(&dest_byte, dest, sizeof(dest_byte), I40E_DMA_TO_NONDMA);
78661ae650dSJack F Vogel 
78761ae650dSJack F Vogel 	dest_byte &= ~mask;	/* get the bits not changing */
78861ae650dSJack F Vogel 	dest_byte |= src_byte;	/* add in the new bits */
78961ae650dSJack F Vogel 
79061ae650dSJack F Vogel 	/* put it all back */
79161ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA);
79261ae650dSJack F Vogel }
79361ae650dSJack F Vogel 
79461ae650dSJack F Vogel /**
79561ae650dSJack F Vogel  * i40e_write_word - replace HMC context word
79661ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
79761ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
79861ae650dSJack F Vogel  * @src: the struct to be read from
79961ae650dSJack F Vogel  **/
80061ae650dSJack F Vogel static void i40e_write_word(u8 *hmc_bits,
80161ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
80261ae650dSJack F Vogel 			    u8 *src)
80361ae650dSJack F Vogel {
80461ae650dSJack F Vogel 	u16 src_word, mask;
80561ae650dSJack F Vogel 	u8 *from, *dest;
80661ae650dSJack F Vogel 	u16 shift_width;
80761ae650dSJack F Vogel 	__le16 dest_word;
80861ae650dSJack F Vogel 
80961ae650dSJack F Vogel 	/* copy from the next struct field */
81061ae650dSJack F Vogel 	from = src + ce_info->offset;
81161ae650dSJack F Vogel 
81261ae650dSJack F Vogel 	/* prepare the bits and mask */
81361ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
814be771cdaSJack F Vogel 	mask = BIT(ce_info->width) - 1;
81561ae650dSJack F Vogel 
81661ae650dSJack F Vogel 	/* don't swizzle the bits until after the mask because the mask bits
81761ae650dSJack F Vogel 	 * will be in a different bit position on big endian machines
81861ae650dSJack F Vogel 	 */
81961ae650dSJack F Vogel 	src_word = *(u16 *)from;
82061ae650dSJack F Vogel 	src_word &= mask;
82161ae650dSJack F Vogel 
82261ae650dSJack F Vogel 	/* shift to correct alignment */
82361ae650dSJack F Vogel 	mask <<= shift_width;
82461ae650dSJack F Vogel 	src_word <<= shift_width;
82561ae650dSJack F Vogel 
82661ae650dSJack F Vogel 	/* get the current bits from the target bit string */
82761ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
82861ae650dSJack F Vogel 
82961ae650dSJack F Vogel 	i40e_memcpy(&dest_word, dest, sizeof(dest_word), I40E_DMA_TO_NONDMA);
83061ae650dSJack F Vogel 
83161ae650dSJack F Vogel 	dest_word &= ~(CPU_TO_LE16(mask));	/* get the bits not changing */
83261ae650dSJack F Vogel 	dest_word |= CPU_TO_LE16(src_word);	/* add in the new bits */
83361ae650dSJack F Vogel 
83461ae650dSJack F Vogel 	/* put it all back */
83561ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA);
83661ae650dSJack F Vogel }
83761ae650dSJack F Vogel 
83861ae650dSJack F Vogel /**
83961ae650dSJack F Vogel  * i40e_write_dword - replace HMC context dword
84061ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
84161ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
84261ae650dSJack F Vogel  * @src: the struct to be read from
84361ae650dSJack F Vogel  **/
84461ae650dSJack F Vogel static void i40e_write_dword(u8 *hmc_bits,
84561ae650dSJack F Vogel 			     struct i40e_context_ele *ce_info,
84661ae650dSJack F Vogel 			     u8 *src)
84761ae650dSJack F Vogel {
84861ae650dSJack F Vogel 	u32 src_dword, mask;
84961ae650dSJack F Vogel 	u8 *from, *dest;
85061ae650dSJack F Vogel 	u16 shift_width;
85161ae650dSJack F Vogel 	__le32 dest_dword;
85261ae650dSJack F Vogel 
85361ae650dSJack F Vogel 	/* copy from the next struct field */
85461ae650dSJack F Vogel 	from = src + ce_info->offset;
85561ae650dSJack F Vogel 
85661ae650dSJack F Vogel 	/* prepare the bits and mask */
85761ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
85861ae650dSJack F Vogel 
85961ae650dSJack F Vogel 	/* if the field width is exactly 32 on an x86 machine, then the shift
86061ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
86161ae650dSJack F Vogel 	 * to 5 bits so the shift will do nothing
86261ae650dSJack F Vogel 	 */
86361ae650dSJack F Vogel 	if (ce_info->width < 32)
864be771cdaSJack F Vogel 		mask = BIT(ce_info->width) - 1;
86561ae650dSJack F Vogel 	else
866f247dc25SJack F Vogel 		mask = ~(u32)0;
86761ae650dSJack F Vogel 
86861ae650dSJack F Vogel 	/* don't swizzle the bits until after the mask because the mask bits
86961ae650dSJack F Vogel 	 * will be in a different bit position on big endian machines
87061ae650dSJack F Vogel 	 */
87161ae650dSJack F Vogel 	src_dword = *(u32 *)from;
87261ae650dSJack F Vogel 	src_dword &= mask;
87361ae650dSJack F Vogel 
87461ae650dSJack F Vogel 	/* shift to correct alignment */
87561ae650dSJack F Vogel 	mask <<= shift_width;
87661ae650dSJack F Vogel 	src_dword <<= shift_width;
87761ae650dSJack F Vogel 
87861ae650dSJack F Vogel 	/* get the current bits from the target bit string */
87961ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
88061ae650dSJack F Vogel 
88161ae650dSJack F Vogel 	i40e_memcpy(&dest_dword, dest, sizeof(dest_dword), I40E_DMA_TO_NONDMA);
88261ae650dSJack F Vogel 
88361ae650dSJack F Vogel 	dest_dword &= ~(CPU_TO_LE32(mask));	/* get the bits not changing */
88461ae650dSJack F Vogel 	dest_dword |= CPU_TO_LE32(src_dword);	/* add in the new bits */
88561ae650dSJack F Vogel 
88661ae650dSJack F Vogel 	/* put it all back */
88761ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_dword, sizeof(dest_dword), I40E_NONDMA_TO_DMA);
88861ae650dSJack F Vogel }
88961ae650dSJack F Vogel 
89061ae650dSJack F Vogel /**
89161ae650dSJack F Vogel  * i40e_write_qword - replace HMC context qword
89261ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
89361ae650dSJack F Vogel  * @ce_info: a description of the struct to be read from
89461ae650dSJack F Vogel  * @src: the struct to be read from
89561ae650dSJack F Vogel  **/
89661ae650dSJack F Vogel static void i40e_write_qword(u8 *hmc_bits,
89761ae650dSJack F Vogel 			     struct i40e_context_ele *ce_info,
89861ae650dSJack F Vogel 			     u8 *src)
89961ae650dSJack F Vogel {
90061ae650dSJack F Vogel 	u64 src_qword, mask;
90161ae650dSJack F Vogel 	u8 *from, *dest;
90261ae650dSJack F Vogel 	u16 shift_width;
90361ae650dSJack F Vogel 	__le64 dest_qword;
90461ae650dSJack F Vogel 
90561ae650dSJack F Vogel 	/* copy from the next struct field */
90661ae650dSJack F Vogel 	from = src + ce_info->offset;
90761ae650dSJack F Vogel 
90861ae650dSJack F Vogel 	/* prepare the bits and mask */
90961ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
91061ae650dSJack F Vogel 
91161ae650dSJack F Vogel 	/* if the field width is exactly 64 on an x86 machine, then the shift
91261ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
91361ae650dSJack F Vogel 	 * to 6 bits so the shift will do nothing
91461ae650dSJack F Vogel 	 */
91561ae650dSJack F Vogel 	if (ce_info->width < 64)
916be771cdaSJack F Vogel 		mask = BIT_ULL(ce_info->width) - 1;
91761ae650dSJack F Vogel 	else
918f247dc25SJack F Vogel 		mask = ~(u64)0;
91961ae650dSJack F Vogel 
92061ae650dSJack F Vogel 	/* don't swizzle the bits until after the mask because the mask bits
92161ae650dSJack F Vogel 	 * will be in a different bit position on big endian machines
92261ae650dSJack F Vogel 	 */
92361ae650dSJack F Vogel 	src_qword = *(u64 *)from;
92461ae650dSJack F Vogel 	src_qword &= mask;
92561ae650dSJack F Vogel 
92661ae650dSJack F Vogel 	/* shift to correct alignment */
92761ae650dSJack F Vogel 	mask <<= shift_width;
92861ae650dSJack F Vogel 	src_qword <<= shift_width;
92961ae650dSJack F Vogel 
93061ae650dSJack F Vogel 	/* get the current bits from the target bit string */
93161ae650dSJack F Vogel 	dest = hmc_bits + (ce_info->lsb / 8);
93261ae650dSJack F Vogel 
93361ae650dSJack F Vogel 	i40e_memcpy(&dest_qword, dest, sizeof(dest_qword), I40E_DMA_TO_NONDMA);
93461ae650dSJack F Vogel 
93561ae650dSJack F Vogel 	dest_qword &= ~(CPU_TO_LE64(mask));	/* get the bits not changing */
93661ae650dSJack F Vogel 	dest_qword |= CPU_TO_LE64(src_qword);	/* add in the new bits */
93761ae650dSJack F Vogel 
93861ae650dSJack F Vogel 	/* put it all back */
93961ae650dSJack F Vogel 	i40e_memcpy(dest, &dest_qword, sizeof(dest_qword), I40E_NONDMA_TO_DMA);
94061ae650dSJack F Vogel }
94161ae650dSJack F Vogel 
94261ae650dSJack F Vogel /**
94361ae650dSJack F Vogel  * i40e_read_byte - read HMC context byte into struct
94461ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
94561ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
94661ae650dSJack F Vogel  * @dest: the struct to be filled
94761ae650dSJack F Vogel  **/
94861ae650dSJack F Vogel static void i40e_read_byte(u8 *hmc_bits,
94961ae650dSJack F Vogel 			   struct i40e_context_ele *ce_info,
95061ae650dSJack F Vogel 			   u8 *dest)
95161ae650dSJack F Vogel {
95261ae650dSJack F Vogel 	u8 dest_byte, mask;
95361ae650dSJack F Vogel 	u8 *src, *target;
95461ae650dSJack F Vogel 	u16 shift_width;
95561ae650dSJack F Vogel 
95661ae650dSJack F Vogel 	/* prepare the bits and mask */
95761ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
9587f70bec6SEric Joyner 	mask = (u8)(BIT(ce_info->width) - 1);
95961ae650dSJack F Vogel 
96061ae650dSJack F Vogel 	/* shift to correct alignment */
96161ae650dSJack F Vogel 	mask <<= shift_width;
96261ae650dSJack F Vogel 
96361ae650dSJack F Vogel 	/* get the current bits from the src bit string */
96461ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
96561ae650dSJack F Vogel 
96661ae650dSJack F Vogel 	i40e_memcpy(&dest_byte, src, sizeof(dest_byte), I40E_DMA_TO_NONDMA);
96761ae650dSJack F Vogel 
96861ae650dSJack F Vogel 	dest_byte &= ~(mask);
96961ae650dSJack F Vogel 
97061ae650dSJack F Vogel 	dest_byte >>= shift_width;
97161ae650dSJack F Vogel 
97261ae650dSJack F Vogel 	/* get the address from the struct field */
97361ae650dSJack F Vogel 	target = dest + ce_info->offset;
97461ae650dSJack F Vogel 
97561ae650dSJack F Vogel 	/* put it back in the struct */
97661ae650dSJack F Vogel 	i40e_memcpy(target, &dest_byte, sizeof(dest_byte), I40E_NONDMA_TO_DMA);
97761ae650dSJack F Vogel }
97861ae650dSJack F Vogel 
97961ae650dSJack F Vogel /**
98061ae650dSJack F Vogel  * i40e_read_word - read HMC context word into struct
98161ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
98261ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
98361ae650dSJack F Vogel  * @dest: the struct to be filled
98461ae650dSJack F Vogel  **/
98561ae650dSJack F Vogel static void i40e_read_word(u8 *hmc_bits,
98661ae650dSJack F Vogel 			   struct i40e_context_ele *ce_info,
98761ae650dSJack F Vogel 			   u8 *dest)
98861ae650dSJack F Vogel {
98961ae650dSJack F Vogel 	u16 dest_word, mask;
99061ae650dSJack F Vogel 	u8 *src, *target;
99161ae650dSJack F Vogel 	u16 shift_width;
99261ae650dSJack F Vogel 	__le16 src_word;
99361ae650dSJack F Vogel 
99461ae650dSJack F Vogel 	/* prepare the bits and mask */
99561ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
996be771cdaSJack F Vogel 	mask = BIT(ce_info->width) - 1;
99761ae650dSJack F Vogel 
99861ae650dSJack F Vogel 	/* shift to correct alignment */
99961ae650dSJack F Vogel 	mask <<= shift_width;
100061ae650dSJack F Vogel 
100161ae650dSJack F Vogel 	/* get the current bits from the src bit string */
100261ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
100361ae650dSJack F Vogel 
100461ae650dSJack F Vogel 	i40e_memcpy(&src_word, src, sizeof(src_word), I40E_DMA_TO_NONDMA);
100561ae650dSJack F Vogel 
100661ae650dSJack F Vogel 	/* the data in the memory is stored as little endian so mask it
100761ae650dSJack F Vogel 	 * correctly
100861ae650dSJack F Vogel 	 */
100961ae650dSJack F Vogel 	src_word &= ~(CPU_TO_LE16(mask));
101061ae650dSJack F Vogel 
101161ae650dSJack F Vogel 	/* get the data back into host order before shifting */
101261ae650dSJack F Vogel 	dest_word = LE16_TO_CPU(src_word);
101361ae650dSJack F Vogel 
101461ae650dSJack F Vogel 	dest_word >>= shift_width;
101561ae650dSJack F Vogel 
101661ae650dSJack F Vogel 	/* get the address from the struct field */
101761ae650dSJack F Vogel 	target = dest + ce_info->offset;
101861ae650dSJack F Vogel 
101961ae650dSJack F Vogel 	/* put it back in the struct */
102061ae650dSJack F Vogel 	i40e_memcpy(target, &dest_word, sizeof(dest_word), I40E_NONDMA_TO_DMA);
102161ae650dSJack F Vogel }
102261ae650dSJack F Vogel 
102361ae650dSJack F Vogel /**
102461ae650dSJack F Vogel  * i40e_read_dword - read HMC context dword into struct
102561ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
102661ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
102761ae650dSJack F Vogel  * @dest: the struct to be filled
102861ae650dSJack F Vogel  **/
102961ae650dSJack F Vogel static void i40e_read_dword(u8 *hmc_bits,
103061ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
103161ae650dSJack F Vogel 			    u8 *dest)
103261ae650dSJack F Vogel {
103361ae650dSJack F Vogel 	u32 dest_dword, mask;
103461ae650dSJack F Vogel 	u8 *src, *target;
103561ae650dSJack F Vogel 	u16 shift_width;
103661ae650dSJack F Vogel 	__le32 src_dword;
103761ae650dSJack F Vogel 
103861ae650dSJack F Vogel 	/* prepare the bits and mask */
103961ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
104061ae650dSJack F Vogel 
104161ae650dSJack F Vogel 	/* if the field width is exactly 32 on an x86 machine, then the shift
104261ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
104361ae650dSJack F Vogel 	 * to 5 bits so the shift will do nothing
104461ae650dSJack F Vogel 	 */
104561ae650dSJack F Vogel 	if (ce_info->width < 32)
1046be771cdaSJack F Vogel 		mask = BIT(ce_info->width) - 1;
104761ae650dSJack F Vogel 	else
1048f247dc25SJack F Vogel 		mask = ~(u32)0;
104961ae650dSJack F Vogel 
105061ae650dSJack F Vogel 	/* shift to correct alignment */
105161ae650dSJack F Vogel 	mask <<= shift_width;
105261ae650dSJack F Vogel 
105361ae650dSJack F Vogel 	/* get the current bits from the src bit string */
105461ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
105561ae650dSJack F Vogel 
105661ae650dSJack F Vogel 	i40e_memcpy(&src_dword, src, sizeof(src_dword), I40E_DMA_TO_NONDMA);
105761ae650dSJack F Vogel 
105861ae650dSJack F Vogel 	/* the data in the memory is stored as little endian so mask it
105961ae650dSJack F Vogel 	 * correctly
106061ae650dSJack F Vogel 	 */
106161ae650dSJack F Vogel 	src_dword &= ~(CPU_TO_LE32(mask));
106261ae650dSJack F Vogel 
106361ae650dSJack F Vogel 	/* get the data back into host order before shifting */
106461ae650dSJack F Vogel 	dest_dword = LE32_TO_CPU(src_dword);
106561ae650dSJack F Vogel 
106661ae650dSJack F Vogel 	dest_dword >>= shift_width;
106761ae650dSJack F Vogel 
106861ae650dSJack F Vogel 	/* get the address from the struct field */
106961ae650dSJack F Vogel 	target = dest + ce_info->offset;
107061ae650dSJack F Vogel 
107161ae650dSJack F Vogel 	/* put it back in the struct */
107261ae650dSJack F Vogel 	i40e_memcpy(target, &dest_dword, sizeof(dest_dword),
107361ae650dSJack F Vogel 		    I40E_NONDMA_TO_DMA);
107461ae650dSJack F Vogel }
107561ae650dSJack F Vogel 
107661ae650dSJack F Vogel /**
107761ae650dSJack F Vogel  * i40e_read_qword - read HMC context qword into struct
107861ae650dSJack F Vogel  * @hmc_bits: pointer to the HMC memory
107961ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
108061ae650dSJack F Vogel  * @dest: the struct to be filled
108161ae650dSJack F Vogel  **/
108261ae650dSJack F Vogel static void i40e_read_qword(u8 *hmc_bits,
108361ae650dSJack F Vogel 			    struct i40e_context_ele *ce_info,
108461ae650dSJack F Vogel 			    u8 *dest)
108561ae650dSJack F Vogel {
108661ae650dSJack F Vogel 	u64 dest_qword, mask;
108761ae650dSJack F Vogel 	u8 *src, *target;
108861ae650dSJack F Vogel 	u16 shift_width;
108961ae650dSJack F Vogel 	__le64 src_qword;
109061ae650dSJack F Vogel 
109161ae650dSJack F Vogel 	/* prepare the bits and mask */
109261ae650dSJack F Vogel 	shift_width = ce_info->lsb % 8;
109361ae650dSJack F Vogel 
109461ae650dSJack F Vogel 	/* if the field width is exactly 64 on an x86 machine, then the shift
109561ae650dSJack F Vogel 	 * operation will not work because the SHL instructions count is masked
109661ae650dSJack F Vogel 	 * to 6 bits so the shift will do nothing
109761ae650dSJack F Vogel 	 */
109861ae650dSJack F Vogel 	if (ce_info->width < 64)
1099be771cdaSJack F Vogel 		mask = BIT_ULL(ce_info->width) - 1;
110061ae650dSJack F Vogel 	else
1101f247dc25SJack F Vogel 		mask = ~(u64)0;
110261ae650dSJack F Vogel 
110361ae650dSJack F Vogel 	/* shift to correct alignment */
110461ae650dSJack F Vogel 	mask <<= shift_width;
110561ae650dSJack F Vogel 
110661ae650dSJack F Vogel 	/* get the current bits from the src bit string */
110761ae650dSJack F Vogel 	src = hmc_bits + (ce_info->lsb / 8);
110861ae650dSJack F Vogel 
110961ae650dSJack F Vogel 	i40e_memcpy(&src_qword, src, sizeof(src_qword), I40E_DMA_TO_NONDMA);
111061ae650dSJack F Vogel 
111161ae650dSJack F Vogel 	/* the data in the memory is stored as little endian so mask it
111261ae650dSJack F Vogel 	 * correctly
111361ae650dSJack F Vogel 	 */
111461ae650dSJack F Vogel 	src_qword &= ~(CPU_TO_LE64(mask));
111561ae650dSJack F Vogel 
111661ae650dSJack F Vogel 	/* get the data back into host order before shifting */
111761ae650dSJack F Vogel 	dest_qword = LE64_TO_CPU(src_qword);
111861ae650dSJack F Vogel 
111961ae650dSJack F Vogel 	dest_qword >>= shift_width;
112061ae650dSJack F Vogel 
112161ae650dSJack F Vogel 	/* get the address from the struct field */
112261ae650dSJack F Vogel 	target = dest + ce_info->offset;
112361ae650dSJack F Vogel 
112461ae650dSJack F Vogel 	/* put it back in the struct */
112561ae650dSJack F Vogel 	i40e_memcpy(target, &dest_qword, sizeof(dest_qword),
112661ae650dSJack F Vogel 		    I40E_NONDMA_TO_DMA);
112761ae650dSJack F Vogel }
112861ae650dSJack F Vogel 
112961ae650dSJack F Vogel /**
113061ae650dSJack F Vogel  * i40e_get_hmc_context - extract HMC context bits
113161ae650dSJack F Vogel  * @context_bytes: pointer to the context bit array
113261ae650dSJack F Vogel  * @ce_info: a description of the struct to be filled
113361ae650dSJack F Vogel  * @dest: the struct to be filled
113461ae650dSJack F Vogel  **/
113561ae650dSJack F Vogel static enum i40e_status_code i40e_get_hmc_context(u8 *context_bytes,
113661ae650dSJack F Vogel 					struct i40e_context_ele *ce_info,
113761ae650dSJack F Vogel 					u8 *dest)
113861ae650dSJack F Vogel {
113961ae650dSJack F Vogel 	int f;
114061ae650dSJack F Vogel 
114161ae650dSJack F Vogel 	for (f = 0; ce_info[f].width != 0; f++) {
114261ae650dSJack F Vogel 		switch (ce_info[f].size_of) {
114361ae650dSJack F Vogel 		case 1:
114461ae650dSJack F Vogel 			i40e_read_byte(context_bytes, &ce_info[f], dest);
114561ae650dSJack F Vogel 			break;
114661ae650dSJack F Vogel 		case 2:
114761ae650dSJack F Vogel 			i40e_read_word(context_bytes, &ce_info[f], dest);
114861ae650dSJack F Vogel 			break;
114961ae650dSJack F Vogel 		case 4:
115061ae650dSJack F Vogel 			i40e_read_dword(context_bytes, &ce_info[f], dest);
115161ae650dSJack F Vogel 			break;
115261ae650dSJack F Vogel 		case 8:
115361ae650dSJack F Vogel 			i40e_read_qword(context_bytes, &ce_info[f], dest);
115461ae650dSJack F Vogel 			break;
115561ae650dSJack F Vogel 		default:
115661ae650dSJack F Vogel 			/* nothing to do, just keep going */
115761ae650dSJack F Vogel 			break;
115861ae650dSJack F Vogel 		}
115961ae650dSJack F Vogel 	}
116061ae650dSJack F Vogel 
116161ae650dSJack F Vogel 	return I40E_SUCCESS;
116261ae650dSJack F Vogel }
116361ae650dSJack F Vogel 
116461ae650dSJack F Vogel /**
116561ae650dSJack F Vogel  * i40e_clear_hmc_context - zero out the HMC context bits
116661ae650dSJack F Vogel  * @hw:       the hardware struct
116761ae650dSJack F Vogel  * @context_bytes: pointer to the context bit array (DMA memory)
116861ae650dSJack F Vogel  * @hmc_type: the type of HMC resource
116961ae650dSJack F Vogel  **/
117061ae650dSJack F Vogel static enum i40e_status_code i40e_clear_hmc_context(struct i40e_hw *hw,
117161ae650dSJack F Vogel 					u8 *context_bytes,
117261ae650dSJack F Vogel 					enum i40e_hmc_lan_rsrc_type hmc_type)
117361ae650dSJack F Vogel {
117461ae650dSJack F Vogel 	/* clean the bit array */
117561ae650dSJack F Vogel 	i40e_memset(context_bytes, 0, (u32)hw->hmc.hmc_obj[hmc_type].size,
117661ae650dSJack F Vogel 		    I40E_DMA_MEM);
117761ae650dSJack F Vogel 
117861ae650dSJack F Vogel 	return I40E_SUCCESS;
117961ae650dSJack F Vogel }
118061ae650dSJack F Vogel 
118161ae650dSJack F Vogel /**
118261ae650dSJack F Vogel  * i40e_set_hmc_context - replace HMC context bits
118361ae650dSJack F Vogel  * @context_bytes: pointer to the context bit array
118461ae650dSJack F Vogel  * @ce_info:  a description of the struct to be filled
118561ae650dSJack F Vogel  * @dest:     the struct to be filled
118661ae650dSJack F Vogel  **/
118761ae650dSJack F Vogel static enum i40e_status_code i40e_set_hmc_context(u8 *context_bytes,
118861ae650dSJack F Vogel 					struct i40e_context_ele *ce_info,
118961ae650dSJack F Vogel 					u8 *dest)
119061ae650dSJack F Vogel {
119161ae650dSJack F Vogel 	int f;
119261ae650dSJack F Vogel 
119361ae650dSJack F Vogel 	for (f = 0; ce_info[f].width != 0; f++) {
119461ae650dSJack F Vogel 
119561ae650dSJack F Vogel 		/* we have to deal with each element of the HMC using the
119661ae650dSJack F Vogel 		 * correct size so that we are correct regardless of the
119761ae650dSJack F Vogel 		 * endianness of the machine
119861ae650dSJack F Vogel 		 */
119961ae650dSJack F Vogel 		switch (ce_info[f].size_of) {
120061ae650dSJack F Vogel 		case 1:
120161ae650dSJack F Vogel 			i40e_write_byte(context_bytes, &ce_info[f], dest);
120261ae650dSJack F Vogel 			break;
120361ae650dSJack F Vogel 		case 2:
120461ae650dSJack F Vogel 			i40e_write_word(context_bytes, &ce_info[f], dest);
120561ae650dSJack F Vogel 			break;
120661ae650dSJack F Vogel 		case 4:
120761ae650dSJack F Vogel 			i40e_write_dword(context_bytes, &ce_info[f], dest);
120861ae650dSJack F Vogel 			break;
120961ae650dSJack F Vogel 		case 8:
121061ae650dSJack F Vogel 			i40e_write_qword(context_bytes, &ce_info[f], dest);
121161ae650dSJack F Vogel 			break;
121261ae650dSJack F Vogel 		}
121361ae650dSJack F Vogel 	}
121461ae650dSJack F Vogel 
121561ae650dSJack F Vogel 	return I40E_SUCCESS;
121661ae650dSJack F Vogel }
121761ae650dSJack F Vogel 
121861ae650dSJack F Vogel /**
121961ae650dSJack F Vogel  * i40e_hmc_get_object_va - retrieves an object's virtual address
1220b6c8f260SJack F Vogel  * @hw: pointer to the hw structure
122161ae650dSJack F Vogel  * @object_base: pointer to u64 to get the va
122261ae650dSJack F Vogel  * @rsrc_type: the hmc resource type
122361ae650dSJack F Vogel  * @obj_idx: hmc object index
122461ae650dSJack F Vogel  *
122561ae650dSJack F Vogel  * This function retrieves the object's virtual address from the object
122661ae650dSJack F Vogel  * base pointer.  This function is used for LAN Queue contexts.
122761ae650dSJack F Vogel  **/
122861ae650dSJack F Vogel static
1229b6c8f260SJack F Vogel enum i40e_status_code i40e_hmc_get_object_va(struct i40e_hw *hw,
123061ae650dSJack F Vogel 					u8 **object_base,
123161ae650dSJack F Vogel 					enum i40e_hmc_lan_rsrc_type rsrc_type,
123261ae650dSJack F Vogel 					u32 obj_idx)
123361ae650dSJack F Vogel {
123461ae650dSJack F Vogel 	u32 obj_offset_in_sd, obj_offset_in_pd;
1235b6c8f260SJack F Vogel 	struct i40e_hmc_info     *hmc_info = &hw->hmc;
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->hmc_obj) {
124461ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
124561ae650dSJack F Vogel 		DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->hmc_obj ptr\n");
124661ae650dSJack F Vogel 		goto exit;
124761ae650dSJack F Vogel 	}
124861ae650dSJack F Vogel 	if (NULL == object_base) {
124961ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
125061ae650dSJack F Vogel 		DEBUGOUT("i40e_hmc_get_object_va: bad object_base ptr\n");
125161ae650dSJack F Vogel 		goto exit;
125261ae650dSJack F Vogel 	}
125361ae650dSJack F Vogel 	if (I40E_HMC_INFO_SIGNATURE != hmc_info->signature) {
125461ae650dSJack F Vogel 		ret_code = I40E_ERR_BAD_PTR;
125561ae650dSJack F Vogel 		DEBUGOUT("i40e_hmc_get_object_va: bad hmc_info->signature\n");
125661ae650dSJack F Vogel 		goto exit;
125761ae650dSJack F Vogel 	}
125861ae650dSJack F Vogel 	if (obj_idx >= hmc_info->hmc_obj[rsrc_type].cnt) {
125961ae650dSJack F Vogel 		DEBUGOUT1("i40e_hmc_get_object_va: returns error %d\n",
126061ae650dSJack F Vogel 			  ret_code);
126161ae650dSJack F Vogel 		ret_code = I40E_ERR_INVALID_HMC_OBJ_INDEX;
126261ae650dSJack F Vogel 		goto exit;
126361ae650dSJack F Vogel 	}
126461ae650dSJack F Vogel 	/* find sd index and limit */
126561ae650dSJack F Vogel 	I40E_FIND_SD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1,
126661ae650dSJack F Vogel 				 &sd_idx, &sd_lmt);
126761ae650dSJack F Vogel 
126861ae650dSJack F Vogel 	sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
126961ae650dSJack F Vogel 	obj_offset_in_fpm = hmc_info->hmc_obj[rsrc_type].base +
127061ae650dSJack F Vogel 			    hmc_info->hmc_obj[rsrc_type].size * obj_idx;
127161ae650dSJack F Vogel 
127261ae650dSJack F Vogel 	if (I40E_SD_TYPE_PAGED == sd_entry->entry_type) {
127361ae650dSJack F Vogel 		I40E_FIND_PD_INDEX_LIMIT(hmc_info, rsrc_type, obj_idx, 1,
127461ae650dSJack F Vogel 					 &pd_idx, &pd_lmt);
127561ae650dSJack F Vogel 		rel_pd_idx = pd_idx % I40E_HMC_PD_CNT_IN_SD;
127661ae650dSJack F Vogel 		pd_entry = &sd_entry->u.pd_table.pd_entry[rel_pd_idx];
127761ae650dSJack F Vogel 		obj_offset_in_pd = (u32)(obj_offset_in_fpm %
127861ae650dSJack F Vogel 					 I40E_HMC_PAGED_BP_SIZE);
127961ae650dSJack F Vogel 		*object_base = (u8 *)pd_entry->bp.addr.va + obj_offset_in_pd;
128061ae650dSJack F Vogel 	} else {
128161ae650dSJack F Vogel 		obj_offset_in_sd = (u32)(obj_offset_in_fpm %
128261ae650dSJack F Vogel 					 I40E_HMC_DIRECT_BP_SIZE);
128361ae650dSJack F Vogel 		*object_base = (u8 *)sd_entry->u.bp.addr.va + obj_offset_in_sd;
128461ae650dSJack F Vogel 	}
128561ae650dSJack F Vogel exit:
128661ae650dSJack F Vogel 	return ret_code;
128761ae650dSJack F Vogel }
128861ae650dSJack F Vogel 
128961ae650dSJack F Vogel /**
129061ae650dSJack F Vogel  * i40e_get_lan_tx_queue_context - return the HMC context for the queue
129161ae650dSJack F Vogel  * @hw:    the hardware struct
129261ae650dSJack F Vogel  * @queue: the queue we care about
129361ae650dSJack F Vogel  * @s:     the struct to be filled
129461ae650dSJack F Vogel  **/
129561ae650dSJack F Vogel enum i40e_status_code i40e_get_lan_tx_queue_context(struct i40e_hw *hw,
129661ae650dSJack F Vogel 						    u16 queue,
129761ae650dSJack F Vogel 						    struct i40e_hmc_obj_txq *s)
129861ae650dSJack F Vogel {
129961ae650dSJack F Vogel 	enum i40e_status_code err;
130061ae650dSJack F Vogel 	u8 *context_bytes;
130161ae650dSJack F Vogel 
1302b6c8f260SJack F Vogel 	err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue);
130361ae650dSJack F Vogel 	if (err < 0)
130461ae650dSJack F Vogel 		return err;
130561ae650dSJack F Vogel 
130661ae650dSJack F Vogel 	return i40e_get_hmc_context(context_bytes,
130761ae650dSJack F Vogel 				    i40e_hmc_txq_ce_info, (u8 *)s);
130861ae650dSJack F Vogel }
130961ae650dSJack F Vogel 
131061ae650dSJack F Vogel /**
131161ae650dSJack F Vogel  * i40e_clear_lan_tx_queue_context - clear the HMC context for the queue
131261ae650dSJack F Vogel  * @hw:    the hardware struct
131361ae650dSJack F Vogel  * @queue: the queue we care about
131461ae650dSJack F Vogel  **/
131561ae650dSJack F Vogel enum i40e_status_code i40e_clear_lan_tx_queue_context(struct i40e_hw *hw,
131661ae650dSJack F Vogel 						      u16 queue)
131761ae650dSJack F Vogel {
131861ae650dSJack F Vogel 	enum i40e_status_code err;
131961ae650dSJack F Vogel 	u8 *context_bytes;
132061ae650dSJack F Vogel 
1321b6c8f260SJack F Vogel 	err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue);
132261ae650dSJack F Vogel 	if (err < 0)
132361ae650dSJack F Vogel 		return err;
132461ae650dSJack F Vogel 
132561ae650dSJack F Vogel 	return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_TX);
132661ae650dSJack F Vogel }
132761ae650dSJack F Vogel 
132861ae650dSJack F Vogel /**
132961ae650dSJack F Vogel  * i40e_set_lan_tx_queue_context - set the HMC context for the queue
133061ae650dSJack F Vogel  * @hw:    the hardware struct
133161ae650dSJack F Vogel  * @queue: the queue we care about
133261ae650dSJack F Vogel  * @s:     the struct to be filled
133361ae650dSJack F Vogel  **/
133461ae650dSJack F Vogel enum i40e_status_code i40e_set_lan_tx_queue_context(struct i40e_hw *hw,
133561ae650dSJack F Vogel 						    u16 queue,
133661ae650dSJack F Vogel 						    struct i40e_hmc_obj_txq *s)
133761ae650dSJack F Vogel {
133861ae650dSJack F Vogel 	enum i40e_status_code err;
133961ae650dSJack F Vogel 	u8 *context_bytes;
134061ae650dSJack F Vogel 
1341b6c8f260SJack F Vogel 	err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_TX, queue);
134261ae650dSJack F Vogel 	if (err < 0)
134361ae650dSJack F Vogel 		return err;
134461ae650dSJack F Vogel 
134561ae650dSJack F Vogel 	return i40e_set_hmc_context(context_bytes,
134661ae650dSJack F Vogel 				    i40e_hmc_txq_ce_info, (u8 *)s);
134761ae650dSJack F Vogel }
134861ae650dSJack F Vogel 
134961ae650dSJack F Vogel /**
135061ae650dSJack F Vogel  * i40e_get_lan_rx_queue_context - return the HMC context for the queue
135161ae650dSJack F Vogel  * @hw:    the hardware struct
135261ae650dSJack F Vogel  * @queue: the queue we care about
135361ae650dSJack F Vogel  * @s:     the struct to be filled
135461ae650dSJack F Vogel  **/
135561ae650dSJack F Vogel enum i40e_status_code i40e_get_lan_rx_queue_context(struct i40e_hw *hw,
135661ae650dSJack F Vogel 						    u16 queue,
135761ae650dSJack F Vogel 						    struct i40e_hmc_obj_rxq *s)
135861ae650dSJack F Vogel {
135961ae650dSJack F Vogel 	enum i40e_status_code err;
136061ae650dSJack F Vogel 	u8 *context_bytes;
136161ae650dSJack F Vogel 
1362b6c8f260SJack F Vogel 	err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue);
136361ae650dSJack F Vogel 	if (err < 0)
136461ae650dSJack F Vogel 		return err;
136561ae650dSJack F Vogel 
136661ae650dSJack F Vogel 	return i40e_get_hmc_context(context_bytes,
136761ae650dSJack F Vogel 				    i40e_hmc_rxq_ce_info, (u8 *)s);
136861ae650dSJack F Vogel }
136961ae650dSJack F Vogel 
137061ae650dSJack F Vogel /**
137161ae650dSJack F Vogel  * i40e_clear_lan_rx_queue_context - clear the HMC context for the queue
137261ae650dSJack F Vogel  * @hw:    the hardware struct
137361ae650dSJack F Vogel  * @queue: the queue we care about
137461ae650dSJack F Vogel  **/
137561ae650dSJack F Vogel enum i40e_status_code i40e_clear_lan_rx_queue_context(struct i40e_hw *hw,
137661ae650dSJack F Vogel 						      u16 queue)
137761ae650dSJack F Vogel {
137861ae650dSJack F Vogel 	enum i40e_status_code err;
137961ae650dSJack F Vogel 	u8 *context_bytes;
138061ae650dSJack F Vogel 
1381b6c8f260SJack F Vogel 	err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue);
138261ae650dSJack F Vogel 	if (err < 0)
138361ae650dSJack F Vogel 		return err;
138461ae650dSJack F Vogel 
138561ae650dSJack F Vogel 	return i40e_clear_hmc_context(hw, context_bytes, I40E_HMC_LAN_RX);
138661ae650dSJack F Vogel }
138761ae650dSJack F Vogel 
138861ae650dSJack F Vogel /**
138961ae650dSJack F Vogel  * i40e_set_lan_rx_queue_context - set the HMC context for the queue
139061ae650dSJack F Vogel  * @hw:    the hardware struct
139161ae650dSJack F Vogel  * @queue: the queue we care about
139261ae650dSJack F Vogel  * @s:     the struct to be filled
139361ae650dSJack F Vogel  **/
139461ae650dSJack F Vogel enum i40e_status_code i40e_set_lan_rx_queue_context(struct i40e_hw *hw,
139561ae650dSJack F Vogel 						    u16 queue,
139661ae650dSJack F Vogel 						    struct i40e_hmc_obj_rxq *s)
139761ae650dSJack F Vogel {
139861ae650dSJack F Vogel 	enum i40e_status_code err;
139961ae650dSJack F Vogel 	u8 *context_bytes;
140061ae650dSJack F Vogel 
1401b6c8f260SJack F Vogel 	err = i40e_hmc_get_object_va(hw, &context_bytes, I40E_HMC_LAN_RX, queue);
140261ae650dSJack F Vogel 	if (err < 0)
140361ae650dSJack F Vogel 		return err;
140461ae650dSJack F Vogel 
140561ae650dSJack F Vogel 	return i40e_set_hmc_context(context_bytes,
140661ae650dSJack F Vogel 				    i40e_hmc_rxq_ce_info, (u8 *)s);
140761ae650dSJack F Vogel }
1408