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