xref: /openbmc/linux/drivers/net/ethernet/marvell/octeontx2/nic/qos.c (revision d6b6592ac6d11eab91e6758d224eac35f4122aca)
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 
otx2_qos_update_tx_netdev_queues(struct otx2_nic * pfvf)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 
otx2_qos_get_regaddr(struct otx2_qos_node * node,struct nix_txschq_config * cfg,int index)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 
otx2_qos_quantum_to_dwrr_weight(struct otx2_nic * pfvf,u32 quantum)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 
otx2_config_sched_shaping(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct nix_txschq_config * cfg,int * num_regs)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 
__otx2_qos_txschq_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct nix_txschq_config * cfg)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*38608d07SRatheesh 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 
otx2_qos_txschq_set_parent_topology(struct otx2_nic * pfvf,struct otx2_qos_node * parent)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 
otx2_qos_free_hw_node_schq(struct otx2_nic * pfvf,struct otx2_qos_node * parent)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 
otx2_qos_free_hw_node(struct otx2_nic * pfvf,struct otx2_qos_node * parent)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 
otx2_qos_free_hw_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * node)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 
otx2_qos_sw_node_delete(struct otx2_nic * pfvf,struct otx2_qos_node * node)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 
otx2_qos_free_sw_node_schq(struct otx2_nic * pfvf,struct otx2_qos_node * parent)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 
__otx2_qos_free_sw_node(struct otx2_nic * pfvf,struct otx2_qos_node * parent)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 
otx2_qos_free_sw_node(struct otx2_nic * pfvf,struct otx2_qos_node * node)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 
otx2_qos_destroy_node(struct otx2_nic * pfvf,struct otx2_qos_node * node)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 
otx2_qos_fill_cfg_schq(struct otx2_qos_node * parent,struct otx2_qos_cfg * cfg)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 
otx2_qos_fill_cfg_tl(struct otx2_qos_node * parent,struct otx2_qos_cfg * cfg)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 
otx2_qos_prepare_txschq_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * parent,struct otx2_qos_cfg * cfg)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 
otx2_qos_read_txschq_cfg_schq(struct otx2_qos_node * parent,struct otx2_qos_cfg * cfg)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 
otx2_qos_read_txschq_cfg_tl(struct otx2_qos_node * parent,struct otx2_qos_cfg * cfg)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;
3847af5582eSHariprasad 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 
otx2_qos_read_txschq_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)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 *
otx2_qos_alloc_root(struct otx2_nic * pfvf)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 
otx2_qos_add_child_node(struct otx2_qos_node * parent,struct otx2_qos_node * node)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 
otx2_qos_alloc_txschq_node(struct otx2_nic * pfvf,struct otx2_qos_node * node)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 *
otx2_qos_sw_create_leaf_node(struct otx2_nic * pfvf,struct otx2_qos_node * parent,u16 classid,u32 prio,u64 rate,u64 ceil,u32 quantum,u16 qid,bool static_cfg)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 
5475e6808b4SNaveen Mamindlapalli static struct otx2_qos_node *
otx2_sw_node_find(struct otx2_nic * pfvf,u32 classid)5485e6808b4SNaveen Mamindlapalli otx2_sw_node_find(struct otx2_nic *pfvf, u32 classid)
5495e6808b4SNaveen Mamindlapalli {
5505e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node = NULL;
5515e6808b4SNaveen Mamindlapalli 
5525e6808b4SNaveen Mamindlapalli 	hash_for_each_possible(pfvf->qos.qos_hlist, node, hlist, classid) {
5535e6808b4SNaveen Mamindlapalli 		if (node->classid == classid)
5545e6808b4SNaveen Mamindlapalli 			break;
5555e6808b4SNaveen Mamindlapalli 	}
5565e6808b4SNaveen Mamindlapalli 
5575e6808b4SNaveen Mamindlapalli 	return node;
5585e6808b4SNaveen Mamindlapalli }
5595e6808b4SNaveen Mamindlapalli 
5605e6808b4SNaveen Mamindlapalli static struct otx2_qos_node *
otx2_sw_node_find_rcu(struct otx2_nic * pfvf,u32 classid)5615e6808b4SNaveen Mamindlapalli otx2_sw_node_find_rcu(struct otx2_nic *pfvf, u32 classid)
5625e6808b4SNaveen Mamindlapalli {
5635e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node = NULL;
5645e6808b4SNaveen Mamindlapalli 
5655e6808b4SNaveen Mamindlapalli 	hash_for_each_possible_rcu(pfvf->qos.qos_hlist, node, hlist, classid) {
5665e6808b4SNaveen Mamindlapalli 		if (node->classid == classid)
5675e6808b4SNaveen Mamindlapalli 			break;
5685e6808b4SNaveen Mamindlapalli 	}
5695e6808b4SNaveen Mamindlapalli 
5705e6808b4SNaveen Mamindlapalli 	return node;
5715e6808b4SNaveen Mamindlapalli }
5725e6808b4SNaveen Mamindlapalli 
otx2_get_txq_by_classid(struct otx2_nic * pfvf,u16 classid)5735e6808b4SNaveen Mamindlapalli int otx2_get_txq_by_classid(struct otx2_nic *pfvf, u16 classid)
5745e6808b4SNaveen Mamindlapalli {
5755e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node;
5765e6808b4SNaveen Mamindlapalli 	u16 qid;
5775e6808b4SNaveen Mamindlapalli 	int res;
5785e6808b4SNaveen Mamindlapalli 
5795e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find_rcu(pfvf, classid);
5805e6808b4SNaveen Mamindlapalli 	if (!node) {
5815e6808b4SNaveen Mamindlapalli 		res = -ENOENT;
5825e6808b4SNaveen Mamindlapalli 		goto out;
5835e6808b4SNaveen Mamindlapalli 	}
5845e6808b4SNaveen Mamindlapalli 	qid = READ_ONCE(node->qid);
5855e6808b4SNaveen Mamindlapalli 	if (qid == OTX2_QOS_QID_INNER) {
5865e6808b4SNaveen Mamindlapalli 		res = -EINVAL;
5875e6808b4SNaveen Mamindlapalli 		goto out;
5885e6808b4SNaveen Mamindlapalli 	}
5895e6808b4SNaveen Mamindlapalli 	res = pfvf->hw.tx_queues + qid;
5905e6808b4SNaveen Mamindlapalli out:
5915e6808b4SNaveen Mamindlapalli 	return res;
5925e6808b4SNaveen Mamindlapalli }
5935e6808b4SNaveen Mamindlapalli 
5945e6808b4SNaveen Mamindlapalli static int
otx2_qos_txschq_config(struct otx2_nic * pfvf,struct otx2_qos_node * node)5955e6808b4SNaveen Mamindlapalli otx2_qos_txschq_config(struct otx2_nic *pfvf, struct otx2_qos_node *node)
5965e6808b4SNaveen Mamindlapalli {
5975e6808b4SNaveen Mamindlapalli 	struct mbox *mbox = &pfvf->mbox;
5985e6808b4SNaveen Mamindlapalli 	struct nix_txschq_config *req;
5995e6808b4SNaveen Mamindlapalli 	int rc;
6005e6808b4SNaveen Mamindlapalli 
6015e6808b4SNaveen Mamindlapalli 	mutex_lock(&mbox->lock);
6025e6808b4SNaveen Mamindlapalli 
6035e6808b4SNaveen Mamindlapalli 	req = otx2_mbox_alloc_msg_nix_txschq_cfg(&pfvf->mbox);
6045e6808b4SNaveen Mamindlapalli 	if (!req) {
6055e6808b4SNaveen Mamindlapalli 		mutex_unlock(&mbox->lock);
6065e6808b4SNaveen Mamindlapalli 		return -ENOMEM;
6075e6808b4SNaveen Mamindlapalli 	}
6085e6808b4SNaveen Mamindlapalli 
6095e6808b4SNaveen Mamindlapalli 	req->lvl = node->level;
6105e6808b4SNaveen Mamindlapalli 	__otx2_qos_txschq_cfg(pfvf, node, req);
6115e6808b4SNaveen Mamindlapalli 
6125e6808b4SNaveen Mamindlapalli 	rc = otx2_sync_mbox_msg(&pfvf->mbox);
6135e6808b4SNaveen Mamindlapalli 
6145e6808b4SNaveen Mamindlapalli 	mutex_unlock(&mbox->lock);
6155e6808b4SNaveen Mamindlapalli 
6165e6808b4SNaveen Mamindlapalli 	return rc;
6175e6808b4SNaveen Mamindlapalli }
6185e6808b4SNaveen Mamindlapalli 
otx2_qos_txschq_alloc(struct otx2_nic * pfvf,struct otx2_qos_cfg * cfg)6195e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_alloc(struct otx2_nic *pfvf,
6205e6808b4SNaveen Mamindlapalli 				 struct otx2_qos_cfg *cfg)
6215e6808b4SNaveen Mamindlapalli {
6225e6808b4SNaveen Mamindlapalli 	struct nix_txsch_alloc_req *req;
6235e6808b4SNaveen Mamindlapalli 	struct nix_txsch_alloc_rsp *rsp;
6245e6808b4SNaveen Mamindlapalli 	struct mbox *mbox = &pfvf->mbox;
6255e6808b4SNaveen Mamindlapalli 	int lvl, rc, schq;
6265e6808b4SNaveen Mamindlapalli 
6275e6808b4SNaveen Mamindlapalli 	mutex_lock(&mbox->lock);
6285e6808b4SNaveen Mamindlapalli 	req = otx2_mbox_alloc_msg_nix_txsch_alloc(&pfvf->mbox);
6295e6808b4SNaveen Mamindlapalli 	if (!req) {
6305e6808b4SNaveen Mamindlapalli 		mutex_unlock(&mbox->lock);
6315e6808b4SNaveen Mamindlapalli 		return -ENOMEM;
6325e6808b4SNaveen Mamindlapalli 	}
6335e6808b4SNaveen Mamindlapalli 
6345e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
6355e6808b4SNaveen Mamindlapalli 		req->schq[lvl] = cfg->schq[lvl];
6365e6808b4SNaveen Mamindlapalli 		req->schq_contig[lvl] = cfg->schq_contig[lvl];
6375e6808b4SNaveen Mamindlapalli 	}
6385e6808b4SNaveen Mamindlapalli 
6395e6808b4SNaveen Mamindlapalli 	rc = otx2_sync_mbox_msg(&pfvf->mbox);
6405e6808b4SNaveen Mamindlapalli 	if (rc) {
6415e6808b4SNaveen Mamindlapalli 		mutex_unlock(&mbox->lock);
6425e6808b4SNaveen Mamindlapalli 		return rc;
6435e6808b4SNaveen Mamindlapalli 	}
6445e6808b4SNaveen Mamindlapalli 
6455e6808b4SNaveen Mamindlapalli 	rsp = (struct nix_txsch_alloc_rsp *)
6465e6808b4SNaveen Mamindlapalli 	      otx2_mbox_get_rsp(&pfvf->mbox.mbox, 0, &req->hdr);
6475e6808b4SNaveen Mamindlapalli 
6485e6808b4SNaveen Mamindlapalli 	if (IS_ERR(rsp)) {
6495e6808b4SNaveen Mamindlapalli 		rc = PTR_ERR(rsp);
6505e6808b4SNaveen Mamindlapalli 		goto out;
6515e6808b4SNaveen Mamindlapalli 	}
6525e6808b4SNaveen Mamindlapalli 
6535e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
6545e6808b4SNaveen Mamindlapalli 		for (schq = 0; schq < rsp->schq_contig[lvl]; schq++) {
6555e6808b4SNaveen Mamindlapalli 			cfg->schq_contig_list[lvl][schq] =
6565e6808b4SNaveen Mamindlapalli 				rsp->schq_contig_list[lvl][schq];
6575e6808b4SNaveen Mamindlapalli 		}
6585e6808b4SNaveen Mamindlapalli 	}
6595e6808b4SNaveen Mamindlapalli 
6605e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
6615e6808b4SNaveen Mamindlapalli 		for (schq = 0; schq < rsp->schq[lvl]; schq++) {
6625e6808b4SNaveen Mamindlapalli 			cfg->schq_list[lvl][schq] =
6635e6808b4SNaveen Mamindlapalli 				rsp->schq_list[lvl][schq];
6645e6808b4SNaveen Mamindlapalli 		}
6655e6808b4SNaveen Mamindlapalli 	}
6665e6808b4SNaveen Mamindlapalli 
6675e6808b4SNaveen Mamindlapalli 	pfvf->qos.link_cfg_lvl = rsp->link_cfg_lvl;
66847a9656fSNaveen Mamindlapalli 	pfvf->hw.txschq_aggr_lvl_rr_prio = rsp->aggr_lvl_rr_prio;
6695e6808b4SNaveen Mamindlapalli 
6705e6808b4SNaveen Mamindlapalli out:
6715e6808b4SNaveen Mamindlapalli 	mutex_unlock(&mbox->lock);
6725e6808b4SNaveen Mamindlapalli 	return rc;
6735e6808b4SNaveen Mamindlapalli }
6745e6808b4SNaveen Mamindlapalli 
otx2_qos_free_unused_txschq(struct otx2_nic * pfvf,struct otx2_qos_cfg * cfg)675f78dca69SNaveen Mamindlapalli static void otx2_qos_free_unused_txschq(struct otx2_nic *pfvf,
676f78dca69SNaveen Mamindlapalli 					struct otx2_qos_cfg *cfg)
677f78dca69SNaveen Mamindlapalli {
678f78dca69SNaveen Mamindlapalli 	int lvl, idx, schq;
679f78dca69SNaveen Mamindlapalli 
680f78dca69SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
681f78dca69SNaveen Mamindlapalli 		for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
682f78dca69SNaveen Mamindlapalli 			if (!cfg->schq_index_used[lvl][idx]) {
683f78dca69SNaveen Mamindlapalli 				schq = cfg->schq_contig_list[lvl][idx];
684f78dca69SNaveen Mamindlapalli 				otx2_txschq_free_one(pfvf, lvl, schq);
685f78dca69SNaveen Mamindlapalli 			}
686f78dca69SNaveen Mamindlapalli 		}
687f78dca69SNaveen Mamindlapalli 	}
688f78dca69SNaveen Mamindlapalli }
689f78dca69SNaveen Mamindlapalli 
otx2_qos_txschq_fill_cfg_schq(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)6905e6808b4SNaveen Mamindlapalli static void otx2_qos_txschq_fill_cfg_schq(struct otx2_nic *pfvf,
6915e6808b4SNaveen Mamindlapalli 					  struct otx2_qos_node *node,
6925e6808b4SNaveen Mamindlapalli 					  struct otx2_qos_cfg *cfg)
6935e6808b4SNaveen Mamindlapalli {
6945e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
6955e6808b4SNaveen Mamindlapalli 	int cnt;
6965e6808b4SNaveen Mamindlapalli 
6975e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_schq_list, list) {
6985e6808b4SNaveen Mamindlapalli 		cnt = cfg->dwrr_node_pos[tmp->level];
6995e6808b4SNaveen Mamindlapalli 		tmp->schq = cfg->schq_list[tmp->level][cnt];
7005e6808b4SNaveen Mamindlapalli 		cfg->dwrr_node_pos[tmp->level]++;
7015e6808b4SNaveen Mamindlapalli 	}
7025e6808b4SNaveen Mamindlapalli }
7035e6808b4SNaveen Mamindlapalli 
otx2_qos_txschq_fill_cfg_tl(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)7045e6808b4SNaveen Mamindlapalli static void otx2_qos_txschq_fill_cfg_tl(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_list, list) {
7125e6808b4SNaveen Mamindlapalli 		otx2_qos_txschq_fill_cfg_tl(pfvf, tmp, cfg);
7135e6808b4SNaveen Mamindlapalli 		cnt = cfg->static_node_pos[tmp->level];
714f78dca69SNaveen Mamindlapalli 		tmp->schq = cfg->schq_contig_list[tmp->level][tmp->txschq_idx];
715f78dca69SNaveen Mamindlapalli 		cfg->schq_index_used[tmp->level][tmp->txschq_idx] = true;
7165e6808b4SNaveen Mamindlapalli 		if (cnt == 0)
717f78dca69SNaveen Mamindlapalli 			node->prio_anchor =
718f78dca69SNaveen Mamindlapalli 				cfg->schq_contig_list[tmp->level][0];
7195e6808b4SNaveen Mamindlapalli 		cfg->static_node_pos[tmp->level]++;
7205e6808b4SNaveen Mamindlapalli 		otx2_qos_txschq_fill_cfg_schq(pfvf, tmp, cfg);
7215e6808b4SNaveen Mamindlapalli 	}
7225e6808b4SNaveen Mamindlapalli }
7235e6808b4SNaveen Mamindlapalli 
otx2_qos_txschq_fill_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)7245e6808b4SNaveen Mamindlapalli static void otx2_qos_txschq_fill_cfg(struct otx2_nic *pfvf,
7255e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_node *node,
7265e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_cfg *cfg)
7275e6808b4SNaveen Mamindlapalli {
7285e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
7295e6808b4SNaveen Mamindlapalli 	otx2_qos_txschq_fill_cfg_tl(pfvf, node, cfg);
7305e6808b4SNaveen Mamindlapalli 	otx2_qos_txschq_fill_cfg_schq(pfvf, node, cfg);
731f78dca69SNaveen Mamindlapalli 	otx2_qos_free_unused_txschq(pfvf, cfg);
7325e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
7335e6808b4SNaveen Mamindlapalli }
7345e6808b4SNaveen Mamindlapalli 
__otx2_qos_assign_base_idx_tl(struct otx2_nic * pfvf,struct otx2_qos_node * tmp,unsigned long * child_idx_bmap,int child_cnt)735f78dca69SNaveen Mamindlapalli static void __otx2_qos_assign_base_idx_tl(struct otx2_nic *pfvf,
736f78dca69SNaveen Mamindlapalli 					  struct otx2_qos_node *tmp,
737f78dca69SNaveen Mamindlapalli 					  unsigned long *child_idx_bmap,
738f78dca69SNaveen Mamindlapalli 					  int child_cnt)
739f78dca69SNaveen Mamindlapalli {
740f78dca69SNaveen Mamindlapalli 	int idx;
741f78dca69SNaveen Mamindlapalli 
742f78dca69SNaveen Mamindlapalli 	if (tmp->txschq_idx != OTX2_QOS_INVALID_TXSCHQ_IDX)
743f78dca69SNaveen Mamindlapalli 		return;
744f78dca69SNaveen Mamindlapalli 
745f78dca69SNaveen Mamindlapalli 	/* assign static nodes 1:1 prio mapping first, then remaining nodes */
746f78dca69SNaveen Mamindlapalli 	for (idx = 0; idx < child_cnt; idx++) {
747f78dca69SNaveen Mamindlapalli 		if (tmp->is_static && tmp->prio == idx &&
748f78dca69SNaveen Mamindlapalli 		    !test_bit(idx, child_idx_bmap)) {
749f78dca69SNaveen Mamindlapalli 			tmp->txschq_idx = idx;
750f78dca69SNaveen Mamindlapalli 			set_bit(idx, child_idx_bmap);
751f78dca69SNaveen Mamindlapalli 			return;
752f78dca69SNaveen Mamindlapalli 		} else if (!tmp->is_static && idx >= tmp->prio &&
753f78dca69SNaveen Mamindlapalli 			   !test_bit(idx, child_idx_bmap)) {
754f78dca69SNaveen Mamindlapalli 			tmp->txschq_idx = idx;
755f78dca69SNaveen Mamindlapalli 			set_bit(idx, child_idx_bmap);
756f78dca69SNaveen Mamindlapalli 			return;
757f78dca69SNaveen Mamindlapalli 		}
758f78dca69SNaveen Mamindlapalli 	}
759f78dca69SNaveen Mamindlapalli }
760f78dca69SNaveen Mamindlapalli 
otx2_qos_assign_base_idx_tl(struct otx2_nic * pfvf,struct otx2_qos_node * node)761f78dca69SNaveen Mamindlapalli static int otx2_qos_assign_base_idx_tl(struct otx2_nic *pfvf,
762f78dca69SNaveen Mamindlapalli 				       struct otx2_qos_node *node)
763f78dca69SNaveen Mamindlapalli {
764f78dca69SNaveen Mamindlapalli 	unsigned long *child_idx_bmap;
765f78dca69SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
766f78dca69SNaveen Mamindlapalli 	int child_cnt;
767f78dca69SNaveen Mamindlapalli 
768f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list)
769f78dca69SNaveen Mamindlapalli 		tmp->txschq_idx = OTX2_QOS_INVALID_TXSCHQ_IDX;
770f78dca69SNaveen Mamindlapalli 
771f78dca69SNaveen Mamindlapalli 	/* allocate child index array */
772f78dca69SNaveen Mamindlapalli 	child_cnt = node->child_dwrr_cnt + node->max_static_prio + 1;
773f78dca69SNaveen Mamindlapalli 	child_idx_bmap = kcalloc(BITS_TO_LONGS(child_cnt),
774f78dca69SNaveen Mamindlapalli 				 sizeof(unsigned long),
775f78dca69SNaveen Mamindlapalli 				 GFP_KERNEL);
776f78dca69SNaveen Mamindlapalli 	if (!child_idx_bmap)
777f78dca69SNaveen Mamindlapalli 		return -ENOMEM;
778f78dca69SNaveen Mamindlapalli 
779f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list)
780f78dca69SNaveen Mamindlapalli 		otx2_qos_assign_base_idx_tl(pfvf, tmp);
781f78dca69SNaveen Mamindlapalli 
782f78dca69SNaveen Mamindlapalli 	/* assign base index of static priority children first */
783f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list) {
784f78dca69SNaveen Mamindlapalli 		if (!tmp->is_static)
785f78dca69SNaveen Mamindlapalli 			continue;
786f78dca69SNaveen Mamindlapalli 		__otx2_qos_assign_base_idx_tl(pfvf, tmp, child_idx_bmap,
787f78dca69SNaveen Mamindlapalli 					      child_cnt);
788f78dca69SNaveen Mamindlapalli 	}
789f78dca69SNaveen Mamindlapalli 
790f78dca69SNaveen Mamindlapalli 	/* assign base index of dwrr priority children */
791f78dca69SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list)
792f78dca69SNaveen Mamindlapalli 		__otx2_qos_assign_base_idx_tl(pfvf, tmp, child_idx_bmap,
793f78dca69SNaveen Mamindlapalli 					      child_cnt);
794f78dca69SNaveen Mamindlapalli 
795f78dca69SNaveen Mamindlapalli 	kfree(child_idx_bmap);
796f78dca69SNaveen Mamindlapalli 
797f78dca69SNaveen Mamindlapalli 	return 0;
798f78dca69SNaveen Mamindlapalli }
799f78dca69SNaveen Mamindlapalli 
otx2_qos_assign_base_idx(struct otx2_nic * pfvf,struct otx2_qos_node * node)800f78dca69SNaveen Mamindlapalli static int otx2_qos_assign_base_idx(struct otx2_nic *pfvf,
801f78dca69SNaveen Mamindlapalli 				    struct otx2_qos_node *node)
802f78dca69SNaveen Mamindlapalli {
803f78dca69SNaveen Mamindlapalli 	int ret = 0;
804f78dca69SNaveen Mamindlapalli 
805f78dca69SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
806f78dca69SNaveen Mamindlapalli 	ret = otx2_qos_assign_base_idx_tl(pfvf, node);
807f78dca69SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
808f78dca69SNaveen Mamindlapalli 
809f78dca69SNaveen Mamindlapalli 	return ret;
810f78dca69SNaveen Mamindlapalli }
811f78dca69SNaveen Mamindlapalli 
otx2_qos_txschq_push_cfg_schq(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)8125e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_push_cfg_schq(struct otx2_nic *pfvf,
8135e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_node *node,
8145e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_cfg *cfg)
8155e6808b4SNaveen Mamindlapalli {
8165e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
8175e6808b4SNaveen Mamindlapalli 	int ret;
8185e6808b4SNaveen Mamindlapalli 
8195e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_schq_list, list) {
8205e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_config(pfvf, tmp);
8215e6808b4SNaveen Mamindlapalli 		if (ret)
8225e6808b4SNaveen Mamindlapalli 			return -EIO;
8235e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_set_parent_topology(pfvf, tmp->parent);
8245e6808b4SNaveen Mamindlapalli 		if (ret)
8255e6808b4SNaveen Mamindlapalli 			return -EIO;
8265e6808b4SNaveen Mamindlapalli 	}
8275e6808b4SNaveen Mamindlapalli 
8285e6808b4SNaveen Mamindlapalli 	return 0;
8295e6808b4SNaveen Mamindlapalli }
8305e6808b4SNaveen Mamindlapalli 
otx2_qos_txschq_push_cfg_tl(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)8315e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_push_cfg_tl(struct otx2_nic *pfvf,
8325e6808b4SNaveen Mamindlapalli 				       struct otx2_qos_node *node,
8335e6808b4SNaveen Mamindlapalli 				       struct otx2_qos_cfg *cfg)
8345e6808b4SNaveen Mamindlapalli {
8355e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
8365e6808b4SNaveen Mamindlapalli 	int ret;
8375e6808b4SNaveen Mamindlapalli 
8385e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list) {
8395e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_push_cfg_tl(pfvf, tmp, cfg);
8405e6808b4SNaveen Mamindlapalli 		if (ret)
8415e6808b4SNaveen Mamindlapalli 			return -EIO;
8425e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_config(pfvf, tmp);
8435e6808b4SNaveen Mamindlapalli 		if (ret)
8445e6808b4SNaveen Mamindlapalli 			return -EIO;
8455e6808b4SNaveen Mamindlapalli 		ret = otx2_qos_txschq_push_cfg_schq(pfvf, tmp, cfg);
8465e6808b4SNaveen Mamindlapalli 		if (ret)
8475e6808b4SNaveen Mamindlapalli 			return -EIO;
8485e6808b4SNaveen Mamindlapalli 	}
8495e6808b4SNaveen Mamindlapalli 
8505e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_set_parent_topology(pfvf, node);
8515e6808b4SNaveen Mamindlapalli 	if (ret)
8525e6808b4SNaveen Mamindlapalli 		return -EIO;
8535e6808b4SNaveen Mamindlapalli 
8545e6808b4SNaveen Mamindlapalli 	return 0;
8555e6808b4SNaveen Mamindlapalli }
8565e6808b4SNaveen Mamindlapalli 
otx2_qos_txschq_push_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)8575e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_push_cfg(struct otx2_nic *pfvf,
8585e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_node *node,
8595e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_cfg *cfg)
8605e6808b4SNaveen Mamindlapalli {
8615e6808b4SNaveen Mamindlapalli 	int ret;
8625e6808b4SNaveen Mamindlapalli 
8635e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
8645e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_push_cfg_tl(pfvf, node, cfg);
8655e6808b4SNaveen Mamindlapalli 	if (ret)
8665e6808b4SNaveen Mamindlapalli 		goto out;
8675e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_push_cfg_schq(pfvf, node, cfg);
8685e6808b4SNaveen Mamindlapalli out:
8695e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
8705e6808b4SNaveen Mamindlapalli 	return ret;
8715e6808b4SNaveen Mamindlapalli }
8725e6808b4SNaveen Mamindlapalli 
otx2_qos_txschq_update_config(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)8735e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_update_config(struct otx2_nic *pfvf,
8745e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_node *node,
8755e6808b4SNaveen Mamindlapalli 					 struct otx2_qos_cfg *cfg)
8765e6808b4SNaveen Mamindlapalli {
8775e6808b4SNaveen Mamindlapalli 	otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
8785e6808b4SNaveen Mamindlapalli 
8795e6808b4SNaveen Mamindlapalli 	return otx2_qos_txschq_push_cfg(pfvf, node, cfg);
8805e6808b4SNaveen Mamindlapalli }
8815e6808b4SNaveen Mamindlapalli 
otx2_qos_txschq_update_root_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * root,struct otx2_qos_cfg * cfg)8825e6808b4SNaveen Mamindlapalli static int otx2_qos_txschq_update_root_cfg(struct otx2_nic *pfvf,
8835e6808b4SNaveen Mamindlapalli 					   struct otx2_qos_node *root,
8845e6808b4SNaveen Mamindlapalli 					   struct otx2_qos_cfg *cfg)
8855e6808b4SNaveen Mamindlapalli {
8865e6808b4SNaveen Mamindlapalli 	root->schq = cfg->schq_list[root->level][0];
8875e6808b4SNaveen Mamindlapalli 	return otx2_qos_txschq_config(pfvf, root);
8885e6808b4SNaveen Mamindlapalli }
8895e6808b4SNaveen Mamindlapalli 
otx2_qos_free_cfg(struct otx2_nic * pfvf,struct otx2_qos_cfg * cfg)8905e6808b4SNaveen Mamindlapalli static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg)
8915e6808b4SNaveen Mamindlapalli {
8925e6808b4SNaveen Mamindlapalli 	int lvl, idx, schq;
8935e6808b4SNaveen Mamindlapalli 
8945e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
8955e6808b4SNaveen Mamindlapalli 		for (idx = 0; idx < cfg->schq[lvl]; idx++) {
8965e6808b4SNaveen Mamindlapalli 			schq = cfg->schq_list[lvl][idx];
8975e6808b4SNaveen Mamindlapalli 			otx2_txschq_free_one(pfvf, lvl, schq);
8985e6808b4SNaveen Mamindlapalli 		}
8995e6808b4SNaveen Mamindlapalli 	}
9005e6808b4SNaveen Mamindlapalli 
9015e6808b4SNaveen Mamindlapalli 	for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
9025e6808b4SNaveen Mamindlapalli 		for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
903f78dca69SNaveen Mamindlapalli 			if (cfg->schq_index_used[lvl][idx]) {
9045e6808b4SNaveen Mamindlapalli 				schq = cfg->schq_contig_list[lvl][idx];
9055e6808b4SNaveen Mamindlapalli 				otx2_txschq_free_one(pfvf, lvl, schq);
9065e6808b4SNaveen Mamindlapalli 			}
9075e6808b4SNaveen Mamindlapalli 		}
9085e6808b4SNaveen Mamindlapalli 	}
909f78dca69SNaveen Mamindlapalli }
9105e6808b4SNaveen Mamindlapalli 
otx2_qos_enadis_sq(struct otx2_nic * pfvf,struct otx2_qos_node * node,u16 qid)9115e6808b4SNaveen Mamindlapalli static void otx2_qos_enadis_sq(struct otx2_nic *pfvf,
9125e6808b4SNaveen Mamindlapalli 			       struct otx2_qos_node *node,
9135e6808b4SNaveen Mamindlapalli 			       u16 qid)
9145e6808b4SNaveen Mamindlapalli {
9155e6808b4SNaveen Mamindlapalli 	if (pfvf->qos.qid_to_sqmap[qid] != OTX2_QOS_INVALID_SQ)
9165e6808b4SNaveen Mamindlapalli 		otx2_qos_disable_sq(pfvf, qid);
9175e6808b4SNaveen Mamindlapalli 
9185e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = node->schq;
9195e6808b4SNaveen Mamindlapalli 	otx2_qos_enable_sq(pfvf, qid);
9205e6808b4SNaveen Mamindlapalli }
9215e6808b4SNaveen Mamindlapalli 
otx2_qos_update_smq_schq(struct otx2_nic * pfvf,struct otx2_qos_node * node,bool action)9225e6808b4SNaveen Mamindlapalli static void otx2_qos_update_smq_schq(struct otx2_nic *pfvf,
9235e6808b4SNaveen Mamindlapalli 				     struct otx2_qos_node *node,
9245e6808b4SNaveen Mamindlapalli 				     bool action)
9255e6808b4SNaveen Mamindlapalli {
9265e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
9275e6808b4SNaveen Mamindlapalli 
9285e6808b4SNaveen Mamindlapalli 	if (node->qid == OTX2_QOS_QID_INNER)
9295e6808b4SNaveen Mamindlapalli 		return;
9305e6808b4SNaveen Mamindlapalli 
9315e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_schq_list, list) {
9325e6808b4SNaveen Mamindlapalli 		if (tmp->level == NIX_TXSCH_LVL_MDQ) {
9335e6808b4SNaveen Mamindlapalli 			if (action == QOS_SMQ_FLUSH)
9345e6808b4SNaveen Mamindlapalli 				otx2_smq_flush(pfvf, tmp->schq);
9355e6808b4SNaveen Mamindlapalli 			else
9365e6808b4SNaveen Mamindlapalli 				otx2_qos_enadis_sq(pfvf, tmp, node->qid);
9375e6808b4SNaveen Mamindlapalli 		}
9385e6808b4SNaveen Mamindlapalli 	}
9395e6808b4SNaveen Mamindlapalli }
9405e6808b4SNaveen Mamindlapalli 
__otx2_qos_update_smq(struct otx2_nic * pfvf,struct otx2_qos_node * node,bool action)9415e6808b4SNaveen Mamindlapalli static void __otx2_qos_update_smq(struct otx2_nic *pfvf,
9425e6808b4SNaveen Mamindlapalli 				  struct otx2_qos_node *node,
9435e6808b4SNaveen Mamindlapalli 				  bool action)
9445e6808b4SNaveen Mamindlapalli {
9455e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *tmp;
9465e6808b4SNaveen Mamindlapalli 
9475e6808b4SNaveen Mamindlapalli 	list_for_each_entry(tmp, &node->child_list, list) {
9485e6808b4SNaveen Mamindlapalli 		__otx2_qos_update_smq(pfvf, tmp, action);
9495e6808b4SNaveen Mamindlapalli 		if (tmp->qid == OTX2_QOS_QID_INNER)
9505e6808b4SNaveen Mamindlapalli 			continue;
9515e6808b4SNaveen Mamindlapalli 		if (tmp->level == NIX_TXSCH_LVL_MDQ) {
9525e6808b4SNaveen Mamindlapalli 			if (action == QOS_SMQ_FLUSH)
9535e6808b4SNaveen Mamindlapalli 				otx2_smq_flush(pfvf, tmp->schq);
9545e6808b4SNaveen Mamindlapalli 			else
9555e6808b4SNaveen Mamindlapalli 				otx2_qos_enadis_sq(pfvf, tmp, tmp->qid);
9565e6808b4SNaveen Mamindlapalli 		} else {
9575e6808b4SNaveen Mamindlapalli 			otx2_qos_update_smq_schq(pfvf, tmp, action);
9585e6808b4SNaveen Mamindlapalli 		}
9595e6808b4SNaveen Mamindlapalli 	}
9605e6808b4SNaveen Mamindlapalli }
9615e6808b4SNaveen Mamindlapalli 
otx2_qos_update_smq(struct otx2_nic * pfvf,struct otx2_qos_node * node,bool action)9625e6808b4SNaveen Mamindlapalli static void otx2_qos_update_smq(struct otx2_nic *pfvf,
9635e6808b4SNaveen Mamindlapalli 				struct otx2_qos_node *node,
9645e6808b4SNaveen Mamindlapalli 				bool action)
9655e6808b4SNaveen Mamindlapalli {
9665e6808b4SNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
9675e6808b4SNaveen Mamindlapalli 	__otx2_qos_update_smq(pfvf, node, action);
9685e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq_schq(pfvf, node, action);
9695e6808b4SNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
9705e6808b4SNaveen Mamindlapalli }
9715e6808b4SNaveen Mamindlapalli 
otx2_qos_push_txschq_cfg(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)9725e6808b4SNaveen Mamindlapalli static int otx2_qos_push_txschq_cfg(struct otx2_nic *pfvf,
9735e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_node *node,
9745e6808b4SNaveen Mamindlapalli 				    struct otx2_qos_cfg *cfg)
9755e6808b4SNaveen Mamindlapalli {
9765e6808b4SNaveen Mamindlapalli 	int ret;
9775e6808b4SNaveen Mamindlapalli 
9785e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_alloc(pfvf, cfg);
9795e6808b4SNaveen Mamindlapalli 	if (ret)
9805e6808b4SNaveen Mamindlapalli 		return -ENOSPC;
9815e6808b4SNaveen Mamindlapalli 
982f78dca69SNaveen Mamindlapalli 	ret = otx2_qos_assign_base_idx(pfvf, node);
983f78dca69SNaveen Mamindlapalli 	if (ret)
984f78dca69SNaveen Mamindlapalli 		return -ENOMEM;
985f78dca69SNaveen Mamindlapalli 
9865e6808b4SNaveen Mamindlapalli 	if (!(pfvf->netdev->flags & IFF_UP)) {
9875e6808b4SNaveen Mamindlapalli 		otx2_qos_txschq_fill_cfg(pfvf, node, cfg);
9885e6808b4SNaveen Mamindlapalli 		return 0;
9895e6808b4SNaveen Mamindlapalli 	}
9905e6808b4SNaveen Mamindlapalli 
9915e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_txschq_update_config(pfvf, node, cfg);
9925e6808b4SNaveen Mamindlapalli 	if (ret) {
9935e6808b4SNaveen Mamindlapalli 		otx2_qos_free_cfg(pfvf, cfg);
9945e6808b4SNaveen Mamindlapalli 		return -EIO;
9955e6808b4SNaveen Mamindlapalli 	}
9965e6808b4SNaveen Mamindlapalli 
9975e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
9985e6808b4SNaveen Mamindlapalli 
9995e6808b4SNaveen Mamindlapalli 	return 0;
10005e6808b4SNaveen Mamindlapalli }
10015e6808b4SNaveen Mamindlapalli 
otx2_qos_update_tree(struct otx2_nic * pfvf,struct otx2_qos_node * node,struct otx2_qos_cfg * cfg)10025e6808b4SNaveen Mamindlapalli static int otx2_qos_update_tree(struct otx2_nic *pfvf,
10035e6808b4SNaveen Mamindlapalli 				struct otx2_qos_node *node,
10045e6808b4SNaveen Mamindlapalli 				struct otx2_qos_cfg *cfg)
10055e6808b4SNaveen Mamindlapalli {
10065e6808b4SNaveen Mamindlapalli 	otx2_qos_prepare_txschq_cfg(pfvf, node->parent, cfg);
10075e6808b4SNaveen Mamindlapalli 	return otx2_qos_push_txschq_cfg(pfvf, node->parent, cfg);
10085e6808b4SNaveen Mamindlapalli }
10095e6808b4SNaveen Mamindlapalli 
otx2_qos_root_add(struct otx2_nic * pfvf,u16 htb_maj_id,u16 htb_defcls,struct netlink_ext_ack * extack)10105e6808b4SNaveen Mamindlapalli static int otx2_qos_root_add(struct otx2_nic *pfvf, u16 htb_maj_id, u16 htb_defcls,
10115e6808b4SNaveen Mamindlapalli 			     struct netlink_ext_ack *extack)
10125e6808b4SNaveen Mamindlapalli {
10135e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *new_cfg;
10145e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
10155e6808b4SNaveen Mamindlapalli 	int err;
10165e6808b4SNaveen Mamindlapalli 
10175e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
10185e6808b4SNaveen Mamindlapalli 		   "TC_HTB_CREATE: handle=0x%x defcls=0x%x\n",
10195e6808b4SNaveen Mamindlapalli 		   htb_maj_id, htb_defcls);
10205e6808b4SNaveen Mamindlapalli 
10215e6808b4SNaveen Mamindlapalli 	root = otx2_qos_alloc_root(pfvf);
10225e6808b4SNaveen Mamindlapalli 	if (IS_ERR(root)) {
10235e6808b4SNaveen Mamindlapalli 		err = PTR_ERR(root);
10245e6808b4SNaveen Mamindlapalli 		return err;
10255e6808b4SNaveen Mamindlapalli 	}
10265e6808b4SNaveen Mamindlapalli 
10275e6808b4SNaveen Mamindlapalli 	/* allocate txschq queue */
10285e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
10295e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
10305e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
10315e6808b4SNaveen Mamindlapalli 		err = -ENOMEM;
10325e6808b4SNaveen Mamindlapalli 		goto free_root_node;
10335e6808b4SNaveen Mamindlapalli 	}
10345e6808b4SNaveen Mamindlapalli 	/* allocate htb root node */
10355e6808b4SNaveen Mamindlapalli 	new_cfg->schq[root->level] = 1;
10365e6808b4SNaveen Mamindlapalli 	err = otx2_qos_txschq_alloc(pfvf, new_cfg);
10375e6808b4SNaveen Mamindlapalli 	if (err) {
10385e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Error allocating txschq");
10395e6808b4SNaveen Mamindlapalli 		goto free_root_node;
10405e6808b4SNaveen Mamindlapalli 	}
10415e6808b4SNaveen Mamindlapalli 
104247a9656fSNaveen Mamindlapalli 	/* Update TL1 RR PRIO */
104347a9656fSNaveen Mamindlapalli 	if (root->level == NIX_TXSCH_LVL_TL1) {
104447a9656fSNaveen Mamindlapalli 		root->child_dwrr_prio = pfvf->hw.txschq_aggr_lvl_rr_prio;
104547a9656fSNaveen Mamindlapalli 		netdev_dbg(pfvf->netdev,
104647a9656fSNaveen Mamindlapalli 			   "TL1 DWRR Priority %d\n", root->child_dwrr_prio);
104747a9656fSNaveen Mamindlapalli 	}
104847a9656fSNaveen Mamindlapalli 
10495e6808b4SNaveen Mamindlapalli 	if (!(pfvf->netdev->flags & IFF_UP) ||
10505e6808b4SNaveen Mamindlapalli 	    root->level == NIX_TXSCH_LVL_TL1) {
10515e6808b4SNaveen Mamindlapalli 		root->schq = new_cfg->schq_list[root->level][0];
10525e6808b4SNaveen Mamindlapalli 		goto out;
10535e6808b4SNaveen Mamindlapalli 	}
10545e6808b4SNaveen Mamindlapalli 
10555e6808b4SNaveen Mamindlapalli 	/* update the txschq configuration in hw */
10565e6808b4SNaveen Mamindlapalli 	err = otx2_qos_txschq_update_root_cfg(pfvf, root, new_cfg);
10575e6808b4SNaveen Mamindlapalli 	if (err) {
10585e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack,
10595e6808b4SNaveen Mamindlapalli 				   "Error updating txschq configuration");
10605e6808b4SNaveen Mamindlapalli 		goto txschq_free;
10615e6808b4SNaveen Mamindlapalli 	}
10625e6808b4SNaveen Mamindlapalli 
10635e6808b4SNaveen Mamindlapalli out:
10645e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(pfvf->qos.defcls, htb_defcls);
10655e6808b4SNaveen Mamindlapalli 	/* Pairs with smp_load_acquire() in ndo_select_queue */
10665e6808b4SNaveen Mamindlapalli 	smp_store_release(&pfvf->qos.maj_id, htb_maj_id);
10675e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
10685e6808b4SNaveen Mamindlapalli 	return 0;
10695e6808b4SNaveen Mamindlapalli 
10705e6808b4SNaveen Mamindlapalli txschq_free:
10715e6808b4SNaveen Mamindlapalli 	otx2_qos_free_cfg(pfvf, new_cfg);
10725e6808b4SNaveen Mamindlapalli free_root_node:
10735e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
10745e6808b4SNaveen Mamindlapalli 	otx2_qos_sw_node_delete(pfvf, root);
10755e6808b4SNaveen Mamindlapalli 	return err;
10765e6808b4SNaveen Mamindlapalli }
10775e6808b4SNaveen Mamindlapalli 
otx2_qos_root_destroy(struct otx2_nic * pfvf)10785e6808b4SNaveen Mamindlapalli static int otx2_qos_root_destroy(struct otx2_nic *pfvf)
10795e6808b4SNaveen Mamindlapalli {
10805e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
10815e6808b4SNaveen Mamindlapalli 
10825e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev, "TC_HTB_DESTROY\n");
10835e6808b4SNaveen Mamindlapalli 
10845e6808b4SNaveen Mamindlapalli 	/* find root node */
10855e6808b4SNaveen Mamindlapalli 	root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
10865e6808b4SNaveen Mamindlapalli 	if (!root)
10875e6808b4SNaveen Mamindlapalli 		return -ENOENT;
10885e6808b4SNaveen Mamindlapalli 
10895e6808b4SNaveen Mamindlapalli 	/* free the hw mappings */
10905e6808b4SNaveen Mamindlapalli 	otx2_qos_destroy_node(pfvf, root);
10915e6808b4SNaveen Mamindlapalli 
10925e6808b4SNaveen Mamindlapalli 	return 0;
10935e6808b4SNaveen Mamindlapalli }
10945e6808b4SNaveen Mamindlapalli 
otx2_qos_validate_quantum(struct otx2_nic * pfvf,u32 quantum)109547a9656fSNaveen Mamindlapalli static int otx2_qos_validate_quantum(struct otx2_nic *pfvf, u32 quantum)
10965e6808b4SNaveen Mamindlapalli {
109747a9656fSNaveen Mamindlapalli 	u32 rr_weight = otx2_qos_quantum_to_dwrr_weight(pfvf, quantum);
109847a9656fSNaveen Mamindlapalli 	int err = 0;
109947a9656fSNaveen Mamindlapalli 
110047a9656fSNaveen Mamindlapalli 	/* Max Round robin weight supported by octeontx2 and CN10K
110147a9656fSNaveen Mamindlapalli 	 * is different. Validate accordingly
110247a9656fSNaveen Mamindlapalli 	 */
110347a9656fSNaveen Mamindlapalli 	if (is_dev_otx2(pfvf->pdev))
110447a9656fSNaveen Mamindlapalli 		err = (rr_weight > OTX2_MAX_RR_QUANTUM) ? -EINVAL : 0;
110547a9656fSNaveen Mamindlapalli 	else if	(rr_weight > CN10K_MAX_RR_WEIGHT)
110647a9656fSNaveen Mamindlapalli 		err = -EINVAL;
110747a9656fSNaveen Mamindlapalli 
110847a9656fSNaveen Mamindlapalli 	return err;
11095e6808b4SNaveen Mamindlapalli }
11105e6808b4SNaveen Mamindlapalli 
otx2_qos_validate_dwrr_cfg(struct otx2_qos_node * parent,struct netlink_ext_ack * extack,struct otx2_nic * pfvf,u64 prio,u64 quantum)111147a9656fSNaveen Mamindlapalli static int otx2_qos_validate_dwrr_cfg(struct otx2_qos_node *parent,
111247a9656fSNaveen Mamindlapalli 				      struct netlink_ext_ack *extack,
111347a9656fSNaveen Mamindlapalli 				      struct otx2_nic *pfvf,
111447a9656fSNaveen Mamindlapalli 				      u64 prio, u64 quantum)
111547a9656fSNaveen Mamindlapalli {
111647a9656fSNaveen Mamindlapalli 	int err;
111747a9656fSNaveen Mamindlapalli 
111847a9656fSNaveen Mamindlapalli 	err = otx2_qos_validate_quantum(pfvf, quantum);
111947a9656fSNaveen Mamindlapalli 	if (err) {
112047a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Unsupported quantum value");
112147a9656fSNaveen Mamindlapalli 		return err;
112247a9656fSNaveen Mamindlapalli 	}
112347a9656fSNaveen Mamindlapalli 
112447a9656fSNaveen Mamindlapalli 	if (parent->child_dwrr_prio == OTX2_QOS_DEFAULT_PRIO) {
112547a9656fSNaveen Mamindlapalli 		parent->child_dwrr_prio = prio;
112647a9656fSNaveen Mamindlapalli 	} else if (prio != parent->child_dwrr_prio) {
112747a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Only one DWRR group is allowed");
112847a9656fSNaveen Mamindlapalli 		return -EOPNOTSUPP;
11295e6808b4SNaveen Mamindlapalli 	}
11305e6808b4SNaveen Mamindlapalli 
11315e6808b4SNaveen Mamindlapalli 	return 0;
11325e6808b4SNaveen Mamindlapalli }
11335e6808b4SNaveen Mamindlapalli 
otx2_qos_validate_configuration(struct otx2_qos_node * parent,struct netlink_ext_ack * extack,struct otx2_nic * pfvf,u64 prio,bool static_cfg)113447a9656fSNaveen Mamindlapalli static int otx2_qos_validate_configuration(struct otx2_qos_node *parent,
113547a9656fSNaveen Mamindlapalli 					   struct netlink_ext_ack *extack,
113647a9656fSNaveen Mamindlapalli 					   struct otx2_nic *pfvf,
113747a9656fSNaveen Mamindlapalli 					   u64 prio, bool static_cfg)
113847a9656fSNaveen Mamindlapalli {
113947a9656fSNaveen Mamindlapalli 	if (prio == parent->child_dwrr_prio && static_cfg) {
114047a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "DWRR child group with same priority exists");
114147a9656fSNaveen Mamindlapalli 		return -EEXIST;
114247a9656fSNaveen Mamindlapalli 	}
114347a9656fSNaveen Mamindlapalli 
114447a9656fSNaveen Mamindlapalli 	if (static_cfg && test_bit(prio, parent->prio_bmap)) {
114547a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack,
114647a9656fSNaveen Mamindlapalli 				   "Static priority child with same priority exists");
114747a9656fSNaveen Mamindlapalli 		return -EEXIST;
114847a9656fSNaveen Mamindlapalli 	}
114947a9656fSNaveen Mamindlapalli 
115047a9656fSNaveen Mamindlapalli 	return 0;
115147a9656fSNaveen Mamindlapalli }
115247a9656fSNaveen Mamindlapalli 
otx2_reset_dwrr_prio(struct otx2_qos_node * parent,u64 prio)115347a9656fSNaveen Mamindlapalli static void otx2_reset_dwrr_prio(struct otx2_qos_node *parent, u64 prio)
115447a9656fSNaveen Mamindlapalli {
115547a9656fSNaveen Mamindlapalli 	/* For PF, root node dwrr priority is static */
115647a9656fSNaveen Mamindlapalli 	if (parent->level == NIX_TXSCH_LVL_TL1)
115747a9656fSNaveen Mamindlapalli 		return;
115847a9656fSNaveen Mamindlapalli 
115947a9656fSNaveen Mamindlapalli 	if (parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO) {
116047a9656fSNaveen Mamindlapalli 		parent->child_dwrr_prio = OTX2_QOS_DEFAULT_PRIO;
116147a9656fSNaveen Mamindlapalli 		clear_bit(prio, parent->prio_bmap);
116247a9656fSNaveen Mamindlapalli 	}
116347a9656fSNaveen Mamindlapalli }
116447a9656fSNaveen Mamindlapalli 
is_qos_node_dwrr(struct otx2_qos_node * parent,struct otx2_nic * pfvf,u64 prio)116547a9656fSNaveen Mamindlapalli static bool is_qos_node_dwrr(struct otx2_qos_node *parent,
116647a9656fSNaveen Mamindlapalli 			     struct otx2_nic *pfvf,
116747a9656fSNaveen Mamindlapalli 			     u64 prio)
116847a9656fSNaveen Mamindlapalli {
116947a9656fSNaveen Mamindlapalli 	struct otx2_qos_node *node;
117047a9656fSNaveen Mamindlapalli 	bool ret = false;
117147a9656fSNaveen Mamindlapalli 
117247a9656fSNaveen Mamindlapalli 	if (parent->child_dwrr_prio == prio)
117347a9656fSNaveen Mamindlapalli 		return true;
117447a9656fSNaveen Mamindlapalli 
117547a9656fSNaveen Mamindlapalli 	mutex_lock(&pfvf->qos.qos_lock);
117647a9656fSNaveen Mamindlapalli 	list_for_each_entry(node, &parent->child_list, list) {
117747a9656fSNaveen Mamindlapalli 		if (prio == node->prio) {
117847a9656fSNaveen Mamindlapalli 			if (parent->child_dwrr_prio != OTX2_QOS_DEFAULT_PRIO &&
117947a9656fSNaveen Mamindlapalli 			    parent->child_dwrr_prio != prio)
118047a9656fSNaveen Mamindlapalli 				continue;
118147a9656fSNaveen Mamindlapalli 
118247a9656fSNaveen Mamindlapalli 			if (otx2_qos_validate_quantum(pfvf, node->quantum)) {
118347a9656fSNaveen Mamindlapalli 				netdev_err(pfvf->netdev,
118447a9656fSNaveen Mamindlapalli 					   "Unsupported quantum value for existing classid=0x%x quantum=%d prio=%d",
118547a9656fSNaveen Mamindlapalli 					    node->classid, node->quantum,
118647a9656fSNaveen Mamindlapalli 					    node->prio);
118747a9656fSNaveen Mamindlapalli 				break;
118847a9656fSNaveen Mamindlapalli 			}
118947a9656fSNaveen Mamindlapalli 			/* mark old node as dwrr */
119047a9656fSNaveen Mamindlapalli 			node->is_static = false;
119147a9656fSNaveen Mamindlapalli 			parent->child_dwrr_cnt++;
119247a9656fSNaveen Mamindlapalli 			parent->child_static_cnt--;
119347a9656fSNaveen Mamindlapalli 			ret = true;
119447a9656fSNaveen Mamindlapalli 			break;
119547a9656fSNaveen Mamindlapalli 		}
119647a9656fSNaveen Mamindlapalli 	}
119747a9656fSNaveen Mamindlapalli 	mutex_unlock(&pfvf->qos.qos_lock);
119847a9656fSNaveen Mamindlapalli 
119947a9656fSNaveen Mamindlapalli 	return ret;
120047a9656fSNaveen Mamindlapalli }
120147a9656fSNaveen Mamindlapalli 
otx2_qos_leaf_alloc_queue(struct otx2_nic * pfvf,u16 classid,u32 parent_classid,u64 rate,u64 ceil,u64 prio,u32 quantum,struct netlink_ext_ack * extack)12025e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_alloc_queue(struct otx2_nic *pfvf, u16 classid,
12035e6808b4SNaveen Mamindlapalli 				     u32 parent_classid, u64 rate, u64 ceil,
120447a9656fSNaveen Mamindlapalli 				     u64 prio, u32 quantum,
120547a9656fSNaveen Mamindlapalli 				     struct netlink_ext_ack *extack)
12065e6808b4SNaveen Mamindlapalli {
12075e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *old_cfg, *new_cfg;
12085e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *parent;
12095e6808b4SNaveen Mamindlapalli 	int qid, ret, err;
121047a9656fSNaveen Mamindlapalli 	bool static_cfg;
12115e6808b4SNaveen Mamindlapalli 
12125e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
121347a9656fSNaveen Mamindlapalli 		   "TC_HTB_LEAF_ALLOC_QUEUE: classid=0x%x parent_classid=0x%x rate=%lld ceil=%lld prio=%lld quantum=%d\n",
121447a9656fSNaveen Mamindlapalli 		   classid, parent_classid, rate, ceil, prio, quantum);
12155e6808b4SNaveen Mamindlapalli 
12165e6808b4SNaveen Mamindlapalli 	if (prio > OTX2_QOS_MAX_PRIO) {
12175e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
12185e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
12195e6808b4SNaveen Mamindlapalli 		goto out;
12205e6808b4SNaveen Mamindlapalli 	}
12215e6808b4SNaveen Mamindlapalli 
122247a9656fSNaveen Mamindlapalli 	if (!quantum || quantum > INT_MAX) {
122347a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Invalid quantum, range 1 - 2147483647 bytes");
122447a9656fSNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
122547a9656fSNaveen Mamindlapalli 		goto out;
122647a9656fSNaveen Mamindlapalli 	}
122747a9656fSNaveen Mamindlapalli 
12285e6808b4SNaveen Mamindlapalli 	/* get parent node */
12295e6808b4SNaveen Mamindlapalli 	parent = otx2_sw_node_find(pfvf, parent_classid);
12305e6808b4SNaveen Mamindlapalli 	if (!parent) {
12315e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "parent node not found");
12325e6808b4SNaveen Mamindlapalli 		ret = -ENOENT;
12335e6808b4SNaveen Mamindlapalli 		goto out;
12345e6808b4SNaveen Mamindlapalli 	}
12355e6808b4SNaveen Mamindlapalli 	if (parent->level == NIX_TXSCH_LVL_MDQ) {
12365e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB qos max levels reached");
12375e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
12385e6808b4SNaveen Mamindlapalli 		goto out;
12395e6808b4SNaveen Mamindlapalli 	}
12405e6808b4SNaveen Mamindlapalli 
124147a9656fSNaveen Mamindlapalli 	static_cfg = !is_qos_node_dwrr(parent, pfvf, prio);
124247a9656fSNaveen Mamindlapalli 	ret = otx2_qos_validate_configuration(parent, extack, pfvf, prio,
124347a9656fSNaveen Mamindlapalli 					      static_cfg);
12445e6808b4SNaveen Mamindlapalli 	if (ret)
12455e6808b4SNaveen Mamindlapalli 		goto out;
12465e6808b4SNaveen Mamindlapalli 
124747a9656fSNaveen Mamindlapalli 	if (!static_cfg) {
124847a9656fSNaveen Mamindlapalli 		ret = otx2_qos_validate_dwrr_cfg(parent, extack, pfvf, prio,
124947a9656fSNaveen Mamindlapalli 						 quantum);
125047a9656fSNaveen Mamindlapalli 		if (ret)
125147a9656fSNaveen Mamindlapalli 			goto out;
125247a9656fSNaveen Mamindlapalli 	}
125347a9656fSNaveen Mamindlapalli 
125447a9656fSNaveen Mamindlapalli 	if (static_cfg)
1255f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt++;
125647a9656fSNaveen Mamindlapalli 	else
125747a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt++;
125847a9656fSNaveen Mamindlapalli 
12595e6808b4SNaveen Mamindlapalli 	set_bit(prio, parent->prio_bmap);
12605e6808b4SNaveen Mamindlapalli 
12615e6808b4SNaveen Mamindlapalli 	/* read current txschq configuration */
12625e6808b4SNaveen Mamindlapalli 	old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
12635e6808b4SNaveen Mamindlapalli 	if (!old_cfg) {
12645e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
12655e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
12665e6808b4SNaveen Mamindlapalli 		goto reset_prio;
12675e6808b4SNaveen Mamindlapalli 	}
12685e6808b4SNaveen Mamindlapalli 	otx2_qos_read_txschq_cfg(pfvf, parent, old_cfg);
12695e6808b4SNaveen Mamindlapalli 
12705e6808b4SNaveen Mamindlapalli 	/* allocate a new sq */
12715e6808b4SNaveen Mamindlapalli 	qid = otx2_qos_get_qid(pfvf);
12725e6808b4SNaveen Mamindlapalli 	if (qid < 0) {
12735e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Reached max supported QOS SQ's");
12745e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
12755e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
12765e6808b4SNaveen Mamindlapalli 	}
12775e6808b4SNaveen Mamindlapalli 
12785e6808b4SNaveen Mamindlapalli 	/* Actual SQ mapping will be updated after SMQ alloc */
12795e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
12805e6808b4SNaveen Mamindlapalli 
12815e6808b4SNaveen Mamindlapalli 	/* allocate and initialize a new child node */
12825e6808b4SNaveen Mamindlapalli 	node = otx2_qos_sw_create_leaf_node(pfvf, parent, classid, prio, rate,
128347a9656fSNaveen Mamindlapalli 					    ceil, quantum, qid, static_cfg);
12845e6808b4SNaveen Mamindlapalli 	if (IS_ERR(node)) {
12855e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
12865e6808b4SNaveen Mamindlapalli 		ret = PTR_ERR(node);
12875e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
12885e6808b4SNaveen Mamindlapalli 	}
12895e6808b4SNaveen Mamindlapalli 
12905e6808b4SNaveen Mamindlapalli 	/* push new txschq config to hw */
12915e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
12925e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
12935e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
12945e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
12955e6808b4SNaveen Mamindlapalli 		goto free_node;
12965e6808b4SNaveen Mamindlapalli 	}
12975e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_update_tree(pfvf, node, new_cfg);
12985e6808b4SNaveen Mamindlapalli 	if (ret) {
12995e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
13005e6808b4SNaveen Mamindlapalli 		kfree(new_cfg);
13015e6808b4SNaveen Mamindlapalli 		otx2_qos_sw_node_delete(pfvf, node);
13025e6808b4SNaveen Mamindlapalli 		/* restore the old qos tree */
13035e6808b4SNaveen Mamindlapalli 		err = otx2_qos_txschq_update_config(pfvf, parent, old_cfg);
13045e6808b4SNaveen Mamindlapalli 		if (err) {
13055e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev,
13065e6808b4SNaveen Mamindlapalli 				   "Failed to restore txcshq configuration");
13075e6808b4SNaveen Mamindlapalli 			goto free_old_cfg;
13085e6808b4SNaveen Mamindlapalli 		}
13095e6808b4SNaveen Mamindlapalli 
13105e6808b4SNaveen Mamindlapalli 		otx2_qos_update_smq(pfvf, parent, QOS_CFG_SQ);
13115e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
13125e6808b4SNaveen Mamindlapalli 	}
13135e6808b4SNaveen Mamindlapalli 
13145e6808b4SNaveen Mamindlapalli 	/* update tx_real_queues */
13155e6808b4SNaveen Mamindlapalli 	otx2_qos_update_tx_netdev_queues(pfvf);
13165e6808b4SNaveen Mamindlapalli 
13175e6808b4SNaveen Mamindlapalli 	/* free new txschq config */
13185e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
13195e6808b4SNaveen Mamindlapalli 
13205e6808b4SNaveen Mamindlapalli 	/* free old txschq config */
13215e6808b4SNaveen Mamindlapalli 	otx2_qos_free_cfg(pfvf, old_cfg);
13225e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
13235e6808b4SNaveen Mamindlapalli 
13245e6808b4SNaveen Mamindlapalli 	return pfvf->hw.tx_queues + qid;
13255e6808b4SNaveen Mamindlapalli 
13265e6808b4SNaveen Mamindlapalli free_node:
13275e6808b4SNaveen Mamindlapalli 	otx2_qos_sw_node_delete(pfvf, node);
13285e6808b4SNaveen Mamindlapalli free_old_cfg:
13295e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
13305e6808b4SNaveen Mamindlapalli reset_prio:
133147a9656fSNaveen Mamindlapalli 	if (static_cfg)
1332f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt--;
133347a9656fSNaveen Mamindlapalli 	else
133447a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt--;
133547a9656fSNaveen Mamindlapalli 
13365e6808b4SNaveen Mamindlapalli 	clear_bit(prio, parent->prio_bmap);
13375e6808b4SNaveen Mamindlapalli out:
13385e6808b4SNaveen Mamindlapalli 	return ret;
13395e6808b4SNaveen Mamindlapalli }
13405e6808b4SNaveen Mamindlapalli 
otx2_qos_leaf_to_inner(struct otx2_nic * pfvf,u16 classid,u16 child_classid,u64 rate,u64 ceil,u64 prio,u32 quantum,struct netlink_ext_ack * extack)13415e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_to_inner(struct otx2_nic *pfvf, u16 classid,
13425e6808b4SNaveen Mamindlapalli 				  u16 child_classid, u64 rate, u64 ceil, u64 prio,
134347a9656fSNaveen Mamindlapalli 				  u32 quantum, struct netlink_ext_ack *extack)
13445e6808b4SNaveen Mamindlapalli {
13455e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *old_cfg, *new_cfg;
13465e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *child;
134747a9656fSNaveen Mamindlapalli 	bool static_cfg;
13485e6808b4SNaveen Mamindlapalli 	int ret, err;
13495e6808b4SNaveen Mamindlapalli 	u16 qid;
13505e6808b4SNaveen Mamindlapalli 
13515e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
13525e6808b4SNaveen Mamindlapalli 		   "TC_HTB_LEAF_TO_INNER classid %04x, child %04x, rate %llu, ceil %llu\n",
13535e6808b4SNaveen Mamindlapalli 		   classid, child_classid, rate, ceil);
13545e6808b4SNaveen Mamindlapalli 
13555e6808b4SNaveen Mamindlapalli 	if (prio > OTX2_QOS_MAX_PRIO) {
13565e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Valid priority range 0 to 7");
13575e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
13585e6808b4SNaveen Mamindlapalli 		goto out;
13595e6808b4SNaveen Mamindlapalli 	}
13605e6808b4SNaveen Mamindlapalli 
136147a9656fSNaveen Mamindlapalli 	if (!quantum || quantum > INT_MAX) {
136247a9656fSNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Invalid quantum, range 1 - 2147483647 bytes");
136347a9656fSNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
136447a9656fSNaveen Mamindlapalli 		goto out;
136547a9656fSNaveen Mamindlapalli 	}
136647a9656fSNaveen Mamindlapalli 
13675e6808b4SNaveen Mamindlapalli 	/* find node related to classid */
13685e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find(pfvf, classid);
13695e6808b4SNaveen Mamindlapalli 	if (!node) {
13705e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
13715e6808b4SNaveen Mamindlapalli 		ret = -ENOENT;
13725e6808b4SNaveen Mamindlapalli 		goto out;
13735e6808b4SNaveen Mamindlapalli 	}
13745e6808b4SNaveen Mamindlapalli 	/* check max qos txschq level */
13755e6808b4SNaveen Mamindlapalli 	if (node->level == NIX_TXSCH_LVL_MDQ) {
13765e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB qos level not supported");
13775e6808b4SNaveen Mamindlapalli 		ret = -EOPNOTSUPP;
13785e6808b4SNaveen Mamindlapalli 		goto out;
13795e6808b4SNaveen Mamindlapalli 	}
13805e6808b4SNaveen Mamindlapalli 
138147a9656fSNaveen Mamindlapalli 	static_cfg = !is_qos_node_dwrr(node, pfvf, prio);
138247a9656fSNaveen Mamindlapalli 	if (!static_cfg) {
138347a9656fSNaveen Mamindlapalli 		ret = otx2_qos_validate_dwrr_cfg(node, extack, pfvf, prio,
138447a9656fSNaveen Mamindlapalli 						 quantum);
138547a9656fSNaveen Mamindlapalli 		if (ret)
138647a9656fSNaveen Mamindlapalli 			goto out;
138747a9656fSNaveen Mamindlapalli 	}
138847a9656fSNaveen Mamindlapalli 
138947a9656fSNaveen Mamindlapalli 	if (static_cfg)
1390f78dca69SNaveen Mamindlapalli 		node->child_static_cnt++;
139147a9656fSNaveen Mamindlapalli 	else
139247a9656fSNaveen Mamindlapalli 		node->child_dwrr_cnt++;
139347a9656fSNaveen Mamindlapalli 
13945e6808b4SNaveen Mamindlapalli 	set_bit(prio, node->prio_bmap);
13955e6808b4SNaveen Mamindlapalli 
13965e6808b4SNaveen Mamindlapalli 	/* store the qid to assign to leaf node */
13975e6808b4SNaveen Mamindlapalli 	qid = node->qid;
13985e6808b4SNaveen Mamindlapalli 
13995e6808b4SNaveen Mamindlapalli 	/* read current txschq configuration */
14005e6808b4SNaveen Mamindlapalli 	old_cfg = kzalloc(sizeof(*old_cfg), GFP_KERNEL);
14015e6808b4SNaveen Mamindlapalli 	if (!old_cfg) {
14025e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
14035e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
14045e6808b4SNaveen Mamindlapalli 		goto reset_prio;
14055e6808b4SNaveen Mamindlapalli 	}
14065e6808b4SNaveen Mamindlapalli 	otx2_qos_read_txschq_cfg(pfvf, node, old_cfg);
14075e6808b4SNaveen Mamindlapalli 
14085e6808b4SNaveen Mamindlapalli 	/* delete the txschq nodes allocated for this node */
1409208d0434SHariprasad Kelam 	otx2_qos_disable_sq(pfvf, qid);
1410208d0434SHariprasad Kelam 	otx2_qos_free_hw_node_schq(pfvf, node);
14115e6808b4SNaveen Mamindlapalli 	otx2_qos_free_sw_node_schq(pfvf, node);
1412208d0434SHariprasad Kelam 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
14135e6808b4SNaveen Mamindlapalli 
14145e6808b4SNaveen Mamindlapalli 	/* mark this node as htb inner node */
14155e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(node->qid, OTX2_QOS_QID_INNER);
14165e6808b4SNaveen Mamindlapalli 
14175e6808b4SNaveen Mamindlapalli 	/* allocate and initialize a new child node */
14185e6808b4SNaveen Mamindlapalli 	child = otx2_qos_sw_create_leaf_node(pfvf, node, child_classid,
141947a9656fSNaveen Mamindlapalli 					     prio, rate, ceil, quantum,
142047a9656fSNaveen Mamindlapalli 					     qid, static_cfg);
14215e6808b4SNaveen Mamindlapalli 	if (IS_ERR(child)) {
14225e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Unable to allocate leaf node");
14235e6808b4SNaveen Mamindlapalli 		ret = PTR_ERR(child);
14245e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
14255e6808b4SNaveen Mamindlapalli 	}
14265e6808b4SNaveen Mamindlapalli 
14275e6808b4SNaveen Mamindlapalli 	/* push new txschq config to hw */
14285e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
14295e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
14305e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
14315e6808b4SNaveen Mamindlapalli 		ret = -ENOMEM;
14325e6808b4SNaveen Mamindlapalli 		goto free_node;
14335e6808b4SNaveen Mamindlapalli 	}
14345e6808b4SNaveen Mamindlapalli 	ret = otx2_qos_update_tree(pfvf, child, new_cfg);
14355e6808b4SNaveen Mamindlapalli 	if (ret) {
14365e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
14375e6808b4SNaveen Mamindlapalli 		kfree(new_cfg);
14385e6808b4SNaveen Mamindlapalli 		otx2_qos_sw_node_delete(pfvf, child);
14395e6808b4SNaveen Mamindlapalli 		/* restore the old qos tree */
14405e6808b4SNaveen Mamindlapalli 		WRITE_ONCE(node->qid, qid);
14415e6808b4SNaveen Mamindlapalli 		err = otx2_qos_alloc_txschq_node(pfvf, node);
14425e6808b4SNaveen Mamindlapalli 		if (err) {
14435e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev,
14445e6808b4SNaveen Mamindlapalli 				   "Failed to restore old leaf node");
14455e6808b4SNaveen Mamindlapalli 			goto free_old_cfg;
14465e6808b4SNaveen Mamindlapalli 		}
14475e6808b4SNaveen Mamindlapalli 		err = otx2_qos_txschq_update_config(pfvf, node, old_cfg);
14485e6808b4SNaveen Mamindlapalli 		if (err) {
14495e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev,
14505e6808b4SNaveen Mamindlapalli 				   "Failed to restore txcshq configuration");
14515e6808b4SNaveen Mamindlapalli 			goto free_old_cfg;
14525e6808b4SNaveen Mamindlapalli 		}
14535e6808b4SNaveen Mamindlapalli 		otx2_qos_update_smq(pfvf, node, QOS_CFG_SQ);
14545e6808b4SNaveen Mamindlapalli 		goto free_old_cfg;
14555e6808b4SNaveen Mamindlapalli 	}
14565e6808b4SNaveen Mamindlapalli 
14575e6808b4SNaveen Mamindlapalli 	/* free new txschq config */
14585e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
14595e6808b4SNaveen Mamindlapalli 
14605e6808b4SNaveen Mamindlapalli 	/* free old txschq config */
14615e6808b4SNaveen Mamindlapalli 	otx2_qos_free_cfg(pfvf, old_cfg);
14625e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
14635e6808b4SNaveen Mamindlapalli 
14645e6808b4SNaveen Mamindlapalli 	return 0;
14655e6808b4SNaveen Mamindlapalli 
14665e6808b4SNaveen Mamindlapalli free_node:
14675e6808b4SNaveen Mamindlapalli 	otx2_qos_sw_node_delete(pfvf, child);
14685e6808b4SNaveen Mamindlapalli free_old_cfg:
14695e6808b4SNaveen Mamindlapalli 	kfree(old_cfg);
14705e6808b4SNaveen Mamindlapalli reset_prio:
147147a9656fSNaveen Mamindlapalli 	if (static_cfg)
1472f78dca69SNaveen Mamindlapalli 		node->child_static_cnt--;
147347a9656fSNaveen Mamindlapalli 	else
147447a9656fSNaveen Mamindlapalli 		node->child_dwrr_cnt--;
14755e6808b4SNaveen Mamindlapalli 	clear_bit(prio, node->prio_bmap);
14765e6808b4SNaveen Mamindlapalli out:
14775e6808b4SNaveen Mamindlapalli 	return ret;
14785e6808b4SNaveen Mamindlapalli }
14795e6808b4SNaveen Mamindlapalli 
otx2_qos_leaf_del(struct otx2_nic * pfvf,u16 * classid,struct netlink_ext_ack * extack)14805e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_del(struct otx2_nic *pfvf, u16 *classid,
14815e6808b4SNaveen Mamindlapalli 			     struct netlink_ext_ack *extack)
14825e6808b4SNaveen Mamindlapalli {
14835e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *parent;
148447a9656fSNaveen Mamindlapalli 	int dwrr_del_node = false;
14855e6808b4SNaveen Mamindlapalli 	u64 prio;
14865e6808b4SNaveen Mamindlapalli 	u16 qid;
14875e6808b4SNaveen Mamindlapalli 
14885e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev, "TC_HTB_LEAF_DEL classid %04x\n", *classid);
14895e6808b4SNaveen Mamindlapalli 
14905e6808b4SNaveen Mamindlapalli 	/* find node related to classid */
14915e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find(pfvf, *classid);
14925e6808b4SNaveen Mamindlapalli 	if (!node) {
14935e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
14945e6808b4SNaveen Mamindlapalli 		return -ENOENT;
14955e6808b4SNaveen Mamindlapalli 	}
14965e6808b4SNaveen Mamindlapalli 	parent = node->parent;
14975e6808b4SNaveen Mamindlapalli 	prio   = node->prio;
14985e6808b4SNaveen Mamindlapalli 	qid    = node->qid;
14995e6808b4SNaveen Mamindlapalli 
150047a9656fSNaveen Mamindlapalli 	if (!node->is_static)
150147a9656fSNaveen Mamindlapalli 		dwrr_del_node = true;
150247a9656fSNaveen Mamindlapalli 
15035e6808b4SNaveen Mamindlapalli 	otx2_qos_disable_sq(pfvf, node->qid);
15045e6808b4SNaveen Mamindlapalli 
15055e6808b4SNaveen Mamindlapalli 	otx2_qos_destroy_node(pfvf, node);
15065e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
15075e6808b4SNaveen Mamindlapalli 
150847a9656fSNaveen Mamindlapalli 	if (dwrr_del_node) {
150947a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt--;
151047a9656fSNaveen Mamindlapalli 	} else {
1511f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt--;
151247a9656fSNaveen Mamindlapalli 		clear_bit(prio, parent->prio_bmap);
151347a9656fSNaveen Mamindlapalli 	}
151447a9656fSNaveen Mamindlapalli 
151547a9656fSNaveen Mamindlapalli 	/* Reset DWRR priority if all dwrr nodes are deleted */
151647a9656fSNaveen Mamindlapalli 	if (!parent->child_dwrr_cnt)
151747a9656fSNaveen Mamindlapalli 		otx2_reset_dwrr_prio(parent, prio);
151847a9656fSNaveen Mamindlapalli 
1519f78dca69SNaveen Mamindlapalli 	if (!parent->child_static_cnt)
1520f78dca69SNaveen Mamindlapalli 		parent->max_static_prio = 0;
1521f78dca69SNaveen Mamindlapalli 
15225e6808b4SNaveen Mamindlapalli 	return 0;
15235e6808b4SNaveen Mamindlapalli }
15245e6808b4SNaveen Mamindlapalli 
otx2_qos_leaf_del_last(struct otx2_nic * pfvf,u16 classid,bool force,struct netlink_ext_ack * extack)15255e6808b4SNaveen Mamindlapalli static int otx2_qos_leaf_del_last(struct otx2_nic *pfvf, u16 classid, bool force,
15265e6808b4SNaveen Mamindlapalli 				  struct netlink_ext_ack *extack)
15275e6808b4SNaveen Mamindlapalli {
15285e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *node, *parent;
15295e6808b4SNaveen Mamindlapalli 	struct otx2_qos_cfg *new_cfg;
153047a9656fSNaveen Mamindlapalli 	int dwrr_del_node = false;
15315e6808b4SNaveen Mamindlapalli 	u64 prio;
15325e6808b4SNaveen Mamindlapalli 	int err;
15335e6808b4SNaveen Mamindlapalli 	u16 qid;
15345e6808b4SNaveen Mamindlapalli 
15355e6808b4SNaveen Mamindlapalli 	netdev_dbg(pfvf->netdev,
15365e6808b4SNaveen Mamindlapalli 		   "TC_HTB_LEAF_DEL_LAST classid %04x\n", classid);
15375e6808b4SNaveen Mamindlapalli 
15385e6808b4SNaveen Mamindlapalli 	/* find node related to classid */
15395e6808b4SNaveen Mamindlapalli 	node = otx2_sw_node_find(pfvf, classid);
15405e6808b4SNaveen Mamindlapalli 	if (!node) {
15415e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB node not found");
15425e6808b4SNaveen Mamindlapalli 		return -ENOENT;
15435e6808b4SNaveen Mamindlapalli 	}
15445e6808b4SNaveen Mamindlapalli 
15455e6808b4SNaveen Mamindlapalli 	/* save qid for use by parent */
15465e6808b4SNaveen Mamindlapalli 	qid = node->qid;
15475e6808b4SNaveen Mamindlapalli 	prio = node->prio;
15485e6808b4SNaveen Mamindlapalli 
15495e6808b4SNaveen Mamindlapalli 	parent = otx2_sw_node_find(pfvf, node->parent->classid);
15505e6808b4SNaveen Mamindlapalli 	if (!parent) {
15515e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "parent node not found");
15525e6808b4SNaveen Mamindlapalli 		return -ENOENT;
15535e6808b4SNaveen Mamindlapalli 	}
15545e6808b4SNaveen Mamindlapalli 
155547a9656fSNaveen Mamindlapalli 	if (!node->is_static)
155647a9656fSNaveen Mamindlapalli 		dwrr_del_node = true;
155747a9656fSNaveen Mamindlapalli 
15585e6808b4SNaveen Mamindlapalli 	/* destroy the leaf node */
1559208d0434SHariprasad Kelam 	otx2_qos_disable_sq(pfvf, qid);
15605e6808b4SNaveen Mamindlapalli 	otx2_qos_destroy_node(pfvf, node);
15615e6808b4SNaveen Mamindlapalli 	pfvf->qos.qid_to_sqmap[qid] = OTX2_QOS_INVALID_SQ;
15625e6808b4SNaveen Mamindlapalli 
156347a9656fSNaveen Mamindlapalli 	if (dwrr_del_node) {
156447a9656fSNaveen Mamindlapalli 		parent->child_dwrr_cnt--;
156547a9656fSNaveen Mamindlapalli 	} else {
1566f78dca69SNaveen Mamindlapalli 		parent->child_static_cnt--;
156747a9656fSNaveen Mamindlapalli 		clear_bit(prio, parent->prio_bmap);
156847a9656fSNaveen Mamindlapalli 	}
156947a9656fSNaveen Mamindlapalli 
157047a9656fSNaveen Mamindlapalli 	/* Reset DWRR priority if all dwrr nodes are deleted */
157147a9656fSNaveen Mamindlapalli 	if (!parent->child_dwrr_cnt)
157247a9656fSNaveen Mamindlapalli 		otx2_reset_dwrr_prio(parent, prio);
157347a9656fSNaveen Mamindlapalli 
1574f78dca69SNaveen Mamindlapalli 	if (!parent->child_static_cnt)
1575f78dca69SNaveen Mamindlapalli 		parent->max_static_prio = 0;
1576f78dca69SNaveen Mamindlapalli 
15775e6808b4SNaveen Mamindlapalli 	/* create downstream txschq entries to parent */
15785e6808b4SNaveen Mamindlapalli 	err = otx2_qos_alloc_txschq_node(pfvf, parent);
15795e6808b4SNaveen Mamindlapalli 	if (err) {
15805e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB failed to create txsch configuration");
15815e6808b4SNaveen Mamindlapalli 		return err;
15825e6808b4SNaveen Mamindlapalli 	}
15835e6808b4SNaveen Mamindlapalli 	WRITE_ONCE(parent->qid, qid);
15845e6808b4SNaveen Mamindlapalli 	__set_bit(qid, pfvf->qos.qos_sq_bmap);
15855e6808b4SNaveen Mamindlapalli 
15865e6808b4SNaveen Mamindlapalli 	/* push new txschq config to hw */
15875e6808b4SNaveen Mamindlapalli 	new_cfg = kzalloc(sizeof(*new_cfg), GFP_KERNEL);
15885e6808b4SNaveen Mamindlapalli 	if (!new_cfg) {
15895e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "Memory allocation error");
15905e6808b4SNaveen Mamindlapalli 		return -ENOMEM;
15915e6808b4SNaveen Mamindlapalli 	}
15925e6808b4SNaveen Mamindlapalli 	/* fill txschq cfg and push txschq cfg to hw */
15935e6808b4SNaveen Mamindlapalli 	otx2_qos_fill_cfg_schq(parent, new_cfg);
15945e6808b4SNaveen Mamindlapalli 	err = otx2_qos_push_txschq_cfg(pfvf, parent, new_cfg);
15955e6808b4SNaveen Mamindlapalli 	if (err) {
15965e6808b4SNaveen Mamindlapalli 		NL_SET_ERR_MSG_MOD(extack, "HTB HW configuration error");
15975e6808b4SNaveen Mamindlapalli 		kfree(new_cfg);
15985e6808b4SNaveen Mamindlapalli 		return err;
15995e6808b4SNaveen Mamindlapalli 	}
16005e6808b4SNaveen Mamindlapalli 	kfree(new_cfg);
16015e6808b4SNaveen Mamindlapalli 
16025e6808b4SNaveen Mamindlapalli 	/* update tx_real_queues */
16035e6808b4SNaveen Mamindlapalli 	otx2_qos_update_tx_netdev_queues(pfvf);
16045e6808b4SNaveen Mamindlapalli 
16055e6808b4SNaveen Mamindlapalli 	return 0;
16065e6808b4SNaveen Mamindlapalli }
16075e6808b4SNaveen Mamindlapalli 
otx2_clean_qos_queues(struct otx2_nic * pfvf)16085e6808b4SNaveen Mamindlapalli void otx2_clean_qos_queues(struct otx2_nic *pfvf)
16095e6808b4SNaveen Mamindlapalli {
16105e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
16115e6808b4SNaveen Mamindlapalli 
16125e6808b4SNaveen Mamindlapalli 	root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
16135e6808b4SNaveen Mamindlapalli 	if (!root)
16145e6808b4SNaveen Mamindlapalli 		return;
16155e6808b4SNaveen Mamindlapalli 
16165e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq(pfvf, root, QOS_SMQ_FLUSH);
16175e6808b4SNaveen Mamindlapalli }
16185e6808b4SNaveen Mamindlapalli 
otx2_qos_config_txschq(struct otx2_nic * pfvf)16195e6808b4SNaveen Mamindlapalli void otx2_qos_config_txschq(struct otx2_nic *pfvf)
16205e6808b4SNaveen Mamindlapalli {
16215e6808b4SNaveen Mamindlapalli 	struct otx2_qos_node *root;
16225e6808b4SNaveen Mamindlapalli 	int err;
16235e6808b4SNaveen Mamindlapalli 
16245e6808b4SNaveen Mamindlapalli 	root = otx2_sw_node_find(pfvf, OTX2_QOS_ROOT_CLASSID);
16255e6808b4SNaveen Mamindlapalli 	if (!root)
16265e6808b4SNaveen Mamindlapalli 		return;
16275e6808b4SNaveen Mamindlapalli 
162847a9656fSNaveen Mamindlapalli 	if (root->level != NIX_TXSCH_LVL_TL1) {
16295e6808b4SNaveen Mamindlapalli 		err = otx2_qos_txschq_config(pfvf, root);
16305e6808b4SNaveen Mamindlapalli 		if (err) {
16315e6808b4SNaveen Mamindlapalli 			netdev_err(pfvf->netdev, "Error update txschq configuration\n");
16325e6808b4SNaveen Mamindlapalli 			goto root_destroy;
16335e6808b4SNaveen Mamindlapalli 		}
163447a9656fSNaveen Mamindlapalli 	}
16355e6808b4SNaveen Mamindlapalli 
16365e6808b4SNaveen Mamindlapalli 	err = otx2_qos_txschq_push_cfg_tl(pfvf, root, NULL);
16375e6808b4SNaveen Mamindlapalli 	if (err) {
16385e6808b4SNaveen Mamindlapalli 		netdev_err(pfvf->netdev, "Error update txschq configuration\n");
16395e6808b4SNaveen Mamindlapalli 		goto root_destroy;
16405e6808b4SNaveen Mamindlapalli 	}
16415e6808b4SNaveen Mamindlapalli 
16425e6808b4SNaveen Mamindlapalli 	otx2_qos_update_smq(pfvf, root, QOS_CFG_SQ);
16435e6808b4SNaveen Mamindlapalli 	return;
16445e6808b4SNaveen Mamindlapalli 
16455e6808b4SNaveen Mamindlapalli root_destroy:
16465e6808b4SNaveen Mamindlapalli 	netdev_err(pfvf->netdev, "Failed to update Scheduler/Shaping config in Hardware\n");
16475e6808b4SNaveen Mamindlapalli 	/* Free resources allocated */
16485e6808b4SNaveen Mamindlapalli 	otx2_qos_root_destroy(pfvf);
16495e6808b4SNaveen Mamindlapalli }
16505e6808b4SNaveen Mamindlapalli 
otx2_setup_tc_htb(struct net_device * ndev,struct tc_htb_qopt_offload * htb)16515e6808b4SNaveen Mamindlapalli int otx2_setup_tc_htb(struct net_device *ndev, struct tc_htb_qopt_offload *htb)
16525e6808b4SNaveen Mamindlapalli {
16535e6808b4SNaveen Mamindlapalli 	struct otx2_nic *pfvf = netdev_priv(ndev);
16545e6808b4SNaveen Mamindlapalli 	int res;
16555e6808b4SNaveen Mamindlapalli 
16565e6808b4SNaveen Mamindlapalli 	switch (htb->command) {
16575e6808b4SNaveen Mamindlapalli 	case TC_HTB_CREATE:
16585e6808b4SNaveen Mamindlapalli 		return otx2_qos_root_add(pfvf, htb->parent_classid,
16595e6808b4SNaveen Mamindlapalli 					 htb->classid, htb->extack);
16605e6808b4SNaveen Mamindlapalli 	case TC_HTB_DESTROY:
16615e6808b4SNaveen Mamindlapalli 		return otx2_qos_root_destroy(pfvf);
16625e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_ALLOC_QUEUE:
16635e6808b4SNaveen Mamindlapalli 		res = otx2_qos_leaf_alloc_queue(pfvf, htb->classid,
16645e6808b4SNaveen Mamindlapalli 						htb->parent_classid,
16655e6808b4SNaveen Mamindlapalli 						htb->rate, htb->ceil,
166647a9656fSNaveen Mamindlapalli 						htb->prio, htb->quantum,
166747a9656fSNaveen Mamindlapalli 						htb->extack);
16685e6808b4SNaveen Mamindlapalli 		if (res < 0)
16695e6808b4SNaveen Mamindlapalli 			return res;
16705e6808b4SNaveen Mamindlapalli 		htb->qid = res;
16715e6808b4SNaveen Mamindlapalli 		return 0;
16725e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_TO_INNER:
16735e6808b4SNaveen Mamindlapalli 		return otx2_qos_leaf_to_inner(pfvf, htb->parent_classid,
16745e6808b4SNaveen Mamindlapalli 					      htb->classid, htb->rate,
16755e6808b4SNaveen Mamindlapalli 					      htb->ceil, htb->prio,
167647a9656fSNaveen Mamindlapalli 					      htb->quantum, htb->extack);
16775e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_DEL:
16785e6808b4SNaveen Mamindlapalli 		return otx2_qos_leaf_del(pfvf, &htb->classid, htb->extack);
16795e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_DEL_LAST:
16805e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_DEL_LAST_FORCE:
16815e6808b4SNaveen Mamindlapalli 		return otx2_qos_leaf_del_last(pfvf, htb->classid,
16825e6808b4SNaveen Mamindlapalli 				htb->command == TC_HTB_LEAF_DEL_LAST_FORCE,
16835e6808b4SNaveen Mamindlapalli 					      htb->extack);
16845e6808b4SNaveen Mamindlapalli 	case TC_HTB_LEAF_QUERY_QUEUE:
16855e6808b4SNaveen Mamindlapalli 		res = otx2_get_txq_by_classid(pfvf, htb->classid);
16865e6808b4SNaveen Mamindlapalli 		htb->qid = res;
16875e6808b4SNaveen Mamindlapalli 		return 0;
16885e6808b4SNaveen Mamindlapalli 	case TC_HTB_NODE_MODIFY:
16895e6808b4SNaveen Mamindlapalli 		fallthrough;
16905e6808b4SNaveen Mamindlapalli 	default:
16915e6808b4SNaveen Mamindlapalli 		return -EOPNOTSUPP;
16925e6808b4SNaveen Mamindlapalli 	}
16935e6808b4SNaveen Mamindlapalli }
1694