net/mlx4_core: Fix endianness bug in set_param_l
[cascardo/linux.git] / drivers / net / ethernet / mellanox / mlx4 / mr.c
index c202d3a..f91719a 100644 (file)
 #include "mlx4.h"
 #include "icm.h"
 
-#define MLX4_MPT_FLAG_SW_OWNS      (0xfUL << 28)
-#define MLX4_MPT_FLAG_FREE         (0x3UL << 28)
-#define MLX4_MPT_FLAG_MIO          (1 << 17)
-#define MLX4_MPT_FLAG_BIND_ENABLE   (1 << 15)
-#define MLX4_MPT_FLAG_PHYSICAL     (1 <<  9)
-#define MLX4_MPT_FLAG_REGION       (1 <<  8)
-
-#define MLX4_MPT_PD_FLAG_FAST_REG   (1 << 27)
-#define MLX4_MPT_PD_FLAG_RAE       (1 << 28)
-#define MLX4_MPT_PD_FLAG_EN_INV            (3 << 24)
-
-#define MLX4_MPT_STATUS_SW             0xF0
-#define MLX4_MPT_STATUS_HW             0x00
-
 static u32 mlx4_buddy_alloc(struct mlx4_buddy *buddy, int order)
 {
        int o;
@@ -197,7 +183,7 @@ u32 __mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
 
 static u32 mlx4_alloc_mtt_range(struct mlx4_dev *dev, int order)
 {
-       u64 in_param;
+       u64 in_param = 0;
        u64 out_param;
        int err;
 
@@ -254,7 +240,7 @@ void __mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
 
 static void mlx4_free_mtt_range(struct mlx4_dev *dev, u32 offset, int order)
 {
-       u64 in_param;
+       u64 in_param = 0;
        int err;
 
        if (mlx4_is_mfunc(dev)) {
@@ -321,7 +307,7 @@ static int mlx4_mr_alloc_reserved(struct mlx4_dev *dev, u32 mridx, u32 pd,
        mr->size       = size;
        mr->pd         = pd;
        mr->access     = access;
-       mr->enabled    = MLX4_MR_DISABLED;
+       mr->enabled    = MLX4_MPT_DISABLED;
        mr->key        = hw_index_to_key(mridx);
 
        return mlx4_mtt_init(dev, npages, page_shift, &mr->mtt);
@@ -335,14 +321,14 @@ static int mlx4_WRITE_MTT(struct mlx4_dev *dev,
                        MLX4_CMD_TIME_CLASS_A,  MLX4_CMD_WRAPPED);
 }
 
-int __mlx4_mr_reserve(struct mlx4_dev *dev)
+int __mlx4_mpt_reserve(struct mlx4_dev *dev)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
 
        return mlx4_bitmap_alloc(&priv->mr_table.mpt_bitmap);
 }
 
-static int mlx4_mr_reserve(struct mlx4_dev *dev)
+static int mlx4_mpt_reserve(struct mlx4_dev *dev)
 {
        u64 out_param;
 
@@ -353,19 +339,19 @@ static int mlx4_mr_reserve(struct mlx4_dev *dev)
                        return -1;
                return get_param_l(&out_param);
        }
-       return  __mlx4_mr_reserve(dev);
+       return  __mlx4_mpt_reserve(dev);
 }
 
-void __mlx4_mr_release(struct mlx4_dev *dev, u32 index)
+void __mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
 
        mlx4_bitmap_free(&priv->mr_table.mpt_bitmap, index);
 }
 
-static void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
+static void mlx4_mpt_release(struct mlx4_dev *dev, u32 index)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, index);
@@ -376,19 +362,19 @@ static void mlx4_mr_release(struct mlx4_dev *dev, u32 index)
                                  index);
                return;
        }
-       __mlx4_mr_release(dev, index);
+       __mlx4_mpt_release(dev, index);
 }
 
-int __mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
+int __mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
 {
        struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
 
        return mlx4_table_get(dev, &mr_table->dmpt_table, index);
 }
 
-static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
+static int mlx4_mpt_alloc_icm(struct mlx4_dev *dev, u32 index)
 {
-       u64 param;
+       u64 param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&param, index);
@@ -397,19 +383,19 @@ static int mlx4_mr_alloc_icm(struct mlx4_dev *dev, u32 index)
                                                        MLX4_CMD_TIME_CLASS_A,
                                                        MLX4_CMD_WRAPPED);
        }
-       return __mlx4_mr_alloc_icm(dev, index);
+       return __mlx4_mpt_alloc_icm(dev, index);
 }
 
-void __mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
+void __mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
 {
        struct mlx4_mr_table *mr_table = &mlx4_priv(dev)->mr_table;
 
        mlx4_table_put(dev, &mr_table->dmpt_table, index);
 }
 
-static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
+static void mlx4_mpt_free_icm(struct mlx4_dev *dev, u32 index)
 {
-       u64 in_param;
+       u64 in_param = 0;
 
        if (mlx4_is_mfunc(dev)) {
                set_param_l(&in_param, index);
@@ -420,7 +406,7 @@ static void mlx4_mr_free_icm(struct mlx4_dev *dev, u32 index)
                                  index);
                return;
        }
-       return __mlx4_mr_free_icm(dev, index);
+       return __mlx4_mpt_free_icm(dev, index);
 }
 
 int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
@@ -429,41 +415,52 @@ int mlx4_mr_alloc(struct mlx4_dev *dev, u32 pd, u64 iova, u64 size, u32 access,
        u32 index;
        int err;
 
-       index = mlx4_mr_reserve(dev);
+       index = mlx4_mpt_reserve(dev);
        if (index == -1)
                return -ENOMEM;
 
        err = mlx4_mr_alloc_reserved(dev, index, pd, iova, size,
                                     access, npages, page_shift, mr);
        if (err)
-               mlx4_mr_release(dev, index);
+               mlx4_mpt_release(dev, index);
 
        return err;
 }
 EXPORT_SYMBOL_GPL(mlx4_mr_alloc);
 
-static void mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr)
+static int mlx4_mr_free_reserved(struct mlx4_dev *dev, struct mlx4_mr *mr)
 {
        int err;
 
-       if (mr->enabled == MLX4_MR_EN_HW) {
+       if (mr->enabled == MLX4_MPT_EN_HW) {
                err = mlx4_HW2SW_MPT(dev, NULL,
                                     key_to_hw_index(mr->key) &
                                     (dev->caps.num_mpts - 1));
-               if (err)
-                       mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err);
+               if (err) {
+                       mlx4_warn(dev, "HW2SW_MPT failed (%d),", err);
+                       mlx4_warn(dev, "MR has MWs bound to it.\n");
+                       return err;
+               }
 
-               mr->enabled = MLX4_MR_EN_SW;
+               mr->enabled = MLX4_MPT_EN_SW;
        }
        mlx4_mtt_cleanup(dev, &mr->mtt);
+
+       return 0;
 }
 
-void mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
+int mlx4_mr_free(struct mlx4_dev *dev, struct mlx4_mr *mr)
 {
-       mlx4_mr_free_reserved(dev, mr);
+       int ret;
+
+       ret = mlx4_mr_free_reserved(dev, mr);
+       if (ret)
+               return ret;
        if (mr->enabled)
-               mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
-       mlx4_mr_release(dev, key_to_hw_index(mr->key));
+               mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
+       mlx4_mpt_release(dev, key_to_hw_index(mr->key));
+
+       return 0;
 }
 EXPORT_SYMBOL_GPL(mlx4_mr_free);
 
@@ -473,7 +470,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
        struct mlx4_mpt_entry *mpt_entry;
        int err;
 
-       err = mlx4_mr_alloc_icm(dev, key_to_hw_index(mr->key));
+       err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mr->key));
        if (err)
                return err;
 
@@ -520,7 +517,7 @@ int mlx4_mr_enable(struct mlx4_dev *dev, struct mlx4_mr *mr)
                mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
                goto err_cmd;
        }
-       mr->enabled = MLX4_MR_EN_HW;
+       mr->enabled = MLX4_MPT_EN_HW;
 
        mlx4_free_cmd_mailbox(dev, mailbox);
 
@@ -530,7 +527,7 @@ err_cmd:
        mlx4_free_cmd_mailbox(dev, mailbox);
 
 err_table:
-       mlx4_mr_free_icm(dev, key_to_hw_index(mr->key));
+       mlx4_mpt_free_icm(dev, key_to_hw_index(mr->key));
        return err;
 }
 EXPORT_SYMBOL_GPL(mlx4_mr_enable);
@@ -657,6 +654,101 @@ int mlx4_buf_write_mtt(struct mlx4_dev *dev, struct mlx4_mtt *mtt,
 }
 EXPORT_SYMBOL_GPL(mlx4_buf_write_mtt);
 
+int mlx4_mw_alloc(struct mlx4_dev *dev, u32 pd, enum mlx4_mw_type type,
+                 struct mlx4_mw *mw)
+{
+       u32 index;
+
+       if ((type == MLX4_MW_TYPE_1 &&
+            !(dev->caps.flags & MLX4_DEV_CAP_FLAG_MEM_WINDOW)) ||
+            (type == MLX4_MW_TYPE_2 &&
+            !(dev->caps.bmme_flags & MLX4_BMME_FLAG_TYPE_2_WIN)))
+               return -ENOTSUPP;
+
+       index = mlx4_mpt_reserve(dev);
+       if (index == -1)
+               return -ENOMEM;
+
+       mw->key     = hw_index_to_key(index);
+       mw->pd      = pd;
+       mw->type    = type;
+       mw->enabled = MLX4_MPT_DISABLED;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mlx4_mw_alloc);
+
+int mlx4_mw_enable(struct mlx4_dev *dev, struct mlx4_mw *mw)
+{
+       struct mlx4_cmd_mailbox *mailbox;
+       struct mlx4_mpt_entry *mpt_entry;
+       int err;
+
+       err = mlx4_mpt_alloc_icm(dev, key_to_hw_index(mw->key));
+       if (err)
+               return err;
+
+       mailbox = mlx4_alloc_cmd_mailbox(dev);
+       if (IS_ERR(mailbox)) {
+               err = PTR_ERR(mailbox);
+               goto err_table;
+       }
+       mpt_entry = mailbox->buf;
+
+       memset(mpt_entry, 0, sizeof(*mpt_entry));
+
+       /* Note that the MLX4_MPT_FLAG_REGION bit in mpt_entry->flags is turned
+        * off, thus creating a memory window and not a memory region.
+        */
+       mpt_entry->key         = cpu_to_be32(key_to_hw_index(mw->key));
+       mpt_entry->pd_flags    = cpu_to_be32(mw->pd);
+       if (mw->type == MLX4_MW_TYPE_2) {
+               mpt_entry->flags    |= cpu_to_be32(MLX4_MPT_FLAG_FREE);
+               mpt_entry->qpn       = cpu_to_be32(MLX4_MPT_QP_FLAG_BOUND_QP);
+               mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_EN_INV);
+       }
+
+       err = mlx4_SW2HW_MPT(dev, mailbox,
+                            key_to_hw_index(mw->key) &
+                            (dev->caps.num_mpts - 1));
+       if (err) {
+               mlx4_warn(dev, "SW2HW_MPT failed (%d)\n", err);
+               goto err_cmd;
+       }
+       mw->enabled = MLX4_MPT_EN_HW;
+
+       mlx4_free_cmd_mailbox(dev, mailbox);
+
+       return 0;
+
+err_cmd:
+       mlx4_free_cmd_mailbox(dev, mailbox);
+
+err_table:
+       mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
+       return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_mw_enable);
+
+void mlx4_mw_free(struct mlx4_dev *dev, struct mlx4_mw *mw)
+{
+       int err;
+
+       if (mw->enabled == MLX4_MPT_EN_HW) {
+               err = mlx4_HW2SW_MPT(dev, NULL,
+                                    key_to_hw_index(mw->key) &
+                                    (dev->caps.num_mpts - 1));
+               if (err)
+                       mlx4_warn(dev, "xxx HW2SW_MPT failed (%d)\n", err);
+
+               mw->enabled = MLX4_MPT_EN_SW;
+       }
+       if (mw->enabled)
+               mlx4_mpt_free_icm(dev, key_to_hw_index(mw->key));
+       mlx4_mpt_release(dev, key_to_hw_index(mw->key));
+}
+EXPORT_SYMBOL_GPL(mlx4_mw_free);
+
 int mlx4_init_mr_table(struct mlx4_dev *dev)
 {
        struct mlx4_priv *priv = mlx4_priv(dev);
@@ -831,7 +923,7 @@ int mlx4_fmr_alloc(struct mlx4_dev *dev, u32 pd, u32 access, int max_pages,
        return 0;
 
 err_free:
-       mlx4_mr_free(dev, &fmr->mr);
+       (void) mlx4_mr_free(dev, &fmr->mr);
        return err;
 }
 EXPORT_SYMBOL_GPL(mlx4_fmr_alloc);
@@ -882,17 +974,21 @@ void mlx4_fmr_unmap(struct mlx4_dev *dev, struct mlx4_fmr *fmr,
                       err);
                return;
        }
-       fmr->mr.enabled = MLX4_MR_EN_SW;
+       fmr->mr.enabled = MLX4_MPT_EN_SW;
 }
 EXPORT_SYMBOL_GPL(mlx4_fmr_unmap);
 
 int mlx4_fmr_free(struct mlx4_dev *dev, struct mlx4_fmr *fmr)
 {
+       int ret;
+
        if (fmr->maps)
                return -EBUSY;
 
-       mlx4_mr_free(dev, &fmr->mr);
-       fmr->mr.enabled = MLX4_MR_DISABLED;
+       ret = mlx4_mr_free(dev, &fmr->mr);
+       if (ret)
+               return ret;
+       fmr->mr.enabled = MLX4_MPT_DISABLED;
 
        return 0;
 }