Skip to content

Commit 5ac388d

Browse files
Sindhu-Devalerleon
authored andcommitted
RDMA/irdma: Add support to re-register a memory region
Add support for reregister MR verb API by doing a de-register followed by a register MR with the new attributes. Reuse resources like iwmr handle and HW stag where possible. Signed-off-by: Sindhu Devale <sindhu.devale@intel.com> Signed-off-by: Shiraz Saleem <shiraz.saleem@intel.com> Link: https://lore.kernel.org/r/20231004151306.228-1-shiraz.saleem@intel.com Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 0aa4459 commit 5ac388d

2 files changed

Lines changed: 191 additions & 43 deletions

File tree

drivers/infiniband/hw/irdma/verbs.c

Lines changed: 189 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -2649,8 +2649,11 @@ static int irdma_hw_alloc_stag(struct irdma_device *iwdev,
26492649
cqp_info->in.u.alloc_stag.scratch = (uintptr_t)cqp_request;
26502650
status = irdma_handle_cqp_op(iwdev->rf, cqp_request);
26512651
irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request);
2652+
if (status)
2653+
return status;
26522654

2653-
return status;
2655+
iwmr->is_hwreg = 1;
2656+
return 0;
26542657
}
26552658

26562659
/**
@@ -2816,14 +2819,18 @@ static int irdma_hwreg_mr(struct irdma_device *iwdev, struct irdma_mr *iwmr,
28162819
ret = irdma_handle_cqp_op(iwdev->rf, cqp_request);
28172820
irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request);
28182821

2822+
if (!ret)
2823+
iwmr->is_hwreg = 1;
2824+
28192825
return ret;
28202826
}
28212827

2822-
static int irdma_reg_user_mr_type_mem(struct irdma_mr *iwmr, int access)
2828+
static int irdma_reg_user_mr_type_mem(struct irdma_mr *iwmr, int access,
2829+
bool create_stag)
28232830
{
28242831
struct irdma_device *iwdev = to_iwdev(iwmr->ibmr.device);
28252832
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
2826-
u32 stag;
2833+
u32 stag = 0;
28272834
u8 lvl;
28282835
int err;
28292836

@@ -2842,23 +2849,27 @@ static int irdma_reg_user_mr_type_mem(struct irdma_mr *iwmr, int access)
28422849
}
28432850
}
28442851

2845-
stag = irdma_create_stag(iwdev);
2846-
if (!stag) {
2847-
err = -ENOMEM;
2848-
goto free_pble;
2852+
if (create_stag) {
2853+
stag = irdma_create_stag(iwdev);
2854+
if (!stag) {
2855+
err = -ENOMEM;
2856+
goto free_pble;
2857+
}
2858+
2859+
iwmr->stag = stag;
2860+
iwmr->ibmr.rkey = stag;
2861+
iwmr->ibmr.lkey = stag;
28492862
}
28502863

2851-
iwmr->stag = stag;
2852-
iwmr->ibmr.rkey = stag;
2853-
iwmr->ibmr.lkey = stag;
28542864
err = irdma_hwreg_mr(iwdev, iwmr, access);
28552865
if (err)
28562866
goto err_hwreg;
28572867

28582868
return 0;
28592869

28602870
err_hwreg:
2861-
irdma_free_stag(iwdev, stag);
2871+
if (stag)
2872+
irdma_free_stag(iwdev, stag);
28622873

28632874
free_pble:
28642875
if (iwpbl->pble_alloc.level != PBLE_LEVEL_0 && iwpbl->pbl_allocated)
@@ -3033,7 +3044,7 @@ static struct ib_mr *irdma_reg_user_mr(struct ib_pd *pd, u64 start, u64 len,
30333044
goto error;
30343045
break;
30353046
case IRDMA_MEMREG_TYPE_MEM:
3036-
err = irdma_reg_user_mr_type_mem(iwmr, access);
3047+
err = irdma_reg_user_mr_type_mem(iwmr, access, true);
30373048
if (err)
30383049
goto error;
30393050

@@ -3077,7 +3088,7 @@ static struct ib_mr *irdma_reg_user_mr_dmabuf(struct ib_pd *pd, u64 start,
30773088
goto err_release;
30783089
}
30793090

3080-
err = irdma_reg_user_mr_type_mem(iwmr, access);
3091+
err = irdma_reg_user_mr_type_mem(iwmr, access, true);
30813092
if (err)
30823093
goto err_iwmr;
30833094

@@ -3092,6 +3103,161 @@ static struct ib_mr *irdma_reg_user_mr_dmabuf(struct ib_pd *pd, u64 start,
30923103
return ERR_PTR(err);
30933104
}
30943105

3106+
static int irdma_hwdereg_mr(struct ib_mr *ib_mr)
3107+
{
3108+
struct irdma_device *iwdev = to_iwdev(ib_mr->device);
3109+
struct irdma_mr *iwmr = to_iwmr(ib_mr);
3110+
struct irdma_pd *iwpd = to_iwpd(ib_mr->pd);
3111+
struct irdma_dealloc_stag_info *info;
3112+
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
3113+
struct irdma_cqp_request *cqp_request;
3114+
struct cqp_cmds_info *cqp_info;
3115+
int status;
3116+
3117+
/* Skip HW MR de-register when it is already de-registered
3118+
* during an MR re-reregister and the re-registration fails
3119+
*/
3120+
if (!iwmr->is_hwreg)
3121+
return 0;
3122+
3123+
cqp_request = irdma_alloc_and_get_cqp_request(&iwdev->rf->cqp, true);
3124+
if (!cqp_request)
3125+
return -ENOMEM;
3126+
3127+
cqp_info = &cqp_request->info;
3128+
info = &cqp_info->in.u.dealloc_stag.info;
3129+
memset(info, 0, sizeof(*info));
3130+
info->pd_id = iwpd->sc_pd.pd_id;
3131+
info->stag_idx = ib_mr->rkey >> IRDMA_CQPSQ_STAG_IDX_S;
3132+
info->mr = true;
3133+
if (iwpbl->pbl_allocated)
3134+
info->dealloc_pbl = true;
3135+
3136+
cqp_info->cqp_cmd = IRDMA_OP_DEALLOC_STAG;
3137+
cqp_info->post_sq = 1;
3138+
cqp_info->in.u.dealloc_stag.dev = &iwdev->rf->sc_dev;
3139+
cqp_info->in.u.dealloc_stag.scratch = (uintptr_t)cqp_request;
3140+
status = irdma_handle_cqp_op(iwdev->rf, cqp_request);
3141+
irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request);
3142+
if (status)
3143+
return status;
3144+
3145+
iwmr->is_hwreg = 0;
3146+
return 0;
3147+
}
3148+
3149+
/*
3150+
* irdma_rereg_mr_trans - Re-register a user MR for a change translation.
3151+
* @iwmr: ptr of iwmr
3152+
* @start: virtual start address
3153+
* @len: length of mr
3154+
* @virt: virtual address
3155+
*
3156+
* Re-register a user memory region when a change translation is requested.
3157+
* Re-register a new region while reusing the stag from the original registration.
3158+
*/
3159+
static int irdma_rereg_mr_trans(struct irdma_mr *iwmr, u64 start, u64 len,
3160+
u64 virt)
3161+
{
3162+
struct irdma_device *iwdev = to_iwdev(iwmr->ibmr.device);
3163+
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
3164+
struct ib_pd *pd = iwmr->ibmr.pd;
3165+
struct ib_umem *region;
3166+
int err;
3167+
3168+
region = ib_umem_get(pd->device, start, len, iwmr->access);
3169+
if (IS_ERR(region))
3170+
return PTR_ERR(region);
3171+
3172+
iwmr->region = region;
3173+
iwmr->ibmr.iova = virt;
3174+
iwmr->ibmr.pd = pd;
3175+
iwmr->page_size = ib_umem_find_best_pgsz(region,
3176+
iwdev->rf->sc_dev.hw_attrs.page_size_cap,
3177+
virt);
3178+
if (unlikely(!iwmr->page_size)) {
3179+
err = -EOPNOTSUPP;
3180+
goto err;
3181+
}
3182+
3183+
iwmr->len = region->length;
3184+
iwpbl->user_base = virt;
3185+
iwmr->page_cnt = ib_umem_num_dma_blocks(region, iwmr->page_size);
3186+
3187+
err = irdma_reg_user_mr_type_mem(iwmr, iwmr->access, false);
3188+
if (err)
3189+
goto err;
3190+
3191+
return 0;
3192+
3193+
err:
3194+
ib_umem_release(region);
3195+
return err;
3196+
}
3197+
3198+
/*
3199+
* irdma_rereg_user_mr - Re-Register a user memory region(MR)
3200+
* @ibmr: ib mem to access iwarp mr pointer
3201+
* @flags: bit mask to indicate which of the attr's of MR modified
3202+
* @start: virtual start address
3203+
* @len: length of mr
3204+
* @virt: virtual address
3205+
* @new_access: bit mask of access flags
3206+
* @new_pd: ptr of pd
3207+
* @udata: user data
3208+
*
3209+
* Return:
3210+
* NULL - Success, existing MR updated
3211+
* ERR_PTR - error occurred
3212+
*/
3213+
static struct ib_mr *irdma_rereg_user_mr(struct ib_mr *ib_mr, int flags,
3214+
u64 start, u64 len, u64 virt,
3215+
int new_access, struct ib_pd *new_pd,
3216+
struct ib_udata *udata)
3217+
{
3218+
struct irdma_device *iwdev = to_iwdev(ib_mr->device);
3219+
struct irdma_mr *iwmr = to_iwmr(ib_mr);
3220+
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
3221+
int ret;
3222+
3223+
if (len > iwdev->rf->sc_dev.hw_attrs.max_mr_size)
3224+
return ERR_PTR(-EINVAL);
3225+
3226+
if (flags & ~(IB_MR_REREG_TRANS | IB_MR_REREG_PD | IB_MR_REREG_ACCESS))
3227+
return ERR_PTR(-EOPNOTSUPP);
3228+
3229+
ret = irdma_hwdereg_mr(ib_mr);
3230+
if (ret)
3231+
return ERR_PTR(ret);
3232+
3233+
if (flags & IB_MR_REREG_ACCESS)
3234+
iwmr->access = new_access;
3235+
3236+
if (flags & IB_MR_REREG_PD) {
3237+
iwmr->ibmr.pd = new_pd;
3238+
iwmr->ibmr.device = new_pd->device;
3239+
}
3240+
3241+
if (flags & IB_MR_REREG_TRANS) {
3242+
if (iwpbl->pbl_allocated) {
3243+
irdma_free_pble(iwdev->rf->pble_rsrc,
3244+
&iwpbl->pble_alloc);
3245+
iwpbl->pbl_allocated = false;
3246+
}
3247+
if (iwmr->region) {
3248+
ib_umem_release(iwmr->region);
3249+
iwmr->region = NULL;
3250+
}
3251+
3252+
ret = irdma_rereg_mr_trans(iwmr, start, len, virt);
3253+
} else
3254+
ret = irdma_hwreg_mr(iwdev, iwmr, iwmr->access);
3255+
if (ret)
3256+
return ERR_PTR(ret);
3257+
3258+
return NULL;
3259+
}
3260+
30953261
/**
30963262
* irdma_reg_phys_mr - register kernel physical memory
30973263
* @pd: ibpd pointer
@@ -3199,16 +3365,10 @@ static void irdma_del_memlist(struct irdma_mr *iwmr,
31993365
*/
32003366
static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
32013367
{
3202-
struct ib_pd *ibpd = ib_mr->pd;
3203-
struct irdma_pd *iwpd = to_iwpd(ibpd);
32043368
struct irdma_mr *iwmr = to_iwmr(ib_mr);
32053369
struct irdma_device *iwdev = to_iwdev(ib_mr->device);
3206-
struct irdma_dealloc_stag_info *info;
32073370
struct irdma_pbl *iwpbl = &iwmr->iwpbl;
3208-
struct irdma_pble_alloc *palloc = &iwpbl->pble_alloc;
3209-
struct irdma_cqp_request *cqp_request;
3210-
struct cqp_cmds_info *cqp_info;
3211-
int status;
3371+
int ret;
32123372

32133373
if (iwmr->type != IRDMA_MEMREG_TYPE_MEM) {
32143374
if (iwmr->region) {
@@ -3222,33 +3382,18 @@ static int irdma_dereg_mr(struct ib_mr *ib_mr, struct ib_udata *udata)
32223382
goto done;
32233383
}
32243384

3225-
cqp_request = irdma_alloc_and_get_cqp_request(&iwdev->rf->cqp, true);
3226-
if (!cqp_request)
3227-
return -ENOMEM;
3228-
3229-
cqp_info = &cqp_request->info;
3230-
info = &cqp_info->in.u.dealloc_stag.info;
3231-
memset(info, 0, sizeof(*info));
3232-
info->pd_id = iwpd->sc_pd.pd_id;
3233-
info->stag_idx = ib_mr->rkey >> IRDMA_CQPSQ_STAG_IDX_S;
3234-
info->mr = true;
3235-
if (iwpbl->pbl_allocated)
3236-
info->dealloc_pbl = true;
3237-
3238-
cqp_info->cqp_cmd = IRDMA_OP_DEALLOC_STAG;
3239-
cqp_info->post_sq = 1;
3240-
cqp_info->in.u.dealloc_stag.dev = &iwdev->rf->sc_dev;
3241-
cqp_info->in.u.dealloc_stag.scratch = (uintptr_t)cqp_request;
3242-
status = irdma_handle_cqp_op(iwdev->rf, cqp_request);
3243-
irdma_put_cqp_request(&iwdev->rf->cqp, cqp_request);
3244-
if (status)
3245-
return status;
3385+
ret = irdma_hwdereg_mr(ib_mr);
3386+
if (ret)
3387+
return ret;
32463388

32473389
irdma_free_stag(iwdev, iwmr->stag);
32483390
done:
32493391
if (iwpbl->pbl_allocated)
3250-
irdma_free_pble(iwdev->rf->pble_rsrc, palloc);
3251-
ib_umem_release(iwmr->region);
3392+
irdma_free_pble(iwdev->rf->pble_rsrc, &iwpbl->pble_alloc);
3393+
3394+
if (iwmr->region)
3395+
ib_umem_release(iwmr->region);
3396+
32523397
kfree(iwmr);
32533398

32543399
return 0;
@@ -4578,6 +4723,7 @@ static const struct ib_device_ops irdma_dev_ops = {
45784723
.query_qp = irdma_query_qp,
45794724
.reg_user_mr = irdma_reg_user_mr,
45804725
.reg_user_mr_dmabuf = irdma_reg_user_mr_dmabuf,
4726+
.rereg_user_mr = irdma_rereg_user_mr,
45814727
.req_notify_cq = irdma_req_notify_cq,
45824728
.resize_cq = irdma_resize_cq,
45834729
INIT_RDMA_OBJ_SIZE(ib_pd, irdma_pd, ibpd),

drivers/infiniband/hw/irdma/verbs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@ struct irdma_mr {
100100
struct ib_mw ibmw;
101101
};
102102
struct ib_umem *region;
103+
int access;
104+
u8 is_hwreg;
103105
u16 type;
104106
u32 page_cnt;
105107
u64 page_size;

0 commit comments

Comments
 (0)