Message ID | 20140516174009.GB11276@arm.com |
---|---|
State | New |
Headers | show |
On Fri, 2014-05-16 at 18:40 +0100, Catalin Marinas wrote: > On Fri, May 16, 2014 at 06:08:45PM +0100, Jon Medhurst (Tixy) wrote: > > On Fri, 2014-05-16 at 13:55 +0100, Catalin Marinas wrote: > > [...] > > > > It could if arm64 would restrict the DMA addresses to 32-bit, but it doesn't > > > > and I end up on my platform with USB DMA buffers allocated >4GB address. > > > > > > dma_alloc_coherent() on arm64 should return 32-bit addresses if the > > > coherent_dma_mask is set to 32-bit. > > > > Not if you have CONFIG_DMA_CMA. Unless I have misread the code, enabling > > CMA means memory comes from a common pool carved out at boot with no way > > for drivers to specify it's restrictions [1]. It's what I've spent most > > of the week trying to work around in a clean way, and have finally given > > up. > > The easiest "hack" would be to pass a limit dma_contiguous_reserve() > in arm64_memblock_init(), something like this: That is by far the easiest but I dismissed it because it affects all platforms built from that source tree; and if the hack were extended to include a kernel config option, that still may not work on a single kernel binary expected to work on multiple platforms. Basically, I've tried various was to do it 'properly' and after failing am resorting to truly hideous hacks to the (out-of-tree driver) code - so at least other platforms won't be impacted.
On Mon, May 19, 2014 at 09:21:17AM +0100, Jon Medhurst (Tixy) wrote: > On Fri, 2014-05-16 at 18:40 +0100, Catalin Marinas wrote: > > On Fri, May 16, 2014 at 06:08:45PM +0100, Jon Medhurst (Tixy) wrote: > > > On Fri, 2014-05-16 at 13:55 +0100, Catalin Marinas wrote: > > > [...] > > > > > It could if arm64 would restrict the DMA addresses to 32-bit, but it doesn't > > > > > and I end up on my platform with USB DMA buffers allocated >4GB address. > > > > > > > > dma_alloc_coherent() on arm64 should return 32-bit addresses if the > > > > coherent_dma_mask is set to 32-bit. > > > > > > Not if you have CONFIG_DMA_CMA. Unless I have misread the code, enabling > > > CMA means memory comes from a common pool carved out at boot with no way > > > for drivers to specify it's restrictions [1]. It's what I've spent most > > > of the week trying to work around in a clean way, and have finally given > > > up. > > > > The easiest "hack" would be to pass a limit dma_contiguous_reserve() > > in arm64_memblock_init(), something like this: > > That is by far the easiest but I dismissed it because it affects all > platforms built from that source tree; and if the hack were extended to > include a kernel config option, that still may not work on a single > kernel binary expected to work on multiple platforms. Basically, I've > tried various was to do it 'properly' and after failing am resorting to > truly hideous hacks to the (out-of-tree driver) code - so at least other > platforms won't be impacted. Can you set a specific reserved memory region in the DT to be used by CMA (via linux,cma-default), or it's just for the default size? On arm64 we enabled CONFIG_DMA_CMA by default but compared to swiotlb it doesn't honour GFP_DMA. The arm32 port sets the CMA limit to arm_dma_limit which is 32-bit or a SoC-define one. So I'm tempted to default to 32-bit as well if it can be overridden via DT.
On Thu, 2014-05-22 at 16:59 +0100, Catalin Marinas wrote: > On Mon, May 19, 2014 at 09:21:17AM +0100, Jon Medhurst (Tixy) wrote: > > On Fri, 2014-05-16 at 18:40 +0100, Catalin Marinas wrote: > > > On Fri, May 16, 2014 at 06:08:45PM +0100, Jon Medhurst (Tixy) wrote: > > > > On Fri, 2014-05-16 at 13:55 +0100, Catalin Marinas wrote: > > > > [...] > > > > > > It could if arm64 would restrict the DMA addresses to 32-bit, but it doesn't > > > > > > and I end up on my platform with USB DMA buffers allocated >4GB address. > > > > > > > > > > dma_alloc_coherent() on arm64 should return 32-bit addresses if the > > > > > coherent_dma_mask is set to 32-bit. > > > > > > > > Not if you have CONFIG_DMA_CMA. Unless I have misread the code, enabling > > > > CMA means memory comes from a common pool carved out at boot with no way > > > > for drivers to specify it's restrictions [1]. It's what I've spent most > > > > of the week trying to work around in a clean way, and have finally given > > > > up. > > > > > > The easiest "hack" would be to pass a limit dma_contiguous_reserve() > > > in arm64_memblock_init(), something like this: > > > > That is by far the easiest but I dismissed it because it affects all > > platforms built from that source tree; and if the hack were extended to > > include a kernel config option, that still may not work on a single > > kernel binary expected to work on multiple platforms. Basically, I've > > tried various was to do it 'properly' and after failing am resorting to > > truly hideous hacks to the (out-of-tree driver) code - so at least other > > platforms won't be impacted. > > Can you set a specific reserved memory region in the DT to be used by > CMA (via linux,cma-default), or it's just for the default size? The bindings and infrastructure got half merged in 3.15 but the patches to actually make this usable in drivers are stalled... http://lkml.org/lkml/2014/5/14/201 > On arm64 we enabled CONFIG_DMA_CMA by default but compared to swiotlb it > doesn't honour GFP_DMA. The arm32 port sets the CMA limit to > arm_dma_limit which is 32-bit or a SoC-define one. So I'm tempted to > default to 32-bit as well if it can be overridden via DT. I believe the CMA pool could have been over-ridden if the stalled patches been accepted. I believe the specific patch for that is http://lkml.org/lkml/2014/2/28/278 The bindings for all this CMA stuf is in Documentation/devicetree/bindings/reserved-memory/reserved-memory.txt
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 51d5352e6ad5..558434c69612 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -162,7 +162,7 @@ void __init arm64_memblock_init(void) } early_init_fdt_scan_reserved_mem(); - dma_contiguous_reserve(0); + dma_contiguous_reserve(dma_to_phys(NULL, DMA_BIT_MASK(32)) + 1); memblock_allow_resize(); memblock_dump_all();