All of lore.kernel.org
 help / color / mirror / Atom feed
* [v3] usb: gadget: net2280: Fix overrun of OUT messages
@ 2019-03-19 17:24 Alan Stern
  0 siblings, 0 replies; 2+ messages in thread
From: Alan Stern @ 2019-03-19 17:24 UTC (permalink / raw)
  To: Guido Kiener; +Cc: felipe.balbi, linux-usb, guido.kiener

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@rohde-schwarz.com>
> ---
>  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@rowland.harvard.edu>

^ permalink raw reply	[flat|nested] 2+ messages in thread

* [v3] usb: gadget: net2280: Fix overrun of OUT messages
@ 2019-03-19 18:12 Guido Kiener
  0 siblings, 0 replies; 2+ messages in thread
From: Guido Kiener @ 2019-03-19 18:12 UTC (permalink / raw)
  To: felipe.balbi, linux-usb, guido.kiener, Alan Stern; +Cc: Guido Kiener

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@rohde-schwarz.com>
---
 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;

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2019-03-19 18:12 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-03-19 17:24 [v3] usb: gadget: net2280: Fix overrun of OUT messages Alan Stern
2019-03-19 18:12 Guido Kiener

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.