]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
usb: gadget: f_fs: fix DMA-BUF OUT queues
authorSam Day <me@samcday.com>
Wed, 7 Jan 2026 22:30:21 +0000 (08:30 +1000)
committerSasha Levin <sashal@kernel.org>
Wed, 4 Mar 2026 12:20:41 +0000 (07:20 -0500)
[ Upstream commit 0145e7acd29855dfba4a2f387d455b5d9a520f0e ]

Currently, DMA_FROM_DEVICE is used when attaching DMABUFs to IN
endpoints and DMA_TO_DEVICE for OUT endpoints. This is inverted from
how it should be.

The result is IOMMU read-only mappings placed on OUT queues,
triggering arm-smmu write faults.

Put differently, OUT endpoints flow data from host -> gadget, meaning
the UDC peripheral needs to have write access to the buffer to fill it
with the incoming data.

This commit flips the directions and updates the implicit-sync helpers
so IN endpoints act as readers and OUT endpoints as writers.

Signed-off-by: Sam Day <me@samcday.com>
Tested-by: David Heidelberg <david@ixit.cz> # OnePlus 6T on sdm845-next-20251119
Link: https://patch.msgid.link/20260108-ffs-dmabuf-ioctl-fix-v1-2-e51633891a81@samcday.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/usb/gadget/function/f_fs.c

index fa467a40949d2ebbb05ef564877600bdf02f9bb7..928f51fddc64e38003f57bde76fa05e69ff6dd7a 100644 (file)
@@ -1509,7 +1509,7 @@ static int ffs_dmabuf_attach(struct file *file, int fd)
                goto err_dmabuf_detach;
        }
 
-       dir = epfile->in ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+       dir = epfile->in ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
 
        err = ffs_dma_resv_lock(dmabuf, nonblock);
        if (err)
@@ -1639,7 +1639,7 @@ static int ffs_dmabuf_transfer(struct file *file,
        /* Make sure we don't have writers */
        timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS);
        retl = dma_resv_wait_timeout(dmabuf->resv,
-                                    dma_resv_usage_rw(epfile->in),
+                                    dma_resv_usage_rw(!epfile->in),
                                     true, timeout);
        if (retl == 0)
                retl = -EBUSY;
@@ -1684,7 +1684,7 @@ static int ffs_dmabuf_transfer(struct file *file,
        dma_fence_init(&fence->base, &ffs_dmabuf_fence_ops,
                       &priv->lock, priv->context, seqno);
 
-       resv_dir = epfile->in ? DMA_RESV_USAGE_WRITE : DMA_RESV_USAGE_READ;
+       resv_dir = epfile->in ? DMA_RESV_USAGE_READ : DMA_RESV_USAGE_WRITE;
 
        dma_resv_add_fence(dmabuf->resv, &fence->base, resv_dir);
        dma_resv_unlock(dmabuf->resv);