On Tue, 19 Mar 2019, Guido Kiener wrote: > The OUT endpoint normally blocks (NAK) subsequent packets when a > short packet was received and returns an incomplete queue entry to > the gadget driver. Thereby the gadget driver can detect a short packet > when reading queue entries with a length that is not equal to a > multiple of packet size. > > The start_queue() function enables receiving OUT packets regardless of > the content of the OUT FIFO. This results in a race: With the current > code, it's possible that the "!ep->is_in && (readl(&ep->regs->ep_stat) > & BIT(NAK_OUT_PACKETS))" test in start_dma() will fail, then a short > packet will be received, and then start_queue() will call > stop_out_naking(). That's what we don't want (OUT naking gets turned > off while there is data in the FIFO) because then the next driver > request might receive a mixture of old and new packets. > > With the patch, this race can't occur because the FIFO's state is > tested after we know that OUT naking is already turned on, and OUT > naking is stopped only when both of the conditions are met. This > ensures that all received data is delivered to the gadget driver, > which can detect a short packet now before new packets are appended > to the last short packet. > > Signed-off-by: Guido Kiener <guido.kiener@xxxxxxxxxxxxxxxxx> > --- > drivers/usb/gadget/udc/net2280.c | 4 +--- > 1 file changed, 1 insertion(+), 3 deletions(-) > > diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c > index f63f82450bf4..e0b413e9e532 100644 > --- a/drivers/usb/gadget/udc/net2280.c > +++ b/drivers/usb/gadget/udc/net2280.c > @@ -866,9 +866,6 @@ static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma) > (void) readl(&ep->dev->pci->pcimstctl); > > writel(BIT(DMA_START), &dma->dmastat); > - > - if (!ep->is_in) > - stop_out_naking(ep); > } > > static void start_dma(struct net2280_ep *ep, struct net2280_request *req) > @@ -907,6 +904,7 @@ static void start_dma(struct net2280_ep *ep, struct net2280_request *req) > writel(BIT(DMA_START), &dma->dmastat); > return; > } > + stop_out_naking(ep); > } > > tmp = dmactl_default; Acked-by: Alan Stern <stern@xxxxxxxxxxxxxxxxxxx>