Re: [PATCH v3] usb: gadget: net2280: Fix overrun of OUT messages

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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>




[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux