Hi Hemant,

On Fri, Jul 3, 2026 at 7:21 PM Hemant Agrawal
<[email protected]> wrote:
>
>
> 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 <[email protected]>
> ---
>  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:
>
> dpcon_disable() — quiesce the hardware channel
> dpcon_close() — release the MC control session
> 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);
>
>
>
On the ordering: there's no real race. This is the .close handler, run
once at teardown from fslmc_vfio_close_group() on a single thread, not
concurrent with the datapath, so nothing can re-acquire the node
between free and close.

But the patch shouldn't exist at all. The pooled DPAA2 objects use a
reprogram-on-borrow model: the free helpers (rte_dpaa2_free_dpcon_dev,
rte_dpaa2_free_dpci_dev, dpaa2_free_dpbp_dev) only drop in_use, and
nothing un-programs an object on return, the next borrower reprograms.
The sibling DPCI close handler confirms it: it does dpci_close() with
no dpci_disable(). Adding dpcon_disable() here makes DPCON the lone
outlier for no benefit, an enabled channel returned to the pool is
inert (FQ parked at unbind, enable is re-applied idempotently on the
next borrow).

So there's no reason to treat dpcon/CDAN differently. Dropping the patch.

Thanks,
Maxime

Reply via email to