summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhil Elwell <phil@raspberrypi.com>2021-05-06 12:22:00 +0100
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-05-22 10:38:29 +0200
commitc4ed56cd72eed867603911d3d43a6eb593066666 (patch)
treef3b7af94b9d52453f27831c5aa9ec39f8afe2984
parent72b08f62a6b657fa1c8fb5598e9cb1849dbfb9e5 (diff)
downloadlinux-stable-c4ed56cd72eed867603911d3d43a6eb593066666.tar.gz
usb: dwc2: Fix gadget DMA unmap direction
commit 75a41ce46bae6cbe7d3bb2584eb844291d642874 upstream. The dwc2 gadget support maps and unmaps DMA buffers as necessary. When mapping and unmapping it uses the direction of the endpoint to select the direction of the DMA transfer, but this fails for Control OUT transfers because the unmap occurs after the endpoint direction has been reversed for the status phase. A possible solution would be to unmap the buffer before the direction is changed, but a safer, less invasive fix is to remember the buffer direction independently of the endpoint direction. Fixes: fe0b94abcdf6 ("usb: dwc2: gadget: manage ep0 state in software") Acked-by: Minas Harutyunyan <Minas.Harutyunyan@synopsys.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Phil Elwell <phil@raspberrypi.com> Link: https://lore.kernel.org/r/20210506112200.2893922-1-phil@raspberrypi.com Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/dwc2/core.h2
-rw-r--r--drivers/usb/dwc2/gadget.c3
2 files changed, 4 insertions, 1 deletions
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index a899d47c2a7c..ecc4d09ea704 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -144,6 +144,7 @@ struct dwc2_hsotg_req;
* @lock: State lock to protect contents of endpoint.
* @dir_in: Set to true if this endpoint is of the IN direction, which
* means that it is sending data to the Host.
+ * @map_dir: Set to the value of dir_in when the DMA buffer is mapped.
* @index: The index for the endpoint registers.
* @mc: Multi Count - number of transactions per microframe
* @interval - Interval for periodic endpoints
@@ -185,6 +186,7 @@ struct dwc2_hsotg_ep {
unsigned short fifo_index;
unsigned char dir_in;
+ unsigned char map_dir;
unsigned char index;
unsigned char mc;
u16 interval;
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 135e97310f11..ab5cde515b1d 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -289,7 +289,7 @@ static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
if (hs_req->req.length == 0)
return;
- usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in);
+ usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->map_dir);
}
/**
@@ -707,6 +707,7 @@ static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg,
if (hs_req->req.length == 0)
return 0;
+ hs_ep->map_dir = hs_ep->dir_in;
ret = usb_gadget_map_request(&hsotg->gadget, req, hs_ep->dir_in);
if (ret)
goto dma_error;