History

octeontx2-pf: reset HTB scheduler topology before freeing queues

HTB offload programs NIX_AF_TLxX_TOPOLOGY on QoS-allocated scheduler queues via otx2_qos_txschq_set_parent_topology(), but teardown freed those queues without clearing TOPOLOGY. The AF only restores PARENT and SCHEDULE on free, so PRIO_ANCHOR/RR_PRIO settings can survive in the shared scheduler pool and affect later allocations. Add otx2_qos_reset_schq_topology() and otx2_qos_free_hw_schq() to zero TL4 through TL2 TOPOLOGY before each schq is returned to the AF during hierarchy teardown and cfg rollback. Skip the aggregation level (TL1): it is a per-tx-link queue shared by the PF, default Tx hierarchy and VFs, and is not freed back to the AF by nix_txschq_free_one().

Ratheesh Kannoth committed 2 months ago

Commit ef39fca1 parent 66ef5ad1 file · +55 −5Browse files

Unified · Split

drivers/net/ethernet/marvell/octeontx2/nic/qos.c+55−5
@@ -235,13 +235,63 @@ static int otx2_qos_txschq_set_parent_topology(struct otx2_nic *pfvf, · 234 unmodified lines
235 return rc;235 return rc;
236}236}
237 237
238static int otx2_qos_reset_schq_topology(struct otx2_nic *pfvf, u16 lvl,
239 u16 schq)
240{
241 struct mbox *mbox = &pfvf->mbox;
242 struct nix_txschq_config *cfg;
243 int rc;
244
245 if (lvl < NIX_TXSCH_LVL_TL4 || lvl >= NIX_TXSCH_LVL_TL1)
246 return 0;
247
248 mutex_lock(&mbox->lock);
249
250 cfg = otx2_mbox_alloc_msg_nix_txschq_cfg(mbox);
251 if (!cfg) {
252 mutex_unlock(&mbox->lock);
253 return -ENOMEM;
254 }
255
256 cfg->lvl = lvl;
257 cfg->num_regs = 1;
258
259 if (lvl == NIX_TXSCH_LVL_TL4)
260 cfg->reg[0] = NIX_AF_TL4X_TOPOLOGY(schq);
261 else if (lvl == NIX_TXSCH_LVL_TL3)
262 cfg->reg[0] = NIX_AF_TL3X_TOPOLOGY(schq);
263 else if (lvl == NIX_TXSCH_LVL_TL2)
264 cfg->reg[0] = NIX_AF_TL2X_TOPOLOGY(schq);
265
266 cfg->regval[0] = 0;
267
268 rc = otx2_sync_mbox_msg(mbox);
269
270 mutex_unlock(&mbox->lock);
271
272 return rc;
273}
274
275static void otx2_qos_free_hw_schq(struct otx2_nic *pfvf, u16 lvl, u16 schq)
276{
277 int err;
278
279 err = otx2_qos_reset_schq_topology(pfvf, lvl, schq);
280 if (err)
281 netdev_warn(pfvf->netdev,
282 "QoS: failed to reset topology for schq %u at level %u: %d\n",
283 schq, lvl, err);
284
285 otx2_txschq_free_one(pfvf, lvl, schq);
286}
287
238static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf,288static void otx2_qos_free_hw_node_schq(struct otx2_nic *pfvf,
239 struct otx2_qos_node *parent)289 struct otx2_qos_node *parent)
240{290{
241 struct otx2_qos_node *node;291 struct otx2_qos_node *node;
242 292
243 list_for_each_entry_reverse(node, &parent->child_schq_list, list)293 list_for_each_entry_reverse(node, &parent->child_schq_list, list)
244 otx2_txschq_free_one(pfvf, node->level, node->schq);294 otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
245}295}
246 296
247static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,297static void otx2_qos_free_hw_node(struct otx2_nic *pfvf,
@@ -252,7 +302,7 @@ static void otx2_qos_free_hw_node(struct otx2_nic *pfvf, · 4 unmodified lines
252 list_for_each_entry_safe(node, tmp, &parent->child_list, list) {302 list_for_each_entry_safe(node, tmp, &parent->child_list, list) {
253 otx2_qos_free_hw_node(pfvf, node);303 otx2_qos_free_hw_node(pfvf, node);
254 otx2_qos_free_hw_node_schq(pfvf, node);304 otx2_qos_free_hw_node_schq(pfvf, node);
255 otx2_txschq_free_one(pfvf, node->level, node->schq);305 otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
256 }306 }
257}307}
258 308
@@ -266,7 +316,7 @@ static void otx2_qos_free_hw_cfg(struct otx2_nic *pfvf, · 7 unmodified lines
266 otx2_qos_free_hw_node_schq(pfvf, node);316 otx2_qos_free_hw_node_schq(pfvf, node);
267 317
268 /* free node hw mappings */318 /* free node hw mappings */
269 otx2_txschq_free_one(pfvf, node->level, node->schq);319 otx2_qos_free_hw_schq(pfvf, node->level, node->schq);
270 320
271 mutex_unlock(&pfvf->qos.qos_lock);321 mutex_unlock(&pfvf->qos.qos_lock);
272}322}
@@ -913,7 +963,7 @@ static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg) · 640 unmodified lines
913 for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {963 for (lvl = 0; lvl < NIX_TXSCH_LVL_CNT; lvl++) {
914 for (idx = 0; idx < cfg->schq[lvl]; idx++) {964 for (idx = 0; idx < cfg->schq[lvl]; idx++) {
915 schq = cfg->schq_list[lvl][idx];965 schq = cfg->schq_list[lvl][idx];
916 otx2_txschq_free_one(pfvf, lvl, schq);966 otx2_qos_free_hw_schq(pfvf, lvl, schq);
917 }967 }
918 }968 }
919 969
@@ -921,7 +971,7 @@ static void otx2_qos_free_cfg(struct otx2_nic *pfvf, struct otx2_qos_cfg *cfg) · 1 unmodified line
921 for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {971 for (idx = 0; idx < cfg->schq_contig[lvl]; idx++) {
922 if (cfg->schq_index_used[lvl][idx]) {972 if (cfg->schq_index_used[lvl][idx]) {
923 schq = cfg->schq_contig_list[lvl][idx];973 schq = cfg->schq_contig_list[lvl][idx];
924 otx2_txschq_free_one(pfvf, lvl, schq);974 otx2_qos_free_hw_schq(pfvf, lvl, schq);
925 }975 }
926 }976 }
927 }977 }