Blob Blame History Raw
From: Saeed Mahameed <saeedm@nvidia.com>
Date: Tue, 9 Feb 2021 15:43:56 -0800
Subject: net/mlx5e: HTB, hide and dynamically allocate mlx5e_htb structure
Patch-mainline: v6.0-rc1
Git-commit: aaffda6b36686a368d6569df3f92acfc7fc0fcd8
References: jsc#PED-1549

Move structure mlx5e_htb from the main driver include file "en.h" to be
hidden in qos.c where the qos functionality is implemented, forward
declare it for the rest of the driver and allocate it dynamically upon
user demand only.

Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Moshe Tal <moshet@nvidia.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Reviewed-by: Maxim Mikityanskiy <maximmi@nvidia.com>
Acked-by: Thomas Bogendoerfer <tbogendoerfer@suse.de>
---
 drivers/net/ethernet/mellanox/mlx5/core/en.h      |    8 --
 drivers/net/ethernet/mellanox/mlx5/core/en/qos.c  |   87 ++++++++++++++++------
 drivers/net/ethernet/mellanox/mlx5/core/en_main.c |    7 +
 3 files changed, 70 insertions(+), 32 deletions(-)

--- a/drivers/net/ethernet/mellanox/mlx5/core/en.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h
@@ -899,12 +899,8 @@ struct mlx5e_scratchpad {
 	cpumask_var_t cpumask;
 };
 
-struct mlx5e_htb {
-	DECLARE_HASHTABLE(qos_tc2node, order_base_2(MLX5E_QOS_MAX_LEAF_NODES));
-	DECLARE_BITMAP(qos_used_qids, MLX5E_QOS_MAX_LEAF_NODES);
-};
-
 struct mlx5e_trap;
+struct mlx5e_htb;
 
 struct mlx5e_priv {
 	/* priv data path fields - start */
@@ -975,7 +971,7 @@ struct mlx5e_priv {
 	struct mlx5e_hv_vhca_stats_agent stats_agent;
 #endif
 	struct mlx5e_scratchpad    scratchpad;
-	struct mlx5e_htb           htb;
+	struct mlx5e_htb          *htb;
 	struct mlx5e_mqprio_rl    *mqprio_rl;
 };
 
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/qos.c
@@ -9,6 +9,11 @@
 
 #define BYTES_IN_MBIT 125000
 
+struct mlx5e_htb {
+	DECLARE_HASHTABLE(qos_tc2node, order_base_2(MLX5E_QOS_MAX_LEAF_NODES));
+	DECLARE_BITMAP(qos_used_qids, MLX5E_QOS_MAX_LEAF_NODES);
+};
+
 int mlx5e_qos_bytes_rate_check(struct mlx5_core_dev *mdev, u64 nbytes)
 {
 	if (nbytes < BYTES_IN_MBIT) {
@@ -31,8 +36,9 @@ int mlx5e_qos_max_leaf_nodes(struct mlx5
 
 int mlx5e_qos_cur_leaf_nodes(struct mlx5e_priv *priv)
 {
-	int last = find_last_bit(priv->htb.qos_used_qids, mlx5e_qos_max_leaf_nodes(priv->mdev));
+	int last;
 
+	last = find_last_bit(priv->htb->qos_used_qids, mlx5e_qos_max_leaf_nodes(priv->mdev));
 	return last == mlx5e_qos_max_leaf_nodes(priv->mdev) ? 0 : last + 1;
 }
 
@@ -44,7 +50,7 @@ static int mlx5e_find_unused_qos_qid(str
 	int res;
 
 	WARN_ONCE(!mutex_is_locked(&priv->state_lock), "%s: state_lock is not held\n", __func__);
-	res = find_first_zero_bit(priv->htb.qos_used_qids, size);
+	res = find_first_zero_bit(priv->htb->qos_used_qids, size);
 
 	return res == size ? -ENOSPC : res;
 }
@@ -76,10 +82,10 @@ mlx5e_sw_node_create_leaf(struct mlx5e_p
 	node->parent = parent;
 
 	node->qid = qid;
-	__set_bit(qid, priv->htb.qos_used_qids);
+	__set_bit(qid, priv->htb->qos_used_qids);
 
 	node->classid = classid;
-	hash_add_rcu(priv->htb.qos_tc2node, &node->hnode, classid);
+	hash_add_rcu(priv->htb->qos_tc2node, &node->hnode, classid);
 
 	mlx5e_update_tx_netdev_queues(priv);
 
@@ -96,7 +102,7 @@ static struct mlx5e_qos_node *mlx5e_sw_n
 
 	node->qid = MLX5E_QOS_QID_INNER;
 	node->classid = MLX5E_HTB_CLASSID_ROOT;
-	hash_add_rcu(priv->htb.qos_tc2node, &node->hnode, node->classid);
+	hash_add_rcu(priv->htb->qos_tc2node, &node->hnode, node->classid);
 
 	return node;
 }
@@ -105,7 +111,7 @@ static struct mlx5e_qos_node *mlx5e_sw_n
 {
 	struct mlx5e_qos_node *node = NULL;
 
-	hash_for_each_possible(priv->htb.qos_tc2node, node, hnode, classid) {
+	hash_for_each_possible(priv->htb->qos_tc2node, node, hnode, classid) {
 		if (node->classid == classid)
 			break;
 	}
@@ -117,7 +123,7 @@ static struct mlx5e_qos_node *mlx5e_sw_n
 {
 	struct mlx5e_qos_node *node = NULL;
 
-	hash_for_each_possible_rcu(priv->htb.qos_tc2node, node, hnode, classid) {
+	hash_for_each_possible_rcu(priv->htb->qos_tc2node, node, hnode, classid) {
 		if (node->classid == classid)
 			break;
 	}
@@ -129,7 +135,7 @@ static void mlx5e_sw_node_delete(struct
 {
 	hash_del_rcu(&node->hnode);
 	if (node->qid != MLX5E_QOS_QID_INNER) {
-		__clear_bit(node->qid, priv->htb.qos_used_qids);
+		__clear_bit(node->qid, priv->htb->qos_used_qids);
 		mlx5e_update_tx_netdev_queues(priv);
 	}
 	/* Make sure this qid is no longer selected by mlx5e_select_queue, so
@@ -424,7 +430,7 @@ int mlx5e_qos_open_queues(struct mlx5e_p
 	if (err)
 		return err;
 
-	hash_for_each(priv->htb.qos_tc2node, bkt, node, hnode) {
+	hash_for_each(priv->htb->qos_tc2node, bkt, node, hnode) {
 		if (node->qid == MLX5E_QOS_QID_INNER)
 			continue;
 		err = mlx5e_open_qos_sq(priv, chs, node);
@@ -442,7 +448,7 @@ void mlx5e_qos_activate_queues(struct ml
 	struct mlx5e_qos_node *node = NULL;
 	int bkt;
 
-	hash_for_each(priv->htb.qos_tc2node, bkt, node, hnode) {
+	hash_for_each(priv->htb->qos_tc2node, bkt, node, hnode) {
 		if (node->qid == MLX5E_QOS_QID_INNER)
 			continue;
 		mlx5e_activate_qos_sq(priv, node);
@@ -495,12 +501,6 @@ mlx5e_htb_root_add(struct mlx5e_priv *pr
 
 	qos_dbg(priv->mdev, "TC_HTB_CREATE handle %04x:, default :%04x\n", htb_maj_id, htb_defcls);
 
-	if (!mlx5_qos_is_supported(priv->mdev)) {
-		NL_SET_ERR_MSG_MOD(extack,
-				   "Missing QoS capabilities. Try disabling SRIOV or use a supported device.");
-		return -EOPNOTSUPP;
-	}
-
 	mlx5e_selq_prepare_htb(&priv->selq, htb_maj_id, htb_defcls);
 
 	opened = test_bit(MLX5E_STATE_OPENED, &priv->state);
@@ -749,7 +749,7 @@ static struct mlx5e_qos_node *mlx5e_sw_n
 	struct mlx5e_qos_node *node = NULL;
 	int bkt;
 
-	hash_for_each(priv->htb.qos_tc2node, bkt, node, hnode)
+	hash_for_each(priv->htb->qos_tc2node, bkt, node, hnode)
 		if (node->qid == qid)
 			break;
 
@@ -837,7 +837,7 @@ static int mlx5e_htb_leaf_del(struct mlx
 
 	/* Stop traffic to the old queue. */
 	WRITE_ONCE(node->qid, MLX5E_QOS_QID_INNER);
-	__clear_bit(moved_qid, priv->htb.qos_used_qids);
+	__clear_bit(moved_qid, priv->htb->qos_used_qids);
 
 	if (opened) {
 		txq = netdev_get_tx_queue(priv->netdev,
@@ -849,7 +849,7 @@ static int mlx5e_htb_leaf_del(struct mlx
 	/* Prevent packets from the old class from getting into the new one. */
 	mlx5e_reset_qdisc(priv->netdev, moved_qid);
 
-	__set_bit(qid, priv->htb.qos_used_qids);
+	__set_bit(qid, priv->htb->qos_used_qids);
 	WRITE_ONCE(node->qid, qid);
 
 	if (test_bit(MLX5E_STATE_OPENED, &priv->state)) {
@@ -960,7 +960,7 @@ mlx5e_qos_update_children(struct mlx5e_p
 	int err = 0;
 	int bkt;
 
-	hash_for_each(priv->htb.qos_tc2node, bkt, child, hnode) {
+	hash_for_each(priv->htb->qos_tc2node, bkt, child, hnode) {
 		u32 old_bw_share = child->bw_share;
 		int err_one;
 
@@ -1027,16 +1027,57 @@ mlx5e_htb_node_modify(struct mlx5e_priv
 }
 
 /* HTB API */
+
+static struct mlx5e_htb *mlx5e_htb_alloc(void)
+{
+	return kvzalloc(sizeof(struct mlx5e_htb), GFP_KERNEL);
+}
+
+static void mlx5e_htb_free(struct mlx5e_htb *htb)
+{
+	kvfree(htb);
+}
+
+static int mlx5e_htb_init(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb)
+{
+	hash_init(priv->htb->qos_tc2node);
+
+	return mlx5e_htb_root_add(priv, htb->parent_classid, htb->classid, htb->extack);
+}
+
+static void mlx5e_htb_cleanup(struct mlx5e_priv *priv)
+{
+	mlx5e_htb_root_del(priv);
+}
+
 int mlx5e_htb_setup_tc(struct mlx5e_priv *priv, struct tc_htb_qopt_offload *htb)
 {
 	int res;
 
+	if (!priv->htb && htb->command != TC_HTB_CREATE)
+		return -EINVAL;
+
 	switch (htb->command) {
 	case TC_HTB_CREATE:
-		return mlx5e_htb_root_add(priv, htb->parent_classid, htb->classid,
-					  htb->extack);
+		if (!mlx5_qos_is_supported(priv->mdev)) {
+			NL_SET_ERR_MSG_MOD(htb->extack,
+					   "Missing QoS capabilities. Try disabling SRIOV or use a supported device.");
+			return -EOPNOTSUPP;
+		}
+		priv->htb = mlx5e_htb_alloc();
+		if (!priv->htb)
+			return -ENOMEM;
+		res = mlx5e_htb_init(priv, htb);
+		if (res) {
+			mlx5e_htb_free(priv->htb);
+			priv->htb = NULL;
+		}
+		return res;
 	case TC_HTB_DESTROY:
-		return mlx5e_htb_root_del(priv);
+		mlx5e_htb_cleanup(priv);
+		mlx5e_htb_free(priv->htb);
+		priv->htb = NULL;
+		return 0;
 	case TC_HTB_LEAF_ALLOC_QUEUE:
 		res = mlx5e_htb_leaf_alloc_queue(priv, htb->classid, htb->parent_classid,
 						 htb->rate, htb->ceil, htb->extack);
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -2572,9 +2572,11 @@ static int mlx5e_netdev_set_tcs(struct n
 
 int mlx5e_update_tx_netdev_queues(struct mlx5e_priv *priv)
 {
-	int qos_queues, nch, ntc, num_txqs, err;
+	int nch, ntc, num_txqs, err;
+	int qos_queues = 0;
 
-	qos_queues = mlx5e_qos_cur_leaf_nodes(priv);
+	if (priv->htb)
+		qos_queues = mlx5e_qos_cur_leaf_nodes(priv);
 
 	nch = priv->channels.params.num_channels;
 	ntc = mlx5e_get_dcb_num_tc(&priv->channels.params);
@@ -5314,7 +5316,6 @@ int mlx5e_priv_init(struct mlx5e_priv *p
 	if (err)
 		goto err_free_cpumask;
 
-	hash_init(priv->htb.qos_tc2node);
 	INIT_WORK(&priv->update_carrier_work, mlx5e_update_carrier_work);
 	INIT_WORK(&priv->set_rx_mode_work, mlx5e_set_rx_mode_work);
 	INIT_WORK(&priv->tx_timeout_work, mlx5e_tx_timeout_work);