Commit c1be5232 authored by Eli Cohen's avatar Eli Cohen Committed by Roland Dreier

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: default avatarEli Cohen <eli@mellanox.com>
Signed-off-by: default avatarRoland Dreier <roland@purestorage.com>
parent 24e42754
...@@ -541,6 +541,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev, ...@@ -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, ...@@ -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, ...@@ -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, ...@@ -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) ...@@ -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) ...@@ -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, ...@@ -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 { ...@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment