162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 or Linux-OpenIB 262306a36Sopenharmony_ci/* Copyright (c) 2015 - 2021 Intel Corporation */ 362306a36Sopenharmony_ci#include "osdep.h" 462306a36Sopenharmony_ci#include "hmc.h" 562306a36Sopenharmony_ci#include "defs.h" 662306a36Sopenharmony_ci#include "type.h" 762306a36Sopenharmony_ci#include "protos.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_ci/** 1062306a36Sopenharmony_ci * irdma_find_sd_index_limit - finds segment descriptor index limit 1162306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information structure 1262306a36Sopenharmony_ci * @type: type of HMC resources we're searching 1362306a36Sopenharmony_ci * @idx: starting index for the object 1462306a36Sopenharmony_ci * @cnt: number of objects we're trying to create 1562306a36Sopenharmony_ci * @sd_idx: pointer to return index of the segment descriptor in question 1662306a36Sopenharmony_ci * @sd_limit: pointer to return the maximum number of segment descriptors 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * This function calculates the segment descriptor index and index limit 1962306a36Sopenharmony_ci * for the resource defined by irdma_hmc_rsrc_type. 2062306a36Sopenharmony_ci */ 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_cistatic void irdma_find_sd_index_limit(struct irdma_hmc_info *hmc_info, u32 type, 2362306a36Sopenharmony_ci u32 idx, u32 cnt, u32 *sd_idx, 2462306a36Sopenharmony_ci u32 *sd_limit) 2562306a36Sopenharmony_ci{ 2662306a36Sopenharmony_ci u64 fpm_addr, fpm_limit; 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci fpm_addr = hmc_info->hmc_obj[(type)].base + 2962306a36Sopenharmony_ci hmc_info->hmc_obj[type].size * idx; 3062306a36Sopenharmony_ci fpm_limit = fpm_addr + hmc_info->hmc_obj[type].size * cnt; 3162306a36Sopenharmony_ci *sd_idx = (u32)(fpm_addr / IRDMA_HMC_DIRECT_BP_SIZE); 3262306a36Sopenharmony_ci *sd_limit = (u32)((fpm_limit - 1) / IRDMA_HMC_DIRECT_BP_SIZE); 3362306a36Sopenharmony_ci *sd_limit += 1; 3462306a36Sopenharmony_ci} 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/** 3762306a36Sopenharmony_ci * irdma_find_pd_index_limit - finds page descriptor index limit 3862306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information struct 3962306a36Sopenharmony_ci * @type: HMC resource type we're examining 4062306a36Sopenharmony_ci * @idx: starting index for the object 4162306a36Sopenharmony_ci * @cnt: number of objects we're trying to create 4262306a36Sopenharmony_ci * @pd_idx: pointer to return page descriptor index 4362306a36Sopenharmony_ci * @pd_limit: pointer to return page descriptor index limit 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * Calculates the page descriptor index and index limit for the resource 4662306a36Sopenharmony_ci * defined by irdma_hmc_rsrc_type. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_cistatic void irdma_find_pd_index_limit(struct irdma_hmc_info *hmc_info, u32 type, 5062306a36Sopenharmony_ci u32 idx, u32 cnt, u32 *pd_idx, 5162306a36Sopenharmony_ci u32 *pd_limit) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci u64 fpm_adr, fpm_limit; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci fpm_adr = hmc_info->hmc_obj[type].base + 5662306a36Sopenharmony_ci hmc_info->hmc_obj[type].size * idx; 5762306a36Sopenharmony_ci fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt); 5862306a36Sopenharmony_ci *pd_idx = (u32)(fpm_adr / IRDMA_HMC_PAGED_BP_SIZE); 5962306a36Sopenharmony_ci *pd_limit = (u32)((fpm_limit - 1) / IRDMA_HMC_PAGED_BP_SIZE); 6062306a36Sopenharmony_ci *pd_limit += 1; 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci/** 6462306a36Sopenharmony_ci * irdma_set_sd_entry - setup entry for sd programming 6562306a36Sopenharmony_ci * @pa: physical addr 6662306a36Sopenharmony_ci * @idx: sd index 6762306a36Sopenharmony_ci * @type: paged or direct sd 6862306a36Sopenharmony_ci * @entry: sd entry ptr 6962306a36Sopenharmony_ci */ 7062306a36Sopenharmony_cistatic void irdma_set_sd_entry(u64 pa, u32 idx, enum irdma_sd_entry_type type, 7162306a36Sopenharmony_ci struct irdma_update_sd_entry *entry) 7262306a36Sopenharmony_ci{ 7362306a36Sopenharmony_ci entry->data = pa | 7462306a36Sopenharmony_ci FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDBPCOUNT, IRDMA_HMC_MAX_BP_COUNT) | 7562306a36Sopenharmony_ci FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDTYPE, 7662306a36Sopenharmony_ci type == IRDMA_SD_TYPE_PAGED ? 0 : 1) | 7762306a36Sopenharmony_ci FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDVALID, 1); 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci entry->cmd = idx | FIELD_PREP(IRDMA_PFHMC_SDCMD_PMSDWR, 1) | BIT(15); 8062306a36Sopenharmony_ci} 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci/** 8362306a36Sopenharmony_ci * irdma_clr_sd_entry - setup entry for sd clear 8462306a36Sopenharmony_ci * @idx: sd index 8562306a36Sopenharmony_ci * @type: paged or direct sd 8662306a36Sopenharmony_ci * @entry: sd entry ptr 8762306a36Sopenharmony_ci */ 8862306a36Sopenharmony_cistatic void irdma_clr_sd_entry(u32 idx, enum irdma_sd_entry_type type, 8962306a36Sopenharmony_ci struct irdma_update_sd_entry *entry) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci entry->data = FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDBPCOUNT, IRDMA_HMC_MAX_BP_COUNT) | 9262306a36Sopenharmony_ci FIELD_PREP(IRDMA_PFHMC_SDDATALOW_PMSDTYPE, 9362306a36Sopenharmony_ci type == IRDMA_SD_TYPE_PAGED ? 0 : 1); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci entry->cmd = idx | FIELD_PREP(IRDMA_PFHMC_SDCMD_PMSDWR, 1) | BIT(15); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci/** 9962306a36Sopenharmony_ci * irdma_invalidate_pf_hmc_pd - Invalidates the pd cache in the hardware for PF 10062306a36Sopenharmony_ci * @dev: pointer to our device struct 10162306a36Sopenharmony_ci * @sd_idx: segment descriptor index 10262306a36Sopenharmony_ci * @pd_idx: page descriptor index 10362306a36Sopenharmony_ci */ 10462306a36Sopenharmony_cistatic inline void irdma_invalidate_pf_hmc_pd(struct irdma_sc_dev *dev, u32 sd_idx, 10562306a36Sopenharmony_ci u32 pd_idx) 10662306a36Sopenharmony_ci{ 10762306a36Sopenharmony_ci u32 val = FIELD_PREP(IRDMA_PFHMC_PDINV_PMSDIDX, sd_idx) | 10862306a36Sopenharmony_ci FIELD_PREP(IRDMA_PFHMC_PDINV_PMSDPARTSEL, 1) | 10962306a36Sopenharmony_ci FIELD_PREP(IRDMA_PFHMC_PDINV_PMPDIDX, pd_idx); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci writel(val, dev->hw_regs[IRDMA_PFHMC_PDINV]); 11262306a36Sopenharmony_ci} 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci/** 11562306a36Sopenharmony_ci * irdma_hmc_sd_one - setup 1 sd entry for cqp 11662306a36Sopenharmony_ci * @dev: pointer to the device structure 11762306a36Sopenharmony_ci * @hmc_fn_id: hmc's function id 11862306a36Sopenharmony_ci * @pa: physical addr 11962306a36Sopenharmony_ci * @sd_idx: sd index 12062306a36Sopenharmony_ci * @type: paged or direct sd 12162306a36Sopenharmony_ci * @setsd: flag to set or clear sd 12262306a36Sopenharmony_ci */ 12362306a36Sopenharmony_ciint irdma_hmc_sd_one(struct irdma_sc_dev *dev, u8 hmc_fn_id, u64 pa, u32 sd_idx, 12462306a36Sopenharmony_ci enum irdma_sd_entry_type type, bool setsd) 12562306a36Sopenharmony_ci{ 12662306a36Sopenharmony_ci struct irdma_update_sds_info sdinfo; 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci sdinfo.cnt = 1; 12962306a36Sopenharmony_ci sdinfo.hmc_fn_id = hmc_fn_id; 13062306a36Sopenharmony_ci if (setsd) 13162306a36Sopenharmony_ci irdma_set_sd_entry(pa, sd_idx, type, sdinfo.entry); 13262306a36Sopenharmony_ci else 13362306a36Sopenharmony_ci irdma_clr_sd_entry(sd_idx, type, sdinfo.entry); 13462306a36Sopenharmony_ci return dev->cqp->process_cqp_sds(dev, &sdinfo); 13562306a36Sopenharmony_ci} 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci/** 13862306a36Sopenharmony_ci * irdma_hmc_sd_grp - setup group of sd entries for cqp 13962306a36Sopenharmony_ci * @dev: pointer to the device structure 14062306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information struct 14162306a36Sopenharmony_ci * @sd_index: sd index 14262306a36Sopenharmony_ci * @sd_cnt: number of sd entries 14362306a36Sopenharmony_ci * @setsd: flag to set or clear sd 14462306a36Sopenharmony_ci */ 14562306a36Sopenharmony_cistatic int irdma_hmc_sd_grp(struct irdma_sc_dev *dev, 14662306a36Sopenharmony_ci struct irdma_hmc_info *hmc_info, u32 sd_index, 14762306a36Sopenharmony_ci u32 sd_cnt, bool setsd) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci struct irdma_hmc_sd_entry *sd_entry; 15062306a36Sopenharmony_ci struct irdma_update_sds_info sdinfo = {}; 15162306a36Sopenharmony_ci u64 pa; 15262306a36Sopenharmony_ci u32 i; 15362306a36Sopenharmony_ci int ret_code = 0; 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci sdinfo.hmc_fn_id = hmc_info->hmc_fn_id; 15662306a36Sopenharmony_ci for (i = sd_index; i < sd_index + sd_cnt; i++) { 15762306a36Sopenharmony_ci sd_entry = &hmc_info->sd_table.sd_entry[i]; 15862306a36Sopenharmony_ci if (!sd_entry || (!sd_entry->valid && setsd) || 15962306a36Sopenharmony_ci (sd_entry->valid && !setsd)) 16062306a36Sopenharmony_ci continue; 16162306a36Sopenharmony_ci if (setsd) { 16262306a36Sopenharmony_ci pa = (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED) ? 16362306a36Sopenharmony_ci sd_entry->u.pd_table.pd_page_addr.pa : 16462306a36Sopenharmony_ci sd_entry->u.bp.addr.pa; 16562306a36Sopenharmony_ci irdma_set_sd_entry(pa, i, sd_entry->entry_type, 16662306a36Sopenharmony_ci &sdinfo.entry[sdinfo.cnt]); 16762306a36Sopenharmony_ci } else { 16862306a36Sopenharmony_ci irdma_clr_sd_entry(i, sd_entry->entry_type, 16962306a36Sopenharmony_ci &sdinfo.entry[sdinfo.cnt]); 17062306a36Sopenharmony_ci } 17162306a36Sopenharmony_ci sdinfo.cnt++; 17262306a36Sopenharmony_ci if (sdinfo.cnt == IRDMA_MAX_SD_ENTRIES) { 17362306a36Sopenharmony_ci ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo); 17462306a36Sopenharmony_ci if (ret_code) { 17562306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), 17662306a36Sopenharmony_ci "HMC: sd_programming failed err=%d\n", 17762306a36Sopenharmony_ci ret_code); 17862306a36Sopenharmony_ci return ret_code; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci sdinfo.cnt = 0; 18262306a36Sopenharmony_ci } 18362306a36Sopenharmony_ci } 18462306a36Sopenharmony_ci if (sdinfo.cnt) 18562306a36Sopenharmony_ci ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo); 18662306a36Sopenharmony_ci 18762306a36Sopenharmony_ci return ret_code; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/** 19162306a36Sopenharmony_ci * irdma_hmc_finish_add_sd_reg - program sd entries for objects 19262306a36Sopenharmony_ci * @dev: pointer to the device structure 19362306a36Sopenharmony_ci * @info: create obj info 19462306a36Sopenharmony_ci */ 19562306a36Sopenharmony_cistatic int irdma_hmc_finish_add_sd_reg(struct irdma_sc_dev *dev, 19662306a36Sopenharmony_ci struct irdma_hmc_create_obj_info *info) 19762306a36Sopenharmony_ci{ 19862306a36Sopenharmony_ci if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) 19962306a36Sopenharmony_ci return -EINVAL; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci if ((info->start_idx + info->count) > 20262306a36Sopenharmony_ci info->hmc_info->hmc_obj[info->rsrc_type].cnt) 20362306a36Sopenharmony_ci return -EINVAL; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci if (!info->add_sd_cnt) 20662306a36Sopenharmony_ci return 0; 20762306a36Sopenharmony_ci return irdma_hmc_sd_grp(dev, info->hmc_info, 20862306a36Sopenharmony_ci info->hmc_info->sd_indexes[0], info->add_sd_cnt, 20962306a36Sopenharmony_ci true); 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_ci/** 21362306a36Sopenharmony_ci * irdma_sc_create_hmc_obj - allocate backing store for hmc objects 21462306a36Sopenharmony_ci * @dev: pointer to the device structure 21562306a36Sopenharmony_ci * @info: pointer to irdma_hmc_create_obj_info struct 21662306a36Sopenharmony_ci * 21762306a36Sopenharmony_ci * This will allocate memory for PDs and backing pages and populate 21862306a36Sopenharmony_ci * the sd and pd entries. 21962306a36Sopenharmony_ci */ 22062306a36Sopenharmony_ciint irdma_sc_create_hmc_obj(struct irdma_sc_dev *dev, 22162306a36Sopenharmony_ci struct irdma_hmc_create_obj_info *info) 22262306a36Sopenharmony_ci{ 22362306a36Sopenharmony_ci struct irdma_hmc_sd_entry *sd_entry; 22462306a36Sopenharmony_ci u32 sd_idx, sd_lmt; 22562306a36Sopenharmony_ci u32 pd_idx = 0, pd_lmt = 0; 22662306a36Sopenharmony_ci u32 pd_idx1 = 0, pd_lmt1 = 0; 22762306a36Sopenharmony_ci u32 i, j; 22862306a36Sopenharmony_ci bool pd_error = false; 22962306a36Sopenharmony_ci int ret_code = 0; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) 23262306a36Sopenharmony_ci return -EINVAL; 23362306a36Sopenharmony_ci 23462306a36Sopenharmony_ci if ((info->start_idx + info->count) > 23562306a36Sopenharmony_ci info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 23662306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), 23762306a36Sopenharmony_ci "HMC: error type %u, start = %u, req cnt %u, cnt = %u\n", 23862306a36Sopenharmony_ci info->rsrc_type, info->start_idx, info->count, 23962306a36Sopenharmony_ci info->hmc_info->hmc_obj[info->rsrc_type].cnt); 24062306a36Sopenharmony_ci return -EINVAL; 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci irdma_find_sd_index_limit(info->hmc_info, info->rsrc_type, 24462306a36Sopenharmony_ci info->start_idx, info->count, &sd_idx, 24562306a36Sopenharmony_ci &sd_lmt); 24662306a36Sopenharmony_ci if (sd_idx >= info->hmc_info->sd_table.sd_cnt || 24762306a36Sopenharmony_ci sd_lmt > info->hmc_info->sd_table.sd_cnt) { 24862306a36Sopenharmony_ci return -EINVAL; 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci irdma_find_pd_index_limit(info->hmc_info, info->rsrc_type, 25262306a36Sopenharmony_ci info->start_idx, info->count, &pd_idx, 25362306a36Sopenharmony_ci &pd_lmt); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci for (j = sd_idx; j < sd_lmt; j++) { 25662306a36Sopenharmony_ci ret_code = irdma_add_sd_table_entry(dev->hw, info->hmc_info, j, 25762306a36Sopenharmony_ci info->entry_type, 25862306a36Sopenharmony_ci IRDMA_HMC_DIRECT_BP_SIZE); 25962306a36Sopenharmony_ci if (ret_code) 26062306a36Sopenharmony_ci goto exit_sd_error; 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci sd_entry = &info->hmc_info->sd_table.sd_entry[j]; 26362306a36Sopenharmony_ci if (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED && 26462306a36Sopenharmony_ci (dev->hmc_info == info->hmc_info && 26562306a36Sopenharmony_ci info->rsrc_type != IRDMA_HMC_IW_PBLE)) { 26662306a36Sopenharmony_ci pd_idx1 = max(pd_idx, (j * IRDMA_HMC_MAX_BP_COUNT)); 26762306a36Sopenharmony_ci pd_lmt1 = min(pd_lmt, (j + 1) * IRDMA_HMC_MAX_BP_COUNT); 26862306a36Sopenharmony_ci for (i = pd_idx1; i < pd_lmt1; i++) { 26962306a36Sopenharmony_ci /* update the pd table entry */ 27062306a36Sopenharmony_ci ret_code = irdma_add_pd_table_entry(dev, 27162306a36Sopenharmony_ci info->hmc_info, 27262306a36Sopenharmony_ci i, NULL); 27362306a36Sopenharmony_ci if (ret_code) { 27462306a36Sopenharmony_ci pd_error = true; 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci } 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci if (pd_error) { 27962306a36Sopenharmony_ci while (i && (i > pd_idx1)) { 28062306a36Sopenharmony_ci irdma_remove_pd_bp(dev, info->hmc_info, 28162306a36Sopenharmony_ci i - 1); 28262306a36Sopenharmony_ci i--; 28362306a36Sopenharmony_ci } 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci } 28662306a36Sopenharmony_ci if (sd_entry->valid) 28762306a36Sopenharmony_ci continue; 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_ci info->hmc_info->sd_indexes[info->add_sd_cnt] = (u16)j; 29062306a36Sopenharmony_ci info->add_sd_cnt++; 29162306a36Sopenharmony_ci sd_entry->valid = true; 29262306a36Sopenharmony_ci } 29362306a36Sopenharmony_ci return irdma_hmc_finish_add_sd_reg(dev, info); 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ciexit_sd_error: 29662306a36Sopenharmony_ci while (j && (j > sd_idx)) { 29762306a36Sopenharmony_ci sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1]; 29862306a36Sopenharmony_ci switch (sd_entry->entry_type) { 29962306a36Sopenharmony_ci case IRDMA_SD_TYPE_PAGED: 30062306a36Sopenharmony_ci pd_idx1 = max(pd_idx, (j - 1) * IRDMA_HMC_MAX_BP_COUNT); 30162306a36Sopenharmony_ci pd_lmt1 = min(pd_lmt, (j * IRDMA_HMC_MAX_BP_COUNT)); 30262306a36Sopenharmony_ci for (i = pd_idx1; i < pd_lmt1; i++) 30362306a36Sopenharmony_ci irdma_prep_remove_pd_page(info->hmc_info, i); 30462306a36Sopenharmony_ci break; 30562306a36Sopenharmony_ci case IRDMA_SD_TYPE_DIRECT: 30662306a36Sopenharmony_ci irdma_prep_remove_pd_page(info->hmc_info, (j - 1)); 30762306a36Sopenharmony_ci break; 30862306a36Sopenharmony_ci default: 30962306a36Sopenharmony_ci ret_code = -EINVAL; 31062306a36Sopenharmony_ci break; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci j--; 31362306a36Sopenharmony_ci } 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci return ret_code; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci/** 31962306a36Sopenharmony_ci * irdma_finish_del_sd_reg - delete sd entries for objects 32062306a36Sopenharmony_ci * @dev: pointer to the device structure 32162306a36Sopenharmony_ci * @info: dele obj info 32262306a36Sopenharmony_ci * @reset: true if called before reset 32362306a36Sopenharmony_ci */ 32462306a36Sopenharmony_cistatic int irdma_finish_del_sd_reg(struct irdma_sc_dev *dev, 32562306a36Sopenharmony_ci struct irdma_hmc_del_obj_info *info, 32662306a36Sopenharmony_ci bool reset) 32762306a36Sopenharmony_ci{ 32862306a36Sopenharmony_ci struct irdma_hmc_sd_entry *sd_entry; 32962306a36Sopenharmony_ci int ret_code = 0; 33062306a36Sopenharmony_ci u32 i, sd_idx; 33162306a36Sopenharmony_ci struct irdma_dma_mem *mem; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci if (!reset) 33462306a36Sopenharmony_ci ret_code = irdma_hmc_sd_grp(dev, info->hmc_info, 33562306a36Sopenharmony_ci info->hmc_info->sd_indexes[0], 33662306a36Sopenharmony_ci info->del_sd_cnt, false); 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci if (ret_code) 33962306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), "HMC: error cqp sd sd_grp\n"); 34062306a36Sopenharmony_ci for (i = 0; i < info->del_sd_cnt; i++) { 34162306a36Sopenharmony_ci sd_idx = info->hmc_info->sd_indexes[i]; 34262306a36Sopenharmony_ci sd_entry = &info->hmc_info->sd_table.sd_entry[sd_idx]; 34362306a36Sopenharmony_ci mem = (sd_entry->entry_type == IRDMA_SD_TYPE_PAGED) ? 34462306a36Sopenharmony_ci &sd_entry->u.pd_table.pd_page_addr : 34562306a36Sopenharmony_ci &sd_entry->u.bp.addr; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci if (!mem || !mem->va) { 34862306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), "HMC: error cqp sd mem\n"); 34962306a36Sopenharmony_ci } else { 35062306a36Sopenharmony_ci dma_free_coherent(dev->hw->device, mem->size, mem->va, 35162306a36Sopenharmony_ci mem->pa); 35262306a36Sopenharmony_ci mem->va = NULL; 35362306a36Sopenharmony_ci } 35462306a36Sopenharmony_ci } 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci return ret_code; 35762306a36Sopenharmony_ci} 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci/** 36062306a36Sopenharmony_ci * irdma_sc_del_hmc_obj - remove pe hmc objects 36162306a36Sopenharmony_ci * @dev: pointer to the device structure 36262306a36Sopenharmony_ci * @info: pointer to irdma_hmc_del_obj_info struct 36362306a36Sopenharmony_ci * @reset: true if called before reset 36462306a36Sopenharmony_ci * 36562306a36Sopenharmony_ci * This will de-populate the SDs and PDs. It frees 36662306a36Sopenharmony_ci * the memory for PDS and backing storage. After this function is returned, 36762306a36Sopenharmony_ci * caller should deallocate memory allocated previously for 36862306a36Sopenharmony_ci * book-keeping information about PDs and backing storage. 36962306a36Sopenharmony_ci */ 37062306a36Sopenharmony_ciint irdma_sc_del_hmc_obj(struct irdma_sc_dev *dev, 37162306a36Sopenharmony_ci struct irdma_hmc_del_obj_info *info, bool reset) 37262306a36Sopenharmony_ci{ 37362306a36Sopenharmony_ci struct irdma_hmc_pd_table *pd_table; 37462306a36Sopenharmony_ci u32 sd_idx, sd_lmt; 37562306a36Sopenharmony_ci u32 pd_idx, pd_lmt, rel_pd_idx; 37662306a36Sopenharmony_ci u32 i, j; 37762306a36Sopenharmony_ci int ret_code = 0; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 38062306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), 38162306a36Sopenharmony_ci "HMC: error start_idx[%04d] >= [type %04d].cnt[%04d]\n", 38262306a36Sopenharmony_ci info->start_idx, info->rsrc_type, 38362306a36Sopenharmony_ci info->hmc_info->hmc_obj[info->rsrc_type].cnt); 38462306a36Sopenharmony_ci return -EINVAL; 38562306a36Sopenharmony_ci } 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci if ((info->start_idx + info->count) > 38862306a36Sopenharmony_ci info->hmc_info->hmc_obj[info->rsrc_type].cnt) { 38962306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), 39062306a36Sopenharmony_ci "HMC: error start_idx[%04d] + count %04d >= [type %04d].cnt[%04d]\n", 39162306a36Sopenharmony_ci info->start_idx, info->count, info->rsrc_type, 39262306a36Sopenharmony_ci info->hmc_info->hmc_obj[info->rsrc_type].cnt); 39362306a36Sopenharmony_ci return -EINVAL; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci irdma_find_pd_index_limit(info->hmc_info, info->rsrc_type, 39762306a36Sopenharmony_ci info->start_idx, info->count, &pd_idx, 39862306a36Sopenharmony_ci &pd_lmt); 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ci for (j = pd_idx; j < pd_lmt; j++) { 40162306a36Sopenharmony_ci sd_idx = j / IRDMA_HMC_PD_CNT_IN_SD; 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci if (!info->hmc_info->sd_table.sd_entry[sd_idx].valid) 40462306a36Sopenharmony_ci continue; 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_ci if (info->hmc_info->sd_table.sd_entry[sd_idx].entry_type != 40762306a36Sopenharmony_ci IRDMA_SD_TYPE_PAGED) 40862306a36Sopenharmony_ci continue; 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci rel_pd_idx = j % IRDMA_HMC_PD_CNT_IN_SD; 41162306a36Sopenharmony_ci pd_table = &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; 41262306a36Sopenharmony_ci if (pd_table->pd_entry && 41362306a36Sopenharmony_ci pd_table->pd_entry[rel_pd_idx].valid) { 41462306a36Sopenharmony_ci ret_code = irdma_remove_pd_bp(dev, info->hmc_info, j); 41562306a36Sopenharmony_ci if (ret_code) { 41662306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), 41762306a36Sopenharmony_ci "HMC: remove_pd_bp error\n"); 41862306a36Sopenharmony_ci return ret_code; 41962306a36Sopenharmony_ci } 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci } 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci irdma_find_sd_index_limit(info->hmc_info, info->rsrc_type, 42462306a36Sopenharmony_ci info->start_idx, info->count, &sd_idx, 42562306a36Sopenharmony_ci &sd_lmt); 42662306a36Sopenharmony_ci if (sd_idx >= info->hmc_info->sd_table.sd_cnt || 42762306a36Sopenharmony_ci sd_lmt > info->hmc_info->sd_table.sd_cnt) { 42862306a36Sopenharmony_ci ibdev_dbg(to_ibdev(dev), "HMC: invalid sd_idx\n"); 42962306a36Sopenharmony_ci return -EINVAL; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci for (i = sd_idx; i < sd_lmt; i++) { 43362306a36Sopenharmony_ci pd_table = &info->hmc_info->sd_table.sd_entry[i].u.pd_table; 43462306a36Sopenharmony_ci if (!info->hmc_info->sd_table.sd_entry[i].valid) 43562306a36Sopenharmony_ci continue; 43662306a36Sopenharmony_ci switch (info->hmc_info->sd_table.sd_entry[i].entry_type) { 43762306a36Sopenharmony_ci case IRDMA_SD_TYPE_DIRECT: 43862306a36Sopenharmony_ci ret_code = irdma_prep_remove_sd_bp(info->hmc_info, i); 43962306a36Sopenharmony_ci if (!ret_code) { 44062306a36Sopenharmony_ci info->hmc_info->sd_indexes[info->del_sd_cnt] = 44162306a36Sopenharmony_ci (u16)i; 44262306a36Sopenharmony_ci info->del_sd_cnt++; 44362306a36Sopenharmony_ci } 44462306a36Sopenharmony_ci break; 44562306a36Sopenharmony_ci case IRDMA_SD_TYPE_PAGED: 44662306a36Sopenharmony_ci ret_code = irdma_prep_remove_pd_page(info->hmc_info, i); 44762306a36Sopenharmony_ci if (ret_code) 44862306a36Sopenharmony_ci break; 44962306a36Sopenharmony_ci if (dev->hmc_info != info->hmc_info && 45062306a36Sopenharmony_ci info->rsrc_type == IRDMA_HMC_IW_PBLE && 45162306a36Sopenharmony_ci pd_table->pd_entry) { 45262306a36Sopenharmony_ci kfree(pd_table->pd_entry_virt_mem.va); 45362306a36Sopenharmony_ci pd_table->pd_entry = NULL; 45462306a36Sopenharmony_ci } 45562306a36Sopenharmony_ci info->hmc_info->sd_indexes[info->del_sd_cnt] = (u16)i; 45662306a36Sopenharmony_ci info->del_sd_cnt++; 45762306a36Sopenharmony_ci break; 45862306a36Sopenharmony_ci default: 45962306a36Sopenharmony_ci break; 46062306a36Sopenharmony_ci } 46162306a36Sopenharmony_ci } 46262306a36Sopenharmony_ci return irdma_finish_del_sd_reg(dev, info, reset); 46362306a36Sopenharmony_ci} 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci/** 46662306a36Sopenharmony_ci * irdma_add_sd_table_entry - Adds a segment descriptor to the table 46762306a36Sopenharmony_ci * @hw: pointer to our hw struct 46862306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information struct 46962306a36Sopenharmony_ci * @sd_index: segment descriptor index to manipulate 47062306a36Sopenharmony_ci * @type: what type of segment descriptor we're manipulating 47162306a36Sopenharmony_ci * @direct_mode_sz: size to alloc in direct mode 47262306a36Sopenharmony_ci */ 47362306a36Sopenharmony_ciint irdma_add_sd_table_entry(struct irdma_hw *hw, 47462306a36Sopenharmony_ci struct irdma_hmc_info *hmc_info, u32 sd_index, 47562306a36Sopenharmony_ci enum irdma_sd_entry_type type, u64 direct_mode_sz) 47662306a36Sopenharmony_ci{ 47762306a36Sopenharmony_ci struct irdma_hmc_sd_entry *sd_entry; 47862306a36Sopenharmony_ci struct irdma_dma_mem dma_mem; 47962306a36Sopenharmony_ci u64 alloc_len; 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci sd_entry = &hmc_info->sd_table.sd_entry[sd_index]; 48262306a36Sopenharmony_ci if (!sd_entry->valid) { 48362306a36Sopenharmony_ci if (type == IRDMA_SD_TYPE_PAGED) 48462306a36Sopenharmony_ci alloc_len = IRDMA_HMC_PAGED_BP_SIZE; 48562306a36Sopenharmony_ci else 48662306a36Sopenharmony_ci alloc_len = direct_mode_sz; 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* allocate a 4K pd page or 2M backing page */ 48962306a36Sopenharmony_ci dma_mem.size = ALIGN(alloc_len, IRDMA_HMC_PD_BP_BUF_ALIGNMENT); 49062306a36Sopenharmony_ci dma_mem.va = dma_alloc_coherent(hw->device, dma_mem.size, 49162306a36Sopenharmony_ci &dma_mem.pa, GFP_KERNEL); 49262306a36Sopenharmony_ci if (!dma_mem.va) 49362306a36Sopenharmony_ci return -ENOMEM; 49462306a36Sopenharmony_ci if (type == IRDMA_SD_TYPE_PAGED) { 49562306a36Sopenharmony_ci struct irdma_virt_mem *vmem = 49662306a36Sopenharmony_ci &sd_entry->u.pd_table.pd_entry_virt_mem; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci vmem->size = sizeof(struct irdma_hmc_pd_entry) * 512; 49962306a36Sopenharmony_ci vmem->va = kzalloc(vmem->size, GFP_KERNEL); 50062306a36Sopenharmony_ci if (!vmem->va) { 50162306a36Sopenharmony_ci dma_free_coherent(hw->device, dma_mem.size, 50262306a36Sopenharmony_ci dma_mem.va, dma_mem.pa); 50362306a36Sopenharmony_ci dma_mem.va = NULL; 50462306a36Sopenharmony_ci return -ENOMEM; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci sd_entry->u.pd_table.pd_entry = vmem->va; 50762306a36Sopenharmony_ci 50862306a36Sopenharmony_ci memcpy(&sd_entry->u.pd_table.pd_page_addr, &dma_mem, 50962306a36Sopenharmony_ci sizeof(sd_entry->u.pd_table.pd_page_addr)); 51062306a36Sopenharmony_ci } else { 51162306a36Sopenharmony_ci memcpy(&sd_entry->u.bp.addr, &dma_mem, 51262306a36Sopenharmony_ci sizeof(sd_entry->u.bp.addr)); 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci sd_entry->u.bp.sd_pd_index = sd_index; 51562306a36Sopenharmony_ci } 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci hmc_info->sd_table.sd_entry[sd_index].entry_type = type; 51862306a36Sopenharmony_ci hmc_info->sd_table.use_cnt++; 51962306a36Sopenharmony_ci } 52062306a36Sopenharmony_ci if (sd_entry->entry_type == IRDMA_SD_TYPE_DIRECT) 52162306a36Sopenharmony_ci sd_entry->u.bp.use_cnt++; 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci return 0; 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci/** 52762306a36Sopenharmony_ci * irdma_add_pd_table_entry - Adds page descriptor to the specified table 52862306a36Sopenharmony_ci * @dev: pointer to our device structure 52962306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information structure 53062306a36Sopenharmony_ci * @pd_index: which page descriptor index to manipulate 53162306a36Sopenharmony_ci * @rsrc_pg: if not NULL, use preallocated page instead of allocating new one. 53262306a36Sopenharmony_ci * 53362306a36Sopenharmony_ci * This function: 53462306a36Sopenharmony_ci * 1. Initializes the pd entry 53562306a36Sopenharmony_ci * 2. Adds pd_entry in the pd_table 53662306a36Sopenharmony_ci * 3. Mark the entry valid in irdma_hmc_pd_entry structure 53762306a36Sopenharmony_ci * 4. Initializes the pd_entry's ref count to 1 53862306a36Sopenharmony_ci * assumptions: 53962306a36Sopenharmony_ci * 1. The memory for pd should be pinned down, physically contiguous and 54062306a36Sopenharmony_ci * aligned on 4K boundary and zeroed memory. 54162306a36Sopenharmony_ci * 2. It should be 4K in size. 54262306a36Sopenharmony_ci */ 54362306a36Sopenharmony_ciint irdma_add_pd_table_entry(struct irdma_sc_dev *dev, 54462306a36Sopenharmony_ci struct irdma_hmc_info *hmc_info, u32 pd_index, 54562306a36Sopenharmony_ci struct irdma_dma_mem *rsrc_pg) 54662306a36Sopenharmony_ci{ 54762306a36Sopenharmony_ci struct irdma_hmc_pd_table *pd_table; 54862306a36Sopenharmony_ci struct irdma_hmc_pd_entry *pd_entry; 54962306a36Sopenharmony_ci struct irdma_dma_mem mem; 55062306a36Sopenharmony_ci struct irdma_dma_mem *page = &mem; 55162306a36Sopenharmony_ci u32 sd_idx, rel_pd_idx; 55262306a36Sopenharmony_ci u64 *pd_addr; 55362306a36Sopenharmony_ci u64 page_desc; 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci if (pd_index / IRDMA_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt) 55662306a36Sopenharmony_ci return -EINVAL; 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci sd_idx = (pd_index / IRDMA_HMC_PD_CNT_IN_SD); 55962306a36Sopenharmony_ci if (hmc_info->sd_table.sd_entry[sd_idx].entry_type != 56062306a36Sopenharmony_ci IRDMA_SD_TYPE_PAGED) 56162306a36Sopenharmony_ci return 0; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci rel_pd_idx = (pd_index % IRDMA_HMC_PD_CNT_IN_SD); 56462306a36Sopenharmony_ci pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; 56562306a36Sopenharmony_ci pd_entry = &pd_table->pd_entry[rel_pd_idx]; 56662306a36Sopenharmony_ci if (!pd_entry->valid) { 56762306a36Sopenharmony_ci if (rsrc_pg) { 56862306a36Sopenharmony_ci pd_entry->rsrc_pg = true; 56962306a36Sopenharmony_ci page = rsrc_pg; 57062306a36Sopenharmony_ci } else { 57162306a36Sopenharmony_ci page->size = ALIGN(IRDMA_HMC_PAGED_BP_SIZE, 57262306a36Sopenharmony_ci IRDMA_HMC_PD_BP_BUF_ALIGNMENT); 57362306a36Sopenharmony_ci page->va = dma_alloc_coherent(dev->hw->device, 57462306a36Sopenharmony_ci page->size, &page->pa, 57562306a36Sopenharmony_ci GFP_KERNEL); 57662306a36Sopenharmony_ci if (!page->va) 57762306a36Sopenharmony_ci return -ENOMEM; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_ci pd_entry->rsrc_pg = false; 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci memcpy(&pd_entry->bp.addr, page, sizeof(pd_entry->bp.addr)); 58362306a36Sopenharmony_ci pd_entry->bp.sd_pd_index = pd_index; 58462306a36Sopenharmony_ci pd_entry->bp.entry_type = IRDMA_SD_TYPE_PAGED; 58562306a36Sopenharmony_ci page_desc = page->pa | 0x1; 58662306a36Sopenharmony_ci pd_addr = pd_table->pd_page_addr.va; 58762306a36Sopenharmony_ci pd_addr += rel_pd_idx; 58862306a36Sopenharmony_ci memcpy(pd_addr, &page_desc, sizeof(*pd_addr)); 58962306a36Sopenharmony_ci pd_entry->sd_index = sd_idx; 59062306a36Sopenharmony_ci pd_entry->valid = true; 59162306a36Sopenharmony_ci pd_table->use_cnt++; 59262306a36Sopenharmony_ci irdma_invalidate_pf_hmc_pd(dev, sd_idx, rel_pd_idx); 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci pd_entry->bp.use_cnt++; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return 0; 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci/** 60062306a36Sopenharmony_ci * irdma_remove_pd_bp - remove a backing page from a page descriptor 60162306a36Sopenharmony_ci * @dev: pointer to our HW structure 60262306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information structure 60362306a36Sopenharmony_ci * @idx: the page index 60462306a36Sopenharmony_ci * 60562306a36Sopenharmony_ci * This function: 60662306a36Sopenharmony_ci * 1. Marks the entry in pd table (for paged address mode) or in sd table 60762306a36Sopenharmony_ci * (for direct address mode) invalid. 60862306a36Sopenharmony_ci * 2. Write to register PMPDINV to invalidate the backing page in FV cache 60962306a36Sopenharmony_ci * 3. Decrement the ref count for the pd _entry 61062306a36Sopenharmony_ci * assumptions: 61162306a36Sopenharmony_ci * 1. Caller can deallocate the memory used by backing storage after this 61262306a36Sopenharmony_ci * function returns. 61362306a36Sopenharmony_ci */ 61462306a36Sopenharmony_ciint irdma_remove_pd_bp(struct irdma_sc_dev *dev, 61562306a36Sopenharmony_ci struct irdma_hmc_info *hmc_info, u32 idx) 61662306a36Sopenharmony_ci{ 61762306a36Sopenharmony_ci struct irdma_hmc_pd_entry *pd_entry; 61862306a36Sopenharmony_ci struct irdma_hmc_pd_table *pd_table; 61962306a36Sopenharmony_ci struct irdma_hmc_sd_entry *sd_entry; 62062306a36Sopenharmony_ci u32 sd_idx, rel_pd_idx; 62162306a36Sopenharmony_ci struct irdma_dma_mem *mem; 62262306a36Sopenharmony_ci u64 *pd_addr; 62362306a36Sopenharmony_ci 62462306a36Sopenharmony_ci sd_idx = idx / IRDMA_HMC_PD_CNT_IN_SD; 62562306a36Sopenharmony_ci rel_pd_idx = idx % IRDMA_HMC_PD_CNT_IN_SD; 62662306a36Sopenharmony_ci if (sd_idx >= hmc_info->sd_table.sd_cnt) 62762306a36Sopenharmony_ci return -EINVAL; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci sd_entry = &hmc_info->sd_table.sd_entry[sd_idx]; 63062306a36Sopenharmony_ci if (sd_entry->entry_type != IRDMA_SD_TYPE_PAGED) 63162306a36Sopenharmony_ci return -EINVAL; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table; 63462306a36Sopenharmony_ci pd_entry = &pd_table->pd_entry[rel_pd_idx]; 63562306a36Sopenharmony_ci if (--pd_entry->bp.use_cnt) 63662306a36Sopenharmony_ci return 0; 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci pd_entry->valid = false; 63962306a36Sopenharmony_ci pd_table->use_cnt--; 64062306a36Sopenharmony_ci pd_addr = pd_table->pd_page_addr.va; 64162306a36Sopenharmony_ci pd_addr += rel_pd_idx; 64262306a36Sopenharmony_ci memset(pd_addr, 0, sizeof(u64)); 64362306a36Sopenharmony_ci irdma_invalidate_pf_hmc_pd(dev, sd_idx, idx); 64462306a36Sopenharmony_ci 64562306a36Sopenharmony_ci if (!pd_entry->rsrc_pg) { 64662306a36Sopenharmony_ci mem = &pd_entry->bp.addr; 64762306a36Sopenharmony_ci if (!mem || !mem->va) 64862306a36Sopenharmony_ci return -EINVAL; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci dma_free_coherent(dev->hw->device, mem->size, mem->va, 65162306a36Sopenharmony_ci mem->pa); 65262306a36Sopenharmony_ci mem->va = NULL; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci if (!pd_table->use_cnt) 65562306a36Sopenharmony_ci kfree(pd_table->pd_entry_virt_mem.va); 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_ci return 0; 65862306a36Sopenharmony_ci} 65962306a36Sopenharmony_ci 66062306a36Sopenharmony_ci/** 66162306a36Sopenharmony_ci * irdma_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry 66262306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information structure 66362306a36Sopenharmony_ci * @idx: the page index 66462306a36Sopenharmony_ci */ 66562306a36Sopenharmony_ciint irdma_prep_remove_sd_bp(struct irdma_hmc_info *hmc_info, u32 idx) 66662306a36Sopenharmony_ci{ 66762306a36Sopenharmony_ci struct irdma_hmc_sd_entry *sd_entry; 66862306a36Sopenharmony_ci 66962306a36Sopenharmony_ci sd_entry = &hmc_info->sd_table.sd_entry[idx]; 67062306a36Sopenharmony_ci if (--sd_entry->u.bp.use_cnt) 67162306a36Sopenharmony_ci return -EBUSY; 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci hmc_info->sd_table.use_cnt--; 67462306a36Sopenharmony_ci sd_entry->valid = false; 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci return 0; 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci/** 68062306a36Sopenharmony_ci * irdma_prep_remove_pd_page - Prepares to remove a PD page from sd entry. 68162306a36Sopenharmony_ci * @hmc_info: pointer to the HMC configuration information structure 68262306a36Sopenharmony_ci * @idx: segment descriptor index to find the relevant page descriptor 68362306a36Sopenharmony_ci */ 68462306a36Sopenharmony_ciint irdma_prep_remove_pd_page(struct irdma_hmc_info *hmc_info, u32 idx) 68562306a36Sopenharmony_ci{ 68662306a36Sopenharmony_ci struct irdma_hmc_sd_entry *sd_entry; 68762306a36Sopenharmony_ci 68862306a36Sopenharmony_ci sd_entry = &hmc_info->sd_table.sd_entry[idx]; 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_ci if (sd_entry->u.pd_table.use_cnt) 69162306a36Sopenharmony_ci return -EBUSY; 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci sd_entry->valid = false; 69462306a36Sopenharmony_ci hmc_info->sd_table.use_cnt--; 69562306a36Sopenharmony_ci 69662306a36Sopenharmony_ci return 0; 69762306a36Sopenharmony_ci} 698