xref: /freebsd/sys/dev/irdma/irdma_hmc.c (revision 01fbb869)
1cdcd52d4SBartosz Sobczak /*-
2cdcd52d4SBartosz Sobczak  * SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB
3cdcd52d4SBartosz Sobczak  *
401fbb869SBartosz Sobczak  * Copyright (c) 2015 - 2023 Intel Corporation
5cdcd52d4SBartosz Sobczak  *
6cdcd52d4SBartosz Sobczak  * This software is available to you under a choice of one of two
7cdcd52d4SBartosz Sobczak  * licenses.  You may choose to be licensed under the terms of the GNU
8cdcd52d4SBartosz Sobczak  * General Public License (GPL) Version 2, available from the file
9cdcd52d4SBartosz Sobczak  * COPYING in the main directory of this source tree, or the
10cdcd52d4SBartosz Sobczak  * OpenFabrics.org BSD license below:
11cdcd52d4SBartosz Sobczak  *
12cdcd52d4SBartosz Sobczak  *   Redistribution and use in source and binary forms, with or
13cdcd52d4SBartosz Sobczak  *   without modification, are permitted provided that the following
14cdcd52d4SBartosz Sobczak  *   conditions are met:
15cdcd52d4SBartosz Sobczak  *
16cdcd52d4SBartosz Sobczak  *    - Redistributions of source code must retain the above
17cdcd52d4SBartosz Sobczak  *	copyright notice, this list of conditions and the following
18cdcd52d4SBartosz Sobczak  *	disclaimer.
19cdcd52d4SBartosz Sobczak  *
20cdcd52d4SBartosz Sobczak  *    - Redistributions in binary form must reproduce the above
21cdcd52d4SBartosz Sobczak  *	copyright notice, this list of conditions and the following
22cdcd52d4SBartosz Sobczak  *	disclaimer in the documentation and/or other materials
23cdcd52d4SBartosz Sobczak  *	provided with the distribution.
24cdcd52d4SBartosz Sobczak  *
25cdcd52d4SBartosz Sobczak  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
26cdcd52d4SBartosz Sobczak  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27cdcd52d4SBartosz Sobczak  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
28cdcd52d4SBartosz Sobczak  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
29cdcd52d4SBartosz Sobczak  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
30cdcd52d4SBartosz Sobczak  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
31cdcd52d4SBartosz Sobczak  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
32cdcd52d4SBartosz Sobczak  * SOFTWARE.
33cdcd52d4SBartosz Sobczak  */
34cdcd52d4SBartosz Sobczak 
35cdcd52d4SBartosz Sobczak #include "osdep.h"
36cdcd52d4SBartosz Sobczak #include "irdma_hmc.h"
37cdcd52d4SBartosz Sobczak #include "irdma_defs.h"
38cdcd52d4SBartosz Sobczak #include "irdma_type.h"
39cdcd52d4SBartosz Sobczak #include "irdma_protos.h"
40cdcd52d4SBartosz Sobczak 
41cdcd52d4SBartosz Sobczak /**
42cdcd52d4SBartosz Sobczak  * irdma_find_sd_index_limit - finds segment descriptor index limit
43cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information structure
44cdcd52d4SBartosz Sobczak  * @type: type of HMC resources we're searching
45cdcd52d4SBartosz Sobczak  * @idx: starting index for the object
46cdcd52d4SBartosz Sobczak  * @cnt: number of objects we're trying to create
47cdcd52d4SBartosz Sobczak  * @sd_idx: pointer to return index of the segment descriptor in question
48cdcd52d4SBartosz Sobczak  * @sd_limit: pointer to return the maximum number of segment descriptors
49cdcd52d4SBartosz Sobczak  *
50cdcd52d4SBartosz Sobczak  * This function calculates the segment descriptor index and index limit
51cdcd52d4SBartosz Sobczak  * for the resource defined by irdma_hmc_rsrc_type.
52cdcd52d4SBartosz Sobczak  */
53cdcd52d4SBartosz Sobczak 
54cdcd52d4SBartosz Sobczak static void
irdma_find_sd_index_limit(struct irdma_hmc_info * hmc_info,u32 type,u32 idx,u32 cnt,u32 * sd_idx,u32 * sd_limit)55cdcd52d4SBartosz Sobczak irdma_find_sd_index_limit(struct irdma_hmc_info *hmc_info, u32 type,
56cdcd52d4SBartosz Sobczak 			  u32 idx, u32 cnt, u32 *sd_idx,
57cdcd52d4SBartosz Sobczak 			  u32 *sd_limit)
58cdcd52d4SBartosz Sobczak {
59cdcd52d4SBartosz Sobczak 	u64 fpm_addr, fpm_limit;
60cdcd52d4SBartosz Sobczak 
61cdcd52d4SBartosz Sobczak 	fpm_addr = hmc_info->hmc_obj[(type)].base +
62cdcd52d4SBartosz Sobczak 	    hmc_info->hmc_obj[type].size * idx;
63cdcd52d4SBartosz Sobczak 	fpm_limit = fpm_addr + hmc_info->hmc_obj[type].size * cnt;
64cdcd52d4SBartosz Sobczak 	*sd_idx = (u32)(fpm_addr / IRDMA_HMC_DIRECT_BP_SIZE);
65cdcd52d4SBartosz Sobczak 	*sd_limit = (u32)((fpm_limit - 1) / IRDMA_HMC_DIRECT_BP_SIZE);
66cdcd52d4SBartosz Sobczak 	*sd_limit += 1;
67cdcd52d4SBartosz Sobczak }
68cdcd52d4SBartosz Sobczak 
69cdcd52d4SBartosz Sobczak /**
70cdcd52d4SBartosz Sobczak  * irdma_find_pd_index_limit - finds page descriptor index limit
71cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information struct
72cdcd52d4SBartosz Sobczak  * @type: HMC resource type we're examining
73cdcd52d4SBartosz Sobczak  * @idx: starting index for the object
74cdcd52d4SBartosz Sobczak  * @cnt: number of objects we're trying to create
75cdcd52d4SBartosz Sobczak  * @pd_idx: pointer to return page descriptor index
76cdcd52d4SBartosz Sobczak  * @pd_limit: pointer to return page descriptor index limit
77cdcd52d4SBartosz Sobczak  *
78cdcd52d4SBartosz Sobczak  * Calculates the page descriptor index and index limit for the resource
79cdcd52d4SBartosz Sobczak  * defined by irdma_hmc_rsrc_type.
80cdcd52d4SBartosz Sobczak  */
81cdcd52d4SBartosz Sobczak 
82cdcd52d4SBartosz Sobczak static void
irdma_find_pd_index_limit(struct irdma_hmc_info * hmc_info,u32 type,u32 idx,u32 cnt,u32 * pd_idx,u32 * pd_limit)83cdcd52d4SBartosz Sobczak irdma_find_pd_index_limit(struct irdma_hmc_info *hmc_info, u32 type,
84cdcd52d4SBartosz Sobczak 			  u32 idx, u32 cnt, u32 *pd_idx,
85cdcd52d4SBartosz Sobczak 			  u32 *pd_limit)
86cdcd52d4SBartosz Sobczak {
87cdcd52d4SBartosz Sobczak 	u64 fpm_adr, fpm_limit;
88cdcd52d4SBartosz Sobczak 
89cdcd52d4SBartosz Sobczak 	fpm_adr = hmc_info->hmc_obj[type].base +
90cdcd52d4SBartosz Sobczak 	    hmc_info->hmc_obj[type].size * idx;
91cdcd52d4SBartosz Sobczak 	fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt);
92cdcd52d4SBartosz Sobczak 	*pd_idx = (u32)(fpm_adr / IRDMA_HMC_PAGED_BP_SIZE);
93cdcd52d4SBartosz Sobczak 	*pd_limit = (u32)((fpm_limit - 1) / IRDMA_HMC_PAGED_BP_SIZE);
94cdcd52d4SBartosz Sobczak 	*pd_limit += 1;
95cdcd52d4SBartosz Sobczak }
96cdcd52d4SBartosz Sobczak 
97cdcd52d4SBartosz Sobczak /**
98cdcd52d4SBartosz Sobczak  * irdma_set_sd_entry - setup entry for sd programming
99cdcd52d4SBartosz Sobczak  * @pa: physical addr
100cdcd52d4SBartosz Sobczak  * @idx: sd index
101cdcd52d4SBartosz Sobczak  * @type: paged or direct sd
102cdcd52d4SBartosz Sobczak  * @entry: sd entry ptr
103cdcd52d4SBartosz Sobczak  */
104cdcd52d4SBartosz Sobczak static void
irdma_set_sd_entry(u64 pa,u32 idx,enum irdma_sd_entry_type type,struct irdma_update_sd_entry * entry)105cdcd52d4SBartosz Sobczak irdma_set_sd_entry(u64 pa, u32 idx, enum irdma_sd_entry_type type,
106cdcd52d4SBartosz Sobczak 		   struct irdma_update_sd_entry *entry)
107cdcd52d4SBartosz Sobczak {
108777e472cSBartosz Sobczak 	entry->data = pa |
109777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDBPCOUNT, IRDMA_HMC_MAX_BP_COUNT) |
110777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDTYPE,
111777e472cSBartosz Sobczak 		       type == IRDMA_SD_TYPE_PAGED ? 0 : 1) |
112777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDVALID, 1);
113777e472cSBartosz Sobczak 
114777e472cSBartosz Sobczak 	entry->cmd = idx | FIELD_PREP(IRDMA_PFHMC_SDCMD_PMSDWR, 1) |
115777e472cSBartosz Sobczak 	    IRDMA_PFHMC_SDCMD_PMSDPARTSEL;
116cdcd52d4SBartosz Sobczak }
117cdcd52d4SBartosz Sobczak 
118cdcd52d4SBartosz Sobczak /**
119cdcd52d4SBartosz Sobczak  * irdma_clr_sd_entry - setup entry for sd clear
120cdcd52d4SBartosz Sobczak  * @idx: sd index
121cdcd52d4SBartosz Sobczak  * @type: paged or direct sd
122cdcd52d4SBartosz Sobczak  * @entry: sd entry ptr
123cdcd52d4SBartosz Sobczak  */
124cdcd52d4SBartosz Sobczak static void
irdma_clr_sd_entry(u32 idx,enum irdma_sd_entry_type type,struct irdma_update_sd_entry * entry)125cdcd52d4SBartosz Sobczak irdma_clr_sd_entry(u32 idx, enum irdma_sd_entry_type type,
126cdcd52d4SBartosz Sobczak 		   struct irdma_update_sd_entry *entry)
127cdcd52d4SBartosz Sobczak {
128777e472cSBartosz Sobczak 	entry->data = FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDBPCOUNT, IRDMA_HMC_MAX_BP_COUNT) |
129777e472cSBartosz Sobczak 	    FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDTYPE,
130777e472cSBartosz Sobczak 		       type == IRDMA_SD_TYPE_PAGED ? 0 : 1);
131777e472cSBartosz Sobczak 
132777e472cSBartosz Sobczak 	entry->cmd = idx | FIELD_PREP(IRDMA_PFHMC_SDCMD_PMSDWR, 1) |
133777e472cSBartosz Sobczak 	    IRDMA_PFHMC_SDCMD_PMSDPARTSEL;
134cdcd52d4SBartosz Sobczak }
135cdcd52d4SBartosz Sobczak 
136cdcd52d4SBartosz Sobczak /**
137cdcd52d4SBartosz Sobczak  * irdma_invalidate_pf_hmc_pd - Invalidates the pd cache in the hardware for PF
138cdcd52d4SBartosz Sobczak  * @dev: pointer to our device struct
139cdcd52d4SBartosz Sobczak  * @sd_idx: segment descriptor index
140cdcd52d4SBartosz Sobczak  * @pd_idx: page descriptor index
141cdcd52d4SBartosz Sobczak  */
142cdcd52d4SBartosz Sobczak static inline void
irdma_invalidate_pf_hmc_pd(struct irdma_sc_dev * dev,u32 sd_idx,u32 pd_idx)143cdcd52d4SBartosz Sobczak irdma_invalidate_pf_hmc_pd(struct irdma_sc_dev *dev, u32 sd_idx,
144cdcd52d4SBartosz Sobczak 			   u32 pd_idx)
145cdcd52d4SBartosz Sobczak {
146777e472cSBartosz Sobczak 	u32 val = FIELD_PREP(IRDMA_PFHMC_PDINV_PMSDIDX, sd_idx) |
147777e472cSBartosz Sobczak 	FIELD_PREP(IRDMA_PFHMC_PDINV_PMSDPARTSEL, 1) |
148777e472cSBartosz Sobczak 	FIELD_PREP(IRDMA_PFHMC_PDINV_PMPDIDX, pd_idx);
149cdcd52d4SBartosz Sobczak 
150cdcd52d4SBartosz Sobczak 	writel(val, dev->hw_regs[IRDMA_PFHMC_PDINV]);
151cdcd52d4SBartosz Sobczak }
152cdcd52d4SBartosz Sobczak 
153cdcd52d4SBartosz Sobczak /**
154cdcd52d4SBartosz Sobczak  * irdma_hmc_sd_one - setup 1 sd entry for cqp
155cdcd52d4SBartosz Sobczak  * @dev: pointer to the device structure
156cdcd52d4SBartosz Sobczak  * @hmc_fn_id: hmc's function id
157cdcd52d4SBartosz Sobczak  * @pa: physical addr
158cdcd52d4SBartosz Sobczak  * @sd_idx: sd index
159cdcd52d4SBartosz Sobczak  * @type: paged or direct sd
160cdcd52d4SBartosz Sobczak  * @setsd: flag to set or clear sd
161cdcd52d4SBartosz Sobczak  */
162cdcd52d4SBartosz Sobczak int
irdma_hmc_sd_one(struct irdma_sc_dev * dev,u16 hmc_fn_id,u64 pa,u32 sd_idx,enum irdma_sd_entry_type type,bool setsd)163777e472cSBartosz Sobczak irdma_hmc_sd_one(struct irdma_sc_dev *dev, u16 hmc_fn_id, u64 pa, u32 sd_idx,
164cdcd52d4SBartosz Sobczak 		 enum irdma_sd_entry_type type, bool setsd)
165cdcd52d4SBartosz Sobczak {
166cdcd52d4SBartosz Sobczak 	struct irdma_update_sds_info sdinfo;
167cdcd52d4SBartosz Sobczak 
168cdcd52d4SBartosz Sobczak 	sdinfo.cnt = 1;
169cdcd52d4SBartosz Sobczak 	sdinfo.hmc_fn_id = hmc_fn_id;
170cdcd52d4SBartosz Sobczak 	if (setsd)
171cdcd52d4SBartosz Sobczak 		irdma_set_sd_entry(pa, sd_idx, type, sdinfo.entry);
172cdcd52d4SBartosz Sobczak 	else
173cdcd52d4SBartosz Sobczak 		irdma_clr_sd_entry(sd_idx, type, sdinfo.entry);
174cdcd52d4SBartosz Sobczak 	return dev->cqp->process_cqp_sds(dev, &sdinfo);
175cdcd52d4SBartosz Sobczak }
176cdcd52d4SBartosz Sobczak 
177cdcd52d4SBartosz Sobczak /**
178cdcd52d4SBartosz Sobczak  * irdma_hmc_sd_grp - setup group of sd entries for cqp
179cdcd52d4SBartosz Sobczak  * @dev: pointer to the device structure
180cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information struct
181cdcd52d4SBartosz Sobczak  * @sd_index: sd index
182cdcd52d4SBartosz Sobczak  * @sd_cnt: number of sd entries
183cdcd52d4SBartosz Sobczak  * @setsd: flag to set or clear sd
184cdcd52d4SBartosz Sobczak  */
185cdcd52d4SBartosz Sobczak static int
irdma_hmc_sd_grp(struct irdma_sc_dev * dev,struct irdma_hmc_info * hmc_info,u32 sd_index,u32 sd_cnt,bool setsd)186cdcd52d4SBartosz Sobczak irdma_hmc_sd_grp(struct irdma_sc_dev *dev,
187cdcd52d4SBartosz Sobczak 		 struct irdma_hmc_info *hmc_info, u32 sd_index,
188cdcd52d4SBartosz Sobczak 		 u32 sd_cnt, bool setsd)
189cdcd52d4SBartosz Sobczak {
190cdcd52d4SBartosz Sobczak 	struct irdma_hmc_sd_entry *sd_entry;
191cdcd52d4SBartosz Sobczak 	struct irdma_update_sds_info sdinfo = {0};
192cdcd52d4SBartosz Sobczak 	u64 pa;
193cdcd52d4SBartosz Sobczak 	u32 i;
194cdcd52d4SBartosz Sobczak 	int ret_code = 0;
195cdcd52d4SBartosz Sobczak 
196cdcd52d4SBartosz Sobczak 	sdinfo.hmc_fn_id = hmc_info->hmc_fn_id;
197cdcd52d4SBartosz Sobczak 	for (i = sd_index; i < sd_index + sd_cnt; i++) {
198cdcd52d4SBartosz Sobczak 		sd_entry = &hmc_info->sd_table.sd_entry[i];
199cdcd52d4SBartosz Sobczak 		if (!sd_entry || (!sd_entry->valid && setsd) ||
200cdcd52d4SBartosz Sobczak 		    (sd_entry->valid && !setsd))
201cdcd52d4SBartosz Sobczak 			continue;
202cdcd52d4SBartosz Sobczak 		if (setsd) {
203cdcd52d4SBartosz Sobczak 			pa = (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED) ?
204cdcd52d4SBartosz Sobczak 			    sd_entry->u.pd_table.pd_page_addr.pa :
205cdcd52d4SBartosz Sobczak 			    sd_entry->u.bp.addr.pa;
206cdcd52d4SBartosz Sobczak 			irdma_set_sd_entry(pa, i, sd_entry->entry_type,
207cdcd52d4SBartosz Sobczak 					   &sdinfo.entry[sdinfo.cnt]);
208cdcd52d4SBartosz Sobczak 		} else {
209cdcd52d4SBartosz Sobczak 			irdma_clr_sd_entry(i, sd_entry->entry_type,
210cdcd52d4SBartosz Sobczak 					   &sdinfo.entry[sdinfo.cnt]);
211cdcd52d4SBartosz Sobczak 		}
212cdcd52d4SBartosz Sobczak 		sdinfo.cnt++;
213cdcd52d4SBartosz Sobczak 		if (sdinfo.cnt == IRDMA_MAX_SD_ENTRIES) {
214cdcd52d4SBartosz Sobczak 			ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
215cdcd52d4SBartosz Sobczak 			if (ret_code) {
216cdcd52d4SBartosz Sobczak 				irdma_debug(dev, IRDMA_DEBUG_HMC,
217cdcd52d4SBartosz Sobczak 					    "sd_programming failed err=%d\n",
218cdcd52d4SBartosz Sobczak 					    ret_code);
219cdcd52d4SBartosz Sobczak 				return ret_code;
220cdcd52d4SBartosz Sobczak 			}
221cdcd52d4SBartosz Sobczak 
222cdcd52d4SBartosz Sobczak 			sdinfo.cnt = 0;
223cdcd52d4SBartosz Sobczak 		}
224cdcd52d4SBartosz Sobczak 	}
225cdcd52d4SBartosz Sobczak 	if (sdinfo.cnt)
226cdcd52d4SBartosz Sobczak 		ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
227cdcd52d4SBartosz Sobczak 
228cdcd52d4SBartosz Sobczak 	return ret_code;
229cdcd52d4SBartosz Sobczak }
230cdcd52d4SBartosz Sobczak 
231cdcd52d4SBartosz Sobczak /**
232cdcd52d4SBartosz Sobczak  * irdma_hmc_finish_add_sd_reg - program sd entries for objects
233cdcd52d4SBartosz Sobczak  * @dev: pointer to the device structure
234cdcd52d4SBartosz Sobczak  * @info: create obj info
235cdcd52d4SBartosz Sobczak  */
236cdcd52d4SBartosz Sobczak static int
irdma_hmc_finish_add_sd_reg(struct irdma_sc_dev * dev,struct irdma_hmc_create_obj_info * info)237cdcd52d4SBartosz Sobczak irdma_hmc_finish_add_sd_reg(struct irdma_sc_dev *dev,
238cdcd52d4SBartosz Sobczak 			    struct irdma_hmc_create_obj_info *info)
239cdcd52d4SBartosz Sobczak {
240cdcd52d4SBartosz Sobczak 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
241cdcd52d4SBartosz Sobczak 		return -EINVAL;
242cdcd52d4SBartosz Sobczak 
243cdcd52d4SBartosz Sobczak 	if ((info->start_idx + info->count) >
244cdcd52d4SBartosz Sobczak 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt)
245cdcd52d4SBartosz Sobczak 		return -EINVAL;
246cdcd52d4SBartosz Sobczak 
247cdcd52d4SBartosz Sobczak 	if (!info->add_sd_cnt)
248cdcd52d4SBartosz Sobczak 		return 0;
249cdcd52d4SBartosz Sobczak 	return irdma_hmc_sd_grp(dev, info->hmc_info,
250cdcd52d4SBartosz Sobczak 				info->hmc_info->sd_indexes[0], info->add_sd_cnt,
251cdcd52d4SBartosz Sobczak 				true);
252cdcd52d4SBartosz Sobczak }
253cdcd52d4SBartosz Sobczak 
254cdcd52d4SBartosz Sobczak /**
255cdcd52d4SBartosz Sobczak  * irdma_sc_create_hmc_obj - allocate backing store for hmc objects
256cdcd52d4SBartosz Sobczak  * @dev: pointer to the device structure
257cdcd52d4SBartosz Sobczak  * @info: pointer to irdma_hmc_create_obj_info struct
258cdcd52d4SBartosz Sobczak  *
259cdcd52d4SBartosz Sobczak  * This will allocate memory for PDs and backing pages and populate
260cdcd52d4SBartosz Sobczak  * the sd and pd entries.
261cdcd52d4SBartosz Sobczak  */
262cdcd52d4SBartosz Sobczak int
irdma_sc_create_hmc_obj(struct irdma_sc_dev * dev,struct irdma_hmc_create_obj_info * info)263cdcd52d4SBartosz Sobczak irdma_sc_create_hmc_obj(struct irdma_sc_dev *dev,
264cdcd52d4SBartosz Sobczak 			struct irdma_hmc_create_obj_info *info)
265cdcd52d4SBartosz Sobczak {
266cdcd52d4SBartosz Sobczak 	struct irdma_hmc_sd_entry *sd_entry;
267cdcd52d4SBartosz Sobczak 	u32 sd_idx, sd_lmt;
268cdcd52d4SBartosz Sobczak 	u32 pd_idx = 0, pd_lmt = 0;
269cdcd52d4SBartosz Sobczak 	u32 pd_idx1 = 0, pd_lmt1 = 0;
270cdcd52d4SBartosz Sobczak 	u32 i, j;
271cdcd52d4SBartosz Sobczak 	bool pd_error = false;
272cdcd52d4SBartosz Sobczak 	int ret_code = 0;
273cdcd52d4SBartosz Sobczak 
274cdcd52d4SBartosz Sobczak 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
275cdcd52d4SBartosz Sobczak 		return -EINVAL;
276cdcd52d4SBartosz Sobczak 
277cdcd52d4SBartosz Sobczak 	if ((info->start_idx + info->count) >
278cdcd52d4SBartosz Sobczak 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
279cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_HMC,
280cdcd52d4SBartosz Sobczak 			    "error type %u, start = %u, req cnt %u, cnt = %u\n",
281cdcd52d4SBartosz Sobczak 			    info->rsrc_type, info->start_idx, info->count,
282cdcd52d4SBartosz Sobczak 			    info->hmc_info->hmc_obj[info->rsrc_type].cnt);
283cdcd52d4SBartosz Sobczak 		return -EINVAL;
284cdcd52d4SBartosz Sobczak 	}
285cdcd52d4SBartosz Sobczak 
286cdcd52d4SBartosz Sobczak 	irdma_find_sd_index_limit(info->hmc_info, info->rsrc_type,
287cdcd52d4SBartosz Sobczak 				  info->start_idx, info->count, &sd_idx,
288cdcd52d4SBartosz Sobczak 				  &sd_lmt);
289cdcd52d4SBartosz Sobczak 	if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
290cdcd52d4SBartosz Sobczak 	    sd_lmt > info->hmc_info->sd_table.sd_cnt) {
291cdcd52d4SBartosz Sobczak 		return -EINVAL;
292cdcd52d4SBartosz Sobczak 	}
293cdcd52d4SBartosz Sobczak 
294cdcd52d4SBartosz Sobczak 	irdma_find_pd_index_limit(info->hmc_info, info->rsrc_type,
295cdcd52d4SBartosz Sobczak 				  info->start_idx, info->count, &pd_idx,
296cdcd52d4SBartosz Sobczak 				  &pd_lmt);
297cdcd52d4SBartosz Sobczak 
298cdcd52d4SBartosz Sobczak 	for (j = sd_idx; j < sd_lmt; j++) {
299cdcd52d4SBartosz Sobczak 		ret_code = irdma_add_sd_table_entry(dev->hw, info->hmc_info, j,
300cdcd52d4SBartosz Sobczak 						    info->entry_type,
301cdcd52d4SBartosz Sobczak 						    IRDMA_HMC_DIRECT_BP_SIZE);
302cdcd52d4SBartosz Sobczak 		if (ret_code)
303cdcd52d4SBartosz Sobczak 			goto exit_sd_error;
304cdcd52d4SBartosz Sobczak 
305cdcd52d4SBartosz Sobczak 		sd_entry = &info->hmc_info->sd_table.sd_entry[j];
306cdcd52d4SBartosz Sobczak 		if (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED &&
307cdcd52d4SBartosz Sobczak 		    (dev->hmc_info == info->hmc_info &&
308cdcd52d4SBartosz Sobczak 		     info->rsrc_type != IRDMA_HMC_IW_PBLE)) {
309cdcd52d4SBartosz Sobczak 			pd_idx1 = max(pd_idx, (j * IRDMA_HMC_MAX_BP_COUNT));
310cdcd52d4SBartosz Sobczak 			pd_lmt1 = min(pd_lmt, (j + 1) * IRDMA_HMC_MAX_BP_COUNT);
311cdcd52d4SBartosz Sobczak 			for (i = pd_idx1; i < pd_lmt1; i++) {
312cdcd52d4SBartosz Sobczak 				/* update the pd table entry */
313cdcd52d4SBartosz Sobczak 				ret_code = irdma_add_pd_table_entry(dev,
314cdcd52d4SBartosz Sobczak 								    info->hmc_info,
315cdcd52d4SBartosz Sobczak 								    i, NULL);
316cdcd52d4SBartosz Sobczak 				if (ret_code) {
317cdcd52d4SBartosz Sobczak 					pd_error = true;
318cdcd52d4SBartosz Sobczak 					break;
319cdcd52d4SBartosz Sobczak 				}
320cdcd52d4SBartosz Sobczak 			}
321cdcd52d4SBartosz Sobczak 			if (pd_error) {
322cdcd52d4SBartosz Sobczak 				while (i && (i > pd_idx1)) {
323cdcd52d4SBartosz Sobczak 					irdma_remove_pd_bp(dev, info->hmc_info,
324cdcd52d4SBartosz Sobczak 							   i - 1);
325cdcd52d4SBartosz Sobczak 					i--;
326cdcd52d4SBartosz Sobczak 				}
327cdcd52d4SBartosz Sobczak 			}
328cdcd52d4SBartosz Sobczak 		}
329cdcd52d4SBartosz Sobczak 		if (sd_entry->valid)
330cdcd52d4SBartosz Sobczak 			continue;
331cdcd52d4SBartosz Sobczak 
332cdcd52d4SBartosz Sobczak 		info->hmc_info->sd_indexes[info->add_sd_cnt] = (u16)j;
333cdcd52d4SBartosz Sobczak 		info->add_sd_cnt++;
334cdcd52d4SBartosz Sobczak 		sd_entry->valid = true;
335cdcd52d4SBartosz Sobczak 	}
336cdcd52d4SBartosz Sobczak 	return irdma_hmc_finish_add_sd_reg(dev, info);
337cdcd52d4SBartosz Sobczak 
338cdcd52d4SBartosz Sobczak exit_sd_error:
339cdcd52d4SBartosz Sobczak 	while (j && (j > sd_idx)) {
340cdcd52d4SBartosz Sobczak 		sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1];
341cdcd52d4SBartosz Sobczak 		switch (sd_entry->entry_type) {
342cdcd52d4SBartosz Sobczak 		case IRDMA_SD_TYPE_PAGED:
343cdcd52d4SBartosz Sobczak 			pd_idx1 = max(pd_idx, (j - 1) * IRDMA_HMC_MAX_BP_COUNT);
344cdcd52d4SBartosz Sobczak 			pd_lmt1 = min(pd_lmt, (j * IRDMA_HMC_MAX_BP_COUNT));
345cdcd52d4SBartosz Sobczak 			for (i = pd_idx1; i < pd_lmt1; i++)
346cdcd52d4SBartosz Sobczak 				irdma_prep_remove_pd_page(info->hmc_info, i);
347cdcd52d4SBartosz Sobczak 			break;
348cdcd52d4SBartosz Sobczak 		case IRDMA_SD_TYPE_DIRECT:
349cdcd52d4SBartosz Sobczak 			irdma_prep_remove_pd_page(info->hmc_info, (j - 1));
350cdcd52d4SBartosz Sobczak 			break;
351cdcd52d4SBartosz Sobczak 		default:
352cdcd52d4SBartosz Sobczak 			ret_code = -EINVAL;
353cdcd52d4SBartosz Sobczak 			break;
354cdcd52d4SBartosz Sobczak 		}
355cdcd52d4SBartosz Sobczak 		j--;
356cdcd52d4SBartosz Sobczak 	}
357cdcd52d4SBartosz Sobczak 
358cdcd52d4SBartosz Sobczak 	return ret_code;
359cdcd52d4SBartosz Sobczak }
360cdcd52d4SBartosz Sobczak 
361cdcd52d4SBartosz Sobczak /**
362cdcd52d4SBartosz Sobczak  * irdma_finish_del_sd_reg - delete sd entries for objects
363cdcd52d4SBartosz Sobczak  * @dev: pointer to the device structure
364cdcd52d4SBartosz Sobczak  * @info: dele obj info
365cdcd52d4SBartosz Sobczak  * @reset: true if called before reset
366cdcd52d4SBartosz Sobczak  */
367cdcd52d4SBartosz Sobczak static int
irdma_finish_del_sd_reg(struct irdma_sc_dev * dev,struct irdma_hmc_del_obj_info * info,bool reset)368cdcd52d4SBartosz Sobczak irdma_finish_del_sd_reg(struct irdma_sc_dev *dev,
369cdcd52d4SBartosz Sobczak 			struct irdma_hmc_del_obj_info *info,
370cdcd52d4SBartosz Sobczak 			bool reset)
371cdcd52d4SBartosz Sobczak {
372cdcd52d4SBartosz Sobczak 	struct irdma_hmc_sd_entry *sd_entry;
373cdcd52d4SBartosz Sobczak 	int ret_code = 0;
374cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *mem;
375cdcd52d4SBartosz Sobczak 	u32 i, sd_idx;
376cdcd52d4SBartosz Sobczak 
377cdcd52d4SBartosz Sobczak 	if (!reset)
378cdcd52d4SBartosz Sobczak 		ret_code = irdma_hmc_sd_grp(dev, info->hmc_info,
379cdcd52d4SBartosz Sobczak 					    info->hmc_info->sd_indexes[0],
380cdcd52d4SBartosz Sobczak 					    info->del_sd_cnt, false);
381cdcd52d4SBartosz Sobczak 
382cdcd52d4SBartosz Sobczak 	if (ret_code)
383cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_HMC, "error cqp sd sd_grp\n");
384cdcd52d4SBartosz Sobczak 	for (i = 0; i < info->del_sd_cnt; i++) {
385cdcd52d4SBartosz Sobczak 		sd_idx = info->hmc_info->sd_indexes[i];
386cdcd52d4SBartosz Sobczak 		sd_entry = &info->hmc_info->sd_table.sd_entry[sd_idx];
387cdcd52d4SBartosz Sobczak 
388cdcd52d4SBartosz Sobczak 		mem = (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED) ?
389cdcd52d4SBartosz Sobczak 		    &sd_entry->u.pd_table.pd_page_addr :
390cdcd52d4SBartosz Sobczak 		    &sd_entry->u.bp.addr;
391cdcd52d4SBartosz Sobczak 
392cdcd52d4SBartosz Sobczak 		if (!mem || !mem->va)
393cdcd52d4SBartosz Sobczak 			irdma_debug(dev, IRDMA_DEBUG_HMC, "error cqp sd mem\n");
394cdcd52d4SBartosz Sobczak 		else
395cdcd52d4SBartosz Sobczak 			irdma_free_dma_mem(dev->hw, mem);
396cdcd52d4SBartosz Sobczak 	}
397cdcd52d4SBartosz Sobczak 
398cdcd52d4SBartosz Sobczak 	return ret_code;
399cdcd52d4SBartosz Sobczak }
400cdcd52d4SBartosz Sobczak 
401cdcd52d4SBartosz Sobczak /**
402cdcd52d4SBartosz Sobczak  * irdma_sc_del_hmc_obj - remove pe hmc objects
403cdcd52d4SBartosz Sobczak  * @dev: pointer to the device structure
404cdcd52d4SBartosz Sobczak  * @info: pointer to irdma_hmc_del_obj_info struct
405cdcd52d4SBartosz Sobczak  * @reset: true if called before reset
406cdcd52d4SBartosz Sobczak  *
407cdcd52d4SBartosz Sobczak  * This will de-populate the SDs and PDs.  It frees
408cdcd52d4SBartosz Sobczak  * the memory for PDS and backing storage.  After this function is returned,
409cdcd52d4SBartosz Sobczak  * caller should deallocate memory allocated previously for
410cdcd52d4SBartosz Sobczak  * book-keeping information about PDs and backing storage.
411cdcd52d4SBartosz Sobczak  */
412cdcd52d4SBartosz Sobczak int
irdma_sc_del_hmc_obj(struct irdma_sc_dev * dev,struct irdma_hmc_del_obj_info * info,bool reset)413cdcd52d4SBartosz Sobczak irdma_sc_del_hmc_obj(struct irdma_sc_dev *dev,
414cdcd52d4SBartosz Sobczak 		     struct irdma_hmc_del_obj_info *info, bool reset)
415cdcd52d4SBartosz Sobczak {
416cdcd52d4SBartosz Sobczak 	struct irdma_hmc_pd_table *pd_table;
417cdcd52d4SBartosz Sobczak 	u32 sd_idx, sd_lmt;
418cdcd52d4SBartosz Sobczak 	u32 pd_idx, pd_lmt, rel_pd_idx;
419cdcd52d4SBartosz Sobczak 	u32 i, j;
420cdcd52d4SBartosz Sobczak 	int ret_code = 0;
421cdcd52d4SBartosz Sobczak 
422cdcd52d4SBartosz Sobczak 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
423cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_HMC,
424cdcd52d4SBartosz Sobczak 			    "error start_idx[%04d] >= [type %04d].cnt[%04d]\n",
425cdcd52d4SBartosz Sobczak 			    info->start_idx, info->rsrc_type,
426cdcd52d4SBartosz Sobczak 			    info->hmc_info->hmc_obj[info->rsrc_type].cnt);
427cdcd52d4SBartosz Sobczak 		return -EINVAL;
428cdcd52d4SBartosz Sobczak 	}
429cdcd52d4SBartosz Sobczak 
430cdcd52d4SBartosz Sobczak 	if ((info->start_idx + info->count) >
431cdcd52d4SBartosz Sobczak 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
432cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_HMC,
433cdcd52d4SBartosz Sobczak 			    "error start_idx[%04d] + count %04d >= [type %04d].cnt[%04d]\n",
434cdcd52d4SBartosz Sobczak 			    info->start_idx, info->count, info->rsrc_type,
435cdcd52d4SBartosz Sobczak 			    info->hmc_info->hmc_obj[info->rsrc_type].cnt);
436cdcd52d4SBartosz Sobczak 		return -EINVAL;
437cdcd52d4SBartosz Sobczak 	}
438cdcd52d4SBartosz Sobczak 
439cdcd52d4SBartosz Sobczak 	irdma_find_pd_index_limit(info->hmc_info, info->rsrc_type,
440cdcd52d4SBartosz Sobczak 				  info->start_idx, info->count, &pd_idx,
441cdcd52d4SBartosz Sobczak 				  &pd_lmt);
442cdcd52d4SBartosz Sobczak 
443cdcd52d4SBartosz Sobczak 	for (j = pd_idx; j < pd_lmt; j++) {
444cdcd52d4SBartosz Sobczak 		sd_idx = j / IRDMA_HMC_PD_CNT_IN_SD;
445cdcd52d4SBartosz Sobczak 
446cdcd52d4SBartosz Sobczak 		if (!info->hmc_info->sd_table.sd_entry[sd_idx].valid)
447cdcd52d4SBartosz Sobczak 			continue;
448cdcd52d4SBartosz Sobczak 
449cdcd52d4SBartosz Sobczak 		if (info->hmc_info->sd_table.sd_entry[sd_idx].entry_type !=
450cdcd52d4SBartosz Sobczak 		    IRDMA_SD_TYPE_PAGED)
451cdcd52d4SBartosz Sobczak 			continue;
452cdcd52d4SBartosz Sobczak 
453cdcd52d4SBartosz Sobczak 		rel_pd_idx = j % IRDMA_HMC_PD_CNT_IN_SD;
454cdcd52d4SBartosz Sobczak 		pd_table = &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
455cdcd52d4SBartosz Sobczak 		if (pd_table->pd_entry &&
456cdcd52d4SBartosz Sobczak 		    pd_table->pd_entry[rel_pd_idx].valid) {
457cdcd52d4SBartosz Sobczak 			ret_code = irdma_remove_pd_bp(dev, info->hmc_info, j);
458cdcd52d4SBartosz Sobczak 			if (ret_code) {
459cdcd52d4SBartosz Sobczak 				irdma_debug(dev, IRDMA_DEBUG_HMC,
460cdcd52d4SBartosz Sobczak 					    "remove_pd_bp error\n");
461cdcd52d4SBartosz Sobczak 				return ret_code;
462cdcd52d4SBartosz Sobczak 			}
463cdcd52d4SBartosz Sobczak 		}
464cdcd52d4SBartosz Sobczak 	}
465cdcd52d4SBartosz Sobczak 
466cdcd52d4SBartosz Sobczak 	irdma_find_sd_index_limit(info->hmc_info, info->rsrc_type,
467cdcd52d4SBartosz Sobczak 				  info->start_idx, info->count, &sd_idx,
468cdcd52d4SBartosz Sobczak 				  &sd_lmt);
469cdcd52d4SBartosz Sobczak 	if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
470cdcd52d4SBartosz Sobczak 	    sd_lmt > info->hmc_info->sd_table.sd_cnt) {
471cdcd52d4SBartosz Sobczak 		irdma_debug(dev, IRDMA_DEBUG_HMC, "invalid sd_idx\n");
472cdcd52d4SBartosz Sobczak 		return -EINVAL;
473cdcd52d4SBartosz Sobczak 	}
474cdcd52d4SBartosz Sobczak 
475cdcd52d4SBartosz Sobczak 	for (i = sd_idx; i < sd_lmt; i++) {
476cdcd52d4SBartosz Sobczak 		pd_table = &info->hmc_info->sd_table.sd_entry[i].u.pd_table;
477cdcd52d4SBartosz Sobczak 		if (!info->hmc_info->sd_table.sd_entry[i].valid)
478cdcd52d4SBartosz Sobczak 			continue;
479cdcd52d4SBartosz Sobczak 		switch (info->hmc_info->sd_table.sd_entry[i].entry_type) {
480cdcd52d4SBartosz Sobczak 		case IRDMA_SD_TYPE_DIRECT:
481cdcd52d4SBartosz Sobczak 			ret_code = irdma_prep_remove_sd_bp(info->hmc_info, i);
482cdcd52d4SBartosz Sobczak 			if (!ret_code) {
483cdcd52d4SBartosz Sobczak 				info->hmc_info->sd_indexes[info->del_sd_cnt] =
484cdcd52d4SBartosz Sobczak 				    (u16)i;
485cdcd52d4SBartosz Sobczak 				info->del_sd_cnt++;
486cdcd52d4SBartosz Sobczak 			}
487cdcd52d4SBartosz Sobczak 			break;
488cdcd52d4SBartosz Sobczak 		case IRDMA_SD_TYPE_PAGED:
489cdcd52d4SBartosz Sobczak 			ret_code = irdma_prep_remove_pd_page(info->hmc_info, i);
490cdcd52d4SBartosz Sobczak 			if (ret_code)
491cdcd52d4SBartosz Sobczak 				break;
492cdcd52d4SBartosz Sobczak 			if (dev->hmc_info != info->hmc_info &&
493cdcd52d4SBartosz Sobczak 			    info->rsrc_type == IRDMA_HMC_IW_PBLE &&
494cdcd52d4SBartosz Sobczak 			    pd_table->pd_entry) {
495cdcd52d4SBartosz Sobczak 				kfree(pd_table->pd_entry_virt_mem.va);
496cdcd52d4SBartosz Sobczak 				pd_table->pd_entry = NULL;
497cdcd52d4SBartosz Sobczak 			}
498cdcd52d4SBartosz Sobczak 			info->hmc_info->sd_indexes[info->del_sd_cnt] = (u16)i;
499cdcd52d4SBartosz Sobczak 			info->del_sd_cnt++;
500cdcd52d4SBartosz Sobczak 			break;
501cdcd52d4SBartosz Sobczak 		default:
502cdcd52d4SBartosz Sobczak 			break;
503cdcd52d4SBartosz Sobczak 		}
504cdcd52d4SBartosz Sobczak 	}
505cdcd52d4SBartosz Sobczak 	return irdma_finish_del_sd_reg(dev, info, reset);
506cdcd52d4SBartosz Sobczak }
507cdcd52d4SBartosz Sobczak 
508cdcd52d4SBartosz Sobczak /**
509cdcd52d4SBartosz Sobczak  * irdma_add_sd_table_entry - Adds a segment descriptor to the table
510cdcd52d4SBartosz Sobczak  * @hw: pointer to our hw struct
511cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information struct
512cdcd52d4SBartosz Sobczak  * @sd_index: segment descriptor index to manipulate
513cdcd52d4SBartosz Sobczak  * @type: what type of segment descriptor we're manipulating
514cdcd52d4SBartosz Sobczak  * @direct_mode_sz: size to alloc in direct mode
515cdcd52d4SBartosz Sobczak  */
516cdcd52d4SBartosz Sobczak int
irdma_add_sd_table_entry(struct irdma_hw * hw,struct irdma_hmc_info * hmc_info,u32 sd_index,enum irdma_sd_entry_type type,u64 direct_mode_sz)517cdcd52d4SBartosz Sobczak irdma_add_sd_table_entry(struct irdma_hw *hw,
518cdcd52d4SBartosz Sobczak 			 struct irdma_hmc_info *hmc_info, u32 sd_index,
519cdcd52d4SBartosz Sobczak 			 enum irdma_sd_entry_type type, u64 direct_mode_sz)
520cdcd52d4SBartosz Sobczak {
521cdcd52d4SBartosz Sobczak 	struct irdma_hmc_sd_entry *sd_entry;
522cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem dma_mem;
523cdcd52d4SBartosz Sobczak 	u64 alloc_len;
524cdcd52d4SBartosz Sobczak 
525cdcd52d4SBartosz Sobczak 	sd_entry = &hmc_info->sd_table.sd_entry[sd_index];
526cdcd52d4SBartosz Sobczak 	if (!sd_entry->valid) {
527cdcd52d4SBartosz Sobczak 		if (type == IRDMA_SD_TYPE_PAGED)
528cdcd52d4SBartosz Sobczak 			alloc_len = IRDMA_HMC_PAGED_BP_SIZE;
529cdcd52d4SBartosz Sobczak 		else
530cdcd52d4SBartosz Sobczak 			alloc_len = direct_mode_sz;
531cdcd52d4SBartosz Sobczak 
532cdcd52d4SBartosz Sobczak 		/* allocate a 4K pd page or 2M backing page */
533cdcd52d4SBartosz Sobczak 		dma_mem.size = alloc_len;
534cdcd52d4SBartosz Sobczak 		dma_mem.va = irdma_allocate_dma_mem(hw, &dma_mem, dma_mem.size,
535cdcd52d4SBartosz Sobczak 						    IRDMA_HMC_PD_BP_BUF_ALIGNMENT);
536cdcd52d4SBartosz Sobczak 		if (!dma_mem.va)
537cdcd52d4SBartosz Sobczak 			return -ENOMEM;
538cdcd52d4SBartosz Sobczak 		if (type == IRDMA_SD_TYPE_PAGED) {
539cdcd52d4SBartosz Sobczak 			struct irdma_virt_mem *vmem =
540cdcd52d4SBartosz Sobczak 			&sd_entry->u.pd_table.pd_entry_virt_mem;
541cdcd52d4SBartosz Sobczak 
542cdcd52d4SBartosz Sobczak 			vmem->size = sizeof(struct irdma_hmc_pd_entry) * 512;
543777e472cSBartosz Sobczak 			vmem->va = kzalloc(vmem->size, GFP_KERNEL);
544cdcd52d4SBartosz Sobczak 			if (!vmem->va) {
545cdcd52d4SBartosz Sobczak 				irdma_free_dma_mem(hw, &dma_mem);
546cdcd52d4SBartosz Sobczak 				return -ENOMEM;
547cdcd52d4SBartosz Sobczak 			}
548cdcd52d4SBartosz Sobczak 			sd_entry->u.pd_table.pd_entry = vmem->va;
549cdcd52d4SBartosz Sobczak 
550cdcd52d4SBartosz Sobczak 			irdma_memcpy(&sd_entry->u.pd_table.pd_page_addr, &dma_mem,
551cdcd52d4SBartosz Sobczak 				     sizeof(sd_entry->u.pd_table.pd_page_addr));
552cdcd52d4SBartosz Sobczak 		} else {
553cdcd52d4SBartosz Sobczak 			irdma_memcpy(&sd_entry->u.bp.addr, &dma_mem,
554cdcd52d4SBartosz Sobczak 				     sizeof(sd_entry->u.bp.addr));
555cdcd52d4SBartosz Sobczak 
556cdcd52d4SBartosz Sobczak 			sd_entry->u.bp.sd_pd_index = sd_index;
557cdcd52d4SBartosz Sobczak 		}
558cdcd52d4SBartosz Sobczak 
559cdcd52d4SBartosz Sobczak 		hmc_info->sd_table.sd_entry[sd_index].entry_type = type;
560cdcd52d4SBartosz Sobczak 		hmc_info->sd_table.use_cnt++;
561cdcd52d4SBartosz Sobczak 	}
562cdcd52d4SBartosz Sobczak 	if (sd_entry->entry_type == IRDMA_SD_TYPE_DIRECT)
563cdcd52d4SBartosz Sobczak 		sd_entry->u.bp.use_cnt++;
564cdcd52d4SBartosz Sobczak 
565cdcd52d4SBartosz Sobczak 	return 0;
566cdcd52d4SBartosz Sobczak }
567cdcd52d4SBartosz Sobczak 
568cdcd52d4SBartosz Sobczak /**
569cdcd52d4SBartosz Sobczak  * irdma_add_pd_table_entry - Adds page descriptor to the specified table
570cdcd52d4SBartosz Sobczak  * @dev: pointer to our device structure
571cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information structure
572cdcd52d4SBartosz Sobczak  * @pd_index: which page descriptor index to manipulate
573cdcd52d4SBartosz Sobczak  * @rsrc_pg: if not NULL, use preallocated page instead of allocating new one.
574cdcd52d4SBartosz Sobczak  *
575cdcd52d4SBartosz Sobczak  * This function:
576cdcd52d4SBartosz Sobczak  *	1. Initializes the pd entry
577cdcd52d4SBartosz Sobczak  *	2. Adds pd_entry in the pd_table
578cdcd52d4SBartosz Sobczak  *	3. Mark the entry valid in irdma_hmc_pd_entry structure
579cdcd52d4SBartosz Sobczak  *	4. Initializes the pd_entry's ref count to 1
580cdcd52d4SBartosz Sobczak  * assumptions:
581cdcd52d4SBartosz Sobczak  *	1. The memory for pd should be pinned down, physically contiguous and
582cdcd52d4SBartosz Sobczak  *	   aligned on 4K boundary and zeroed memory.
583cdcd52d4SBartosz Sobczak  *	2. It should be 4K in size.
584cdcd52d4SBartosz Sobczak  */
585cdcd52d4SBartosz Sobczak int
irdma_add_pd_table_entry(struct irdma_sc_dev * dev,struct irdma_hmc_info * hmc_info,u32 pd_index,struct irdma_dma_mem * rsrc_pg)586cdcd52d4SBartosz Sobczak irdma_add_pd_table_entry(struct irdma_sc_dev *dev,
587cdcd52d4SBartosz Sobczak 			 struct irdma_hmc_info *hmc_info, u32 pd_index,
588cdcd52d4SBartosz Sobczak 			 struct irdma_dma_mem *rsrc_pg)
589cdcd52d4SBartosz Sobczak {
590cdcd52d4SBartosz Sobczak 	struct irdma_hmc_pd_table *pd_table;
591cdcd52d4SBartosz Sobczak 	struct irdma_hmc_pd_entry *pd_entry;
592cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem mem;
593cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *page = &mem;
594cdcd52d4SBartosz Sobczak 	u32 sd_idx, rel_pd_idx;
595cdcd52d4SBartosz Sobczak 	u64 *pd_addr;
596cdcd52d4SBartosz Sobczak 	u64 page_desc;
597cdcd52d4SBartosz Sobczak 
598cdcd52d4SBartosz Sobczak 	if (pd_index / IRDMA_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt)
599cdcd52d4SBartosz Sobczak 		return -EINVAL;
600cdcd52d4SBartosz Sobczak 
601cdcd52d4SBartosz Sobczak 	sd_idx = (pd_index / IRDMA_HMC_PD_CNT_IN_SD);
602cdcd52d4SBartosz Sobczak 	if (hmc_info->sd_table.sd_entry[sd_idx].entry_type !=
603cdcd52d4SBartosz Sobczak 	    IRDMA_SD_TYPE_PAGED)
604cdcd52d4SBartosz Sobczak 		return 0;
605cdcd52d4SBartosz Sobczak 
606cdcd52d4SBartosz Sobczak 	rel_pd_idx = (pd_index % IRDMA_HMC_PD_CNT_IN_SD);
607cdcd52d4SBartosz Sobczak 	pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
608cdcd52d4SBartosz Sobczak 	pd_entry = &pd_table->pd_entry[rel_pd_idx];
609cdcd52d4SBartosz Sobczak 	if (!pd_entry->valid) {
610cdcd52d4SBartosz Sobczak 		if (rsrc_pg) {
611cdcd52d4SBartosz Sobczak 			pd_entry->rsrc_pg = true;
612cdcd52d4SBartosz Sobczak 			page = rsrc_pg;
613cdcd52d4SBartosz Sobczak 		} else {
614cdcd52d4SBartosz Sobczak 			page->size = IRDMA_HMC_PAGED_BP_SIZE;
615cdcd52d4SBartosz Sobczak 			page->va = irdma_allocate_dma_mem(dev->hw, page,
616cdcd52d4SBartosz Sobczak 							  page->size,
617cdcd52d4SBartosz Sobczak 							  IRDMA_HMC_PD_BP_BUF_ALIGNMENT);
618cdcd52d4SBartosz Sobczak 			if (!page->va)
619cdcd52d4SBartosz Sobczak 				return -ENOMEM;
620cdcd52d4SBartosz Sobczak 
621cdcd52d4SBartosz Sobczak 			pd_entry->rsrc_pg = false;
622cdcd52d4SBartosz Sobczak 		}
623cdcd52d4SBartosz Sobczak 
624cdcd52d4SBartosz Sobczak 		irdma_memcpy(&pd_entry->bp.addr, page, sizeof(pd_entry->bp.addr));
625cdcd52d4SBartosz Sobczak 		pd_entry->bp.sd_pd_index = pd_index;
626cdcd52d4SBartosz Sobczak 		pd_entry->bp.entry_type = IRDMA_SD_TYPE_PAGED;
627cdcd52d4SBartosz Sobczak 		page_desc = page->pa | 0x1;
628cdcd52d4SBartosz Sobczak 		pd_addr = pd_table->pd_page_addr.va;
629cdcd52d4SBartosz Sobczak 		pd_addr += rel_pd_idx;
630cdcd52d4SBartosz Sobczak 		irdma_memcpy(pd_addr, &page_desc, sizeof(*pd_addr));
631cdcd52d4SBartosz Sobczak 		pd_entry->sd_index = sd_idx;
632cdcd52d4SBartosz Sobczak 		pd_entry->valid = true;
633cdcd52d4SBartosz Sobczak 		pd_table->use_cnt++;
634cdcd52d4SBartosz Sobczak 		irdma_invalidate_pf_hmc_pd(dev, sd_idx, rel_pd_idx);
635cdcd52d4SBartosz Sobczak 	}
636cdcd52d4SBartosz Sobczak 	pd_entry->bp.use_cnt++;
637cdcd52d4SBartosz Sobczak 
638cdcd52d4SBartosz Sobczak 	return 0;
639cdcd52d4SBartosz Sobczak }
640cdcd52d4SBartosz Sobczak 
641cdcd52d4SBartosz Sobczak /**
642cdcd52d4SBartosz Sobczak  * irdma_remove_pd_bp - remove a backing page from a page descriptor
643cdcd52d4SBartosz Sobczak  * @dev: pointer to our HW structure
644cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information structure
645cdcd52d4SBartosz Sobczak  * @idx: the page index
646cdcd52d4SBartosz Sobczak  *
647cdcd52d4SBartosz Sobczak  * This function:
648cdcd52d4SBartosz Sobczak  *	1. Marks the entry in pd table (for paged address mode) or in sd table
649cdcd52d4SBartosz Sobczak  *	   (for direct address mode) invalid.
650cdcd52d4SBartosz Sobczak  *	2. Write to register PMPDINV to invalidate the backing page in FV cache
651cdcd52d4SBartosz Sobczak  *	3. Decrement the ref count for the pd _entry
652cdcd52d4SBartosz Sobczak  * assumptions:
653cdcd52d4SBartosz Sobczak  *	1. Caller can deallocate the memory used by backing storage after this
654cdcd52d4SBartosz Sobczak  *	   function returns.
655cdcd52d4SBartosz Sobczak  */
656cdcd52d4SBartosz Sobczak int
irdma_remove_pd_bp(struct irdma_sc_dev * dev,struct irdma_hmc_info * hmc_info,u32 idx)657cdcd52d4SBartosz Sobczak irdma_remove_pd_bp(struct irdma_sc_dev *dev,
658cdcd52d4SBartosz Sobczak 		   struct irdma_hmc_info *hmc_info, u32 idx)
659cdcd52d4SBartosz Sobczak {
660cdcd52d4SBartosz Sobczak 	struct irdma_hmc_pd_entry *pd_entry;
661cdcd52d4SBartosz Sobczak 	struct irdma_hmc_pd_table *pd_table;
662cdcd52d4SBartosz Sobczak 	struct irdma_hmc_sd_entry *sd_entry;
663cdcd52d4SBartosz Sobczak 	u32 sd_idx, rel_pd_idx;
664cdcd52d4SBartosz Sobczak 	struct irdma_dma_mem *mem;
665cdcd52d4SBartosz Sobczak 	u64 *pd_addr;
666cdcd52d4SBartosz Sobczak 
667cdcd52d4SBartosz Sobczak 	sd_idx = idx / IRDMA_HMC_PD_CNT_IN_SD;
668cdcd52d4SBartosz Sobczak 	rel_pd_idx = idx % IRDMA_HMC_PD_CNT_IN_SD;
669cdcd52d4SBartosz Sobczak 	if (sd_idx >= hmc_info->sd_table.sd_cnt)
670cdcd52d4SBartosz Sobczak 		return -EINVAL;
671cdcd52d4SBartosz Sobczak 
672cdcd52d4SBartosz Sobczak 	sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
673cdcd52d4SBartosz Sobczak 	if (sd_entry->entry_type != IRDMA_SD_TYPE_PAGED)
674cdcd52d4SBartosz Sobczak 		return -EINVAL;
675cdcd52d4SBartosz Sobczak 
676cdcd52d4SBartosz Sobczak 	pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
677cdcd52d4SBartosz Sobczak 	pd_entry = &pd_table->pd_entry[rel_pd_idx];
678cdcd52d4SBartosz Sobczak 	if (--pd_entry->bp.use_cnt)
679cdcd52d4SBartosz Sobczak 		return 0;
680cdcd52d4SBartosz Sobczak 
681cdcd52d4SBartosz Sobczak 	pd_entry->valid = false;
682cdcd52d4SBartosz Sobczak 	pd_table->use_cnt--;
683cdcd52d4SBartosz Sobczak 	pd_addr = pd_table->pd_page_addr.va;
684cdcd52d4SBartosz Sobczak 	pd_addr += rel_pd_idx;
685cdcd52d4SBartosz Sobczak 	irdma_memset(pd_addr, 0, sizeof(u64));
686cdcd52d4SBartosz Sobczak 	irdma_invalidate_pf_hmc_pd(dev, sd_idx, idx);
687cdcd52d4SBartosz Sobczak 
688cdcd52d4SBartosz Sobczak 	if (!pd_entry->rsrc_pg) {
689cdcd52d4SBartosz Sobczak 		mem = &pd_entry->bp.addr;
690cdcd52d4SBartosz Sobczak 		if (!mem || !mem->va)
691cdcd52d4SBartosz Sobczak 			return -EINVAL;
692cdcd52d4SBartosz Sobczak 
693cdcd52d4SBartosz Sobczak 		irdma_free_dma_mem(dev->hw, mem);
694cdcd52d4SBartosz Sobczak 	}
695cdcd52d4SBartosz Sobczak 	if (!pd_table->use_cnt)
696cdcd52d4SBartosz Sobczak 		kfree(pd_table->pd_entry_virt_mem.va);
697cdcd52d4SBartosz Sobczak 
698cdcd52d4SBartosz Sobczak 	return 0;
699cdcd52d4SBartosz Sobczak }
700cdcd52d4SBartosz Sobczak 
701cdcd52d4SBartosz Sobczak /**
702cdcd52d4SBartosz Sobczak  * irdma_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry
703cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information structure
704cdcd52d4SBartosz Sobczak  * @idx: the page index
705cdcd52d4SBartosz Sobczak  */
706cdcd52d4SBartosz Sobczak int
irdma_prep_remove_sd_bp(struct irdma_hmc_info * hmc_info,u32 idx)707cdcd52d4SBartosz Sobczak irdma_prep_remove_sd_bp(struct irdma_hmc_info *hmc_info, u32 idx)
708cdcd52d4SBartosz Sobczak {
709cdcd52d4SBartosz Sobczak 	struct irdma_hmc_sd_entry *sd_entry;
710cdcd52d4SBartosz Sobczak 
711cdcd52d4SBartosz Sobczak 	sd_entry = &hmc_info->sd_table.sd_entry[idx];
712cdcd52d4SBartosz Sobczak 	if (--sd_entry->u.bp.use_cnt)
713cdcd52d4SBartosz Sobczak 		return -EBUSY;
714cdcd52d4SBartosz Sobczak 
715cdcd52d4SBartosz Sobczak 	hmc_info->sd_table.use_cnt--;
716cdcd52d4SBartosz Sobczak 	sd_entry->valid = false;
717cdcd52d4SBartosz Sobczak 
718cdcd52d4SBartosz Sobczak 	return 0;
719cdcd52d4SBartosz Sobczak }
720cdcd52d4SBartosz Sobczak 
721cdcd52d4SBartosz Sobczak /**
722cdcd52d4SBartosz Sobczak  * irdma_prep_remove_pd_page - Prepares to remove a PD page from sd entry.
723cdcd52d4SBartosz Sobczak  * @hmc_info: pointer to the HMC configuration information structure
724cdcd52d4SBartosz Sobczak  * @idx: segment descriptor index to find the relevant page descriptor
725cdcd52d4SBartosz Sobczak  */
726cdcd52d4SBartosz Sobczak int
irdma_prep_remove_pd_page(struct irdma_hmc_info * hmc_info,u32 idx)727cdcd52d4SBartosz Sobczak irdma_prep_remove_pd_page(struct irdma_hmc_info *hmc_info, u32 idx)
728cdcd52d4SBartosz Sobczak {
729cdcd52d4SBartosz Sobczak 	struct irdma_hmc_sd_entry *sd_entry;
730cdcd52d4SBartosz Sobczak 
731cdcd52d4SBartosz Sobczak 	sd_entry = &hmc_info->sd_table.sd_entry[idx];
732cdcd52d4SBartosz Sobczak 
733cdcd52d4SBartosz Sobczak 	if (sd_entry->u.pd_table.use_cnt)
734cdcd52d4SBartosz Sobczak 		return -EBUSY;
735cdcd52d4SBartosz Sobczak 
736cdcd52d4SBartosz Sobczak 	sd_entry->valid = false;
737cdcd52d4SBartosz Sobczak 	hmc_info->sd_table.use_cnt--;
738cdcd52d4SBartosz Sobczak 
739cdcd52d4SBartosz Sobczak 	return 0;
740cdcd52d4SBartosz Sobczak }
741