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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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