On Fri, Oct 9, 2015 at 5:30 AM, Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx> 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? -- 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