2023-03-22 09:39:08

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v2 0/3] usb: gadget: functionfs: DMABUF import interface

Hi,

This small patchset adds three new IOCTLs that can be used to attach,
detach, or transfer from/to a DMABUF object.

Changes since v1:
- patch [2/3] is new. I had to reuse a piece of code that was already
duplicated in the driver, so I factorized the code.
- Make ffs_dma_resv_lock() static
- Add MODULE_IMPORT_NS(DMA_BUF);
- The attach/detach functions are now performed without locking the
eps_lock spinlock. The transfer function starts with the spinlock
unlocked, then locks it before allocating and queueing the USB
transfer.

Cheers,
-Paul

Paul Cercueil (3):
usb: gadget: Support already-mapped DMA SGs
usb: gadget: functionfs: Factorize wait-for-endpoint code
usb: gadget: functionfs: Add DMABUF import interface

drivers/usb/gadget/function/f_fs.c | 467 ++++++++++++++++++++++++++--
drivers/usb/gadget/udc/core.c | 7 +-
include/linux/usb/gadget.h | 2 +
include/uapi/linux/usb/functionfs.h | 14 +-
4 files changed, 468 insertions(+), 22 deletions(-)

--
2.39.2


2023-03-22 09:40:03

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v2 2/3] usb: gadget: functionfs: Factorize wait-for-endpoint code

This exact same code was duplicated in two different places.

Signed-off-by: Paul Cercueil <[email protected]>
---
drivers/usb/gadget/function/f_fs.c | 48 +++++++++++++++++-------------
1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index ddfc537c7526..8da64f0fdef0 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -947,31 +947,44 @@ static ssize_t __ffs_epfile_read_data(struct ffs_epfile *epfile,
return ret;
}

-static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
+static struct ffs_ep *ffs_epfile_wait_ep(struct file *file)
{
struct ffs_epfile *epfile = file->private_data;
- struct usb_request *req;
struct ffs_ep *ep;
- char *data = NULL;
- ssize_t ret, data_len = -EINVAL;
- int halt;
-
- /* Are we still active? */
- if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
- return -ENODEV;
+ int ret;

/* Wait for endpoint to be enabled */
ep = epfile->ep;
if (!ep) {
if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
+ return ERR_PTR(-EAGAIN);

ret = wait_event_interruptible(
epfile->ffs->wait, (ep = epfile->ep));
if (ret)
- return -EINTR;
+ return ERR_PTR(-EINTR);
}

+ return ep;
+}
+
+static ssize_t ffs_epfile_io(struct file *file, struct ffs_io_data *io_data)
+{
+ struct ffs_epfile *epfile = file->private_data;
+ struct usb_request *req;
+ struct ffs_ep *ep;
+ char *data = NULL;
+ ssize_t ret, data_len = -EINVAL;
+ int halt;
+
+ /* Are we still active? */
+ if (WARN_ON(epfile->ffs->state != FFS_ACTIVE))
+ return -ENODEV;
+
+ ep = ffs_epfile_wait_ep(file);
+ if (IS_ERR(ep))
+ return PTR_ERR(ep);
+
/* Do we halt? */
halt = (!io_data->read == !epfile->in);
if (halt && epfile->isoc)
@@ -1305,16 +1318,9 @@ static long ffs_epfile_ioctl(struct file *file, unsigned code,
return -ENODEV;

/* Wait for endpoint to be enabled */
- ep = epfile->ep;
- if (!ep) {
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
-
- ret = wait_event_interruptible(
- epfile->ffs->wait, (ep = epfile->ep));
- if (ret)
- return -EINTR;
- }
+ ep = ffs_epfile_wait_ep(file);
+ if (IS_ERR(ep))
+ return PTR_ERR(ep);

spin_lock_irq(&epfile->ffs->eps_lock);

--
2.39.2

2023-03-22 09:49:52

by Paul Cercueil

[permalink] [raw]
Subject: [PATCH v2 1/3] usb: gadget: Support already-mapped DMA SGs

Add a new 'sg_was_mapped' field to the struct usb_request. This field
can be used to indicate that the scatterlist associated to the USB
transfer has already been mapped into the DMA space, and it does not
have to be done internally.

Signed-off-by: Paul Cercueil <[email protected]>
---
drivers/usb/gadget/udc/core.c | 7 ++++++-
include/linux/usb/gadget.h | 2 ++
2 files changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/gadget/udc/core.c b/drivers/usb/gadget/udc/core.c
index 23b0629a8774..5f2c4933769d 100644
--- a/drivers/usb/gadget/udc/core.c
+++ b/drivers/usb/gadget/udc/core.c
@@ -829,6 +829,11 @@ int usb_gadget_map_request_by_dev(struct device *dev,
if (req->length == 0)
return 0;

+ if (req->sg_was_mapped) {
+ req->num_mapped_sgs = req->num_sgs;
+ return 0;
+ }
+
if (req->num_sgs) {
int mapped;

@@ -874,7 +879,7 @@ EXPORT_SYMBOL_GPL(usb_gadget_map_request);
void usb_gadget_unmap_request_by_dev(struct device *dev,
struct usb_request *req, int is_in)
{
- if (req->length == 0)
+ if (req->length == 0 || req->sg_was_mapped)
return;

if (req->num_mapped_sgs) {
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 00750f7020f3..9dd829b8974a 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -52,6 +52,7 @@ struct usb_ep;
* @short_not_ok: When reading data, makes short packets be
* treated as errors (queue stops advancing till cleanup).
* @dma_mapped: Indicates if request has been mapped to DMA (internal)
+ * @sg_was_mapped: Set if the scatterlist has been mapped before the request
* @complete: Function called when request completes, so this request and
* its buffer may be re-used. The function will always be called with
* interrupts disabled, and it must not sleep.
@@ -111,6 +112,7 @@ struct usb_request {
unsigned zero:1;
unsigned short_not_ok:1;
unsigned dma_mapped:1;
+ unsigned sg_was_mapped:1;

void (*complete)(struct usb_ep *ep,
struct usb_request *req);
--
2.39.2

2023-03-31 09:53:48

by Andrzej Pietrasiewicz

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] usb: gadget: functionfs: DMABUF import interface

Hi Paul,

W dniu 22.03.2023 o 10:21, Paul Cercueil pisze:
> Hi,
>
> This small patchset adds three new IOCTLs that can be used to attach,
> detach, or transfer from/to a DMABUF object.
>
> Changes since v1:
> - patch [2/3] is new. I had to reuse a piece of code that was already
> duplicated in the driver, so I factorized the code.
> - Make ffs_dma_resv_lock() static
> - Add MODULE_IMPORT_NS(DMA_BUF);
> - The attach/detach functions are now performed without locking the
> eps_lock spinlock. The transfer function starts with the spinlock
> unlocked, then locks it before allocating and queueing the USB
> transfer.
>

Can you share an example use case for these new features?
Is there a userspace that excercises the new ioctls?

Regards,

Andrzej

2023-04-01 14:37:08

by Paul Cercueil

[permalink] [raw]
Subject: Re: [PATCH v2 0/3] usb: gadget: functionfs: DMABUF import interface

Hi Andrzej,

Le vendredi 31 mars 2023 à 11:40 +0200, Andrzej Pietrasiewicz a écrit :
> Hi Paul,
>
> W dniu 22.03.2023 o 10:21, Paul Cercueil pisze:
> > Hi,
> >
> > This small patchset adds three new IOCTLs that can be used to
> > attach,
> > detach, or transfer from/to a DMABUF object.
> >
> > Changes since v1:
> > - patch [2/3] is new. I had to reuse a piece of code that was
> > already
> >    duplicated in the driver, so I factorized the code.
> > - Make ffs_dma_resv_lock() static
> > - Add MODULE_IMPORT_NS(DMA_BUF);
> > - The attach/detach functions are now performed without locking the
> >    eps_lock spinlock. The transfer function starts with the
> > spinlock
> >    unlocked, then locks it before allocating and queueing the USB
> >    transfer.
> >
>
> Can you share an example use case for these new features?
> Is there a userspace that excercises the new ioctls?

We use it at Analog Devices to share buffers between the IIO subsystem
and the USB stack, which makes it possible to stream data samples
between a host computer and high-speed transceivers as fast as
possible, in a zero-copy fashion.

This will be used by Libiio:
https://github.com/analogdevicesinc/libiio/pull/928/commits/dd348137ce371532fd952a2b249cfd96afaef7d1

The code that uses these IOCTLs is not yet merged to the "master"
branch, but will be as soon as this patchset is accepted.

Cheers,
-Paul