[PATCH] m68k: mvme16x: lower min_low_pfn to make RAM DMA-able
From: Denis Ahrens
Date: Mon Oct 26 2026 - 05:54:33 EST
paging_init() sets min_low_pfn to availmem, i.e. the first free page
after the kernel image, so that nothing allocates DMA buffers into the
image. But free_initmem() later returns the freed .init pages of that
same area to the page allocator without touching min_low_pfn, and
dma_capable() in dma-direct keeps refusing to map any RAM below it.
With the ~8 MiB kernel image the MVME177 needs, kmalloc() hands out
buffers well below min_low_pfn, so the on-board NCR53c710 SCSI adapter
fails to map its command blocks and the SCSI disk stops working.
All bus master devices on the MVME16x boards address RAM with plain
physical addresses, so lower min_low_pfn to the bottom of the first
memory block from board-specific code, and leave mm/ and dma-direct
alone. This mirrors what arch/m68k/virt/platform.c already does for its
goldfish/virtio devices. The min_low_pfn check only applies when
dma_addr_t is 32 bits, which is the case on m68k.
The mvme16x SCSI and i82596 Ethernet drivers are platform devices
registered by their own module_init(), i.e. after this arch_initcall, so
min_low_pfn is already lowered before the first DMA mapping happens.
Fixes: b12d66278dd6 ("dma-direct: check for overflows on 32 bit DMA addresses")
Tested-by: Denis Ahrens <denis@xxxxxxx> # MVME177, 53c710 rev 2, ZuluSCSI
Signed-off-by: Denis Ahrens <denis@xxxxxxx>
---
arch/m68k/mvme16x/config.c | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index 99768fe8da73..56e29e43c5bb 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -23,6 +23,7 @@
#include <linux/major.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/memblock.h>
#include <linux/platform_device.h>
#include <linux/rtc/m48t59.h>
@@ -328,6 +329,29 @@ static int __init mvme16x_platform_init(void)
arch_initcall(mvme16x_platform_init);
+/*
+ * paging_init() sets min_low_pfn to the first free page after the kernel
+ * image, but free_initmem() later returns the .init section of that same
+ * image to the page allocator. All bus master devices on the MVME16x
+ * boards address RAM with plain physical addresses, so mark all of RAM
+ * DMA-able by lowering min_low_pfn to the bottom of the first memory
+ * block. This mirrors what arch/m68k/virt/platform.c does.
+ */
+static int __init mvme16x_init_dma_pfn_limit(void)
+{
+ unsigned long pfn = m68k_memory[0].addr >> PAGE_SHIFT;
+
+ if (pfn >= min_low_pfn)
+ return 0;
+
+ pr_info("MVME16x: lowering min_low_pfn 0x%lx -> 0x%lx\n",
+ min_low_pfn, pfn);
+ min_low_pfn = pfn;
+
+ return 0;
+}
+arch_initcall(mvme16x_init_dma_pfn_limit);
+
static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
{
unsigned long *new = (unsigned long *)vectors;
base-commit: c03c1a14507dfaf8b856c2608f9ac216021fc222
--
2.43.0