Commit 91bfae25 authored by Huazhong Tan's avatar Huazhong Tan Committed by Jakub Kicinski
Browse files

net: hns3: add support for configuring interrupt quantity limiting



QL(quantity limiting) means that hardware supports the interrupt
coalesce based on the frame quantity.  QL can be configured when
int_ql_max in device's specification is non-zero, so add support
to configure it. Also, rename two coalesce init function to fit
their purpose.

Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 0676a4ea
Loading
Loading
Loading
Loading
+49 −16
Original line number Diff line number Diff line
@@ -237,35 +237,68 @@ void hns3_set_vector_coalesce_tx_gl(struct hns3_enet_tqp_vector *tqp_vector,
	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,
void hns3_set_vector_coalesce_tx_ql(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 ql_value)
{
	writel(ql_value, tqp_vector->mask_addr + HNS3_VECTOR_TX_QL_OFFSET);
}

void hns3_set_vector_coalesce_rx_ql(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 ql_value)
{
	writel(ql_value, tqp_vector->mask_addr + HNS3_VECTOR_RX_QL_OFFSET);
}

static void hns3_vector_coalesce_init(struct hns3_enet_tqp_vector *tqp_vector,
				      struct hns3_nic_priv *priv)
{
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(priv->ae_handle->pdev);
	struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal;
	struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal;

	/* initialize the configuration for interrupt coalescing.
	 * 1. GL (Interrupt Gap Limiter)
	 * 2. RL (Interrupt Rate Limiter)
	 * 3. QL (Interrupt Quantity Limiter)
	 *
	 * Default: enable interrupt coalescing self-adaptive and GL
	 */
	tqp_vector->tx_group.coal.gl_adapt_enable = 1;
	tqp_vector->rx_group.coal.gl_adapt_enable = 1;
	tx_coal->gl_adapt_enable = 1;
	rx_coal->gl_adapt_enable = 1;

	tqp_vector->tx_group.coal.int_gl = HNS3_INT_GL_50K;
	tqp_vector->rx_group.coal.int_gl = HNS3_INT_GL_50K;
	tx_coal->int_gl = HNS3_INT_GL_50K;
	rx_coal->int_gl = HNS3_INT_GL_50K;

	tqp_vector->rx_group.coal.flow_level = HNS3_FLOW_LOW;
	tqp_vector->tx_group.coal.flow_level = HNS3_FLOW_LOW;
	rx_coal->flow_level = HNS3_FLOW_LOW;
	tx_coal->flow_level = HNS3_FLOW_LOW;

	if (ae_dev->dev_specs.int_ql_max) {
		tx_coal->ql_enable = 1;
		rx_coal->ql_enable = 1;
		tx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
		rx_coal->int_ql_max = ae_dev->dev_specs.int_ql_max;
		tx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
		rx_coal->int_ql = HNS3_INT_QL_DEFAULT_CFG;
	}
}

static void hns3_vector_gl_rl_init_hw(struct hns3_enet_tqp_vector *tqp_vector,
static void
hns3_vector_coalesce_init_hw(struct hns3_enet_tqp_vector *tqp_vector,
			     struct hns3_nic_priv *priv)
{
	struct hns3_enet_coalesce *tx_coal = &tqp_vector->tx_group.coal;
	struct hns3_enet_coalesce *rx_coal = &tqp_vector->rx_group.coal;
	struct hnae3_handle *h = priv->ae_handle;

	hns3_set_vector_coalesce_tx_gl(tqp_vector,
				       tqp_vector->tx_group.coal.int_gl);
	hns3_set_vector_coalesce_rx_gl(tqp_vector,
				       tqp_vector->rx_group.coal.int_gl);
	hns3_set_vector_coalesce_tx_gl(tqp_vector, tx_coal->int_gl);
	hns3_set_vector_coalesce_rx_gl(tqp_vector, rx_coal->int_gl);
	hns3_set_vector_coalesce_rl(tqp_vector, h->kinfo.int_rl_setting);

	if (tx_coal->ql_enable)
		hns3_set_vector_coalesce_tx_ql(tqp_vector, tx_coal->int_ql);

	if (rx_coal->ql_enable)
		hns3_set_vector_coalesce_rx_ql(tqp_vector, rx_coal->int_ql);
}

static int hns3_nic_set_real_num_queue(struct net_device *netdev)
@@ -3536,7 +3569,7 @@ static int hns3_nic_init_vector_data(struct hns3_nic_priv *priv)

	for (i = 0; i < priv->vector_num; i++) {
		tqp_vector = &priv->tqp_vector[i];
		hns3_vector_gl_rl_init_hw(tqp_vector, priv);
		hns3_vector_coalesce_init_hw(tqp_vector, priv);
		tqp_vector->num_tqps = 0;
	}

@@ -3632,7 +3665,7 @@ static int hns3_nic_alloc_vector_data(struct hns3_nic_priv *priv)
		tqp_vector->idx = i;
		tqp_vector->mask_addr = vector[i].io_addr;
		tqp_vector->vector_irq = vector[i].vector;
		hns3_vector_gl_rl_init(tqp_vector, priv);
		hns3_vector_coalesce_init(tqp_vector, priv);
	}

out:
+12 −1
Original line number Diff line number Diff line
@@ -181,6 +181,8 @@ enum hns3_nic_state {
#define HNS3_VECTOR_GL2_OFFSET			0x300
#define HNS3_VECTOR_RL_OFFSET			0x900
#define HNS3_VECTOR_RL_EN_B			6
#define HNS3_VECTOR_TX_QL_OFFSET		0xe00
#define HNS3_VECTOR_RX_QL_OFFSET		0xf00

#define HNS3_RING_EN_B				0

@@ -427,9 +429,14 @@ enum hns3_flow_level_range {
#define HNS3_INT_RL_MAX			0x00EC
#define HNS3_INT_RL_ENABLE_MASK		0x40

#define HNS3_INT_QL_DEFAULT_CFG		0x20

struct hns3_enet_coalesce {
	u16 int_gl;
	u8 gl_adapt_enable;
	u16 int_ql;
	u16 int_ql_max;
	u8 gl_adapt_enable:1;
	u8 ql_enable:1;
	enum hns3_flow_level_range flow_level;
};

@@ -595,6 +602,10 @@ 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);
void hns3_set_vector_coalesce_rx_ql(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 ql_value);
void hns3_set_vector_coalesce_tx_ql(struct hns3_enet_tqp_vector *tqp_vector,
				    u32 ql_value);

void hns3_enable_vlan_filter(struct net_device *netdev, bool enable);
void hns3_request_update_promisc_mode(struct hnae3_handle *handle);
+42 −1
Original line number Diff line number Diff line
@@ -1115,6 +1115,9 @@ static int hns3_get_coalesce_per_queue(struct net_device *netdev, u32 queue,
	cmd->tx_coalesce_usecs_high = h->kinfo.int_rl_setting;
	cmd->rx_coalesce_usecs_high = h->kinfo.int_rl_setting;

	cmd->tx_max_coalesced_frames = tx_vector->tx_group.coal.int_ql;
	cmd->rx_max_coalesced_frames = rx_vector->rx_group.coal.int_ql;

	return 0;
}

@@ -1188,6 +1191,29 @@ static int hns3_check_rl_coalesce_para(struct net_device *netdev,
	return 0;
}

static int hns3_check_ql_coalesce_param(struct net_device *netdev,
					struct ethtool_coalesce *cmd)
{
	struct hnae3_handle *handle = hns3_get_handle(netdev);
	struct hnae3_ae_dev *ae_dev = pci_get_drvdata(handle->pdev);

	if ((cmd->tx_max_coalesced_frames || cmd->rx_max_coalesced_frames) &&
	    !ae_dev->dev_specs.int_ql_max) {
		netdev_err(netdev, "coalesced frames is not supported\n");
		return -EOPNOTSUPP;
	}

	if (cmd->tx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max ||
	    cmd->rx_max_coalesced_frames > ae_dev->dev_specs.int_ql_max) {
		netdev_err(netdev,
			   "invalid coalesced_frames value, range is 0-%u\n",
			   ae_dev->dev_specs.int_ql_max);
		return -ERANGE;
	}

	return 0;
}

static int hns3_check_coalesce_para(struct net_device *netdev,
				    struct ethtool_coalesce *cmd)
{
@@ -1207,6 +1233,10 @@ static int hns3_check_coalesce_para(struct net_device *netdev,
		return ret;
	}

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

	if (cmd->use_adaptive_tx_coalesce == 1 ||
	    cmd->use_adaptive_rx_coalesce == 1) {
		netdev_info(netdev,
@@ -1238,6 +1268,9 @@ static void hns3_set_coalesce_per_queue(struct net_device *netdev,
	tx_vector->tx_group.coal.int_gl = cmd->tx_coalesce_usecs;
	rx_vector->rx_group.coal.int_gl = cmd->rx_coalesce_usecs;

	tx_vector->tx_group.coal.int_ql = cmd->tx_max_coalesced_frames;
	rx_vector->rx_group.coal.int_ql = cmd->rx_max_coalesced_frames;

	hns3_set_vector_coalesce_tx_gl(tx_vector,
				       tx_vector->tx_group.coal.int_gl);
	hns3_set_vector_coalesce_rx_gl(rx_vector,
@@ -1245,6 +1278,13 @@ static void hns3_set_coalesce_per_queue(struct net_device *netdev,

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

	if (tx_vector->tx_group.coal.ql_enable)
		hns3_set_vector_coalesce_tx_ql(tx_vector,
					       tx_vector->tx_group.coal.int_ql);
	if (rx_vector->rx_group.coal.ql_enable)
		hns3_set_vector_coalesce_rx_ql(rx_vector,
					       rx_vector->rx_group.coal.int_ql);
}

static int hns3_set_coalesce(struct net_device *netdev,
@@ -1471,7 +1511,8 @@ static int hns3_get_module_eeprom(struct net_device *netdev,
#define HNS3_ETHTOOL_COALESCE	(ETHTOOL_COALESCE_USECS |		\
				 ETHTOOL_COALESCE_USE_ADAPTIVE |	\
				 ETHTOOL_COALESCE_RX_USECS_HIGH |	\
				 ETHTOOL_COALESCE_TX_USECS_HIGH)
				 ETHTOOL_COALESCE_TX_USECS_HIGH |	\
				 ETHTOOL_COALESCE_MAX_FRAMES)

static const struct ethtool_ops hns3vf_ethtool_ops = {
	.supported_coalesce_params = HNS3_ETHTOOL_COALESCE,
+1 −0
Original line number Diff line number Diff line
@@ -1379,6 +1379,7 @@ static void hclge_parse_dev_specs(struct hclge_dev *hdev,
	ae_dev->dev_specs.max_non_tso_bd_num = req0->max_non_tso_bd_num;
	ae_dev->dev_specs.rss_ind_tbl_size =
		le16_to_cpu(req0->rss_ind_tbl_size);
	ae_dev->dev_specs.int_ql_max = le16_to_cpu(req0->int_ql_max);
	ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size);
	ae_dev->dev_specs.max_tm_rate = le32_to_cpu(req0->max_tm_rate);
}
+1 −0
Original line number Diff line number Diff line
@@ -3004,6 +3004,7 @@ static void hclgevf_parse_dev_specs(struct hclgevf_dev *hdev,
	ae_dev->dev_specs.max_non_tso_bd_num = req0->max_non_tso_bd_num;
	ae_dev->dev_specs.rss_ind_tbl_size =
					le16_to_cpu(req0->rss_ind_tbl_size);
	ae_dev->dev_specs.int_ql_max = le16_to_cpu(req0->int_ql_max);
	ae_dev->dev_specs.rss_key_size = le16_to_cpu(req0->rss_key_size);
}