xref: /linux/drivers/infiniband/hw/irdma/hmc.c (revision 0ea5c948cb64bab5bc7a5516774eb8536f05aa0d)
1*3ec648c6SKrzysztof Kozlowski // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2d1850c00SMustafa Ismail /* Copyright (c) 2015 - 2021 Intel Corporation */
3d1850c00SMustafa Ismail #include "osdep.h"
4d1850c00SMustafa Ismail #include "hmc.h"
5d1850c00SMustafa Ismail #include "defs.h"
6d1850c00SMustafa Ismail #include "type.h"
7d1850c00SMustafa Ismail #include "protos.h"
8d1850c00SMustafa Ismail 
9d1850c00SMustafa Ismail /**
10d1850c00SMustafa Ismail  * irdma_find_sd_index_limit - finds segment descriptor index limit
11d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information structure
12d1850c00SMustafa Ismail  * @type: type of HMC resources we're searching
13d1850c00SMustafa Ismail  * @idx: starting index for the object
14d1850c00SMustafa Ismail  * @cnt: number of objects we're trying to create
15d1850c00SMustafa Ismail  * @sd_idx: pointer to return index of the segment descriptor in question
16d1850c00SMustafa Ismail  * @sd_limit: pointer to return the maximum number of segment descriptors
17d1850c00SMustafa Ismail  *
18d1850c00SMustafa Ismail  * This function calculates the segment descriptor index and index limit
19d1850c00SMustafa Ismail  * for the resource defined by irdma_hmc_rsrc_type.
20d1850c00SMustafa Ismail  */
21d1850c00SMustafa Ismail 
irdma_find_sd_index_limit(struct irdma_hmc_info * hmc_info,u32 type,u32 idx,u32 cnt,u32 * sd_idx,u32 * sd_limit)22d1850c00SMustafa Ismail static void irdma_find_sd_index_limit(struct irdma_hmc_info *hmc_info, u32 type,
23d1850c00SMustafa Ismail 				      u32 idx, u32 cnt, u32 *sd_idx,
24d1850c00SMustafa Ismail 				      u32 *sd_limit)
25d1850c00SMustafa Ismail {
26d1850c00SMustafa Ismail 	u64 fpm_addr, fpm_limit;
27d1850c00SMustafa Ismail 
28d1850c00SMustafa Ismail 	fpm_addr = hmc_info->hmc_obj[(type)].base +
29d1850c00SMustafa Ismail 		   hmc_info->hmc_obj[type].size * idx;
30d1850c00SMustafa Ismail 	fpm_limit = fpm_addr + hmc_info->hmc_obj[type].size * cnt;
31d1850c00SMustafa Ismail 	*sd_idx = (u32)(fpm_addr / IRDMA_HMC_DIRECT_BP_SIZE);
32d1850c00SMustafa Ismail 	*sd_limit = (u32)((fpm_limit - 1) / IRDMA_HMC_DIRECT_BP_SIZE);
33d1850c00SMustafa Ismail 	*sd_limit += 1;
34d1850c00SMustafa Ismail }
35d1850c00SMustafa Ismail 
36d1850c00SMustafa Ismail /**
37d1850c00SMustafa Ismail  * irdma_find_pd_index_limit - finds page descriptor index limit
38d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information struct
39d1850c00SMustafa Ismail  * @type: HMC resource type we're examining
40d1850c00SMustafa Ismail  * @idx: starting index for the object
41d1850c00SMustafa Ismail  * @cnt: number of objects we're trying to create
42d1850c00SMustafa Ismail  * @pd_idx: pointer to return page descriptor index
43d1850c00SMustafa Ismail  * @pd_limit: pointer to return page descriptor index limit
44d1850c00SMustafa Ismail  *
45d1850c00SMustafa Ismail  * Calculates the page descriptor index and index limit for the resource
46d1850c00SMustafa Ismail  * defined by irdma_hmc_rsrc_type.
47d1850c00SMustafa Ismail  */
48d1850c00SMustafa Ismail 
irdma_find_pd_index_limit(struct irdma_hmc_info * hmc_info,u32 type,u32 idx,u32 cnt,u32 * pd_idx,u32 * pd_limit)49d1850c00SMustafa Ismail static void irdma_find_pd_index_limit(struct irdma_hmc_info *hmc_info, u32 type,
50d1850c00SMustafa Ismail 				      u32 idx, u32 cnt, u32 *pd_idx,
51d1850c00SMustafa Ismail 				      u32 *pd_limit)
52d1850c00SMustafa Ismail {
53d1850c00SMustafa Ismail 	u64 fpm_adr, fpm_limit;
54d1850c00SMustafa Ismail 
55d1850c00SMustafa Ismail 	fpm_adr = hmc_info->hmc_obj[type].base +
56d1850c00SMustafa Ismail 		  hmc_info->hmc_obj[type].size * idx;
57d1850c00SMustafa Ismail 	fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt);
58d1850c00SMustafa Ismail 	*pd_idx = (u32)(fpm_adr / IRDMA_HMC_PAGED_BP_SIZE);
59d1850c00SMustafa Ismail 	*pd_limit = (u32)((fpm_limit - 1) / IRDMA_HMC_PAGED_BP_SIZE);
60d1850c00SMustafa Ismail 	*pd_limit += 1;
61d1850c00SMustafa Ismail }
62d1850c00SMustafa Ismail 
63d1850c00SMustafa Ismail /**
64d1850c00SMustafa Ismail  * irdma_set_sd_entry - setup entry for sd programming
65d1850c00SMustafa Ismail  * @pa: physical addr
66d1850c00SMustafa Ismail  * @idx: sd index
67d1850c00SMustafa Ismail  * @type: paged or direct sd
68d1850c00SMustafa Ismail  * @entry: sd entry ptr
69d1850c00SMustafa Ismail  */
irdma_set_sd_entry(u64 pa,u32 idx,enum irdma_sd_entry_type type,struct irdma_update_sd_entry * entry)70d1850c00SMustafa Ismail static void irdma_set_sd_entry(u64 pa, u32 idx, enum irdma_sd_entry_type type,
71d1850c00SMustafa Ismail 			       struct irdma_update_sd_entry *entry)
72d1850c00SMustafa Ismail {
73d1850c00SMustafa Ismail 	entry->data = pa |
74d1850c00SMustafa Ismail 		      FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDBPCOUNT, IRDMA_HMC_MAX_BP_COUNT) |
75d1850c00SMustafa Ismail 		      FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDTYPE,
76d1850c00SMustafa Ismail 				 type == IRDMA_SD_TYPE_PAGED ? 0 : 1) |
77d1850c00SMustafa Ismail 		      FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDVALID, 1);
78d1850c00SMustafa Ismail 
79d1850c00SMustafa Ismail 	entry->cmd = idx | FIELD_PREP(IRDMA_PFHMC_SDCMD_PMSDWR, 1) | BIT(15);
80d1850c00SMustafa Ismail }
81d1850c00SMustafa Ismail 
82d1850c00SMustafa Ismail /**
83d1850c00SMustafa Ismail  * irdma_clr_sd_entry - setup entry for sd clear
84d1850c00SMustafa Ismail  * @idx: sd index
85d1850c00SMustafa Ismail  * @type: paged or direct sd
86d1850c00SMustafa Ismail  * @entry: sd entry ptr
87d1850c00SMustafa Ismail  */
irdma_clr_sd_entry(u32 idx,enum irdma_sd_entry_type type,struct irdma_update_sd_entry * entry)88d1850c00SMustafa Ismail static void irdma_clr_sd_entry(u32 idx, enum irdma_sd_entry_type type,
89d1850c00SMustafa Ismail 			       struct irdma_update_sd_entry *entry)
90d1850c00SMustafa Ismail {
91d1850c00SMustafa Ismail 	entry->data = FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDBPCOUNT, IRDMA_HMC_MAX_BP_COUNT) |
92d1850c00SMustafa Ismail 		      FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDTYPE,
93d1850c00SMustafa Ismail 				 type == IRDMA_SD_TYPE_PAGED ? 0 : 1);
94d1850c00SMustafa Ismail 
95d1850c00SMustafa Ismail 	entry->cmd = idx | FIELD_PREP(IRDMA_PFHMC_SDCMD_PMSDWR, 1) | BIT(15);
96d1850c00SMustafa Ismail }
97d1850c00SMustafa Ismail 
98d1850c00SMustafa Ismail /**
99d1850c00SMustafa Ismail  * irdma_invalidate_pf_hmc_pd - Invalidates the pd cache in the hardware for PF
100d1850c00SMustafa Ismail  * @dev: pointer to our device struct
101d1850c00SMustafa Ismail  * @sd_idx: segment descriptor index
102d1850c00SMustafa Ismail  * @pd_idx: page descriptor index
103d1850c00SMustafa Ismail  */
irdma_invalidate_pf_hmc_pd(struct irdma_sc_dev * dev,u32 sd_idx,u32 pd_idx)104d1850c00SMustafa Ismail static inline void irdma_invalidate_pf_hmc_pd(struct irdma_sc_dev *dev, u32 sd_idx,
105d1850c00SMustafa Ismail 					      u32 pd_idx)
106d1850c00SMustafa Ismail {
107d1850c00SMustafa Ismail 	u32 val = FIELD_PREP(IRDMA_PFHMC_PDINV_PMSDIDX, sd_idx) |
108d1850c00SMustafa Ismail 		  FIELD_PREP(IRDMA_PFHMC_PDINV_PMSDPARTSEL, 1) |
109d1850c00SMustafa Ismail 		  FIELD_PREP(IRDMA_PFHMC_PDINV_PMPDIDX, pd_idx);
110d1850c00SMustafa Ismail 
111d1850c00SMustafa Ismail 	writel(val, dev->hw_regs[IRDMA_PFHMC_PDINV]);
112d1850c00SMustafa Ismail }
113d1850c00SMustafa Ismail 
114d1850c00SMustafa Ismail /**
115d1850c00SMustafa Ismail  * irdma_hmc_sd_one - setup 1 sd entry for cqp
116d1850c00SMustafa Ismail  * @dev: pointer to the device structure
117d1850c00SMustafa Ismail  * @hmc_fn_id: hmc's function id
118d1850c00SMustafa Ismail  * @pa: physical addr
119d1850c00SMustafa Ismail  * @sd_idx: sd index
120d1850c00SMustafa Ismail  * @type: paged or direct sd
121d1850c00SMustafa Ismail  * @setsd: flag to set or clear sd
122d1850c00SMustafa Ismail  */
irdma_hmc_sd_one(struct irdma_sc_dev * dev,u8 hmc_fn_id,u64 pa,u32 sd_idx,enum irdma_sd_entry_type type,bool setsd)1232c4b14eaSShiraz Saleem int irdma_hmc_sd_one(struct irdma_sc_dev *dev, u8 hmc_fn_id, u64 pa, u32 sd_idx,
1242c4b14eaSShiraz Saleem 		     enum irdma_sd_entry_type type, bool setsd)
125d1850c00SMustafa Ismail {
126d1850c00SMustafa Ismail 	struct irdma_update_sds_info sdinfo;
127d1850c00SMustafa Ismail 
128d1850c00SMustafa Ismail 	sdinfo.cnt = 1;
129d1850c00SMustafa Ismail 	sdinfo.hmc_fn_id = hmc_fn_id;
130d1850c00SMustafa Ismail 	if (setsd)
131d1850c00SMustafa Ismail 		irdma_set_sd_entry(pa, sd_idx, type, sdinfo.entry);
132d1850c00SMustafa Ismail 	else
133d1850c00SMustafa Ismail 		irdma_clr_sd_entry(sd_idx, type, sdinfo.entry);
134d1850c00SMustafa Ismail 	return dev->cqp->process_cqp_sds(dev, &sdinfo);
135d1850c00SMustafa Ismail }
136d1850c00SMustafa Ismail 
137d1850c00SMustafa Ismail /**
138d1850c00SMustafa Ismail  * irdma_hmc_sd_grp - setup group of sd entries for cqp
139d1850c00SMustafa Ismail  * @dev: pointer to the device structure
140d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information struct
141d1850c00SMustafa Ismail  * @sd_index: sd index
142d1850c00SMustafa Ismail  * @sd_cnt: number of sd entries
143d1850c00SMustafa Ismail  * @setsd: flag to set or clear sd
144d1850c00SMustafa Ismail  */
irdma_hmc_sd_grp(struct irdma_sc_dev * dev,struct irdma_hmc_info * hmc_info,u32 sd_index,u32 sd_cnt,bool setsd)1452c4b14eaSShiraz Saleem static int irdma_hmc_sd_grp(struct irdma_sc_dev *dev,
1462c4b14eaSShiraz Saleem 			    struct irdma_hmc_info *hmc_info, u32 sd_index,
1472c4b14eaSShiraz Saleem 			    u32 sd_cnt, bool setsd)
148d1850c00SMustafa Ismail {
149d1850c00SMustafa Ismail 	struct irdma_hmc_sd_entry *sd_entry;
150d1850c00SMustafa Ismail 	struct irdma_update_sds_info sdinfo = {};
151d1850c00SMustafa Ismail 	u64 pa;
152d1850c00SMustafa Ismail 	u32 i;
1532c4b14eaSShiraz Saleem 	int ret_code = 0;
154d1850c00SMustafa Ismail 
155d1850c00SMustafa Ismail 	sdinfo.hmc_fn_id = hmc_info->hmc_fn_id;
156d1850c00SMustafa Ismail 	for (i = sd_index; i < sd_index + sd_cnt; i++) {
157d1850c00SMustafa Ismail 		sd_entry = &hmc_info->sd_table.sd_entry[i];
158d1850c00SMustafa Ismail 		if (!sd_entry || (!sd_entry->valid && setsd) ||
159d1850c00SMustafa Ismail 		    (sd_entry->valid && !setsd))
160d1850c00SMustafa Ismail 			continue;
161d1850c00SMustafa Ismail 		if (setsd) {
162d1850c00SMustafa Ismail 			pa = (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED) ?
163d1850c00SMustafa Ismail 				     sd_entry->u.pd_table.pd_page_addr.pa :
164d1850c00SMustafa Ismail 				     sd_entry->u.bp.addr.pa;
165d1850c00SMustafa Ismail 			irdma_set_sd_entry(pa, i, sd_entry->entry_type,
166d1850c00SMustafa Ismail 					   &sdinfo.entry[sdinfo.cnt]);
167d1850c00SMustafa Ismail 		} else {
168d1850c00SMustafa Ismail 			irdma_clr_sd_entry(i, sd_entry->entry_type,
169d1850c00SMustafa Ismail 					   &sdinfo.entry[sdinfo.cnt]);
170d1850c00SMustafa Ismail 		}
171d1850c00SMustafa Ismail 		sdinfo.cnt++;
172d1850c00SMustafa Ismail 		if (sdinfo.cnt == IRDMA_MAX_SD_ENTRIES) {
173d1850c00SMustafa Ismail 			ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
174d1850c00SMustafa Ismail 			if (ret_code) {
175d1850c00SMustafa Ismail 				ibdev_dbg(to_ibdev(dev),
176d1850c00SMustafa Ismail 					  "HMC: sd_programming failed err=%d\n",
177d1850c00SMustafa Ismail 					  ret_code);
178d1850c00SMustafa Ismail 				return ret_code;
179d1850c00SMustafa Ismail 			}
180d1850c00SMustafa Ismail 
181d1850c00SMustafa Ismail 			sdinfo.cnt = 0;
182d1850c00SMustafa Ismail 		}
183d1850c00SMustafa Ismail 	}
184d1850c00SMustafa Ismail 	if (sdinfo.cnt)
185d1850c00SMustafa Ismail 		ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
186d1850c00SMustafa Ismail 
187d1850c00SMustafa Ismail 	return ret_code;
188d1850c00SMustafa Ismail }
189d1850c00SMustafa Ismail 
190d1850c00SMustafa Ismail /**
191d1850c00SMustafa Ismail  * irdma_hmc_finish_add_sd_reg - program sd entries for objects
192d1850c00SMustafa Ismail  * @dev: pointer to the device structure
193d1850c00SMustafa Ismail  * @info: create obj info
194d1850c00SMustafa Ismail  */
irdma_hmc_finish_add_sd_reg(struct irdma_sc_dev * dev,struct irdma_hmc_create_obj_info * info)1952c4b14eaSShiraz Saleem static int irdma_hmc_finish_add_sd_reg(struct irdma_sc_dev *dev,
196d1850c00SMustafa Ismail 				       struct irdma_hmc_create_obj_info *info)
197d1850c00SMustafa Ismail {
198d1850c00SMustafa Ismail 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
1992c4b14eaSShiraz Saleem 		return -EINVAL;
200d1850c00SMustafa Ismail 
201d1850c00SMustafa Ismail 	if ((info->start_idx + info->count) >
202d1850c00SMustafa Ismail 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt)
2032c4b14eaSShiraz Saleem 		return -EINVAL;
204d1850c00SMustafa Ismail 
205d1850c00SMustafa Ismail 	if (!info->add_sd_cnt)
206d1850c00SMustafa Ismail 		return 0;
207d1850c00SMustafa Ismail 	return irdma_hmc_sd_grp(dev, info->hmc_info,
208d1850c00SMustafa Ismail 				info->hmc_info->sd_indexes[0], info->add_sd_cnt,
209d1850c00SMustafa Ismail 				true);
210d1850c00SMustafa Ismail }
211d1850c00SMustafa Ismail 
212d1850c00SMustafa Ismail /**
213d1850c00SMustafa Ismail  * irdma_sc_create_hmc_obj - allocate backing store for hmc objects
214d1850c00SMustafa Ismail  * @dev: pointer to the device structure
215d1850c00SMustafa Ismail  * @info: pointer to irdma_hmc_create_obj_info struct
216d1850c00SMustafa Ismail  *
217d1850c00SMustafa Ismail  * This will allocate memory for PDs and backing pages and populate
218d1850c00SMustafa Ismail  * the sd and pd entries.
219d1850c00SMustafa Ismail  */
irdma_sc_create_hmc_obj(struct irdma_sc_dev * dev,struct irdma_hmc_create_obj_info * info)2202c4b14eaSShiraz Saleem int irdma_sc_create_hmc_obj(struct irdma_sc_dev *dev,
221d1850c00SMustafa Ismail 			    struct irdma_hmc_create_obj_info *info)
222d1850c00SMustafa Ismail {
223d1850c00SMustafa Ismail 	struct irdma_hmc_sd_entry *sd_entry;
224d1850c00SMustafa Ismail 	u32 sd_idx, sd_lmt;
225d1850c00SMustafa Ismail 	u32 pd_idx = 0, pd_lmt = 0;
226d1850c00SMustafa Ismail 	u32 pd_idx1 = 0, pd_lmt1 = 0;
227d1850c00SMustafa Ismail 	u32 i, j;
228d1850c00SMustafa Ismail 	bool pd_error = false;
2292c4b14eaSShiraz Saleem 	int ret_code = 0;
230d1850c00SMustafa Ismail 
231d1850c00SMustafa Ismail 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
2322c4b14eaSShiraz Saleem 		return -EINVAL;
233d1850c00SMustafa Ismail 
234d1850c00SMustafa Ismail 	if ((info->start_idx + info->count) >
235d1850c00SMustafa Ismail 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
236d1850c00SMustafa Ismail 		ibdev_dbg(to_ibdev(dev),
237d1850c00SMustafa Ismail 			  "HMC: error type %u, start = %u, req cnt %u, cnt = %u\n",
238d1850c00SMustafa Ismail 			  info->rsrc_type, info->start_idx, info->count,
239d1850c00SMustafa Ismail 			  info->hmc_info->hmc_obj[info->rsrc_type].cnt);
2402c4b14eaSShiraz Saleem 		return -EINVAL;
241d1850c00SMustafa Ismail 	}
242d1850c00SMustafa Ismail 
243d1850c00SMustafa Ismail 	irdma_find_sd_index_limit(info->hmc_info, info->rsrc_type,
244d1850c00SMustafa Ismail 				  info->start_idx, info->count, &sd_idx,
245d1850c00SMustafa Ismail 				  &sd_lmt);
246d1850c00SMustafa Ismail 	if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
247d1850c00SMustafa Ismail 	    sd_lmt > info->hmc_info->sd_table.sd_cnt) {
2482c4b14eaSShiraz Saleem 		return -EINVAL;
249d1850c00SMustafa Ismail 	}
250d1850c00SMustafa Ismail 
251d1850c00SMustafa Ismail 	irdma_find_pd_index_limit(info->hmc_info, info->rsrc_type,
252d1850c00SMustafa Ismail 				  info->start_idx, info->count, &pd_idx,
253d1850c00SMustafa Ismail 				  &pd_lmt);
254d1850c00SMustafa Ismail 
255d1850c00SMustafa Ismail 	for (j = sd_idx; j < sd_lmt; j++) {
256d1850c00SMustafa Ismail 		ret_code = irdma_add_sd_table_entry(dev->hw, info->hmc_info, j,
257d1850c00SMustafa Ismail 						    info->entry_type,
258d1850c00SMustafa Ismail 						    IRDMA_HMC_DIRECT_BP_SIZE);
259d1850c00SMustafa Ismail 		if (ret_code)
260d1850c00SMustafa Ismail 			goto exit_sd_error;
261d1850c00SMustafa Ismail 
262d1850c00SMustafa Ismail 		sd_entry = &info->hmc_info->sd_table.sd_entry[j];
263d1850c00SMustafa Ismail 		if (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED &&
264d1850c00SMustafa Ismail 		    (dev->hmc_info == info->hmc_info &&
265d1850c00SMustafa Ismail 		     info->rsrc_type != IRDMA_HMC_IW_PBLE)) {
266d1850c00SMustafa Ismail 			pd_idx1 = max(pd_idx, (j * IRDMA_HMC_MAX_BP_COUNT));
267d1850c00SMustafa Ismail 			pd_lmt1 = min(pd_lmt, (j + 1) * IRDMA_HMC_MAX_BP_COUNT);
268d1850c00SMustafa Ismail 			for (i = pd_idx1; i < pd_lmt1; i++) {
269d1850c00SMustafa Ismail 				/* update the pd table entry */
270d1850c00SMustafa Ismail 				ret_code = irdma_add_pd_table_entry(dev,
271d1850c00SMustafa Ismail 								    info->hmc_info,
272d1850c00SMustafa Ismail 								    i, NULL);
273d1850c00SMustafa Ismail 				if (ret_code) {
274d1850c00SMustafa Ismail 					pd_error = true;
275d1850c00SMustafa Ismail 					break;
276d1850c00SMustafa Ismail 				}
277d1850c00SMustafa Ismail 			}
278d1850c00SMustafa Ismail 			if (pd_error) {
279d1850c00SMustafa Ismail 				while (i && (i > pd_idx1)) {
280d1850c00SMustafa Ismail 					irdma_remove_pd_bp(dev, info->hmc_info,
281d1850c00SMustafa Ismail 							   i - 1);
282d1850c00SMustafa Ismail 					i--;
283d1850c00SMustafa Ismail 				}
284d1850c00SMustafa Ismail 			}
285d1850c00SMustafa Ismail 		}
286d1850c00SMustafa Ismail 		if (sd_entry->valid)
287d1850c00SMustafa Ismail 			continue;
288d1850c00SMustafa Ismail 
289d1850c00SMustafa Ismail 		info->hmc_info->sd_indexes[info->add_sd_cnt] = (u16)j;
290d1850c00SMustafa Ismail 		info->add_sd_cnt++;
291d1850c00SMustafa Ismail 		sd_entry->valid = true;
292d1850c00SMustafa Ismail 	}
293d1850c00SMustafa Ismail 	return irdma_hmc_finish_add_sd_reg(dev, info);
294d1850c00SMustafa Ismail 
295d1850c00SMustafa Ismail exit_sd_error:
296d1850c00SMustafa Ismail 	while (j && (j > sd_idx)) {
297d1850c00SMustafa Ismail 		sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1];
298d1850c00SMustafa Ismail 		switch (sd_entry->entry_type) {
299d1850c00SMustafa Ismail 		case IRDMA_SD_TYPE_PAGED:
300d1850c00SMustafa Ismail 			pd_idx1 = max(pd_idx, (j - 1) * IRDMA_HMC_MAX_BP_COUNT);
301d1850c00SMustafa Ismail 			pd_lmt1 = min(pd_lmt, (j * IRDMA_HMC_MAX_BP_COUNT));
302d1850c00SMustafa Ismail 			for (i = pd_idx1; i < pd_lmt1; i++)
303d1850c00SMustafa Ismail 				irdma_prep_remove_pd_page(info->hmc_info, i);
304d1850c00SMustafa Ismail 			break;
305d1850c00SMustafa Ismail 		case IRDMA_SD_TYPE_DIRECT:
306d1850c00SMustafa Ismail 			irdma_prep_remove_pd_page(info->hmc_info, (j - 1));
307d1850c00SMustafa Ismail 			break;
308d1850c00SMustafa Ismail 		default:
3092c4b14eaSShiraz Saleem 			ret_code = -EINVAL;
310d1850c00SMustafa Ismail 			break;
311d1850c00SMustafa Ismail 		}
312d1850c00SMustafa Ismail 		j--;
313d1850c00SMustafa Ismail 	}
314d1850c00SMustafa Ismail 
315d1850c00SMustafa Ismail 	return ret_code;
316d1850c00SMustafa Ismail }
317d1850c00SMustafa Ismail 
318d1850c00SMustafa Ismail /**
319d1850c00SMustafa Ismail  * irdma_finish_del_sd_reg - delete sd entries for objects
320d1850c00SMustafa Ismail  * @dev: pointer to the device structure
321d1850c00SMustafa Ismail  * @info: dele obj info
322d1850c00SMustafa Ismail  * @reset: true if called before reset
323d1850c00SMustafa Ismail  */
irdma_finish_del_sd_reg(struct irdma_sc_dev * dev,struct irdma_hmc_del_obj_info * info,bool reset)3242c4b14eaSShiraz Saleem static int irdma_finish_del_sd_reg(struct irdma_sc_dev *dev,
3252c4b14eaSShiraz Saleem 				   struct irdma_hmc_del_obj_info *info,
3262c4b14eaSShiraz Saleem 				   bool reset)
327d1850c00SMustafa Ismail {
328d1850c00SMustafa Ismail 	struct irdma_hmc_sd_entry *sd_entry;
3292c4b14eaSShiraz Saleem 	int ret_code = 0;
330d1850c00SMustafa Ismail 	u32 i, sd_idx;
331d1850c00SMustafa Ismail 	struct irdma_dma_mem *mem;
332d1850c00SMustafa Ismail 
333d1850c00SMustafa Ismail 	if (!reset)
334d1850c00SMustafa Ismail 		ret_code = irdma_hmc_sd_grp(dev, info->hmc_info,
335d1850c00SMustafa Ismail 					    info->hmc_info->sd_indexes[0],
336d1850c00SMustafa Ismail 					    info->del_sd_cnt, false);
337d1850c00SMustafa Ismail 
338d1850c00SMustafa Ismail 	if (ret_code)
339d1850c00SMustafa Ismail 		ibdev_dbg(to_ibdev(dev), "HMC: error cqp sd sd_grp\n");
340d1850c00SMustafa Ismail 	for (i = 0; i < info->del_sd_cnt; i++) {
341d1850c00SMustafa Ismail 		sd_idx = info->hmc_info->sd_indexes[i];
342d1850c00SMustafa Ismail 		sd_entry = &info->hmc_info->sd_table.sd_entry[sd_idx];
343d1850c00SMustafa Ismail 		mem = (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED) ?
344d1850c00SMustafa Ismail 			      &sd_entry->u.pd_table.pd_page_addr :
345d1850c00SMustafa Ismail 			      &sd_entry->u.bp.addr;
346d1850c00SMustafa Ismail 
347d1850c00SMustafa Ismail 		if (!mem || !mem->va) {
348d1850c00SMustafa Ismail 			ibdev_dbg(to_ibdev(dev), "HMC: error cqp sd mem\n");
349d1850c00SMustafa Ismail 		} else {
350d1850c00SMustafa Ismail 			dma_free_coherent(dev->hw->device, mem->size, mem->va,
351d1850c00SMustafa Ismail 					  mem->pa);
352d1850c00SMustafa Ismail 			mem->va = NULL;
353d1850c00SMustafa Ismail 		}
354d1850c00SMustafa Ismail 	}
355d1850c00SMustafa Ismail 
356d1850c00SMustafa Ismail 	return ret_code;
357d1850c00SMustafa Ismail }
358d1850c00SMustafa Ismail 
359d1850c00SMustafa Ismail /**
360d1850c00SMustafa Ismail  * irdma_sc_del_hmc_obj - remove pe hmc objects
361d1850c00SMustafa Ismail  * @dev: pointer to the device structure
362d1850c00SMustafa Ismail  * @info: pointer to irdma_hmc_del_obj_info struct
363d1850c00SMustafa Ismail  * @reset: true if called before reset
364d1850c00SMustafa Ismail  *
365d1850c00SMustafa Ismail  * This will de-populate the SDs and PDs.  It frees
366d1850c00SMustafa Ismail  * the memory for PDS and backing storage.  After this function is returned,
367d1850c00SMustafa Ismail  * caller should deallocate memory allocated previously for
368d1850c00SMustafa Ismail  * book-keeping information about PDs and backing storage.
369d1850c00SMustafa Ismail  */
irdma_sc_del_hmc_obj(struct irdma_sc_dev * dev,struct irdma_hmc_del_obj_info * info,bool reset)3702c4b14eaSShiraz Saleem int irdma_sc_del_hmc_obj(struct irdma_sc_dev *dev,
3712c4b14eaSShiraz Saleem 			 struct irdma_hmc_del_obj_info *info, bool reset)
372d1850c00SMustafa Ismail {
373d1850c00SMustafa Ismail 	struct irdma_hmc_pd_table *pd_table;
374d1850c00SMustafa Ismail 	u32 sd_idx, sd_lmt;
375d1850c00SMustafa Ismail 	u32 pd_idx, pd_lmt, rel_pd_idx;
376d1850c00SMustafa Ismail 	u32 i, j;
3772c4b14eaSShiraz Saleem 	int ret_code = 0;
378d1850c00SMustafa Ismail 
379d1850c00SMustafa Ismail 	if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
380d1850c00SMustafa Ismail 		ibdev_dbg(to_ibdev(dev),
381d1850c00SMustafa Ismail 			  "HMC: error start_idx[%04d]  >= [type %04d].cnt[%04d]\n",
382d1850c00SMustafa Ismail 			  info->start_idx, info->rsrc_type,
383d1850c00SMustafa Ismail 			  info->hmc_info->hmc_obj[info->rsrc_type].cnt);
3842c4b14eaSShiraz Saleem 		return -EINVAL;
385d1850c00SMustafa Ismail 	}
386d1850c00SMustafa Ismail 
387d1850c00SMustafa Ismail 	if ((info->start_idx + info->count) >
388d1850c00SMustafa Ismail 	    info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
389d1850c00SMustafa Ismail 		ibdev_dbg(to_ibdev(dev),
390d1850c00SMustafa Ismail 			  "HMC: error start_idx[%04d] + count %04d  >= [type %04d].cnt[%04d]\n",
391d1850c00SMustafa Ismail 			  info->start_idx, info->count, info->rsrc_type,
392d1850c00SMustafa Ismail 			  info->hmc_info->hmc_obj[info->rsrc_type].cnt);
3932c4b14eaSShiraz Saleem 		return -EINVAL;
394d1850c00SMustafa Ismail 	}
395d1850c00SMustafa Ismail 
396d1850c00SMustafa Ismail 	irdma_find_pd_index_limit(info->hmc_info, info->rsrc_type,
397d1850c00SMustafa Ismail 				  info->start_idx, info->count, &pd_idx,
398d1850c00SMustafa Ismail 				  &pd_lmt);
399d1850c00SMustafa Ismail 
400d1850c00SMustafa Ismail 	for (j = pd_idx; j < pd_lmt; j++) {
401d1850c00SMustafa Ismail 		sd_idx = j / IRDMA_HMC_PD_CNT_IN_SD;
402d1850c00SMustafa Ismail 
403d1850c00SMustafa Ismail 		if (!info->hmc_info->sd_table.sd_entry[sd_idx].valid)
404d1850c00SMustafa Ismail 			continue;
405d1850c00SMustafa Ismail 
406d1850c00SMustafa Ismail 		if (info->hmc_info->sd_table.sd_entry[sd_idx].entry_type !=
407d1850c00SMustafa Ismail 		    IRDMA_SD_TYPE_PAGED)
408d1850c00SMustafa Ismail 			continue;
409d1850c00SMustafa Ismail 
410d1850c00SMustafa Ismail 		rel_pd_idx = j % IRDMA_HMC_PD_CNT_IN_SD;
411d1850c00SMustafa Ismail 		pd_table = &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
412d1850c00SMustafa Ismail 		if (pd_table->pd_entry &&
413d1850c00SMustafa Ismail 		    pd_table->pd_entry[rel_pd_idx].valid) {
414d1850c00SMustafa Ismail 			ret_code = irdma_remove_pd_bp(dev, info->hmc_info, j);
415d1850c00SMustafa Ismail 			if (ret_code) {
416d1850c00SMustafa Ismail 				ibdev_dbg(to_ibdev(dev),
417d1850c00SMustafa Ismail 					  "HMC: remove_pd_bp error\n");
418d1850c00SMustafa Ismail 				return ret_code;
419d1850c00SMustafa Ismail 			}
420d1850c00SMustafa Ismail 		}
421d1850c00SMustafa Ismail 	}
422d1850c00SMustafa Ismail 
423d1850c00SMustafa Ismail 	irdma_find_sd_index_limit(info->hmc_info, info->rsrc_type,
424d1850c00SMustafa Ismail 				  info->start_idx, info->count, &sd_idx,
425d1850c00SMustafa Ismail 				  &sd_lmt);
426d1850c00SMustafa Ismail 	if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
427d1850c00SMustafa Ismail 	    sd_lmt > info->hmc_info->sd_table.sd_cnt) {
428d1850c00SMustafa Ismail 		ibdev_dbg(to_ibdev(dev), "HMC: invalid sd_idx\n");
4292c4b14eaSShiraz Saleem 		return -EINVAL;
430d1850c00SMustafa Ismail 	}
431d1850c00SMustafa Ismail 
432d1850c00SMustafa Ismail 	for (i = sd_idx; i < sd_lmt; i++) {
433d1850c00SMustafa Ismail 		pd_table = &info->hmc_info->sd_table.sd_entry[i].u.pd_table;
434d1850c00SMustafa Ismail 		if (!info->hmc_info->sd_table.sd_entry[i].valid)
435d1850c00SMustafa Ismail 			continue;
436d1850c00SMustafa Ismail 		switch (info->hmc_info->sd_table.sd_entry[i].entry_type) {
437d1850c00SMustafa Ismail 		case IRDMA_SD_TYPE_DIRECT:
438d1850c00SMustafa Ismail 			ret_code = irdma_prep_remove_sd_bp(info->hmc_info, i);
439d1850c00SMustafa Ismail 			if (!ret_code) {
440d1850c00SMustafa Ismail 				info->hmc_info->sd_indexes[info->del_sd_cnt] =
441d1850c00SMustafa Ismail 					(u16)i;
442d1850c00SMustafa Ismail 				info->del_sd_cnt++;
443d1850c00SMustafa Ismail 			}
444d1850c00SMustafa Ismail 			break;
445d1850c00SMustafa Ismail 		case IRDMA_SD_TYPE_PAGED:
446d1850c00SMustafa Ismail 			ret_code = irdma_prep_remove_pd_page(info->hmc_info, i);
447d1850c00SMustafa Ismail 			if (ret_code)
448d1850c00SMustafa Ismail 				break;
449d1850c00SMustafa Ismail 			if (dev->hmc_info != info->hmc_info &&
450d1850c00SMustafa Ismail 			    info->rsrc_type == IRDMA_HMC_IW_PBLE &&
451d1850c00SMustafa Ismail 			    pd_table->pd_entry) {
452d1850c00SMustafa Ismail 				kfree(pd_table->pd_entry_virt_mem.va);
453d1850c00SMustafa Ismail 				pd_table->pd_entry = NULL;
454d1850c00SMustafa Ismail 			}
455d1850c00SMustafa Ismail 			info->hmc_info->sd_indexes[info->del_sd_cnt] = (u16)i;
456d1850c00SMustafa Ismail 			info->del_sd_cnt++;
457d1850c00SMustafa Ismail 			break;
458d1850c00SMustafa Ismail 		default:
459d1850c00SMustafa Ismail 			break;
460d1850c00SMustafa Ismail 		}
461d1850c00SMustafa Ismail 	}
462d1850c00SMustafa Ismail 	return irdma_finish_del_sd_reg(dev, info, reset);
463d1850c00SMustafa Ismail }
464d1850c00SMustafa Ismail 
465d1850c00SMustafa Ismail /**
466d1850c00SMustafa Ismail  * irdma_add_sd_table_entry - Adds a segment descriptor to the table
467d1850c00SMustafa Ismail  * @hw: pointer to our hw struct
468d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information struct
469d1850c00SMustafa Ismail  * @sd_index: segment descriptor index to manipulate
470d1850c00SMustafa Ismail  * @type: what type of segment descriptor we're manipulating
471d1850c00SMustafa Ismail  * @direct_mode_sz: size to alloc in direct mode
472d1850c00SMustafa Ismail  */
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)4732c4b14eaSShiraz Saleem int irdma_add_sd_table_entry(struct irdma_hw *hw,
4742c4b14eaSShiraz Saleem 			     struct irdma_hmc_info *hmc_info, u32 sd_index,
4752c4b14eaSShiraz Saleem 			     enum irdma_sd_entry_type type, u64 direct_mode_sz)
476d1850c00SMustafa Ismail {
477d1850c00SMustafa Ismail 	struct irdma_hmc_sd_entry *sd_entry;
478d1850c00SMustafa Ismail 	struct irdma_dma_mem dma_mem;
479d1850c00SMustafa Ismail 	u64 alloc_len;
480d1850c00SMustafa Ismail 
481d1850c00SMustafa Ismail 	sd_entry = &hmc_info->sd_table.sd_entry[sd_index];
482d1850c00SMustafa Ismail 	if (!sd_entry->valid) {
483d1850c00SMustafa Ismail 		if (type == IRDMA_SD_TYPE_PAGED)
484d1850c00SMustafa Ismail 			alloc_len = IRDMA_HMC_PAGED_BP_SIZE;
485d1850c00SMustafa Ismail 		else
486d1850c00SMustafa Ismail 			alloc_len = direct_mode_sz;
487d1850c00SMustafa Ismail 
488d1850c00SMustafa Ismail 		/* allocate a 4K pd page or 2M backing page */
489d1850c00SMustafa Ismail 		dma_mem.size = ALIGN(alloc_len, IRDMA_HMC_PD_BP_BUF_ALIGNMENT);
490d1850c00SMustafa Ismail 		dma_mem.va = dma_alloc_coherent(hw->device, dma_mem.size,
491d1850c00SMustafa Ismail 						&dma_mem.pa, GFP_KERNEL);
492d1850c00SMustafa Ismail 		if (!dma_mem.va)
4932c4b14eaSShiraz Saleem 			return -ENOMEM;
494d1850c00SMustafa Ismail 		if (type == IRDMA_SD_TYPE_PAGED) {
495d1850c00SMustafa Ismail 			struct irdma_virt_mem *vmem =
496d1850c00SMustafa Ismail 				&sd_entry->u.pd_table.pd_entry_virt_mem;
497d1850c00SMustafa Ismail 
498d1850c00SMustafa Ismail 			vmem->size = sizeof(struct irdma_hmc_pd_entry) * 512;
499d1850c00SMustafa Ismail 			vmem->va = kzalloc(vmem->size, GFP_KERNEL);
500d1850c00SMustafa Ismail 			if (!vmem->va) {
501d1850c00SMustafa Ismail 				dma_free_coherent(hw->device, dma_mem.size,
502d1850c00SMustafa Ismail 						  dma_mem.va, dma_mem.pa);
503d1850c00SMustafa Ismail 				dma_mem.va = NULL;
5042c4b14eaSShiraz Saleem 				return -ENOMEM;
505d1850c00SMustafa Ismail 			}
506d1850c00SMustafa Ismail 			sd_entry->u.pd_table.pd_entry = vmem->va;
507d1850c00SMustafa Ismail 
508d1850c00SMustafa Ismail 			memcpy(&sd_entry->u.pd_table.pd_page_addr, &dma_mem,
509d1850c00SMustafa Ismail 			       sizeof(sd_entry->u.pd_table.pd_page_addr));
510d1850c00SMustafa Ismail 		} else {
511d1850c00SMustafa Ismail 			memcpy(&sd_entry->u.bp.addr, &dma_mem,
512d1850c00SMustafa Ismail 			       sizeof(sd_entry->u.bp.addr));
513d1850c00SMustafa Ismail 
514d1850c00SMustafa Ismail 			sd_entry->u.bp.sd_pd_index = sd_index;
515d1850c00SMustafa Ismail 		}
516d1850c00SMustafa Ismail 
517d1850c00SMustafa Ismail 		hmc_info->sd_table.sd_entry[sd_index].entry_type = type;
518d1850c00SMustafa Ismail 		hmc_info->sd_table.use_cnt++;
519d1850c00SMustafa Ismail 	}
520d1850c00SMustafa Ismail 	if (sd_entry->entry_type == IRDMA_SD_TYPE_DIRECT)
521d1850c00SMustafa Ismail 		sd_entry->u.bp.use_cnt++;
522d1850c00SMustafa Ismail 
523d1850c00SMustafa Ismail 	return 0;
524d1850c00SMustafa Ismail }
525d1850c00SMustafa Ismail 
526d1850c00SMustafa Ismail /**
527d1850c00SMustafa Ismail  * irdma_add_pd_table_entry - Adds page descriptor to the specified table
528d1850c00SMustafa Ismail  * @dev: pointer to our device structure
529d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information structure
530d1850c00SMustafa Ismail  * @pd_index: which page descriptor index to manipulate
531d1850c00SMustafa Ismail  * @rsrc_pg: if not NULL, use preallocated page instead of allocating new one.
532d1850c00SMustafa Ismail  *
533d1850c00SMustafa Ismail  * This function:
534d1850c00SMustafa Ismail  *	1. Initializes the pd entry
535d1850c00SMustafa Ismail  *	2. Adds pd_entry in the pd_table
536d1850c00SMustafa Ismail  *	3. Mark the entry valid in irdma_hmc_pd_entry structure
537d1850c00SMustafa Ismail  *	4. Initializes the pd_entry's ref count to 1
538d1850c00SMustafa Ismail  * assumptions:
539d1850c00SMustafa Ismail  *	1. The memory for pd should be pinned down, physically contiguous and
540d1850c00SMustafa Ismail  *	   aligned on 4K boundary and zeroed memory.
541d1850c00SMustafa Ismail  *	2. It should be 4K in size.
542d1850c00SMustafa Ismail  */
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)5432c4b14eaSShiraz Saleem int irdma_add_pd_table_entry(struct irdma_sc_dev *dev,
5442c4b14eaSShiraz Saleem 			     struct irdma_hmc_info *hmc_info, u32 pd_index,
545d1850c00SMustafa Ismail 			     struct irdma_dma_mem *rsrc_pg)
546d1850c00SMustafa Ismail {
547d1850c00SMustafa Ismail 	struct irdma_hmc_pd_table *pd_table;
548d1850c00SMustafa Ismail 	struct irdma_hmc_pd_entry *pd_entry;
549d1850c00SMustafa Ismail 	struct irdma_dma_mem mem;
550d1850c00SMustafa Ismail 	struct irdma_dma_mem *page = &mem;
551d1850c00SMustafa Ismail 	u32 sd_idx, rel_pd_idx;
552d1850c00SMustafa Ismail 	u64 *pd_addr;
553d1850c00SMustafa Ismail 	u64 page_desc;
554d1850c00SMustafa Ismail 
555d1850c00SMustafa Ismail 	if (pd_index / IRDMA_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt)
5562c4b14eaSShiraz Saleem 		return -EINVAL;
557d1850c00SMustafa Ismail 
558d1850c00SMustafa Ismail 	sd_idx = (pd_index / IRDMA_HMC_PD_CNT_IN_SD);
559d1850c00SMustafa Ismail 	if (hmc_info->sd_table.sd_entry[sd_idx].entry_type !=
560d1850c00SMustafa Ismail 	    IRDMA_SD_TYPE_PAGED)
561d1850c00SMustafa Ismail 		return 0;
562d1850c00SMustafa Ismail 
563d1850c00SMustafa Ismail 	rel_pd_idx = (pd_index % IRDMA_HMC_PD_CNT_IN_SD);
564d1850c00SMustafa Ismail 	pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
565d1850c00SMustafa Ismail 	pd_entry = &pd_table->pd_entry[rel_pd_idx];
566d1850c00SMustafa Ismail 	if (!pd_entry->valid) {
567d1850c00SMustafa Ismail 		if (rsrc_pg) {
568d1850c00SMustafa Ismail 			pd_entry->rsrc_pg = true;
569d1850c00SMustafa Ismail 			page = rsrc_pg;
570d1850c00SMustafa Ismail 		} else {
571d1850c00SMustafa Ismail 			page->size = ALIGN(IRDMA_HMC_PAGED_BP_SIZE,
572d1850c00SMustafa Ismail 					   IRDMA_HMC_PD_BP_BUF_ALIGNMENT);
573d1850c00SMustafa Ismail 			page->va = dma_alloc_coherent(dev->hw->device,
574d1850c00SMustafa Ismail 						      page->size, &page->pa,
575d1850c00SMustafa Ismail 						      GFP_KERNEL);
576d1850c00SMustafa Ismail 			if (!page->va)
5772c4b14eaSShiraz Saleem 				return -ENOMEM;
578d1850c00SMustafa Ismail 
579d1850c00SMustafa Ismail 			pd_entry->rsrc_pg = false;
580d1850c00SMustafa Ismail 		}
581d1850c00SMustafa Ismail 
582d1850c00SMustafa Ismail 		memcpy(&pd_entry->bp.addr, page, sizeof(pd_entry->bp.addr));
583d1850c00SMustafa Ismail 		pd_entry->bp.sd_pd_index = pd_index;
584d1850c00SMustafa Ismail 		pd_entry->bp.entry_type = IRDMA_SD_TYPE_PAGED;
585d1850c00SMustafa Ismail 		page_desc = page->pa | 0x1;
586d1850c00SMustafa Ismail 		pd_addr = pd_table->pd_page_addr.va;
587d1850c00SMustafa Ismail 		pd_addr += rel_pd_idx;
588d1850c00SMustafa Ismail 		memcpy(pd_addr, &page_desc, sizeof(*pd_addr));
589d1850c00SMustafa Ismail 		pd_entry->sd_index = sd_idx;
590d1850c00SMustafa Ismail 		pd_entry->valid = true;
591d1850c00SMustafa Ismail 		pd_table->use_cnt++;
592d1850c00SMustafa Ismail 		irdma_invalidate_pf_hmc_pd(dev, sd_idx, rel_pd_idx);
593d1850c00SMustafa Ismail 	}
594d1850c00SMustafa Ismail 	pd_entry->bp.use_cnt++;
595d1850c00SMustafa Ismail 
596d1850c00SMustafa Ismail 	return 0;
597d1850c00SMustafa Ismail }
598d1850c00SMustafa Ismail 
599d1850c00SMustafa Ismail /**
600d1850c00SMustafa Ismail  * irdma_remove_pd_bp - remove a backing page from a page descriptor
601d1850c00SMustafa Ismail  * @dev: pointer to our HW structure
602d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information structure
603d1850c00SMustafa Ismail  * @idx: the page index
604d1850c00SMustafa Ismail  *
605d1850c00SMustafa Ismail  * This function:
606d1850c00SMustafa Ismail  *	1. Marks the entry in pd table (for paged address mode) or in sd table
607d1850c00SMustafa Ismail  *	   (for direct address mode) invalid.
608d1850c00SMustafa Ismail  *	2. Write to register PMPDINV to invalidate the backing page in FV cache
609d1850c00SMustafa Ismail  *	3. Decrement the ref count for the pd _entry
610d1850c00SMustafa Ismail  * assumptions:
611d1850c00SMustafa Ismail  *	1. Caller can deallocate the memory used by backing storage after this
612d1850c00SMustafa Ismail  *	   function returns.
613d1850c00SMustafa Ismail  */
irdma_remove_pd_bp(struct irdma_sc_dev * dev,struct irdma_hmc_info * hmc_info,u32 idx)6142c4b14eaSShiraz Saleem int irdma_remove_pd_bp(struct irdma_sc_dev *dev,
6152c4b14eaSShiraz Saleem 		       struct irdma_hmc_info *hmc_info, u32 idx)
616d1850c00SMustafa Ismail {
617d1850c00SMustafa Ismail 	struct irdma_hmc_pd_entry *pd_entry;
618d1850c00SMustafa Ismail 	struct irdma_hmc_pd_table *pd_table;
619d1850c00SMustafa Ismail 	struct irdma_hmc_sd_entry *sd_entry;
620d1850c00SMustafa Ismail 	u32 sd_idx, rel_pd_idx;
621d1850c00SMustafa Ismail 	struct irdma_dma_mem *mem;
622d1850c00SMustafa Ismail 	u64 *pd_addr;
623d1850c00SMustafa Ismail 
624d1850c00SMustafa Ismail 	sd_idx = idx / IRDMA_HMC_PD_CNT_IN_SD;
625d1850c00SMustafa Ismail 	rel_pd_idx = idx % IRDMA_HMC_PD_CNT_IN_SD;
626d1850c00SMustafa Ismail 	if (sd_idx >= hmc_info->sd_table.sd_cnt)
6272c4b14eaSShiraz Saleem 		return -EINVAL;
628d1850c00SMustafa Ismail 
629d1850c00SMustafa Ismail 	sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
630d1850c00SMustafa Ismail 	if (sd_entry->entry_type != IRDMA_SD_TYPE_PAGED)
6312c4b14eaSShiraz Saleem 		return -EINVAL;
632d1850c00SMustafa Ismail 
633d1850c00SMustafa Ismail 	pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
634d1850c00SMustafa Ismail 	pd_entry = &pd_table->pd_entry[rel_pd_idx];
635d1850c00SMustafa Ismail 	if (--pd_entry->bp.use_cnt)
636d1850c00SMustafa Ismail 		return 0;
637d1850c00SMustafa Ismail 
638d1850c00SMustafa Ismail 	pd_entry->valid = false;
639d1850c00SMustafa Ismail 	pd_table->use_cnt--;
640d1850c00SMustafa Ismail 	pd_addr = pd_table->pd_page_addr.va;
641d1850c00SMustafa Ismail 	pd_addr += rel_pd_idx;
642d1850c00SMustafa Ismail 	memset(pd_addr, 0, sizeof(u64));
643d1850c00SMustafa Ismail 	irdma_invalidate_pf_hmc_pd(dev, sd_idx, idx);
644d1850c00SMustafa Ismail 
645d1850c00SMustafa Ismail 	if (!pd_entry->rsrc_pg) {
646d1850c00SMustafa Ismail 		mem = &pd_entry->bp.addr;
647d1850c00SMustafa Ismail 		if (!mem || !mem->va)
6482c4b14eaSShiraz Saleem 			return -EINVAL;
649d1850c00SMustafa Ismail 
650d1850c00SMustafa Ismail 		dma_free_coherent(dev->hw->device, mem->size, mem->va,
651d1850c00SMustafa Ismail 				  mem->pa);
652d1850c00SMustafa Ismail 		mem->va = NULL;
653d1850c00SMustafa Ismail 	}
654d1850c00SMustafa Ismail 	if (!pd_table->use_cnt)
655d1850c00SMustafa Ismail 		kfree(pd_table->pd_entry_virt_mem.va);
656d1850c00SMustafa Ismail 
657d1850c00SMustafa Ismail 	return 0;
658d1850c00SMustafa Ismail }
659d1850c00SMustafa Ismail 
660d1850c00SMustafa Ismail /**
661d1850c00SMustafa Ismail  * irdma_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry
662d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information structure
663d1850c00SMustafa Ismail  * @idx: the page index
664d1850c00SMustafa Ismail  */
irdma_prep_remove_sd_bp(struct irdma_hmc_info * hmc_info,u32 idx)6652c4b14eaSShiraz Saleem int irdma_prep_remove_sd_bp(struct irdma_hmc_info *hmc_info, u32 idx)
666d1850c00SMustafa Ismail {
667d1850c00SMustafa Ismail 	struct irdma_hmc_sd_entry *sd_entry;
668d1850c00SMustafa Ismail 
669d1850c00SMustafa Ismail 	sd_entry = &hmc_info->sd_table.sd_entry[idx];
670d1850c00SMustafa Ismail 	if (--sd_entry->u.bp.use_cnt)
6712c4b14eaSShiraz Saleem 		return -EBUSY;
672d1850c00SMustafa Ismail 
673d1850c00SMustafa Ismail 	hmc_info->sd_table.use_cnt--;
674d1850c00SMustafa Ismail 	sd_entry->valid = false;
675d1850c00SMustafa Ismail 
676d1850c00SMustafa Ismail 	return 0;
677d1850c00SMustafa Ismail }
678d1850c00SMustafa Ismail 
679d1850c00SMustafa Ismail /**
680d1850c00SMustafa Ismail  * irdma_prep_remove_pd_page - Prepares to remove a PD page from sd entry.
681d1850c00SMustafa Ismail  * @hmc_info: pointer to the HMC configuration information structure
682d1850c00SMustafa Ismail  * @idx: segment descriptor index to find the relevant page descriptor
683d1850c00SMustafa Ismail  */
irdma_prep_remove_pd_page(struct irdma_hmc_info * hmc_info,u32 idx)6842c4b14eaSShiraz Saleem int irdma_prep_remove_pd_page(struct irdma_hmc_info *hmc_info, u32 idx)
685d1850c00SMustafa Ismail {
686d1850c00SMustafa Ismail 	struct irdma_hmc_sd_entry *sd_entry;
687d1850c00SMustafa Ismail 
688d1850c00SMustafa Ismail 	sd_entry = &hmc_info->sd_table.sd_entry[idx];
689d1850c00SMustafa Ismail 
690d1850c00SMustafa Ismail 	if (sd_entry->u.pd_table.use_cnt)
6912c4b14eaSShiraz Saleem 		return -EBUSY;
692d1850c00SMustafa Ismail 
693d1850c00SMustafa Ismail 	sd_entry->valid = false;
694d1850c00SMustafa Ismail 	hmc_info->sd_table.use_cnt--;
695d1850c00SMustafa Ismail 
696d1850c00SMustafa Ismail 	return 0;
697d1850c00SMustafa Ismail }
698