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

Merge branch 'txq_max_rate'



Or Gerlitz says:

====================
Add max rate TXQ attribute

Add the ability to set a max-rate limitation for TX queues.
The attribute name is maxrate and the units are Mbs, to make
it similar to the existing max-rate limitation knobs (ETS and
SRIOV ndo calls).

changes from V2:
  - added Documentation (thanks Florian and Tom)
  - rebased to latest net-next to comply with the swdev ndo removal
  - addressed more feedback from Dave on the comments style

changes from V1:
  - addressed feedback from Dave

changes from V0:
  - addressed feedback from Sergei

John Fastabend (1):
  net: Add max rate tx queue attribute
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b65885d2 c10e4fc6
Loading
Loading
Loading
Loading
+8 −0
Original line number Original line Diff line number Diff line
@@ -24,6 +24,14 @@ Description:
		Indicates the number of transmit timeout events seen by this
		Indicates the number of transmit timeout events seen by this
		network interface transmit queue.
		network interface transmit queue.


What:		/sys/class/<iface>/queues/tx-<queue>/tx_maxrate
Date:		March 2015
KernelVersion:	4.1
Contact:	netdev@vger.kernel.org
Description:
		A Mbps max-rate set for the queue, a value of zero means disabled,
		default is disabled.

What:		/sys/class/<iface>/queues/tx-<queue>/xps_cpus
What:		/sys/class/<iface>/queues/tx-<queue>/xps_cpus
Date:		November 2010
Date:		November 2010
KernelVersion:	2.6.38
KernelVersion:	2.6.38
+9 −0
Original line number Original line Diff line number Diff line
@@ -421,6 +421,15 @@ best CPUs to share a given queue are probably those that share the cache
with the CPU that processes transmit completions for that queue
with the CPU that processes transmit completions for that queue
(transmit interrupts).
(transmit interrupts).


Per TX Queue rate limitation:
=============================

These are rate-limitation mechanisms implemented by HW, where currently
a max-rate attribute is supported, by setting a Mbps value to

/sys/class/net/<dev>/queues/tx-<n>/tx_maxrate

A value of zero means disabled, and this is the default.


Further Information
Further Information
===================
===================
+29 −0
Original line number Original line Diff line number Diff line
@@ -2379,6 +2379,33 @@ static netdev_features_t mlx4_en_features_check(struct sk_buff *skb,
}
}
#endif
#endif


int mlx4_en_set_tx_maxrate(struct net_device *dev, int queue_index, u32 maxrate)
{
	struct mlx4_en_priv *priv = netdev_priv(dev);
	struct mlx4_en_tx_ring *tx_ring = priv->tx_ring[queue_index];
	struct mlx4_update_qp_params params;
	int err;

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

	/* rate provided to us in Mbs, check if it fits into 12 bits, if not use Gbs */
	if (maxrate >> 12) {
		params.rate_unit = MLX4_QP_RATE_LIMIT_GBS;
		params.rate_val  = maxrate / 1000;
	} else if (maxrate) {
		params.rate_unit = MLX4_QP_RATE_LIMIT_MBS;
		params.rate_val  = maxrate;
	} else { /* zero serves to revoke the QP rate-limitation */
		params.rate_unit = 0;
		params.rate_val  = 0;
	}

	err = mlx4_update_qp(priv->mdev->dev, tx_ring->qpn, MLX4_UPDATE_QP_RATE_LIMIT,
			     &params);
	return err;
}

static const struct net_device_ops mlx4_netdev_ops = {
static const struct net_device_ops mlx4_netdev_ops = {
	.ndo_open		= mlx4_en_open,
	.ndo_open		= mlx4_en_open,
	.ndo_stop		= mlx4_en_close,
	.ndo_stop		= mlx4_en_close,
@@ -2410,6 +2437,7 @@ static const struct net_device_ops mlx4_netdev_ops = {
	.ndo_del_vxlan_port	= mlx4_en_del_vxlan_port,
	.ndo_del_vxlan_port	= mlx4_en_del_vxlan_port,
	.ndo_features_check	= mlx4_en_features_check,
	.ndo_features_check	= mlx4_en_features_check,
#endif
#endif
	.ndo_set_tx_maxrate	= mlx4_en_set_tx_maxrate,
};
};


static const struct net_device_ops mlx4_netdev_ops_master = {
static const struct net_device_ops mlx4_netdev_ops_master = {
@@ -2444,6 +2472,7 @@ static const struct net_device_ops mlx4_netdev_ops_master = {
	.ndo_del_vxlan_port	= mlx4_en_del_vxlan_port,
	.ndo_del_vxlan_port	= mlx4_en_del_vxlan_port,
	.ndo_features_check	= mlx4_en_features_check,
	.ndo_features_check	= mlx4_en_features_check,
#endif
#endif
	.ndo_set_tx_maxrate	= mlx4_en_set_tx_maxrate,
};
};


struct mlx4_en_bond {
struct mlx4_en_bond {
+32 −1
Original line number Original line 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",
		[19] = "Performance optimized for limited rule configuration flow steering support",
		[20] = "Recoverable error events support",
		[20] = "Recoverable error events support",
		[21] = "Port Remap support",
		[21] = "Port Remap support",
		[22] = "QCN support"
		[22] = "QCN support",
		[23] = "QP rate limiting support"
	};
	};
	int i;
	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_MAD_DEMUX_OFFSET		0xb0
#define QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_BASE_OFFSET	0xa8
#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_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;
	dev_cap->flags2 = 0;
	mailbox = mlx4_alloc_cmd_mailbox(dev);
	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);
		 QUERY_DEV_CAP_DMFS_HIGH_RATE_QPN_RANGE_OFFSET);
	dev_cap->dmfs_high_rate_qpn_range &= MGM_QPN_MASK;
	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);
	MLX4_GET(field32, outbox, QUERY_DEV_CAP_EXT_2_FLAGS_OFFSET);
	if (field32 & (1 << 16))
	if (field32 & (1 << 16))
		dev_cap->flags2 |= MLX4_DEV_CAP_FLAG2_UPDATE_QP;
		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);
		 dev_cap->dmfs_high_rate_qpn_base);
	mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n",
	mlx4_dbg(dev, "DMFS high rate steer QPn range: %d\n",
		 dev_cap->dmfs_high_rate_qpn_range);
		 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_flags(dev, dev_cap->flags);
	dump_dev_cap_flags2(dev, dev_cap->flags2);
	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;
	u64	flags;
	int	err = 0;
	int	err = 0;
	u8	field;
	u8	field;
	u16	field16;
	u32	bmme_flags, field32;
	u32	bmme_flags, field32;
	int	real_port;
	int	real_port;
	int	slave_port;
	int	slave_port;
@@ -1158,6 +1185,10 @@ int mlx4_QUERY_DEV_CAP_wrapper(struct mlx4_dev *dev, int slave,
	field &= 0xfe;
	field &= 0xfe;
	MLX4_PUT(outbox->buf, field, QUERY_DEV_CAP_ECN_QCN_VER_OFFSET);
	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;
	return 0;
}
}


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


Loading