lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <755e4576-584f-4753-9ec4-cadac42b2e91@ti.com>
Date: Wed, 11 Feb 2026 13:12:09 +0530
From: Sai Sree Kartheek Adivi <s-adivi@...com>
To: <peter.ujfalusi@...il.com>, <vkoul@...nel.org>, <robh@...nel.org>,
	<krzk+dt@...nel.org>, <conor+dt@...nel.org>, <nm@...com>,
	<ssantosh@...nel.org>, <dmaengine@...r.kernel.org>,
	<devicetree@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
	<linux-arm-kernel@...ts.infradead.org>, <vigneshr@...com>
CC: <r-sharma3@...com>, <gehariprasath@...com>
Subject: Re: [PATCH v4 19/19] dmaengine: ti: k3-udma: switch to synchronous
 descriptor freeing


On 30/01/26 16:31, Sai Sree Kartheek Adivi wrote:
> The driver currently uses a worker thread to free processed
> descriptors. Under high load (e.g., CRYPTO_MANAGER_EXTRA_TESTS), the
> descriptor allocation rate can significantly outpace the worker
> thread's execution rate.
>
> This leads to false resource exhaustion where dma_alloc_coherent()
> fails even though many descriptors are waiting in the purge queue to
> be freed.
>
> Remove the lazy freeing mechanism (desc_to_purge list and worker) and
> instead free the descriptors immediately in the completion callback.
>
> This eliminates the latency gap between hardware completion and
> software reclaim, preventing the pool exhaustion during stress tests.

Please discard this patch.

Further testing revealed that dma_free_coherent triggers a

WARN_ON(irqs_disabled()) in this path due to atomic context.


I'll send a v5 with valid fix. Apologies for the noise.

>
> Signed-off-by: Sai Sree Kartheek Adivi <s-adivi@...com>
> ---
>   drivers/dma/ti/k3-udma-common.c | 40 +++------------------------------
>   drivers/dma/ti/k3-udma-v2.c     |  2 --
>   drivers/dma/ti/k3-udma.c        |  2 --
>   drivers/dma/ti/k3-udma.h        |  3 ---
>   4 files changed, 3 insertions(+), 44 deletions(-)
>
> diff --git a/drivers/dma/ti/k3-udma-common.c b/drivers/dma/ti/k3-udma-common.c
> index 05b2b6b962a06..f9da00298b60f 100644
> --- a/drivers/dma/ti/k3-udma-common.c
> +++ b/drivers/dma/ti/k3-udma-common.c
> @@ -95,32 +95,6 @@ void udma_free_hwdesc(struct udma_chan *uc, struct udma_desc *d)
>   	}
>   }
>   
> -void udma_purge_desc_work(struct work_struct *work)
> -{
> -	struct udma_dev *ud = container_of(work, typeof(*ud), purge_work);
> -	struct virt_dma_desc *vd, *_vd;
> -	unsigned long flags;
> -	LIST_HEAD(head);
> -
> -	spin_lock_irqsave(&ud->lock, flags);
> -	list_splice_tail_init(&ud->desc_to_purge, &head);
> -	spin_unlock_irqrestore(&ud->lock, flags);
> -
> -	list_for_each_entry_safe(vd, _vd, &head, node) {
> -		struct udma_chan *uc = to_udma_chan(vd->tx.chan);
> -		struct udma_desc *d = to_udma_desc(&vd->tx);
> -
> -		udma_free_hwdesc(uc, d);
> -		list_del(&vd->node);
> -		kfree(d);
> -	}
> -
> -	/* If more to purge, schedule the work again */
> -	if (!list_empty(&ud->desc_to_purge))
> -		schedule_work(&ud->purge_work);
> -}
> -EXPORT_SYMBOL_GPL(udma_purge_desc_work);
> -
>   void udma_desc_free(struct virt_dma_desc *vd)
>   {
>   	struct udma_dev *ud = to_udma_dev(vd->tx.chan->device);
> @@ -131,17 +105,9 @@ void udma_desc_free(struct virt_dma_desc *vd)
>   	if (uc->terminated_desc == d)
>   		uc->terminated_desc = NULL;
>   
> -	if (uc->use_dma_pool) {
> -		udma_free_hwdesc(uc, d);
> -		kfree(d);
> -		return;
> -	}
> -
> -	spin_lock_irqsave(&ud->lock, flags);
> -	list_add_tail(&vd->node, &ud->desc_to_purge);
> -	spin_unlock_irqrestore(&ud->lock, flags);
> -
> -	schedule_work(&ud->purge_work);
> +	udma_free_hwdesc(uc, d);
> +	kfree(d);
> +	return;
>   }
>   EXPORT_SYMBOL_GPL(udma_desc_free);
>   
> diff --git a/drivers/dma/ti/k3-udma-v2.c b/drivers/dma/ti/k3-udma-v2.c
> index 6761a079025ba..d33382cc0356a 100644
> --- a/drivers/dma/ti/k3-udma-v2.c
> +++ b/drivers/dma/ti/k3-udma-v2.c
> @@ -1320,14 +1320,12 @@ static int udma_v2_probe(struct platform_device *pdev)
>   	ud->psil_base = ud->match_data->psil_base;
>   
>   	INIT_LIST_HEAD(&ud->ddev.channels);
> -	INIT_LIST_HEAD(&ud->desc_to_purge);
>   
>   	ch_count = setup_resources(ud);
>   	if (ch_count <= 0)
>   		return ch_count;
>   
>   	spin_lock_init(&ud->lock);
> -	INIT_WORK(&ud->purge_work, udma_purge_desc_work);
>   
>   	ud->desc_align = 64;
>   	if (ud->desc_align < dma_get_cache_alignment())
> diff --git a/drivers/dma/ti/k3-udma.c b/drivers/dma/ti/k3-udma.c
> index a8d01d955651a..34d458b4a0dbc 100644
> --- a/drivers/dma/ti/k3-udma.c
> +++ b/drivers/dma/ti/k3-udma.c
> @@ -2704,14 +2704,12 @@ static int udma_probe(struct platform_device *pdev)
>   	ud->psil_base = ud->match_data->psil_base;
>   
>   	INIT_LIST_HEAD(&ud->ddev.channels);
> -	INIT_LIST_HEAD(&ud->desc_to_purge);
>   
>   	ch_count = setup_resources(ud);
>   	if (ch_count <= 0)
>   		return ch_count;
>   
>   	spin_lock_init(&ud->lock);
> -	INIT_WORK(&ud->purge_work, udma_purge_desc_work);
>   
>   	ud->desc_align = 64;
>   	if (ud->desc_align < dma_get_cache_alignment())
> diff --git a/drivers/dma/ti/k3-udma.h b/drivers/dma/ti/k3-udma.h
> index 3ae2400e67990..67de9feb9906b 100644
> --- a/drivers/dma/ti/k3-udma.h
> +++ b/drivers/dma/ti/k3-udma.h
> @@ -353,8 +353,6 @@ struct udma_dev {
>   
>   	struct k3_ringacc *ringacc;
>   
> -	struct work_struct purge_work;
> -	struct list_head desc_to_purge;
>   	spinlock_t lock;
>   
>   	struct udma_rx_flush rx_flush;
> @@ -596,7 +594,6 @@ static inline void udma_fetch_epib(struct udma_chan *uc, struct udma_desc *d)
>   struct udma_desc *udma_udma_desc_from_paddr(struct udma_chan *uc,
>   					    dma_addr_t paddr);
>   void udma_free_hwdesc(struct udma_chan *uc, struct udma_desc *d);
> -void udma_purge_desc_work(struct work_struct *work);
>   void udma_desc_free(struct virt_dma_desc *vd);
>   bool udma_desc_is_rx_flush(struct udma_chan *uc, dma_addr_t addr);
>   bool udma_is_desc_really_done(struct udma_chan *uc, struct udma_desc *d);

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ