xref: /linux/drivers/net/ethernet/marvell/octeontx2/nic/qos.c (revision 36ec807b627b4c0a0a382f0ae48eac7187d14b2b)
15e6808b4SNaveen Mamindlapalli // SPDX-License-Identifier: GPL-2.0
25e6808b4SNaveen Mamindlapalli /* Marvell RVU Ethernet driver
35e6808b4SNaveen Mamindlapalli  *
45e6808b4SNaveen Mamindlapalli  * Copyright (C) 2023 Marvell.
55e6808b4SNaveen Mamindlapalli  *
65e6808b4SNaveen Mamindlapalli  */
75e6808b4SNaveen Mamindlapalli #include <linux/netdevice.h>
85e6808b4SNaveen Mamindlapalli #include <linux/etherdevice.h>
95e6808b4SNaveen Mamindlapalli #include <linux/inetdevice.h>
105e6808b4SNaveen Mamindlapalli #include <linux/bitfield.h>
115e6808b4SNaveen Mamindlapalli 
125e6808b4SNaveen Mamindlapalli #include "otx2_common.h"
135e6808b4SNaveen Mamindlapalli #include "cn10k.h"
145e6808b4SNaveen Mamindlapalli #include "qos.h"
155e6808b4SNaveen Mamindlapalli 
165e6808b4SNaveen Mamindlapalli #define OTX2_QOS_QID_INNER		0xFFFFU
175e6808b4SNaveen Mamindlapalli #define OTX2_QOS_QID_NONE		0xFFFEU
185e6808b4SNaveen Mamindlapalli #define OTX2_QOS_ROOT_CLASSID		0xFFFFFFFF
195e6808b4SNaveen Mamindlapalli #define OTX2_QOS_CLASS_NONE		0
205e6808b4SNaveen Mamindlapalli #define OTX2_QOS_DEFAULT_PRIO		0xF
215e6808b4SNaveen Mamindlapalli #define OTX2_QOS_INVALID_SQ		0xFFFF
22f78dca69SNaveen Mamindlapalli #define OTX2_QOS_INVALID_TXSCHQ_IDX	0xFFFF
2347a9656fSNaveen Mamindlapalli #define CN10K_MAX_RR_WEIGHT		GENMASK_ULL(13, 0)
2447a9656fSNaveen Mamindlapalli #define OTX2_MAX_RR_QUANTUM		GENMASK_ULL(23, 0)
255e6808b4SNaveen Mamindlapalli 
265e6808b4SNaveen Mamindlapalli static void otx2_qos_update_tx_netdev_queues(struct otx2_nic *pfvf)
275e6808b4SNaveen Mamindlapalli {
285e6808b4SNaveen Mamindlapalli 	struct otx2_hw *hw = &pfvf->hw;
295e6808b4SNaveen Mamindlapalli 	int tx_queues, qos_txqs, err;
305e6808b4SNaveen Mamindlapalli 
315e6808b4SNaveen Mamindlapalli 	qos_txqs = bitmap_weight(pfvf->qos.qos_sq_bmap,
325e6808b4SNaveen Mamindlapalli 				 OTX2_QOS_MAX_LEAF_NODES);
335e6808b4SNaveen Mamindlapalli 
345e6808b4SNaveen Mamindlapalli 	tx_queues = hw->tx_queues + qos_txqs;
355e6808b4SNaveen Mamindlapalli 
365e6808b4SNaveen Mamindlapalli 	err = netif_set_real_num_tx_queues(pfvf->netdev, tx_queues);
375e6808b4SNaveen Mamindlapalli 	if (err) {
385e6808b4SNaveen Mamindlapalli 		netdev_err(pfvf->netdev,
395e6808b4SNaveen Mamindlapalli 			   "Failed to set no of Tx queues: %d\n", tx_queues);
405e6808b4SNaveen Mamindlapalli 		return;
415e6808b4SNaveen Mamindlapalli 	}
425e6808b4SNaveen Mamindlapalli }
435e6808b4SNaveen Mamindlapalli 
445e6808b4SNaveen Mamindlapalli static void otx2_qos_get_regaddr(struct otx2_qos_node *node,
455e6808b4SNaveen Mamindlapalli 				 struct nix_txschq_config *cfg,
465e6808b4SNaveen Mamindlapalli 				 int index)
475e6808b4SNaveen Mamindlapalli {
485e6808b4SNaveen Mamindlapalli 	if (node->level == NIX_TXSCH_LVL_SMQ) {
495e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_MDQX_PARENT(node->schq);
505e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_MDQX_SCHEDULE(node->schq);
515e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_MDQX_PIR(node->schq);
525e6808b4SNaveen Mamindlapalli 		cfg->reg[index]   = NIX_AF_MDQX_CIR(node->schq);
535e6808b4SNaveen Mamindlapalli 	} else if (node->level == NIX_TXSCH_LVL_TL4) {
545e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL4X_PARENT(node->schq);
555e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL4X_SCHEDULE(node->schq);
565e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL4X_PIR(node->schq);
575e6808b4SNaveen Mamindlapalli 		cfg->reg[index]   = NIX_AF_TL4X_CIR(node->schq);
585e6808b4SNaveen Mamindlapalli 	} else if (node->level == NIX_TXSCH_LVL_TL3) {
595e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL3X_PARENT(node->schq);
605e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL3X_SCHEDULE(node->schq);
615e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL3X_PIR(node->schq);
625e6808b4SNaveen Mamindlapalli 		cfg->reg[index]   = NIX_AF_TL3X_CIR(node->schq);
635e6808b4SNaveen Mamindlapalli 	} else if (node->level == NIX_TXSCH_LVL_TL2) {
645e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL2X_PARENT(node->schq);
655e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL2X_SCHEDULE(node->schq);
665e6808b4SNaveen Mamindlapalli 		cfg->reg[index++] = NIX_AF_TL2X_PIR(node->schq);
675e6808b4SNaveen Mamindlapalli 		cfg->reg[index]   = NIX_AF_TL2X_CIR(node->schq);
685e6808b4SNaveen Mamindlapalli 	}
695e6808b4SNaveen Mamindlapalli }
705e6808b4SNaveen Mamindlapalli 
7147a9656fSNaveen Mamindlapalli static int otx2_qos_quantum_to_dwrr_weight(struct otx2_nic *pfvf, u32 quantum)
7247a9656fSNaveen Mamindlapalli {
7347a9656fSNaveen Mamindlapalli 	u32 weight;
7447a9656fSNaveen Mamindlapalli 
7547a9656fSNaveen Mamindlapalli 	weight = quantum / pfvf->hw.dwrr_mtu;
7647a9656fSNaveen Mamindlapalli 	if (quantum % pfvf->hw.dwrr_mtu)
7747a9656fSNaveen Mamindlapalli 		weight += 1;
7847a9656fSNaveen Mamindlapalli 
7947a9656fSNaveen Mamindlapalli 	return weight;
8047a9656fSNaveen Mamindlapalli }
8147a9656fSNaveen Mamindlapalli 
825e6808b4SNaveen Mamindlapalli static void otx2_config_sched_shaping(struct otx2_nic *pfvf,
835e6808b4SNaveen Mamindlapalli 				      struct otx2_qos_node *node,
845e6808b4SNaveen Mamindlapalli 				      struct nix_txschq_config *cfg,
855e6808b4SNaveen Mamindlapalli 				      int *num_regs)
865e6808b4SNaveen Mamindlapalli {
8747a9656fSNaveen Mamindlapalli 	u32 rr_weight;
8847a9656fSNaveen Mamindlapalli 	u32 quantum;
895e6808b4SNaveen Mamindlapalli 	u64 maxrate;
905e6808b4SNaveen Mamindlapalli 
915e6808b4SNaveen Mamindlapalli 	otx2_qos_get_regaddr(node, cfg, *num_regs);
925e6808b4SNaveen Mamindlapalli 
935e6808b4SNaveen Mamindlapalli 	/* configure parent txschq */
945e6808b4SNaveen Mamindlapalli 	cfg->regval[*num_regs] = node->parent->schq << 16;
955e6808b4SNaveen Mamindlapalli 	(*num_regs)++;
965e6808b4SNaveen Mamindlapalli 
975e6808b4SNaveen Mamindlapalli 	/* configure prio/quantum */
985e6808b4SNaveen Mamindlapalli 	if (node->qid == OTX2_QOS_QID_NONE) {
995e6808b4SNaveen Mamindlapalli 		cfg->regval[*num_regs] =  node->prio << 24 |
1005e6808b4SNaveen Mamindlapalli 					  mtu_to_dwrr_weight(pfvf, pfvf->tx_max_pktlen);
1015e6808b4SNaveen Mamindlapalli 		(*num_regs)++;
1025e6808b4SNaveen Mamindlapalli 		return;
1035e6808b4SNaveen Mamindlapalli 	}
1045e6808b4SNaveen Mamindlapalli 
10547a9656fSNaveen Mamindlapalli 	/* configure priority/quantum  */
10647a9656fSNaveen Mamindlapalli 	if (node->is_static) {
10747a9656fSNaveen Mamindlapalli 		cfg->regval[*num_regs] =
10847a9656fSNaveen Mamindlapalli 			(node->schq - node->parent->prio_anchor) << 24;
10947a9656fSNaveen Mamindlapalli 	} else {
11047a9656fSNaveen Mamindlapalli 		quantum = node->quantum ?
11147a9656fSNaveen Mamindlapalli 			  node->quantum : pfvf->tx_max_pktlen;
11247a9656fSNaveen Mamindlapalli 		rr_weight = otx2_qos_quantum_to_dwrr_weight(pfvf, quantum);
11347a9656fSNaveen Mamindlapalli 		cfg->regval[*num_regs] = node->parent->child_dwrr_prio << 24 |
11447a9656fSNaveen Mamindlapalli 					 rr_weight;
11547a9656fSNaveen Mamindlapalli 	}
1165e6808b4SNaveen Mamindlapalli 	(*num_regs)++;
1175e6808b4SNaveen Mamindlapalli 
1185e6808b4SNaveen Mamindlapalli 	/* configure PIR */
1195e6808b4SNaveen Mamindlapalli 	maxrate = (node->rate > node->ceil) ? node->rate : node->ceil;
1205e6808b4SNaveen Mamindlapalli 
1215e6808b4SNaveen Mamindlapalli 	cfg->regval[*num_regs] =
1225e6808b4SNaveen Mamindlapalli 		otx2_get_txschq_rate_regval(pfvf, maxrate, 65536);
1235e6808b4SNaveen Mamindlapalli 	(*num_regs)++;
1245e6808b4SNaveen Mamindlapalli 
1255e6808b4SNaveen Mamindlapalli 	/* Don't configure CIR when both CIR+PIR not supported
1265e6808b4SNaveen Mamindlapalli 	 * On 96xx, CIR + PIR + RED_ALGO=STALL causes deadlock
1275e6808b4SNaveen Mamindlapalli 	 */
1285e6808b4SNaveen Mamindlapalli 	if (!test_bit(QOS_CIR_PIR_SUPPORT, &pfvf->hw.cap_flag))
1295e6808b4SNaveen Mamindlapalli 		return;
1305e6808b4SNaveen Mamindlapalli 
1315e6808b4SNaveen Mamindlapalli 	cfg->regval[*num_regs] =
1325e6808b4SNaveen Mamindlapalli 		otx2_get_txschq_rate_regval(pfvf, node->rate, 65536);
1335e6808b4SNaveen Mamindlapalli 	(*num_regs)++;
1345e6808b4SNaveen Mamindlapalli }
1355e6808b4SNaveen Mamindlapalli 
1365e6808b4SNaveen Mamindlapalli static void __otx2_qos_txschq_cfg(struct otx2_nic *pfvf,
1375e6808b4SNaveen Mamindlapalli 				  struct otx2_qos_node *node,
1385e6808b4SNaveen Mamindlapalli 				  struct nix_txschq_config *cfg)
1395e6808b4SNaveen Mamindlapalli {
1405e6808b4SNaveen Mamindlapalli 	struct otx2_hw *hw = &pfvf->hw;
1415e6808b4SNaveen Mamindlapalli 	int num_regs = 0;
1425e6808b4SNaveen Mamindlapalli 	u8 level;
1435e6808b4SNaveen Mamindlapalli 
1445e6808b4SNaveen Mamindlapalli 	level = node->level;
1455e6808b4SNaveen Mamindlapalli 
1465e6808b4SNaveen Mamindlapalli 	/* program txschq registers */
1475e6808b4SNaveen Mamindlapalli 	if (level == NIX_TXSCH_LVL_SMQ) {
1485e6808b4SNaveen Mamindlapalli 		cfg->reg[num_regs] = NIX_AF_SMQX_CFG(node->schq);
1495e6808b4SNaveen Mamindlapalli 		cfg->regval[num_regs] = ((u64)pfvf->tx_max_pktlen << 8) |
1505e6808b4SNaveen Mamindlapalli 					OTX2_MIN_MTU;
1515e6808b4SNaveen Mamindlapalli 		cfg->regval[num_regs] |= (0x20ULL << 51) | (0x80ULL << 39) |
1525e6808b4SNaveen Mamindlapalli 					 (0x2ULL << 36);
1535e6808b4SNaveen Mamindlapalli 		num_regs++;
1545e6808b4SNaveen Mamindlapalli 
1555e6808b4SNaveen Mamindlapalli 		otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
1565e6808b4SNaveen Mamindlapalli 	} else if (level == NIX_TXSCH_LVL_TL4) {
1575e6808b4SNaveen Mamindlapalli 		otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
1585e6808b4SNaveen Mamindlapalli 	} else if (level == NIX_TXSCH_LVL_TL3) {
1595e6808b4SNaveen Mamindlapalli 		/* configure link cfg */
1605e6808b4SNaveen Mamindlapalli 		if (level == pfvf->qos.link_cfg_lvl) {
1615e6808b4SNaveen Mamindlapalli 			cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link);
1625e6808b4SNaveen Mamindlapalli 			cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12);
1635e6808b4SNaveen Mamindlapalli 			num_regs++;
1645e6808b4SNaveen Mamindlapalli 		}
1655e6808b4SNaveen Mamindlapalli 
1665e6808b4SNaveen Mamindlapalli 		otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
1675e6808b4SNaveen Mamindlapalli 	} else if (level == NIX_TXSCH_LVL_TL2) {
1685e6808b4SNaveen Mamindlapalli 		/* configure link cfg */
1695e6808b4SNaveen Mamindlapalli 		if (level == pfvf->qos.link_cfg_lvl) {
1705e6808b4SNaveen Mamindlapalli 			cfg->reg[num_regs] = NIX_AF_TL3_TL2X_LINKX_CFG(node->schq, hw->tx_link);
1715e6808b4SNaveen Mamindlapalli 			cfg->regval[num_regs] = BIT_ULL(13) | BIT_ULL(12);
1725e6808b4SNaveen Mamindlapalli 			num_regs++;
1735e6808b4SNaveen Mamindlapalli 		}
1745e6808b4SNaveen Mamindlapalli 
1755e6808b4SNaveen Mamindlapalli 		/* check if node is root */
1765e6808b4SNaveen Mamindlapalli 		if (node->qid == OTX2_QOS_QID_INNER && !node->parent) {
1775e6808b4SNaveen Mamindlapalli 			cfg->reg[num_regs] = NIX_AF_TL2X_SCHEDULE(node->schq);
178*02ea3120SRatheesh Kannoth 			cfg->regval[num_regs] =  (u64)hw->txschq_aggr_lvl_rr_prio << 24 |
1795e6808b4SNaveen Mamindlapalli 						 mtu_to_dwrr_weight(pfvf,
1805e6808b4SNaveen Mamindlapalli 								    pfvf->tx_max_pktlen);
1815e6808b4SNaveen Mamindlapalli 			num_regs++;
1825e6808b4SNaveen Mamindlapalli 			goto txschq_cfg_out;
1835e6808b4SNaveen Mamindlapalli 		}
1845e6808b4SNaveen Mamindlapalli 
1855e6808b4SNaveen Mamindlapalli 		otx2_config_sched_shaping(pfvf, node, cfg, &num_regs);
1865e6808b4SNaveen Mamindlapalli 	}
1875e6808b4SNaveen Mamindlapalli 
1885e6808b4SNaveen Mamindlapalli txschq_cfg_out:
1895e6808b4SNaveen Mamindlapalli 	cfg->num_regs = num_regs;
1905e6808b4SNaveen Mamindlapalli }
1915e6808b4SNaveen Mamindlapalli 
1925e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf,
1935e6808b4SNaveen Mamindlapalli 					       struct otx2_qos_node *parent)
1945e6808b4SNaveen Mamindlapalli {
1955e6808b4SNaveen Mamindlapalli 	struct mbox *mbox = &pfvf->mbox;
1965e6808b4SNaveen Mamindlapalli 	struct nix_txschq_config *cfg;
1975e6808b4SNaveen Mamindlapalli 	int rc;
1985e6808b4SNaveen Mamindlapalli 
1995e6808b4SNaveen Mamindlapalli 	if (parent->level == NIX_TXSCH_LVL_MDQ)
2005e6808b4SNaveen Mamindlapalli 		return 0;
2015e6808b4SNaveen Mamindlapalli 
2025e6808b4SNaveen Mamindlapalli 	mutex_lock(&mbox->lock);
2035e6808b4SNaveen Mamindlapalli 
2045e6808b4SNaveen Mamindlapalli 	cfg = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
2055e6808b4SNaveen Mamindlapalli 	if (!cfg) {
2065e6808b4SNaveen Mamindlapalli 		mutex_unlock(&mbox->lock);
2075e6808b4SNaveen Mamindlapalli 		return -ENOMEM;
2085e6808b4SNaveen Mamindlapalli 	}
2095e6808b4SNaveen Mamindlapalli 
2105e6808b4SNaveen Mamindlapalli 	cfg->lvl = parent->level;
2115e6808b4SNaveen Mamindlapalli 
2125e6808b4SNaveen Mamindlapalli 	if (parent->level == NIX_TXSCH_LVL_TL4)
2135e6808b4SNaveen Mamindlapalli 		cfg->reg[0] = NIX_AF_TL4X_TOPOLOGY(parent->schq);
2145e6808b4SNaveen Mamindlapalli 	else if (parent->level == NIX_TXSCH_LVL_TL3)
2155e6808b4SNaveen Mamindlapalli 		cfg->reg[0] = NIX_AF_TL3X_TOPOLOGY(parent->schq);
2165e6808b4SNaveen Mamindlapalli 	else if (parent->level == NIX_TXSCH_LVL_TL2)
2175e6808b4SNaveen Mamindlapalli 		cfg->reg[0] = NIX_AF_TL2X_TOPOLOGY(parent->schq);
2185e6808b4SNaveen Mamindlapalli 	else if (parent->level == NIX_TXSCH_LVL_TL1)
2195e6808b4SNaveen Mamindlapalli 		cfg->reg[0] = NIX_AF_TL1X_TOPOLOGY(parent->schq);
2205e6808b4SNaveen Mamindlapalli 
2215e6808b4SNaveen Mamindlapalli 	cfg->regval[0] = (u64)parent->prio_anchor << 32;
22247a9656fSNaveen Mamindlapalli 	cfg->regval[0] |= ((parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO) ?
22347a9656fSNaveen Mamindlapalli 			    parent->child_dwrr_prio : 0)  << 1;
2245e6808b4SNaveen Mamindlapalli 	cfg->num_regs++;
2255e6808b4SNaveen Mamindlapalli 
2265e6808b4SNaveen Mamindlapalli 	rc = otx2_sync_mbox_msg(&pfvf->mbox);
2275e6808b4SNaveen Mamindlapalli 
2285e6808b4SNaveen Mamindlapalli 	mutex_unlock(&mbox->lock);
2295e6808b4SNaveen Mamindlapalli 
2305e6808b4SNaveen Mamindlapalli 	return rc;
2315e6808b4SNaveen Mamindlapalli }
2325e6808b4SNaveen Mamindlapalli 
2335e6808b4SNaveen Mamindlapalli static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf,
2345e6808b4SNaveen Mamindlapalli 				       struct otx2_qos_node *parent)
2355e6808b4SNaveen Mamindlapalli {
2365e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
2375e6808b4SNaveen Mamindlapalli 
2385e6808b4SNaveen Mamindlapalli 	list_for_each_entry_reverse(node, &parent->child_schq_list, list)
2395e6808b4SNaveen Mamindlapalli 		otx2_txschq_free_one(pfvf, node->level, node->schq);
2405e6808b4SNaveen Mamindlapalli }
2415e6808b4SNaveen Mamindlapalli 
2425e6808b4SNaveen Mamindlapalli static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
2435e6808b4SNaveen Mamindlapalli 				  struct otx2_qos_node *parent)
2445e6808b4SNaveen Mamindlapalli {
2455e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *tmp;
2465e6808b4SNaveen Mamindlapalli 
2475e6808b4SNaveen Mamindlapalli 	list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
2485e6808b4SNaveen Mamindlapalli 		otx2_qos_free_hw_node(pfvf, node);
2495e6808b4SNaveen Mamindlapalli 		otx2_qos_free_hw_node_schq(pfvf, node);
2505e6808b4SNaveen Mamindlapalli 		otx2_txschq_free_one(pfvf, node->level, node->schq);
2515e6808b4SNaveen Mamindlapalli 	}
2525e6808b4SNaveen Mamindlapalli }
2535e6808b4SNaveen Mamindlapalli 
2545e6808b4SNaveen Mamindlapalli static void otx2_qos_free_hw_cfg(struct otx2_nic *pfvf,
2555e6808b4SNaveen Mamindlapalli 				 struct otx2_qos_node *node)
2565e6808b4SNaveen Mamindlapalli {
2575e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
2585e6808b4SNaveen Mamindlapalli 
2595e6808b4SNaveen Mamindlapalli 	/* free child node hw mappings */
2605e6808b4SNaveen Mamindlapalli 	otx2_qos_free_hw_node(pfvf, node);
2615e6808b4SNaveen Mamindlapalli 	otx2_qos_free_hw_node_schq(pfvf, node);
2625e6808b4SNaveen Mamindlapalli 
2635e6808b4SNaveen Mamindlapalli 	/* free node hw mappings */
2645e6808b4SNaveen Mamindlapalli 	otx2_txschq_free_one(pfvf, node->level, node->schq);
2655e6808b4SNaveen Mamindlapalli 
2665e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
2675e6808b4SNaveen Mamindlapalli }
2685e6808b4SNaveen Mamindlapalli 
2695e6808b4SNaveen Mamindlapalli static void otx2_qos_sw_node_delete(struct otx2_nic *pfvf,
2705e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_node *node)
2715e6808b4SNaveen Mamindlapalli {
2725e6808b4SNaveen Mamindlapalli 	hash_del_rcu(&node->hlist);
2735e6808b4SNaveen Mamindlapalli 
2745e6808b4SNaveen Mamindlapalli 	if (node->qid != OTX2_QOS_QID_INNER && node->qid != OTX2_QOS_QID_NONE) {
2755e6808b4SNaveen Mamindlapalli 		__clear_bit(node->qid, pfvf->qos.qos_sq_bmap);
2765e6808b4SNaveen Mamindlapalli 		otx2_qos_update_tx_netdev_queues(pfvf);
2775e6808b4SNaveen Mamindlapalli 	}
2785e6808b4SNaveen Mamindlapalli 
2795e6808b4SNaveen Mamindlapalli 	list_del(&node->list);
2805e6808b4SNaveen Mamindlapalli 	kfree(node);
2815e6808b4SNaveen Mamindlapalli }
2825e6808b4SNaveen Mamindlapalli 
2835e6808b4SNaveen Mamindlapalli static void otx2_qos_free_sw_node_schq(struct otx2_nic *pfvf,
2845e6808b4SNaveen Mamindlapalli 				       struct otx2_qos_node *parent)
2855e6808b4SNaveen Mamindlapalli {
2865e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *tmp;
2875e6808b4SNaveen Mamindlapalli 
2885e6808b4SNaveen Mamindlapalli 	list_for_each_entry_safe(node, tmp, &parent->child_schq_list, list) {
2895e6808b4SNaveen Mamindlapalli 		list_del(&node->list);
2905e6808b4SNaveen Mamindlapalli 		kfree(node);
2915e6808b4SNaveen Mamindlapalli 	}
2925e6808b4SNaveen Mamindlapalli }
2935e6808b4SNaveen Mamindlapalli 
2945e6808b4SNaveen Mamindlapalli static void __otx2_qos_free_sw_node(struct otx2_nic *pfvf,
2955e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_node *parent)
2965e6808b4SNaveen Mamindlapalli {
2975e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *tmp;
2985e6808b4SNaveen Mamindlapalli 
2995e6808b4SNaveen Mamindlapalli 	list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
3005e6808b4SNaveen Mamindlapalli 		__otx2_qos_free_sw_node(pfvf, node);
3015e6808b4SNaveen Mamindlapalli 		otx2_qos_free_sw_node_schq(pfvf, node);
3025e6808b4SNaveen Mamindlapalli 		otx2_qos_sw_node_delete(pfvf, node);
3035e6808b4SNaveen Mamindlapalli 	}
3045e6808b4SNaveen Mamindlapalli }
3055e6808b4SNaveen Mamindlapalli 
3065e6808b4SNaveen Mamindlapalli static void otx2_qos_free_sw_node(struct otx2_nic *pfvf,
3075e6808b4SNaveen Mamindlapalli 				  struct otx2_qos_node *node)
3085e6808b4SNaveen Mamindlapalli {
3095e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
3105e6808b4SNaveen Mamindlapalli 
3115e6808b4SNaveen Mamindlapalli 	__otx2_qos_free_sw_node(pfvf, node);
3125e6808b4SNaveen Mamindlapalli 	otx2_qos_free_sw_node_schq(pfvf, node);
3135e6808b4SNaveen Mamindlapalli 	otx2_qos_sw_node_delete(pfvf, node);
3145e6808b4SNaveen Mamindlapalli 
3155e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
3165e6808b4SNaveen Mamindlapalli }
3175e6808b4SNaveen Mamindlapalli 
3185e6808b4SNaveen Mamindlapalli static void otx2_qos_destroy_node(struct otx2_nic *pfvf,
3195e6808b4SNaveen Mamindlapalli 				  struct otx2_qos_node *node)
3205e6808b4SNaveen Mamindlapalli {
3215e6808b4SNaveen Mamindlapalli 	otx2_qos_free_hw_cfg(pfvf, node);
3225e6808b4SNaveen Mamindlapalli 	otx2_qos_free_sw_node(pfvf, node);
3235e6808b4SNaveen Mamindlapalli }
3245e6808b4SNaveen Mamindlapalli 
3255e6808b4SNaveen Mamindlapalli static void otx2_qos_fill_cfg_schq(struct otx2_qos_node *parent,
3265e6808b4SNaveen Mamindlapalli 				   struct otx2_qos_cfg *cfg)
3275e6808b4SNaveen Mamindlapalli {
3285e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
3295e6808b4SNaveen Mamindlapalli 
3305e6808b4SNaveen Mamindlapalli 	list_for_each_entry(node, &parent->child_schq_list, list)
3315e6808b4SNaveen Mamindlapalli 		cfg->schq[node->level]++;
3325e6808b4SNaveen Mamindlapalli }
3335e6808b4SNaveen Mamindlapalli 
3345e6808b4SNaveen Mamindlapalli static void otx2_qos_fill_cfg_tl(struct otx2_qos_node *parent,
3355e6808b4SNaveen Mamindlapalli 				 struct otx2_qos_cfg *cfg)
3365e6808b4SNaveen Mamindlapalli {
3375e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
3385e6808b4SNaveen Mamindlapalli 
3395e6808b4SNaveen Mamindlapalli 	list_for_each_entry(node, &parent->child_list, list) {
3405e6808b4SNaveen Mamindlapalli 		otx2_qos_fill_cfg_tl(node, cfg);
3415e6808b4SNaveen Mamindlapalli 		otx2_qos_fill_cfg_schq(node, cfg);
3425e6808b4SNaveen Mamindlapalli 	}
343f78dca69SNaveen Mamindlapalli 
344f78dca69SNaveen Mamindlapalli 	/* Assign the required number of transmit schedular queues under the
345f78dca69SNaveen Mamindlapalli 	 * given class
346f78dca69SNaveen Mamindlapalli 	 */
347f78dca69SNaveen Mamindlapalli 	cfg->schq_contig[parent->level - 1] += parent->child_dwrr_cnt +
348f78dca69SNaveen Mamindlapalli 					       parent->max_static_prio + 1;
3495e6808b4SNaveen Mamindlapalli }
3505e6808b4SNaveen Mamindlapalli 
3515e6808b4SNaveen Mamindlapalli static void otx2_qos_prepare_txschq_cfg(struct otx2_nic *pfvf,
3525e6808b4SNaveen Mamindlapalli 					struct otx2_qos_node *parent,
3535e6808b4SNaveen Mamindlapalli 					struct otx2_qos_cfg *cfg)
3545e6808b4SNaveen Mamindlapalli {
3555e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
3565e6808b4SNaveen Mamindlapalli 	otx2_qos_fill_cfg_tl(parent, cfg);
3575e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
3585e6808b4SNaveen Mamindlapalli }
3595e6808b4SNaveen Mamindlapalli 
3605e6808b4SNaveen Mamindlapalli static void otx2_qos_read_txschq_cfg_schq(struct otx2_qos_node *parent,
3615e6808b4SNaveen Mamindlapalli 					  struct otx2_qos_cfg *cfg)
3625e6808b4SNaveen Mamindlapalli {
3635e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
3645e6808b4SNaveen Mamindlapalli 	int cnt;
3655e6808b4SNaveen Mamindlapalli 
3665e6808b4SNaveen Mamindlapalli 	list_for_each_entry(node, &parent->child_schq_list, list) {
3675e6808b4SNaveen Mamindlapalli 		cnt = cfg->dwrr_node_pos[node->level];
3685e6808b4SNaveen Mamindlapalli 		cfg->schq_list[node->level][cnt] = node->schq;
3695e6808b4SNaveen Mamindlapalli 		cfg->schq[node->level]++;
3705e6808b4SNaveen Mamindlapalli 		cfg->dwrr_node_pos[node->level]++;
3715e6808b4SNaveen Mamindlapalli 	}
3725e6808b4SNaveen Mamindlapalli }
3735e6808b4SNaveen Mamindlapalli 
3745e6808b4SNaveen Mamindlapalli static void otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node *parent,
3755e6808b4SNaveen Mamindlapalli 					struct otx2_qos_cfg *cfg)
3765e6808b4SNaveen Mamindlapalli {
3775e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
3785e6808b4SNaveen Mamindlapalli 	int cnt;
3795e6808b4SNaveen Mamindlapalli 
3805e6808b4SNaveen Mamindlapalli 	list_for_each_entry(node, &parent->child_list, list) {
3815e6808b4SNaveen Mamindlapalli 		otx2_qos_read_txschq_cfg_tl(node, cfg);
3825e6808b4SNaveen Mamindlapalli 		cnt = cfg->static_node_pos[node->level];
3835e6808b4SNaveen Mamindlapalli 		cfg->schq_contig_list[node->level][cnt] = node->schq;
384bccb798eSHariprasad Kelam 		cfg->schq_index_used[node->level][cnt] = true;
3855e6808b4SNaveen Mamindlapalli 		cfg->schq_contig[node->level]++;
3865e6808b4SNaveen Mamindlapalli 		cfg->static_node_pos[node->level]++;
3875e6808b4SNaveen Mamindlapalli 		otx2_qos_read_txschq_cfg_schq(node, cfg);
3885e6808b4SNaveen Mamindlapalli 	}
3895e6808b4SNaveen Mamindlapalli }
3905e6808b4SNaveen Mamindlapalli 
3915e6808b4SNaveen Mamindlapalli static void otx2_qos_read_txschq_cfg(struct otx2_nic *pfvf,
3925e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_node *node,
3935e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_cfg *cfg)
3945e6808b4SNaveen Mamindlapalli {
3955e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
3965e6808b4SNaveen Mamindlapalli 	otx2_qos_read_txschq_cfg_tl(node, cfg);
3975e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
3985e6808b4SNaveen Mamindlapalli }
3995e6808b4SNaveen Mamindlapalli 
4005e6808b4SNaveen Mamindlapalli static struct otx2_qos_node *
4015e6808b4SNaveen Mamindlapalli otx2_qos_alloc_root(struct otx2_nic *pfvf)
4025e6808b4SNaveen Mamindlapalli {
4035e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
4045e6808b4SNaveen Mamindlapalli 
4055e6808b4SNaveen Mamindlapalli 	node = kzalloc(sizeof(*node), GFP_KERNEL);
4065e6808b4SNaveen Mamindlapalli 	if (!node)
4075e6808b4SNaveen Mamindlapalli 		return ERR_PTR(-ENOMEM);
4085e6808b4SNaveen Mamindlapalli 
4095e6808b4SNaveen Mamindlapalli 	node->parent = NULL;
41047a9656fSNaveen Mamindlapalli 	if (!is_otx2_vf(pfvf->pcifunc)) {
4115e6808b4SNaveen Mamindlapalli 		node->level = NIX_TXSCH_LVL_TL1;
41247a9656fSNaveen Mamindlapalli 	} else {
4135e6808b4SNaveen Mamindlapalli 		node->level = NIX_TXSCH_LVL_TL2;
41447a9656fSNaveen Mamindlapalli 		node->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO;
41547a9656fSNaveen Mamindlapalli 	}
4165e6808b4SNaveen Mamindlapalli 
4175e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER);
4185e6808b4SNaveen Mamindlapalli 	node->classid = OTX2_QOS_ROOT_CLASSID;
4195e6808b4SNaveen Mamindlapalli 
4205e6808b4SNaveen Mamindlapalli 	hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, node->classid);
4215e6808b4SNaveen Mamindlapalli 	list_add_tail(&node->list, &pfvf->qos.qos_tree);
4225e6808b4SNaveen Mamindlapalli 	INIT_LIST_HEAD(&node->child_list);
4235e6808b4SNaveen Mamindlapalli 	INIT_LIST_HEAD(&node->child_schq_list);
4245e6808b4SNaveen Mamindlapalli 
4255e6808b4SNaveen Mamindlapalli 	return node;
4265e6808b4SNaveen Mamindlapalli }
4275e6808b4SNaveen Mamindlapalli 
4285e6808b4SNaveen Mamindlapalli static int otx2_qos_add_child_node(struct otx2_qos_node *parent,
4295e6808b4SNaveen Mamindlapalli 				   struct otx2_qos_node *node)
4305e6808b4SNaveen Mamindlapalli {
4315e6808b4SNaveen Mamindlapalli 	struct list_head *head = &parent->child_list;
4325e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp_node;
4335e6808b4SNaveen Mamindlapalli 	struct list_head *tmp;
4345e6808b4SNaveen Mamindlapalli 
435f78dca69SNaveen Mamindlapalli 	if (node->prio > parent->max_static_prio)
436f78dca69SNaveen Mamindlapalli 		parent->max_static_prio = node->prio;
437f78dca69SNaveen Mamindlapalli 
4385e6808b4SNaveen Mamindlapalli 	for (tmp = head->next; tmp != head; tmp = tmp->next) {
4395e6808b4SNaveen Mamindlapalli 		tmp_node = list_entry(tmp, struct otx2_qos_node, list);
440f78dca69SNaveen Mamindlapalli 		if (tmp_node->prio == node->prio &&
441f78dca69SNaveen Mamindlapalli 		    tmp_node->is_static)
4425e6808b4SNaveen Mamindlapalli 			return -EEXIST;
4435e6808b4SNaveen Mamindlapalli 		if (tmp_node->prio > node->prio) {
4445e6808b4SNaveen Mamindlapalli 			list_add_tail(&node->list, tmp);
4455e6808b4SNaveen Mamindlapalli 			return 0;
4465e6808b4SNaveen Mamindlapalli 		}
4475e6808b4SNaveen Mamindlapalli 	}
4485e6808b4SNaveen Mamindlapalli 
4495e6808b4SNaveen Mamindlapalli 	list_add_tail(&node->list, head);
4505e6808b4SNaveen Mamindlapalli 	return 0;
4515e6808b4SNaveen Mamindlapalli }
4525e6808b4SNaveen Mamindlapalli 
4535e6808b4SNaveen Mamindlapalli static int otx2_qos_alloc_txschq_node(struct otx2_nic *pfvf,
4545e6808b4SNaveen Mamindlapalli 				      struct otx2_qos_node *node)
4555e6808b4SNaveen Mamindlapalli {
4565e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *txschq_node, *parent, *tmp;
4575e6808b4SNaveen Mamindlapalli 	int lvl;
4585e6808b4SNaveen Mamindlapalli 
4595e6808b4SNaveen Mamindlapalli 	parent = node;
4605e6808b4SNaveen Mamindlapalli 	for (lvl = node->level - 1; lvl >= NIX_TXSCH_LVL_MDQ; lvl--) {
4615e6808b4SNaveen Mamindlapalli 		txschq_node = kzalloc(sizeof(*txschq_node), GFP_KERNEL);
4625e6808b4SNaveen Mamindlapalli 		if (!txschq_node)
4635e6808b4SNaveen Mamindlapalli 			goto err_out;
4645e6808b4SNaveen Mamindlapalli 
4655e6808b4SNaveen Mamindlapalli 		txschq_node->parent = parent;
4665e6808b4SNaveen Mamindlapalli 		txschq_node->level = lvl;
4675e6808b4SNaveen Mamindlapalli 		txschq_node->classid = OTX2_QOS_CLASS_NONE;
4685e6808b4SNaveen Mamindlapalli 		WRITE_ONCE(txschq_node->qid, OTX2_QOS_QID_NONE);
4695e6808b4SNaveen Mamindlapalli 		txschq_node->rate = 0;
4705e6808b4SNaveen Mamindlapalli 		txschq_node->ceil = 0;
4715e6808b4SNaveen Mamindlapalli 		txschq_node->prio = 0;
47247a9656fSNaveen Mamindlapalli 		txschq_node->quantum = 0;
47347a9656fSNaveen Mamindlapalli 		txschq_node->is_static = true;
47447a9656fSNaveen Mamindlapalli 		txschq_node->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO;
47547a9656fSNaveen Mamindlapalli 		txschq_node->txschq_idx = OTX2_QOS_INVALID_TXSCHQ_IDX;
4765e6808b4SNaveen Mamindlapalli 
4775e6808b4SNaveen Mamindlapalli 		mutex_lock(&pfvf->qos.qos_lock);
4785e6808b4SNaveen Mamindlapalli 		list_add_tail(&txschq_node->list, &node->child_schq_list);
4795e6808b4SNaveen Mamindlapalli 		mutex_unlock(&pfvf->qos.qos_lock);
4805e6808b4SNaveen Mamindlapalli 
4815e6808b4SNaveen Mamindlapalli 		INIT_LIST_HEAD(&txschq_node->child_list);
4825e6808b4SNaveen Mamindlapalli 		INIT_LIST_HEAD(&txschq_node->child_schq_list);
4835e6808b4SNaveen Mamindlapalli 		parent = txschq_node;
4845e6808b4SNaveen Mamindlapalli 	}
4855e6808b4SNaveen Mamindlapalli 
4865e6808b4SNaveen Mamindlapalli 	return 0;
4875e6808b4SNaveen Mamindlapalli 
4885e6808b4SNaveen Mamindlapalli err_out:
4895e6808b4SNaveen Mamindlapalli 	list_for_each_entry_safe(txschq_node, tmp, &node->child_schq_list,
4905e6808b4SNaveen Mamindlapalli 				 list) {
4915e6808b4SNaveen Mamindlapalli 		list_del(&txschq_node->list);
4925e6808b4SNaveen Mamindlapalli 		kfree(txschq_node);
4935e6808b4SNaveen Mamindlapalli 	}
4945e6808b4SNaveen Mamindlapalli 	return -ENOMEM;
4955e6808b4SNaveen Mamindlapalli }
4965e6808b4SNaveen Mamindlapalli 
4975e6808b4SNaveen Mamindlapalli static struct otx2_qos_node *
4985e6808b4SNaveen Mamindlapalli otx2_qos_sw_create_leaf_node(struct otx2_nic *pfvf,
4995e6808b4SNaveen Mamindlapalli 			     struct otx2_qos_node *parent,
5005e6808b4SNaveen Mamindlapalli 			     u16 classid, u32 prio, u64 rate, u64 ceil,
50147a9656fSNaveen Mamindlapalli 			     u32 quantum, u16 qid, bool static_cfg)
5025e6808b4SNaveen Mamindlapalli {
5035e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
5045e6808b4SNaveen Mamindlapalli 	int err;
5055e6808b4SNaveen Mamindlapalli 
5065e6808b4SNaveen Mamindlapalli 	node = kzalloc(sizeof(*node), GFP_KERNEL);
5075e6808b4SNaveen Mamindlapalli 	if (!node)
5085e6808b4SNaveen Mamindlapalli 		return ERR_PTR(-ENOMEM);
5095e6808b4SNaveen Mamindlapalli 
5105e6808b4SNaveen Mamindlapalli 	node->parent = parent;
5115e6808b4SNaveen Mamindlapalli 	node->level = parent->level - 1;
5125e6808b4SNaveen Mamindlapalli 	node->classid = classid;
5135e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(node->qid, qid);
5145e6808b4SNaveen Mamindlapalli 
5155e6808b4SNaveen Mamindlapalli 	node->rate = otx2_convert_rate(rate);
5165e6808b4SNaveen Mamindlapalli 	node->ceil = otx2_convert_rate(ceil);
5175e6808b4SNaveen Mamindlapalli 	node->prio = prio;
51847a9656fSNaveen Mamindlapalli 	node->quantum = quantum;
51947a9656fSNaveen Mamindlapalli 	node->is_static = static_cfg;
52047a9656fSNaveen Mamindlapalli 	node->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO;
52147a9656fSNaveen Mamindlapalli 	node->txschq_idx = OTX2_QOS_INVALID_TXSCHQ_IDX;
5225e6808b4SNaveen Mamindlapalli 
5235e6808b4SNaveen Mamindlapalli 	__set_bit(qid, pfvf->qos.qos_sq_bmap);
5245e6808b4SNaveen Mamindlapalli 
5255e6808b4SNaveen Mamindlapalli 	hash_add_rcu(pfvf->qos.qos_hlist, &node->hlist, classid);
5265e6808b4SNaveen Mamindlapalli 
5275e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
5285e6808b4SNaveen Mamindlapalli 	err = otx2_qos_add_child_node(parent, node);
5295e6808b4SNaveen Mamindlapalli 	if (err) {
5305e6808b4SNaveen Mamindlapalli 		mutex_unlock(&pfvf->qos.qos_lock);
5315e6808b4SNaveen Mamindlapalli 		return ERR_PTR(err);
5325e6808b4SNaveen Mamindlapalli 	}
5335e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
5345e6808b4SNaveen Mamindlapalli 
5355e6808b4SNaveen Mamindlapalli 	INIT_LIST_HEAD(&node->child_list);
5365e6808b4SNaveen Mamindlapalli 	INIT_LIST_HEAD(&node->child_schq_list);
5375e6808b4SNaveen Mamindlapalli 
5385e6808b4SNaveen Mamindlapalli 	err = otx2_qos_alloc_txschq_node(pfvf, node);
5395e6808b4SNaveen Mamindlapalli 	if (err) {
5405e6808b4SNaveen Mamindlapalli 		otx2_qos_sw_node_delete(pfvf, node);
5415e6808b4SNaveen Mamindlapalli 		return ERR_PTR(-ENOMEM);
5425e6808b4SNaveen Mamindlapalli 	}
5435e6808b4SNaveen Mamindlapalli 
5445e6808b4SNaveen Mamindlapalli 	return node;
5455e6808b4SNaveen Mamindlapalli }
5465e6808b4SNaveen Mamindlapalli 
54704fb71ccSHariprasad Kelam static struct otx2_qos_node
54804fb71ccSHariprasad Kelam *otx2_sw_node_find_by_qid(struct otx2_nic *pfvf, u16 qid)
54904fb71ccSHariprasad Kelam {
55004fb71ccSHariprasad Kelam 	struct otx2_qos_node *node = NULL;
55104fb71ccSHariprasad Kelam 	int bkt;
55204fb71ccSHariprasad Kelam 
55304fb71ccSHariprasad Kelam 	hash_for_each(pfvf->qos.qos_hlist, bkt, node, hlist) {
55404fb71ccSHariprasad Kelam 		if (node->qid == qid)
55504fb71ccSHariprasad Kelam 			break;
55604fb71ccSHariprasad Kelam 	}
55704fb71ccSHariprasad Kelam 
55804fb71ccSHariprasad Kelam 	return node;
55904fb71ccSHariprasad Kelam }
56004fb71ccSHariprasad Kelam 
5615e6808b4SNaveen Mamindlapalli static struct otx2_qos_node *
5625e6808b4SNaveen Mamindlapalli otx2_sw_node_find(struct otx2_nic *pfvf, u32 classid)
5635e6808b4SNaveen Mamindlapalli {
5645e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node = NULL;
5655e6808b4SNaveen Mamindlapalli 
5665e6808b4SNaveen Mamindlapalli 	hash_for_each_possible(pfvf->qos.qos_hlist, node, hlist, classid) {
5675e6808b4SNaveen Mamindlapalli 		if (node->classid == classid)
5685e6808b4SNaveen Mamindlapalli 			break;
5695e6808b4SNaveen Mamindlapalli 	}
5705e6808b4SNaveen Mamindlapalli 
5715e6808b4SNaveen Mamindlapalli 	return node;
5725e6808b4SNaveen Mamindlapalli }
5735e6808b4SNaveen Mamindlapalli 
5745e6808b4SNaveen Mamindlapalli static struct otx2_qos_node *
5755e6808b4SNaveen Mamindlapalli otx2_sw_node_find_rcu(struct otx2_nic *pfvf, u32 classid)
5765e6808b4SNaveen Mamindlapalli {
5775e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node = NULL;
5785e6808b4SNaveen Mamindlapalli 
5795e6808b4SNaveen Mamindlapalli 	hash_for_each_possible_rcu(pfvf->qos.qos_hlist, node, hlist, classid) {
5805e6808b4SNaveen Mamindlapalli 		if (node->classid == classid)
5815e6808b4SNaveen Mamindlapalli 			break;
5825e6808b4SNaveen Mamindlapalli 	}
5835e6808b4SNaveen Mamindlapalli 
5845e6808b4SNaveen Mamindlapalli 	return node;
5855e6808b4SNaveen Mamindlapalli }
5865e6808b4SNaveen Mamindlapalli 
5875e6808b4SNaveen Mamindlapalli int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid)
5885e6808b4SNaveen Mamindlapalli {
5895e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
5905e6808b4SNaveen Mamindlapalli 	u16 qid;
5915e6808b4SNaveen Mamindlapalli 	int res;
5925e6808b4SNaveen Mamindlapalli 
5935e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find_rcu(pfvf, classid);
5945e6808b4SNaveen Mamindlapalli 	if (!node) {
5955e6808b4SNaveen Mamindlapalli 		res = -ENOENT;
5965e6808b4SNaveen Mamindlapalli 		goto out;
5975e6808b4SNaveen Mamindlapalli 	}
5985e6808b4SNaveen Mamindlapalli 	qid = READ_ONCE(node->qid);
5995e6808b4SNaveen Mamindlapalli 	if (qid == OTX2_QOS_QID_INNER) {
6005e6808b4SNaveen Mamindlapalli 		res = -EINVAL;
6015e6808b4SNaveen Mamindlapalli 		goto out;
6025e6808b4SNaveen Mamindlapalli 	}
6035e6808b4SNaveen Mamindlapalli 	res = pfvf->hw.tx_queues + qid;
6045e6808b4SNaveen Mamindlapalli out:
6055e6808b4SNaveen Mamindlapalli 	return res;
6065e6808b4SNaveen Mamindlapalli }
6075e6808b4SNaveen Mamindlapalli 
6085e6808b4SNaveen Mamindlapalli static int
6095e6808b4SNaveen Mamindlapalli otx2_qos_txschq_config(struct otx2_nic *pfvf, struct otx2_qos_node *node)
6105e6808b4SNaveen Mamindlapalli {
6115e6808b4SNaveen Mamindlapalli 	struct mbox *mbox = &pfvf->mbox;
6125e6808b4SNaveen Mamindlapalli 	struct nix_txschq_config *req;
6135e6808b4SNaveen Mamindlapalli 	int rc;
6145e6808b4SNaveen Mamindlapalli 
6155e6808b4SNaveen Mamindlapalli 	mutex_lock(&mbox->lock);
6165e6808b4SNaveen Mamindlapalli 
6175e6808b4SNaveen Mamindlapalli 	req = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
6185e6808b4SNaveen Mamindlapalli 	if (!req) {
6195e6808b4SNaveen Mamindlapalli 		mutex_unlock(&mbox->lock);
6205e6808b4SNaveen Mamindlapalli 		return -ENOMEM;
6215e6808b4SNaveen Mamindlapalli 	}
6225e6808b4SNaveen Mamindlapalli 
6235e6808b4SNaveen Mamindlapalli 	req->lvl = node->level;
6245e6808b4SNaveen Mamindlapalli 	__otx2_qos_txschq_cfg(pfvf, node, req);
6255e6808b4SNaveen Mamindlapalli 
6265e6808b4SNaveen Mamindlapalli 	rc = otx2_sync_mbox_msg(&pfvf->mbox);
6275e6808b4SNaveen Mamindlapalli 
6285e6808b4SNaveen Mamindlapalli 	mutex_unlock(&mbox->lock);
6295e6808b4SNaveen Mamindlapalli 
6305e6808b4SNaveen Mamindlapalli 	return rc;
6315e6808b4SNaveen Mamindlapalli }
6325e6808b4SNaveen Mamindlapalli 
6335e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_alloc(struct otx2_nic *pfvf,
6345e6808b4SNaveen Mamindlapalli 				 struct otx2_qos_cfg *cfg)
6355e6808b4SNaveen Mamindlapalli {
6365e6808b4SNaveen Mamindlapalli 	struct nix_txsch_alloc_req *req;
6375e6808b4SNaveen Mamindlapalli 	struct nix_txsch_alloc_rsp *rsp;
6385e6808b4SNaveen Mamindlapalli 	struct mbox *mbox = &pfvf->mbox;
6395e6808b4SNaveen Mamindlapalli 	int lvl, rc, schq;
6405e6808b4SNaveen Mamindlapalli 
6415e6808b4SNaveen Mamindlapalli 	mutex_lock(&mbox->lock);
6425e6808b4SNaveen Mamindlapalli 	req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
6435e6808b4SNaveen Mamindlapalli 	if (!req) {
6445e6808b4SNaveen Mamindlapalli 		mutex_unlock(&mbox->lock);
6455e6808b4SNaveen Mamindlapalli 		return -ENOMEM;
6465e6808b4SNaveen Mamindlapalli 	}
6475e6808b4SNaveen Mamindlapalli 
6485e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
6495e6808b4SNaveen Mamindlapalli 		req->schq[lvl] = cfg->schq[lvl];
6505e6808b4SNaveen Mamindlapalli 		req->schq_contig[lvl] = cfg->schq_contig[lvl];
6515e6808b4SNaveen Mamindlapalli 	}
6525e6808b4SNaveen Mamindlapalli 
6535e6808b4SNaveen Mamindlapalli 	rc = otx2_sync_mbox_msg(&pfvf->mbox);
6545e6808b4SNaveen Mamindlapalli 	if (rc) {
6555e6808b4SNaveen Mamindlapalli 		mutex_unlock(&mbox->lock);
6565e6808b4SNaveen Mamindlapalli 		return rc;
6575e6808b4SNaveen Mamindlapalli 	}
6585e6808b4SNaveen Mamindlapalli 
6595e6808b4SNaveen Mamindlapalli 	rsp = (struct nix_txsch_alloc_rsp *)
6605e6808b4SNaveen Mamindlapalli 	      otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
6615e6808b4SNaveen Mamindlapalli 
6625e6808b4SNaveen Mamindlapalli 	if (IS_ERR(rsp)) {
6635e6808b4SNaveen Mamindlapalli 		rc = PTR_ERR(rsp);
6645e6808b4SNaveen Mamindlapalli 		goto out;
6655e6808b4SNaveen Mamindlapalli 	}
6665e6808b4SNaveen Mamindlapalli 
6675e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
6685e6808b4SNaveen Mamindlapalli 		for (schq = 0; schq < rsp->schq_contig[lvl]; schq++) {
6695e6808b4SNaveen Mamindlapalli 			cfg->schq_contig_list[lvl][schq] =
6705e6808b4SNaveen Mamindlapalli 				rsp->schq_contig_list[lvl][schq];
6715e6808b4SNaveen Mamindlapalli 		}
6725e6808b4SNaveen Mamindlapalli 	}
6735e6808b4SNaveen Mamindlapalli 
6745e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
6755e6808b4SNaveen Mamindlapalli 		for (schq = 0; schq < rsp->schq[lvl]; schq++) {
6765e6808b4SNaveen Mamindlapalli 			cfg->schq_list[lvl][schq] =
6775e6808b4SNaveen Mamindlapalli 				rsp->schq_list[lvl][schq];
6785e6808b4SNaveen Mamindlapalli 		}
6795e6808b4SNaveen Mamindlapalli 	}
6805e6808b4SNaveen Mamindlapalli 
6815e6808b4SNaveen Mamindlapalli 	pfvf->qos.link_cfg_lvl = rsp->link_cfg_lvl;
68247a9656fSNaveen Mamindlapalli 	pfvf->hw.txschq_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio;
6835e6808b4SNaveen Mamindlapalli 
6845e6808b4SNaveen Mamindlapalli out:
6855e6808b4SNaveen Mamindlapalli 	mutex_unlock(&mbox->lock);
6865e6808b4SNaveen Mamindlapalli 	return rc;
6875e6808b4SNaveen Mamindlapalli }
6885e6808b4SNaveen Mamindlapalli 
689f78dca69SNaveen Mamindlapalli static void otx2_qos_free_unused_txschq(struct otx2_nic *pfvf,
690f78dca69SNaveen Mamindlapalli 					struct otx2_qos_cfg *cfg)
691f78dca69SNaveen Mamindlapalli {
692f78dca69SNaveen Mamindlapalli 	int lvl, idx, schq;
693f78dca69SNaveen Mamindlapalli 
694f78dca69SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
695f78dca69SNaveen Mamindlapalli 		for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
696f78dca69SNaveen Mamindlapalli 			if (!cfg->schq_index_used[lvl][idx]) {
697f78dca69SNaveen Mamindlapalli 				schq = cfg->schq_contig_list[lvl][idx];
698f78dca69SNaveen Mamindlapalli 				otx2_txschq_free_one(pfvf, lvl, schq);
699f78dca69SNaveen Mamindlapalli 			}
700f78dca69SNaveen Mamindlapalli 		}
701f78dca69SNaveen Mamindlapalli 	}
702f78dca69SNaveen Mamindlapalli }
703f78dca69SNaveen Mamindlapalli 
7045e6808b4SNaveen Mamindlapalli static void otx2_qos_txschq_fill_cfg_schq(struct otx2_nic *pfvf,
7055e6808b4SNaveen Mamindlapalli 					  struct otx2_qos_node *node,
7065e6808b4SNaveen Mamindlapalli 					  struct otx2_qos_cfg *cfg)
7075e6808b4SNaveen Mamindlapalli {
7085e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
7095e6808b4SNaveen Mamindlapalli 	int cnt;
7105e6808b4SNaveen Mamindlapalli 
7115e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_schq_list, list) {
7125e6808b4SNaveen Mamindlapalli 		cnt = cfg->dwrr_node_pos[tmp->level];
7135e6808b4SNaveen Mamindlapalli 		tmp->schq = cfg->schq_list[tmp->level][cnt];
7145e6808b4SNaveen Mamindlapalli 		cfg->dwrr_node_pos[tmp->level]++;
7155e6808b4SNaveen Mamindlapalli 	}
7165e6808b4SNaveen Mamindlapalli }
7175e6808b4SNaveen Mamindlapalli 
7185e6808b4SNaveen Mamindlapalli static void otx2_qos_txschq_fill_cfg_tl(struct otx2_nic *pfvf,
7195e6808b4SNaveen Mamindlapalli 					struct otx2_qos_node *node,
7205e6808b4SNaveen Mamindlapalli 					struct otx2_qos_cfg *cfg)
7215e6808b4SNaveen Mamindlapalli {
7225e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
7235e6808b4SNaveen Mamindlapalli 	int cnt;
7245e6808b4SNaveen Mamindlapalli 
7255e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list) {
7265e6808b4SNaveen Mamindlapalli 		otx2_qos_txschq_fill_cfg_tl(pfvf, tmp, cfg);
7275e6808b4SNaveen Mamindlapalli 		cnt = cfg->static_node_pos[tmp->level];
728f78dca69SNaveen Mamindlapalli 		tmp->schq = cfg->schq_contig_list[tmp->level][tmp->txschq_idx];
729f78dca69SNaveen Mamindlapalli 		cfg->schq_index_used[tmp->level][tmp->txschq_idx] = true;
7305e6808b4SNaveen Mamindlapalli 		if (cnt == 0)
731f78dca69SNaveen Mamindlapalli 			node->prio_anchor =
732f78dca69SNaveen Mamindlapalli 				cfg->schq_contig_list[tmp->level][0];
7335e6808b4SNaveen Mamindlapalli 		cfg->static_node_pos[tmp->level]++;
7345e6808b4SNaveen Mamindlapalli 		otx2_qos_txschq_fill_cfg_schq(pfvf, tmp, cfg);
7355e6808b4SNaveen Mamindlapalli 	}
7365e6808b4SNaveen Mamindlapalli }
7375e6808b4SNaveen Mamindlapalli 
7385e6808b4SNaveen Mamindlapalli static void otx2_qos_txschq_fill_cfg(struct otx2_nic *pfvf,
7395e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_node *node,
7405e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_cfg *cfg)
7415e6808b4SNaveen Mamindlapalli {
7425e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
7435e6808b4SNaveen Mamindlapalli 	otx2_qos_txschq_fill_cfg_tl(pfvf, node, cfg);
7445e6808b4SNaveen Mamindlapalli 	otx2_qos_txschq_fill_cfg_schq(pfvf, node, cfg);
745f78dca69SNaveen Mamindlapalli 	otx2_qos_free_unused_txschq(pfvf, cfg);
7465e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
7475e6808b4SNaveen Mamindlapalli }
7485e6808b4SNaveen Mamindlapalli 
749f78dca69SNaveen Mamindlapalli static void __otx2_qos_assign_base_idx_tl(struct otx2_nic *pfvf,
750f78dca69SNaveen Mamindlapalli 					  struct otx2_qos_node *tmp,
751f78dca69SNaveen Mamindlapalli 					  unsigned long *child_idx_bmap,
752f78dca69SNaveen Mamindlapalli 					  int child_cnt)
753f78dca69SNaveen Mamindlapalli {
754f78dca69SNaveen Mamindlapalli 	int idx;
755f78dca69SNaveen Mamindlapalli 
756f78dca69SNaveen Mamindlapalli 	if (tmp->txschq_idx != OTX2_QOS_INVALID_TXSCHQ_IDX)
757f78dca69SNaveen Mamindlapalli 		return;
758f78dca69SNaveen Mamindlapalli 
759f78dca69SNaveen Mamindlapalli 	/* assign static nodes 1:1 prio mapping first, then remaining nodes */
760f78dca69SNaveen Mamindlapalli 	for (idx = 0; idx < child_cnt; idx++) {
761f78dca69SNaveen Mamindlapalli 		if (tmp->is_static && tmp->prio == idx &&
762f78dca69SNaveen Mamindlapalli 		    !test_bit(idx, child_idx_bmap)) {
763f78dca69SNaveen Mamindlapalli 			tmp->txschq_idx = idx;
764f78dca69SNaveen Mamindlapalli 			set_bit(idx, child_idx_bmap);
765f78dca69SNaveen Mamindlapalli 			return;
766f78dca69SNaveen Mamindlapalli 		} else if (!tmp->is_static && idx >= tmp->prio &&
767f78dca69SNaveen Mamindlapalli 			   !test_bit(idx, child_idx_bmap)) {
768f78dca69SNaveen Mamindlapalli 			tmp->txschq_idx = idx;
769f78dca69SNaveen Mamindlapalli 			set_bit(idx, child_idx_bmap);
770f78dca69SNaveen Mamindlapalli 			return;
771f78dca69SNaveen Mamindlapalli 		}
772f78dca69SNaveen Mamindlapalli 	}
773f78dca69SNaveen Mamindlapalli }
774f78dca69SNaveen Mamindlapalli 
775f78dca69SNaveen Mamindlapalli static int otx2_qos_assign_base_idx_tl(struct otx2_nic *pfvf,
776f78dca69SNaveen Mamindlapalli 				       struct otx2_qos_node *node)
777f78dca69SNaveen Mamindlapalli {
778f78dca69SNaveen Mamindlapalli 	unsigned long *child_idx_bmap;
779f78dca69SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
780f78dca69SNaveen Mamindlapalli 	int child_cnt;
781f78dca69SNaveen Mamindlapalli 
782f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list)
783f78dca69SNaveen Mamindlapalli 		tmp->txschq_idx = OTX2_QOS_INVALID_TXSCHQ_IDX;
784f78dca69SNaveen Mamindlapalli 
785f78dca69SNaveen Mamindlapalli 	/* allocate child index array */
786f78dca69SNaveen Mamindlapalli 	child_cnt = node->child_dwrr_cnt + node->max_static_prio + 1;
787f78dca69SNaveen Mamindlapalli 	child_idx_bmap = kcalloc(BITS_TO_LONGS(child_cnt),
788f78dca69SNaveen Mamindlapalli 				 sizeof(unsigned long),
789f78dca69SNaveen Mamindlapalli 				 GFP_KERNEL);
790f78dca69SNaveen Mamindlapalli 	if (!child_idx_bmap)
791f78dca69SNaveen Mamindlapalli 		return -ENOMEM;
792f78dca69SNaveen Mamindlapalli 
793f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list)
794f78dca69SNaveen Mamindlapalli 		otx2_qos_assign_base_idx_tl(pfvf, tmp);
795f78dca69SNaveen Mamindlapalli 
796f78dca69SNaveen Mamindlapalli 	/* assign base index of static priority children first */
797f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list) {
798f78dca69SNaveen Mamindlapalli 		if (!tmp->is_static)
799f78dca69SNaveen Mamindlapalli 			continue;
800f78dca69SNaveen Mamindlapalli 		__otx2_qos_assign_base_idx_tl(pfvf, tmp, child_idx_bmap,
801f78dca69SNaveen Mamindlapalli 					      child_cnt);
802f78dca69SNaveen Mamindlapalli 	}
803f78dca69SNaveen Mamindlapalli 
804f78dca69SNaveen Mamindlapalli 	/* assign base index of dwrr priority children */
805f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list)
806f78dca69SNaveen Mamindlapalli 		__otx2_qos_assign_base_idx_tl(pfvf, tmp, child_idx_bmap,
807f78dca69SNaveen Mamindlapalli 					      child_cnt);
808f78dca69SNaveen Mamindlapalli 
809f78dca69SNaveen Mamindlapalli 	kfree(child_idx_bmap);
810f78dca69SNaveen Mamindlapalli 
811f78dca69SNaveen Mamindlapalli 	return 0;
812f78dca69SNaveen Mamindlapalli }
813f78dca69SNaveen Mamindlapalli 
814f78dca69SNaveen Mamindlapalli static int otx2_qos_assign_base_idx(struct otx2_nic *pfvf,
815f78dca69SNaveen Mamindlapalli 				    struct otx2_qos_node *node)
816f78dca69SNaveen Mamindlapalli {
817f78dca69SNaveen Mamindlapalli 	int ret = 0;
818f78dca69SNaveen Mamindlapalli 
819f78dca69SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
820f78dca69SNaveen Mamindlapalli 	ret = otx2_qos_assign_base_idx_tl(pfvf, node);
821f78dca69SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
822f78dca69SNaveen Mamindlapalli 
823f78dca69SNaveen Mamindlapalli 	return ret;
824f78dca69SNaveen Mamindlapalli }
825f78dca69SNaveen Mamindlapalli 
8265e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_push_cfg_schq(struct otx2_nic *pfvf,
8275e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_node *node,
8285e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_cfg *cfg)
8295e6808b4SNaveen Mamindlapalli {
8305e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
8315e6808b4SNaveen Mamindlapalli 	int ret;
8325e6808b4SNaveen Mamindlapalli 
8335e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_schq_list, list) {
8345e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_config(pfvf, tmp);
8355e6808b4SNaveen Mamindlapalli 		if (ret)
8365e6808b4SNaveen Mamindlapalli 			return -EIO;
8375e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_set_parent_topology(pfvf, tmp->parent);
8385e6808b4SNaveen Mamindlapalli 		if (ret)
8395e6808b4SNaveen Mamindlapalli 			return -EIO;
8405e6808b4SNaveen Mamindlapalli 	}
8415e6808b4SNaveen Mamindlapalli 
8425e6808b4SNaveen Mamindlapalli 	return 0;
8435e6808b4SNaveen Mamindlapalli }
8445e6808b4SNaveen Mamindlapalli 
8455e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_push_cfg_tl(struct otx2_nic *pfvf,
8465e6808b4SNaveen Mamindlapalli 				       struct otx2_qos_node *node,
8475e6808b4SNaveen Mamindlapalli 				       struct otx2_qos_cfg *cfg)
8485e6808b4SNaveen Mamindlapalli {
8495e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
8505e6808b4SNaveen Mamindlapalli 	int ret;
8515e6808b4SNaveen Mamindlapalli 
8525e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list) {
8535e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_push_cfg_tl(pfvf, tmp, cfg);
8545e6808b4SNaveen Mamindlapalli 		if (ret)
8555e6808b4SNaveen Mamindlapalli 			return -EIO;
8565e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_config(pfvf, tmp);
8575e6808b4SNaveen Mamindlapalli 		if (ret)
8585e6808b4SNaveen Mamindlapalli 			return -EIO;
8595e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_push_cfg_schq(pfvf, tmp, cfg);
8605e6808b4SNaveen Mamindlapalli 		if (ret)
8615e6808b4SNaveen Mamindlapalli 			return -EIO;
8625e6808b4SNaveen Mamindlapalli 	}
8635e6808b4SNaveen Mamindlapalli 
8645e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_set_parent_topology(pfvf, node);
8655e6808b4SNaveen Mamindlapalli 	if (ret)
8665e6808b4SNaveen Mamindlapalli 		return -EIO;
8675e6808b4SNaveen Mamindlapalli 
8685e6808b4SNaveen Mamindlapalli 	return 0;
8695e6808b4SNaveen Mamindlapalli }
8705e6808b4SNaveen Mamindlapalli 
8715e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_push_cfg(struct otx2_nic *pfvf,
8725e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_node *node,
8735e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_cfg *cfg)
8745e6808b4SNaveen Mamindlapalli {
8755e6808b4SNaveen Mamindlapalli 	int ret;
8765e6808b4SNaveen Mamindlapalli 
8775e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
8785e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_push_cfg_tl(pfvf, node, cfg);
8795e6808b4SNaveen Mamindlapalli 	if (ret)
8805e6808b4SNaveen Mamindlapalli 		goto out;
8815e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_push_cfg_schq(pfvf, node, cfg);
8825e6808b4SNaveen Mamindlapalli out:
8835e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
8845e6808b4SNaveen Mamindlapalli 	return ret;
8855e6808b4SNaveen Mamindlapalli }
8865e6808b4SNaveen Mamindlapalli 
8875e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_update_config(struct otx2_nic *pfvf,
8885e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_node *node,
8895e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_cfg *cfg)
8905e6808b4SNaveen Mamindlapalli {
8915e6808b4SNaveen Mamindlapalli 	otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
8925e6808b4SNaveen Mamindlapalli 
8935e6808b4SNaveen Mamindlapalli 	return otx2_qos_txschq_push_cfg(pfvf, node, cfg);
8945e6808b4SNaveen Mamindlapalli }
8955e6808b4SNaveen Mamindlapalli 
8965e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_update_root_cfg(struct otx2_nic *pfvf,
8975e6808b4SNaveen Mamindlapalli 					   struct otx2_qos_node *root,
8985e6808b4SNaveen Mamindlapalli 					   struct otx2_qos_cfg *cfg)
8995e6808b4SNaveen Mamindlapalli {
9005e6808b4SNaveen Mamindlapalli 	root->schq = cfg->schq_list[root->level][0];
9015e6808b4SNaveen Mamindlapalli 	return otx2_qos_txschq_config(pfvf, root);
9025e6808b4SNaveen Mamindlapalli }
9035e6808b4SNaveen Mamindlapalli 
9045e6808b4SNaveen Mamindlapalli static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
9055e6808b4SNaveen Mamindlapalli {
9065e6808b4SNaveen Mamindlapalli 	int lvl, idx, schq;
9075e6808b4SNaveen Mamindlapalli 
9085e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
9095e6808b4SNaveen Mamindlapalli 		for (idx = 0; idx < cfg->schq[lvl]; idx++) {
9105e6808b4SNaveen Mamindlapalli 			schq = cfg->schq_list[lvl][idx];
9115e6808b4SNaveen Mamindlapalli 			otx2_txschq_free_one(pfvf, lvl, schq);
9125e6808b4SNaveen Mamindlapalli 		}
9135e6808b4SNaveen Mamindlapalli 	}
9145e6808b4SNaveen Mamindlapalli 
9155e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
9165e6808b4SNaveen Mamindlapalli 		for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
917f78dca69SNaveen Mamindlapalli 			if (cfg->schq_index_used[lvl][idx]) {
9185e6808b4SNaveen Mamindlapalli 				schq = cfg->schq_contig_list[lvl][idx];
9195e6808b4SNaveen Mamindlapalli 				otx2_txschq_free_one(pfvf, lvl, schq);
9205e6808b4SNaveen Mamindlapalli 			}
9215e6808b4SNaveen Mamindlapalli 		}
9225e6808b4SNaveen Mamindlapalli 	}
923f78dca69SNaveen Mamindlapalli }
9245e6808b4SNaveen Mamindlapalli 
9255e6808b4SNaveen Mamindlapalli static void otx2_qos_enadis_sq(struct otx2_nic *pfvf,
9265e6808b4SNaveen Mamindlapalli 			       struct otx2_qos_node *node,
9275e6808b4SNaveen Mamindlapalli 			       u16 qid)
9285e6808b4SNaveen Mamindlapalli {
9295e6808b4SNaveen Mamindlapalli 	if (pfvf->qos.qid_to_sqmap[qid] != OTX2_QOS_INVALID_SQ)
9305e6808b4SNaveen Mamindlapalli 		otx2_qos_disable_sq(pfvf, qid);
9315e6808b4SNaveen Mamindlapalli 
9325e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = node->schq;
93304fb71ccSHariprasad Kelam 	otx2_qos_txschq_config(pfvf, node);
9345e6808b4SNaveen Mamindlapalli 	otx2_qos_enable_sq(pfvf, qid);
9355e6808b4SNaveen Mamindlapalli }
9365e6808b4SNaveen Mamindlapalli 
9375e6808b4SNaveen Mamindlapalli static void otx2_qos_update_smq_schq(struct otx2_nic *pfvf,
9385e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_node *node,
9395e6808b4SNaveen Mamindlapalli 				     bool action)
9405e6808b4SNaveen Mamindlapalli {
9415e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
9425e6808b4SNaveen Mamindlapalli 
9435e6808b4SNaveen Mamindlapalli 	if (node->qid == OTX2_QOS_QID_INNER)
9445e6808b4SNaveen Mamindlapalli 		return;
9455e6808b4SNaveen Mamindlapalli 
9465e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_schq_list, list) {
9475e6808b4SNaveen Mamindlapalli 		if (tmp->level == NIX_TXSCH_LVL_MDQ) {
9485e6808b4SNaveen Mamindlapalli 			if (action == QOS_SMQ_FLUSH)
9495e6808b4SNaveen Mamindlapalli 				otx2_smq_flush(pfvf, tmp->schq);
9505e6808b4SNaveen Mamindlapalli 			else
9515e6808b4SNaveen Mamindlapalli 				otx2_qos_enadis_sq(pfvf, tmp, node->qid);
9525e6808b4SNaveen Mamindlapalli 		}
9535e6808b4SNaveen Mamindlapalli 	}
9545e6808b4SNaveen Mamindlapalli }
9555e6808b4SNaveen Mamindlapalli 
9565e6808b4SNaveen Mamindlapalli static void __otx2_qos_update_smq(struct otx2_nic *pfvf,
9575e6808b4SNaveen Mamindlapalli 				  struct otx2_qos_node *node,
9585e6808b4SNaveen Mamindlapalli 				  bool action)
9595e6808b4SNaveen Mamindlapalli {
9605e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
9615e6808b4SNaveen Mamindlapalli 
9625e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list) {
9635e6808b4SNaveen Mamindlapalli 		__otx2_qos_update_smq(pfvf, tmp, action);
9645e6808b4SNaveen Mamindlapalli 		if (tmp->qid == OTX2_QOS_QID_INNER)
9655e6808b4SNaveen Mamindlapalli 			continue;
9665e6808b4SNaveen Mamindlapalli 		if (tmp->level == NIX_TXSCH_LVL_MDQ) {
9675e6808b4SNaveen Mamindlapalli 			if (action == QOS_SMQ_FLUSH)
9685e6808b4SNaveen Mamindlapalli 				otx2_smq_flush(pfvf, tmp->schq);
9695e6808b4SNaveen Mamindlapalli 			else
9705e6808b4SNaveen Mamindlapalli 				otx2_qos_enadis_sq(pfvf, tmp, tmp->qid);
9715e6808b4SNaveen Mamindlapalli 		} else {
9725e6808b4SNaveen Mamindlapalli 			otx2_qos_update_smq_schq(pfvf, tmp, action);
9735e6808b4SNaveen Mamindlapalli 		}
9745e6808b4SNaveen Mamindlapalli 	}
9755e6808b4SNaveen Mamindlapalli }
9765e6808b4SNaveen Mamindlapalli 
9775e6808b4SNaveen Mamindlapalli static void otx2_qos_update_smq(struct otx2_nic *pfvf,
9785e6808b4SNaveen Mamindlapalli 				struct otx2_qos_node *node,
9795e6808b4SNaveen Mamindlapalli 				bool action)
9805e6808b4SNaveen Mamindlapalli {
9815e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
9825e6808b4SNaveen Mamindlapalli 	__otx2_qos_update_smq(pfvf, node, action);
9835e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq_schq(pfvf, node, action);
9845e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
9855e6808b4SNaveen Mamindlapalli }
9865e6808b4SNaveen Mamindlapalli 
9875e6808b4SNaveen Mamindlapalli static int otx2_qos_push_txschq_cfg(struct otx2_nic *pfvf,
9885e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_node *node,
9895e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_cfg *cfg)
9905e6808b4SNaveen Mamindlapalli {
9915e6808b4SNaveen Mamindlapalli 	int ret;
9925e6808b4SNaveen Mamindlapalli 
9935e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_alloc(pfvf, cfg);
9945e6808b4SNaveen Mamindlapalli 	if (ret)
9955e6808b4SNaveen Mamindlapalli 		return -ENOSPC;
9965e6808b4SNaveen Mamindlapalli 
997f78dca69SNaveen Mamindlapalli 	ret = otx2_qos_assign_base_idx(pfvf, node);
998f78dca69SNaveen Mamindlapalli 	if (ret)
999f78dca69SNaveen Mamindlapalli 		return -ENOMEM;
1000f78dca69SNaveen Mamindlapalli 
10015e6808b4SNaveen Mamindlapalli 	if (!(pfvf->netdev->flags & IFF_UP)) {
10025e6808b4SNaveen Mamindlapalli 		otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
10035e6808b4SNaveen Mamindlapalli 		return 0;
10045e6808b4SNaveen Mamindlapalli 	}
10055e6808b4SNaveen Mamindlapalli 
10065e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_update_config(pfvf, node, cfg);
10075e6808b4SNaveen Mamindlapalli 	if (ret) {
10085e6808b4SNaveen Mamindlapalli 		otx2_qos_free_cfg(pfvf, cfg);
10095e6808b4SNaveen Mamindlapalli 		return -EIO;
10105e6808b4SNaveen Mamindlapalli 	}
10115e6808b4SNaveen Mamindlapalli 
10125e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
10135e6808b4SNaveen Mamindlapalli 
10145e6808b4SNaveen Mamindlapalli 	return 0;
10155e6808b4SNaveen Mamindlapalli }
10165e6808b4SNaveen Mamindlapalli 
10175e6808b4SNaveen Mamindlapalli static int otx2_qos_update_tree(struct otx2_nic *pfvf,
10185e6808b4SNaveen Mamindlapalli 				struct otx2_qos_node *node,
10195e6808b4SNaveen Mamindlapalli 				struct otx2_qos_cfg *cfg)
10205e6808b4SNaveen Mamindlapalli {
10215e6808b4SNaveen Mamindlapalli 	otx2_qos_prepare_txschq_cfg(pfvf, node->parent, cfg);
10225e6808b4SNaveen Mamindlapalli 	return otx2_qos_push_txschq_cfg(pfvf, node->parent, cfg);
10235e6808b4SNaveen Mamindlapalli }
10245e6808b4SNaveen Mamindlapalli 
10255e6808b4SNaveen Mamindlapalli static int otx2_qos_root_add(struct otx2_nic *pfvf, u16 htb_maj_id, u16 htb_defcls,
10265e6808b4SNaveen Mamindlapalli 			     struct netlink_ext_ack *extack)
10275e6808b4SNaveen Mamindlapalli {
10285e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *new_cfg;
10295e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
10305e6808b4SNaveen Mamindlapalli 	int err;
10315e6808b4SNaveen Mamindlapalli 
10325e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
10335e6808b4SNaveen Mamindlapalli 		   "TC_HTB_CREATE: handle=0x%x defcls=0x%x\n",
10345e6808b4SNaveen Mamindlapalli 		   htb_maj_id, htb_defcls);
10355e6808b4SNaveen Mamindlapalli 
10365e6808b4SNaveen Mamindlapalli 	root = otx2_qos_alloc_root(pfvf);
10375e6808b4SNaveen Mamindlapalli 	if (IS_ERR(root)) {
10385e6808b4SNaveen Mamindlapalli 		err = PTR_ERR(root);
10395e6808b4SNaveen Mamindlapalli 		return err;
10405e6808b4SNaveen Mamindlapalli 	}
10415e6808b4SNaveen Mamindlapalli 
10425e6808b4SNaveen Mamindlapalli 	/* allocate txschq queue */
10435e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
10445e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
10455e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
10465e6808b4SNaveen Mamindlapalli 		err = -ENOMEM;
10475e6808b4SNaveen Mamindlapalli 		goto free_root_node;
10485e6808b4SNaveen Mamindlapalli 	}
10495e6808b4SNaveen Mamindlapalli 	/* allocate htb root node */
10505e6808b4SNaveen Mamindlapalli 	new_cfg->schq[root->level] = 1;
10515e6808b4SNaveen Mamindlapalli 	err = otx2_qos_txschq_alloc(pfvf, new_cfg);
10525e6808b4SNaveen Mamindlapalli 	if (err) {
10535e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Error allocating txschq");
10545e6808b4SNaveen Mamindlapalli 		goto free_root_node;
10555e6808b4SNaveen Mamindlapalli 	}
10565e6808b4SNaveen Mamindlapalli 
105747a9656fSNaveen Mamindlapalli 	/* Update TL1 RR PRIO */
105847a9656fSNaveen Mamindlapalli 	if (root->level == NIX_TXSCH_LVL_TL1) {
105947a9656fSNaveen Mamindlapalli 		root->child_dwrr_prio = pfvf->hw.txschq_aggr_lvl_rr_prio;
106047a9656fSNaveen Mamindlapalli 		netdev_dbg(pfvf->netdev,
106147a9656fSNaveen Mamindlapalli 			   "TL1 DWRR Priority %d\n", root->child_dwrr_prio);
106247a9656fSNaveen Mamindlapalli 	}
106347a9656fSNaveen Mamindlapalli 
10645e6808b4SNaveen Mamindlapalli 	if (!(pfvf->netdev->flags & IFF_UP) ||
10655e6808b4SNaveen Mamindlapalli 	    root->level == NIX_TXSCH_LVL_TL1) {
10665e6808b4SNaveen Mamindlapalli 		root->schq = new_cfg->schq_list[root->level][0];
10675e6808b4SNaveen Mamindlapalli 		goto out;
10685e6808b4SNaveen Mamindlapalli 	}
10695e6808b4SNaveen Mamindlapalli 
10705e6808b4SNaveen Mamindlapalli 	/* update the txschq configuration in hw */
10715e6808b4SNaveen Mamindlapalli 	err = otx2_qos_txschq_update_root_cfg(pfvf, root, new_cfg);
10725e6808b4SNaveen Mamindlapalli 	if (err) {
10735e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack,
10745e6808b4SNaveen Mamindlapalli 				   "Error updating txschq configuration");
10755e6808b4SNaveen Mamindlapalli 		goto txschq_free;
10765e6808b4SNaveen Mamindlapalli 	}
10775e6808b4SNaveen Mamindlapalli 
10785e6808b4SNaveen Mamindlapalli out:
10795e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(pfvf->qos.defcls, htb_defcls);
10805e6808b4SNaveen Mamindlapalli 	/* Pairs with smp_load_acquire() in ndo_select_queue */
10815e6808b4SNaveen Mamindlapalli 	smp_store_release(&pfvf->qos.maj_id, htb_maj_id);
10825e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
10835e6808b4SNaveen Mamindlapalli 	return 0;
10845e6808b4SNaveen Mamindlapalli 
10855e6808b4SNaveen Mamindlapalli txschq_free:
10865e6808b4SNaveen Mamindlapalli 	otx2_qos_free_cfg(pfvf, new_cfg);
10875e6808b4SNaveen Mamindlapalli free_root_node:
10885e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
10895e6808b4SNaveen Mamindlapalli 	otx2_qos_sw_node_delete(pfvf, root);
10905e6808b4SNaveen Mamindlapalli 	return err;
10915e6808b4SNaveen Mamindlapalli }
10925e6808b4SNaveen Mamindlapalli 
10935e6808b4SNaveen Mamindlapalli static int otx2_qos_root_destroy(struct otx2_nic *pfvf)
10945e6808b4SNaveen Mamindlapalli {
10955e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
10965e6808b4SNaveen Mamindlapalli 
10975e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev, "TC_HTB_DESTROY\n");
10985e6808b4SNaveen Mamindlapalli 
10995e6808b4SNaveen Mamindlapalli 	/* find root node */
11005e6808b4SNaveen Mamindlapalli 	root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
11015e6808b4SNaveen Mamindlapalli 	if (!root)
11025e6808b4SNaveen Mamindlapalli 		return -ENOENT;
11035e6808b4SNaveen Mamindlapalli 
11045e6808b4SNaveen Mamindlapalli 	/* free the hw mappings */
11055e6808b4SNaveen Mamindlapalli 	otx2_qos_destroy_node(pfvf, root);
11065e6808b4SNaveen Mamindlapalli 
11075e6808b4SNaveen Mamindlapalli 	return 0;
11085e6808b4SNaveen Mamindlapalli }
11095e6808b4SNaveen Mamindlapalli 
111047a9656fSNaveen Mamindlapalli static int otx2_qos_validate_quantum(struct otx2_nic *pfvf, u32 quantum)
11115e6808b4SNaveen Mamindlapalli {
111247a9656fSNaveen Mamindlapalli 	u32 rr_weight = otx2_qos_quantum_to_dwrr_weight(pfvf, quantum);
111347a9656fSNaveen Mamindlapalli 	int err = 0;
111447a9656fSNaveen Mamindlapalli 
111547a9656fSNaveen Mamindlapalli 	/* Max Round robin weight supported by octeontx2 and CN10K
111647a9656fSNaveen Mamindlapalli 	 * is different. Validate accordingly
111747a9656fSNaveen Mamindlapalli 	 */
111847a9656fSNaveen Mamindlapalli 	if (is_dev_otx2(pfvf->pdev))
111947a9656fSNaveen Mamindlapalli 		err = (rr_weight > OTX2_MAX_RR_QUANTUM) ? -EINVAL : 0;
112047a9656fSNaveen Mamindlapalli 	else if	(rr_weight > CN10K_MAX_RR_WEIGHT)
112147a9656fSNaveen Mamindlapalli 		err = -EINVAL;
112247a9656fSNaveen Mamindlapalli 
112347a9656fSNaveen Mamindlapalli 	return err;
11245e6808b4SNaveen Mamindlapalli }
11255e6808b4SNaveen Mamindlapalli 
112647a9656fSNaveen Mamindlapalli static int otx2_qos_validate_dwrr_cfg(struct otx2_qos_node *parent,
112747a9656fSNaveen Mamindlapalli 				      struct netlink_ext_ack *extack,
112847a9656fSNaveen Mamindlapalli 				      struct otx2_nic *pfvf,
112947a9656fSNaveen Mamindlapalli 				      u64 prio, u64 quantum)
113047a9656fSNaveen Mamindlapalli {
113147a9656fSNaveen Mamindlapalli 	int err;
113247a9656fSNaveen Mamindlapalli 
113347a9656fSNaveen Mamindlapalli 	err = otx2_qos_validate_quantum(pfvf, quantum);
113447a9656fSNaveen Mamindlapalli 	if (err) {
113547a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Unsupported quantum value");
113647a9656fSNaveen Mamindlapalli 		return err;
113747a9656fSNaveen Mamindlapalli 	}
113847a9656fSNaveen Mamindlapalli 
113947a9656fSNaveen Mamindlapalli 	if (parent->child_dwrr_prio == OTX2_QOS_DEFAULT_PRIO) {
114047a9656fSNaveen Mamindlapalli 		parent->child_dwrr_prio = prio;
114147a9656fSNaveen Mamindlapalli 	} else if (prio != parent->child_dwrr_prio) {
114247a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Only one DWRR group is allowed");
114347a9656fSNaveen Mamindlapalli 		return -EOPNOTSUPP;
11445e6808b4SNaveen Mamindlapalli 	}
11455e6808b4SNaveen Mamindlapalli 
11465e6808b4SNaveen Mamindlapalli 	return 0;
11475e6808b4SNaveen Mamindlapalli }
11485e6808b4SNaveen Mamindlapalli 
114947a9656fSNaveen Mamindlapalli static int otx2_qos_validate_configuration(struct otx2_qos_node *parent,
115047a9656fSNaveen Mamindlapalli 					   struct netlink_ext_ack *extack,
115147a9656fSNaveen Mamindlapalli 					   struct otx2_nic *pfvf,
115247a9656fSNaveen Mamindlapalli 					   u64 prio, bool static_cfg)
115347a9656fSNaveen Mamindlapalli {
115447a9656fSNaveen Mamindlapalli 	if (prio == parent->child_dwrr_prio && static_cfg) {
115547a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "DWRR child group with same priority exists");
115647a9656fSNaveen Mamindlapalli 		return -EEXIST;
115747a9656fSNaveen Mamindlapalli 	}
115847a9656fSNaveen Mamindlapalli 
115947a9656fSNaveen Mamindlapalli 	if (static_cfg && test_bit(prio, parent->prio_bmap)) {
116047a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack,
116147a9656fSNaveen Mamindlapalli 				   "Static priority child with same priority exists");
116247a9656fSNaveen Mamindlapalli 		return -EEXIST;
116347a9656fSNaveen Mamindlapalli 	}
116447a9656fSNaveen Mamindlapalli 
116547a9656fSNaveen Mamindlapalli 	return 0;
116647a9656fSNaveen Mamindlapalli }
116747a9656fSNaveen Mamindlapalli 
116847a9656fSNaveen Mamindlapalli static void otx2_reset_dwrr_prio(struct otx2_qos_node *parent, u64 prio)
116947a9656fSNaveen Mamindlapalli {
117047a9656fSNaveen Mamindlapalli 	/* For PF, root node dwrr priority is static */
117147a9656fSNaveen Mamindlapalli 	if (parent->level == NIX_TXSCH_LVL_TL1)
117247a9656fSNaveen Mamindlapalli 		return;
117347a9656fSNaveen Mamindlapalli 
117447a9656fSNaveen Mamindlapalli 	if (parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO) {
117547a9656fSNaveen Mamindlapalli 		parent->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO;
117647a9656fSNaveen Mamindlapalli 		clear_bit(prio, parent->prio_bmap);
117747a9656fSNaveen Mamindlapalli 	}
117847a9656fSNaveen Mamindlapalli }
117947a9656fSNaveen Mamindlapalli 
118047a9656fSNaveen Mamindlapalli static bool is_qos_node_dwrr(struct otx2_qos_node *parent,
118147a9656fSNaveen Mamindlapalli 			     struct otx2_nic *pfvf,
118247a9656fSNaveen Mamindlapalli 			     u64 prio)
118347a9656fSNaveen Mamindlapalli {
118447a9656fSNaveen Mamindlapalli 	struct otx2_qos_node *node;
118547a9656fSNaveen Mamindlapalli 	bool ret = false;
118647a9656fSNaveen Mamindlapalli 
118747a9656fSNaveen Mamindlapalli 	if (parent->child_dwrr_prio == prio)
118847a9656fSNaveen Mamindlapalli 		return true;
118947a9656fSNaveen Mamindlapalli 
119047a9656fSNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
119147a9656fSNaveen Mamindlapalli 	list_for_each_entry(node, &parent->child_list, list) {
119247a9656fSNaveen Mamindlapalli 		if (prio == node->prio) {
119347a9656fSNaveen Mamindlapalli 			if (parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO &&
119447a9656fSNaveen Mamindlapalli 			    parent->child_dwrr_prio != prio)
119547a9656fSNaveen Mamindlapalli 				continue;
119647a9656fSNaveen Mamindlapalli 
119747a9656fSNaveen Mamindlapalli 			if (otx2_qos_validate_quantum(pfvf, node->quantum)) {
119847a9656fSNaveen Mamindlapalli 				netdev_err(pfvf->netdev,
119947a9656fSNaveen Mamindlapalli 					   "Unsupported quantum value for existing classid=0x%x quantum=%d prio=%d",
120047a9656fSNaveen Mamindlapalli 					    node->classid, node->quantum,
120147a9656fSNaveen Mamindlapalli 					    node->prio);
120247a9656fSNaveen Mamindlapalli 				break;
120347a9656fSNaveen Mamindlapalli 			}
120447a9656fSNaveen Mamindlapalli 			/* mark old node as dwrr */
120547a9656fSNaveen Mamindlapalli 			node->is_static = false;
120647a9656fSNaveen Mamindlapalli 			parent->child_dwrr_cnt++;
120747a9656fSNaveen Mamindlapalli 			parent->child_static_cnt--;
120847a9656fSNaveen Mamindlapalli 			ret = true;
120947a9656fSNaveen Mamindlapalli 			break;
121047a9656fSNaveen Mamindlapalli 		}
121147a9656fSNaveen Mamindlapalli 	}
121247a9656fSNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
121347a9656fSNaveen Mamindlapalli 
121447a9656fSNaveen Mamindlapalli 	return ret;
121547a9656fSNaveen Mamindlapalli }
121647a9656fSNaveen Mamindlapalli 
12175e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid,
12185e6808b4SNaveen Mamindlapalli 				     u32 parent_classid, u64 rate, u64 ceil,
121947a9656fSNaveen Mamindlapalli 				     u64 prio, u32 quantum,
122047a9656fSNaveen Mamindlapalli 				     struct netlink_ext_ack *extack)
12215e6808b4SNaveen Mamindlapalli {
12225e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *old_cfg, *new_cfg;
12235e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *parent;
12245e6808b4SNaveen Mamindlapalli 	int qid, ret, err;
122547a9656fSNaveen Mamindlapalli 	bool static_cfg;
12265e6808b4SNaveen Mamindlapalli 
12275e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
122847a9656fSNaveen Mamindlapalli 		   "TC_HTB_LEAF_ALLOC_QUEUE: classid=0x%x parent_classid=0x%x rate=%lld ceil=%lld prio=%lld quantum=%d\n",
122947a9656fSNaveen Mamindlapalli 		   classid, parent_classid, rate, ceil, prio, quantum);
12305e6808b4SNaveen Mamindlapalli 
12315e6808b4SNaveen Mamindlapalli 	if (prio > OTX2_QOS_MAX_PRIO) {
12325e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
12335e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
12345e6808b4SNaveen Mamindlapalli 		goto out;
12355e6808b4SNaveen Mamindlapalli 	}
12365e6808b4SNaveen Mamindlapalli 
123747a9656fSNaveen Mamindlapalli 	if (!quantum || quantum > INT_MAX) {
123847a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Invalid quantum, range 1 - 2147483647 bytes");
123947a9656fSNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
124047a9656fSNaveen Mamindlapalli 		goto out;
124147a9656fSNaveen Mamindlapalli 	}
124247a9656fSNaveen Mamindlapalli 
12435e6808b4SNaveen Mamindlapalli 	/* get parent node */
12445e6808b4SNaveen Mamindlapalli 	parent = otx2_sw_node_find(pfvf, parent_classid);
12455e6808b4SNaveen Mamindlapalli 	if (!parent) {
12465e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "parent node not found");
12475e6808b4SNaveen Mamindlapalli 		ret = -ENOENT;
12485e6808b4SNaveen Mamindlapalli 		goto out;
12495e6808b4SNaveen Mamindlapalli 	}
12505e6808b4SNaveen Mamindlapalli 	if (parent->level == NIX_TXSCH_LVL_MDQ) {
12515e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB qos max levels reached");
12525e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
12535e6808b4SNaveen Mamindlapalli 		goto out;
12545e6808b4SNaveen Mamindlapalli 	}
12555e6808b4SNaveen Mamindlapalli 
125647a9656fSNaveen Mamindlapalli 	static_cfg = !is_qos_node_dwrr(parent, pfvf, prio);
125747a9656fSNaveen Mamindlapalli 	ret = otx2_qos_validate_configuration(parent, extack, pfvf, prio,
125847a9656fSNaveen Mamindlapalli 					      static_cfg);
12595e6808b4SNaveen Mamindlapalli 	if (ret)
12605e6808b4SNaveen Mamindlapalli 		goto out;
12615e6808b4SNaveen Mamindlapalli 
126247a9656fSNaveen Mamindlapalli 	if (!static_cfg) {
126347a9656fSNaveen Mamindlapalli 		ret = otx2_qos_validate_dwrr_cfg(parent, extack, pfvf, prio,
126447a9656fSNaveen Mamindlapalli 						 quantum);
126547a9656fSNaveen Mamindlapalli 		if (ret)
126647a9656fSNaveen Mamindlapalli 			goto out;
126747a9656fSNaveen Mamindlapalli 	}
126847a9656fSNaveen Mamindlapalli 
126947a9656fSNaveen Mamindlapalli 	if (static_cfg)
1270f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt++;
127147a9656fSNaveen Mamindlapalli 	else
127247a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt++;
127347a9656fSNaveen Mamindlapalli 
12745e6808b4SNaveen Mamindlapalli 	set_bit(prio, parent->prio_bmap);
12755e6808b4SNaveen Mamindlapalli 
12765e6808b4SNaveen Mamindlapalli 	/* read current txschq configuration */
12775e6808b4SNaveen Mamindlapalli 	old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
12785e6808b4SNaveen Mamindlapalli 	if (!old_cfg) {
12795e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
12805e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
12815e6808b4SNaveen Mamindlapalli 		goto reset_prio;
12825e6808b4SNaveen Mamindlapalli 	}
12835e6808b4SNaveen Mamindlapalli 	otx2_qos_read_txschq_cfg(pfvf, parent, old_cfg);
12845e6808b4SNaveen Mamindlapalli 
12855e6808b4SNaveen Mamindlapalli 	/* allocate a new sq */
12865e6808b4SNaveen Mamindlapalli 	qid = otx2_qos_get_qid(pfvf);
12875e6808b4SNaveen Mamindlapalli 	if (qid < 0) {
12885e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Reached max supported QOS SQ's");
12895e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
12905e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
12915e6808b4SNaveen Mamindlapalli 	}
12925e6808b4SNaveen Mamindlapalli 
12935e6808b4SNaveen Mamindlapalli 	/* Actual SQ mapping will be updated after SMQ alloc */
12945e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
12955e6808b4SNaveen Mamindlapalli 
12965e6808b4SNaveen Mamindlapalli 	/* allocate and initialize a new child node */
12975e6808b4SNaveen Mamindlapalli 	node = otx2_qos_sw_create_leaf_node(pfvf, parent, classid, prio, rate,
129847a9656fSNaveen Mamindlapalli 					    ceil, quantum, qid, static_cfg);
12995e6808b4SNaveen Mamindlapalli 	if (IS_ERR(node)) {
13005e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
13015e6808b4SNaveen Mamindlapalli 		ret = PTR_ERR(node);
13025e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
13035e6808b4SNaveen Mamindlapalli 	}
13045e6808b4SNaveen Mamindlapalli 
13055e6808b4SNaveen Mamindlapalli 	/* push new txschq config to hw */
13065e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
13075e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
13085e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
13095e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
13105e6808b4SNaveen Mamindlapalli 		goto free_node;
13115e6808b4SNaveen Mamindlapalli 	}
13125e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_update_tree(pfvf, node, new_cfg);
13135e6808b4SNaveen Mamindlapalli 	if (ret) {
13145e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
13155e6808b4SNaveen Mamindlapalli 		kfree(new_cfg);
13165e6808b4SNaveen Mamindlapalli 		otx2_qos_sw_node_delete(pfvf, node);
13175e6808b4SNaveen Mamindlapalli 		/* restore the old qos tree */
13185e6808b4SNaveen Mamindlapalli 		err = otx2_qos_txschq_update_config(pfvf, parent, old_cfg);
13195e6808b4SNaveen Mamindlapalli 		if (err) {
13205e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev,
13215e6808b4SNaveen Mamindlapalli 				   "Failed to restore txcshq configuration");
13225e6808b4SNaveen Mamindlapalli 			goto free_old_cfg;
13235e6808b4SNaveen Mamindlapalli 		}
13245e6808b4SNaveen Mamindlapalli 
13255e6808b4SNaveen Mamindlapalli 		otx2_qos_update_smq(pfvf, parent, QOS_CFG_SQ);
13265e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
13275e6808b4SNaveen Mamindlapalli 	}
13285e6808b4SNaveen Mamindlapalli 
13295e6808b4SNaveen Mamindlapalli 	/* update tx_real_queues */
13305e6808b4SNaveen Mamindlapalli 	otx2_qos_update_tx_netdev_queues(pfvf);
13315e6808b4SNaveen Mamindlapalli 
13325e6808b4SNaveen Mamindlapalli 	/* free new txschq config */
13335e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
13345e6808b4SNaveen Mamindlapalli 
13355e6808b4SNaveen Mamindlapalli 	/* free old txschq config */
13365e6808b4SNaveen Mamindlapalli 	otx2_qos_free_cfg(pfvf, old_cfg);
13375e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
13385e6808b4SNaveen Mamindlapalli 
13395e6808b4SNaveen Mamindlapalli 	return pfvf->hw.tx_queues + qid;
13405e6808b4SNaveen Mamindlapalli 
13415e6808b4SNaveen Mamindlapalli free_node:
13425e6808b4SNaveen Mamindlapalli 	otx2_qos_sw_node_delete(pfvf, node);
13435e6808b4SNaveen Mamindlapalli free_old_cfg:
13445e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
13455e6808b4SNaveen Mamindlapalli reset_prio:
134647a9656fSNaveen Mamindlapalli 	if (static_cfg)
1347f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt--;
134847a9656fSNaveen Mamindlapalli 	else
134947a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt--;
135047a9656fSNaveen Mamindlapalli 
13515e6808b4SNaveen Mamindlapalli 	clear_bit(prio, parent->prio_bmap);
13525e6808b4SNaveen Mamindlapalli out:
13535e6808b4SNaveen Mamindlapalli 	return ret;
13545e6808b4SNaveen Mamindlapalli }
13555e6808b4SNaveen Mamindlapalli 
13565e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid,
13575e6808b4SNaveen Mamindlapalli 				  u16 child_classid, u64 rate, u64 ceil, u64 prio,
135847a9656fSNaveen Mamindlapalli 				  u32 quantum, struct netlink_ext_ack *extack)
13595e6808b4SNaveen Mamindlapalli {
13605e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *old_cfg, *new_cfg;
13615e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *child;
136247a9656fSNaveen Mamindlapalli 	bool static_cfg;
13635e6808b4SNaveen Mamindlapalli 	int ret, err;
13645e6808b4SNaveen Mamindlapalli 	u16 qid;
13655e6808b4SNaveen Mamindlapalli 
13665e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
13675e6808b4SNaveen Mamindlapalli 		   "TC_HTB_LEAF_TO_INNER classid %04x, child %04x, rate %llu, ceil %llu\n",
13685e6808b4SNaveen Mamindlapalli 		   classid, child_classid, rate, ceil);
13695e6808b4SNaveen Mamindlapalli 
13705e6808b4SNaveen Mamindlapalli 	if (prio > OTX2_QOS_MAX_PRIO) {
13715e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
13725e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
13735e6808b4SNaveen Mamindlapalli 		goto out;
13745e6808b4SNaveen Mamindlapalli 	}
13755e6808b4SNaveen Mamindlapalli 
137647a9656fSNaveen Mamindlapalli 	if (!quantum || quantum > INT_MAX) {
137747a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Invalid quantum, range 1 - 2147483647 bytes");
137847a9656fSNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
137947a9656fSNaveen Mamindlapalli 		goto out;
138047a9656fSNaveen Mamindlapalli 	}
138147a9656fSNaveen Mamindlapalli 
13825e6808b4SNaveen Mamindlapalli 	/* find node related to classid */
13835e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find(pfvf, classid);
13845e6808b4SNaveen Mamindlapalli 	if (!node) {
13855e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
13865e6808b4SNaveen Mamindlapalli 		ret = -ENOENT;
13875e6808b4SNaveen Mamindlapalli 		goto out;
13885e6808b4SNaveen Mamindlapalli 	}
13895e6808b4SNaveen Mamindlapalli 	/* check max qos txschq level */
13905e6808b4SNaveen Mamindlapalli 	if (node->level == NIX_TXSCH_LVL_MDQ) {
13915e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB qos level not supported");
13925e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
13935e6808b4SNaveen Mamindlapalli 		goto out;
13945e6808b4SNaveen Mamindlapalli 	}
13955e6808b4SNaveen Mamindlapalli 
139647a9656fSNaveen Mamindlapalli 	static_cfg = !is_qos_node_dwrr(node, pfvf, prio);
139747a9656fSNaveen Mamindlapalli 	if (!static_cfg) {
139847a9656fSNaveen Mamindlapalli 		ret = otx2_qos_validate_dwrr_cfg(node, extack, pfvf, prio,
139947a9656fSNaveen Mamindlapalli 						 quantum);
140047a9656fSNaveen Mamindlapalli 		if (ret)
140147a9656fSNaveen Mamindlapalli 			goto out;
140247a9656fSNaveen Mamindlapalli 	}
140347a9656fSNaveen Mamindlapalli 
140447a9656fSNaveen Mamindlapalli 	if (static_cfg)
1405f78dca69SNaveen Mamindlapalli 		node->child_static_cnt++;
140647a9656fSNaveen Mamindlapalli 	else
140747a9656fSNaveen Mamindlapalli 		node->child_dwrr_cnt++;
140847a9656fSNaveen Mamindlapalli 
14095e6808b4SNaveen Mamindlapalli 	set_bit(prio, node->prio_bmap);
14105e6808b4SNaveen Mamindlapalli 
14115e6808b4SNaveen Mamindlapalli 	/* store the qid to assign to leaf node */
14125e6808b4SNaveen Mamindlapalli 	qid = node->qid;
14135e6808b4SNaveen Mamindlapalli 
14145e6808b4SNaveen Mamindlapalli 	/* read current txschq configuration */
14155e6808b4SNaveen Mamindlapalli 	old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
14165e6808b4SNaveen Mamindlapalli 	if (!old_cfg) {
14175e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
14185e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
14195e6808b4SNaveen Mamindlapalli 		goto reset_prio;
14205e6808b4SNaveen Mamindlapalli 	}
14215e6808b4SNaveen Mamindlapalli 	otx2_qos_read_txschq_cfg(pfvf, node, old_cfg);
14225e6808b4SNaveen Mamindlapalli 
14235e6808b4SNaveen Mamindlapalli 	/* delete the txschq nodes allocated for this node */
142416848421SHariprasad Kelam 	otx2_qos_disable_sq(pfvf, qid);
142516848421SHariprasad Kelam 	otx2_qos_free_hw_node_schq(pfvf, node);
14265e6808b4SNaveen Mamindlapalli 	otx2_qos_free_sw_node_schq(pfvf, node);
142716848421SHariprasad Kelam 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
14285e6808b4SNaveen Mamindlapalli 
14295e6808b4SNaveen Mamindlapalli 	/* mark this node as htb inner node */
14305e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER);
14315e6808b4SNaveen Mamindlapalli 
14325e6808b4SNaveen Mamindlapalli 	/* allocate and initialize a new child node */
14335e6808b4SNaveen Mamindlapalli 	child = otx2_qos_sw_create_leaf_node(pfvf, node, child_classid,
143447a9656fSNaveen Mamindlapalli 					     prio, rate, ceil, quantum,
143547a9656fSNaveen Mamindlapalli 					     qid, static_cfg);
14365e6808b4SNaveen Mamindlapalli 	if (IS_ERR(child)) {
14375e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
14385e6808b4SNaveen Mamindlapalli 		ret = PTR_ERR(child);
14395e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
14405e6808b4SNaveen Mamindlapalli 	}
14415e6808b4SNaveen Mamindlapalli 
14425e6808b4SNaveen Mamindlapalli 	/* push new txschq config to hw */
14435e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
14445e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
14455e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
14465e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
14475e6808b4SNaveen Mamindlapalli 		goto free_node;
14485e6808b4SNaveen Mamindlapalli 	}
14495e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_update_tree(pfvf, child, new_cfg);
14505e6808b4SNaveen Mamindlapalli 	if (ret) {
14515e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
14525e6808b4SNaveen Mamindlapalli 		kfree(new_cfg);
14535e6808b4SNaveen Mamindlapalli 		otx2_qos_sw_node_delete(pfvf, child);
14545e6808b4SNaveen Mamindlapalli 		/* restore the old qos tree */
14555e6808b4SNaveen Mamindlapalli 		WRITE_ONCE(node->qid, qid);
14565e6808b4SNaveen Mamindlapalli 		err = otx2_qos_alloc_txschq_node(pfvf, node);
14575e6808b4SNaveen Mamindlapalli 		if (err) {
14585e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev,
14595e6808b4SNaveen Mamindlapalli 				   "Failed to restore old leaf node");
14605e6808b4SNaveen Mamindlapalli 			goto free_old_cfg;
14615e6808b4SNaveen Mamindlapalli 		}
14625e6808b4SNaveen Mamindlapalli 		err = otx2_qos_txschq_update_config(pfvf, node, old_cfg);
14635e6808b4SNaveen Mamindlapalli 		if (err) {
14645e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev,
14655e6808b4SNaveen Mamindlapalli 				   "Failed to restore txcshq configuration");
14665e6808b4SNaveen Mamindlapalli 			goto free_old_cfg;
14675e6808b4SNaveen Mamindlapalli 		}
14685e6808b4SNaveen Mamindlapalli 		otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
14695e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
14705e6808b4SNaveen Mamindlapalli 	}
14715e6808b4SNaveen Mamindlapalli 
14725e6808b4SNaveen Mamindlapalli 	/* free new txschq config */
14735e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
14745e6808b4SNaveen Mamindlapalli 
14755e6808b4SNaveen Mamindlapalli 	/* free old txschq config */
14765e6808b4SNaveen Mamindlapalli 	otx2_qos_free_cfg(pfvf, old_cfg);
14775e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
14785e6808b4SNaveen Mamindlapalli 
14795e6808b4SNaveen Mamindlapalli 	return 0;
14805e6808b4SNaveen Mamindlapalli 
14815e6808b4SNaveen Mamindlapalli free_node:
14825e6808b4SNaveen Mamindlapalli 	otx2_qos_sw_node_delete(pfvf, child);
14835e6808b4SNaveen Mamindlapalli free_old_cfg:
14845e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
14855e6808b4SNaveen Mamindlapalli reset_prio:
148647a9656fSNaveen Mamindlapalli 	if (static_cfg)
1487f78dca69SNaveen Mamindlapalli 		node->child_static_cnt--;
148847a9656fSNaveen Mamindlapalli 	else
148947a9656fSNaveen Mamindlapalli 		node->child_dwrr_cnt--;
14905e6808b4SNaveen Mamindlapalli 	clear_bit(prio, node->prio_bmap);
14915e6808b4SNaveen Mamindlapalli out:
14925e6808b4SNaveen Mamindlapalli 	return ret;
14935e6808b4SNaveen Mamindlapalli }
14945e6808b4SNaveen Mamindlapalli 
149504fb71ccSHariprasad Kelam static int otx2_qos_cur_leaf_nodes(struct otx2_nic *pfvf)
149604fb71ccSHariprasad Kelam {
149704fb71ccSHariprasad Kelam 	int last = find_last_bit(pfvf->qos.qos_sq_bmap, pfvf->hw.tc_tx_queues);
149804fb71ccSHariprasad Kelam 
149904fb71ccSHariprasad Kelam 	return last ==  pfvf->hw.tc_tx_queues ? 0 : last + 1;
150004fb71ccSHariprasad Kelam }
150104fb71ccSHariprasad Kelam 
150204fb71ccSHariprasad Kelam static void otx2_reset_qdisc(struct net_device *dev, u16 qid)
150304fb71ccSHariprasad Kelam {
150404fb71ccSHariprasad Kelam 	struct netdev_queue *dev_queue = netdev_get_tx_queue(dev, qid);
150504fb71ccSHariprasad Kelam 	struct Qdisc *qdisc = rtnl_dereference(dev_queue->qdisc_sleeping);
150604fb71ccSHariprasad Kelam 
150704fb71ccSHariprasad Kelam 	if (!qdisc)
150804fb71ccSHariprasad Kelam 		return;
150904fb71ccSHariprasad Kelam 
151004fb71ccSHariprasad Kelam 	spin_lock_bh(qdisc_lock(qdisc));
151104fb71ccSHariprasad Kelam 	qdisc_reset(qdisc);
151204fb71ccSHariprasad Kelam 	spin_unlock_bh(qdisc_lock(qdisc));
151304fb71ccSHariprasad Kelam }
151404fb71ccSHariprasad Kelam 
151504fb71ccSHariprasad Kelam static void otx2_cfg_smq(struct otx2_nic *pfvf, struct otx2_qos_node *node,
151604fb71ccSHariprasad Kelam 			 int qid)
151704fb71ccSHariprasad Kelam {
151804fb71ccSHariprasad Kelam 	struct otx2_qos_node *tmp;
151904fb71ccSHariprasad Kelam 
152004fb71ccSHariprasad Kelam 	list_for_each_entry(tmp, &node->child_schq_list, list)
152104fb71ccSHariprasad Kelam 		if (tmp->level == NIX_TXSCH_LVL_MDQ) {
152204fb71ccSHariprasad Kelam 			otx2_qos_txschq_config(pfvf, tmp);
152304fb71ccSHariprasad Kelam 			pfvf->qos.qid_to_sqmap[qid] = tmp->schq;
152404fb71ccSHariprasad Kelam 		}
152504fb71ccSHariprasad Kelam }
152604fb71ccSHariprasad Kelam 
15275e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid,
15285e6808b4SNaveen Mamindlapalli 			     struct netlink_ext_ack *extack)
15295e6808b4SNaveen Mamindlapalli {
15305e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *parent;
153147a9656fSNaveen Mamindlapalli 	int dwrr_del_node = false;
153204fb71ccSHariprasad Kelam 	u16 qid, moved_qid;
15335e6808b4SNaveen Mamindlapalli 	u64 prio;
15345e6808b4SNaveen Mamindlapalli 
15355e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev, "TC_HTB_LEAF_DEL classid %04x\n", *classid);
15365e6808b4SNaveen Mamindlapalli 
15375e6808b4SNaveen Mamindlapalli 	/* find node related to classid */
15385e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find(pfvf, *classid);
15395e6808b4SNaveen Mamindlapalli 	if (!node) {
15405e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
15415e6808b4SNaveen Mamindlapalli 		return -ENOENT;
15425e6808b4SNaveen Mamindlapalli 	}
15435e6808b4SNaveen Mamindlapalli 	parent = node->parent;
15445e6808b4SNaveen Mamindlapalli 	prio   = node->prio;
15455e6808b4SNaveen Mamindlapalli 	qid    = node->qid;
15465e6808b4SNaveen Mamindlapalli 
154747a9656fSNaveen Mamindlapalli 	if (!node->is_static)
154847a9656fSNaveen Mamindlapalli 		dwrr_del_node = true;
154947a9656fSNaveen Mamindlapalli 
15505e6808b4SNaveen Mamindlapalli 	otx2_qos_disable_sq(pfvf, node->qid);
15515e6808b4SNaveen Mamindlapalli 
15525e6808b4SNaveen Mamindlapalli 	otx2_qos_destroy_node(pfvf, node);
15535e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
15545e6808b4SNaveen Mamindlapalli 
155547a9656fSNaveen Mamindlapalli 	if (dwrr_del_node) {
155647a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt--;
155747a9656fSNaveen Mamindlapalli 	} else {
1558f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt--;
155947a9656fSNaveen Mamindlapalli 		clear_bit(prio, parent->prio_bmap);
156047a9656fSNaveen Mamindlapalli 	}
156147a9656fSNaveen Mamindlapalli 
156247a9656fSNaveen Mamindlapalli 	/* Reset DWRR priority if all dwrr nodes are deleted */
156347a9656fSNaveen Mamindlapalli 	if (!parent->child_dwrr_cnt)
156447a9656fSNaveen Mamindlapalli 		otx2_reset_dwrr_prio(parent, prio);
156547a9656fSNaveen Mamindlapalli 
1566f78dca69SNaveen Mamindlapalli 	if (!parent->child_static_cnt)
1567f78dca69SNaveen Mamindlapalli 		parent->max_static_prio = 0;
1568f78dca69SNaveen Mamindlapalli 
156904fb71ccSHariprasad Kelam 	moved_qid = otx2_qos_cur_leaf_nodes(pfvf);
157004fb71ccSHariprasad Kelam 
157104fb71ccSHariprasad Kelam 	/* last node just deleted */
157204fb71ccSHariprasad Kelam 	if (moved_qid == 0 || moved_qid == qid)
157304fb71ccSHariprasad Kelam 		return 0;
157404fb71ccSHariprasad Kelam 
157504fb71ccSHariprasad Kelam 	moved_qid--;
157604fb71ccSHariprasad Kelam 
157704fb71ccSHariprasad Kelam 	node = otx2_sw_node_find_by_qid(pfvf, moved_qid);
157804fb71ccSHariprasad Kelam 	if (!node)
157904fb71ccSHariprasad Kelam 		return 0;
158004fb71ccSHariprasad Kelam 
158104fb71ccSHariprasad Kelam 	/* stop traffic to the old queue and disable
158204fb71ccSHariprasad Kelam 	 * SQ associated with it
158304fb71ccSHariprasad Kelam 	 */
158404fb71ccSHariprasad Kelam 	node->qid =  OTX2_QOS_QID_INNER;
158504fb71ccSHariprasad Kelam 	__clear_bit(moved_qid, pfvf->qos.qos_sq_bmap);
158604fb71ccSHariprasad Kelam 	otx2_qos_disable_sq(pfvf, moved_qid);
158704fb71ccSHariprasad Kelam 
158804fb71ccSHariprasad Kelam 	otx2_reset_qdisc(pfvf->netdev, pfvf->hw.tx_queues + moved_qid);
158904fb71ccSHariprasad Kelam 
159004fb71ccSHariprasad Kelam 	/* enable SQ associated with qid and
159104fb71ccSHariprasad Kelam 	 * update the node
159204fb71ccSHariprasad Kelam 	 */
159304fb71ccSHariprasad Kelam 	otx2_cfg_smq(pfvf, node, qid);
159404fb71ccSHariprasad Kelam 
159504fb71ccSHariprasad Kelam 	otx2_qos_enable_sq(pfvf, qid);
159604fb71ccSHariprasad Kelam 	__set_bit(qid, pfvf->qos.qos_sq_bmap);
159704fb71ccSHariprasad Kelam 	node->qid = qid;
159804fb71ccSHariprasad Kelam 
159904fb71ccSHariprasad Kelam 	*classid = node->classid;
16005e6808b4SNaveen Mamindlapalli 	return 0;
16015e6808b4SNaveen Mamindlapalli }
16025e6808b4SNaveen Mamindlapalli 
16035e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force,
16045e6808b4SNaveen Mamindlapalli 				  struct netlink_ext_ack *extack)
16055e6808b4SNaveen Mamindlapalli {
16065e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *parent;
16075e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *new_cfg;
160847a9656fSNaveen Mamindlapalli 	int dwrr_del_node = false;
16095e6808b4SNaveen Mamindlapalli 	u64 prio;
16105e6808b4SNaveen Mamindlapalli 	int err;
16115e6808b4SNaveen Mamindlapalli 	u16 qid;
16125e6808b4SNaveen Mamindlapalli 
16135e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
16145e6808b4SNaveen Mamindlapalli 		   "TC_HTB_LEAF_DEL_LAST classid %04x\n", classid);
16155e6808b4SNaveen Mamindlapalli 
16165e6808b4SNaveen Mamindlapalli 	/* find node related to classid */
16175e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find(pfvf, classid);
16185e6808b4SNaveen Mamindlapalli 	if (!node) {
16195e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
16205e6808b4SNaveen Mamindlapalli 		return -ENOENT;
16215e6808b4SNaveen Mamindlapalli 	}
16225e6808b4SNaveen Mamindlapalli 
16235e6808b4SNaveen Mamindlapalli 	/* save qid for use by parent */
16245e6808b4SNaveen Mamindlapalli 	qid = node->qid;
16255e6808b4SNaveen Mamindlapalli 	prio = node->prio;
16265e6808b4SNaveen Mamindlapalli 
16275e6808b4SNaveen Mamindlapalli 	parent = otx2_sw_node_find(pfvf, node->parent->classid);
16285e6808b4SNaveen Mamindlapalli 	if (!parent) {
16295e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "parent node not found");
16305e6808b4SNaveen Mamindlapalli 		return -ENOENT;
16315e6808b4SNaveen Mamindlapalli 	}
16325e6808b4SNaveen Mamindlapalli 
163347a9656fSNaveen Mamindlapalli 	if (!node->is_static)
163447a9656fSNaveen Mamindlapalli 		dwrr_del_node = true;
163547a9656fSNaveen Mamindlapalli 
16365e6808b4SNaveen Mamindlapalli 	/* destroy the leaf node */
163716848421SHariprasad Kelam 	otx2_qos_disable_sq(pfvf, qid);
16385e6808b4SNaveen Mamindlapalli 	otx2_qos_destroy_node(pfvf, node);
16395e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
16405e6808b4SNaveen Mamindlapalli 
164147a9656fSNaveen Mamindlapalli 	if (dwrr_del_node) {
164247a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt--;
164347a9656fSNaveen Mamindlapalli 	} else {
1644f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt--;
164547a9656fSNaveen Mamindlapalli 		clear_bit(prio, parent->prio_bmap);
164647a9656fSNaveen Mamindlapalli 	}
164747a9656fSNaveen Mamindlapalli 
164847a9656fSNaveen Mamindlapalli 	/* Reset DWRR priority if all dwrr nodes are deleted */
164947a9656fSNaveen Mamindlapalli 	if (!parent->child_dwrr_cnt)
165047a9656fSNaveen Mamindlapalli 		otx2_reset_dwrr_prio(parent, prio);
165147a9656fSNaveen Mamindlapalli 
1652f78dca69SNaveen Mamindlapalli 	if (!parent->child_static_cnt)
1653f78dca69SNaveen Mamindlapalli 		parent->max_static_prio = 0;
1654f78dca69SNaveen Mamindlapalli 
16555e6808b4SNaveen Mamindlapalli 	/* create downstream txschq entries to parent */
16565e6808b4SNaveen Mamindlapalli 	err = otx2_qos_alloc_txschq_node(pfvf, parent);
16575e6808b4SNaveen Mamindlapalli 	if (err) {
16585e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB failed to create txsch configuration");
16595e6808b4SNaveen Mamindlapalli 		return err;
16605e6808b4SNaveen Mamindlapalli 	}
16615e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(parent->qid, qid);
16625e6808b4SNaveen Mamindlapalli 	__set_bit(qid, pfvf->qos.qos_sq_bmap);
16635e6808b4SNaveen Mamindlapalli 
16645e6808b4SNaveen Mamindlapalli 	/* push new txschq config to hw */
16655e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
16665e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
16675e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
16685e6808b4SNaveen Mamindlapalli 		return -ENOMEM;
16695e6808b4SNaveen Mamindlapalli 	}
16705e6808b4SNaveen Mamindlapalli 	/* fill txschq cfg and push txschq cfg to hw */
16715e6808b4SNaveen Mamindlapalli 	otx2_qos_fill_cfg_schq(parent, new_cfg);
16725e6808b4SNaveen Mamindlapalli 	err = otx2_qos_push_txschq_cfg(pfvf, parent, new_cfg);
16735e6808b4SNaveen Mamindlapalli 	if (err) {
16745e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
16755e6808b4SNaveen Mamindlapalli 		kfree(new_cfg);
16765e6808b4SNaveen Mamindlapalli 		return err;
16775e6808b4SNaveen Mamindlapalli 	}
16785e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
16795e6808b4SNaveen Mamindlapalli 
16805e6808b4SNaveen Mamindlapalli 	/* update tx_real_queues */
16815e6808b4SNaveen Mamindlapalli 	otx2_qos_update_tx_netdev_queues(pfvf);
16825e6808b4SNaveen Mamindlapalli 
16835e6808b4SNaveen Mamindlapalli 	return 0;
16845e6808b4SNaveen Mamindlapalli }
16855e6808b4SNaveen Mamindlapalli 
16865e6808b4SNaveen Mamindlapalli void otx2_clean_qos_queues(struct otx2_nic *pfvf)
16875e6808b4SNaveen Mamindlapalli {
16885e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
16895e6808b4SNaveen Mamindlapalli 
16905e6808b4SNaveen Mamindlapalli 	root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
16915e6808b4SNaveen Mamindlapalli 	if (!root)
16925e6808b4SNaveen Mamindlapalli 		return;
16935e6808b4SNaveen Mamindlapalli 
16945e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq(pfvf, root, QOS_SMQ_FLUSH);
16955e6808b4SNaveen Mamindlapalli }
16965e6808b4SNaveen Mamindlapalli 
16975e6808b4SNaveen Mamindlapalli void otx2_qos_config_txschq(struct otx2_nic *pfvf)
16985e6808b4SNaveen Mamindlapalli {
16995e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
17005e6808b4SNaveen Mamindlapalli 	int err;
17015e6808b4SNaveen Mamindlapalli 
17025e6808b4SNaveen Mamindlapalli 	root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
17035e6808b4SNaveen Mamindlapalli 	if (!root)
17045e6808b4SNaveen Mamindlapalli 		return;
17055e6808b4SNaveen Mamindlapalli 
170647a9656fSNaveen Mamindlapalli 	if (root->level != NIX_TXSCH_LVL_TL1) {
17075e6808b4SNaveen Mamindlapalli 		err = otx2_qos_txschq_config(pfvf, root);
17085e6808b4SNaveen Mamindlapalli 		if (err) {
17095e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev, "Error update txschq configuration\n");
17105e6808b4SNaveen Mamindlapalli 			goto root_destroy;
17115e6808b4SNaveen Mamindlapalli 		}
171247a9656fSNaveen Mamindlapalli 	}
17135e6808b4SNaveen Mamindlapalli 
17145e6808b4SNaveen Mamindlapalli 	err = otx2_qos_txschq_push_cfg_tl(pfvf, root, NULL);
17155e6808b4SNaveen Mamindlapalli 	if (err) {
17165e6808b4SNaveen Mamindlapalli 		netdev_err(pfvf->netdev, "Error update txschq configuration\n");
17175e6808b4SNaveen Mamindlapalli 		goto root_destroy;
17185e6808b4SNaveen Mamindlapalli 	}
17195e6808b4SNaveen Mamindlapalli 
17205e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq(pfvf, root, QOS_CFG_SQ);
17215e6808b4SNaveen Mamindlapalli 	return;
17225e6808b4SNaveen Mamindlapalli 
17235e6808b4SNaveen Mamindlapalli root_destroy:
17245e6808b4SNaveen Mamindlapalli 	netdev_err(pfvf->netdev, "Failed to update Scheduler/Shaping config in Hardware\n");
17255e6808b4SNaveen Mamindlapalli 	/* Free resources allocated */
17265e6808b4SNaveen Mamindlapalli 	otx2_qos_root_destroy(pfvf);
17275e6808b4SNaveen Mamindlapalli }
17285e6808b4SNaveen Mamindlapalli 
17295e6808b4SNaveen Mamindlapalli int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb)
17305e6808b4SNaveen Mamindlapalli {
17315e6808b4SNaveen Mamindlapalli 	struct otx2_nic *pfvf = netdev_priv(ndev);
17325e6808b4SNaveen Mamindlapalli 	int res;
17335e6808b4SNaveen Mamindlapalli 
17345e6808b4SNaveen Mamindlapalli 	switch (htb->command) {
17355e6808b4SNaveen Mamindlapalli 	case TC_HTB_CREATE:
17365e6808b4SNaveen Mamindlapalli 		return otx2_qos_root_add(pfvf, htb->parent_classid,
17375e6808b4SNaveen Mamindlapalli 					 htb->classid, htb->extack);
17385e6808b4SNaveen Mamindlapalli 	case TC_HTB_DESTROY:
17395e6808b4SNaveen Mamindlapalli 		return otx2_qos_root_destroy(pfvf);
17405e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_ALLOC_QUEUE:
17415e6808b4SNaveen Mamindlapalli 		res = otx2_qos_leaf_alloc_queue(pfvf, htb->classid,
17425e6808b4SNaveen Mamindlapalli 						htb->parent_classid,
17435e6808b4SNaveen Mamindlapalli 						htb->rate, htb->ceil,
174447a9656fSNaveen Mamindlapalli 						htb->prio, htb->quantum,
174547a9656fSNaveen Mamindlapalli 						htb->extack);
17465e6808b4SNaveen Mamindlapalli 		if (res < 0)
17475e6808b4SNaveen Mamindlapalli 			return res;
17485e6808b4SNaveen Mamindlapalli 		htb->qid = res;
17495e6808b4SNaveen Mamindlapalli 		return 0;
17505e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_TO_INNER:
17515e6808b4SNaveen Mamindlapalli 		return otx2_qos_leaf_to_inner(pfvf, htb->parent_classid,
17525e6808b4SNaveen Mamindlapalli 					      htb->classid, htb->rate,
17535e6808b4SNaveen Mamindlapalli 					      htb->ceil, htb->prio,
175447a9656fSNaveen Mamindlapalli 					      htb->quantum, htb->extack);
17555e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_DEL:
17565e6808b4SNaveen Mamindlapalli 		return otx2_qos_leaf_del(pfvf, &htb->classid, htb->extack);
17575e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_DEL_LAST:
17585e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_DEL_LAST_FORCE:
17595e6808b4SNaveen Mamindlapalli 		return otx2_qos_leaf_del_last(pfvf, htb->classid,
17605e6808b4SNaveen Mamindlapalli 				htb->command == TC_HTB_LEAF_DEL_LAST_FORCE,
17615e6808b4SNaveen Mamindlapalli 					      htb->extack);
17625e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_QUERY_QUEUE:
17635e6808b4SNaveen Mamindlapalli 		res = otx2_get_txq_by_classid(pfvf, htb->classid);
17645e6808b4SNaveen Mamindlapalli 		htb->qid = res;
17655e6808b4SNaveen Mamindlapalli 		return 0;
17665e6808b4SNaveen Mamindlapalli 	case TC_HTB_NODE_MODIFY:
17675e6808b4SNaveen Mamindlapalli 		fallthrough;
17685e6808b4SNaveen Mamindlapalli 	default:
17695e6808b4SNaveen Mamindlapalli 		return -EOPNOTSUPP;
17705e6808b4SNaveen Mamindlapalli 	}
17715e6808b4SNaveen Mamindlapalli }
1772