mlx4_core: Disable memory windows for virtual functions
authorShani Michaeli <shanim@mellanox.com>
Wed, 6 Feb 2013 16:19:10 +0000 (16:19 +0000)
committerRoland Dreier <roland@purestorage.com>
Mon, 25 Feb 2013 18:44:31 +0000 (10:44 -0800)
Do not enable memory windows allocation for virtual functions.

In addition, add a few safety checks, such as:

* Verifying the PD of a new MPT matches the VF.
* Making sure binding memory window isn't enabled for FMRs, and
  that new memory windows are not FMR themselves.

Signed-off-by: Haggai Eran <haggaie@mellanox.com>
Signed-off-by: Shani Michaeli <shanim@mellanox.com>
Signed-off-by: Or Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: Roland Dreier <roland@purestorage.com>
drivers/net/ethernet/mellanox/mlx4/fw.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/mr.c
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c

index 8b3d0512a46bd90f5d8678f127069c17f04460a2..a389612f8a4a97627a6a77aff608d9afb7e07212 100644 (file)
@@ -757,15 +757,19 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        u64     flags;
        int     err = 0;
        u8      field;
+       u32     bmme_flags;
 
        err = mlx4_cmd_box(dev, 0, outbox->dma, 0, 0, MLX4_CMD_QUERY_DEV_CAP,
                           MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE);
        if (err)
                return err;
 
-       /* add port mng change event capability unconditionally to slaves */
+       /* add port mng change event capability and disable mw type 1
+        * unconditionally to slaves
+        */
        MLX4_GET(flags, outbox->buf, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
        flags |= MLX4_DEV_CAP_FLAG_PORT_MNG_CHG_EV;
+       flags &= ~MLX4_DEV_CAP_FLAG_MEM_WINDOW;
        MLX4_PUT(outbox->buf, flags, QUERY_DEV_CAP_EXT_FLAGS_OFFSET);
 
        /* For guests, report Blueflame disabled */
@@ -773,6 +777,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
        field &= 0x7f;
        MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_BF_OFFSET);
 
+       /* For guests, disable mw type 2 */
+       MLX4_GET(bmme_flags, outbox, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
+       bmme_flags &= ~MLX4_BMME_FLAG_TYPE_2_WIN;
+       MLX4_PUT(outbox->buf, bmme_flags, QUERY_DEV_CAP_BMME_FLAGS_OFFSET);
+
        return 0;
 }
 
index 5075236a140dd7555ad98afa1319ed1c2fbc495e..539212b1c8dcb23fbf1c03ae863b207077c0955d 100644 (file)
@@ -268,6 +268,22 @@ struct mlx4_icm_table {
        struct mlx4_icm       **icm;
 };
 
+#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_QP_FLAG_BOUND_QP   (1 << 7)
+
+#define MLX4_MPT_STATUS_SW             0xF0
+#define MLX4_MPT_STATUS_HW             0x00
+
 /*
  * Must be packed because mtt_seg is 64 bits but only aligned to 32 bits.
  */
index 06b16e4ace8056177f2cee726bb6d9d64b0b20dc..5e785bdcc6948b016a4527be2bd9f5d6e81ba34c 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;
index 2287dfda621241134a2b990ac1a44b20f7f7183e..9185e2eef8fa96bbee8992586450d34b24054efb 100644 (file)
@@ -1796,6 +1796,26 @@ static int mr_get_mtt_size(struct mlx4_mpt_entry *mpt)
        return be32_to_cpu(mpt->mtt_sz);
 }
 
+static u32 mr_get_pd(struct mlx4_mpt_entry *mpt)
+{
+       return be32_to_cpu(mpt->pd_flags) & 0x00ffffff;
+}
+
+static int mr_is_fmr(struct mlx4_mpt_entry *mpt)
+{
+       return be32_to_cpu(mpt->pd_flags) & MLX4_MPT_PD_FLAG_FAST_REG;
+}
+
+static int mr_is_bind_enabled(struct mlx4_mpt_entry *mpt)
+{
+       return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_BIND_ENABLE;
+}
+
+static int mr_is_region(struct mlx4_mpt_entry *mpt)
+{
+       return be32_to_cpu(mpt->flags) & MLX4_MPT_FLAG_REGION;
+}
+
 static int qp_get_mtt_addr(struct mlx4_qp_context *qpc)
 {
        return be32_to_cpu(qpc->mtt_base_addr_l) & 0xfffffff8;
@@ -1856,12 +1876,41 @@ int mlx4_SW2HW_MPT_wrapper(struct mlx4_dev *dev, int slave,
        int mtt_base = mr_get_mtt_addr(inbox->buf) / dev->caps.mtt_entry_sz;
        int phys;
        int id;
+       u32 pd;
+       int pd_slave;
 
        id = index & mpt_mask(dev);
        err = mr_res_start_move_to(dev, slave, id, RES_MPT_HW, &mpt);
        if (err)
                return err;
 
+       /* Disable memory windows for VFs. */
+       if (!mr_is_region(inbox->buf)) {
+               err = -EPERM;
+               goto ex_abort;
+       }
+
+       /* Make sure that the PD bits related to the slave id are zeros. */
+       pd = mr_get_pd(inbox->buf);
+       pd_slave = (pd >> 17) & 0x7f;
+       if (pd_slave != 0 && pd_slave != slave) {
+               err = -EPERM;
+               goto ex_abort;
+       }
+
+       if (mr_is_fmr(inbox->buf)) {
+               /* FMR and Bind Enable are forbidden in slave devices. */
+               if (mr_is_bind_enabled(inbox->buf)) {
+                       err = -EPERM;
+                       goto ex_abort;
+               }
+               /* FMR and Memory Windows are also forbidden. */
+               if (!mr_is_region(inbox->buf)) {
+                       err = -EPERM;
+                       goto ex_abort;
+               }
+       }
+
        phys = mr_phys_mpt(inbox->buf);
        if (!phys) {
                err = get_res(dev, slave, mtt_base, RES_MTT, &mtt);