mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-07-07 14:25:22 +02:00
IB/mlx5: Create UMR QP just before first reg_mr occurs
UMR QP is not used in some cases, so move QP and its CQ creations from driver load flow to the time first reg_mr occurs, that is when MR interfaces are first called. The initialization of dev->umrc.pd and dev->umrc.lock is still done in driver load because pd is needed for mlx5_mkey_cache_init and the lock is reused to protect against the concurrent creation. When testing 4G bytes memory registration latency with rtool [1] and 8 threads in parallel, there is minor performance degradation (<5% for the max latency) is seen for the first reg_mr with this change. Link: https://github.com/paravmellanox/rtool [1] Signed-off-by: Jianbo Liu <jianbol@nvidia.com> Link: https://lore.kernel.org/r/55d3c4f8a542fd974d8a4c5816eccfb318a59b38.1717409369.git.leon@kernel.org Signed-off-by: Leon Romanovsky <leon@kernel.org>
This commit is contained in:
parent
ae6f6dd5fd
commit
638420115c
|
@ -4086,6 +4086,7 @@ static void mlx5_ib_stage_pre_ib_reg_umr_cleanup(struct mlx5_ib_dev *dev)
|
||||||
{
|
{
|
||||||
mlx5_mkey_cache_cleanup(dev);
|
mlx5_mkey_cache_cleanup(dev);
|
||||||
mlx5r_umr_resource_cleanup(dev);
|
mlx5r_umr_resource_cleanup(dev);
|
||||||
|
mlx5r_umr_cleanup(dev);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
|
static void mlx5_ib_stage_ib_reg_cleanup(struct mlx5_ib_dev *dev)
|
||||||
|
@ -4097,7 +4098,7 @@ static int mlx5_ib_stage_post_ib_reg_umr_init(struct mlx5_ib_dev *dev)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = mlx5r_umr_resource_init(dev);
|
ret = mlx5r_umr_init(dev);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
@ -751,6 +751,8 @@ struct umr_common {
|
||||||
*/
|
*/
|
||||||
struct mutex lock;
|
struct mutex lock;
|
||||||
unsigned int state;
|
unsigned int state;
|
||||||
|
/* Protects from repeat UMR QP creation */
|
||||||
|
struct mutex init_lock;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define NUM_MKEYS_PER_PAGE \
|
#define NUM_MKEYS_PER_PAGE \
|
||||||
|
|
|
@ -1470,6 +1470,7 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||||
{
|
{
|
||||||
struct mlx5_ib_dev *dev = to_mdev(pd->device);
|
struct mlx5_ib_dev *dev = to_mdev(pd->device);
|
||||||
struct ib_umem *umem;
|
struct ib_umem *umem;
|
||||||
|
int err;
|
||||||
|
|
||||||
if (!IS_ENABLED(CONFIG_INFINIBAND_USER_MEM))
|
if (!IS_ENABLED(CONFIG_INFINIBAND_USER_MEM))
|
||||||
return ERR_PTR(-EOPNOTSUPP);
|
return ERR_PTR(-EOPNOTSUPP);
|
||||||
|
@ -1477,6 +1478,10 @@ struct ib_mr *mlx5_ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
|
||||||
mlx5_ib_dbg(dev, "start 0x%llx, iova 0x%llx, length 0x%llx, access_flags 0x%x\n",
|
mlx5_ib_dbg(dev, "start 0x%llx, iova 0x%llx, length 0x%llx, access_flags 0x%x\n",
|
||||||
start, iova, length, access_flags);
|
start, iova, length, access_flags);
|
||||||
|
|
||||||
|
err = mlx5r_umr_resource_init(dev);
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
|
||||||
if (access_flags & IB_ACCESS_ON_DEMAND)
|
if (access_flags & IB_ACCESS_ON_DEMAND)
|
||||||
return create_user_odp_mr(pd, start, length, iova, access_flags,
|
return create_user_odp_mr(pd, start, length, iova, access_flags,
|
||||||
udata);
|
udata);
|
||||||
|
@ -1523,6 +1528,10 @@ struct ib_mr *mlx5_ib_reg_user_mr_dmabuf(struct ib_pd *pd, u64 offset,
|
||||||
"offset 0x%llx, virt_addr 0x%llx, length 0x%llx, fd %d, access_flags 0x%x\n",
|
"offset 0x%llx, virt_addr 0x%llx, length 0x%llx, fd %d, access_flags 0x%x\n",
|
||||||
offset, virt_addr, length, fd, access_flags);
|
offset, virt_addr, length, fd, access_flags);
|
||||||
|
|
||||||
|
err = mlx5r_umr_resource_init(dev);
|
||||||
|
if (err)
|
||||||
|
return ERR_PTR(err);
|
||||||
|
|
||||||
/* dmabuf requires xlt update via umr to work. */
|
/* dmabuf requires xlt update via umr to work. */
|
||||||
if (!mlx5r_umr_can_load_pas(dev, length))
|
if (!mlx5r_umr_can_load_pas(dev, length))
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
|
@ -135,22 +135,28 @@ static int mlx5r_umr_qp_rst2rts(struct mlx5_ib_dev *dev, struct ib_qp *qp)
|
||||||
int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
|
int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
|
||||||
{
|
{
|
||||||
struct ib_qp_init_attr init_attr = {};
|
struct ib_qp_init_attr init_attr = {};
|
||||||
struct ib_pd *pd;
|
|
||||||
struct ib_cq *cq;
|
struct ib_cq *cq;
|
||||||
struct ib_qp *qp;
|
struct ib_qp *qp;
|
||||||
int ret;
|
int ret = 0;
|
||||||
|
|
||||||
pd = ib_alloc_pd(&dev->ib_dev, 0);
|
|
||||||
if (IS_ERR(pd)) {
|
/*
|
||||||
mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n");
|
* UMR qp is set once, never changed until device unload.
|
||||||
return PTR_ERR(pd);
|
* Avoid taking the mutex if initialization is already done.
|
||||||
}
|
*/
|
||||||
|
if (dev->umrc.qp)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mutex_lock(&dev->umrc.init_lock);
|
||||||
|
/* First user allocates the UMR resources. Skip if already allocated. */
|
||||||
|
if (dev->umrc.qp)
|
||||||
|
goto unlock;
|
||||||
|
|
||||||
cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ);
|
cq = ib_alloc_cq(&dev->ib_dev, NULL, 128, 0, IB_POLL_SOFTIRQ);
|
||||||
if (IS_ERR(cq)) {
|
if (IS_ERR(cq)) {
|
||||||
mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n");
|
mlx5_ib_dbg(dev, "Couldn't create CQ for sync UMR QP\n");
|
||||||
ret = PTR_ERR(cq);
|
ret = PTR_ERR(cq);
|
||||||
goto destroy_pd;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
init_attr.send_cq = cq;
|
init_attr.send_cq = cq;
|
||||||
|
@ -160,7 +166,7 @@ int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
|
||||||
init_attr.cap.max_send_sge = 1;
|
init_attr.cap.max_send_sge = 1;
|
||||||
init_attr.qp_type = MLX5_IB_QPT_REG_UMR;
|
init_attr.qp_type = MLX5_IB_QPT_REG_UMR;
|
||||||
init_attr.port_num = 1;
|
init_attr.port_num = 1;
|
||||||
qp = ib_create_qp(pd, &init_attr);
|
qp = ib_create_qp(dev->umrc.pd, &init_attr);
|
||||||
if (IS_ERR(qp)) {
|
if (IS_ERR(qp)) {
|
||||||
mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
|
mlx5_ib_dbg(dev, "Couldn't create sync UMR QP\n");
|
||||||
ret = PTR_ERR(qp);
|
ret = PTR_ERR(qp);
|
||||||
|
@ -171,22 +177,22 @@ int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev)
|
||||||
if (ret)
|
if (ret)
|
||||||
goto destroy_qp;
|
goto destroy_qp;
|
||||||
|
|
||||||
dev->umrc.qp = qp;
|
|
||||||
dev->umrc.cq = cq;
|
dev->umrc.cq = cq;
|
||||||
dev->umrc.pd = pd;
|
|
||||||
|
|
||||||
sema_init(&dev->umrc.sem, MAX_UMR_WR);
|
sema_init(&dev->umrc.sem, MAX_UMR_WR);
|
||||||
mutex_init(&dev->umrc.lock);
|
mutex_init(&dev->umrc.lock);
|
||||||
dev->umrc.state = MLX5_UMR_STATE_ACTIVE;
|
dev->umrc.state = MLX5_UMR_STATE_ACTIVE;
|
||||||
|
dev->umrc.qp = qp;
|
||||||
|
|
||||||
|
mutex_unlock(&dev->umrc.init_lock);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
destroy_qp:
|
destroy_qp:
|
||||||
ib_destroy_qp(qp);
|
ib_destroy_qp(qp);
|
||||||
destroy_cq:
|
destroy_cq:
|
||||||
ib_free_cq(cq);
|
ib_free_cq(cq);
|
||||||
destroy_pd:
|
unlock:
|
||||||
ib_dealloc_pd(pd);
|
mutex_unlock(&dev->umrc.init_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,8 +200,31 @@ void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev)
|
||||||
{
|
{
|
||||||
if (dev->umrc.state == MLX5_UMR_STATE_UNINIT)
|
if (dev->umrc.state == MLX5_UMR_STATE_UNINIT)
|
||||||
return;
|
return;
|
||||||
|
mutex_destroy(&dev->umrc.lock);
|
||||||
|
/* After device init, UMR cp/qp are not unset during the lifetime. */
|
||||||
ib_destroy_qp(dev->umrc.qp);
|
ib_destroy_qp(dev->umrc.qp);
|
||||||
ib_free_cq(dev->umrc.cq);
|
ib_free_cq(dev->umrc.cq);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mlx5r_umr_init(struct mlx5_ib_dev *dev)
|
||||||
|
{
|
||||||
|
struct ib_pd *pd;
|
||||||
|
|
||||||
|
pd = ib_alloc_pd(&dev->ib_dev, 0);
|
||||||
|
if (IS_ERR(pd)) {
|
||||||
|
mlx5_ib_dbg(dev, "Couldn't create PD for sync UMR QP\n");
|
||||||
|
return PTR_ERR(pd);
|
||||||
|
}
|
||||||
|
dev->umrc.pd = pd;
|
||||||
|
|
||||||
|
mutex_init(&dev->umrc.init_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void mlx5r_umr_cleanup(struct mlx5_ib_dev *dev)
|
||||||
|
{
|
||||||
|
mutex_destroy(&dev->umrc.init_lock);
|
||||||
ib_dealloc_pd(dev->umrc.pd);
|
ib_dealloc_pd(dev->umrc.pd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,9 @@
|
||||||
int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev);
|
int mlx5r_umr_resource_init(struct mlx5_ib_dev *dev);
|
||||||
void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev);
|
void mlx5r_umr_resource_cleanup(struct mlx5_ib_dev *dev);
|
||||||
|
|
||||||
|
int mlx5r_umr_init(struct mlx5_ib_dev *dev);
|
||||||
|
void mlx5r_umr_cleanup(struct mlx5_ib_dev *dev);
|
||||||
|
|
||||||
static inline bool mlx5r_umr_can_load_pas(struct mlx5_ib_dev *dev,
|
static inline bool mlx5r_umr_can_load_pas(struct mlx5_ib_dev *dev,
|
||||||
size_t length)
|
size_t length)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue
Block a user