Skip to content

Commit

Permalink
mlx5: Add reserved_qpn allocation/deallocation support
Browse files Browse the repository at this point in the history
Support allocate and deallocate a reserved QP number over DEVX APIs.

Signed-off-by: Mark Zhang <[email protected]>
Signed-off-by: Yishai Hadas <[email protected]>
  • Loading branch information
MarkZhang81 authored and Yishai Hadas committed Jan 21, 2021
1 parent b8986e3 commit 628fb16
Show file tree
Hide file tree
Showing 10 changed files with 257 additions and 1 deletion.
3 changes: 3 additions & 0 deletions debian/ibverbs-providers.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ libmlx5.so.1 ibverbs-providers #MINVER#
MLX5_1.15@MLX5_1.15 31
MLX5_1.16@MLX5_1.16 32
MLX5_1.17@MLX5_1.17 33
MLX5_1.18@MLX5_1.18 34
mlx5dv_init_obj@MLX5_1.0 13
mlx5dv_init_obj@MLX5_1.2 15
mlx5dv_query_device@MLX5_1.0 13
Expand Down Expand Up @@ -121,6 +122,8 @@ libmlx5.so.1 ibverbs-providers #MINVER#
mlx5dv_sched_node_create@MLX5_1.17 33
mlx5dv_sched_node_destroy@MLX5_1.17 33
mlx5dv_sched_node_modify@MLX5_1.17 33
mlx5dv_reserved_qpn_alloc@MLX5_1.18 34
mlx5dv_reserved_qpn_dealloc@MLX5_1.18 34
libefa.so.1 ibverbs-providers #MINVER#
* Build-Depends-Package: libibverbs-dev
EFA_1.0@EFA_1.0 24
Expand Down
2 changes: 1 addition & 1 deletion providers/mlx5/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ if (MLX5_MW_DEBUG)
endif()

rdma_shared_provider(mlx5 libmlx5.map
1 1.17.${PACKAGE_VERSION}
1 1.18.${PACKAGE_VERSION}
buf.c
cq.c
dbrec.c
Expand Down
6 changes: 6 additions & 0 deletions providers/mlx5/libmlx5.map
Original file line number Diff line number Diff line change
Expand Up @@ -168,3 +168,9 @@ MLX5_1.17 {
mlx5dv_sched_node_destroy;
mlx5dv_sched_node_modify;
} MLX5_1.16;

MLX5_1.18 {
global:
mlx5dv_reserved_qpn_alloc;
mlx5dv_reserved_qpn_dealloc;
} MLX5_1.17;
2 changes: 2 additions & 0 deletions providers/mlx5/man/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ rdma_man_pages(
mlx5dv_pp_alloc.3.md
mlx5dv_query_device.3
mlx5dv_query_qp_lag_port.3.md
mlx5dv_reserved_qpn_alloc.3.md
mlx5dv_sched_node_create.3.md
mlx5dv_ts_to_ns.3
mlx5dv_wr_post.3.md
Expand Down Expand Up @@ -92,6 +93,7 @@ rdma_alias_man_pages(
mlx5dv_dump.3 mlx5dv_dump_dr_rule.3
mlx5dv_dump.3 mlx5dv_dump_dr_table.3
mlx5dv_pp_alloc.3 mlx5dv_pp_free.3
mlx5dv_reserved_qpn_alloc.3 mlx5dv_reserved_qpn_dealloc.3
mlx5dv_sched_node_create.3 mlx5dv_sched_leaf_create.3
mlx5dv_sched_node_create.3 mlx5dv_sched_leaf_destroy.3
mlx5dv_sched_node_create.3 mlx5dv_sched_leaf_modify.3
Expand Down
54 changes: 54 additions & 0 deletions providers/mlx5/man/mlx5dv_reserved_qpn_alloc.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
layout: page
title: mlx5dv_reserved_qpn_alloc / dealloc
section: 3
tagline: Verbs
date: 2020-12-29
header: "mlx5 Programmer's Manual"
footer: mlx5
---

# NAME

mlx5dv_reserved_qpn_alloc - Allocate a reserved QP number from device

mlx5dv_reserved_qpn_dealloc - Release the reserved QP number

# SYNOPSIS

```c
#include <infiniband/mlx5dv.h>

int mlx5dv_reserved_qpn_alloc(struct ibv_context *ctx, uint32_t *qpn);

int mlx5dv_reserved_qpn_dealloc(struct ibv_context *ctx, uint32_t qpn);
```
# DESCRIPTION
When work with RDMA_CM RDMA_TCP_PS + external QP support, a client node needs GUID level unique QP numbers to comply with the CM's timewait logic.
If a real unique QP is not allocated, a device global QPN value is required and can be allocated via this interface.
The mlx5 DCI QP is such an example, which could connect to the remote DCT's multiple times as long as the application provides unique QPN for each new RDMA_CM connection.
These 2 APIs provide the allocation/deallocation of a unique QP number from/to device. This qpn can be used with
DC QPN in RDMA_CM connection establishment, which will comply with the CM timewait kernel logic.
# ARGUMENTS
*ctx*
: The device context to issue the action on.
*qpn*
: The allocated QP number (for alloc API), or the QP number to be deallocated (for dealloc API).
# RETURN VALUE
0 on success; EOPNOTSUPP if not supported, or other errno value on other failures.
# AUTHOR
Mark Zhang <[email protected]>
Alex Rosenbaum <[email protected]>
158 changes: 158 additions & 0 deletions providers/mlx5/mlx5.c
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,160 @@ int mlx5dv_modify_qp_sched_elem(struct ibv_qp *qp,
}
}

static struct reserved_qpn_blk *reserved_qpn_blk_alloc(struct mlx5_context *mctx)
{
uint32_t out[DEVX_ST_SZ_DW(general_obj_out_cmd_hdr)] = {};
uint32_t in[DEVX_ST_SZ_DW(create_reserved_qpn_in)] = {};
struct reserved_qpn_blk *blk;
void *attr;

blk = calloc(1, sizeof(*blk));
if (!blk) {
errno = ENOMEM;
return NULL;
}

blk->bmp = bitmap_alloc0(1 << mctx->hca_cap_2_caps.log_reserved_qpns_per_obj);
if (!blk->bmp) {
errno = ENOMEM;
goto bmp_alloc_fail;
}

attr = DEVX_ADDR_OF(create_reserved_qpn_in, in, hdr);
DEVX_SET(general_obj_in_cmd_hdr,
attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
DEVX_SET(general_obj_in_cmd_hdr,
attr, obj_type, MLX5_OBJ_TYPE_RESERVED_QPN);
DEVX_SET(general_obj_in_cmd_hdr,
attr, log_obj_range, mctx->hca_cap_2_caps.log_reserved_qpns_per_obj);

blk->obj = mlx5dv_devx_obj_create(&mctx->ibv_ctx.context,
in, sizeof(in), out, sizeof(out));
if (!blk->obj)
goto obj_alloc_fail;

blk->first_qpn = blk->obj->object_id;
blk->next_avail_slot = 0;

return blk;

obj_alloc_fail:
free(blk->bmp);

bmp_alloc_fail:
free(blk);
return NULL;
}

static void reserved_qpn_blk_dealloc(struct reserved_qpn_blk *blk)
{
if (mlx5dv_devx_obj_destroy(blk->obj))
assert(false);

free(blk->bmp);
free(blk);
}

static void reserved_qpn_blks_free(struct mlx5_context *mctx)
{
struct reserved_qpn_blk *blk, *tmp;

pthread_mutex_lock(&mctx->reserved_qpns.mutex);

list_for_each_safe(&mctx->reserved_qpns.blk_list,
blk, tmp, entry) {
list_del(&blk->entry);
reserved_qpn_blk_dealloc(blk);
}

pthread_mutex_unlock(&mctx->reserved_qpns.mutex);
}

/**
* Allocate a reserved QPN either from the last FW object allocated,
* or by allocating a new one. When find a free QPN in an object, it
* always starts from last allocation position, to make sure the QPN
* always move forward to prevent stale QPN.
*/
int mlx5dv_reserved_qpn_alloc(struct ibv_context *ctx, uint32_t *qpn)
{
struct mlx5_context *mctx = to_mctx(ctx);
struct reserved_qpn_blk *blk;
uint32_t qpns_per_obj;
int ret = 0;

if (!is_mlx5_dev(ctx->device) ||
!(mctx->general_obj_types_caps & (1ULL << MLX5_OBJ_TYPE_RESERVED_QPN)))
return EOPNOTSUPP;

qpns_per_obj = 1 << mctx->hca_cap_2_caps.log_reserved_qpns_per_obj;

pthread_mutex_lock(&mctx->reserved_qpns.mutex);

blk = list_tail(&mctx->reserved_qpns.blk_list,
struct reserved_qpn_blk, entry);
if (!blk ||
(blk->next_avail_slot >= qpns_per_obj)) {
blk = reserved_qpn_blk_alloc(mctx);
if (!blk) {
ret = errno;
goto end;
}
list_add_tail(&mctx->reserved_qpns.blk_list, &blk->entry);
}

*qpn = blk->first_qpn + blk->next_avail_slot;
bitmap_set_bit(blk->bmp, blk->next_avail_slot);
blk->next_avail_slot++;

end:
pthread_mutex_unlock(&mctx->reserved_qpns.mutex);
return ret;
}

/**
* Deallocate a reserved QPN. The FW object is destroyed only when all QPNs
* in this object were used and freed.
*/
int mlx5dv_reserved_qpn_dealloc(struct ibv_context *ctx, uint32_t qpn)
{
struct mlx5_context *mctx = to_mctx(ctx);
struct reserved_qpn_blk *blk, *tmp;
uint32_t qpns_per_obj;
bool found = false;
int ret = 0;

qpns_per_obj = 1 << mctx->hca_cap_2_caps.log_reserved_qpns_per_obj;

pthread_mutex_lock(&mctx->reserved_qpns.mutex);

list_for_each_safe(&mctx->reserved_qpns.blk_list,
blk, tmp, entry) {
if ((qpn >= blk->first_qpn) &&
(qpn < blk->first_qpn + qpns_per_obj)) {
found = true;
break;
}
}

if (!found || !bitmap_test_bit(blk->bmp, qpn - blk->first_qpn)) {
errno = EINVAL;
ret = errno;
goto end;
}

bitmap_clear_bit(blk->bmp, qpn - blk->first_qpn);
if ((blk->next_avail_slot >= qpns_per_obj) &&
(bitmap_empty(blk->bmp, qpns_per_obj))) {
list_del(&blk->entry);
reserved_qpn_blk_dealloc(blk);
}

end:
pthread_mutex_unlock(&mctx->reserved_qpns.mutex);
return ret;
}

LATEST_SYMVER_FUNC(mlx5dv_init_obj, 1_2, "MLX5_1.2",
int,
struct mlx5dv_obj *obj, uint64_t obj_type)
Expand Down Expand Up @@ -1961,6 +2115,9 @@ static int mlx5_set_context(struct mlx5_context *context,
mlx5_set_singleton_nc_uar(&v_ctx->context);
context->cq_uar_reg = context->nc_uar ? context->nc_uar->uar : context->uar[0].reg;

pthread_mutex_init(&context->reserved_qpns.mutex, NULL);
list_head_init(&context->reserved_qpns.blk_list);

return 0;

err_free_bf:
Expand Down Expand Up @@ -2089,6 +2246,7 @@ static void mlx5_free_context(struct ibv_context *ibctx)
munmap((void *)context->clock_info_page, page_size);
close_debug_file(context);
clean_dyn_uars(ibctx);
reserved_qpn_blks_free(context);

verbs_uninit_context(&context->ibv_ctx);
free(context);
Expand Down
16 changes: 16 additions & 0 deletions providers/mlx5/mlx5.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <util/udma_barrier.h>
#include <util/util.h>
#include "mlx5-abi.h"
#include <ccan/bitmap.h>
#include <ccan/list.h>
#include "bitmap.h"
#include <ccan/minmax.h>
Expand Down Expand Up @@ -276,6 +277,19 @@ struct mlx5_hca_cap_2_caps {
uint32_t log_reserved_qpns_per_obj;
};

struct reserved_qpn_blk {
bitmap *bmp;
uint32_t first_qpn;
struct list_node entry;
unsigned int next_avail_slot;
struct mlx5dv_devx_obj *obj;
};

struct mlx5_reserved_qpns {
struct list_head blk_list;
pthread_mutex_t mutex;
};

struct mlx5_context {
struct verbs_context ibv_ctx;
int max_num_qps;
Expand Down Expand Up @@ -347,6 +361,7 @@ struct mlx5_context {
struct mlx5_entropy_caps entropy_caps;
struct mlx5_qos_caps qos_caps;
struct mlx5_hca_cap_2_caps hca_cap_2_caps;
uint64_t general_obj_types_caps;
uint8_t qpc_extension_cap:1;
pthread_mutex_t dyn_bfregs_mutex; /* protects the dynamic bfregs allocation */
uint32_t num_dyn_bfregs;
Expand All @@ -367,6 +382,7 @@ struct mlx5_context {
uint16_t qp_alloc_shared_uuars;
struct mlx5_bf *nc_uar;
void *cq_uar_reg;
struct mlx5_reserved_qpns reserved_qpns;
};

struct mlx5_bitmap {
Expand Down
10 changes: 10 additions & 0 deletions providers/mlx5/mlx5_ifc.h
Original file line number Diff line number Diff line change
Expand Up @@ -2446,6 +2446,7 @@ enum {
MLX5_OBJ_TYPE_ASO_FLOW_METER = 0x0024,
MLX5_OBJ_TYPE_ASO_FIRST_HIT = 0x0025,
MLX5_OBJ_TYPE_SCHEDULING_ELEMENT = 0x0026,
MLX5_OBJ_TYPE_RESERVED_QPN = 0x002C,
};

struct mlx5_ifc_general_obj_in_cmd_hdr_bits {
Expand Down Expand Up @@ -3487,4 +3488,13 @@ struct mlx5_ifc_modify_sq_in_bits {
struct mlx5_ifc_sqc_bits sq_context;
};

struct mlx5_ifc_reserved_qpn_bits {
u8 reserved_at_0[0x80];
};

struct mlx5_ifc_create_reserved_qpn_in_bits {
struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr;
struct mlx5_ifc_reserved_qpn_bits rqpns;
};

#endif /* MLX5_IFC_H */
3 changes: 3 additions & 0 deletions providers/mlx5/mlx5dv.h
Original file line number Diff line number Diff line change
Expand Up @@ -1657,6 +1657,9 @@ int mlx5dv_modify_qp_sched_elem(struct ibv_qp *qp,
const struct mlx5dv_sched_leaf *requestor,
const struct mlx5dv_sched_leaf *responder);

int mlx5dv_reserved_qpn_alloc(struct ibv_context *ctx, uint32_t *qpn);
int mlx5dv_reserved_qpn_dealloc(struct ibv_context *ctx, uint32_t qpn);

#ifdef __cplusplus
}
#endif
Expand Down
4 changes: 4 additions & 0 deletions providers/mlx5/verbs.c
Original file line number Diff line number Diff line change
Expand Up @@ -3488,6 +3488,10 @@ static void get_hca_general_caps(struct mlx5_context *mctx)
DEVX_GET(query_hca_cap_out, out,
capability.cmd_hca_cap.qpc_extension);

mctx->general_obj_types_caps =
DEVX_GET64(query_hca_cap_out, out,
capability.cmd_hca_cap.general_obj_types);

if (DEVX_GET(query_hca_cap_out, out,
capability.cmd_hca_cap.hca_cap_2))
get_hca_general_caps_2(mctx);
Expand Down

0 comments on commit 628fb16

Please sign in to comment.