Commit 862b4165 authored by Paul Cercueil's avatar Paul Cercueil Committed by Greg Kroah-Hartman

usb: gadget: functionfs: Wait for fences before enqueueing DMABUF

Instead of bailing when fences have already been installed on the
DMABUF, wait for them (with a timeout) when doing a blocking operation.

This fixes the issue where userspace would submit a DMABUF with fences
already installed, with the (correct) expectation that it would just
work.

Fixes: 7b07a2a7 ("usb: gadget: functionfs: Add DMABUF import interface")
Signed-off-by: default avatarPaul Cercueil <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20240402110951.16376-3-paul@crapouillou.netSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1500a7b2
...@@ -46,6 +46,8 @@ ...@@ -46,6 +46,8 @@
#define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */ #define FUNCTIONFS_MAGIC 0xa647361 /* Chosen by a honest dice roll ;) */
#define DMABUF_ENQUEUE_TIMEOUT_MS 5000
MODULE_IMPORT_NS(DMA_BUF); MODULE_IMPORT_NS(DMA_BUF);
/* Reference counter handling */ /* Reference counter handling */
...@@ -1580,9 +1582,11 @@ static int ffs_dmabuf_transfer(struct file *file, ...@@ -1580,9 +1582,11 @@ static int ffs_dmabuf_transfer(struct file *file,
struct usb_request *usb_req; struct usb_request *usb_req;
enum dma_resv_usage resv_dir; enum dma_resv_usage resv_dir;
struct dma_buf *dmabuf; struct dma_buf *dmabuf;
unsigned long timeout;
struct ffs_ep *ep; struct ffs_ep *ep;
bool cookie; bool cookie;
u32 seqno; u32 seqno;
long retl;
int ret; int ret;
if (req->flags & ~USB_FFS_DMABUF_TRANSFER_MASK) if (req->flags & ~USB_FFS_DMABUF_TRANSFER_MASK)
...@@ -1616,17 +1620,14 @@ static int ffs_dmabuf_transfer(struct file *file, ...@@ -1616,17 +1620,14 @@ static int ffs_dmabuf_transfer(struct file *file,
goto err_attachment_put; goto err_attachment_put;
/* Make sure we don't have writers */ /* Make sure we don't have writers */
if (!dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_WRITE)) { timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS);
pr_vdebug("FFS WRITE fence is not signaled\n"); retl = dma_resv_wait_timeout(dmabuf->resv,
ret = -EBUSY; dma_resv_usage_rw(epfile->in),
goto err_resv_unlock; true, timeout);
} if (retl == 0)
retl = -EBUSY;
/* If we're writing to the DMABUF, make sure we don't have readers */ if (retl < 0) {
if (epfile->in && ret = (int)retl;
!dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_READ)) {
pr_vdebug("FFS READ fence is not signaled\n");
ret = -EBUSY;
goto err_resv_unlock; goto err_resv_unlock;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment