From: sashiko-bot@kernel.org
To: "Bartosz Golaszewski" <bartosz.golaszewski@oss.qualcomm.com>
Cc: dmaengine@vger.kernel.org, vkoul@kernel.org, Frank.Li@kernel.org
Subject: Re: [PATCH v17 06/14] dmaengine: qcom: bam_dma: add support for BAM locking
Date: Tue, 19 May 2026 13:54:27 +0000 [thread overview]
Message-ID: <20260519135428.9D6C7C2BCB3@smtp.kernel.org> (raw)
In-Reply-To: <20260519-qcom-qce-cmd-descr-v17-6-53a595414b79@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 8 potential issue(s) to consider:
- [Critical] Out-of-order DMA cookie assignment causes premature transaction completion for clients.
- [Critical] Native integers assigned directly to little-endian hardware descriptors.
- [High] Unconditional injection of LOCK/UNLOCK descriptors corrupts the pending transaction queue.
- [High] Unhandled allocation failure for UNLOCK descriptor leaves the BAM pipe permanently locked.
- [High] DMA engine control flag is invalidly passed as a DMA mapping attribute.
- [High] Descriptor-specific metadata unsafely overwrites global channel state.
- [Medium] Direction check contradicts commit message intent, explicitly skipping pipe locking for RX channels.
- [Medium] Missing length validation in `bam_metadata_attach` allows out-of-bounds reads.
--
commit 44d1fcb40281218d18c6b56492066d2d5e6beb61
Author: Bartosz Golaszewski <bartosz.golaszewski@oss.qualcomm.com>
dmaengine: qcom: bam_dma: add support for BAM locking
Add support for BAM pipe locking by prepending a dummy command descriptor
with the LOCK bit set, and appending one with the UNLOCK bit once the
transaction is done. The dummy writes use a scratchpad address provided via
descriptor metadata.
> diff --git a/drivers/dma/qcom/bam_dma.c b/drivers/dma/qcom/bam_dma.c
> index 30318cf01ee20..2c9f90313c313 100644
> --- a/drivers/dma/qcom/bam_dma.c
> +++ b/drivers/dma/qcom/bam_dma.c
[ ... ]
> @@ -652,6 +664,35 @@ static int bam_slave_config(struct dma_chan *chan,
> return 0;
> }
>
> +static int bam_metadata_attach(struct dma_async_tx_descriptor *desc, void *data, size_t len)
> +{
> + struct bam_chan *bchan = to_bam_chan(desc->chan);
> + const struct bam_device_data *bdata = bchan->bdev->dev_data;
> + struct bam_desc_metadata *metadata = data;
> +
> + if (!data)
> + return -EINVAL;
> +
Does this code need to validate the len parameter? If the caller passes a
buffer smaller than sizeof(struct bam_desc_metadata), will this read
out-of-bounds memory when accessing the metadata fields?
> + if (!bdata->pipe_lock_supported)
> + /*
> + * The client wants to use locking but this BAM version doesn't
> + * support it. Don't return an error here as this will stop the
> + * client from using DMA at all for no reason.
> + */
> + return 0;
> +
> + guard(spinlock_irqsave)(&bchan->vc.lock);
> +
> + bchan->scratchpad_addr = metadata->scratchpad_addr;
> + bchan->direction = metadata->direction;
By saving descriptor-specific metadata directly into the global channel
structure, could this overwrite the state if a client queues multiple
descriptors with different metadata?
Also, does the scratchpad_addr remain set for subsequent unrelated
transactions, potentially causing dummy writes to a stale address?
> +
> + return 0;
> +}
[ ... ]
> +static struct bam_async_desc *
> +bam_make_lock_desc(struct bam_chan *bchan, unsigned long flag)
> +{
> + struct dma_chan *chan = &bchan->vc.chan;
> + struct bam_async_desc *async_desc;
> + struct bam_desc_hw *desc;
> + struct virt_dma_desc *vd;
> + struct virt_dma_chan *vc;
> + unsigned int mapped;
> + dma_cookie_t cookie;
> + int ret;
> +
> + async_desc = kzalloc_flex(*async_desc, desc, 1, GFP_NOWAIT);
[ ... ]
> + bam_prep_ce_le32(&async_desc->lock_ce, bchan->scratchpad_addr, BAM_WRITE_COMMAND, 0);
> + sg_set_buf(&async_desc->lock_sg, &async_desc->lock_ce, sizeof(async_desc->lock_ce));
> +
> + mapped = dma_map_sg_attrs(chan->slave, &async_desc->lock_sg,
> + 1, DMA_TO_DEVICE, DMA_PREP_CMD);
DMA_PREP_CMD is a dmaengine control flag, but it's being passed as the attrs
parameter here. Could this cause undefined DMA mapping behavior by being
interpreted as a mapping attribute like DMA_ATTR_ALLOC_SINGLE_PAGES?
Additionally, since unmapping is done without attributes later, will this
violate the requirement that mapping and unmapping attributes must match?
> + if (!mapped) {
> + kfree(async_desc);
> + return ERR_PTR(-ENOMEM);
> + }
> +
> + desc->flags |= cpu_to_le16(DESC_FLAG_CMD | flag);
> + desc->addr = sg_dma_address(&async_desc->lock_sg);
> + desc->size = sizeof(struct bam_cmd_element);
Since the addr and size fields of struct bam_desc_hw are little-endian,
will assigning native integers here corrupt the physical address and size
on big-endian systems?
> +
> + vc = &bchan->vc;
> + vd = &async_desc->vd;
> +
> + dma_async_tx_descriptor_init(&vd->tx, &vc->chan);
> + vd->tx.flags = DMA_PREP_CMD;
> + vd->tx.desc_free = vchan_tx_desc_free;
> + vd->tx_result.result = DMA_TRANS_NOERROR;
> + vd->tx_result.residue = 0;
> +
> + cookie = dma_cookie_assign(&vd->tx);
Because this happens inside bam_start_dma(), after the client has already
prepared and queued their own descriptors, will the new LOCK descriptor
receive a cookie value that is numerically larger than the pending client
transactions?
Since the LOCK descriptor is inserted at the head of desc_issued and will
complete first, will this update the channel's completed_cookie to this
higher value, causing clients to see their own transactions as prematurely
completed?
> + ret = dma_submit_error(cookie);
> + if (ret) {
> + dma_unmap_sg(chan->slave, &async_desc->lock_sg, 1, DMA_TO_DEVICE);
> + kfree(async_desc);
> + return ERR_PTR(ret);
> + }
> +
> + return async_desc;
> +}
> +
> +static int bam_do_setup_pipe_lock(struct bam_chan *bchan, bool lock)
> +{
> + struct bam_device *bdev = bchan->bdev;
> + const struct bam_device_data *bdata = bdev->dev_data;
> + struct bam_async_desc *lock_desc;
> + unsigned long flag;
> +
> + lockdep_assert_held(&bchan->vc.lock);
> +
> + if (!bdata->pipe_lock_supported || !bchan->scratchpad_addr ||
> + bchan->direction != DMA_MEM_TO_DEV)
The commit message explicitly states this is intended for RX channels.
However, DMA_MEM_TO_DEV specifies a TX transfer. Does this check skip
locking for RX channels (DMA_DEV_TO_MEM), contradicting the commit message?
> + return 0;
> +
> + flag = lock ? DESC_FLAG_LOCK : DESC_FLAG_UNLOCK;
> +
> + lock_desc = bam_make_lock_desc(bchan, flag);
> + if (IS_ERR(lock_desc))
> + return PTR_ERR(lock_desc);
> +
> + if (lock)
> + list_add(&lock_desc->vd.node, &bchan->vc.desc_issued);
> + else
> + list_add_tail(&lock_desc->vd.node, &bchan->vc.desc_issued);
> +
> + return 0;
> +}
> +
> +static void bam_setup_pipe_lock(struct bam_chan *bchan)
> +{
> + if (bam_do_setup_pipe_lock(bchan, true) || bam_do_setup_pipe_lock(bchan, false))
If the first call successfully creates the LOCK descriptor (returning 0)
but the second call fails to allocate the UNLOCK descriptor, will the LOCK
descriptor remain queued without its corresponding UNLOCK, permanently
deadlocking the channel?
> + dev_err(bchan->vc.chan.slave, "Failed to setup BAM pipe lock descriptors");
> +}
> +
> /**
> * bam_start_dma - start next transaction
> * @bchan: bam dma channel
> */
> static void bam_start_dma(struct bam_chan *bchan)
> {
> - struct virt_dma_desc *vd = vchan_next_desc(&bchan->vc);
> + struct virt_dma_desc *vd;
> struct bam_device *bdev = bchan->bdev;
> struct bam_async_desc *async_desc = NULL;
> struct bam_desc_hw *desc;
> @@ -1030,6 +1170,9 @@ static void bam_start_dma(struct bam_chan *bchan)
>
> lockdep_assert_held(&bchan->vc.lock);
>
> + bam_setup_pipe_lock(bchan);
If bam_start_dma() encounters a full BAM FIFO and exits early, it leaves
unprocessed descriptors in the desc_issued list. When bam_start_dma() is
called again later, won't it prepend another LOCK and append another UNLOCK
into the middle of the pending transaction sequence, corrupting the hardware
stream?
> +
> + vd = vchan_next_desc(&bchan->vc);
> if (!vd)
> return;
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260519-qcom-qce-cmd-descr-v17-0-53a595414b79@oss.qualcomm.com?part=6
next prev parent reply other threads:[~2026-05-19 13:54 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-19 13:17 [PATCH v17 00/14] crypto/dmaengine: qce: introduce BAM locking and use DMA for register I/O Bartosz Golaszewski
2026-05-19 13:17 ` [PATCH v17 01/14] dmaengine: constify struct dma_descriptor_metadata_ops Bartosz Golaszewski
2026-05-19 13:17 ` [PATCH v17 02/14] dmaengine: qcom: bam_dma: free interrupt before the clock in error path Bartosz Golaszewski
2026-05-19 13:48 ` sashiko-bot
2026-05-19 13:17 ` [PATCH v17 03/14] dmaengine: qcom: bam_dma: convert tasklet to a BH workqueue Bartosz Golaszewski
2026-05-19 13:44 ` sashiko-bot
2026-05-19 13:17 ` [PATCH v17 04/14] dmaengine: qcom: bam_dma: Extend the driver's device match data Bartosz Golaszewski
2026-05-19 13:17 ` [PATCH v17 05/14] dmaengine: qcom: bam_dma: Add pipe_lock_supported flag support Bartosz Golaszewski
2026-05-19 13:17 ` [PATCH v17 06/14] dmaengine: qcom: bam_dma: add support for BAM locking Bartosz Golaszewski
2026-05-19 13:54 ` sashiko-bot [this message]
2026-05-19 13:17 ` [PATCH v17 07/14] crypto: qce - Cancel work on device detach Bartosz Golaszewski
2026-05-19 13:47 ` sashiko-bot
2026-05-19 13:17 ` [PATCH v17 08/14] crypto: qce - Include algapi.h in the core.h header Bartosz Golaszewski
2026-05-19 13:17 ` [PATCH v17 09/14] crypto: qce - Remove unused ignore_buf Bartosz Golaszewski
2026-05-19 13:48 ` sashiko-bot
2026-05-19 13:17 ` [PATCH v17 10/14] crypto: qce - Simplify arguments of devm_qce_dma_request() Bartosz Golaszewski
2026-05-19 13:17 ` [PATCH v17 11/14] crypto: qce - Use existing devres APIs in devm_qce_dma_request() Bartosz Golaszewski
2026-05-19 14:00 ` sashiko-bot
2026-05-19 13:17 ` [PATCH v17 12/14] crypto: qce - Map crypto memory for DMA Bartosz Golaszewski
2026-05-19 13:52 ` sashiko-bot
2026-05-19 13:17 ` [PATCH v17 13/14] crypto: qce - Add BAM DMA support for crypto register I/O Bartosz Golaszewski
2026-05-19 13:56 ` sashiko-bot
2026-05-19 13:17 ` [PATCH v17 14/14] crypto: qce - Communicate the base physical address to the dmaengine Bartosz Golaszewski
2026-05-19 14:17 ` sashiko-bot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260519135428.9D6C7C2BCB3@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=Frank.Li@kernel.org \
--cc=bartosz.golaszewski@oss.qualcomm.com \
--cc=dmaengine@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=vkoul@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox