* [PATCH v3 1/4] arm64: mm: use arm64_dma_phys_limit instead of calling max_zone_dma_phys()
2019-09-02 14:10 [PATCH v3 0/4] Raspberry Pi 4 DMA addressing support Nicolas Saenz Julienne
@ 2019-09-02 14:10 ` Nicolas Saenz Julienne
2019-09-05 17:05 ` Catalin Marinas
2019-09-02 14:10 ` [PATCH v3 2/4] arm64: rename variables used to calculate ZONE_DMA32's size Nicolas Saenz Julienne
` (2 subsequent siblings)
3 siblings, 1 reply; 10+ messages in thread
From: Nicolas Saenz Julienne @ 2019-09-02 14:10 UTC (permalink / raw)
To: catalin.marinas, hch, wahrenst, marc.zyngier, robh+dt,
linux-arm-kernel, linux-mm, linux-riscv, linux-kernel
Cc: f.fainelli, will, robin.murphy, nsaenzjulienne, mbrugger,
linux-rpi-kernel, phill, m.szyprowski
By the time we call zones_sizes_init() arm64_dma_phys_limit already
contains the result of max_zone_dma_phys(). We use the variable instead
of calling the function directly to save some precious cpu time.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
---
Changes in v3: None
Changes in v2: None
arch/arm64/mm/init.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index f3c795278def..6112d6c90fa8 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -181,7 +181,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
unsigned long max_zone_pfns[MAX_NR_ZONES] = {0};
#ifdef CONFIG_ZONE_DMA32
- max_zone_pfns[ZONE_DMA32] = PFN_DOWN(max_zone_dma_phys());
+ max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma_phys_limit);
#endif
max_zone_pfns[ZONE_NORMAL] = max;
--
2.23.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 1/4] arm64: mm: use arm64_dma_phys_limit instead of calling max_zone_dma_phys()
2019-09-02 14:10 ` [PATCH v3 1/4] arm64: mm: use arm64_dma_phys_limit instead of calling max_zone_dma_phys() Nicolas Saenz Julienne
@ 2019-09-05 17:05 ` Catalin Marinas
0 siblings, 0 replies; 10+ messages in thread
From: Catalin Marinas @ 2019-09-05 17:05 UTC (permalink / raw)
To: Nicolas Saenz Julienne
Cc: hch, wahrenst, marc.zyngier, robh+dt, linux-arm-kernel, linux-mm,
linux-riscv, linux-kernel, f.fainelli, will, robin.murphy,
mbrugger, linux-rpi-kernel, phill, m.szyprowski
On Mon, Sep 02, 2019 at 04:10:39PM +0200, Nicolas Saenz Julienne wrote:
> By the time we call zones_sizes_init() arm64_dma_phys_limit already
> contains the result of max_zone_dma_phys(). We use the variable instead
> of calling the function directly to save some precious cpu time.
>
> Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 2/4] arm64: rename variables used to calculate ZONE_DMA32's size
2019-09-02 14:10 [PATCH v3 0/4] Raspberry Pi 4 DMA addressing support Nicolas Saenz Julienne
2019-09-02 14:10 ` [PATCH v3 1/4] arm64: mm: use arm64_dma_phys_limit instead of calling max_zone_dma_phys() Nicolas Saenz Julienne
@ 2019-09-02 14:10 ` Nicolas Saenz Julienne
2019-09-05 17:05 ` Catalin Marinas
2019-09-02 14:10 ` [PATCH v3 3/4] arm64: use both ZONE_DMA and ZONE_DMA32 Nicolas Saenz Julienne
2019-09-02 14:10 ` [PATCH v3 4/4] mm: refresh ZONE_DMA and ZONE_DMA32 comments in 'enum zone_type' Nicolas Saenz Julienne
3 siblings, 1 reply; 10+ messages in thread
From: Nicolas Saenz Julienne @ 2019-09-02 14:10 UTC (permalink / raw)
To: catalin.marinas, hch, wahrenst, marc.zyngier, robh+dt,
linux-arm-kernel, linux-mm, linux-riscv, linux-kernel
Cc: f.fainelli, will, robin.murphy, nsaenzjulienne, mbrugger,
linux-rpi-kernel, phill, m.szyprowski
Let the name indicate that they are used to calculate ZONE_DMA32's size
as opposed to ZONE_DMA.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
---
Changes in v3: None
Changes in v2: None
arch/arm64/mm/init.c | 30 +++++++++++++++---------------
1 file changed, 15 insertions(+), 15 deletions(-)
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index 6112d6c90fa8..8956c22634dd 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -50,7 +50,7 @@
s64 memstart_addr __ro_after_init = -1;
EXPORT_SYMBOL(memstart_addr);
-phys_addr_t arm64_dma_phys_limit __ro_after_init;
+phys_addr_t arm64_dma32_phys_limit __ro_after_init;
#ifdef CONFIG_KEXEC_CORE
/*
@@ -168,7 +168,7 @@ static void __init reserve_elfcorehdr(void)
* currently assumes that for memory starting above 4G, 32-bit devices will
* use a DMA offset.
*/
-static phys_addr_t __init max_zone_dma_phys(void)
+static phys_addr_t __init max_zone_dma32_phys(void)
{
phys_addr_t offset = memblock_start_of_DRAM() & GENMASK_ULL(63, 32);
return min(offset + (1ULL << 32), memblock_end_of_DRAM());
@@ -181,7 +181,7 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
unsigned long max_zone_pfns[MAX_NR_ZONES] = {0};
#ifdef CONFIG_ZONE_DMA32
- max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma_phys_limit);
+ max_zone_pfns[ZONE_DMA32] = PFN_DOWN(arm64_dma32_phys_limit);
#endif
max_zone_pfns[ZONE_NORMAL] = max;
@@ -194,16 +194,16 @@ 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_dma = min;
+ unsigned long max_dma32 = min;
memset(zone_size, 0, sizeof(zone_size));
/* 4GB maximum for 32-bit only capable devices */
#ifdef CONFIG_ZONE_DMA32
- max_dma = PFN_DOWN(arm64_dma_phys_limit);
- zone_size[ZONE_DMA32] = max_dma - min;
+ max_dma32 = PFN_DOWN(arm64_dma32_phys_limit);
+ zone_size[ZONE_DMA32] = max_dma32 - min;
#endif
- zone_size[ZONE_NORMAL] = max - max_dma;
+ zone_size[ZONE_NORMAL] = max - max_dma32;
memcpy(zhole_size, zone_size, sizeof(zhole_size));
@@ -215,14 +215,14 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
continue;
#ifdef CONFIG_ZONE_DMA32
- if (start < max_dma) {
- unsigned long dma_end = min(end, max_dma);
+ if (start < max_dma32) {
+ unsigned long dma_end = min(end, max_dma32);
zhole_size[ZONE_DMA32] -= dma_end - start;
}
#endif
- if (end > max_dma) {
+ if (end > max_dma32) {
unsigned long normal_end = min(end, max);
- unsigned long normal_start = max(start, max_dma);
+ unsigned long normal_start = max(start, max_dma32);
zhole_size[ZONE_NORMAL] -= normal_end - normal_start;
}
}
@@ -407,9 +407,9 @@ void __init arm64_memblock_init(void)
/* 4GB maximum for 32-bit only capable devices */
if (IS_ENABLED(CONFIG_ZONE_DMA32))
- arm64_dma_phys_limit = max_zone_dma_phys();
+ arm64_dma32_phys_limit = max_zone_dma32_phys();
else
- arm64_dma_phys_limit = PHYS_MASK + 1;
+ arm64_dma32_phys_limit = PHYS_MASK + 1;
reserve_crashkernel();
@@ -417,7 +417,7 @@ void __init arm64_memblock_init(void)
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
- dma_contiguous_reserve(arm64_dma_phys_limit);
+ dma_contiguous_reserve(arm64_dma32_phys_limit);
}
void __init bootmem_init(void)
@@ -521,7 +521,7 @@ static void __init free_unused_memmap(void)
void __init mem_init(void)
{
if (swiotlb_force == SWIOTLB_FORCE ||
- max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT))
+ max_pfn > (arm64_dma32_phys_limit >> PAGE_SHIFT))
swiotlb_init(1);
else
swiotlb_force = SWIOTLB_NO_FORCE;
--
2.23.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 2/4] arm64: rename variables used to calculate ZONE_DMA32's size
2019-09-02 14:10 ` [PATCH v3 2/4] arm64: rename variables used to calculate ZONE_DMA32's size Nicolas Saenz Julienne
@ 2019-09-05 17:05 ` Catalin Marinas
0 siblings, 0 replies; 10+ messages in thread
From: Catalin Marinas @ 2019-09-05 17:05 UTC (permalink / raw)
To: Nicolas Saenz Julienne
Cc: hch, wahrenst, marc.zyngier, robh+dt, linux-arm-kernel, linux-mm,
linux-riscv, linux-kernel, f.fainelli, will, robin.murphy,
mbrugger, linux-rpi-kernel, phill, m.szyprowski
On Mon, Sep 02, 2019 at 04:10:40PM +0200, Nicolas Saenz Julienne wrote:
> Let the name indicate that they are used to calculate ZONE_DMA32's size
> as opposed to ZONE_DMA.
>
> Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 3/4] arm64: use both ZONE_DMA and ZONE_DMA32
2019-09-02 14:10 [PATCH v3 0/4] Raspberry Pi 4 DMA addressing support Nicolas Saenz Julienne
2019-09-02 14:10 ` [PATCH v3 1/4] arm64: mm: use arm64_dma_phys_limit instead of calling max_zone_dma_phys() Nicolas Saenz Julienne
2019-09-02 14:10 ` [PATCH v3 2/4] arm64: rename variables used to calculate ZONE_DMA32's size Nicolas Saenz Julienne
@ 2019-09-02 14:10 ` Nicolas Saenz Julienne
2019-09-05 17:19 ` Catalin Marinas
2019-09-02 14:10 ` [PATCH v3 4/4] mm: refresh ZONE_DMA and ZONE_DMA32 comments in 'enum zone_type' Nicolas Saenz Julienne
3 siblings, 1 reply; 10+ messages in thread
From: Nicolas Saenz Julienne @ 2019-09-02 14:10 UTC (permalink / raw)
To: catalin.marinas, hch, wahrenst, marc.zyngier, robh+dt,
linux-arm-kernel, linux-mm, linux-riscv, Will Deacon
Cc: f.fainelli, robin.murphy, nsaenzjulienne, linux-kernel, mbrugger,
linux-rpi-kernel, phill, m.szyprowski
So far all arm64 devices have supported 32 bit DMA masks for their
peripherals. This is not true anymore for the Raspberry Pi 4 as most of
it's peripherals can only address the first GB of memory on a total of
up to 4 GB.
This goes against ZONE_DMA32's intent, as it's expected for ZONE_DMA32
to be addressable with a 32 bit mask. So it was decided to re-introduce
ZONE_DMA in arm64.
ZONE_DMA will contain the lower 1G of memory, which is currently the
memory area addressable by any peripheral on an arm64 device.
ZONE_DMA32 will contain the rest of the 32 bit addressable memory.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
---
Changes in v3:
- Used fixed size ZONE_DMA
- Fix check befor swiotlb_init()
Changes in v2:
- Update comment to reflect new zones split
- ZONE_DMA will never be left empty
arch/arm64/Kconfig | 4 +++
arch/arm64/include/asm/page.h | 2 ++
arch/arm64/mm/init.c | 51 ++++++++++++++++++++++++++++-------
3 files changed, 47 insertions(+), 10 deletions(-)
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3adcec05b1f6..a9fd71d3bc8e 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -266,6 +266,10 @@ config GENERIC_CSUM
config GENERIC_CALIBRATE_DELAY
def_bool y
+config ZONE_DMA
+ bool "Support DMA zone" if EXPERT
+ default y
+
config ZONE_DMA32
bool "Support DMA32 zone" if EXPERT
default y
diff --git a/arch/arm64/include/asm/page.h b/arch/arm64/include/asm/page.h
index d39ddb258a04..7b8c98830101 100644
--- a/arch/arm64/include/asm/page.h
+++ b/arch/arm64/include/asm/page.h
@@ -38,4 +38,6 @@ extern int pfn_valid(unsigned long);
#include <asm-generic/getorder.h>
+#define ARCH_ZONE_DMA_BITS 30
+
#endif
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());
+}
+
#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;
+#endif
#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;
@@ -213,11 +235,17 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
if (start >= max)
continue;
-
+#ifdef CONFIG_ZONE_DMA
+ if (start < max_dma) {
+ unsigned long dma_end = min_not_zero(end, max_dma);
+ zhole_size[ZONE_DMA] -= dma_end - start;
+ }
+#endif
#ifdef CONFIG_ZONE_DMA32
if (start < max_dma32) {
- unsigned long dma_end = min(end, max_dma32);
- zhole_size[ZONE_DMA32] -= dma_end - start;
+ unsigned long dma32_end = min(end, max_dma32);
+ unsigned long dma32_start = max(start, max_dma);
+ zhole_size[ZONE_DMA32] -= dma32_end - dma32_start;
}
#endif
if (end > max_dma32) {
@@ -405,7 +433,9 @@ void __init arm64_memblock_init(void)
early_init_fdt_scan_reserved_mem();
- /* 4GB maximum for 32-bit only capable devices */
+ if (IS_ENABLED(CONFIG_ZONE_DMA))
+ arm64_dma_phys_limit = max_zone_dma_phys();
+
if (IS_ENABLED(CONFIG_ZONE_DMA32))
arm64_dma32_phys_limit = max_zone_dma32_phys();
else
@@ -417,7 +447,7 @@ void __init arm64_memblock_init(void)
high_memory = __va(memblock_end_of_DRAM() - 1) + 1;
- dma_contiguous_reserve(arm64_dma32_phys_limit);
+ dma_contiguous_reserve(arm64_dma_phys_limit ? : arm64_dma32_phys_limit);
}
void __init bootmem_init(void)
@@ -521,6 +551,7 @@ static void __init free_unused_memmap(void)
void __init mem_init(void)
{
if (swiotlb_force == SWIOTLB_FORCE ||
+ max_pfn > (arm64_dma_phys_limit >> PAGE_SHIFT) ||
max_pfn > (arm64_dma32_phys_limit >> PAGE_SHIFT))
swiotlb_init(1);
else
--
2.23.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/4] arm64: use both ZONE_DMA and ZONE_DMA32
2019-09-02 14:10 ` [PATCH v3 3/4] arm64: use both ZONE_DMA and ZONE_DMA32 Nicolas Saenz Julienne
@ 2019-09-05 17:19 ` Catalin Marinas
2019-09-05 17:28 ` Nicolas Saenz Julienne
0 siblings, 1 reply; 10+ messages in thread
From: Catalin Marinas @ 2019-09-05 17:19 UTC (permalink / raw)
To: Nicolas Saenz Julienne
Cc: hch, wahrenst, marc.zyngier, robh+dt, linux-arm-kernel, linux-mm,
linux-riscv, Will Deacon, f.fainelli, robin.murphy, linux-kernel,
mbrugger, linux-rpi-kernel, phill, m.szyprowski
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.
> +
> #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;
> +#endif
> #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.
> @@ -213,11 +235,17 @@ static void __init zone_sizes_init(unsigned long min, unsigned long max)
>
> if (start >= max)
> continue;
> -
> +#ifdef CONFIG_ZONE_DMA
> + if (start < max_dma) {
> + unsigned long dma_end = min_not_zero(end, max_dma);
> + zhole_size[ZONE_DMA] -= dma_end - start;
> + }
> +#endif
> #ifdef CONFIG_ZONE_DMA32
> if (start < max_dma32) {
> - unsigned long dma_end = min(end, max_dma32);
> - zhole_size[ZONE_DMA32] -= dma_end - start;
> + unsigned long dma32_end = min(end, max_dma32);
> + unsigned long dma32_start = max(start, max_dma);
> + zhole_size[ZONE_DMA32] -= dma32_end - dma32_start;
> }
> #endif
> if (end > max_dma32) {
Similar comment here.
--
Catalin
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH v3 3/4] arm64: use both ZONE_DMA and ZONE_DMA32
2019-09-05 17:19 ` Catalin Marinas
@ 2019-09-05 17:28 ` Nicolas Saenz Julienne
0 siblings, 0 replies; 10+ messages in thread
From: Nicolas Saenz Julienne @ 2019-09-05 17:28 UTC (permalink / raw)
To: Catalin Marinas
Cc: f.fainelli, mbrugger, marc.zyngier, robin.murphy, linux-kernel,
linux-mm, robh+dt, wahrenst, m.szyprowski, linux-riscv, phill,
Will Deacon, hch, linux-arm-kernel, linux-rpi-kernel
[-- Attachment #1: Type: text/plain, Size: 3644 bytes --]
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
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH v3 4/4] mm: refresh ZONE_DMA and ZONE_DMA32 comments in 'enum zone_type'
2019-09-02 14:10 [PATCH v3 0/4] Raspberry Pi 4 DMA addressing support Nicolas Saenz Julienne
` (2 preceding siblings ...)
2019-09-02 14:10 ` [PATCH v3 3/4] arm64: use both ZONE_DMA and ZONE_DMA32 Nicolas Saenz Julienne
@ 2019-09-02 14:10 ` Nicolas Saenz Julienne
2019-09-05 17:21 ` Catalin Marinas
3 siblings, 1 reply; 10+ messages in thread
From: Nicolas Saenz Julienne @ 2019-09-02 14:10 UTC (permalink / raw)
To: catalin.marinas, hch, wahrenst, marc.zyngier, robh+dt,
linux-arm-kernel, linux-mm, linux-riscv, Paul Walmsley,
Palmer Dabbelt, Albert Ou
Cc: f.fainelli, will, robin.murphy, nsaenzjulienne, linux-kernel,
mbrugger, linux-rpi-kernel, phill, m.szyprowski
These zones usage has evolved with time and the comments were outdated.
This joins both ZONE_DMA and ZONE_DMA32 explanation and gives up to date
examples on how they are used on different architectures.
Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
Reviewed-by: Christoph Hellwig <hch@lst.de>
---
Changes in v3:
- Update comment to match changes in arm64
Changes in v2:
- Try another approach merging both ZONE_DMA comments into one
- Address Christoph's comments
- If this approach doesn't get much traction I'll just drop the patch
from the series as it's not really essential
include/linux/mmzone.h | 45 ++++++++++++++++++++++++------------------
1 file changed, 26 insertions(+), 19 deletions(-)
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
index 3f38c30d2f13..bf1b916c9ecb 100644
--- a/include/linux/mmzone.h
+++ b/include/linux/mmzone.h
@@ -357,33 +357,40 @@ struct per_cpu_nodestat {
#endif /* !__GENERATING_BOUNDS.H */
enum zone_type {
-#ifdef CONFIG_ZONE_DMA
/*
- * ZONE_DMA is used when there are devices that are not able
- * to do DMA to all of addressable memory (ZONE_NORMAL). Then we
- * carve out the portion of memory that is needed for these devices.
- * The range is arch specific.
+ * ZONE_DMA and ZONE_DMA32 are used when there are peripherals not able
+ * to DMA to all of the addressable memory (ZONE_NORMAL).
+ * On architectures where this area covers the whole 32 bit address
+ * space ZONE_DMA32 is used. ZONE_DMA is left for the ones with smaller
+ * DMA addressing constraints. This distinction is important as a 32bit
+ * DMA mask is assumed when ZONE_DMA32 is defined. Some 64-bit
+ * platforms may need both zones as they support peripherals with
+ * different DMA addressing limitations.
+ *
+ * Some examples:
+ *
+ * - i386 and x86_64 have a fixed 16M ZONE_DMA and ZONE_DMA32 for the
+ * rest of the lower 4G.
+ *
+ * - arm only uses ZONE_DMA, the size, up to 4G, may vary depending on
+ * the specific device.
+ *
+ * - arm64 has a fixed 1G ZONE_DMA and ZONE_DMA32 for the rest of the
+ * lower 4G.
*
- * Some examples
+ * - powerpc only uses ZONE_DMA, the size, up to 2G, may vary
+ * depending on the specific device.
*
- * Architecture Limit
- * ---------------------------
- * parisc, ia64, sparc <4G
- * s390, powerpc <2G
- * arm Various
- * alpha Unlimited or 0-16MB.
+ * - s390 uses ZONE_DMA fixed to the lower 2G.
*
- * i386, x86_64 and multiple other arches
- * <16M.
+ * - ia64 and riscv only use ZONE_DMA32.
+ *
+ * - parisc uses neither.
*/
+#ifdef CONFIG_ZONE_DMA
ZONE_DMA,
#endif
#ifdef CONFIG_ZONE_DMA32
- /*
- * x86_64 needs two ZONE_DMAs because it supports devices that are
- * only able to do DMA to the lower 16M but also 32 bit devices that
- * can only do DMA areas below 4G.
- */
ZONE_DMA32,
#endif
/*
--
2.23.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH v3 4/4] mm: refresh ZONE_DMA and ZONE_DMA32 comments in 'enum zone_type'
2019-09-02 14:10 ` [PATCH v3 4/4] mm: refresh ZONE_DMA and ZONE_DMA32 comments in 'enum zone_type' Nicolas Saenz Julienne
@ 2019-09-05 17:21 ` Catalin Marinas
0 siblings, 0 replies; 10+ messages in thread
From: Catalin Marinas @ 2019-09-05 17:21 UTC (permalink / raw)
To: Nicolas Saenz Julienne
Cc: hch, wahrenst, marc.zyngier, robh+dt, linux-arm-kernel, linux-mm,
linux-riscv, Paul Walmsley, Palmer Dabbelt, Albert Ou,
f.fainelli, will, robin.murphy, linux-kernel, mbrugger,
linux-rpi-kernel, phill, m.szyprowski
On Mon, Sep 02, 2019 at 04:10:42PM +0200, Nicolas Saenz Julienne wrote:
> These zones usage has evolved with time and the comments were outdated.
> This joins both ZONE_DMA and ZONE_DMA32 explanation and gives up to date
> examples on how they are used on different architectures.
>
> Signed-off-by: Nicolas Saenz Julienne <nsaenzjulienne@suse.de>
> Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
^ permalink raw reply [flat|nested] 10+ messages in thread