From: Long Li <[email protected]> Release EQs above the live queue count after retiring queues are freed or replacement allocation fails. All CQs using those EQs must be gone. Return their vector allocations to the pool; IRQ registrations remain.
Store each EQ's debugfs dentry in apc->eqs[] rather than a stack copy so shrinking can remove individual EQ directories. Signed-off-by: Long Li <[email protected]> Signed-off-by: Wei Hu <[email protected]> --- drivers/net/ethernet/microsoft/mana/mana_en.c | 49 ++++++++++++++++--- .../ethernet/microsoft/mana/mana_ethtool.c | 1 - 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c index 9297ce15efce..86a09828b5f4 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_en.c +++ b/drivers/net/ethernet/microsoft/mana/mana_en.c @@ -1910,6 +1910,8 @@ void mana_destroy_eq(struct mana_port_context *apc) msi = eq->eq.msix_index; mana_gd_destroy_queue(gc, eq); mana_gd_put_gic(gc, !gc->msi_sharing, msi); + apc->eqs[i].eq = NULL; + apc->eqs[i].mana_eq_debugfs = NULL; } kfree(apc->eqs); @@ -1920,15 +1922,16 @@ EXPORT_SYMBOL_NS(mana_destroy_eq, "NET_MANA"); static void mana_create_eq_debugfs(struct mana_port_context *apc, int i) { - struct mana_eq eq = apc->eqs[i]; + struct mana_eq *eq = &apc->eqs[i]; char eqnum[32]; sprintf(eqnum, "eq%d", i); - eq.mana_eq_debugfs = debugfs_create_dir(eqnum, apc->mana_eqs_debugfs); - debugfs_create_u32("head", 0400, eq.mana_eq_debugfs, &eq.eq->head); - debugfs_create_u32("tail", 0400, eq.mana_eq_debugfs, &eq.eq->tail); - debugfs_create_u32("irq", 0400, eq.mana_eq_debugfs, &eq.eq->eq.irq); - debugfs_create_file("eq_dump", 0400, eq.mana_eq_debugfs, eq.eq, &mana_dbg_q_fops); + eq->mana_eq_debugfs = debugfs_create_dir(eqnum, apc->mana_eqs_debugfs); + debugfs_create_u32("head", 0400, eq->mana_eq_debugfs, &eq->eq->head); + debugfs_create_u32("tail", 0400, eq->mana_eq_debugfs, &eq->eq->tail); + debugfs_create_u32("irq", 0400, eq->mana_eq_debugfs, &eq->eq->eq.irq); + debugfs_create_file("eq_dump", 0400, eq->mana_eq_debugfs, eq->eq, + &mana_dbg_q_fops); } int mana_create_eq(struct mana_port_context *apc) @@ -2037,11 +2040,37 @@ static int mana_grow_eqs(struct mana_port_context *apc, unsigned int need) return 0; out: - /* Retain partial growth for reuse; the live set still needs this pool. - */ return err; } +/* All CQs referencing EQs at or above @keep must be destroyed first. */ +static void mana_shrink_eqs(struct mana_port_context *apc, unsigned int keep) +{ + struct gdma_context *gc = apc->ac->gdma_dev->gdma_context; + struct gdma_queue *eq; + unsigned int msi; + unsigned int i; + + if (!apc->eqs || keep >= apc->num_eqs) + return; + + for (i = keep; i < apc->num_eqs; i++) { + eq = apc->eqs[i].eq; + if (!eq) + continue; + + debugfs_remove_recursive(apc->eqs[i].mana_eq_debugfs); + apc->eqs[i].mana_eq_debugfs = NULL; + + msi = eq->eq.msix_index; + mana_gd_destroy_queue(gc, eq); + mana_gd_put_gic(gc, !gc->msi_sharing, msi); + apc->eqs[i].eq = NULL; + } + + apc->num_eqs = keep; +} + static int mana_fence_rq(struct mana_port_context *apc, struct mana_rxq *rxq) { struct mana_fence_rq_resp resp = {}; @@ -4151,6 +4180,8 @@ int mana_alloc_qset(struct mana_port_context *apc, kfree(scratch->rxqs); scratch->rxqs = NULL; out_err: + mana_shrink_eqs(apc, apc->num_queues); + netdev_err(ndev, "%s(num_queues=%u) failed: %d\n", __func__, num_queues, err); return err; @@ -4511,6 +4542,8 @@ void mana_free_qset(struct mana_port_context *scratch, struct mana_qset *qset) */ netif_set_real_num_rx_queues(apc->ndev, apc->num_queues); + mana_shrink_eqs(apc, apc->num_queues); + mana_qset_debugfs_publish(apc); } diff --git a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c index a438bc6097d6..611521d2d6d1 100644 --- a/drivers/net/ethernet/microsoft/mana/mana_ethtool.c +++ b/drivers/net/ethernet/microsoft/mana/mana_ethtool.c @@ -752,7 +752,6 @@ static int mana_set_channels(struct net_device *ndev, mana_free_qset(scratch, &oldq); free_scratch: - /* Release unpublished queues before closing their shared EQ pool. */ mana_publish_close_if_needed(apc); mana_qset_scratch_free(scratch); clear_flag:

