On Thu, 2019-09-05 at 18:19 +0100, Catalin Marinas wrote: > On Mon, Sep 02, 2019 at 04:10:41PM +0200, Nicolas Saenz Julienne wrote: > > diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c > > index 8956c22634dd..f02a4945aeac 100644 > > --- a/arch/arm64/mm/init.c > > +++ b/arch/arm64/mm/init.c > > @@ -50,6 +50,13 @@ > > s64 memstart_addr __ro_after_init = -1; > > EXPORT_SYMBOL(memstart_addr); > > > > +/* > > + * We create both ZONE_DMA and ZONE_DMA32. ZONE_DMA covers the first 1G of > > + * memory as some devices, namely the Raspberry Pi 4, have peripherals with > > + * this limited view of the memory. ZONE_DMA32 will cover the rest of the > > 32 > > + * bit addressable memory area. > > + */ > > +phys_addr_t arm64_dma_phys_limit __ro_after_init; > > phys_addr_t arm64_dma32_phys_limit __ro_after_init; > > > > #ifdef CONFIG_KEXEC_CORE > > @@ -164,9 +171,9 @@ static void __init reserve_elfcorehdr(void) > > } > > #endif /* CONFIG_CRASH_DUMP */ > > /* > > - * Return the maximum physical address for ZONE_DMA32 (DMA_BIT_MASK(32)). > > It > > - * currently assumes that for memory starting above 4G, 32-bit devices will > > - * use a DMA offset. > > + * Return the maximum physical address for ZONE_DMA32 (DMA_BIT_MASK(32)) > > and > > + * ZONE_DMA (DMA_BIT_MASK(30)) respectively. It currently assumes that for > > + * memory starting above 4G, 32-bit devices will use a DMA offset. > > */ > > static phys_addr_t __init max_zone_dma32_phys(void) > > { > > @@ -174,12 +181,23 @@ static phys_addr_t __init max_zone_dma32_phys(void) > > return min(offset + (1ULL << 32), memblock_end_of_DRAM()); > > } > > > > +static phys_addr_t __init max_zone_dma_phys(void) > > +{ > > + phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32); > > + > > + return min(offset + (1ULL << ARCH_ZONE_DMA_BITS), > > + memblock_end_of_DRAM()); > > +} > > I think we could squash these two functions into a single one with a > "bits" argument that is either 32 or ARCH_ZONE_DMA_BITS. Hi Catalin, thanks for the review. Agree, it'll look nicer. > > + > > #ifdef CONFIG_NUMA > > > > static void __init zone_sizes_init(unsigned long min, unsigned long max) > > { > > unsigned long max_zone_pfns[MAX_NR_ZONES] = {0}; > > > > +#ifdef CONFIG_ZONE_DMA > > + max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit); > > +#endif > > #ifdef CONFIG_ZONE_DMA32 > > max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma32_phys_limit); > > #endif > > @@ -195,13 +213,17 @@ static void __init zone_sizes_init(unsigned long min, > > unsigned long max) > > struct memblock_region *reg; > > unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES]; > > unsigned long max_dma32 = min; > > + unsigned long max_dma = min; > > > > memset(zone_size, 0, sizeof(zone_size)); > > > > - /* 4GB maximum for 32-bit only capable devices */ > > +#ifdef CONFIG_ZONE_DMA > > + max_dma = PFN_DOWN(arm64_dma_phys_limit); > > + zone_size[ZONE_DMA] = max_dma - min; > > +#endifmax_dma32 > > #ifdef CONFIG_ZONE_DMA32 > > max_dma32 = PFN_DOWN(arm64_dma32_phys_limit); > > - zone_size[ZONE_DMA32] = max_dma32 - min; > > + zone_size[ZONE_DMA32] = max_dma32 - max_dma; > > #endif > > zone_size[ZONE_NORMAL] = max - max_dma32; > > Does this still work if we have ZONE_DMA32 disabled but ZONE_DMA > enabled? You could use a max(max_dma32, max_dma) or just update > max_dma32 to max_dma in the CONFIG_ZONE_DMA block. You're right, I missed that scenario. I'll fix it and give it a test for the next series. Regards, Nicolas