root/drivers/infiniband/hw/i40iw/i40iw_hmc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. i40iw_find_sd_index_limit
  2. i40iw_find_pd_index_limit
  3. i40iw_set_sd_entry
  4. i40iw_clr_sd_entry
  5. i40iw_hmc_sd_one
  6. i40iw_hmc_sd_grp
  7. i40iw_vfdev_from_fpm
  8. i40iw_vf_hmcinfo_from_fpm
  9. i40iw_hmc_finish_add_sd_reg
  10. i40iw_sc_create_hmc_obj
  11. i40iw_finish_del_sd_reg
  12. i40iw_sc_del_hmc_obj
  13. i40iw_add_sd_table_entry
  14. i40iw_add_pd_table_entry
  15. i40iw_remove_pd_bp
  16. i40iw_prep_remove_sd_bp
  17. i40iw_prep_remove_pd_page
  18. i40iw_pf_init_vfhmc

   1 /*******************************************************************************
   2 *
   3 * Copyright (c) 2015-2016 Intel Corporation.  All rights reserved.
   4 *
   5 * This software is available to you under a choice of one of two
   6 * licenses.  You may choose to be licensed under the terms of the GNU
   7 * General Public License (GPL) Version 2, available from the file
   8 * COPYING in the main directory of this source tree, or the
   9 * OpenFabrics.org BSD license below:
  10 *
  11 *   Redistribution and use in source and binary forms, with or
  12 *   without modification, are permitted provided that the following
  13 *   conditions are met:
  14 *
  15 *    - Redistributions of source code must retain the above
  16 *       copyright notice, this list of conditions and the following
  17 *       disclaimer.
  18 *
  19 *    - Redistributions in binary form must reproduce the above
  20 *       copyright notice, this list of conditions and the following
  21 *       disclaimer in the documentation and/or other materials
  22 *       provided with the distribution.
  23 *
  24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  31 * SOFTWARE.
  32 *
  33 *******************************************************************************/
  34 
  35 #include "i40iw_osdep.h"
  36 #include "i40iw_register.h"
  37 #include "i40iw_status.h"
  38 #include "i40iw_hmc.h"
  39 #include "i40iw_d.h"
  40 #include "i40iw_type.h"
  41 #include "i40iw_p.h"
  42 #include "i40iw_vf.h"
  43 #include "i40iw_virtchnl.h"
  44 
  45 /**
  46  * i40iw_find_sd_index_limit - finds segment descriptor index limit
  47  * @hmc_info: pointer to the HMC configuration information structure
  48  * @type: type of HMC resources we're searching
  49  * @index: starting index for the object
  50  * @cnt: number of objects we're trying to create
  51  * @sd_idx: pointer to return index of the segment descriptor in question
  52  * @sd_limit: pointer to return the maximum number of segment descriptors
  53  *
  54  * This function calculates the segment descriptor index and index limit
  55  * for the resource defined by i40iw_hmc_rsrc_type.
  56  */
  57 
  58 static inline void i40iw_find_sd_index_limit(struct i40iw_hmc_info *hmc_info,
  59                                              u32 type,
  60                                              u32 idx,
  61                                              u32 cnt,
  62                                              u32 *sd_idx,
  63                                              u32 *sd_limit)
  64 {
  65         u64 fpm_addr, fpm_limit;
  66 
  67         fpm_addr = hmc_info->hmc_obj[(type)].base +
  68                         hmc_info->hmc_obj[type].size * idx;
  69         fpm_limit = fpm_addr + hmc_info->hmc_obj[type].size * cnt;
  70         *sd_idx = (u32)(fpm_addr / I40IW_HMC_DIRECT_BP_SIZE);
  71         *sd_limit = (u32)((fpm_limit - 1) / I40IW_HMC_DIRECT_BP_SIZE);
  72         *sd_limit += 1;
  73 }
  74 
  75 /**
  76  * i40iw_find_pd_index_limit - finds page descriptor index limit
  77  * @hmc_info: pointer to the HMC configuration information struct
  78  * @type: HMC resource type we're examining
  79  * @idx: starting index for the object
  80  * @cnt: number of objects we're trying to create
  81  * @pd_index: pointer to return page descriptor index
  82  * @pd_limit: pointer to return page descriptor index limit
  83  *
  84  * Calculates the page descriptor index and index limit for the resource
  85  * defined by i40iw_hmc_rsrc_type.
  86  */
  87 
  88 static inline void i40iw_find_pd_index_limit(struct i40iw_hmc_info *hmc_info,
  89                                              u32 type,
  90                                              u32 idx,
  91                                              u32 cnt,
  92                                              u32 *pd_idx,
  93                                              u32 *pd_limit)
  94 {
  95         u64 fpm_adr, fpm_limit;
  96 
  97         fpm_adr = hmc_info->hmc_obj[type].base +
  98                         hmc_info->hmc_obj[type].size * idx;
  99         fpm_limit = fpm_adr + (hmc_info)->hmc_obj[(type)].size * (cnt);
 100         *(pd_idx) = (u32)(fpm_adr / I40IW_HMC_PAGED_BP_SIZE);
 101         *(pd_limit) = (u32)((fpm_limit - 1) / I40IW_HMC_PAGED_BP_SIZE);
 102         *(pd_limit) += 1;
 103 }
 104 
 105 /**
 106  * i40iw_set_sd_entry - setup entry for sd programming
 107  * @pa: physical addr
 108  * @idx: sd index
 109  * @type: paged or direct sd
 110  * @entry: sd entry ptr
 111  */
 112 static inline void i40iw_set_sd_entry(u64 pa,
 113                                       u32 idx,
 114                                       enum i40iw_sd_entry_type type,
 115                                       struct update_sd_entry *entry)
 116 {
 117         entry->data = pa | (I40IW_HMC_MAX_BP_COUNT << I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |
 118                         (((type == I40IW_SD_TYPE_PAGED) ? 0 : 1) <<
 119                                 I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT) |
 120                         (1 << I40E_PFHMC_SDDATALOW_PMSDVALID_SHIFT);
 121         entry->cmd = (idx | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT) | (1 << 15));
 122 }
 123 
 124 /**
 125  * i40iw_clr_sd_entry - setup entry for sd clear
 126  * @idx: sd index
 127  * @type: paged or direct sd
 128  * @entry: sd entry ptr
 129  */
 130 static inline void i40iw_clr_sd_entry(u32 idx, enum i40iw_sd_entry_type type,
 131                                       struct update_sd_entry *entry)
 132 {
 133         entry->data = (I40IW_HMC_MAX_BP_COUNT <<
 134                         I40E_PFHMC_SDDATALOW_PMSDBPCOUNT_SHIFT) |
 135                         (((type == I40IW_SD_TYPE_PAGED) ? 0 : 1) <<
 136                                 I40E_PFHMC_SDDATALOW_PMSDTYPE_SHIFT);
 137         entry->cmd = (idx | (1 << I40E_PFHMC_SDCMD_PMSDWR_SHIFT) | (1 << 15));
 138 }
 139 
 140 /**
 141  * i40iw_hmc_sd_one - setup 1 sd entry for cqp
 142  * @dev: pointer to the device structure
 143  * @hmc_fn_id: hmc's function id
 144  * @pa: physical addr
 145  * @sd_idx: sd index
 146  * @type: paged or direct sd
 147  * @setsd: flag to set or clear sd
 148  */
 149 enum i40iw_status_code i40iw_hmc_sd_one(struct i40iw_sc_dev *dev,
 150                                         u8 hmc_fn_id,
 151                                         u64 pa, u32 sd_idx,
 152                                         enum i40iw_sd_entry_type type,
 153                                         bool setsd)
 154 {
 155         struct i40iw_update_sds_info sdinfo;
 156 
 157         sdinfo.cnt = 1;
 158         sdinfo.hmc_fn_id = hmc_fn_id;
 159         if (setsd)
 160                 i40iw_set_sd_entry(pa, sd_idx, type, sdinfo.entry);
 161         else
 162                 i40iw_clr_sd_entry(sd_idx, type, sdinfo.entry);
 163 
 164         return dev->cqp->process_cqp_sds(dev, &sdinfo);
 165 }
 166 
 167 /**
 168  * i40iw_hmc_sd_grp - setup group od sd entries for cqp
 169  * @dev: pointer to the device structure
 170  * @hmc_info: pointer to the HMC configuration information struct
 171  * @sd_index: sd index
 172  * @sd_cnt: number of sd entries
 173  * @setsd: flag to set or clear sd
 174  */
 175 static enum i40iw_status_code i40iw_hmc_sd_grp(struct i40iw_sc_dev *dev,
 176                                                struct i40iw_hmc_info *hmc_info,
 177                                                u32 sd_index,
 178                                                u32 sd_cnt,
 179                                                bool setsd)
 180 {
 181         struct i40iw_hmc_sd_entry *sd_entry;
 182         struct i40iw_update_sds_info sdinfo;
 183         u64 pa;
 184         u32 i;
 185         enum i40iw_status_code ret_code = 0;
 186 
 187         memset(&sdinfo, 0, sizeof(sdinfo));
 188         sdinfo.hmc_fn_id = hmc_info->hmc_fn_id;
 189         for (i = sd_index; i < sd_index + sd_cnt; i++) {
 190                 sd_entry = &hmc_info->sd_table.sd_entry[i];
 191                 if (!sd_entry ||
 192                     (!sd_entry->valid && setsd) ||
 193                     (sd_entry->valid && !setsd))
 194                         continue;
 195                 if (setsd) {
 196                         pa = (sd_entry->entry_type == I40IW_SD_TYPE_PAGED) ?
 197                             sd_entry->u.pd_table.pd_page_addr.pa :
 198                             sd_entry->u.bp.addr.pa;
 199                         i40iw_set_sd_entry(pa, i, sd_entry->entry_type,
 200                                            &sdinfo.entry[sdinfo.cnt]);
 201                 } else {
 202                         i40iw_clr_sd_entry(i, sd_entry->entry_type,
 203                                            &sdinfo.entry[sdinfo.cnt]);
 204                 }
 205                 sdinfo.cnt++;
 206                 if (sdinfo.cnt == I40IW_MAX_SD_ENTRIES) {
 207                         ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
 208                         if (ret_code) {
 209                                 i40iw_debug(dev, I40IW_DEBUG_HMC,
 210                                             "i40iw_hmc_sd_grp: sd_programming failed err=%d\n",
 211                                             ret_code);
 212                                 return ret_code;
 213                         }
 214                         sdinfo.cnt = 0;
 215                 }
 216         }
 217         if (sdinfo.cnt)
 218                 ret_code = dev->cqp->process_cqp_sds(dev, &sdinfo);
 219 
 220         return ret_code;
 221 }
 222 
 223 /**
 224  * i40iw_vfdev_from_fpm - return vf dev ptr for hmc function id
 225  * @dev: pointer to the device structure
 226  * @hmc_fn_id: hmc's function id
 227  */
 228 struct i40iw_vfdev *i40iw_vfdev_from_fpm(struct i40iw_sc_dev *dev, u8 hmc_fn_id)
 229 {
 230         struct i40iw_vfdev *vf_dev = NULL;
 231         u16 idx;
 232 
 233         for (idx = 0; idx < I40IW_MAX_PE_ENABLED_VF_COUNT; idx++) {
 234                 if (dev->vf_dev[idx] &&
 235                     ((u8)dev->vf_dev[idx]->pmf_index == hmc_fn_id)) {
 236                         vf_dev = dev->vf_dev[idx];
 237                         break;
 238                 }
 239         }
 240         return vf_dev;
 241 }
 242 
 243 /**
 244  * i40iw_vf_hmcinfo_from_fpm - get ptr to hmc for func_id
 245  * @dev: pointer to the device structure
 246  * @hmc_fn_id: hmc's function id
 247  */
 248 struct i40iw_hmc_info *i40iw_vf_hmcinfo_from_fpm(struct i40iw_sc_dev *dev,
 249                                                  u8 hmc_fn_id)
 250 {
 251         struct i40iw_hmc_info *hmc_info = NULL;
 252         u16 idx;
 253 
 254         for (idx = 0; idx < I40IW_MAX_PE_ENABLED_VF_COUNT; idx++) {
 255                 if (dev->vf_dev[idx] &&
 256                     ((u8)dev->vf_dev[idx]->pmf_index == hmc_fn_id)) {
 257                         hmc_info = &dev->vf_dev[idx]->hmc_info;
 258                         break;
 259                 }
 260         }
 261         return hmc_info;
 262 }
 263 
 264 /**
 265  * i40iw_hmc_finish_add_sd_reg - program sd entries for objects
 266  * @dev: pointer to the device structure
 267  * @info: create obj info
 268  */
 269 static enum i40iw_status_code i40iw_hmc_finish_add_sd_reg(struct i40iw_sc_dev *dev,
 270                                                           struct i40iw_hmc_create_obj_info *info)
 271 {
 272         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
 273                 return I40IW_ERR_INVALID_HMC_OBJ_INDEX;
 274 
 275         if ((info->start_idx + info->count) >
 276                         info->hmc_info->hmc_obj[info->rsrc_type].cnt)
 277                 return I40IW_ERR_INVALID_HMC_OBJ_COUNT;
 278 
 279         if (!info->add_sd_cnt)
 280                 return 0;
 281 
 282         return i40iw_hmc_sd_grp(dev, info->hmc_info,
 283                                 info->hmc_info->sd_indexes[0],
 284                                 info->add_sd_cnt, true);
 285 }
 286 
 287 /**
 288  * i40iw_create_iw_hmc_obj - allocate backing store for hmc objects
 289  * @dev: pointer to the device structure
 290  * @info: pointer to i40iw_hmc_iw_create_obj_info struct
 291  *
 292  * This will allocate memory for PDs and backing pages and populate
 293  * the sd and pd entries.
 294  */
 295 enum i40iw_status_code i40iw_sc_create_hmc_obj(struct i40iw_sc_dev *dev,
 296                                                struct i40iw_hmc_create_obj_info *info)
 297 {
 298         struct i40iw_hmc_sd_entry *sd_entry;
 299         u32 sd_idx, sd_lmt;
 300         u32 pd_idx = 0, pd_lmt = 0;
 301         u32 pd_idx1 = 0, pd_lmt1 = 0;
 302         u32 i, j;
 303         bool pd_error = false;
 304         enum i40iw_status_code ret_code = 0;
 305 
 306         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt)
 307                 return I40IW_ERR_INVALID_HMC_OBJ_INDEX;
 308 
 309         if ((info->start_idx + info->count) >
 310             info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
 311                 i40iw_debug(dev, I40IW_DEBUG_HMC,
 312                             "%s: error type %u, start = %u, req cnt %u, cnt = %u\n",
 313                             __func__, info->rsrc_type, info->start_idx, info->count,
 314                             info->hmc_info->hmc_obj[info->rsrc_type].cnt);
 315                 return I40IW_ERR_INVALID_HMC_OBJ_COUNT;
 316         }
 317 
 318         if (!dev->is_pf)
 319                 return i40iw_vchnl_vf_add_hmc_objs(dev, info->rsrc_type, 0, info->count);
 320 
 321         i40iw_find_sd_index_limit(info->hmc_info, info->rsrc_type,
 322                                   info->start_idx, info->count,
 323                                   &sd_idx, &sd_lmt);
 324         if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
 325             sd_lmt > info->hmc_info->sd_table.sd_cnt) {
 326                 return I40IW_ERR_INVALID_SD_INDEX;
 327         }
 328         i40iw_find_pd_index_limit(info->hmc_info, info->rsrc_type,
 329                                   info->start_idx, info->count, &pd_idx, &pd_lmt);
 330 
 331         for (j = sd_idx; j < sd_lmt; j++) {
 332                 ret_code = i40iw_add_sd_table_entry(dev->hw, info->hmc_info,
 333                                                     j,
 334                                                     info->entry_type,
 335                                                     I40IW_HMC_DIRECT_BP_SIZE);
 336                 if (ret_code)
 337                         goto exit_sd_error;
 338                 sd_entry = &info->hmc_info->sd_table.sd_entry[j];
 339 
 340                 if ((sd_entry->entry_type == I40IW_SD_TYPE_PAGED) &&
 341                     ((dev->hmc_info == info->hmc_info) &&
 342                      (info->rsrc_type != I40IW_HMC_IW_PBLE))) {
 343                         pd_idx1 = max(pd_idx, (j * I40IW_HMC_MAX_BP_COUNT));
 344                         pd_lmt1 = min(pd_lmt,
 345                                       (j + 1) * I40IW_HMC_MAX_BP_COUNT);
 346                         for (i = pd_idx1; i < pd_lmt1; i++) {
 347                                 /* update the pd table entry */
 348                                 ret_code = i40iw_add_pd_table_entry(dev->hw, info->hmc_info,
 349                                                                     i, NULL);
 350                                 if (ret_code) {
 351                                         pd_error = true;
 352                                         break;
 353                                 }
 354                         }
 355                         if (pd_error) {
 356                                 while (i && (i > pd_idx1)) {
 357                                         i40iw_remove_pd_bp(dev->hw, info->hmc_info, (i - 1),
 358                                                            info->is_pf);
 359                                         i--;
 360                                 }
 361                         }
 362                 }
 363                 if (sd_entry->valid)
 364                         continue;
 365 
 366                 info->hmc_info->sd_indexes[info->add_sd_cnt] = (u16)j;
 367                 info->add_sd_cnt++;
 368                 sd_entry->valid = true;
 369         }
 370         return i40iw_hmc_finish_add_sd_reg(dev, info);
 371 
 372 exit_sd_error:
 373         while (j && (j > sd_idx)) {
 374                 sd_entry = &info->hmc_info->sd_table.sd_entry[j - 1];
 375                 switch (sd_entry->entry_type) {
 376                 case I40IW_SD_TYPE_PAGED:
 377                         pd_idx1 = max(pd_idx,
 378                                       (j - 1) * I40IW_HMC_MAX_BP_COUNT);
 379                         pd_lmt1 = min(pd_lmt, (j * I40IW_HMC_MAX_BP_COUNT));
 380                         for (i = pd_idx1; i < pd_lmt1; i++)
 381                                 i40iw_prep_remove_pd_page(info->hmc_info, i);
 382                         break;
 383                 case I40IW_SD_TYPE_DIRECT:
 384                         i40iw_prep_remove_pd_page(info->hmc_info, (j - 1));
 385                         break;
 386                 default:
 387                         ret_code = I40IW_ERR_INVALID_SD_TYPE;
 388                         break;
 389                 }
 390                 j--;
 391         }
 392 
 393         return ret_code;
 394 }
 395 
 396 /**
 397  * i40iw_finish_del_sd_reg - delete sd entries for objects
 398  * @dev: pointer to the device structure
 399  * @info: dele obj info
 400  * @reset: true if called before reset
 401  */
 402 static enum i40iw_status_code i40iw_finish_del_sd_reg(struct i40iw_sc_dev *dev,
 403                                                       struct i40iw_hmc_del_obj_info *info,
 404                                                       bool reset)
 405 {
 406         struct i40iw_hmc_sd_entry *sd_entry;
 407         enum i40iw_status_code ret_code = 0;
 408         u32 i, sd_idx;
 409         struct i40iw_dma_mem *mem;
 410 
 411         if (dev->is_pf && !reset)
 412                 ret_code = i40iw_hmc_sd_grp(dev, info->hmc_info,
 413                                             info->hmc_info->sd_indexes[0],
 414                                             info->del_sd_cnt, false);
 415 
 416         if (ret_code)
 417                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error cqp sd sd_grp\n", __func__);
 418 
 419         for (i = 0; i < info->del_sd_cnt; i++) {
 420                 sd_idx = info->hmc_info->sd_indexes[i];
 421                 sd_entry = &info->hmc_info->sd_table.sd_entry[sd_idx];
 422                 if (!sd_entry)
 423                         continue;
 424                 mem = (sd_entry->entry_type == I40IW_SD_TYPE_PAGED) ?
 425                         &sd_entry->u.pd_table.pd_page_addr :
 426                         &sd_entry->u.bp.addr;
 427 
 428                 if (!mem || !mem->va)
 429                         i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error cqp sd mem\n", __func__);
 430                 else
 431                         i40iw_free_dma_mem(dev->hw, mem);
 432         }
 433         return ret_code;
 434 }
 435 
 436 /**
 437  * i40iw_del_iw_hmc_obj - remove pe hmc objects
 438  * @dev: pointer to the device structure
 439  * @info: pointer to i40iw_hmc_del_obj_info struct
 440  * @reset: true if called before reset
 441  *
 442  * This will de-populate the SDs and PDs.  It frees
 443  * the memory for PDS and backing storage.  After this function is returned,
 444  * caller should deallocate memory allocated previously for
 445  * book-keeping information about PDs and backing storage.
 446  */
 447 enum i40iw_status_code i40iw_sc_del_hmc_obj(struct i40iw_sc_dev *dev,
 448                                             struct i40iw_hmc_del_obj_info *info,
 449                                             bool reset)
 450 {
 451         struct i40iw_hmc_pd_table *pd_table;
 452         u32 sd_idx, sd_lmt;
 453         u32 pd_idx, pd_lmt, rel_pd_idx;
 454         u32 i, j;
 455         enum i40iw_status_code ret_code = 0;
 456 
 457         if (info->start_idx >= info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
 458                 i40iw_debug(dev, I40IW_DEBUG_HMC,
 459                             "%s: error start_idx[%04d]  >= [type %04d].cnt[%04d]\n",
 460                             __func__, info->start_idx, info->rsrc_type,
 461                             info->hmc_info->hmc_obj[info->rsrc_type].cnt);
 462                 return I40IW_ERR_INVALID_HMC_OBJ_INDEX;
 463         }
 464 
 465         if ((info->start_idx + info->count) >
 466             info->hmc_info->hmc_obj[info->rsrc_type].cnt) {
 467                 i40iw_debug(dev, I40IW_DEBUG_HMC,
 468                             "%s: error start_idx[%04d] + count %04d  >= [type %04d].cnt[%04d]\n",
 469                             __func__, info->start_idx, info->count,
 470                             info->rsrc_type,
 471                             info->hmc_info->hmc_obj[info->rsrc_type].cnt);
 472                 return I40IW_ERR_INVALID_HMC_OBJ_COUNT;
 473         }
 474         if (!dev->is_pf) {
 475                 ret_code = i40iw_vchnl_vf_del_hmc_obj(dev, info->rsrc_type, 0,
 476                                                       info->count);
 477                 if (info->rsrc_type != I40IW_HMC_IW_PBLE)
 478                         return ret_code;
 479         }
 480 
 481         i40iw_find_pd_index_limit(info->hmc_info, info->rsrc_type,
 482                                   info->start_idx, info->count, &pd_idx, &pd_lmt);
 483 
 484         for (j = pd_idx; j < pd_lmt; j++) {
 485                 sd_idx = j / I40IW_HMC_PD_CNT_IN_SD;
 486 
 487                 if (info->hmc_info->sd_table.sd_entry[sd_idx].entry_type !=
 488                     I40IW_SD_TYPE_PAGED)
 489                         continue;
 490 
 491                 rel_pd_idx = j % I40IW_HMC_PD_CNT_IN_SD;
 492                 pd_table = &info->hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
 493                 if (pd_table->pd_entry[rel_pd_idx].valid) {
 494                         ret_code = i40iw_remove_pd_bp(dev->hw, info->hmc_info, j,
 495                                                       info->is_pf);
 496                         if (ret_code) {
 497                                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error\n", __func__);
 498                                 return ret_code;
 499                         }
 500                 }
 501         }
 502 
 503         i40iw_find_sd_index_limit(info->hmc_info, info->rsrc_type,
 504                                   info->start_idx, info->count, &sd_idx, &sd_lmt);
 505         if (sd_idx >= info->hmc_info->sd_table.sd_cnt ||
 506             sd_lmt > info->hmc_info->sd_table.sd_cnt) {
 507                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: error invalid sd_idx\n", __func__);
 508                 return I40IW_ERR_INVALID_SD_INDEX;
 509         }
 510 
 511         for (i = sd_idx; i < sd_lmt; i++) {
 512                 if (!info->hmc_info->sd_table.sd_entry[i].valid)
 513                         continue;
 514                 switch (info->hmc_info->sd_table.sd_entry[i].entry_type) {
 515                 case I40IW_SD_TYPE_DIRECT:
 516                         ret_code = i40iw_prep_remove_sd_bp(info->hmc_info, i);
 517                         if (!ret_code) {
 518                                 info->hmc_info->sd_indexes[info->del_sd_cnt] = (u16)i;
 519                                 info->del_sd_cnt++;
 520                         }
 521                         break;
 522                 case I40IW_SD_TYPE_PAGED:
 523                         ret_code = i40iw_prep_remove_pd_page(info->hmc_info, i);
 524                         if (!ret_code) {
 525                                 info->hmc_info->sd_indexes[info->del_sd_cnt] = (u16)i;
 526                                 info->del_sd_cnt++;
 527                         }
 528                         break;
 529                 default:
 530                         break;
 531                 }
 532         }
 533         return i40iw_finish_del_sd_reg(dev, info, reset);
 534 }
 535 
 536 /**
 537  * i40iw_add_sd_table_entry - Adds a segment descriptor to the table
 538  * @hw: pointer to our hw struct
 539  * @hmc_info: pointer to the HMC configuration information struct
 540  * @sd_index: segment descriptor index to manipulate
 541  * @type: what type of segment descriptor we're manipulating
 542  * @direct_mode_sz: size to alloc in direct mode
 543  */
 544 enum i40iw_status_code i40iw_add_sd_table_entry(struct i40iw_hw *hw,
 545                                                 struct i40iw_hmc_info *hmc_info,
 546                                                 u32 sd_index,
 547                                                 enum i40iw_sd_entry_type type,
 548                                                 u64 direct_mode_sz)
 549 {
 550         enum i40iw_status_code ret_code = 0;
 551         struct i40iw_hmc_sd_entry *sd_entry;
 552         bool dma_mem_alloc_done = false;
 553         struct i40iw_dma_mem mem;
 554         u64 alloc_len;
 555 
 556         sd_entry = &hmc_info->sd_table.sd_entry[sd_index];
 557         if (!sd_entry->valid) {
 558                 if (type == I40IW_SD_TYPE_PAGED)
 559                         alloc_len = I40IW_HMC_PAGED_BP_SIZE;
 560                 else
 561                         alloc_len = direct_mode_sz;
 562 
 563                 /* allocate a 4K pd page or 2M backing page */
 564                 ret_code = i40iw_allocate_dma_mem(hw, &mem, alloc_len,
 565                                                   I40IW_HMC_PD_BP_BUF_ALIGNMENT);
 566                 if (ret_code)
 567                         goto exit;
 568                 dma_mem_alloc_done = true;
 569                 if (type == I40IW_SD_TYPE_PAGED) {
 570                         ret_code = i40iw_allocate_virt_mem(hw,
 571                                                            &sd_entry->u.pd_table.pd_entry_virt_mem,
 572                                                            sizeof(struct i40iw_hmc_pd_entry) * 512);
 573                         if (ret_code)
 574                                 goto exit;
 575                         sd_entry->u.pd_table.pd_entry = (struct i40iw_hmc_pd_entry *)
 576                                                          sd_entry->u.pd_table.pd_entry_virt_mem.va;
 577 
 578                         memcpy(&sd_entry->u.pd_table.pd_page_addr, &mem, sizeof(struct i40iw_dma_mem));
 579                 } else {
 580                         memcpy(&sd_entry->u.bp.addr, &mem, sizeof(struct i40iw_dma_mem));
 581                         sd_entry->u.bp.sd_pd_index = sd_index;
 582                 }
 583 
 584                 hmc_info->sd_table.sd_entry[sd_index].entry_type = type;
 585 
 586                 I40IW_INC_SD_REFCNT(&hmc_info->sd_table);
 587         }
 588         if (sd_entry->entry_type == I40IW_SD_TYPE_DIRECT)
 589                 I40IW_INC_BP_REFCNT(&sd_entry->u.bp);
 590 exit:
 591         if (ret_code)
 592                 if (dma_mem_alloc_done)
 593                         i40iw_free_dma_mem(hw, &mem);
 594 
 595         return ret_code;
 596 }
 597 
 598 /**
 599  * i40iw_add_pd_table_entry - Adds page descriptor to the specified table
 600  * @hw: pointer to our HW structure
 601  * @hmc_info: pointer to the HMC configuration information structure
 602  * @pd_index: which page descriptor index to manipulate
 603  * @rsrc_pg: if not NULL, use preallocated page instead of allocating new one.
 604  *
 605  * This function:
 606  *      1. Initializes the pd entry
 607  *      2. Adds pd_entry in the pd_table
 608  *      3. Mark the entry valid in i40iw_hmc_pd_entry structure
 609  *      4. Initializes the pd_entry's ref count to 1
 610  * assumptions:
 611  *      1. The memory for pd should be pinned down, physically contiguous and
 612  *         aligned on 4K boundary and zeroed memory.
 613  *      2. It should be 4K in size.
 614  */
 615 enum i40iw_status_code i40iw_add_pd_table_entry(struct i40iw_hw *hw,
 616                                                 struct i40iw_hmc_info *hmc_info,
 617                                                 u32 pd_index,
 618                                                 struct i40iw_dma_mem *rsrc_pg)
 619 {
 620         enum i40iw_status_code ret_code = 0;
 621         struct i40iw_hmc_pd_table *pd_table;
 622         struct i40iw_hmc_pd_entry *pd_entry;
 623         struct i40iw_dma_mem mem;
 624         struct i40iw_dma_mem *page = &mem;
 625         u32 sd_idx, rel_pd_idx;
 626         u64 *pd_addr;
 627         u64 page_desc;
 628 
 629         if (pd_index / I40IW_HMC_PD_CNT_IN_SD >= hmc_info->sd_table.sd_cnt)
 630                 return I40IW_ERR_INVALID_PAGE_DESC_INDEX;
 631 
 632         sd_idx = (pd_index / I40IW_HMC_PD_CNT_IN_SD);
 633         if (hmc_info->sd_table.sd_entry[sd_idx].entry_type != I40IW_SD_TYPE_PAGED)
 634                 return 0;
 635 
 636         rel_pd_idx = (pd_index % I40IW_HMC_PD_CNT_IN_SD);
 637         pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
 638         pd_entry = &pd_table->pd_entry[rel_pd_idx];
 639         if (!pd_entry->valid) {
 640                 if (rsrc_pg) {
 641                         pd_entry->rsrc_pg = true;
 642                         page = rsrc_pg;
 643                 } else {
 644                         ret_code = i40iw_allocate_dma_mem(hw, page,
 645                                                           I40IW_HMC_PAGED_BP_SIZE,
 646                                                           I40IW_HMC_PD_BP_BUF_ALIGNMENT);
 647                         if (ret_code)
 648                                 return ret_code;
 649                         pd_entry->rsrc_pg = false;
 650                 }
 651 
 652                 memcpy(&pd_entry->bp.addr, page, sizeof(struct i40iw_dma_mem));
 653                 pd_entry->bp.sd_pd_index = pd_index;
 654                 pd_entry->bp.entry_type = I40IW_SD_TYPE_PAGED;
 655                 page_desc = page->pa | 0x1;
 656 
 657                 pd_addr = (u64 *)pd_table->pd_page_addr.va;
 658                 pd_addr += rel_pd_idx;
 659 
 660                 memcpy(pd_addr, &page_desc, sizeof(*pd_addr));
 661 
 662                 pd_entry->sd_index = sd_idx;
 663                 pd_entry->valid = true;
 664                 I40IW_INC_PD_REFCNT(pd_table);
 665                 if (hmc_info->hmc_fn_id < I40IW_FIRST_VF_FPM_ID)
 666                         I40IW_INVALIDATE_PF_HMC_PD(hw, sd_idx, rel_pd_idx);
 667                 else if (hw->hmc.hmc_fn_id != hmc_info->hmc_fn_id)
 668                         I40IW_INVALIDATE_VF_HMC_PD(hw, sd_idx, rel_pd_idx,
 669                                                    hmc_info->hmc_fn_id);
 670         }
 671         I40IW_INC_BP_REFCNT(&pd_entry->bp);
 672 
 673         return 0;
 674 }
 675 
 676 /**
 677  * i40iw_remove_pd_bp - remove a backing page from a page descriptor
 678  * @hw: pointer to our HW structure
 679  * @hmc_info: pointer to the HMC configuration information structure
 680  * @idx: the page index
 681  * @is_pf: distinguishes a VF from a PF
 682  *
 683  * This function:
 684  *      1. Marks the entry in pd table (for paged address mode) or in sd table
 685  *         (for direct address mode) invalid.
 686  *      2. Write to register PMPDINV to invalidate the backing page in FV cache
 687  *      3. Decrement the ref count for the pd _entry
 688  * assumptions:
 689  *      1. Caller can deallocate the memory used by backing storage after this
 690  *         function returns.
 691  */
 692 enum i40iw_status_code i40iw_remove_pd_bp(struct i40iw_hw *hw,
 693                                           struct i40iw_hmc_info *hmc_info,
 694                                           u32 idx,
 695                                           bool is_pf)
 696 {
 697         struct i40iw_hmc_pd_entry *pd_entry;
 698         struct i40iw_hmc_pd_table *pd_table;
 699         struct i40iw_hmc_sd_entry *sd_entry;
 700         u32 sd_idx, rel_pd_idx;
 701         struct i40iw_dma_mem *mem;
 702         u64 *pd_addr;
 703 
 704         sd_idx = idx / I40IW_HMC_PD_CNT_IN_SD;
 705         rel_pd_idx = idx % I40IW_HMC_PD_CNT_IN_SD;
 706         if (sd_idx >= hmc_info->sd_table.sd_cnt)
 707                 return I40IW_ERR_INVALID_PAGE_DESC_INDEX;
 708 
 709         sd_entry = &hmc_info->sd_table.sd_entry[sd_idx];
 710         if (sd_entry->entry_type != I40IW_SD_TYPE_PAGED)
 711                 return I40IW_ERR_INVALID_SD_TYPE;
 712 
 713         pd_table = &hmc_info->sd_table.sd_entry[sd_idx].u.pd_table;
 714         pd_entry = &pd_table->pd_entry[rel_pd_idx];
 715         I40IW_DEC_BP_REFCNT(&pd_entry->bp);
 716         if (pd_entry->bp.ref_cnt)
 717                 return 0;
 718 
 719         pd_entry->valid = false;
 720         I40IW_DEC_PD_REFCNT(pd_table);
 721         pd_addr = (u64 *)pd_table->pd_page_addr.va;
 722         pd_addr += rel_pd_idx;
 723         memset(pd_addr, 0, sizeof(u64));
 724         if (is_pf)
 725                 I40IW_INVALIDATE_PF_HMC_PD(hw, sd_idx, idx);
 726         else
 727                 I40IW_INVALIDATE_VF_HMC_PD(hw, sd_idx, idx,
 728                                            hmc_info->hmc_fn_id);
 729 
 730         if (!pd_entry->rsrc_pg) {
 731                 mem = &pd_entry->bp.addr;
 732                 if (!mem || !mem->va)
 733                         return I40IW_ERR_PARAM;
 734                 i40iw_free_dma_mem(hw, mem);
 735         }
 736         if (!pd_table->ref_cnt)
 737                 i40iw_free_virt_mem(hw, &pd_table->pd_entry_virt_mem);
 738 
 739         return 0;
 740 }
 741 
 742 /**
 743  * i40iw_prep_remove_sd_bp - Prepares to remove a backing page from a sd entry
 744  * @hmc_info: pointer to the HMC configuration information structure
 745  * @idx: the page index
 746  */
 747 enum i40iw_status_code i40iw_prep_remove_sd_bp(struct i40iw_hmc_info *hmc_info, u32 idx)
 748 {
 749         struct i40iw_hmc_sd_entry *sd_entry;
 750 
 751         sd_entry = &hmc_info->sd_table.sd_entry[idx];
 752         I40IW_DEC_BP_REFCNT(&sd_entry->u.bp);
 753         if (sd_entry->u.bp.ref_cnt)
 754                 return I40IW_ERR_NOT_READY;
 755 
 756         I40IW_DEC_SD_REFCNT(&hmc_info->sd_table);
 757         sd_entry->valid = false;
 758 
 759         return 0;
 760 }
 761 
 762 /**
 763  * i40iw_prep_remove_pd_page - Prepares to remove a PD page from sd entry.
 764  * @hmc_info: pointer to the HMC configuration information structure
 765  * @idx: segment descriptor index to find the relevant page descriptor
 766  */
 767 enum i40iw_status_code i40iw_prep_remove_pd_page(struct i40iw_hmc_info *hmc_info,
 768                                                  u32 idx)
 769 {
 770         struct i40iw_hmc_sd_entry *sd_entry;
 771 
 772         sd_entry = &hmc_info->sd_table.sd_entry[idx];
 773 
 774         if (sd_entry->u.pd_table.ref_cnt)
 775                 return I40IW_ERR_NOT_READY;
 776 
 777         sd_entry->valid = false;
 778         I40IW_DEC_SD_REFCNT(&hmc_info->sd_table);
 779 
 780         return 0;
 781 }
 782 
 783 /**
 784  * i40iw_pf_init_vfhmc -
 785  * @vf_cnt_array: array of cnt values of iwarp hmc objects
 786  * @vf_hmc_fn_id: hmc function id ofr vf driver
 787  * @dev: pointer to i40iw_dev struct
 788  *
 789  * Called by pf driver to initialize hmc_info for vf driver instance.
 790  */
 791 enum i40iw_status_code i40iw_pf_init_vfhmc(struct i40iw_sc_dev *dev,
 792                                            u8 vf_hmc_fn_id,
 793                                            u32 *vf_cnt_array)
 794 {
 795         struct i40iw_hmc_info *hmc_info;
 796         enum i40iw_status_code ret_code = 0;
 797         u32 i;
 798 
 799         if ((vf_hmc_fn_id < I40IW_FIRST_VF_FPM_ID) ||
 800             (vf_hmc_fn_id >= I40IW_FIRST_VF_FPM_ID +
 801              I40IW_MAX_PE_ENABLED_VF_COUNT)) {
 802                 i40iw_debug(dev, I40IW_DEBUG_HMC, "%s: invalid vf_hmc_fn_id  0x%x\n",
 803                             __func__, vf_hmc_fn_id);
 804                 return I40IW_ERR_INVALID_HMCFN_ID;
 805         }
 806 
 807         ret_code = i40iw_sc_init_iw_hmc(dev, vf_hmc_fn_id);
 808         if (ret_code)
 809                 return ret_code;
 810 
 811         hmc_info = i40iw_vf_hmcinfo_from_fpm(dev, vf_hmc_fn_id);
 812 
 813         for (i = I40IW_HMC_IW_QP; i < I40IW_HMC_IW_MAX; i++)
 814                 if (vf_cnt_array)
 815                         hmc_info->hmc_obj[i].cnt =
 816                             vf_cnt_array[i - I40IW_HMC_IW_QP];
 817                 else
 818                         hmc_info->hmc_obj[i].cnt = hmc_info->hmc_obj[i].max_cnt;
 819 
 820         return 0;
 821 }

/* [<][>][^][v][top][bottom][index][help] */