Skip to content

Commit a5e9c31

Browse files
committed
efa: Add support to allocate a parent domain
Parent domains are an extension for PDs and are interchangeable with them. Add support for parent domain allocations and deallocations. Since alloc parent domain verb is strictly a userspace verb and it binds an existing PD to it we can't dealloc the PD if it has parent domains referencing it so to handle it add PD refcount for parent domains. Also parent domains can't be deallocated while there are active objects (CQs/QPs etc.) using it, to prevent its deallocation add a refcount for it. Signed-off-by: Yonatan Nachum <[email protected]>
1 parent e8661f3 commit a5e9c31

File tree

4 files changed

+94
-0
lines changed

4 files changed

+94
-0
lines changed

providers/efa/efa.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ static const struct verbs_match_ent efa_table[] = {
2828

2929
static const struct verbs_context_ops efa_ctx_ops = {
3030
.alloc_pd = efa_alloc_pd,
31+
.alloc_parent_domain = efa_alloc_parent_domain,
3132
.alloc_td = efa_alloc_td,
3233
.create_ah = efa_create_ah,
3334
.create_cq = efa_create_cq,

providers/efa/efa.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ struct efa_context {
5151
struct efa_pd {
5252
struct ibv_pd ibvpd;
5353
uint16_t pdn;
54+
/* Pointer to original PD used to create parent domain */
55+
struct efa_pd *orig_pd;
56+
/* Number of parent domains referencing this PD */
57+
atomic_int refcount;
5458
};
5559

5660
struct efa_td {
@@ -59,6 +63,14 @@ struct efa_td {
5963
atomic_int refcount;
6064
};
6165

66+
struct efa_parent_domain {
67+
struct efa_pd pd;
68+
struct efa_td *td;
69+
/* Number of objects referencing this parent domain */
70+
atomic_int refcount;
71+
void *pd_context;
72+
};
73+
6274
struct efa_sub_cq {
6375
uint16_t consumed_cnt;
6476
int phase;
@@ -212,6 +224,11 @@ static inline struct efa_td *to_efa_td(struct ibv_td *ibvtd)
212224
return container_of(ibvtd, struct efa_td, ibvtd);
213225
}
214226

227+
static inline struct efa_parent_domain *to_efa_parent_domain(struct ibv_pd *ibvpd)
228+
{
229+
return container_of(ibvpd, struct efa_parent_domain, pd.ibvpd);
230+
}
231+
215232
bool is_efa_dev(struct ibv_device *device);
216233

217234
#endif /* __EFA_H__ */

providers/efa/verbs.c

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,7 @@ struct ibv_pd *efa_alloc_pd(struct ibv_context *ibvctx)
213213
goto out;
214214
}
215215

216+
atomic_init(&pd->refcount, 0);
216217
pd->pdn = resp.pdn;
217218

218219
return &pd->ibvpd;
@@ -223,11 +224,84 @@ struct ibv_pd *efa_alloc_pd(struct ibv_context *ibvctx)
223224
return NULL;
224225
}
225226

227+
struct ibv_pd *efa_alloc_parent_domain(struct ibv_context *ibvctx,
228+
struct ibv_parent_domain_init_attr *attr)
229+
{
230+
struct efa_parent_domain *parent_domain;
231+
struct efa_pd *pd;
232+
233+
if (ibv_check_alloc_parent_domain(attr)) {
234+
errno = EINVAL;
235+
return NULL;
236+
}
237+
238+
if (!check_comp_mask(attr->comp_mask,
239+
IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT)) {
240+
verbs_err(verbs_get_ctx(ibvctx), "Invalid comp_mask\n");
241+
errno = EOPNOTSUPP;
242+
return NULL;
243+
}
244+
245+
pd = to_efa_pd(attr->pd);
246+
247+
/* We don't allow nested parent domains */
248+
if (pd->orig_pd) {
249+
errno = EINVAL;
250+
return NULL;
251+
}
252+
253+
parent_domain = calloc(1, sizeof(*parent_domain));
254+
if (!parent_domain) {
255+
errno = ENOMEM;
256+
return NULL;
257+
}
258+
259+
atomic_init(&parent_domain->refcount, 0);
260+
261+
if (attr->td) {
262+
parent_domain->td = to_efa_td(attr->td);
263+
atomic_fetch_add(&parent_domain->td->refcount, 1);
264+
}
265+
266+
parent_domain->pd.orig_pd = pd;
267+
atomic_fetch_add(&pd->refcount, 1);
268+
269+
ibv_initialize_parent_domain(&parent_domain->pd.ibvpd, attr->pd);
270+
271+
if (attr->comp_mask & IBV_PARENT_DOMAIN_INIT_ATTR_PD_CONTEXT)
272+
parent_domain->pd_context = attr->pd_context;
273+
274+
return &parent_domain->pd.ibvpd;
275+
}
276+
277+
static int efa_dealloc_parent_domain(struct efa_parent_domain *parent_domain)
278+
{
279+
if (atomic_load(&parent_domain->refcount) > 0)
280+
return EBUSY;
281+
282+
atomic_fetch_sub(&parent_domain->pd.orig_pd->refcount, 1);
283+
284+
if (parent_domain->td)
285+
atomic_fetch_sub(&parent_domain->td->refcount, 1);
286+
287+
free(parent_domain);
288+
return 0;
289+
}
290+
226291
int efa_dealloc_pd(struct ibv_pd *ibvpd)
227292
{
293+
struct efa_parent_domain *parent_domain;
228294
struct efa_pd *pd = to_efa_pd(ibvpd);
229295
int err;
230296

297+
if (pd->orig_pd) {
298+
parent_domain = to_efa_parent_domain(ibvpd);
299+
return efa_dealloc_parent_domain(parent_domain);
300+
}
301+
302+
if (atomic_load(&pd->refcount) > 0)
303+
return EBUSY;
304+
231305
err = ibv_cmd_dealloc_pd(ibvpd);
232306
if (err) {
233307
verbs_err(verbs_get_ctx(ibvpd->context),

providers/efa/verbs.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ int efa_query_device_ex(struct ibv_context *context,
1616
const struct ibv_query_device_ex_input *input,
1717
struct ibv_device_attr_ex *attr, size_t attr_size);
1818
struct ibv_pd *efa_alloc_pd(struct ibv_context *uctx);
19+
struct ibv_pd *efa_alloc_parent_domain(struct ibv_context *ibvctx,
20+
struct ibv_parent_domain_init_attr *attr);
1921
int efa_dealloc_pd(struct ibv_pd *ibvpd);
2022
struct ibv_mr *efa_reg_dmabuf_mr(struct ibv_pd *pd, uint64_t offset,
2123
size_t length, uint64_t iova, int fd, int acc);

0 commit comments

Comments
 (0)