Hi all,
This series fixes some long-term issues in kernel that preventing
some machine from work properly.
Hopefully that will rescue some system in wild :-)
Thanks
Signed-off-by: Jiaxun Yang <[email protected]>
---
Jiaxun Yang (3):
MIPS: Loongson64: Reserve vgabios memory on boot
MIPS: Loongson64: Enable DMA noncoherent support
MIPS: Loongson64: Handle more memory types passed from firmware
arch/mips/Kconfig | 2 +
arch/mips/include/asm/mach-loongson64/boot_param.h | 9 ++++-
arch/mips/loongson64/env.c | 9 ++++-
arch/mips/loongson64/init.c | 47 ++++++++++++++--------
4 files changed, 48 insertions(+), 19 deletions(-)
---
base-commit: 9c2d379d63450ae464eeab45462e0cb573cd97d0
change-id: 20231101-loongson64_fixes-0afb1b503d1e
Best regards,
--
Jiaxun Yang <[email protected]>
vgabios is passed from firmware to kernel on Loongson64 systems.
Sane firmware will keep this pointer in reserved memory space
passed from the firmware but insane firmware keeps it in low
memory before kernel entry that is not reserved.
Previously kernel won't try to allocate memory from low memory
before kernel entry on boot, but after converting to memblock
it will do that.
Fix by resversing those memory on early boot.
Cc: [email protected]
Fixes: a94e4f24ec83 ("MIPS: init: Drop boot_mem_map")
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/loongson64/init.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
index ee8de1735b7c..d62262f93069 100644
--- a/arch/mips/loongson64/init.c
+++ b/arch/mips/loongson64/init.c
@@ -88,6 +88,11 @@ void __init szmem(unsigned int node)
break;
}
}
+
+ /* Reserve vgabios if it comes from firmware */
+ if (loongson_sysconf.vgabios_addr)
+ memblock_reserve(virt_to_phys((void *)loongson_sysconf.vgabios_addr),
+ SZ_256K);
}
#ifndef CONFIG_NUMA
--
2.34.1
There are some Loongson64 systems come with broken coherent DMA
support, firmware will set a bit in boot_param and pass nocoherentio
in cmdline.
However nonconherent support was missed out when spin off Loongson-2EF
form Loongson64, and that boot_param change never made itself into
upstream.
Support DMA noncoherent properly to get those systems work.
Cc: [email protected]
Fixes: 71e2f4dd5a65 ("MIPS: Fork loongson2ef from loongson64")
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/Kconfig | 2 ++
arch/mips/include/asm/mach-loongson64/boot_param.h | 3 ++-
arch/mips/loongson64/env.c | 9 ++++++++-
3 files changed, 12 insertions(+), 2 deletions(-)
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig
index 76db82542519..797ae590ebdb 100644
--- a/arch/mips/Kconfig
+++ b/arch/mips/Kconfig
@@ -460,6 +460,7 @@ config MACH_LOONGSON2EF
config MACH_LOONGSON64
bool "Loongson 64-bit family of machines"
+ select ARCH_DMA_DEFAULT_COHERENT
select ARCH_SPARSEMEM_ENABLE
select ARCH_MIGHT_HAVE_PC_PARPORT
select ARCH_MIGHT_HAVE_PC_SERIO
@@ -1251,6 +1252,7 @@ config CPU_LOONGSON64
select CPU_SUPPORTS_MSA
select CPU_DIEI_BROKEN if !LOONGSON3_ENHANCEMENT
select CPU_MIPSR2_IRQ_VI
+ select DMA_NONCOHERENT
select WEAK_ORDERING
select WEAK_REORDERING_BEYOND_LLSC
select MIPS_ASID_BITS_VARIABLE
diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
index 035b1a69e2d0..c454ef734c45 100644
--- a/arch/mips/include/asm/mach-loongson64/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -117,7 +117,8 @@ struct irq_source_routing_table {
u64 pci_io_start_addr;
u64 pci_io_end_addr;
u64 pci_config_addr;
- u32 dma_mask_bits;
+ u16 dma_mask_bits;
+ u16 dma_noncoherent;
} __packed;
struct interface_info {
diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
index c961e2999f15..df0e92cd3920 100644
--- a/arch/mips/loongson64/env.c
+++ b/arch/mips/loongson64/env.c
@@ -13,6 +13,8 @@
* Copyright (C) 2009 Lemote Inc.
* Author: Wu Zhangjin, [email protected]
*/
+
+#include <linux/dma-map-ops.h>
#include <linux/export.h>
#include <linux/pci_ids.h>
#include <asm/bootinfo.h>
@@ -147,8 +149,13 @@ void __init prom_lefi_init_env(void)
loongson_sysconf.dma_mask_bits = eirq_source->dma_mask_bits;
if (loongson_sysconf.dma_mask_bits < 32 ||
- loongson_sysconf.dma_mask_bits > 64)
+ loongson_sysconf.dma_mask_bits > 64) {
loongson_sysconf.dma_mask_bits = 32;
+ dma_default_coherent = true;
+ } else
+ dma_default_coherent = !eirq_source->dma_noncoherent;
+
+ pr_info("DMA coherent: %s\n", dma_default_coherent ? "on" : "off");
loongson_sysconf.restart_addr = boot_p->reset_system.ResetWarm;
loongson_sysconf.poweroff_addr = boot_p->reset_system.Shutdown;
--
2.34.1
There are many types of revsered memory passed from firmware
that should be reserved in memblock, and UMA memory passed
from firmware that should be added to system memory for system
to use.
Also for memblock there is no need to align those space into page,
which actually cause problems.
Handle them properly to prevent memory corruption on some systems.
Cc: [email protected]
Signed-off-by: Jiaxun Yang <[email protected]>
---
arch/mips/include/asm/mach-loongson64/boot_param.h | 6 +++-
arch/mips/loongson64/init.c | 42 +++++++++++++---------
2 files changed, 31 insertions(+), 17 deletions(-)
diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
index c454ef734c45..e007edd6b60a 100644
--- a/arch/mips/include/asm/mach-loongson64/boot_param.h
+++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
@@ -14,7 +14,11 @@
#define ADAPTER_ROM 8
#define ACPI_TABLE 9
#define SMBIOS_TABLE 10
-#define MAX_MEMORY_TYPE 11
+#define UMA_VIDEO_RAM 11
+#define VUMA_VIDEO_RAM 12
+#define MAX_MEMORY_TYPE 13
+
+#define MEM_SIZE_IS_IN_BYTES (1 << 31)
#define LOONGSON3_BOOT_MEM_MAP_MAX 128
struct efi_memory_map_loongson {
diff --git a/arch/mips/loongson64/init.c b/arch/mips/loongson64/init.c
index d62262f93069..f25caa6aa9d3 100644
--- a/arch/mips/loongson64/init.c
+++ b/arch/mips/loongson64/init.c
@@ -49,8 +49,7 @@ void virtual_early_config(void)
void __init szmem(unsigned int node)
{
u32 i, mem_type;
- static unsigned long num_physpages;
- u64 node_id, node_psize, start_pfn, end_pfn, mem_start, mem_size;
+ phys_addr_t node_id, mem_start, mem_size;
/* Otherwise come from DTB */
if (loongson_sysconf.fw_interface != LOONGSON_LEFI)
@@ -64,27 +63,38 @@ void __init szmem(unsigned int node)
mem_type = loongson_memmap->map[i].mem_type;
mem_size = loongson_memmap->map[i].mem_size;
- mem_start = loongson_memmap->map[i].mem_start;
+
+ /* Memory size comes in MB if MEM_SIZE_IS_IN_BYTES not set */
+ if (mem_size & MEM_SIZE_IS_IN_BYTES)
+ mem_size &= ~MEM_SIZE_IS_IN_BYTES;
+ else
+ mem_size = mem_size << 20;
+
+ mem_start = (node_id << 44) | loongson_memmap->map[i].mem_start;
switch (mem_type) {
case SYSTEM_RAM_LOW:
case SYSTEM_RAM_HIGH:
- start_pfn = ((node_id << 44) + mem_start) >> PAGE_SHIFT;
- node_psize = (mem_size << 20) >> PAGE_SHIFT;
- end_pfn = start_pfn + node_psize;
- num_physpages += node_psize;
- pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
- (u32)node_id, mem_type, mem_start, mem_size);
- pr_info(" start_pfn:0x%llx, end_pfn:0x%llx, num_physpages:0x%lx\n",
- start_pfn, end_pfn, num_physpages);
- memblock_add_node(PFN_PHYS(start_pfn),
- PFN_PHYS(node_psize), node,
+ case UMA_VIDEO_RAM:
+ pr_info("Node %d, mem_type:%d\t[%pa], %pa bytes usable\n",
+ (u32)node_id, mem_type, &mem_start, &mem_size);
+ memblock_add_node(mem_start, mem_size, node,
MEMBLOCK_NONE);
break;
case SYSTEM_RAM_RESERVED:
- pr_info("Node%d: mem_type:%d, mem_start:0x%llx, mem_size:0x%llx MB\n",
- (u32)node_id, mem_type, mem_start, mem_size);
- memblock_reserve(((node_id << 44) + mem_start), mem_size << 20);
+ case VIDEO_ROM:
+ case ADAPTER_ROM:
+ case ACPI_TABLE:
+ case SMBIOS_TABLE:
+ pr_info("Node %d, mem_type:%d\t[%pa], %pa bytes reserved\n",
+ (u32)node_id, mem_type, &mem_start, &mem_size);
+ memblock_reserve(mem_start, mem_size);
+ break;
+ /* We should not reserve VUMA_VIDEO_RAM as it overlaps with MMIO */
+ case VUMA_VIDEO_RAM:
+ default:
+ pr_info("Node %d, mem_type:%d\t[%pa], %pa bytes unhandled\n",
+ (u32)node_id, mem_type, &mem_start, &mem_size);
break;
}
}
--
2.34.1
On 11/1/23 2:39 PM, Jiaxun Yang wrote:
> vgabios is passed from firmware to kernel on Loongson64 systems.
> Sane firmware will keep this pointer in reserved memory space
> passed from the firmware but insane firmware keeps it in low
> memory before kernel entry that is not reserved.
>
> Previously kernel won't try to allocate memory from low memory
> before kernel entry on boot, but after converting to memblock
> it will do that.
>
> Fix by resversing those memory on early boot.
Reserving? :-)
> Cc: [email protected]
> Fixes: a94e4f24ec83 ("MIPS: init: Drop boot_mem_map")
> Signed-off-by: Jiaxun Yang <[email protected]>
[...]
MBR, Sergey
On 11/1/23 2:39 PM, Jiaxun Yang wrote:
> There are some Loongson64 systems come with broken coherent DMA
> support, firmware will set a bit in boot_param and pass nocoherentio
> in cmdline.
>
> However nonconherent support was missed out when spin off Loongson-2EF
> form Loongson64, and that boot_param change never made itself into
> upstream.
>
> Support DMA noncoherent properly to get those systems work.
Working.
>
> Cc: [email protected]
> Fixes: 71e2f4dd5a65 ("MIPS: Fork loongson2ef from loongson64")
> Signed-off-by: Jiaxun Yang <[email protected]>
[...]
> diff --git a/arch/mips/include/asm/mach-loongson64/boot_param.h b/arch/mips/include/asm/mach-loongson64/boot_param.h
> index 035b1a69e2d0..c454ef734c45 100644
> --- a/arch/mips/include/asm/mach-loongson64/boot_param.h
> +++ b/arch/mips/include/asm/mach-loongson64/boot_param.h
> @@ -117,7 +117,8 @@ struct irq_source_routing_table {
> u64 pci_io_start_addr;
> u64 pci_io_end_addr;
> u64 pci_config_addr;
> - u32 dma_mask_bits;
> + u16 dma_mask_bits;
> + u16 dma_noncoherent;
> } __packed;
>
> struct interface_info {
> diff --git a/arch/mips/loongson64/env.c b/arch/mips/loongson64/env.c
> index c961e2999f15..df0e92cd3920 100644
> --- a/arch/mips/loongson64/env.c
> +++ b/arch/mips/loongson64/env.c
> @@ -13,6 +13,8 @@
> * Copyright (C) 2009 Lemote Inc.
> * Author: Wu Zhangjin, [email protected]
> */
> +
> +#include <linux/dma-map-ops.h>
> #include <linux/export.h>
> #include <linux/pci_ids.h>
> #include <asm/bootinfo.h>
> @@ -147,8 +149,13 @@ void __init prom_lefi_init_env(void)
>
> loongson_sysconf.dma_mask_bits = eirq_source->dma_mask_bits;
> if (loongson_sysconf.dma_mask_bits < 32 ||
> - loongson_sysconf.dma_mask_bits > 64)
> + loongson_sysconf.dma_mask_bits > 64) {
Please indent this line differently, so it doesn't blend
with the following line (either start it in the same column
as the *if* expression above, or add 1 more tab).
> loongson_sysconf.dma_mask_bits = 32;
> + dma_default_coherent = true;
> + } else
The kernel style dictates that you need to add {} on the *else*
branchh too.
> + dma_default_coherent = !eirq_source->dma_noncoherent;
> +
> + pr_info("DMA coherent: %s\n", dma_default_coherent ? "on" : "off");
Maybe "Coherent DMA: %s\n"?
[...]
MBR, Sergey