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

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

 



On Wed, Jun 26, 2013 at 01:20:53AM +0300, Xenia Ragiadakou wrote:
> On 06/26/2013 12:16 AM, Sarah Sharp wrote:
> >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:
> >>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.
> 
> Since, now the dma_mask pointer points to the coherent_dma_mask,
> the value of both will be set via dma_set_mask().
> I do not know if that is more clear.

Ah, ok, I understand why you wrote the original code that way.

> >>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.
> 
> I did not add, in purpose, this check because since both dma_mask
> and coherent_dma_mask will be assigned the same bitmask,
> I thought better to make the assignment once.
> The fact that maybe there is problem when changing the address to
> which points dma_mask in pci platforms didnot cross my mind at
> that moment.

I looked at the PCI init code.  Here's what happens in
drivers/pci/probe.c:

During PCI initialization, pci_dev->dma_mask gets set to 32-bits in
pci_setup_device().  Later, when the PCI device is added, the base
device structure's DMA mask is changed to point to pci_dev->dma_mask.
That means pci_device_add() sets pci_dev->dev.dma mask to point to
pci_dev->dma_mask.  The pci_dev->dev.coherent_dma_mask is set to a
32-bit value.

If you change the dev->dma_mask pointer to point to
&dev->coherent_dma_mask, that means the pci_dev->dma_mask won't get
updated when you call dma_set_mask().  That wouldn't be good, since the
underlying base device and pci_dev structures could end up with
different DMA masks.

The TLDR; version is that if dev->dma_mask is set, you shouldn't change
it.  That means you'll need to add the additional if statement, and
call dma_set_coherent_mask() as well.

> >>+		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).
> 
> Sorry, about that! Actually I wanted to call just:
> 
> xhci_dbg(xhci, "Enabling 64-bit DMA addresses.\n");

Ok, please fix that too.

> >>  		} 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?
> 
> As I said above, dma_set_mask() will set the DMA bitmask to both,
> if this bitmask is supported. If it is supported, it is guaranteed
> that the same bitmask will also be supported for consistent DMA
> mappings so there is no need to call dma_set_coherent_mask()
> (since now the coherent mask is already set via dma_set_mask()
> and it is sure that it is supported).

Right, there was no need to call dma_set_coherent_mask() in your
original code, but in the next revision of the patch, you will need to
call it here.

Sarah Sharp
--
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