usb: gadget: Support already-mapped DMA SGs
authorPaul Cercueil <paul@crapouillou.net>
Tue, 30 Jan 2024 12:23:37 +0000 (13:23 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 17 Feb 2024 16:00:09 +0000 (17:00 +0100)
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 <paul@crapouillou.net>
Link: https://lore.kernel.org/r/20240130122340.54813-2-paul@crapouillou.net
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/usb/gadget/udc/core.c
include/linux/usb/gadget.h

index d59f94464b870b76c21a5b0380460479fdd1e8ed..9d4150124fdb82b91dcbddc3e8ee9dc24abee7ba 100644 (file)
@@ -903,6 +903,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;
 
@@ -948,7 +953,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) {
index a771ccc038ac949f2b4a835e28d720735e17ee22..c529e4e069975db0a20a63cf9896b21849922ba3 100644 (file)
@@ -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);