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

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.net


Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1500a7b2
Loading
Loading
Loading
Loading
+12 −11
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@

#define FUNCTIONFS_MAGIC	0xa647361 /* Chosen by a honest dice roll ;) */

#define DMABUF_ENQUEUE_TIMEOUT_MS 5000

MODULE_IMPORT_NS(DMA_BUF);

/* Reference counter handling */
@@ -1580,9 +1582,11 @@ static int ffs_dmabuf_transfer(struct file *file,
	struct usb_request *usb_req;
	enum dma_resv_usage resv_dir;
	struct dma_buf *dmabuf;
	unsigned long timeout;
	struct ffs_ep *ep;
	bool cookie;
	u32 seqno;
	long retl;
	int ret;

	if (req->flags & ~USB_FFS_DMABUF_TRANSFER_MASK)
@@ -1616,17 +1620,14 @@ static int ffs_dmabuf_transfer(struct file *file,
		goto err_attachment_put;

	/* Make sure we don't have writers */
	if (!dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_WRITE)) {
		pr_vdebug("FFS WRITE fence is not signaled\n");
		ret = -EBUSY;
		goto err_resv_unlock;
	}

	/* If we're writing to the DMABUF, make sure we don't have readers */
	if (epfile->in &&
	    !dma_resv_test_signaled(dmabuf->resv, DMA_RESV_USAGE_READ)) {
		pr_vdebug("FFS READ fence is not signaled\n");
		ret = -EBUSY;
	timeout = nonblock ? 0 : msecs_to_jiffies(DMABUF_ENQUEUE_TIMEOUT_MS);
	retl = dma_resv_wait_timeout(dmabuf->resv,
				     dma_resv_usage_rw(epfile->in),
				     true, timeout);
	if (retl == 0)
		retl = -EBUSY;
	if (retl < 0) {
		ret = (int)retl;
		goto err_resv_unlock;
	}