From: Jun Yang <[email protected]>

A BPID allocated by dpaa_mbuf_create_pool() is only returned to the
kernel allocator from dpaa_mbuf_free_pool(). An application that exits
without calling rte_mempool_free() therefore leaks the BPID, and the ID
stays reserved until the board is rebooted.

Track the allocated BPIDs and the flags they were created with in a
static per-BPID table, and add a driver destructor that releases any
BPID still marked in use at process exit. The destructor cannot touch
the bman_pool object because it lives in EAL memory that may already be
gone, so bman_free_bpid() is added to release the ID from the flags
alone.

rte_dpaa_bpid_info is deliberately left alone. It is shared hugepage
memory referenced by every Rx queue through fq->bp_array, including in
secondary processes where the Rx path installs the primary's array, so
releasing it when the last local mempool goes away would leave those
references dangling. A destructor cannot release it either, because
rte_eal_cleanup() detaches EAL memory before the destructors run. Only
the per-BPID mp and bp pointers are cleared in dpaa_mbuf_free_pool();
the array itself is left to process teardown.

Allocate bp_info with rte_zmalloc() so no uninitialised field is left
behind, and use FSL_BM_BURST_MAX instead of the open-coded 8 for the
hardware bulk acquire size.

Signed-off-by: Jun Yang <[email protected]>
---
 drivers/bus/dpaa/base/qbman/bman.c       |  8 +++
 drivers/bus/dpaa/dpaa_bus_base_symbols.c |  1 +
 drivers/bus/dpaa/include/fsl_bman.h      |  3 ++
 drivers/mempool/dpaa/dpaa_mempool.c      | 65 +++++++++++++++++++++---
 drivers/mempool/dpaa/dpaa_mempool.h      |  2 +-
 5 files changed, 72 insertions(+), 7 deletions(-)

diff --git a/drivers/bus/dpaa/base/qbman/bman.c 
b/drivers/bus/dpaa/base/qbman/bman.c
index ee4232d0a0..0ae1160973 100644
--- a/drivers/bus/dpaa/base/qbman/bman.c
+++ b/drivers/bus/dpaa/base/qbman/bman.c
@@ -251,6 +251,14 @@ void bman_free_pool(struct bman_pool *pool)
        kfree(pool);
 }
 
+void bman_free_bpid(u8 bpid, u32 flags)
+{
+       if (flags & BMAN_POOL_FLAG_THRESH)
+               bm_pool_set(bpid, zero_thresholds);
+       if (flags & BMAN_POOL_FLAG_DYNAMIC_BPID)
+               bman_release_bpid(bpid);
+}
+
 const struct bman_pool_params *bman_get_params(const struct bman_pool *pool)
 {
        return &pool->params;
diff --git a/drivers/bus/dpaa/dpaa_bus_base_symbols.c 
b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
index c2784272b2..78dc1f8f31 100644
--- a/drivers/bus/dpaa/dpaa_bus_base_symbols.c
+++ b/drivers/bus/dpaa/dpaa_bus_base_symbols.c
@@ -44,6 +44,7 @@ RTE_EXPORT_INTERNAL_SYMBOL(fman_if_receive_rx_errors)
 RTE_EXPORT_INTERNAL_SYMBOL(netcfg_acquire)
 RTE_EXPORT_INTERNAL_SYMBOL(netcfg_release)
 RTE_EXPORT_INTERNAL_SYMBOL(bman_new_pool)
+RTE_EXPORT_INTERNAL_SYMBOL(bman_free_bpid)
 RTE_EXPORT_INTERNAL_SYMBOL(bman_free_pool)
 RTE_EXPORT_INTERNAL_SYMBOL(bman_get_params)
 RTE_EXPORT_INTERNAL_SYMBOL(bman_release)
diff --git a/drivers/bus/dpaa/include/fsl_bman.h 
b/drivers/bus/dpaa/include/fsl_bman.h
index 639e0edc96..88e4df503f 100644
--- a/drivers/bus/dpaa/include/fsl_bman.h
+++ b/drivers/bus/dpaa/include/fsl_bman.h
@@ -292,6 +292,9 @@ struct bman_pool *bman_new_pool(const struct 
bman_pool_params *params);
 __rte_internal
 void bman_free_pool(struct bman_pool *pool);
 
+__rte_internal
+void bman_free_bpid(u8 bpid, u32 flags);
+
 /**
  * bman_get_params - Returns a pool object's parameters.
  * @pool: the pool object
diff --git a/drivers/mempool/dpaa/dpaa_mempool.c 
b/drivers/mempool/dpaa/dpaa_mempool.c
index 94aea5e77c..da746a6ca9 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.c
+++ b/drivers/mempool/dpaa/dpaa_mempool.c
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  *
- *   Copyright 2017,2019,2023-2025 NXP
+ *   Copyright 2017,2019,2023-2026 NXP
  *
  */
 
@@ -25,10 +25,24 @@
 #include <rte_eal.h>
 #include <rte_malloc.h>
 #include <rte_ring.h>
+#include <rte_common.h>
 
 #include <dpaa_mempool.h>
 #include <dpaax_iova_table.h>
 
+struct dpaa_bpid_flag {
+       uint32_t flags;
+       bool used;
+};
+
+/* Referenced from the destructor to release the BPIDs allocated by this
+ * process. The destructor cannot touch the bman_pool object because it lives
+ * in EAL memory that rte_eal_cleanup() may already have detached, so the ID
+ * is released from the recorded flags alone. This table is process-local
+ * static storage and therefore still valid at that point.
+ */
+static struct dpaa_bpid_flag s_dpaa_bpid_allocated_flag[DPAA_MAX_BPOOLS];
+
 #define FMAN_ERRATA_BOUNDARY ((uint64_t)4096)
 #define FMAN_ERRATA_BOUNDARY_MASK (~(FMAN_ERRATA_BOUNDARY - 1))
 
@@ -50,7 +64,7 @@ static int
 dpaa_mbuf_create_pool(struct rte_mempool *mp)
 {
        struct bman_pool *bp;
-       struct bm_buffer bufs[8];
+       struct bm_buffer bufs[FSL_BM_BURST_MAX];
        struct dpaa_bp_info *bp_info;
        uint8_t bpid;
        int num_bufs = 0, ret = 0;
@@ -83,8 +97,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
                 * then in 1s for the remainder.
                 */
                if (ret != 1)
-                       ret = bman_acquire(bp, bufs, 8, 0);
-               if (ret < 8)
+                       ret = bman_acquire(bp, bufs, FSL_BM_BURST_MAX, 0);
+               if (ret < FSL_BM_BURST_MAX)
                        ret = bman_acquire(bp, bufs, 1, 0);
                if (ret > 0)
                        num_bufs += ret;
@@ -115,7 +129,7 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
        rte_dpaa_bpid_info[bpid].ptov_off = 0;
        rte_dpaa_bpid_info[bpid].flags = 0;
 
-       bp_info = rte_malloc(NULL,
+       bp_info = rte_zmalloc(NULL,
                             sizeof(struct dpaa_bp_info),
                             RTE_CACHE_LINE_SIZE);
        if (!bp_info) {
@@ -127,6 +141,8 @@ dpaa_mbuf_create_pool(struct rte_mempool *mp)
        rte_memcpy(bp_info, (void *)&rte_dpaa_bpid_info[bpid],
                   sizeof(struct dpaa_bp_info));
        mp->pool_data = (void *)bp_info;
+       s_dpaa_bpid_allocated_flag[bpid].flags = params.flags;
+       s_dpaa_bpid_allocated_flag[bpid].used = true;
 
        DPAA_MEMPOOL_INFO("BMAN pool created for bpid =%d", bpid);
        return 0;
@@ -143,10 +159,25 @@ dpaa_mbuf_free_pool(struct rte_mempool *mp)
                bman_free_pool(bp_info->bp);
                DPAA_MEMPOOL_INFO("BMAN pool freed for bpid =%d",
                                  bp_info->bpid);
-               bp_info->bp = NULL;
+               if (rte_dpaa_bpid_info != NULL) {
+                       rte_dpaa_bpid_info[bp_info->bpid].mp = NULL;
+                       rte_dpaa_bpid_info[bp_info->bpid].bp = NULL;
+               }
+               s_dpaa_bpid_allocated_flag[bp_info->bpid].used = false;
                rte_free(bp_info);
                mp->pool_data = NULL;
        }
+
+       /* rte_dpaa_bpid_info is not freed here, and not from the driver
+        * destructor either. It is a single fixed-size array in EAL memory,
+        * allocated once and referenced by every Rx queue via fq->bp_array;
+        * in a secondary process the Rx path installs the primary's array
+        * (see dpaa_rxtx.c). Releasing it when the last local mempool goes
+        * away would leave those references dangling, and a destructor
+        * cannot release it either because rte_eal_cleanup() detaches EAL
+        * memory before the destructors run. It is therefore left to the
+        * process teardown.
+        */
 }
 
 static int
@@ -481,4 +512,26 @@ static const struct rte_mempool_ops dpaa_mpool_ops = {
        .populate = dpaa_populate,
 };
 
+#define RTE_PRIORITY_104 104
+
+RTE_FINI_PRIO(dpaa_mpool_finish, RTE_PRIORITY_104)
+{
+       uint16_t bpid;
+
+       for (bpid = 0; bpid < DPAA_MAX_BPOOLS; bpid++) {
+               if (s_dpaa_bpid_allocated_flag[bpid].used) {
+                       bman_free_bpid(bpid, 
s_dpaa_bpid_allocated_flag[bpid].flags);
+                       s_dpaa_bpid_allocated_flag[bpid].used = false;
+               }
+       }
+
+       /* rte_dpaa_bpid_info is deliberately not freed here. It is EAL memory,
+        * and rte_eal_cleanup() has already called rte_eal_memory_detach() by
+        * the time the destructors run, so rte_free() would operate on an
+        * unmapped mapping. In a secondary it is not even a local allocation:
+        * the Rx path installs the primary's array (see dpaa_rxtx.c), so
+        * freeing it would release the primary's live BPID table.
+        */
+}
+
 RTE_MEMPOOL_REGISTER_OPS(dpaa_mpool_ops);
diff --git a/drivers/mempool/dpaa/dpaa_mempool.h 
b/drivers/mempool/dpaa/dpaa_mempool.h
index 865b533b8f..ca34747711 100644
--- a/drivers/mempool/dpaa/dpaa_mempool.h
+++ b/drivers/mempool/dpaa/dpaa_mempool.h
@@ -1,6 +1,6 @@
 /* SPDX-License-Identifier: BSD-3-Clause
  *
- *   Copyright 2017,2019,2024 -2025 NXP
+ *   Copyright 2017,2019,2024 -2026 NXP
  *
  */
 #ifndef __DPAA_MEMPOOL_H__
-- 
2.25.1

Reply via email to