IB/mlx5: Fix micro UAR allocator
authorEli Cohen <eli@dev.mellanox.co.il>
Tue, 14 Jan 2014 15:45:12 +0000 (17:45 +0200)
committerRoland Dreier <roland@purestorage.com>
Tue, 14 Jan 2014 21:54:23 +0000 (13:54 -0800)
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>
drivers/infiniband/hw/mlx5/main.c
drivers/infiniband/hw/mlx5/qp.c
include/linux/mlx5/device.h

index 306534109627082c36e30f270b219e1a500c5590..9660d093f8cf14cdb686f2b432f6eca96519fb8b 100644 (file)
@@ -541,6 +541,7 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        struct mlx5_ib_ucontext *context;
        struct mlx5_uuar_info *uuari;
        struct mlx5_uar *uars;
+       int gross_uuars;
        int num_uars;
        int uuarn;
        int err;
@@ -559,11 +560,13 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        if (req.total_num_uuars == 0)
                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)
                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.bf_reg_size      = dev->mdev.caps.bf_reg_size;
        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;
        }
 
-       uuari->bitmap = kcalloc(BITS_TO_LONGS(req.total_num_uuars),
+       uuari->bitmap = kcalloc(BITS_TO_LONGS(gross_uuars),
                                sizeof(*uuari->bitmap),
                                GFP_KERNEL);
        if (!uuari->bitmap) {
@@ -595,13 +598,13 @@ static struct ib_ucontext *mlx5_ib_alloc_ucontext(struct ib_device *ibdev,
        /*
         * clear all fast path uuars
         */
-       for (i = 0; i < req.total_num_uuars; i++) {
+       for (i = 0; i < gross_uuars; i++) {
                uuarn = i & 3;
                if (uuarn == 2 || uuarn == 3)
                        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) {
                err = -ENOMEM;
                goto out_bitmap;
index 7c6b4ba49bec13c920120cb775090bd153354fb5..a056c243ddcde00471e0f05625b251e07bfa66ca 100644 (file)
@@ -340,14 +340,57 @@ static int qp_has_rq(struct ib_qp_init_attr *attr)
        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)
 {
-       int nuuars = uuari->num_uars * MLX5_BF_REGS_PER_PAGE;
-       int start_uuar;
        int i;
 
-       start_uuar = nuuars - uuari->num_low_latency_uuars;
-       for (i = start_uuar; i < nuuars; i++) {
+       for (i = first_hi_uuar(uuari); i < max_uuari(uuari); i = next_uuar(i)) {
                if (!test_bit(i, uuari->bitmap)) {
                        set_bit(i, uuari->bitmap);
                        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)
 {
-       int nuuars = uuari->num_uars * MLX5_BF_REGS_PER_PAGE;
-       int minidx = 1;
-       int uuarn;
-       int end;
+       int minidx = first_med_uuar();
        int i;
 
-       end = nuuars - uuari->num_low_latency_uuars;
-
-       for (i = 1; i < end; i++) {
-               uuarn = i & 3;
-               if (uuarn == 2 || uuarn == 3)
-                       continue;
-
+       for (i = first_med_uuar(); i < first_hi_uuar(uuari); i = next_uuar(i)) {
                if (uuari->count[i] < uuari->count[minidx])
                        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);
        if (uuarn < 0) {
                mlx5_ib_dbg(dev, "failed to allocate low latency UUAR\n");
-               mlx5_ib_dbg(dev, "reverting to high latency\n");
-               uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_LOW);
+               mlx5_ib_dbg(dev, "reverting to medium latency\n");
+               uuarn = alloc_uuar(&context->uuari, MLX5_IB_LATENCY_CLASS_MEDIUM);
                if (uuarn < 0) {
-                       mlx5_ib_dbg(dev, "uuar allocation failed\n");
-                       return uuarn;
+                       mlx5_ib_dbg(dev, "failed to allocate medium latency UUAR\n");
+                       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;
+                       }
                }
        }
 
index da78875807fc33bb7c77dff5d374e474ba815f31..2c1c62e339caad1a109b10c9f933227005ea9bf9 100644 (file)
@@ -104,9 +104,10 @@ enum {
 };
 
 enum {
-       MLX5_BF_REGS_PER_PAGE   = 4,
-       MLX5_MAX_UAR_PAGES      = 1 << 8,
-       MLX5_MAX_UUARS          = MLX5_MAX_UAR_PAGES * MLX5_BF_REGS_PER_PAGE,
+       MLX5_BF_REGS_PER_PAGE           = 4,
+       MLX5_MAX_UAR_PAGES              = 1 << 8,
+       MLX5_NON_FP_BF_REGS_PER_PAGE    = 2,
+       MLX5_MAX_UUARS  = MLX5_MAX_UAR_PAGES * MLX5_NON_FP_BF_REGS_PER_PAGE,
 };
 
 enum {