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

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

Merge branch 'hns3-add-some-new-features-and-fix-some-bugs'



Peng Li says:

====================
hns3: add some new features and fix some bugs

This patchset adds 3 ethtool features: get_channels,
get_coalesce and get_coalesce, and fix some bugs.

[patch 1/11] adds ethtool_ops.get_channels (ethtool -l) support
for VF.

[patch 2/11] removes TSO config command from VF driver,
as only main PF can config TSO MSS length according to
hardware.

[patch 3/11 - 4/11] add ethtool_ops {get|set}_coalesce
(ethtool -c/-C) support to PF.
[patch 5/11 - 9/11] fix some bugs related to {get|set}_coalesce.

[patch 10/11 - 11/11] fix the features handling in
hns3_nic_set_features(). Local variable "changed" was defined
to indicates features changed, but was used only for feature
NETIF_F_HW_VLAN_CTAG_RX. Add checking to improve the reliability.

---
Change log:
V1 -> V2:
1, Rewrite the cover letter requested by David Miller.
====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 19d28fbd bd368416
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -133,11 +133,16 @@ struct hnae3_vector_info {
#define HNAE3_RING_TYPE_B 0
#define HNAE3_RING_TYPE_TX 0
#define HNAE3_RING_TYPE_RX 1
#define HNAE3_RING_GL_IDX_S 0
#define HNAE3_RING_GL_IDX_M GENMASK(1, 0)
#define HNAE3_RING_GL_RX 0
#define HNAE3_RING_GL_TX 1

struct hnae3_ring_chain_node {
	struct hnae3_ring_chain_node *next;
	u32 tqp_index;
	u32 flag;
	u32 int_gl_idx;
};

#define HNAE3_IS_TX_RING(node) \
@@ -448,6 +453,8 @@ struct hnae3_knic_private_info {
	u16 num_tqps;		  /* total number of TQPs in this handle */
	struct hnae3_queue **tqp;  /* array base of all TQPs in this instance */
	const struct hnae3_dcb_ops *dcb_ops;

	u16 int_rl_setting;
};

struct hnae3_roce_private_info {
+93 −55
Original line number Diff line number Diff line
@@ -158,43 +158,68 @@ static void hns3_vector_disable(struct hns3_enet_tqp_vector *tqp_vector)
	napi_disable(&tqp_vector->napi);
}

static void hns3_set_vector_coalesc_gl(struct hns3_enet_tqp_vector *tqp_vector,
				       u32 gl_value)
{
	/* this defines the configuration for GL (Interrupt Gap Limiter)
	 * GL defines inter interrupt gap.
	 * GL and RL(Rate Limiter) are 2 ways to acheive interrupt coalescing
	 */
	writel(gl_value, tqp_vector->mask_addr + HNS3_VECTOR_GL0_OFFSET);
	writel(gl_value, tqp_vector->mask_addr + HNS3_VECTOR_GL1_OFFSET);
	writel(gl_value, tqp_vector->mask_addr + HNS3_VECTOR_GL2_OFFSET);
}

static void hns3_set_vector_coalesc_rl(struct hns3_enet_tqp_vector *tqp_vector,
void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
				 u32 rl_value)
{
	u32 rl_reg = hns3_rl_usec_to_reg(rl_value);

	/* this defines the configuration for RL (Interrupt Rate Limiter).
	 * Rl defines rate of interrupts i.e. number of interrupts-per-second
	 * GL and RL(Rate Limiter) are 2 ways to acheive interrupt coalescing
	 */
	writel(rl_value, tqp_vector->mask_addr + HNS3_VECTOR_RL_OFFSET);

	if (rl_reg > 0 && !tqp_vector->tx_group.gl_adapt_enable &&
	    !tqp_vector->rx_group.gl_adapt_enable)
		/* According to the hardware, the range of rl_reg is
		 * 0-59 and the unit is 4.
		 */
		rl_reg |=  HNS3_INT_RL_ENABLE_MASK;

	writel(rl_reg, tqp_vector->mask_addr + HNS3_VECTOR_RL_OFFSET);
}

void hns3_set_vector_coalesce_rx_gl(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 gl_value)
{
	u32 rx_gl_reg = hns3_gl_usec_to_reg(gl_value);

	writel(rx_gl_reg, tqp_vector->mask_addr + HNS3_VECTOR_GL0_OFFSET);
}

void hns3_set_vector_coalesce_tx_gl(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 gl_value)
{
	u32 tx_gl_reg = hns3_gl_usec_to_reg(gl_value);

	writel(tx_gl_reg, tqp_vector->mask_addr + HNS3_VECTOR_GL1_OFFSET);
}

static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector)
static void hns3_vector_gl_rl_init(struct hns3_enet_tqp_vector *tqp_vector,
				   struct hns3_nic_priv *priv)
{
	struct hnae3_handle *h = priv->ae_handle;

	/* initialize the configuration for interrupt coalescing.
	 * 1. GL (Interrupt Gap Limiter)
	 * 2. RL (Interrupt Rate Limiter)
	 */

	/* Default :enable interrupt coalesce */
	tqp_vector->rx_group.int_gl = HNS3_INT_GL_50K;
	/* Default: enable interrupt coalescing self-adaptive and GL */
	tqp_vector->tx_group.gl_adapt_enable = 1;
	tqp_vector->rx_group.gl_adapt_enable = 1;

	tqp_vector->tx_group.int_gl = HNS3_INT_GL_50K;
	hns3_set_vector_coalesc_gl(tqp_vector, HNS3_INT_GL_50K);
	/* for now we are disabling Interrupt RL - we
	 * will re-enable later
	 */
	hns3_set_vector_coalesc_rl(tqp_vector, 0);
	tqp_vector->rx_group.int_gl = HNS3_INT_GL_50K;

	hns3_set_vector_coalesce_tx_gl(tqp_vector,
				       tqp_vector->tx_group.int_gl);
	hns3_set_vector_coalesce_rx_gl(tqp_vector,
				       tqp_vector->rx_group.int_gl);

	/* Default: disable RL */
	h->kinfo.int_rl_setting = 0;
	hns3_set_vector_coalesce_rl(tqp_vector, h->kinfo.int_rl_setting);

	tqp_vector->rx_group.flow_level = HNS3_FLOW_LOW;
	tqp_vector->tx_group.flow_level = HNS3_FLOW_LOW;
}
@@ -1093,11 +1118,12 @@ static int hns3_nic_net_set_mac_address(struct net_device *netdev, void *p)
static int hns3_nic_set_features(struct net_device *netdev,
				 netdev_features_t features)
{
	netdev_features_t changed = netdev->features ^ features;
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	struct hnae3_handle *h = priv->ae_handle;
	netdev_features_t changed;
	int ret;

	if (changed & (NETIF_F_TSO | NETIF_F_TSO6)) {
		if (features & (NETIF_F_TSO | NETIF_F_TSO6)) {
			priv->ops.fill_desc = hns3_fill_desc_tso;
			priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tso;
@@ -1105,14 +1131,18 @@ static int hns3_nic_set_features(struct net_device *netdev,
			priv->ops.fill_desc = hns3_fill_desc;
			priv->ops.maybe_stop_tx = hns3_nic_maybe_stop_tx;
		}
	}

	if ((changed & NETIF_F_HW_VLAN_CTAG_FILTER) &&
	    h->ae_algo->ops->enable_vlan_filter) {
		if (features & NETIF_F_HW_VLAN_CTAG_FILTER)
			h->ae_algo->ops->enable_vlan_filter(h, true);
		else
			h->ae_algo->ops->enable_vlan_filter(h, false);
	}

	changed = netdev->features ^ features;
	if (changed & NETIF_F_HW_VLAN_CTAG_RX) {
	if ((changed & NETIF_F_HW_VLAN_CTAG_RX) &&
	    h->ae_algo->ops->enable_hw_strip_rxvtag) {
		if (features & NETIF_F_HW_VLAN_CTAG_RX)
			ret = h->ae_algo->ops->enable_hw_strip_rxvtag(h, true);
		else
@@ -2422,25 +2452,22 @@ static bool hns3_get_new_int_gl(struct hns3_enet_ring_group *ring_group)

static void hns3_update_new_int_gl(struct hns3_enet_tqp_vector *tqp_vector)
{
	u16 rx_int_gl, tx_int_gl;
	bool rx, tx;

	rx = hns3_get_new_int_gl(&tqp_vector->rx_group);
	tx = hns3_get_new_int_gl(&tqp_vector->tx_group);
	rx_int_gl = tqp_vector->rx_group.int_gl;
	tx_int_gl = tqp_vector->tx_group.int_gl;
	if (rx && tx) {
		if (rx_int_gl > tx_int_gl) {
			tqp_vector->tx_group.int_gl = rx_int_gl;
			tqp_vector->tx_group.flow_level =
				tqp_vector->rx_group.flow_level;
			hns3_set_vector_coalesc_gl(tqp_vector, rx_int_gl);
		} else {
			tqp_vector->rx_group.int_gl = tx_int_gl;
			tqp_vector->rx_group.flow_level =
				tqp_vector->tx_group.flow_level;
			hns3_set_vector_coalesc_gl(tqp_vector, tx_int_gl);
	struct hns3_enet_ring_group *rx_group = &tqp_vector->rx_group;
	struct hns3_enet_ring_group *tx_group = &tqp_vector->tx_group;
	bool rx_update, tx_update;

	if (rx_group->gl_adapt_enable) {
		rx_update = hns3_get_new_int_gl(rx_group);
		if (rx_update)
			hns3_set_vector_coalesce_rx_gl(tqp_vector,
						       rx_group->int_gl);
	}

	if (tx_group->gl_adapt_enable) {
		tx_update = hns3_get_new_int_gl(&tqp_vector->tx_group);
		if (tx_update)
			hns3_set_vector_coalesce_tx_gl(tqp_vector,
						       tx_group->int_gl);
	}
}

@@ -2501,6 +2528,8 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
		cur_chain->tqp_index = tx_ring->tqp->tqp_index;
		hnae_set_bit(cur_chain->flag, HNAE3_RING_TYPE_B,
			     HNAE3_RING_TYPE_TX);
		hnae_set_field(cur_chain->int_gl_idx, HNAE3_RING_GL_IDX_M,
			       HNAE3_RING_GL_IDX_S, HNAE3_RING_GL_TX);

		cur_chain->next = NULL;

@@ -2516,6 +2545,10 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
			chain->tqp_index = tx_ring->tqp->tqp_index;
			hnae_set_bit(chain->flag, HNAE3_RING_TYPE_B,
				     HNAE3_RING_TYPE_TX);
			hnae_set_field(chain->int_gl_idx,
				       HNAE3_RING_GL_IDX_M,
				       HNAE3_RING_GL_IDX_S,
				       HNAE3_RING_GL_TX);

			cur_chain = chain;
		}
@@ -2527,6 +2560,8 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
		cur_chain->tqp_index = rx_ring->tqp->tqp_index;
		hnae_set_bit(cur_chain->flag, HNAE3_RING_TYPE_B,
			     HNAE3_RING_TYPE_RX);
		hnae_set_field(cur_chain->int_gl_idx, HNAE3_RING_GL_IDX_M,
			       HNAE3_RING_GL_IDX_S, HNAE3_RING_GL_RX);

		rx_ring = rx_ring->next;
	}
@@ -2540,6 +2575,9 @@ static int hns3_get_vector_ring_chain(struct hns3_enet_tqp_vector *tqp_vector,
		chain->tqp_index = rx_ring->tqp->tqp_index;
		hnae_set_bit(chain->flag, HNAE3_RING_TYPE_B,
			     HNAE3_RING_TYPE_RX);
		hnae_set_field(chain->int_gl_idx, HNAE3_RING_GL_IDX_M,
			       HNAE3_RING_GL_IDX_S, HNAE3_RING_GL_RX);

		cur_chain = chain;

		rx_ring = rx_ring->next;
@@ -2628,7 +2666,7 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)
		tqp_vector->rx_group.total_packets = 0;
		tqp_vector->tx_group.total_bytes = 0;
		tqp_vector->tx_group.total_packets = 0;
		hns3_vector_gl_rl_init(tqp_vector);
		hns3_vector_gl_rl_init(tqp_vector, priv);
		tqp_vector->handle = h;

		ret = hns3_get_vector_ring_chain(tqp_vector,
+22 −4
Original line number Diff line number Diff line
@@ -451,10 +451,14 @@ enum hns3_link_mode_bits {
	HNS3_LM_COUNT = 15
};

#define HNS3_INT_GL_50K		0x000A
#define HNS3_INT_GL_20K		0x0019
#define HNS3_INT_GL_18K		0x001B
#define HNS3_INT_GL_8K		0x003E
#define HNS3_INT_GL_MAX			0x1FE0
#define HNS3_INT_GL_50K			0x0014
#define HNS3_INT_GL_20K			0x0032
#define HNS3_INT_GL_18K			0x0036
#define HNS3_INT_GL_8K			0x007C

#define HNS3_INT_RL_MAX			0x00EC
#define HNS3_INT_RL_ENABLE_MASK		0x40

struct hns3_enet_ring_group {
	/* array of pointers to rings */
@@ -464,6 +468,7 @@ struct hns3_enet_ring_group {
	u16 count;
	enum hns3_flow_level_range flow_level;
	u16 int_gl;
	u8 gl_adapt_enable;
};

struct hns3_enet_tqp_vector {
@@ -594,6 +599,12 @@ static inline void hns3_write_reg(void __iomem *base, u32 reg, u32 value)
#define hns3_get_handle(ndev) \
	(((struct hns3_nic_priv *)netdev_priv(ndev))->ae_handle)

#define hns3_gl_usec_to_reg(int_gl) (int_gl >> 1)
#define hns3_gl_round_down(int_gl) round_down(int_gl, 2)

#define hns3_rl_usec_to_reg(int_rl) (int_rl >> 2)
#define hns3_rl_round_down(int_rl) round_down(int_rl, 4)

void hns3_ethtool_set_ops(struct net_device *netdev);
int hns3_set_channels(struct net_device *netdev,
		      struct ethtool_channels *ch);
@@ -606,6 +617,13 @@ int hns3_clean_rx_ring(
		struct hns3_enet_ring *ring, int budget,
		void (*rx_fn)(struct hns3_enet_ring *, struct sk_buff *));

void hns3_set_vector_coalesce_rx_gl(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 gl_value);
void hns3_set_vector_coalesce_tx_gl(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 gl_value);
void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
				 u32 rl_value);

#ifdef CONFIG_HNS3_DCB
void hns3_dcbnl_setup(struct hnae3_handle *handle);
#else
+179 −0
Original line number Diff line number Diff line
@@ -887,6 +887,182 @@ static void hns3_get_channels(struct net_device *netdev,
		h->ae_algo->ops->get_channels(h, ch);
}

static int hns3_get_coalesce_per_queue(struct net_device *netdev, u32 queue,
				       struct ethtool_coalesce *cmd)
{
	struct hns3_enet_tqp_vector *tx_vector, *rx_vector;
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	struct hnae3_handle *h = priv->ae_handle;
	u16 queue_num = h->kinfo.num_tqps;

	if (queue >= queue_num) {
		netdev_err(netdev,
			   "Invalid queue value %d! Queue max id=%d\n",
			   queue, queue_num - 1);
		return -EINVAL;
	}

	tx_vector = priv->ring_data[queue].ring->tqp_vector;
	rx_vector = priv->ring_data[queue_num + queue].ring->tqp_vector;

	cmd->use_adaptive_tx_coalesce = tx_vector->tx_group.gl_adapt_enable;
	cmd->use_adaptive_rx_coalesce = rx_vector->rx_group.gl_adapt_enable;

	cmd->tx_coalesce_usecs = tx_vector->tx_group.int_gl;
	cmd->rx_coalesce_usecs = rx_vector->rx_group.int_gl;

	cmd->tx_coalesce_usecs_high = h->kinfo.int_rl_setting;
	cmd->rx_coalesce_usecs_high = h->kinfo.int_rl_setting;

	return 0;
}

static int hns3_get_coalesce(struct net_device *netdev,
			     struct ethtool_coalesce *cmd)
{
	return hns3_get_coalesce_per_queue(netdev, 0, cmd);
}

static int hns3_check_gl_coalesce_para(struct net_device *netdev,
				       struct ethtool_coalesce *cmd)
{
	u32 rx_gl, tx_gl;

	if (cmd->rx_coalesce_usecs > HNS3_INT_GL_MAX) {
		netdev_err(netdev,
			   "Invalid rx-usecs value, rx-usecs range is 0-%d\n",
			   HNS3_INT_GL_MAX);
		return -EINVAL;
	}

	if (cmd->tx_coalesce_usecs > HNS3_INT_GL_MAX) {
		netdev_err(netdev,
			   "Invalid tx-usecs value, tx-usecs range is 0-%d\n",
			   HNS3_INT_GL_MAX);
		return -EINVAL;
	}

	rx_gl = hns3_gl_round_down(cmd->rx_coalesce_usecs);
	if (rx_gl != cmd->rx_coalesce_usecs) {
		netdev_info(netdev,
			    "rx_usecs(%d) rounded down to %d, because it must be multiple of 2.\n",
			    cmd->rx_coalesce_usecs, rx_gl);
	}

	tx_gl = hns3_gl_round_down(cmd->tx_coalesce_usecs);
	if (tx_gl != cmd->tx_coalesce_usecs) {
		netdev_info(netdev,
			    "tx_usecs(%d) rounded down to %d, because it must be multiple of 2.\n",
			    cmd->tx_coalesce_usecs, tx_gl);
	}

	return 0;
}

static int hns3_check_rl_coalesce_para(struct net_device *netdev,
				       struct ethtool_coalesce *cmd)
{
	u32 rl;

	if (cmd->tx_coalesce_usecs_high != cmd->rx_coalesce_usecs_high) {
		netdev_err(netdev,
			   "tx_usecs_high must be same as rx_usecs_high.\n");
		return -EINVAL;
	}

	if (cmd->rx_coalesce_usecs_high > HNS3_INT_RL_MAX) {
		netdev_err(netdev,
			   "Invalid usecs_high value, usecs_high range is 0-%d\n",
			   HNS3_INT_RL_MAX);
		return -EINVAL;
	}

	rl = hns3_rl_round_down(cmd->rx_coalesce_usecs_high);
	if (rl != cmd->rx_coalesce_usecs_high) {
		netdev_info(netdev,
			    "usecs_high(%d) rounded down to %d, because it must be multiple of 4.\n",
			    cmd->rx_coalesce_usecs_high, rl);
	}

	return 0;
}

static int hns3_check_coalesce_para(struct net_device *netdev,
				    struct ethtool_coalesce *cmd)
{
	int ret;

	ret = hns3_check_gl_coalesce_para(netdev, cmd);
	if (ret) {
		netdev_err(netdev,
			   "Check gl coalesce param fail. ret = %d\n", ret);
		return ret;
	}

	ret = hns3_check_rl_coalesce_para(netdev, cmd);
	if (ret) {
		netdev_err(netdev,
			   "Check rl coalesce param fail. ret = %d\n", ret);
		return ret;
	}

	if (cmd->use_adaptive_tx_coalesce == 1 ||
	    cmd->use_adaptive_rx_coalesce == 1) {
		netdev_info(netdev,
			    "adaptive-tx=%d and adaptive-rx=%d, tx_usecs or rx_usecs will changed dynamically.\n",
			    cmd->use_adaptive_tx_coalesce,
			    cmd->use_adaptive_rx_coalesce);
	}

	return 0;
}

static void hns3_set_coalesce_per_queue(struct net_device *netdev,
					struct ethtool_coalesce *cmd,
					u32 queue)
{
	struct hns3_enet_tqp_vector *tx_vector, *rx_vector;
	struct hns3_nic_priv *priv = netdev_priv(netdev);
	struct hnae3_handle *h = priv->ae_handle;
	int queue_num = h->kinfo.num_tqps;

	tx_vector = priv->ring_data[queue].ring->tqp_vector;
	rx_vector = priv->ring_data[queue_num + queue].ring->tqp_vector;

	tx_vector->tx_group.gl_adapt_enable = cmd->use_adaptive_tx_coalesce;
	rx_vector->rx_group.gl_adapt_enable = cmd->use_adaptive_rx_coalesce;

	tx_vector->tx_group.int_gl = cmd->tx_coalesce_usecs;
	rx_vector->rx_group.int_gl = cmd->rx_coalesce_usecs;

	hns3_set_vector_coalesce_tx_gl(tx_vector, tx_vector->tx_group.int_gl);
	hns3_set_vector_coalesce_rx_gl(rx_vector, rx_vector->rx_group.int_gl);

	hns3_set_vector_coalesce_rl(tx_vector, h->kinfo.int_rl_setting);
	hns3_set_vector_coalesce_rl(rx_vector, h->kinfo.int_rl_setting);
}

static int hns3_set_coalesce(struct net_device *netdev,
			     struct ethtool_coalesce *cmd)
{
	struct hnae3_handle *h = hns3_get_handle(netdev);
	u16 queue_num = h->kinfo.num_tqps;
	int ret;
	int i;

	ret = hns3_check_coalesce_para(netdev, cmd);
	if (ret)
		return ret;

	h->kinfo.int_rl_setting =
		hns3_rl_round_down(cmd->rx_coalesce_usecs_high);

	for (i = 0; i < queue_num; i++)
		hns3_set_coalesce_per_queue(netdev, cmd, i);

	return 0;
}

static const struct ethtool_ops hns3vf_ethtool_ops = {
	.get_drvinfo = hns3_get_drvinfo,
	.get_ringparam = hns3_get_ringparam,
@@ -900,6 +1076,7 @@ static const struct ethtool_ops hns3vf_ethtool_ops = {
	.get_rxfh = hns3_get_rss,
	.set_rxfh = hns3_set_rss,
	.get_link_ksettings = hns3_get_link_ksettings,
	.get_channels = hns3_get_channels,
};

static const struct ethtool_ops hns3_ethtool_ops = {
@@ -924,6 +1101,8 @@ static const struct ethtool_ops hns3_ethtool_ops = {
	.nway_reset = hns3_nway_reset,
	.get_channels = hns3_get_channels,
	.set_channels = hns3_set_channels,
	.get_coalesce = hns3_get_coalesce,
	.set_coalesce = hns3_set_coalesce,
};

void hns3_ethtool_set_ops(struct net_device *netdev)
+5 −0
Original line number Diff line number Diff line
@@ -3409,6 +3409,11 @@ int hclge_bind_ring_with_vector(struct hclge_vport *vport,
			       hnae_get_bit(node->flag, HNAE3_RING_TYPE_B));
		hnae_set_field(tqp_type_and_id, HCLGE_TQP_ID_M,
			       HCLGE_TQP_ID_S, node->tqp_index);
		hnae_set_field(tqp_type_and_id, HCLGE_INT_GL_IDX_M,
			       HCLGE_INT_GL_IDX_S,
			       hnae_get_field(node->int_gl_idx,
					      HNAE3_RING_GL_IDX_M,
					      HNAE3_RING_GL_IDX_S));
		req->tqp_type_and_id[i] = cpu_to_le16(tqp_type_and_id);
		if (++i >= HCLGE_VECTOR_ELEMENTS_PER_CMD) {
			req->int_cause_num = HCLGE_VECTOR_ELEMENTS_PER_CMD;
Loading