On 04.03.2016 20:30, Timur Tabi wrote:
On Fri, Oct 9, 2015 at 5:30 AM, Mathias Nyman
<mathias.ny...@linux.intel.com> wrote:
The xhci platform driver needs to work on systems that
either only support 64-bit DMA or only support 32-bit DMA.
Attempt to set a coherent dma mask for 64-bit DMA, and
attempt again with 32-bit DMA if that fails.
I know this patch is a few months old and has already been merged, but
I have a question about how it works, because we're thinking about
doing something similar for another driver.
+ /* Try to set 64-bit DMA first */
+ if (WARN_ON(!pdev->dev.dma_mask))
+ /* Platform did not initialize dma_mask */
+ ret = dma_coerce_mask_and_coherent(&pdev->dev,
+ DMA_BIT_MASK(64));
else
- dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
+
+ /* If seting 64-bit DMA mask fails, fall back to 32-bit DMA mask */
+ if (ret) {
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+ }
I don't understand why this is necessary. I was under the impression
that when a driver calls dma_set_mask_xxx, all it's doing is telling
the kernel what DMA ranges the device is capable of. If a device is
physically capable of DMA'ing to all of RAM (let's assume everything
is coherent), then it should set the mask to 64 and leave it at that.
If the platform has some other DMA address range limitation, the
driver shouldn't have to worry about that. It should still set the
mask to 64, and something else will figure out that the *real* mask is
less than that. Then when the driver calls dma_alloc_coherent(), it
will always get a DMA buffer from low memory, but that's okay.
But apparently, that's not how it really works, which is why this
patch exists. And that's why I'm confused.
I have a few other related questions. Let's say that we have a device
that is normally capable of 64-bit DMA. But on one particular
platform, only 32 bits of the address bus is wired up, so effectively
the device is only capable of 32-bit DMA. This information is hidden
from the device, so the driver cannot query the device itself to
discover this. What is the proper way to handle this? We probably
don't want to add platform-specific code to the driver (like an MIDR
check on ARM systems).
Thanks in advance for any answers. DMA-API-HOWTO.txt says this:
"Rather, it may fail in this case simply because 32-bit
addressing is done more efficiently than 64-bit addressing."
But that doesn't apply in our situation. And even then, this seems
like an odd reason to fail. Wouldn't it make more sense for the
dma_set_mask_xxx() API to just automatically adjust the mask to a
smaller value, and return success?
--
Evolution of the patch can be found in this thread:
http://www.spinics.net/lists/linux-usb/msg128495.html
I think version 8 was the final one.
-Mathias
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majord...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html