From nobody Thu Apr 2 15:37:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D09CD3644A5; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; cv=none; b=iujLfjfmDwutYtAFaaeUB7UIl7aqHeuQpahuByGyEq3Ll6UFQgM50xI3JwpWenclfVhY+E9h2U3XFM5K1awNRxSWE1bL665h1Xe7PFu5D+hODXwW50hHY4Qx3pAY10GB+8bBHBqO4dSkltrTWrOAW0ZktCfzcacTa9sQAfX3rMo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; c=relaxed/simple; bh=tM8m65XuDlt5RZNy9a9VEBHaYpJqz9qh0EbGJHjxdUg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=DEeQDGPb76XOkN1blenqRKmuV27G468GWlAlVTHFfCt/8KNm4rcMUEelK+SgHqvBsrFJbIuMxuSsyaZtHlA+3gQ2d8NhCjxesBJFZSyUVRzK4ZEaj3stMUKxwz6uRADCvnJbVFLqMsONWoRO4Me6UG+lD2TIWgcz1ha55G+duAU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=PmvUqzyw; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="PmvUqzyw" Received: by smtp.kernel.org (Postfix) with ESMTPS id 863A4C19424; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774630672; bh=tM8m65XuDlt5RZNy9a9VEBHaYpJqz9qh0EbGJHjxdUg=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=PmvUqzywgeB3j3SvznZcAElB7X6aZV+dSd9k2cKIrbwPKpocqmKhIDrkhant/Ufke nOLxpCTXUEFXBmIjlmUsGLN6xcoGUQv20pOx5kuLmspWIYMYgozzXW0IhkCKE+XWQF a045j/9pPEEUz5clva7LQyzckoduQgVt/4Ps3/F3NzPHw7OvRtv9MC5q9Ac3CoWElk GllfykrmLXY8QU9qgIg2zgRsEqMT86k90tjFgbWr5LF4OMiHXWQnAYqb5aoi7CfuEj 5gI6fRWFK4Rh5lf13qmwGDQlmGw7jlI6l1iN5FH7dbKmEKbRMCRusgPMlYdpBPmpS+ 3Xtlm5z8Y/lZA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 6B67010F284F; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Fri, 27 Mar 2026 16:58:38 +0000 Subject: [PATCH v2 1/4] dmaengine: Fix possuible use after free Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260327-dma-dmac-handle-vunmap-v2-1-021f95f0e87b@analog.com> References: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> To: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Lars-Peter Clausen , Vinod Koul , Frank Li X-Mailer: b4 0.15.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774630718; l=1349; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=6XbKWWnu/XLY2+T0r/woFDDSj9C/H1ATZbhK/NSCskE=; b=lXIMTGocwl8/MP1F1RFhzO+xdmSHtDqB5OsyHuXX7vOGHAs5bnJFZFrvijo0zWLpG5AdmoPFy Tg9faofxAzMDjhJakLfrZRqrfhfBLEzcqakWAtNGROYiF+dx9Dm4FeA X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno S=C3=A1 In dma_release_channel(), we first called dma_chan_put() and then checked chan->device->privatecnt for possibly clearing DMA_PRIVATE. However, dma_chan_put() will call dma_device_put() which could, potentially (if the DMA provider is already gone for example), release the last reference of the device and hence freeing the it. Fix it, by doing the check before calling dma_chan_put(). Fixes: 0f571515c332 ("dmaengine: Add privatecnt to revert DMA_PRIVATE prope= rty") Signed-off-by: Nuno S=C3=A1 --- drivers/dma/dmaengine.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 405bd2fbb4a3..9049171df857 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -905,11 +905,12 @@ void dma_release_channel(struct dma_chan *chan) mutex_lock(&dma_list_mutex); WARN_ONCE(chan->client_count !=3D 1, "chan reference count %d !=3D 1\n", chan->client_count); - dma_chan_put(chan); /* drop PRIVATE cap enabled by __dma_request_channel() */ if (--chan->device->privatecnt =3D=3D 0) dma_cap_clear(DMA_PRIVATE, chan->device->cap_mask); =20 + dma_chan_put(chan); + if (chan->slave) { sysfs_remove_link(&chan->dev->device.kobj, DMA_SLAVE_NAME); sysfs_remove_link(&chan->slave->kobj, chan->name); --=20 2.53.0 From nobody Thu Apr 2 15:37:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D033E3644A2; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; cv=none; b=cKYwS1/O7jk70N2HeDLJw2wUebWgykuadYPWghJDssyJUINejjhWCLmuycTka7KQt8v8/XCzMO+5uctkwanqdwtQLAqm+ah5kU61PXPHjva9euTK6qN3ivo+XHStRO1dhNZ2B7g0mIeYqxWWduquML5Gvj20t3VhPc+8m2DTD9Y= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; c=relaxed/simple; bh=09nJSRlAd6N1UqTYdtf9KSCV6nHMp6BK6/gYyYC5J8k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=nDcrff3Xw9SygUEwiygmKgf9NLFHxrWRaRbAEaNIGwF+AML3hq7dXPNgCI4dGW2ePmdkQJoH0pAmfrJ0uCf1cg0+KF6DCwXuKzuopEAX3Bk0KZQVTewho4rKAo2Vl2yH+AenqSmgp+qwrN4JSrslboS+k05LMdF3aVxGS+Ydl5Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Qc8IR/7o; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Qc8IR/7o" Received: by smtp.kernel.org (Postfix) with ESMTPS id 90485C2BCB0; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774630672; bh=09nJSRlAd6N1UqTYdtf9KSCV6nHMp6BK6/gYyYC5J8k=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Qc8IR/7ojbMRvTud0Zmou41XjGx1QBfdiQAZv087Gqq8dAd1XP54cnGJ7xaA0P5uW V1BUYs8sVVlmWvtNK6GDIuNlYI6ov6Ht6bxWjgqF/YYLNOL5KxUM5vWzRCf6aNJgPv adtlka7S2dyAA9hCS9vsX4J79ffzMlgrT7Tn/vBQdpUsWqMUfJy5c+YV9X7TJs0XWh RFCcAPRKr63Hl38YRRjjSjWdDRnmCQyDNkS7M1pxZhfYS1Ecs6LAo2E9jNk64015z0 QH+2dqb+iUjzsXAO5wh7GEUl6iUSBZ9fVYcjN2KtPPQcycwTw69lr/KTY2AW9yQn8r VJ7iVNxiGncEA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 797C810F285A; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Fri, 27 Mar 2026 16:58:39 +0000 Subject: [PATCH v2 2/4] dmaengine: dma-axi-dmac: Properly free struct axi_dmac_desc Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260327-dma-dmac-handle-vunmap-v2-2-021f95f0e87b@analog.com> References: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> To: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Lars-Peter Clausen , Vinod Koul , Frank Li X-Mailer: b4 0.15.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774630718; l=889; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=FiW+zvQ0Vg5geNpbllXV8K8Pu2uQGa6K1A0veJRrIZI=; b=ZqTnBw5uXCp7pFYSt/5bMscZVq8LUTat+TLk9lcl/HYXupAduoZ+/etCrHJx2iu/Lrrppym8+ XVRcBW4z8eGC+jBms4+uT94JNNhP/WrH/N4bIcVGvwrHSZdfVinVc5E X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno S=C3=A1 In axi_dmac_prep_peripheral_dma_vec() if we fail after calling axi_dmac_alloc_desc(), we need to use axi_dmac_free_desc() to fully free the descriptor. Fixes: 74609e568670 ("dmaengine: dma-axi-dmac: Implement device_prep_periph= eral_dma_vec") Signed-off-by: Nuno S=C3=A1 --- drivers/dma/dma-axi-dmac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 45c2c8e4bc45..127c3cf80a0e 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -769,7 +769,7 @@ axi_dmac_prep_peripheral_dma_vec(struct dma_chan *c, co= nst struct dma_vec *vecs, for (i =3D 0; i < nb; i++) { if (!axi_dmac_check_addr(chan, vecs[i].addr) || !axi_dmac_check_len(chan, vecs[i].len)) { - kfree(desc); + axi_dmac_free_desc(desc); return NULL; } =20 --=20 2.53.0 From nobody Thu Apr 2 15:37:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CFE93363084; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; cv=none; b=ILNOVBQD+6jTtFmjzTJ9YEAp2wekvFDjh1L9Bq3JDNT3/WayebN3Ggf/7w2L1Hx01rP1ffrRFyI5nOW7qfwBYG9TRNwswvNROGYUgFUESIqc2sLYw8c7jFdjeoMnxd/M3JCcbzcsgXgLgvSX+2vCe4FWV/F6W1s9cAT3I7vcu2I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; c=relaxed/simple; bh=bRskiND37H8zr+VsGdBTgwErj7Q7boGCxXn+DjuUp8o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=fACJtXQPA1FkNuWhECgRILu/ql4dyRYYfWfIBDdeaOvWCViDseIhclgqE0GvRQn396zq3YQ8z2sS12EZZQZzYAo92cJSpMiLE/zzHFuS8B3wyRrwgr3n96L+QYLGAwVoTlQ/UdOaZHzji4e3+JfhPQfdXsknGWFcpdMADwGikak= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=NpDFaTla; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="NpDFaTla" Received: by smtp.kernel.org (Postfix) with ESMTPS id 99971C2BCB2; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774630672; bh=bRskiND37H8zr+VsGdBTgwErj7Q7boGCxXn+DjuUp8o=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=NpDFaTlaXWJgjU4TbQrxYxCdnuQZkQkQ0mKSjoll9mkS9zBVuWnUU8WjiDBCmxzIW Y1txuNUoAZyY2kIWiy4QLWq/C81drcuPPXZA5jnBunKN6UDu2EdVNqygpJqnKxPYs4 yX0vQcwVrjfQQtOxjHkHASl2WZtyrCKbzZ8U7LSX3ONGXn7waJjFwyXeZh0s6/Gv/p FG7v0zXmmB3yiT4tuoWlpE8Tnod+wHjzTD9iZDQNxlqaNdeksPfR0qKnR7PqA6EkWb R4JgzE7BbXfBsZW2GdA1KsYjBo7V32y5MCZ67Zdt71so79TEtzhth5x847KMisdTph RbjuPzAc/1IxA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8806810F2859; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Fri, 27 Mar 2026 16:58:40 +0000 Subject: [PATCH v2 3/4] dmaengine: dma-axi-dmac: fix use-after-free on unbind Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260327-dma-dmac-handle-vunmap-v2-3-021f95f0e87b@analog.com> References: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> To: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Lars-Peter Clausen , Vinod Koul , Frank Li X-Mailer: b4 0.15.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774630718; l=6083; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=wNR0oMrw1rZtsi8jCBNE5cHKX8fscvXjfWhQBVv80wM=; b=SKBxoXgda0GYVlhNewidU0+iQyqeuYD43xtQpNKW0k1sukH/ROqnRR76dXCn/DVTduLPpPA4f pR1KTZu6VhyCV/5BU7SWgWMUklipVMh4imabMsvPGScJy+mxNaXTQhR X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Nuno S=C3=A1 The DMA device lifetime can extend beyond the platform driver unbind if DMA channels are still referenced by client drivers. This leads to use-after-free when the devm-managed memory is freed on unbind but the DMA device callbacks still access it. Fix this by: - Allocating axi_dmac with kzalloc_obj() instead of devm_kzalloc() so its lifetime is not tied to the platform device. - Implementing the device_release callback that so that we can free the object when reference count gets to 0 (no users). - Adding an 'unbound' flag protected by the vchan lock that is set during driver removal, preventing MMIO accesses after the device has been unbound. While at it, explicitly include spinlock.h given it was missing. Signed-off-by: Nuno S=C3=A1 --- drivers/dma/dma-axi-dmac.c | 70 +++++++++++++++++++++++++++++++++++++++---= ---- 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 127c3cf80a0e..70d3ad7e7d37 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -24,6 +24,7 @@ #include #include #include +#include =20 #include =20 @@ -174,6 +175,8 @@ struct axi_dmac { =20 struct dma_device dma_dev; struct axi_dmac_chan chan; + + bool unbound; }; =20 static struct axi_dmac *chan_to_axi_dmac(struct axi_dmac_chan *chan) @@ -182,6 +185,11 @@ static struct axi_dmac *chan_to_axi_dmac(struct axi_dm= ac_chan *chan) dma_dev); } =20 +static struct axi_dmac *dev_to_axi_dmac(struct dma_device *dev) +{ + return container_of(dev, struct axi_dmac, dma_dev); +} + static struct axi_dmac_chan *to_axi_dmac_chan(struct dma_chan *c) { return container_of(c, struct axi_dmac_chan, vchan.chan); @@ -614,7 +622,12 @@ static int axi_dmac_terminate_all(struct dma_chan *c) LIST_HEAD(head); =20 spin_lock_irqsave(&chan->vchan.lock, flags); - axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0); + /* + * Only allow the MMIO access if the device is live. Otherwise still + * go for freeing the descriptors. + */ + if (!dmac->unbound) + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0); chan->next_desc =3D NULL; vchan_get_all_descriptors(&chan->vchan, &head); list_splice_tail_init(&chan->active_descs, &head); @@ -642,9 +655,12 @@ static void axi_dmac_issue_pending(struct dma_chan *c) if (chan->hw_sg) ctrl |=3D AXI_DMAC_CTRL_ENABLE_SG; =20 - axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, ctrl); - spin_lock_irqsave(&chan->vchan.lock, flags); + if (dmac->unbound) { + spin_unlock_irqrestore(&chan->vchan.lock, flags); + return; + } + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, ctrl); if (vchan_issue_pending(&chan->vchan)) axi_dmac_start_transfer(chan); spin_unlock_irqrestore(&chan->vchan.lock, flags); @@ -1184,6 +1200,14 @@ static int axi_dmac_detect_caps(struct axi_dmac *dma= c, unsigned int version) return 0; } =20 +static void axi_dmac_release(struct dma_device *dma_dev) +{ + struct axi_dmac *dmac =3D dev_to_axi_dmac(dma_dev); + + put_device(dma_dev->dev); + kfree(dmac); +} + static void axi_dmac_tasklet_kill(void *task) { tasklet_kill(task); @@ -1194,16 +1218,27 @@ static void axi_dmac_free_dma_controller(void *of_n= ode) of_dma_controller_free(of_node); } =20 +static void axi_dmac_disable(void *__dmac) +{ + struct axi_dmac *dmac =3D __dmac; + unsigned long flags; + + spin_lock_irqsave(&dmac->chan.vchan.lock, flags); + dmac->unbound =3D true; + spin_unlock_irqrestore(&dmac->chan.vchan.lock, flags); + axi_dmac_write(dmac, AXI_DMAC_REG_CTRL, 0); +} + static int axi_dmac_probe(struct platform_device *pdev) { struct dma_device *dma_dev; - struct axi_dmac *dmac; + struct axi_dmac *__dmac; struct regmap *regmap; unsigned int version; u32 irq_mask =3D 0; int ret; =20 - dmac =3D devm_kzalloc(&pdev->dev, sizeof(*dmac), GFP_KERNEL); + struct axi_dmac *dmac __free(kfree) =3D kzalloc_obj(struct axi_dmac); if (!dmac) return -ENOMEM; =20 @@ -1251,6 +1286,7 @@ static int axi_dmac_probe(struct platform_device *pde= v) dma_dev->dev =3D &pdev->dev; dma_dev->src_addr_widths =3D BIT(dmac->chan.src_width); dma_dev->dst_addr_widths =3D BIT(dmac->chan.dest_width); + dma_dev->device_release =3D axi_dmac_release; dma_dev->directions =3D BIT(dmac->chan.direction); dma_dev->residue_granularity =3D DMA_RESIDUE_GRANULARITY_DESCRIPTOR; dma_dev->max_sg_burst =3D 31; /* 31 SGs maximum in one burst */ @@ -1285,12 +1321,21 @@ static int axi_dmac_probe(struct platform_device *p= dev) if (ret) return ret; =20 + /* + * From this point on, our dmac object has it's lifetime bounded with + * dma_dev. Will be freed when dma_dev refcount goes to 0. That means, + * no more automatic kfree(). Also note that dmac is now NULL so we + * need __dmac. + */ + __dmac =3D no_free_ptr(dmac); + get_device(&pdev->dev); + /* * Put the action in here so it get's done before unregistering the DMA * device. */ ret =3D devm_add_action_or_reset(&pdev->dev, axi_dmac_tasklet_kill, - &dmac->chan.vchan.task); + &__dmac->chan.vchan.task); if (ret) return ret; =20 @@ -1304,13 +1349,18 @@ static int axi_dmac_probe(struct platform_device *p= dev) if (ret) return ret; =20 - ret =3D devm_request_irq(&pdev->dev, dmac->irq, axi_dmac_interrupt_handle= r, - IRQF_SHARED, dev_name(&pdev->dev), dmac); + /* So that we can mark the device as unbound and disable it */ + ret =3D devm_add_action_or_reset(&pdev->dev, axi_dmac_disable, __dmac); if (ret) return ret; =20 - regmap =3D devm_regmap_init_mmio(&pdev->dev, dmac->base, - &axi_dmac_regmap_config); + ret =3D devm_request_irq(&pdev->dev, __dmac->irq, axi_dmac_interrupt_hand= ler, + IRQF_SHARED, dev_name(&pdev->dev), __dmac); + if (ret) + return ret; + + regmap =3D devm_regmap_init_mmio(&pdev->dev, __dmac->base, + &axi_dmac_regmap_config); =20 return PTR_ERR_OR_ZERO(regmap); } --=20 2.53.0 From nobody Thu Apr 2 15:37:29 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D34083644A7; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; cv=none; b=U0ARKqfpM9VS+7qBNpt7gRItbg5p3Timv2UhYkdPW5DEYQblwYy3y+RUizI03fmm41N9qRljlJM2jzGTa5EU60sdu4PldF33G1mkScOYxG5Dw3WRyrVST07H08rs/beVOlsdzfBwuaMJYDqkKjlHXgMw1tpmL1JFPJcbGErE644= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1774630672; c=relaxed/simple; bh=SsiVQydKDWPQwQpTdDBmaBONRxD+mD9a9QbQWIJhazo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=LA8wQEaTY2fI5kXOwvbkXsCFrFGUzu+4HimgGE+I3gdNJR7jk6pD+fI6fWXycehTZvQWFh5dPusn5LHBUtWI9wDRA8lK1jCw/a7cp0BfEcST99JBsaxex/rbapGhN8pbFWSrjZA2IUdo0uCM+qzXYTnJsr4eZWHdZJuN4FK0jas= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=Il4gd/Wt; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="Il4gd/Wt" Received: by smtp.kernel.org (Postfix) with ESMTPS id A0DF2C4AF09; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1774630672; bh=SsiVQydKDWPQwQpTdDBmaBONRxD+mD9a9QbQWIJhazo=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=Il4gd/WtL8U2Gznpcys1LQA+hNVwaIyxfgioKs02SG1BsfnN4jeOvO4+gOkfhX6SO pLGAI1Sw6g9fdZOaVDzclxMlltHsci6kiJrmyMAkyEL68MiOQvPA1JHQRRKKlnwGCL ygsG9Le0W9rUkvOC16remp+0PRru7KofjIqAb3jeYPnW2ukv2omftKW9oZ3r1I8jms EKyMzzVORzkjAeywJ8ha1AisEPHxaFykCOrwm5UGJ8J8EyX0mflJjqn3ITpF+hUu6H 3iHZeuZw/gZt+geVlrxvH92vT0oIi2A8gPfft9VLy0ccUsOpLoJ2dvUmwbiKMBw/45 zHqp1YhMJj4yA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 9533E10F285D; Fri, 27 Mar 2026 16:57:52 +0000 (UTC) From: =?utf-8?q?Nuno_S=C3=A1_via_B4_Relay?= Date: Fri, 27 Mar 2026 16:58:41 +0000 Subject: [PATCH v2 4/4] dmaengine: dma-axi-dmac: Defer freeing DMA descriptors Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260327-dma-dmac-handle-vunmap-v2-4-021f95f0e87b@analog.com> References: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> In-Reply-To: <20260327-dma-dmac-handle-vunmap-v2-0-021f95f0e87b@analog.com> To: dmaengine@vger.kernel.org, linux-kernel@vger.kernel.org Cc: Lars-Peter Clausen , Vinod Koul , Frank Li , Eliza Balas X-Mailer: b4 0.15.0 X-Developer-Signature: v=1; a=ed25519-sha256; t=1774630718; l=4336; i=nuno.sa@analog.com; s=20231116; h=from:subject:message-id; bh=iMbPiK/wOeXYmM5fOnDfGQN+n3bpnujjiiAlZriC4to=; b=ta7WMPtxj1EzNdcXn+Q4f3+NDIrTIPaL1n/IM6GuOTrYbw/cY9q/QRd8g71GNM1BDoEnmig7e 2QWONkYu+2hC/3Aj+K0pwzvmqTwy/0+86nR3TGeyVpxNg4YsZC6xM3f X-Developer-Key: i=nuno.sa@analog.com; a=ed25519; pk=3NQwYA013OUYZsmDFBf8rmyyr5iQlxV/9H4/Df83o1E= X-Endpoint-Received: by B4 Relay for nuno.sa@analog.com/20231116 with auth_id=100 X-Original-From: =?utf-8?q?Nuno_S=C3=A1?= Reply-To: nuno.sa@analog.com From: Eliza Balas This IP core can be used in architectures (like Microblaze) where DMA descriptors are allocated with vmalloc(). Hence, given that freeing the descriptors happen in softirq context, vunmpap() will BUG(). To solve the above, we setup a work item during allocation of the descriptors and schedule in softirq context. Hence, the actual freeing happens in threaded context. Also note that to account for the possible race where the struct axi_dmac object is gone between scheduling the work and actually running it, we now save and get a reference of struct device when allocating the descriptor (given that's all we need in axi_dmac_free_desc()) and release it in axi_dmac_free_desc(). Signed-off-by: Eliza Balas Co-developed-by: Nuno S=C3=A1 Signed-off-by: Nuno S=C3=A1 --- drivers/dma/dma-axi-dmac.c | 50 ++++++++++++++++++++++++++++++++++--------= ---- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/drivers/dma/dma-axi-dmac.c b/drivers/dma/dma-axi-dmac.c index 70d3ad7e7d37..46f1ead0c7d7 100644 --- a/drivers/dma/dma-axi-dmac.c +++ b/drivers/dma/dma-axi-dmac.c @@ -25,6 +25,7 @@ #include #include #include +#include =20 #include =20 @@ -133,6 +134,9 @@ struct axi_dmac_sg { struct axi_dmac_desc { struct virt_dma_desc vdesc; struct axi_dmac_chan *chan; + struct device *dev; + + struct work_struct sched_work; =20 bool cyclic; bool cyclic_eot; @@ -666,6 +670,25 @@ static void axi_dmac_issue_pending(struct dma_chan *c) spin_unlock_irqrestore(&chan->vchan.lock, flags); } =20 +static void axi_dmac_free_desc(struct axi_dmac_desc *desc) +{ + struct axi_dmac_hw_desc *hw =3D desc->sg[0].hw; + dma_addr_t hw_phys =3D desc->sg[0].hw_phys; + + dma_free_coherent(desc->dev, PAGE_ALIGN(desc->num_sgs * sizeof(*hw)), + hw, hw_phys); + put_device(desc->dev); + kfree(desc); +} + +static void axi_dmac_free_desc_schedule_work(struct work_struct *work) +{ + struct axi_dmac_desc *desc =3D container_of(work, struct axi_dmac_desc, + sched_work); + + axi_dmac_free_desc(desc); +} + static struct axi_dmac_desc * axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigned int num_sgs) { @@ -681,6 +704,7 @@ axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsigne= d int num_sgs) return NULL; desc->num_sgs =3D num_sgs; desc->chan =3D chan; + desc->dev =3D get_device(dmac->dma_dev.dev); =20 hws =3D dma_alloc_coherent(dev, PAGE_ALIGN(num_sgs * sizeof(*hws)), &hw_phys, GFP_ATOMIC); @@ -703,21 +727,18 @@ axi_dmac_alloc_desc(struct axi_dmac_chan *chan, unsig= ned int num_sgs) /* The last hardware descriptor will trigger an interrupt */ desc->sg[num_sgs - 1].hw->flags =3D AXI_DMAC_HW_FLAG_LAST | AXI_DMAC_HW_F= LAG_IRQ; =20 + /* + * We need to setup a work item because this IP can be used on archs + * that rely on vmalloced memory for descriptors. And given that freeing + * the descriptors happens in softirq context, vunmpap() will BUG(). + * Hence, setup the worker so that we can queue it and free the + * descriptor in threaded context. + */ + INIT_WORK(&desc->sched_work, axi_dmac_free_desc_schedule_work); + return desc; } =20 -static void axi_dmac_free_desc(struct axi_dmac_desc *desc) -{ - struct axi_dmac *dmac =3D chan_to_axi_dmac(desc->chan); - struct device *dev =3D dmac->dma_dev.dev; - struct axi_dmac_hw_desc *hw =3D desc->sg[0].hw; - dma_addr_t hw_phys =3D desc->sg[0].hw_phys; - - dma_free_coherent(dev, PAGE_ALIGN(desc->num_sgs * sizeof(*hw)), - hw, hw_phys); - kfree(desc); -} - static struct axi_dmac_sg *axi_dmac_fill_linear_sg(struct axi_dmac_chan *c= han, enum dma_transfer_direction direction, dma_addr_t addr, unsigned int num_periods, unsigned int period_len, @@ -958,7 +979,10 @@ static void axi_dmac_free_chan_resources(struct dma_ch= an *c) =20 static void axi_dmac_desc_free(struct virt_dma_desc *vdesc) { - axi_dmac_free_desc(to_axi_dmac_desc(vdesc)); + struct axi_dmac_desc *desc =3D to_axi_dmac_desc(vdesc); + + /* See the comment in axi_dmac_alloc_desc() for the why! */ + schedule_work(&desc->sched_work); } =20 static bool axi_dmac_regmap_rdwr(struct device *dev, unsigned int reg) --=20 2.53.0