Message ID | 1309919442-20451-1-git-send-email-nicolas.pitre@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
2011/7/6 Nicolas Pitre <nicolas.pitre@linaro.org>: > Having this value defined at compile time prevents multiple machines with > conflicting definitions to coexist. Move it to a variable in preparation > for having a per machine value selected at run time. This is relevant > only when CONFIG_ZONE_DMA is selected. > > Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> that is definitely good. i am not sure whether it will be better if dma zone becomes a property in memory node of DT. memory { reg = <0x00000000 0x20000000>; dma_zone = <0x00000000 0x10000000>; }; > --- > arch/arm/include/asm/dma.h | 7 ++++--- > arch/arm/include/asm/memory.h | 7 +++++-- > arch/arm/mm/init.c | 20 +++++++++++++------- > 3 files changed, 22 insertions(+), 12 deletions(-) > > diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h > index 4200554..1d34c11 100644 > --- a/arch/arm/include/asm/dma.h > +++ b/arch/arm/include/asm/dma.h > @@ -6,10 +6,11 @@ > /* > * This is the maximum virtual address which can be DMA'd from. > */ > -#ifndef ARM_DMA_ZONE_SIZE > -#define MAX_DMA_ADDRESS 0xffffffff > +#ifndef CONFIG_ZONE_DMA > +#define MAX_DMA_ADDRESS 0xffffffffUL > #else > -#define MAX_DMA_ADDRESS (PAGE_OFFSET + ARM_DMA_ZONE_SIZE) > +extern unsigned long arm_dma_zone_size; > +#define MAX_DMA_ADDRESS (PAGE_OFFSET + arm_dma_zone_size) > #endif > > #ifdef CONFIG_ISA_DMA_API > diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h > index af44a8f..deb2eaa 100644 > --- a/arch/arm/include/asm/memory.h > +++ b/arch/arm/include/asm/memory.h > @@ -209,10 +209,13 @@ static inline unsigned long __phys_to_virt(unsigned long x) > * allocations. This must be the smallest DMA mask in the system, > * so a successful GFP_DMA allocation will always satisfy this. > */ > -#ifndef ARM_DMA_ZONE_SIZE > +#ifndef CONFIG_ZONE_DMA > #define ISA_DMA_THRESHOLD (0xffffffffULL) > #else > -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + ARM_DMA_ZONE_SIZE - 1) > +#define ISA_DMA_THRESHOLD ({ \ > + extern unsigned long arm_dma_zone_size; \ > + arm_dma_zone_size ? \ > + (PHYS_OFFSET + arm_dma_zone_size - 1) : 0xffffffffULL; }) > #endif > > /* > diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c > index c19571c..a14caff 100644 > --- a/arch/arm/mm/init.c > +++ b/arch/arm/mm/init.c > @@ -34,6 +34,15 @@ > > #include "mm.h" > > +#ifdef CONFIG_ZONE_DMA > +#ifdef ARM_DMA_ZONE_SIZE > +unsigned long arm_dma_zone_size = ARM_DMA_ZONE_SIZE; > +#else > +unsigned long arm_dma_zone_size __read_mostly; > +#endif > +EXPORT_SYMBOL(arm_dma_zone_size); > +#endif > + > static unsigned long phys_initrd_start __initdata = 0; > static unsigned long phys_initrd_size __initdata = 0; > > @@ -267,17 +276,14 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, > #endif > } > > -#ifdef ARM_DMA_ZONE_SIZE > -#ifndef CONFIG_ZONE_DMA > -#error ARM_DMA_ZONE_SIZE set but no DMA zone to limit allocations > -#endif > - > +#ifdef CONFIG_ZONE_DMA > /* > * Adjust the sizes according to any special requirements for > * this machine type. > */ > - arm_adjust_dma_zone(zone_size, zhole_size, > - ARM_DMA_ZONE_SIZE >> PAGE_SHIFT); > + if (arm_dma_zone_size) > + arm_adjust_dma_zone(zone_size, zhole_size, > + arm_dma_zone_size >> PAGE_SHIFT); > #endif > > free_area_init_node(0, zone_size, min, zhole_size); > -- > 1.7.4 > > > _______________________________________________ > linux-arm-kernel mailing list > linux-arm-kernel@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/linux-arm-kernel >
On Wed, 6 Jul 2011, Barry Song wrote: > 2011/7/6 Nicolas Pitre <nicolas.pitre@linaro.org>: > > Having this value defined at compile time prevents multiple machines with > > conflicting definitions to coexist. Move it to a variable in preparation > > for having a per machine value selected at run time. This is relevant > > only when CONFIG_ZONE_DMA is selected. > > > > Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> > > that is definitely good. i am not sure whether it will be better if > dma zone becomes a property in memory node of DT. Certainly. But one thing at a time. This is the first step. Then, those machines that are converted to DT could more easily provide the information via this mechanism if they so desire. Nicolas
On Tue, Jul 05, 2011 at 10:30:33PM -0400, Nicolas Pitre wrote: > +extern unsigned long arm_dma_zone_size; > +#define MAX_DMA_ADDRESS (PAGE_OFFSET + arm_dma_zone_size) ... > -#ifndef ARM_DMA_ZONE_SIZE > +#ifndef CONFIG_ZONE_DMA > #define ISA_DMA_THRESHOLD (0xffffffffULL) > #else > -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + ARM_DMA_ZONE_SIZE - 1) > +#define ISA_DMA_THRESHOLD ({ \ > + extern unsigned long arm_dma_zone_size; \ > + arm_dma_zone_size ? \ > + (PHYS_OFFSET + arm_dma_zone_size - 1) : 0xffffffffULL; }) These two usages do not agree. With unrestricted DMA, both MAX_DMA_ADDRESS and ISA_DMA_THRESHOLD should be 0xffffffff. However, you get that with arm_dma_zone_size=0 for ISA_DMA_THRESHOLD, which then gives a MAX_DMA_ADDRESS of PAGE_OFFSET. So this potentially changes the behaviour of these macros.
On Tue, Jul 05, 2011 at 11:12:16PM -0400, Nicolas Pitre wrote: > On Wed, 6 Jul 2011, Barry Song wrote: > > > 2011/7/6 Nicolas Pitre <nicolas.pitre@linaro.org>: > > > Having this value defined at compile time prevents multiple machines with > > > conflicting definitions to coexist. Move it to a variable in preparation > > > for having a per machine value selected at run time. This is relevant > > > only when CONFIG_ZONE_DMA is selected. > > > > > > Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> > > > > that is definitely good. i am not sure whether it will be better if > > dma zone becomes a property in memory node of DT. > > Certainly. But one thing at a time. This is the first step. Then, > those machines that are converted to DT could more easily provide the > information via this mechanism if they so desire. Actually, putting that information into DT is probably not right - you're describing something which is specific to Linux, not something which is due to hardware. What I mean is that the DMA zone is a Linux specific thing. Another OS could have a different way of dealing with the DMA restrictions (it may be possible to allocate memory within a certain set of bounds.) What is hardware specific is that the DMA devices can only address a limited range of memory. IMHO it's that which should be described in DT, not that we'll have a DMA zone of X bytes in size.
On Thu, 7 Jul 2011, Russell King - ARM Linux wrote: > On Tue, Jul 05, 2011 at 11:12:16PM -0400, Nicolas Pitre wrote: > > On Wed, 6 Jul 2011, Barry Song wrote: > > > > > 2011/7/6 Nicolas Pitre <nicolas.pitre@linaro.org>: > > > > Having this value defined at compile time prevents multiple machines with > > > > conflicting definitions to coexist. Move it to a variable in preparation > > > > for having a per machine value selected at run time. This is relevant > > > > only when CONFIG_ZONE_DMA is selected. > > > > > > > > Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> > > > > > > that is definitely good. i am not sure whether it will be better if > > > dma zone becomes a property in memory node of DT. > > > > Certainly. But one thing at a time. This is the first step. Then, > > those machines that are converted to DT could more easily provide the > > information via this mechanism if they so desire. > > Actually, putting that information into DT is probably not right - > you're describing something which is specific to Linux, not something > which is due to hardware. > > What I mean is that the DMA zone is a Linux specific thing. Another OS > could have a different way of dealing with the DMA restrictions (it > may be possible to allocate memory within a certain set of bounds.) > > What is hardware specific is that the DMA devices can only address a > limited range of memory. IMHO it's that which should be described in > DT, not that we'll have a DMA zone of X bytes in size. I think that we all agree on the principle. I certainly never intended to suggest that the DMA zone size be stored as is in the device tree. Nicolas
On Thursday 07 July 2011, Nicolas Pitre wrote: > > What is hardware specific is that the DMA devices can only address a > > limited range of memory. IMHO it's that which should be described in > > DT, not that we'll have a DMA zone of X bytes in size. > > I think that we all agree on the principle. I certainly never intended > to suggest that the DMA zone size be stored as is in the device tree. There is a way to specify DMA address ranges in the device tree, though I forgot the exact format. It comes down to saying the device sees memory range XXX to YYY as its local address AAA to BBB. We could use that information at boot time to determine what the largest range of memory is that is visible by all devices (and hope that it's at the start of physical memory). Arnd
On Thu, Jul 07, 2011 at 06:17:11PM +0200, Arnd Bergmann wrote: > On Thursday 07 July 2011, Nicolas Pitre wrote: > > > What is hardware specific is that the DMA devices can only address a > > > limited range of memory. IMHO it's that which should be described in > > > DT, not that we'll have a DMA zone of X bytes in size. > > > > I think that we all agree on the principle. I certainly never intended > > to suggest that the DMA zone size be stored as is in the device tree. > > There is a way to specify DMA address ranges in the device tree, though > I forgot the exact format. It comes down to saying the device sees > memory range XXX to YYY as its local address AAA to BBB. We could use > that information at boot time to determine what the largest range > of memory is that is visible by all devices (and hope that it's at > the start of physical memory). It's called dma-ranges, and it has the same syntax as the ranges property. See section 2.3.9 on page 30 in ePAPR: http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf This describes the hardware constraints, not the DMA zone size or any software decisions like that. g.
On Thu, Jul 07, 2011 at 11:08:38AM -0600, John Linn wrote: > If I'm following this right.... > > We have a hole at the start of physical memory (when it's at 0) so that > DMA can't DMA into it. Sounds like that won't work for us? That depends what you mean by that. If you're saying that your physical RAM starts at some non-zero address, then that isn't a problem. We have lots of ARM platforms where that is true. If you're saying that the first N MB of RAM can't be DMA'd to, then that is a problem as the kernel has no way to be told about that restriction. The best we can manage is to avoid freeing that memory into the normal allocation pools. We do have a very small number of platforms where that's true, but we 'work around' that by having the kernel occupy that space. If N MB is less than sizeof(kernel) + 32K then you haven't lost much.
> -----Original Message----- > From: Russell King - ARM Linux [mailto:linux@arm.linux.org.uk] > Sent: Friday, July 08, 2011 3:00 AM > To: John Linn > Cc: Arnd Bergmann; linux-arm-kernel@lists.infradead.org; Nicolas Pitre; > grant.likely@secretlab.ca; Barry Song > Subject: Re: [PATCH 01/10] ARM: change ARM_DMA_ZONE_SIZE into a > variable > > On Thu, Jul 07, 2011 at 11:08:38AM -0600, John Linn wrote: > > If I'm following this right.... > > > > We have a hole at the start of physical memory (when it's at 0) so > that > > DMA can't DMA into it. Sounds like that won't work for us? > > That depends what you mean by that. > > If you're saying that your physical RAM starts at some non-zero > address, > then that isn't a problem. We have lots of ARM platforms where that is > true. > > If you're saying that the first N MB of RAM can't be DMA'd to, then > that > is a problem as the kernel has no way to be told about that > restriction. > The best we can manage is to avoid freeing that memory into the normal > allocation pools. Yes that is what I'm saying. Catalin and I had some conversation about this previously (my apologies if I just didn't get it Catalin). > > We do have a very small number of platforms where that's true, but we > 'work around' that by having the kernel occupy that space. If N MB is > less than sizeof(kernel) + 32K then you haven't lost much. It's only at addresses 0 - 512K that's not DMA-able. I am using a DMA zone (with a hole at the front) to avoid this problem right now but maybe I'm not really understanding it and it's not working correctly. Testing looks good with the DMA zone. I didn't like the other solution since we had to add another exception where the kernel frees it's memory (not to free it). But maybe this is really the right solution as Catalin had tried to explain to me. Thanks for the input, John Please ignore any legal footer at the bottom of this email, this problem is still being worked. This email and any attachments are intended for the sole use of the named recipient(s) and contain(s) confidential information that may be proprietary, privileged or copyrighted under applicable law. If you are not the intended recipient, do not read, copy, or forward this email message or any attachments. Delete this email message and any attachments immediately.
On Fri, Jul 08, 2011 at 07:58:03AM -0600, John Linn wrote: > It's only at addresses 0 - 512K that's not DMA-able. I am using a DMA > zone (with a hole at the front) to avoid this problem right now but > maybe I'm not really understanding it and it's not working correctly. > Testing looks good with the DMA zone. That's more or less what we do with Integrator platforms. It's very unlikely that a kernel will ever be smaller than 512K, so if you place it at 32K as normal, avoid freeing the .init text/data, and keep the first 32K reserved (the second 16K will be reserved for the swapper page table in any case) then you'll keep that memory away from anything that might hand it out for DMA purposes. See free_initmem() for the integrator stuff avoiding .init freeing, and integrator_reserve() to keep the first 16K reserved.
diff --git a/arch/arm/include/asm/dma.h b/arch/arm/include/asm/dma.h index 4200554..1d34c11 100644 --- a/arch/arm/include/asm/dma.h +++ b/arch/arm/include/asm/dma.h @@ -6,10 +6,11 @@ /* * This is the maximum virtual address which can be DMA'd from. */ -#ifndef ARM_DMA_ZONE_SIZE -#define MAX_DMA_ADDRESS 0xffffffff +#ifndef CONFIG_ZONE_DMA +#define MAX_DMA_ADDRESS 0xffffffffUL #else -#define MAX_DMA_ADDRESS (PAGE_OFFSET + ARM_DMA_ZONE_SIZE) +extern unsigned long arm_dma_zone_size; +#define MAX_DMA_ADDRESS (PAGE_OFFSET + arm_dma_zone_size) #endif #ifdef CONFIG_ISA_DMA_API diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h index af44a8f..deb2eaa 100644 --- a/arch/arm/include/asm/memory.h +++ b/arch/arm/include/asm/memory.h @@ -209,10 +209,13 @@ static inline unsigned long __phys_to_virt(unsigned long x) * allocations. This must be the smallest DMA mask in the system, * so a successful GFP_DMA allocation will always satisfy this. */ -#ifndef ARM_DMA_ZONE_SIZE +#ifndef CONFIG_ZONE_DMA #define ISA_DMA_THRESHOLD (0xffffffffULL) #else -#define ISA_DMA_THRESHOLD (PHYS_OFFSET + ARM_DMA_ZONE_SIZE - 1) +#define ISA_DMA_THRESHOLD ({ \ + extern unsigned long arm_dma_zone_size; \ + arm_dma_zone_size ? \ + (PHYS_OFFSET + arm_dma_zone_size - 1) : 0xffffffffULL; }) #endif /* diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index c19571c..a14caff 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -34,6 +34,15 @@ #include "mm.h" +#ifdef CONFIG_ZONE_DMA +#ifdef ARM_DMA_ZONE_SIZE +unsigned long arm_dma_zone_size = ARM_DMA_ZONE_SIZE; +#else +unsigned long arm_dma_zone_size __read_mostly; +#endif +EXPORT_SYMBOL(arm_dma_zone_size); +#endif + static unsigned long phys_initrd_start __initdata = 0; static unsigned long phys_initrd_size __initdata = 0; @@ -267,17 +276,14 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low, #endif } -#ifdef ARM_DMA_ZONE_SIZE -#ifndef CONFIG_ZONE_DMA -#error ARM_DMA_ZONE_SIZE set but no DMA zone to limit allocations -#endif - +#ifdef CONFIG_ZONE_DMA /* * Adjust the sizes according to any special requirements for * this machine type. */ - arm_adjust_dma_zone(zone_size, zhole_size, - ARM_DMA_ZONE_SIZE >> PAGE_SHIFT); + if (arm_dma_zone_size) + arm_adjust_dma_zone(zone_size, zhole_size, + arm_dma_zone_size >> PAGE_SHIFT); #endif free_area_init_node(0, zone_size, min, zhole_size);
Having this value defined at compile time prevents multiple machines with conflicting definitions to coexist. Move it to a variable in preparation for having a per machine value selected at run time. This is relevant only when CONFIG_ZONE_DMA is selected. Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> --- arch/arm/include/asm/dma.h | 7 ++++--- arch/arm/include/asm/memory.h | 7 +++++-- arch/arm/mm/init.c | 20 +++++++++++++------- 3 files changed, 22 insertions(+), 12 deletions(-)