@@ -1028,6 +1028,7 @@ static int mlx5_init_context(struct verbs_device *vdev,
v_ctx->modify_cq = mlx5_modify_cq;
v_ctx->alloc_td = mlx5_alloc_td;
v_ctx->dealloc_td = mlx5_dealloc_td;
+ v_ctx->alloc_parent_domain = mlx5_alloc_parent_domain;
memset(&device_attr, 0, sizeof(device_attr));
if (!mlx5_query_device_ex(ctx, NULL, &device_attr,
@@ -329,6 +329,13 @@ struct mlx5_td {
struct mlx5_pd {
struct ibv_pd ibv_pd;
uint32_t pdn;
+ atomic_int refcount;
+ struct mlx5_pd *mprotection_domain;
+};
+
+struct mlx5_parent_domain {
+ struct mlx5_pd mpd;
+ struct mlx5_td *mtd;
};
enum {
@@ -557,9 +564,27 @@ static inline struct mlx5_context *to_mctx(struct ibv_context *ibctx)
return to_mxxx(ctx, context);
}
+/* to_mpd always returns the real mlx5_pd object ie the protection domain. */
static inline struct mlx5_pd *to_mpd(struct ibv_pd *ibpd)
{
- return to_mxxx(pd, pd);
+ struct mlx5_pd *mpd = to_mxxx(pd, pd);
+
+ if (mpd->mprotection_domain)
+ return mpd->mprotection_domain;
+
+ return mpd;
+}
+
+static inline struct mlx5_parent_domain *to_mparent_domain(struct ibv_pd *ibpd)
+{
+ struct mlx5_parent_domain *mparent_domain =
+ ibpd ? container_of(ibpd, struct mlx5_parent_domain, mpd.ibv_pd) : NULL;
+
+ if (mparent_domain && mparent_domain->mpd.mprotection_domain)
+ return mparent_domain;
+
+ /* Otherwise ibpd isn't a parent_domain */
+ return NULL;
}
static inline struct mlx5_cq *to_mcq(struct ibv_cq *ibcq)
@@ -767,6 +792,10 @@ int mlx5_post_srq_ops(struct ibv_srq *srq,
struct ibv_td *mlx5_alloc_td(struct ibv_context *context, struct ibv_td_init_attr *init_attr);
int mlx5_dealloc_td(struct ibv_td *td);
+struct ibv_pd *mlx5_alloc_parent_domain(struct ibv_context *context,
+ struct ibv_parent_domain_init_attr *attr);
+
+
static inline void *mlx5_find_uidx(struct mlx5_context *ctx, uint32_t uidx)
{
int tind = uidx >> MLX5_UIDX_TABLE_SHIFT;
@@ -148,6 +148,7 @@ struct ibv_pd *mlx5_alloc_pd(struct ibv_context *context)
return NULL;
}
+ atomic_init(&pd->refcount, 1);
pd->pdn = resp.pdn;
return &pd->ibv_pd;
@@ -203,15 +204,73 @@ int mlx5_dealloc_td(struct ibv_td *ib_td)
return 0;
}
+struct ibv_pd *
+mlx5_alloc_parent_domain(struct ibv_context *context,
+ struct ibv_parent_domain_init_attr *attr)
+{
+ struct mlx5_parent_domain *mparent_domain;
+
+ if (ibv_check_alloc_parent_domain(attr))
+ return NULL;
+
+ if (attr->comp_mask) {
+ errno = EINVAL;
+ return NULL;
+ }
+
+ mparent_domain = calloc(1, sizeof(*mparent_domain));
+ if (!mparent_domain) {
+ errno = ENOMEM;
+ return NULL;
+ }
+
+ if (attr->td) {
+ mparent_domain->mtd = to_mtd(attr->td);
+ atomic_fetch_add(&mparent_domain->mtd->refcount, 1);
+ }
+
+ mparent_domain->mpd.mprotection_domain = to_mpd(attr->pd);
+ atomic_fetch_add(&mparent_domain->mpd.mprotection_domain->refcount, 1);
+ atomic_init(&mparent_domain->mpd.refcount, 1);
+
+ ibv_initialize_parent_domain(
+ &mparent_domain->mpd.ibv_pd,
+ &mparent_domain->mpd.mprotection_domain->ibv_pd);
+
+ return &mparent_domain->mpd.ibv_pd;
+}
+
+static int mlx5_dealloc_parent_domain(struct mlx5_parent_domain *mparent_domain)
+{
+ if (atomic_load(&mparent_domain->mpd.refcount) > 1)
+ return EBUSY;
+
+ atomic_fetch_sub(&mparent_domain->mpd.mprotection_domain->refcount, 1);
+
+ if (mparent_domain->mtd)
+ atomic_fetch_sub(&mparent_domain->mtd->refcount, 1);
+
+ free(mparent_domain);
+ return 0;
+}
+
int mlx5_free_pd(struct ibv_pd *pd)
{
int ret;
+ struct mlx5_parent_domain *mparent_domain = to_mparent_domain(pd);
+ struct mlx5_pd *mpd = to_mpd(pd);
+
+ if (mparent_domain)
+ return mlx5_dealloc_parent_domain(mparent_domain);
+
+ if (atomic_load(&mpd->refcount) > 1)
+ return EBUSY;
ret = ibv_cmd_dealloc_pd(pd);
if (ret)
return ret;
- free(to_mpd(pd));
+ free(mpd);
return 0;
}
This patch adds support for ibv_alloc_parent domain verb in the mlx5 driver. The driver uses internally the mlx5_pd structure which as its prefix holds the core ibv_pd so that the return ibv_pd can be used with any verb that gets a protection domain. A parent domain must include a valid protection domain pointer and optionally can hold a thread domain. When used as a parent domain the core ibv_pd completely duplicates the protection domain core fields, so the two pointers are totally interchangeable in all core APIs, minimizing driver changes. Signed-off-by: Yishai Hadas <yishaih@mellanox.com> --- providers/mlx5/mlx5.c | 1 + providers/mlx5/mlx5.h | 31 ++++++++++++++++++++++++- providers/mlx5/verbs.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 91 insertions(+), 2 deletions(-)