Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

LoongArch: Make WriteCombine configurable for ioremap()

LoongArch maintains cache coherency in hardware, but when paired with
LS7A chipsets the WUC attribute (Weak-ordered UnCached, which is similar
to WriteCombine) is out of the scope of cache coherency machanism for
PCIe devices (this is a PCIe protocol violation, which may be fixed in
newer chipsets).

This means WUC can only used for write-only memory regions now, so this
option is disabled by default, making WUC silently fallback to SUC for
ioremap(). You can enable this option if the kernel is ensured to run on
hardware without this bug.

Kernel parameter writecombine=on/off can be used to override the Kconfig
option.

Cc: stable@vger.kernel.org
Suggested-by: WANG Xuerui <kernel@xen0n.name>
Reviewed-by: WANG Xuerui <kernel@xen0n.name>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>

+47 -1
+1
Documentation/admin-guide/kernel-parameters.rst
··· 128 128 KVM Kernel Virtual Machine support is enabled. 129 129 LIBATA Libata driver is enabled 130 130 LP Printer support is enabled. 131 + LOONGARCH LoongArch architecture is enabled. 131 132 LOOP Loopback device support is enabled. 132 133 M68k M68k architecture is enabled. 133 134 These options have more detailed description inside of
+6
Documentation/admin-guide/kernel-parameters.txt
··· 6933 6933 When enabled, memory and cache locality will be 6934 6934 impacted. 6935 6935 6936 + writecombine= [LOONGARCH] Control the MAT (Memory Access Type) of 6937 + ioremap_wc(). 6938 + 6939 + on - Enable writecombine, use WUC for ioremap_wc() 6940 + off - Disable writecombine, use SUC for ioremap_wc() 6941 + 6936 6942 x2apic_phys [X86-64,APIC] Use x2apic physical mode instead of 6937 6943 default x2apic cluster mode on platforms 6938 6944 supporting x2apic.
+16
arch/loongarch/Kconfig
··· 447 447 protection support. However, you can enable LoongArch DMW-based 448 448 ioremap() for better performance. 449 449 450 + config ARCH_WRITECOMBINE 451 + bool "Enable WriteCombine (WUC) for ioremap()" 452 + help 453 + LoongArch maintains cache coherency in hardware, but when paired 454 + with LS7A chipsets the WUC attribute (Weak-ordered UnCached, which 455 + is similar to WriteCombine) is out of the scope of cache coherency 456 + machanism for PCIe devices (this is a PCIe protocol violation, which 457 + may be fixed in newer chipsets). 458 + 459 + This means WUC can only used for write-only memory regions now, so 460 + this option is disabled by default, making WUC silently fallback to 461 + SUC for ioremap(). You can enable this option if the kernel is ensured 462 + to run on hardware without this bug. 463 + 464 + You can override this setting via writecombine=on/off boot parameter. 465 + 450 466 config ARCH_STRICT_ALIGN 451 467 bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT 452 468 default y
+3 -1
arch/loongarch/include/asm/io.h
··· 54 54 * @offset: bus address of the memory 55 55 * @size: size of the resource to map 56 56 */ 57 + extern pgprot_t pgprot_wc; 58 + 57 59 #define ioremap_wc(offset, size) \ 58 - ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC)) 60 + ioremap_prot((offset), (size), pgprot_val(pgprot_wc)) 59 61 60 62 #define ioremap_cache(offset, size) \ 61 63 ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
+21
arch/loongarch/kernel/setup.c
··· 160 160 dmi_walk(find_tokens, NULL); 161 161 } 162 162 163 + #ifdef CONFIG_ARCH_WRITECOMBINE 164 + pgprot_t pgprot_wc = PAGE_KERNEL_WUC; 165 + #else 166 + pgprot_t pgprot_wc = PAGE_KERNEL_SUC; 167 + #endif 168 + 169 + EXPORT_SYMBOL(pgprot_wc); 170 + 171 + static int __init setup_writecombine(char *p) 172 + { 173 + if (!strcmp(p, "on")) 174 + pgprot_wc = PAGE_KERNEL_WUC; 175 + else if (!strcmp(p, "off")) 176 + pgprot_wc = PAGE_KERNEL_SUC; 177 + else 178 + pr_warn("Unknown writecombine setting \"%s\".\n", p); 179 + 180 + return 0; 181 + } 182 + early_param("writecombine", setup_writecombine); 183 + 163 184 static int usermem __initdata; 164 185 165 186 static int __init early_parse_mem(char *p)