IB/mlx5: Fix micro UAR allocator
The micro UAR (uuar) allocator had a bug which resulted from the fact that in each UAR we only have two micro UARs avaialable, those at index 0 and 1. This patch defines iterators to aid in traversing the list of available micro UARs when allocating a uuar. In addition, change the logic in create_user_qp() so that if high class allocation fails (high class means lower latency), we revert to medium class and not to the low class. Signed-off-by: Eli Cohen <eli@mellanox.com> Signed-off-by: Roland Dreier <roland@purestorage.com>
This commit is contained in:
parent
24e42754f6
commit
c1be5232d2
@ -541,6 +541,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
|
|||||||
struct mlx5_ib_ucontext *context;
|
struct mlx5_ib_ucontext *context;
|
||||||
struct mlx5_uuar_info *uuari;
|
struct mlx5_uuar_info *uuari;
|
||||||
struct mlx5_uar *uars;
|
struct mlx5_uar *uars;
|
||||||
|
int gross_uuars;
|
||||||
int num_uars;
|
int num_uars;
|
||||||
int uuarn;
|
int uuarn;
|
||||||
int err;
|
int err;
|
||||||
@ -559,11 +560,13 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
|
|||||||
if (req.total_num_uuars == 0)
|
if (req.total_num_uuars == 0)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
req.total_num_uuars = ALIGN(req.total_num_uuars, MLX5_BF_REGS_PER_PAGE);
|
req.total_num_uuars = ALIGN(req.total_num_uuars,
|
||||||
|
MLX5_NON_FP_BF_REGS_PER_PAGE);
|
||||||
if (req.num_low_latency_uuars > req.total_num_uuars - 1)
|
if (req.num_low_latency_uuars > req.total_num_uuars - 1)
|
||||||
return ERR_PTR(-EINVAL);
|
return ERR_PTR(-EINVAL);
|
||||||
|
|
||||||
num_uars = req.total_num_uuars / MLX5_BF_REGS_PER_PAGE;
|
num_uars = req.total_num_uuars / MLX5_NON_FP_BF_REGS_PER_PAGE;
|
||||||
|
gross_uuars = num_uars * MLX5_BF_REGS_PER_PAGE;
|
||||||
resp.qp_tab_size = 1 << dev->mdev.caps.log_max_qp;
|
resp.qp_tab_size = 1 << dev->mdev.caps.log_max_qp;
|
||||||
resp.bf_reg_size = dev->mdev.caps.bf_reg_size;
|
resp.bf_reg_size = dev->mdev.caps.bf_reg_size;
|
||||||
resp.cache_line_size = L1_CACHE_BYTES;
|
resp.cache_line_size = L1_CACHE_BYTES;
|
||||||
@ -585,7 +588,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
|
|||||||
goto out_ctx;
|
goto out_ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
uuari->bitmap = kcalloc(BITS_TO_LONGS(req.total_num_uuars),
|
uuari->bitmap = kcalloc(BITS_TO_LONGS(gross_uuars),
|
||||||
sizeof(*uuari->bitmap),
|
sizeof(*uuari->bitmap),
|
||||||
GFP_KERNEL);
|
GFP_KERNEL);
|
||||||
if (!uuari->bitmap) {
|
if (!uuari->bitmap) {
|
||||||
@ -595,13 +598,13 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
|
|||||||
/*
|
/*
|
||||||
* clear all fast path uuars
|
* clear all fast path uuars
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < req.total_num_uuars; i++) {
|
for (i = 0; i < gross_uuars; i++) {
|
||||||
uuarn = i & 3;
|
uuarn = i & 3;
|
||||||
if (uuarn == 2 || uuarn == 3)
|
if (uuarn == 2 || uuarn == 3)
|
||||||
set_bit(i, uuari->bitmap);
|
set_bit(i, uuari->bitmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
uuari->count = kcalloc(req.total_num_uuars, sizeof(*uuari->count), GFP_KERNEL);
|
uuari->count = kcalloc(gross_uuars, sizeof(*uuari->count), GFP_KERNEL);
|
||||||
if (!uuari->count) {
|
if (!uuari->count) {
|
||||||
err = -ENOMEM;
|
err = -ENOMEM;
|
||||||
goto out_bitmap;
|
goto out_bitmap;
|
||||||
|
@ -340,14 +340,57 @@ static int qp_has_rq(struct ib_qp_init_attr *attr)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int first_med_uuar(void)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int next_uuar(int n)
|
||||||
|
{
|
||||||
|
n++;
|
||||||
|
|
||||||
|
while (((n % 4) & 2))
|
||||||
|
n++;
|
||||||
|
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int num_med_uuar(struct mlx5_uuar_info *uuari)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = uuari->num_uars * MLX5_NON_FP_BF_REGS_PER_PAGE -
|
||||||
|
uuari->num_low_latency_uuars - 1;
|
||||||
|
|
||||||
|
return n >= 0 ? n : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int max_uuari(struct mlx5_uuar_info *uuari)
|
||||||
|
{
|
||||||
|
return uuari->num_uars * 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int first_hi_uuar(struct mlx5_uuar_info *uuari)
|
||||||
|
{
|
||||||
|
int med;
|
||||||
|
int i;
|
||||||
|
int t;
|
||||||
|
|
||||||
|
med = num_med_uuar(uuari);
|
||||||
|
for (t = 0, i = first_med_uuar();; i = next_uuar(i)) {
|
||||||
|
t++;
|
||||||
|
if (t == med)
|
||||||
|
return next_uuar(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int alloc_high_class_uuar(struct mlx5_uuar_info *uuari)
|
static int alloc_high_class_uuar(struct mlx5_uuar_info *uuari)
|
||||||
{
|
{
|
||||||
int nuuars = uuari->num_uars * MLX5_BF_REGS_PER_PAGE;
|
|
||||||
int start_uuar;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
start_uuar = nuuars - uuari->num_low_latency_uuars;
|
for (i = first_hi_uuar(uuari); i < max_uuari(uuari); i = next_uuar(i)) {
|
||||||
for (i = start_uuar; i < nuuars; i++) {
|
|
||||||
if (!test_bit(i, uuari->bitmap)) {
|
if (!test_bit(i, uuari->bitmap)) {
|
||||||
set_bit(i, uuari->bitmap);
|
set_bit(i, uuari->bitmap);
|
||||||
uuari->count[i]++;
|
uuari->count[i]++;
|
||||||
@ -360,19 +403,10 @@ static int alloc_high_class_uuar(struct mlx5_uuar_info *uuari)
|
|||||||
|
|
||||||
static int alloc_med_class_uuar(struct mlx5_uuar_info *uuari)
|
static int alloc_med_class_uuar(struct mlx5_uuar_info *uuari)
|
||||||
{
|
{
|
||||||
int nuuars = uuari->num_uars * MLX5_BF_REGS_PER_PAGE;
|
int minidx = first_med_uuar();
|
||||||
int minidx = 1;
|
|
||||||
int uuarn;
|
|
||||||
int end;
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
end = nuuars - uuari->num_low_latency_uuars;
|
for (i = first_med_uuar(); i < first_hi_uuar(uuari); i = next_uuar(i)) {
|
||||||
|
|
||||||
for (i = 1; i < end; i++) {
|
|
||||||
uuarn = i & 3;
|
|
||||||
if (uuarn == 2 || uuarn == 3)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (uuari->count[i] < uuari->count[minidx])
|
if (uuari->count[i] < uuari->count[minidx])
|
||||||
minidx = i;
|
minidx = i;
|
||||||
}
|
}
|
||||||
@ -510,11 +544,16 @@ static int create_user_qp(struct mlx5_ib_dev *dev, struct ib_pd *pd,
|
|||||||
uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_HIGH);
|
uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_HIGH);
|
||||||
if (uuarn < 0) {
|
if (uuarn < 0) {
|
||||||
mlx5_ib_dbg(dev, "failed to allocate low latency UUAR\n");
|
mlx5_ib_dbg(dev, "failed to allocate low latency UUAR\n");
|
||||||
mlx5_ib_dbg(dev, "reverting to high latency\n");
|
mlx5_ib_dbg(dev, "reverting to medium latency\n");
|
||||||
uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_LOW);
|
uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_MEDIUM);
|
||||||
if (uuarn < 0) {
|
if (uuarn < 0) {
|
||||||
mlx5_ib_dbg(dev, "uuar allocation failed\n");
|
mlx5_ib_dbg(dev, "failed to allocate medium latency UUAR\n");
|
||||||
return uuarn;
|
mlx5_ib_dbg(dev, "reverting to high latency\n");
|
||||||
|
uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_LOW);
|
||||||
|
if (uuarn < 0) {
|
||||||
|
mlx5_ib_warn(dev, "uuar allocation failed\n");
|
||||||
|
return uuarn;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,9 +104,10 @@ enum {
|
|||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MLX5_BF_REGS_PER_PAGE = 4,
|
MLX5_BF_REGS_PER_PAGE = 4,
|
||||||
MLX5_MAX_UAR_PAGES = 1 << 8,
|
MLX5_MAX_UAR_PAGES = 1 << 8,
|
||||||
MLX5_MAX_UUARS = MLX5_MAX_UAR_PAGES * MLX5_BF_REGS_PER_PAGE,
|
MLX5_NON_FP_BF_REGS_PER_PAGE = 2,
|
||||||
|
MLX5_MAX_UUARS = MLX5_MAX_UAR_PAGES * MLX5_NON_FP_BF_REGS_PER_PAGE,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
|
Loading…
Reference in New Issue
Block a user