net/mlx5: Set ODP SRQ support in firmware
authorMoni Shoua <monis@mellanox.com>
Tue, 22 Jan 2019 06:48:51 +0000 (08:48 +0200)
committerLeon Romanovsky <leonro@mellanox.com>
Sun, 3 Feb 2019 10:49:59 +0000 (12:49 +0200)
To avoid compatibility issue with older kernels the firmware doesn't
allow SRQ to work with ODP unless kernel asks for it.

Signed-off-by: Moni Shoua <monis@mellanox.com>
Reviewed-by: Majd Dibbiny <majd@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
drivers/net/ethernet/mellanox/mlx5/core/main.c
include/linux/mlx5/device.h
include/linux/mlx5/mlx5_ifc.h

index 085e113..e38aa20 100644 (file)
@@ -459,6 +459,53 @@ static int handle_hca_cap_atomic(struct mlx5_core_dev *dev)
        return err;
 }
 
+static int handle_hca_cap_odp(struct mlx5_core_dev *dev)
+{
+       void *set_ctx;
+       void *set_hca_cap;
+       int set_sz = MLX5_ST_SZ_BYTES(set_hca_cap_in);
+       int err;
+
+       if (!MLX5_CAP_GEN(dev, pg))
+               return 0;
+
+       err = mlx5_core_get_caps(dev, MLX5_CAP_ODP);
+       if (err)
+               return err;
+
+       /**
+        * If all bits are cleared we shouldn't try to set it
+        * or we might fail while trying to access a reserved bit.
+        */
+       if (!(MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive) ||
+             MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive) ||
+             MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive)))
+               return 0;
+
+       set_ctx = kzalloc(set_sz, GFP_KERNEL);
+       if (!set_ctx)
+               return -ENOMEM;
+
+       set_hca_cap = MLX5_ADDR_OF(set_hca_cap_in, set_ctx, capability);
+       memcpy(set_hca_cap, dev->caps.hca_cur[MLX5_CAP_ODP],
+              MLX5_ST_SZ_BYTES(odp_cap));
+
+       /* set ODP SRQ support for RC/UD and XRC transports */
+       MLX5_SET(odp_cap, set_hca_cap, ud_odp_caps.srq_receive,
+                (MLX5_CAP_ODP_MAX(dev, ud_odp_caps.srq_receive)));
+
+       MLX5_SET(odp_cap, set_hca_cap, rc_odp_caps.srq_receive,
+                (MLX5_CAP_ODP_MAX(dev, rc_odp_caps.srq_receive)));
+
+       MLX5_SET(odp_cap, set_hca_cap, xrc_odp_caps.srq_receive,
+                (MLX5_CAP_ODP_MAX(dev, xrc_odp_caps.srq_receive)));
+
+       err = set_caps(dev, set_ctx, set_sz, MLX5_SET_HCA_CAP_OP_MOD_ODP);
+
+       kfree(set_ctx);
+       return err;
+}
+
 static int handle_hca_cap(struct mlx5_core_dev *dev)
 {
        void *set_ctx = NULL;
@@ -931,6 +978,12 @@ static int mlx5_load_one(struct mlx5_core_dev *dev, struct mlx5_priv *priv,
                goto reclaim_boot_pages;
        }
 
+       err = handle_hca_cap_odp(dev);
+       if (err) {
+               dev_err(&pdev->dev, "handle_hca_cap_odp failed\n");
+               goto reclaim_boot_pages;
+       }
+
        err = mlx5_satisfy_startup_pages(dev, 0);
        if (err) {
                dev_err(&pdev->dev, "failed to allocate init pages\n");
index 8c4a820..0845a22 100644 (file)
@@ -1201,6 +1201,9 @@ enum mlx5_qcam_feature_groups {
 #define MLX5_CAP_ODP(mdev, cap)\
        MLX5_GET(odp_cap, mdev->caps.hca_cur[MLX5_CAP_ODP], cap)
 
+#define MLX5_CAP_ODP_MAX(mdev, cap)\
+       MLX5_GET(odp_cap, mdev->caps.hca_max[MLX5_CAP_ODP], cap)
+
 #define MLX5_CAP_VECTOR_CALC(mdev, cap) \
        MLX5_GET(vector_calc_cap, \
                 mdev->caps.hca_cur[MLX5_CAP_VECTOR_CALC], cap)
index 5407db8..c5c6793 100644 (file)
@@ -72,6 +72,7 @@ enum {
 
 enum {
        MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE        = 0x0,
+       MLX5_SET_HCA_CAP_OP_MOD_ODP                   = 0x2,
        MLX5_SET_HCA_CAP_OP_MOD_ATOMIC                = 0x3,
 };