📄 ehca_mrmw.c
字号:
pginfo.num_kpages = list_len; pginfo.hwpage_size = e_fmr->hwpage_size; pginfo.num_hwpages = list_len * e_fmr->fmr_page_size / pginfo.hwpage_size; pginfo.u.fmr.page_list = page_list; pginfo.next_hwpage = (iova & (e_fmr->fmr_page_size-1)) / pginfo.hwpage_size; pginfo.u.fmr.fmr_pgsize = e_fmr->fmr_page_size; ret = ehca_rereg_mr(shca, e_fmr, (u64 *)iova, list_len * e_fmr->fmr_page_size, e_fmr->acl, e_pd, &pginfo, &tmp_lkey, &tmp_rkey); if (ret) goto map_phys_fmr_exit0; /* successful reregistration */ e_fmr->fmr_map_cnt++; e_fmr->ib.ib_fmr.lkey = tmp_lkey; e_fmr->ib.ib_fmr.rkey = tmp_rkey; return 0;map_phys_fmr_exit0: if (ret) ehca_err(fmr->device, "ret=%i fmr=%p page_list=%p list_len=%x " "iova=%lx", ret, fmr, page_list, list_len, iova); return ret;} /* end ehca_map_phys_fmr() *//*----------------------------------------------------------------------*/int ehca_unmap_fmr(struct list_head *fmr_list){ int ret = 0; struct ib_fmr *ib_fmr; struct ehca_shca *shca = NULL; struct ehca_shca *prev_shca; struct ehca_mr *e_fmr; u32 num_fmr = 0; u32 unmap_fmr_cnt = 0; /* check all FMR belong to same SHCA, and check internal flag */ list_for_each_entry(ib_fmr, fmr_list, list) { prev_shca = shca; if (!ib_fmr) { ehca_gen_err("bad fmr=%p in list", ib_fmr); ret = -EINVAL; goto unmap_fmr_exit0; } shca = container_of(ib_fmr->device, struct ehca_shca, ib_device); e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); if ((shca != prev_shca) && prev_shca) { ehca_err(&shca->ib_device, "SHCA mismatch, shca=%p " "prev_shca=%p e_fmr=%p", shca, prev_shca, e_fmr); ret = -EINVAL; goto unmap_fmr_exit0; } if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { ehca_err(&shca->ib_device, "not a FMR, e_fmr=%p " "e_fmr->flags=%x", e_fmr, e_fmr->flags); ret = -EINVAL; goto unmap_fmr_exit0; } num_fmr++; } /* loop over all FMRs to unmap */ list_for_each_entry(ib_fmr, fmr_list, list) { unmap_fmr_cnt++; e_fmr = container_of(ib_fmr, struct ehca_mr, ib.ib_fmr); shca = container_of(ib_fmr->device, struct ehca_shca, ib_device); ret = ehca_unmap_one_fmr(shca, e_fmr); if (ret) { /* unmap failed, stop unmapping of rest of FMRs */ ehca_err(&shca->ib_device, "unmap of one FMR failed, " "stop rest, e_fmr=%p num_fmr=%x " "unmap_fmr_cnt=%x lkey=%x", e_fmr, num_fmr, unmap_fmr_cnt, e_fmr->ib.ib_fmr.lkey); goto unmap_fmr_exit0; } }unmap_fmr_exit0: if (ret) ehca_gen_err("ret=%i fmr_list=%p num_fmr=%x unmap_fmr_cnt=%x", ret, fmr_list, num_fmr, unmap_fmr_cnt); return ret;} /* end ehca_unmap_fmr() *//*----------------------------------------------------------------------*/int ehca_dealloc_fmr(struct ib_fmr *fmr){ int ret; u64 h_ret; struct ehca_shca *shca = container_of(fmr->device, struct ehca_shca, ib_device); struct ehca_mr *e_fmr = container_of(fmr, struct ehca_mr, ib.ib_fmr); if (!(e_fmr->flags & EHCA_MR_FLAG_FMR)) { ehca_err(fmr->device, "not a FMR, e_fmr=%p e_fmr->flags=%x", e_fmr, e_fmr->flags); ret = -EINVAL; goto free_fmr_exit0; } h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_fmr); if (h_ret != H_SUCCESS) { ehca_err(fmr->device, "hipz_free_mr failed, h_ret=%li e_fmr=%p " "hca_hndl=%lx fmr_hndl=%lx fmr->lkey=%x", h_ret, e_fmr, shca->ipz_hca_handle.handle, e_fmr->ipz_mr_handle.handle, fmr->lkey); ret = ehca2ib_return_code(h_ret); goto free_fmr_exit0; } /* successful deregistration */ ehca_mr_delete(e_fmr); return 0;free_fmr_exit0: if (ret) ehca_err(&shca->ib_device, "ret=%i fmr=%p", ret, fmr); return ret;} /* end ehca_dealloc_fmr() *//*----------------------------------------------------------------------*/int ehca_reg_mr(struct ehca_shca *shca, struct ehca_mr *e_mr, u64 *iova_start, u64 size, int acl, struct ehca_pd *e_pd, struct ehca_mr_pginfo *pginfo, u32 *lkey, /*OUT*/ u32 *rkey) /*OUT*/{ int ret; u64 h_ret; u32 hipz_acl; struct ehca_mr_hipzout_parms hipzout; ehca_mrmw_map_acl(acl, &hipz_acl); ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl); if (ehca_use_hp_mr == 1) hipz_acl |= 0x00000001; h_ret = hipz_h_alloc_resource_mr(shca->ipz_hca_handle, e_mr, (u64)iova_start, size, hipz_acl, e_pd->fw_pd, &hipzout); if (h_ret != H_SUCCESS) { ehca_err(&shca->ib_device, "hipz_alloc_mr failed, h_ret=%li " "hca_hndl=%lx", h_ret, shca->ipz_hca_handle.handle); ret = ehca2ib_return_code(h_ret); goto ehca_reg_mr_exit0; } e_mr->ipz_mr_handle = hipzout.handle; ret = ehca_reg_mr_rpages(shca, e_mr, pginfo); if (ret) goto ehca_reg_mr_exit1; /* successful registration */ e_mr->num_kpages = pginfo->num_kpages; e_mr->num_hwpages = pginfo->num_hwpages; e_mr->hwpage_size = pginfo->hwpage_size; e_mr->start = iova_start; e_mr->size = size; e_mr->acl = acl; *lkey = hipzout.lkey; *rkey = hipzout.rkey; return 0;ehca_reg_mr_exit1: h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); if (h_ret != H_SUCCESS) { ehca_err(&shca->ib_device, "h_ret=%li shca=%p e_mr=%p " "iova_start=%p size=%lx acl=%x e_pd=%p lkey=%x " "pginfo=%p num_kpages=%lx num_hwpages=%lx ret=%i", h_ret, shca, e_mr, iova_start, size, acl, e_pd, hipzout.lkey, pginfo, pginfo->num_kpages, pginfo->num_hwpages, ret); ehca_err(&shca->ib_device, "internal error in ehca_reg_mr, " "not recoverable"); }ehca_reg_mr_exit0: if (ret) ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p " "iova_start=%p size=%lx acl=%x e_pd=%p pginfo=%p " "num_kpages=%lx num_hwpages=%lx", ret, shca, e_mr, iova_start, size, acl, e_pd, pginfo, pginfo->num_kpages, pginfo->num_hwpages); return ret;} /* end ehca_reg_mr() *//*----------------------------------------------------------------------*/int ehca_reg_mr_rpages(struct ehca_shca *shca, struct ehca_mr *e_mr, struct ehca_mr_pginfo *pginfo){ int ret = 0; u64 h_ret; u32 rnum; u64 rpage; u32 i; u64 *kpage; if (!pginfo->num_hwpages) /* in case of fmr */ return 0; kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL); if (!kpage) { ehca_err(&shca->ib_device, "kpage alloc failed"); ret = -ENOMEM; goto ehca_reg_mr_rpages_exit0; } /* max MAX_RPAGES ehca mr pages per register call */ for (i = 0; i < NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES); i++) { if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) { rnum = pginfo->num_hwpages % MAX_RPAGES; /* last shot */ if (rnum == 0) rnum = MAX_RPAGES; /* last shot is full */ } else rnum = MAX_RPAGES; ret = ehca_set_pagebuf(pginfo, rnum, kpage); if (ret) { ehca_err(&shca->ib_device, "ehca_set_pagebuf " "bad rc, ret=%i rnum=%x kpage=%p", ret, rnum, kpage); goto ehca_reg_mr_rpages_exit1; } if (rnum > 1) { rpage = virt_to_abs(kpage); if (!rpage) { ehca_err(&shca->ib_device, "kpage=%p i=%x", kpage, i); ret = -EFAULT; goto ehca_reg_mr_rpages_exit1; } } else rpage = *kpage; h_ret = hipz_h_register_rpage_mr( shca->ipz_hca_handle, e_mr, ehca_encode_hwpage_size(pginfo->hwpage_size), 0, rpage, rnum); if (i == NUM_CHUNKS(pginfo->num_hwpages, MAX_RPAGES) - 1) { /* * check for 'registration complete'==H_SUCCESS * and for 'page registered'==H_PAGE_REGISTERED */ if (h_ret != H_SUCCESS) { ehca_err(&shca->ib_device, "last " "hipz_reg_rpage_mr failed, h_ret=%li " "e_mr=%p i=%x hca_hndl=%lx mr_hndl=%lx" " lkey=%x", h_ret, e_mr, i, shca->ipz_hca_handle.handle, e_mr->ipz_mr_handle.handle, e_mr->ib.ib_mr.lkey); ret = ehca2ib_return_code(h_ret); break; } else ret = 0; } else if (h_ret != H_PAGE_REGISTERED) { ehca_err(&shca->ib_device, "hipz_reg_rpage_mr failed, " "h_ret=%li e_mr=%p i=%x lkey=%x hca_hndl=%lx " "mr_hndl=%lx", h_ret, e_mr, i, e_mr->ib.ib_mr.lkey, shca->ipz_hca_handle.handle, e_mr->ipz_mr_handle.handle); ret = ehca2ib_return_code(h_ret); break; } else ret = 0; } /* end for(i) */ehca_reg_mr_rpages_exit1: ehca_free_fw_ctrlblock(kpage);ehca_reg_mr_rpages_exit0: if (ret) ehca_err(&shca->ib_device, "ret=%i shca=%p e_mr=%p pginfo=%p " "num_kpages=%lx num_hwpages=%lx", ret, shca, e_mr, pginfo, pginfo->num_kpages, pginfo->num_hwpages); return ret;} /* end ehca_reg_mr_rpages() *//*----------------------------------------------------------------------*/inline int ehca_rereg_mr_rereg1(struct ehca_shca *shca, struct ehca_mr *e_mr, u64 *iova_start, u64 size, u32 acl, struct ehca_pd *e_pd, struct ehca_mr_pginfo *pginfo, u32 *lkey, /*OUT*/ u32 *rkey) /*OUT*/{ int ret; u64 h_ret; u32 hipz_acl; u64 *kpage; u64 rpage; struct ehca_mr_pginfo pginfo_save; struct ehca_mr_hipzout_parms hipzout; ehca_mrmw_map_acl(acl, &hipz_acl); ehca_mrmw_set_pgsize_hipz_acl(pginfo->hwpage_size, &hipz_acl); kpage = ehca_alloc_fw_ctrlblock(GFP_KERNEL); if (!kpage) { ehca_err(&shca->ib_device, "kpage alloc failed"); ret = -ENOMEM; goto ehca_rereg_mr_rereg1_exit0; } pginfo_save = *pginfo; ret = ehca_set_pagebuf(pginfo, pginfo->num_hwpages, kpage); if (ret) { ehca_err(&shca->ib_device, "set pagebuf failed, e_mr=%p " "pginfo=%p type=%x num_kpages=%lx num_hwpages=%lx " "kpage=%p", e_mr, pginfo, pginfo->type, pginfo->num_kpages, pginfo->num_hwpages, kpage); goto ehca_rereg_mr_rereg1_exit1; } rpage = virt_to_abs(kpage); if (!rpage) { ehca_err(&shca->ib_device, "kpage=%p", kpage); ret = -EFAULT; goto ehca_rereg_mr_rereg1_exit1; } h_ret = hipz_h_reregister_pmr(shca->ipz_hca_handle, e_mr, (u64)iova_start, size, hipz_acl, e_pd->fw_pd, rpage, &hipzout); if (h_ret != H_SUCCESS) { /* * reregistration unsuccessful, try it again with the 3 hCalls, * e.g. this is required in case H_MR_CONDITION * (MW bound or MR is shared) */ ehca_warn(&shca->ib_device, "hipz_h_reregister_pmr failed " "(Rereg1), h_ret=%li e_mr=%p", h_ret, e_mr); *pginfo = pginfo_save; ret = -EAGAIN; } else if ((u64 *)hipzout.vaddr != iova_start) { ehca_err(&shca->ib_device, "PHYP changed iova_start in " "rereg_pmr, iova_start=%p iova_start_out=%lx e_mr=%p " "mr_handle=%lx lkey=%x lkey_out=%x", iova_start, hipzout.vaddr, e_mr, e_mr->ipz_mr_handle.handle, e_mr->ib.ib_mr.lkey, hipzout.lkey); ret = -EFAULT; } else { /* * successful reregistration * note: start and start_out are identical for eServer HCAs */ e_mr->num_kpages = pginfo->num_kpages; e_mr->num_hwpages = pginfo->num_hwpages; e_mr->hwpage_size = pginfo->hwpage_size; e_mr->start = iova_start; e_mr->size = size; e_mr->acl = acl; *lkey = hipzout.lkey; *rkey = hipzout.rkey; }ehca_rereg_mr_rereg1_exit1: ehca_free_fw_ctrlblock(kpage);ehca_rereg_mr_rereg1_exit0: if ( ret && (ret != -EAGAIN) ) ehca_err(&shca->ib_device, "ret=%i lkey=%x rkey=%x " "pginfo=%p num_kpages=%lx num_hwpages=%lx", ret, *lkey, *rkey, pginfo, pginfo->num_kpages, pginfo->num_hwpages); return ret;} /* end ehca_rereg_mr_rereg1() *//*----------------------------------------------------------------------*/int ehca_rereg_mr(struct ehca_shca *shca, struct ehca_mr *e_mr, u64 *iova_start, u64 size, int acl, struct ehca_pd *e_pd, struct ehca_mr_pginfo *pginfo, u32 *lkey, u32 *rkey){ int ret = 0; u64 h_ret; int rereg_1_hcall = 1; /* 1: use hipz_h_reregister_pmr directly */ int rereg_3_hcall = 0; /* 1: use 3 hipz calls for reregistration */ /* first determine reregistration hCall(s) */ if ((pginfo->num_hwpages > MAX_RPAGES) || (e_mr->num_hwpages > MAX_RPAGES) || (pginfo->num_hwpages > e_mr->num_hwpages)) { ehca_dbg(&shca->ib_device, "Rereg3 case, " "pginfo->num_hwpages=%lx e_mr->num_hwpages=%x", pginfo->num_hwpages, e_mr->num_hwpages); rereg_1_hcall = 0; rereg_3_hcall = 1; } if (e_mr->flags & EHCA_MR_FLAG_MAXMR) { /* check for max-MR */ rereg_1_hcall = 0; rereg_3_hcall = 1; e_mr->flags &= ~EHCA_MR_FLAG_MAXMR; ehca_err(&shca->ib_device, "Rereg MR for max-MR! e_mr=%p", e_mr); } if (rereg_1_hcall) { ret = ehca_rereg_mr_rereg1(shca, e_mr, iova_start, size, acl, e_pd, pginfo, lkey, rkey); if (ret) { if (ret == -EAGAIN) rereg_3_hcall = 1; else goto ehca_rereg_mr_exit0; } } if (rereg_3_hcall) { struct ehca_mr save_mr; /* first deregister old MR */ h_ret = hipz_h_free_resource_mr(shca->ipz_hca_handle, e_mr); if (h_ret != H_SUCCESS) { ehca_err(&shca->ib_device, "hipz_free_mr failed, " "h_ret=%li e_mr=%p hca_hndl=%lx mr_hndl=%lx " "mr->lkey=%x", h_ret, e_mr, shca->ipz_hca_handle.handle,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -