On 30-06-2026 20:13, Maxime Leroy wrote:
rte_dpaa2_close_dpcon_device() called dpcon_close() but not
dpcon_disable(). close only releases the MC control session; it does not
disable the channel. Cosmetic: an idle DPCON generates nothing and every
consumer reprograms on setup, so disable before close only to return the
channel clean, as the symmetric counterpart of the dpcon_enable() done on
setup.

Signed-off-by: Maxime Leroy <maxime@leroys.fr>
---
 drivers/event/dpaa2/dpaa2_hw_dpcon.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/event/dpaa2/dpaa2_hw_dpcon.c b/drivers/event/dpaa2/dpaa2_hw_dpcon.c
index ea5b0d4b85..f65a63a786 100644
--- a/drivers/event/dpaa2/dpaa2_hw_dpcon.c
+++ b/drivers/event/dpaa2/dpaa2_hw_dpcon.c
@@ -128,6 +128,7 @@ rte_dpaa2_close_dpcon_device(int object_id)
 
 	if (dpcon_dev) {
 		rte_dpaa2_free_dpcon_dev(dpcon_dev);
+		dpcon_disable(&dpcon_dev->dpcon, CMD_PRI_LOW, dpcon_dev->token);
 		dpcon_close(&dpcon_dev->dpcon, CMD_PRI_LOW, dpcon_dev->token);
 		TAILQ_REMOVE(&dpcon_dev_list, dpcon_dev, next);
 		rte_free(dpcon_dev);

The ordering here is wrong. rte_dpaa2_free_dpcon_dev(dpcon_dev) is called before dpcon_disable(). Once the device is returned to the shared pool via rte_dpaa2_free_dpcon_dev(), another thread can immediately re-allocate the same dpcon_dev pointer. The subsequent dpcon_disable() call would then quiesce a channel already in active use by the new owner — a use-after-free on the pool object.

The correct teardown sequence must be:

  1. dpcon_disable() — quiesce the hardware channel
  2. dpcon_close() — release the MC control session
  3. rte_dpaa2_free_dpcon_dev() — return to pool

Please reorder accordingly:

dpcon_disable(&dpcon_dev->dpcon, CMD_PRI_LOW, dpcon_dev->token); 

dpcon_close(&dpcon_dev->dpcon, CMD_PRI_LOW, dpcon_dev->token);

 TAILQ_REMOVE(&dpcon_dev_list, dpcon_dev, next);

 rte_dpaa2_free_dpcon_dev(dpcon_dev);

 rte_free(dpcon_dev);