Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit fc31e256 authored by Or Gerlitz's avatar Or Gerlitz Committed by David S. Miller
Browse files

net/mlx4_core: Add basic support for QP max-rate limiting



Add the low-level device commands and definitions used for QP max-rate limiting.

This is done through the following elements:

  - read rate-limit device caps in QUERY_DEV_CAP: number of different
    rates and the min/max rates in Kbs/Mbs/Gbs units

  - enhance the QP context struct to contain rate limit units and value

  - allow to do run time rate-limit setting to QPs through the
    update-qp firmware command

  - QP rate-limiting is disallowed for VFs

Signed-off-by: default avatarOr Gerlitz <ogerlitz@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 822b3b2e
Loading
Loading
Loading
Loading
+32 −1
Original line number Diff line number Diff line
@@ -144,7 +144,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
		[19] = "Performance optimized for limited rule configuration flow steering support",
		[20] = "Recoverable error events support",
		[21] = "Port Remap support",
		[22] = "QCN support"
		[22] = "QCN support",
		[23] = "QP rate limiting support"
	};
	int i;

@@ -697,6 +698,10 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_MAD_DEMUX_OFFSET		0xb0
#define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET	0xa8
#define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET	0xac
#define QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET	0xcc
#define QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET	0xd0
#define QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET	0xd2


	dev_cap->flags2 = 0;
	mailbox = mlx4_alloc_cmd_mailbox(dev);
@@ -904,6 +909,18 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
		 QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET);
	dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK;

	MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET);
	dev_cap->rl_caps.num_rates = size;
	if (dev_cap->rl_caps.num_rates) {
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT;
		MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MAX_OFFSET);
		dev_cap->rl_caps.max_val  = size & 0xfff;
		dev_cap->rl_caps.max_unit = size >> 14;
		MLX4_GET(size, outbox, QUERY_DEV_CAP_QP_RATE_LIMIT_MIN_OFFSET);
		dev_cap->rl_caps.min_val  = size & 0xfff;
		dev_cap->rl_caps.min_unit = size >> 14;
	}

	MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
	if (field32 & (1 << 16))
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
@@ -979,6 +996,15 @@ void mlx4_dev_cap_dump(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
		 dev_cap->dmfs_high_rate_qpn_base);
	mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n",
		 dev_cap->dmfs_high_rate_qpn_range);

	if (dev_cap->flags2 & MLX4_DEV_CAP_FLAG2_QP_RATE_LIMIT) {
		struct mlx4_rate_limit_caps *rl_caps = &dev_cap->rl_caps;

		mlx4_dbg(dev, "QP Rate-Limit: #rates %d, unit/val max %d/%d, min %d/%d\n",
			 rl_caps->num_rates, rl_caps->max_unit, rl_caps->max_val,
			 rl_caps->min_unit, rl_caps->min_val);
	}

	dump_dev_cap_flags(dev, dev_cap->flags);
	dump_dev_cap_flags2(dev, dev_cap->flags2);
}
@@ -1075,6 +1101,7 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
	u64	flags;
	int	err = 0;
	u8	field;
	u16	field16;
	u32	bmme_flags, field32;
	int	real_port;
	int	slave_port;
@@ -1158,6 +1185,10 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
	field &= 0xfe;
	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);

	/* turn off QP max-rate limiting for guests */
	field16 = 0;
	MLX4_PUT(outbox->buf, field16, QUERY_DEV_CAP_QP_RATE_LIMIT_NUM_OFFSET);

	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -127,6 +127,7 @@ struct mlx4_dev_cap {
	u32 max_counters;
	u32 dmfs_high_rate_qpn_base;
	u32 dmfs_high_rate_qpn_range;
	struct mlx4_rate_limit_caps rl_caps;
	struct mlx4_port_cap port_cap[MLX4_MAX_PORTS + 1];
};

+2 −0
Original line number Diff line number Diff line
@@ -489,6 +489,8 @@ static int mlx4_dev_cap(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
		dev->caps.dmfs_high_rate_qpn_range = MLX4_A0_STEERING_TABLE_SIZE;
	}

	dev->caps.rl_caps = dev_cap->rl_caps;

	dev->caps.reserved_qps_cnt[MLX4_QP_REGION_RSS_RAW_ETH] =
		dev->caps.dmfs_high_rate_qpn_range;

+5 −0
Original line number Diff line number Diff line
@@ -442,6 +442,11 @@ int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn,
			cmd->qp_context.param3 |= cpu_to_be32(MLX4_STRIP_VLAN);
	}

	if (attr & MLX4_UPDATE_QP_RATE_LIMIT) {
		qp_mask |= 1ULL << MLX4_UPD_QP_MASK_RATE_LIMIT;
		cmd->qp_context.rate_limit_params = cpu_to_be16((params->rate_unit << 14) | params->rate_val);
	}

	cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask);
	cmd->qp_mask = cpu_to_be64(qp_mask);

+5 −1
Original line number Diff line number Diff line
@@ -2947,8 +2947,12 @@ static int verify_qp_parameters(struct mlx4_dev *dev,
	qp_type	= (be32_to_cpu(qp_ctx->flags) >> 16) & 0xff;
	optpar	= be32_to_cpu(*(__be32 *) inbox->buf);

	if (slave != mlx4_master_func_num(dev))
	if (slave != mlx4_master_func_num(dev)) {
		qp_ctx->params2 &= ~MLX4_QP_BIT_FPP;
		/* setting QP rate-limit is disallowed for VFs */
		if (qp_ctx->rate_limit_params)
			return -EPERM;
	}

	switch (qp_type) {
	case MLX4_QP_ST_RC:
Loading