Re: [PATCH] xhci: fix dma mask setup in xhci.c

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

 



I'm a little bit confused by this patch, so I'm CC-ing the list.

On Tue, Jun 25, 2013 at 08:52:49AM +0300, Xenia Ragiadakou wrote:
> According to DMA-API-HOWTO, if coherent DMA address
> mask has not been set explicitly, and the driver
> calls dma_alloc_coherent() or dma_pool_create() to
> allocate consistent DMA memory blocks, the consistent
> DMA mapping interface will return by default DMA
> addresses which are 32-bit addressable.
> 
> In the xhci driver, coherent_dma_mask is not set to
> 64-bits to take advantage of 64-bit DMA mapping
> when it is supported.
> 
> Another thing is that dma_set_mask() tests internally
> whether dma_mask pointer is NULL. For pci platforms,
> dma_mask pointer initialization is done when pci devices
> are enumerated (the dma_mask for pci devices is set to
> 32-bits). However, for non-pci platforms, dma_mask pointer
> is not initialized and dma_set_mask() will fail.
> 
> This patch initializes the dma_mask pointer to point
> to the coherent_dma_mask, since the same value will
> be assigned to both, and adds a check on the value
> returned by dma_set_mask().
> 
> dma_set_coherent_mask() is not called because it is
> guaranteed that if dma_set_mask() succeeds, for a
> given bitmask, dma_set_coherent_mask() will also
> succeed for the same bitmask.

Did you mean to say "The return value of dma_set_coherent_mask() is not
checked because..." instead of "dma_set_coherent_mask() is not called
because..." ?

I believe the discussion was that dma_set_coherent_mask() is guaranteed
to succeed if dma_set_mask() succeeds.  However, you still need to set
dev.coherent_dma_mask with a call to dma_set_coherent_mask().  I don't
see where in this patch you do that.

> Signed-off-by: Xenia Ragiadakou <burzalodowa@xxxxxxxxx>
> ---
>  drivers/usb/host/xhci.c | 18 ++++++++++++------
>  1 file changed, 12 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
> index d8f640b..b5db324 100644
> --- a/drivers/usb/host/xhci.c
> +++ b/drivers/usb/host/xhci.c
> @@ -4672,11 +4672,14 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
>  		 */
>  		xhci = hcd_to_xhci(hcd);
>  		temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
> -		if (HCC_64BIT_ADDR(temp)) {
> +		dev->dma_mask = &dev->coherent_dma_mask;

This should be

		if (!dev->dev.dma_mask)
			dev->dma_mask = &dev->coherent_dma_mask;

If the dma_mask pointer is already set (say by the PCI core), we don't
want to overwrite it.  We just want to set the mask pointer if this is a
platform device without a DMA pointer.

> +		if (HCC_64BIT_ADDR(temp) &&
> +		    !dma_set_mask(dev, DMA_BIT_MASK(64))) {
>  			xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
> -			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
> +			dma_set_mask(dev, DMA_BIT_MASK(64));

I believe you wanted to call dma_set_coherent_mask() in that last line
above, rather than calling dma_set_mask() again (you called it in the if
statement).

>  		} else {
> -			dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
> +			if (dma_set_mask(dev, DMA_BIT_MASK(32)))
> +				goto error;

I think you need to call dma_set_coherent_mask(dev, DMA_BIT_MASK(32))
when that dma_set_mask() call succeeds.  If we're dealing with a
platform device, it may not have the coherent mask set.  Alan, Andy,
Felipe, does this sound correct?

>  		}
>  		return 0;
>  	}
> @@ -4710,11 +4713,14 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
>  	xhci_dbg(xhci, "Reset complete\n");
>  
>  	temp = xhci_readl(xhci, &xhci->cap_regs->hcc_params);
> -	if (HCC_64BIT_ADDR(temp)) {
> +	dev->dma_mask = &dev->coherent_dma_mask;
> +	if (HCC_64BIT_ADDR(temp) &&
> +	    !dma_set_mask(dev, DMA_BIT_MASK(64))) {
>  		xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");
> -		dma_set_mask(hcd->self.controller, DMA_BIT_MASK(64));
> +		dma_set_mask(dev, DMA_BIT_MASK(64));
>  	} else {
> -		dma_set_mask(hcd->self.controller, DMA_BIT_MASK(32));
> +		if (dma_set_mask(dev, DMA_BIT_MASK(32)))
> +			goto error;
>  	}

Given that this code is in xhci_gen_setup twice, can you please refactor
the existing code into a separate function, and then in another patch
change that function to set the dev->dma_mask pointer, and then call
dma_set_mask and dma_set_coherent_mask?

>  
>  	xhci_dbg(xhci, "Calling HCD init\n");
> -- 
> 1.8.3.1
> 

Sarah Sharp

p.s.

> +		if (HCC_64BIT_ADDR(temp) &&
> +		    !dma_set_mask(dev, DMA_BIT_MASK(64))) {

Although Greg prefers aligning trailing lines to parenthesis,  I do not.
I would prefer this line look like:

		if (HCC_64BIT_ADDR(temp) &&
			!dma_set_mask(dev, DMA_BIT_MASK(64))) {

Please stick with the coding style in the xHCI driver and align the code
according the standard vim or emacs C file indentation.  You can set up
your .vimrc file to recognize file types by adding this line:

filetype plugin indent on
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




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

  Powered by Linux