[U-Boot] [PATCH v5 02/19] usb: dwc2: Use separate input and output buffers

Marek Vasut marex at denx.de
Sat Apr 1 20:15:27 UTC 2017


On 04/01/2017 08:05 PM, Simon Glass wrote:
> On Raspberry Pi 2 and 3 a problem was noticed when enabling driver model
> for USB: the cache invalidate after an incoming transfer does not seem to
> work correctly.
> 
> This may be a problem with the underlying caching implementation on armv7
> and armv8 but this seems very unlikely. As a work-around, use separate
> buffers for input and output. This ensures that the input buffer will not
> hold dirty cache data.

What do you think of this patch:
[U-Boot] usb: dwc2: invalidate the dcache before starting the DMA

> Signed-off-by: Simon Glass <sjg at chromium.org>
> ---
> 
> Changes in v5:
> - Add new patch for dwc2 to se separate input and output buffers
> 
> Changes in v4: None
> Changes in v3: None
> 
>  drivers/usb/host/dwc2.c | 27 ++++++++++++++++++++-------
>  1 file changed, 20 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c
> index d253b946f3..a65ed4f66c 100644
> --- a/drivers/usb/host/dwc2.c
> +++ b/drivers/usb/host/dwc2.c
> @@ -31,10 +31,14 @@ DECLARE_GLOBAL_DATA_PTR;
>  
>  struct dwc2_priv {
>  #ifdef CONFIG_DM_USB
> -	uint8_t aligned_buffer[DWC2_DATA_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
> +	uint8_t aligned_buffer_in[DWC2_DATA_BUF_SIZE]
> +			__aligned(ARCH_DMA_MINALIGN);
> +	uint8_t aligned_buffer_out[DWC2_DATA_BUF_SIZE]
> +			__aligned(ARCH_DMA_MINALIGN);
>  	uint8_t status_buffer[DWC2_STATUS_BUF_SIZE] __aligned(ARCH_DMA_MINALIGN);
>  #else
> -	uint8_t *aligned_buffer;
> +	uint8_t *aligned_buffer_in;
> +	uint8_t *aligned_buffer_out;
>  	uint8_t *status_buffer;
>  #endif
>  	u8 in_data_toggle[MAX_DEVICE][MAX_ENDPOINT];
> @@ -769,10 +773,12 @@ static int dwc2_eptype[] = {
>  	DWC2_HCCHAR_EPTYPE_BULK,
>  };
>  
> -static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer,
> -			  u8 *pid, int in, void *buffer, int num_packets,
> -			  int xfer_len, int *actual_len, int odd_frame)
> +static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer_in,
> +			  void *aligned_buffer_out, u8 *pid, int in,
> +			  void *buffer, int num_packets, int xfer_len,
> +			  int *actual_len, int odd_frame)
>  {
> +	void *aligned_buffer;
>  	int ret = 0;
>  	uint32_t sub;
>  
> @@ -785,11 +791,14 @@ static int transfer_chunk(struct dwc2_hc_regs *hc_regs, void *aligned_buffer,
>  	       &hc_regs->hctsiz);
>  
>  	if (!in && xfer_len) {
> +		aligned_buffer = aligned_buffer_in;
>  		memcpy(aligned_buffer, buffer, xfer_len);
>  
>  		flush_dcache_range((unsigned long)aligned_buffer,
>  				   (unsigned long)aligned_buffer +
>  				   roundup(xfer_len, ARCH_DMA_MINALIGN));
> +	} else {
> +		aligned_buffer = aligned_buffer_out;
>  	}
>  
>  	writel(phys_to_bus((unsigned long)aligned_buffer), &hc_regs->hcdma);
> @@ -901,7 +910,8 @@ int chunk_msg(struct dwc2_priv *priv, struct usb_device *dev,
>  				odd_frame = 1;
>  		}
>  
> -		ret = transfer_chunk(hc_regs, priv->aligned_buffer, pid,
> +		ret = transfer_chunk(hc_regs, priv->aligned_buffer_in,
> +				     priv->aligned_buffer_out, pid,
>  				     in, (char *)buffer + done, num_packets,
>  				     xfer_len, &actual_len, odd_frame);
>  
> @@ -1136,7 +1146,10 @@ int usb_lowlevel_init(int index, enum usb_init_type init, void **controller)
>  	memset(priv, '\0', sizeof(*priv));
>  	priv->root_hub_devnum = 0;
>  	priv->regs = (struct dwc2_core_regs *)CONFIG_USB_DWC2_REG_ADDR;
> -	priv->aligned_buffer = aligned_buffer_addr;
> +
> +	/* We can use the same buffer for input and output */
> +	priv->aligned_buffer_in = aligned_buffer_addr;
> +	priv->aligned_buffer_out = aligned_buffer_addr;
>  	priv->status_buffer = status_buffer_addr;
>  
>  	/* board-dependant init */
> 


-- 
Best regards,
Marek Vasut


More information about the U-Boot mailing list