On 5/6/2021 3:22 PM, Phil Elwell wrote: > 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") > Signed-off-by: Phil Elwell <phil@xxxxxxxxxxxxxxx> Acked-by: Minas Harutyunyan <Minas.Harutyunyan@xxxxxxxxxxxx> > --- > drivers/usb/dwc2/core.h | 2 ++ > drivers/usb/dwc2/gadget.c | 3 ++- > 2 files changed, 4 insertions(+), 1 deletion(-) > > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h > index da5ac4a4595b..ab6b815e0089 100644 > --- a/drivers/usb/dwc2/core.h > +++ b/drivers/usb/dwc2/core.h > @@ -113,6 +113,7 @@ struct dwc2_hsotg_req; > * @debugfs: File entry for debugfs file for this 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, in frames or microframes. > @@ -162,6 +163,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 e6bb1bdb2760..184964174dc0 100644 > --- a/drivers/usb/dwc2/gadget.c > +++ b/drivers/usb/dwc2/gadget.c > @@ -422,7 +422,7 @@ static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg, > { > struct usb_request *req = &hs_req->req; > > - usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in); > + usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->map_dir); > } > > /* > @@ -1242,6 +1242,7 @@ static int dwc2_hsotg_map_dma(struct dwc2_hsotg *hsotg, > { > int ret; > > + 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; >