Hi, Mathias Nyman <mathias.nyman@xxxxxxxxxxxxxxx> writes: > [ text/plain ] > On 04.03.2016 20:30, Timur Tabi wrote: >> 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? >> -- > > 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. wonder if we should provide a generic static inline for that. Seems like that will replicate on many drivers. How about: static inline int dma_try_mask_and_coherent(struct device *dev) { int ret; ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(64)); if (ret) { ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); if (ret) { dev_err(dev, "failed to set dma mask\n"); return ret; } } return 0; } -- balbi
Attachment:
signature.asc
Description: PGP signature