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

Commit f68a8ebd authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'mlx4-qcn'



Or Gerlitz says:

====================
Add QCN support to the DCB NL layer

This series from Shani Michaeli adds support for the IEEE QCN attribute
to the kernel DCB NL stack, and implementation in the mlx4 driver which
programs the firmware according to the admin directives.

changes from V0:

 - applied feedback from John and added his acked-by to patch #1
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 34de26d3 708b869b
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -1499,6 +1499,15 @@ static struct mlx4_cmd_info cmd_info[] = {
		.verify = NULL,
		.wrapper = mlx4_ACCESS_REG_wrapper,
	},
	{
		.opcode = MLX4_CMD_CONGESTION_CTRL_OPCODE,
		.has_inbox = false,
		.has_outbox = false,
		.out_is_imm = false,
		.encode_slave_id = false,
		.verify = NULL,
		.wrapper = mlx4_CMD_EPERM_wrapper,
	},
	/* Native multicast commands are not available for guests */
	{
		.opcode = MLX4_CMD_QP_ATTACH,
+218 −0
Original line number Diff line number Diff line
@@ -36,6 +36,49 @@

#include "mlx4_en.h"

/* Definitions for QCN
 */

struct mlx4_congestion_control_mb_prio_802_1_qau_params {
	__be32 modify_enable_high;
	__be32 modify_enable_low;
	__be32 reserved1;
	__be32 extended_enable;
	__be32 rppp_max_rps;
	__be32 rpg_time_reset;
	__be32 rpg_byte_reset;
	__be32 rpg_threshold;
	__be32 rpg_max_rate;
	__be32 rpg_ai_rate;
	__be32 rpg_hai_rate;
	__be32 rpg_gd;
	__be32 rpg_min_dec_fac;
	__be32 rpg_min_rate;
	__be32 max_time_rise;
	__be32 max_byte_rise;
	__be32 max_qdelta;
	__be32 min_qoffset;
	__be32 gd_coefficient;
	__be32 reserved2[5];
	__be32 cp_sample_base;
	__be32 reserved3[39];
};

struct mlx4_congestion_control_mb_prio_802_1_qau_statistics {
	__be64 rppp_rp_centiseconds;
	__be32 reserved1;
	__be32 ignored_cnm;
	__be32 rppp_created_rps;
	__be32 estimated_total_rate;
	__be32 max_active_rate_limiter_index;
	__be32 dropped_cnms_busy_fw;
	__be32 reserved2;
	__be32 cnms_handled_successfully;
	__be32 min_total_limiters_rate;
	__be32 max_total_limiters_rate;
	__be32 reserved3[4];
};

static int mlx4_en_dcbnl_ieee_getets(struct net_device *dev,
				   struct ieee_ets *ets)
{
@@ -242,6 +285,178 @@ static int mlx4_en_dcbnl_ieee_setmaxrate(struct net_device *dev,
	return 0;
}

#define RPG_ENABLE_BIT	31
#define CN_TAG_BIT	30

static int mlx4_en_dcbnl_ieee_getqcn(struct net_device *dev,
				     struct ieee_qcn *qcn)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;
	struct mlx4_cmd_mailbox *mailbox_out = NULL;
	u64 mailbox_in_dma = 0;
	u32 inmod = 0;
	int i, err;

	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
		return -EOPNOTSUPP;

	mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
	if (IS_ERR(mailbox_out))
		return -ENOMEM;
	hw_qcn =
	(struct mlx4_congestion_control_mb_prio_802_1_qau_params *)
	mailbox_out->buf;

	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
		inmod = priv->port | ((1 << i) << 8) |
			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);
		err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,
				   mailbox_out->dma,
				   inmod, MLX4_CONGESTION_CONTROL_GET_PARAMS,
				   MLX4_CMD_CONGESTION_CTRL_OPCODE,
				   MLX4_CMD_TIME_CLASS_C,
				   MLX4_CMD_NATIVE);
		if (err) {
			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
			return err;
		}

		qcn->rpg_enable[i] =
			be32_to_cpu(hw_qcn->extended_enable) >> RPG_ENABLE_BIT;
		qcn->rppp_max_rps[i] =
			be32_to_cpu(hw_qcn->rppp_max_rps);
		qcn->rpg_time_reset[i] =
			be32_to_cpu(hw_qcn->rpg_time_reset);
		qcn->rpg_byte_reset[i] =
			be32_to_cpu(hw_qcn->rpg_byte_reset);
		qcn->rpg_threshold[i] =
			be32_to_cpu(hw_qcn->rpg_threshold);
		qcn->rpg_max_rate[i] =
			be32_to_cpu(hw_qcn->rpg_max_rate);
		qcn->rpg_ai_rate[i] =
			be32_to_cpu(hw_qcn->rpg_ai_rate);
		qcn->rpg_hai_rate[i] =
			be32_to_cpu(hw_qcn->rpg_hai_rate);
		qcn->rpg_gd[i] =
			be32_to_cpu(hw_qcn->rpg_gd);
		qcn->rpg_min_dec_fac[i] =
			be32_to_cpu(hw_qcn->rpg_min_dec_fac);
		qcn->rpg_min_rate[i] =
			be32_to_cpu(hw_qcn->rpg_min_rate);
		qcn->cndd_state_machine[i] =
			priv->cndd_state[i];
	}
	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
	return 0;
}

static int mlx4_en_dcbnl_ieee_setqcn(struct net_device *dev,
				     struct ieee_qcn *qcn)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	struct mlx4_congestion_control_mb_prio_802_1_qau_params *hw_qcn;
	struct mlx4_cmd_mailbox *mailbox_in = NULL;
	u64 mailbox_in_dma = 0;
	u32 inmod = 0;
	int i, err;
#define MODIFY_ENABLE_HIGH_MASK 0xc0000000
#define MODIFY_ENABLE_LOW_MASK 0xffc00000

	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
		return -EOPNOTSUPP;

	mailbox_in = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
	if (IS_ERR(mailbox_in))
		return -ENOMEM;

	mailbox_in_dma = mailbox_in->dma;
	hw_qcn =
	(struct mlx4_congestion_control_mb_prio_802_1_qau_params *)mailbox_in->buf;
	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
		inmod = priv->port | ((1 << i) << 8) |
			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);

		/* Before updating QCN parameter,
		 * need to set it's modify enable bit to 1
		 */

		hw_qcn->modify_enable_high = cpu_to_be32(
						MODIFY_ENABLE_HIGH_MASK);
		hw_qcn->modify_enable_low = cpu_to_be32(MODIFY_ENABLE_LOW_MASK);

		hw_qcn->extended_enable = cpu_to_be32(qcn->rpg_enable[i] << RPG_ENABLE_BIT);
		hw_qcn->rppp_max_rps = cpu_to_be32(qcn->rppp_max_rps[i]);
		hw_qcn->rpg_time_reset = cpu_to_be32(qcn->rpg_time_reset[i]);
		hw_qcn->rpg_byte_reset = cpu_to_be32(qcn->rpg_byte_reset[i]);
		hw_qcn->rpg_threshold = cpu_to_be32(qcn->rpg_threshold[i]);
		hw_qcn->rpg_max_rate = cpu_to_be32(qcn->rpg_max_rate[i]);
		hw_qcn->rpg_ai_rate = cpu_to_be32(qcn->rpg_ai_rate[i]);
		hw_qcn->rpg_hai_rate = cpu_to_be32(qcn->rpg_hai_rate[i]);
		hw_qcn->rpg_gd = cpu_to_be32(qcn->rpg_gd[i]);
		hw_qcn->rpg_min_dec_fac = cpu_to_be32(qcn->rpg_min_dec_fac[i]);
		hw_qcn->rpg_min_rate = cpu_to_be32(qcn->rpg_min_rate[i]);
		priv->cndd_state[i] = qcn->cndd_state_machine[i];
		if (qcn->cndd_state_machine[i] == DCB_CNDD_INTERIOR_READY)
			hw_qcn->extended_enable |= cpu_to_be32(1 << CN_TAG_BIT);

		err = mlx4_cmd(priv->mdev->dev, mailbox_in_dma, inmod,
			       MLX4_CONGESTION_CONTROL_SET_PARAMS,
			       MLX4_CMD_CONGESTION_CTRL_OPCODE,
			       MLX4_CMD_TIME_CLASS_C,
			       MLX4_CMD_NATIVE);
		if (err) {
			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);
			return err;
		}
	}
	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_in);
	return 0;
}

static int mlx4_en_dcbnl_ieee_getqcnstats(struct net_device *dev,
					  struct ieee_qcn_stats *qcn_stats)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *hw_qcn_stats;
	struct mlx4_cmd_mailbox *mailbox_out = NULL;
	u64 mailbox_in_dma = 0;
	u32 inmod = 0;
	int i, err;

	if (!(priv->mdev->dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_QCN))
		return -EOPNOTSUPP;

	mailbox_out = mlx4_alloc_cmd_mailbox(priv->mdev->dev);
	if (IS_ERR(mailbox_out))
		return -ENOMEM;

	hw_qcn_stats =
	(struct mlx4_congestion_control_mb_prio_802_1_qau_statistics *)
	mailbox_out->buf;

	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
		inmod = priv->port | ((1 << i) << 8) |
			 (MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT << 16);
		err = mlx4_cmd_box(priv->mdev->dev, mailbox_in_dma,
				   mailbox_out->dma, inmod,
				   MLX4_CONGESTION_CONTROL_GET_STATISTICS,
				   MLX4_CMD_CONGESTION_CTRL_OPCODE,
				   MLX4_CMD_TIME_CLASS_C,
				   MLX4_CMD_NATIVE);
		if (err) {
			mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
			return err;
		}
		qcn_stats->rppp_rp_centiseconds[i] =
			be64_to_cpu(hw_qcn_stats->rppp_rp_centiseconds);
		qcn_stats->rppp_created_rps[i] =
			be32_to_cpu(hw_qcn_stats->rppp_created_rps);
	}
	mlx4_free_cmd_mailbox(priv->mdev->dev, mailbox_out);
	return 0;
}

const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = {
	.ieee_getets	= mlx4_en_dcbnl_ieee_getets,
	.ieee_setets	= mlx4_en_dcbnl_ieee_setets,
@@ -252,6 +467,9 @@ const struct dcbnl_rtnl_ops mlx4_en_dcbnl_ops = {

	.getdcbx	= mlx4_en_dcbnl_getdcbx,
	.setdcbx	= mlx4_en_dcbnl_setdcbx,
	.ieee_getqcn	= mlx4_en_dcbnl_ieee_getqcn,
	.ieee_setqcn	= mlx4_en_dcbnl_ieee_setqcn,
	.ieee_getqcnstats = mlx4_en_dcbnl_ieee_getqcnstats,
};

const struct dcbnl_rtnl_ops mlx4_en_dcbnl_pfc_ops = {
+11 −2
Original line number Diff line number Diff line
@@ -143,7 +143,8 @@ static void dump_dev_cap_flags2(struct mlx4_dev *dev, u64 flags)
		[18] = "More than 80 VFs support",
		[19] = "Performance optimized for limited rule configuration flow steering support",
		[20] = "Recoverable error events support",
		[21] = "Port Remap support"
		[21] = "Port Remap support",
		[22] = "QCN support"
	};
	int i;

@@ -675,7 +676,7 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
#define QUERY_DEV_CAP_FLOW_STEERING_RANGE_EN_OFFSET	0x76
#define QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET	0x77
#define QUERY_DEV_CAP_CQ_EQ_CACHE_LINE_STRIDE	0x7a
#define QUERY_DEV_CAP_ETH_PROT_CTRL_OFFSET	0x7a
#define QUERY_DEV_CAP_ECN_QCN_VER_OFFSET	0x7b
#define QUERY_DEV_CAP_RDMARC_ENTRY_SZ_OFFSET	0x80
#define QUERY_DEV_CAP_QPC_ENTRY_SZ_OFFSET	0x82
#define QUERY_DEV_CAP_AUX_ENTRY_SZ_OFFSET	0x84
@@ -777,6 +778,9 @@ int mlx4_QUERY_DEV_CAP(struct mlx4_dev *dev, struct mlx4_dev_cap *dev_cap)
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_DMFS_IPOIB;
	MLX4_GET(field, outbox, QUERY_DEV_CAP_FLOW_STEERING_MAX_QP_OFFSET);
	dev_cap->fs_max_num_qp_per_entry = field;
	MLX4_GET(field, outbox, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
	if (field & 0x1)
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_QCN;
	MLX4_GET(stat_rate, outbox, QUERY_DEV_CAP_RATE_SUPPORT_OFFSET);
	dev_cap->stat_rate_support = stat_rate;
	MLX4_GET(field, outbox, QUERY_DEV_CAP_CQ_TS_SUPPORT_OFFSET);
@@ -1149,6 +1153,11 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
		     DEV_CAP_EXT_2_FLAG_FSM);
	MLX4_PUT(outbox->buf, field32, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);

	/* turn off QCN for guests */
	MLX4_GET(field, outbox->buf, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
	field &= 0xfe;
	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);

	return 0;
}

+1 −0
Original line number Diff line number Diff line
@@ -608,6 +608,7 @@ struct mlx4_en_priv {
#ifdef CONFIG_MLX4_EN_DCB
	struct ieee_ets ets;
	u16 maxrate[IEEE_8021QAZ_MAX_TCS];
	enum dcbnl_cndd_states cndd_state[IEEE_8021QAZ_MAX_TCS];
#endif
#ifdef CONFIG_RFS_ACCEL
	spinlock_t filters_lock;
+13 −0
Original line number Diff line number Diff line
@@ -163,6 +163,9 @@ enum {
	MLX4_QP_FLOW_STEERING_ATTACH = 0x65,
	MLX4_QP_FLOW_STEERING_DETACH = 0x66,
	MLX4_FLOW_STEERING_IB_UC_QP_RANGE = 0x64,

	/* Update and read QCN parameters */
	MLX4_CMD_CONGESTION_CTRL_OPCODE = 0x68,
};

enum {
@@ -233,6 +236,16 @@ struct mlx4_config_dev_params {
	u8	rx_csum_flags_port_2;
};

enum mlx4_en_congestion_control_algorithm {
	MLX4_CTRL_ALGO_802_1_QAU_REACTION_POINT = 0,
};

enum mlx4_en_congestion_control_opmod {
	MLX4_CONGESTION_CONTROL_GET_PARAMS,
	MLX4_CONGESTION_CONTROL_GET_STATISTICS,
	MLX4_CONGESTION_CONTROL_SET_PARAMS = 4,
};

struct mlx4_dev;

struct mlx4_cmd_mailbox {
Loading