IB/mlx5: Add additional checks before processing MADs
authorMaor Gottlieb <maorg@mellanox.com>
Wed, 18 Jan 2017 12:10:33 +0000 (14:10 +0200)
committerDoug Ledford <dledford@redhat.com>
Tue, 14 Feb 2017 15:14:25 +0000 (10:14 -0500)
Check the has_smi bit in vport context and class version of MADs
before allowing MADs processing to take place.
MAD_IFC SMI commands can be executed only if smi bit is set.

Fixes: e126ba97dba9 ('mlx5: Add driver for Mellanox Connect-IB adapters')
Signed-off-by: Maor Gottlieb <maorg@mellanox.com>
Signed-off-by: Parvi Kaustubhi <parvik@mellanox.com>
Reviewed-by: Eli Cohen <eli@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Doug Ledford <dledford@redhat.com>
drivers/infiniband/hw/mlx5/mad.c
drivers/infiniband/hw/mlx5/main.c
include/linux/mlx5/driver.h

index 39e58489dcc2c22e15388a1e6dc4027a25cd0214..af962e7fdc3a10e9db4351e063596f59e444da57 100644 (file)
@@ -42,12 +42,24 @@ enum {
        MLX5_IB_VENDOR_CLASS2 = 0xa
 };
 
+static bool can_do_mad_ifc(struct mlx5_ib_dev *dev, u8 port_num,
+                          struct ib_mad *in_mad)
+{
+       if (in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_LID_ROUTED &&
+           in_mad->mad_hdr.mgmt_class != IB_MGMT_CLASS_SUBN_DIRECTED_ROUTE)
+               return true;
+       return dev->mdev->port_caps[port_num - 1].has_smi;
+}
+
 int mlx5_MAD_IFC(struct mlx5_ib_dev *dev, int ignore_mkey, int ignore_bkey,
                 u8 port, const struct ib_wc *in_wc, const struct ib_grh *in_grh,
                 const void *in_mad, void *response_mad)
 {
        u8 op_modifier = 0;
 
+       if (!can_do_mad_ifc(dev, port, (struct ib_mad *)in_mad))
+               return -EPERM;
+
        /* Key check traps can't be generated unless we have in_wc to
         * tell us where to send the trap.
         */
index 0187f1d7234a71ae76f62c69f19cad530b77fdcd..1dea4073d83f6567f01ee607efe303c6d90c3f19 100644 (file)
@@ -2533,6 +2533,35 @@ static void mlx5_ib_event(struct mlx5_core_dev *dev, void *context,
                ibdev->ib_active = false;
 }
 
+static int set_has_smi_cap(struct mlx5_ib_dev *dev)
+{
+       struct mlx5_hca_vport_context vport_ctx;
+       int err;
+       int port;
+
+       for (port = 1; port <= MLX5_CAP_GEN(dev->mdev, num_ports); port++) {
+               dev->mdev->port_caps[port - 1].has_smi = false;
+               if (MLX5_CAP_GEN(dev->mdev, port_type) ==
+                   MLX5_CAP_PORT_TYPE_IB) {
+                       if (MLX5_CAP_GEN(dev->mdev, ib_virt)) {
+                               err = mlx5_query_hca_vport_context(dev->mdev, 0,
+                                                                  port, 0,
+                                                                  &vport_ctx);
+                               if (err) {
+                                       mlx5_ib_err(dev, "query_hca_vport_context for port=%d failed %d\n",
+                                                   port, err);
+                                       return err;
+                               }
+                               dev->mdev->port_caps[port - 1].has_smi =
+                                       vport_ctx.has_smi;
+                       } else {
+                               dev->mdev->port_caps[port - 1].has_smi = true;
+                       }
+               }
+       }
+       return 0;
+}
+
 static void get_ext_port_caps(struct mlx5_ib_dev *dev)
 {
        int port;
@@ -2557,6 +2586,10 @@ static int get_port_caps(struct mlx5_ib_dev *dev)
        if (!dprops)
                goto out;
 
+       err = set_has_smi_cap(dev);
+       if (err)
+               goto out;
+
        err = mlx5_ib_query_device(&dev->ib_dev, dprops, &uhw);
        if (err) {
                mlx5_ib_warn(dev, "query_device failed %d\n", err);
index 3a309f6a4a15ad919deeb059346535d4f962ef08..b8d69aeb178417385414eff2bd01d15a0422e4a4 100644 (file)
@@ -289,6 +289,7 @@ struct mlx5_port_caps {
        int     gid_table_len;
        int     pkey_table_len;
        u8      ext_port_cap;
+       bool    has_smi;
 };
 
 struct mlx5_cmd_mailbox {