Commit 16c52e50 authored by Huacai Chen's avatar Huacai Chen
Browse files

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: default avatarWANG Xuerui <kernel@xen0n.name>
Reviewed-by: default avatarWANG Xuerui <kernel@xen0n.name>
Signed-off-by: default avatarHuacai Chen <chenhuacai@loongson.cn>
parent 6a8f57ae
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ parameter is applicable::
	KVM	Kernel Virtual Machine support is enabled.
	LIBATA  Libata driver is enabled
	LP	Printer support is enabled.
	LOONGARCH LoongArch architecture is enabled.
	LOOP	Loopback device support is enabled.
	M68k	M68k architecture is enabled.
			These options have more detailed description inside of
+6 −0
Original line number Diff line number Diff line
@@ -6933,6 +6933,12 @@
			When enabled, memory and cache locality will be
			impacted.

	writecombine=	[LOONGARCH] Control the MAT (Memory Access Type) of
			ioremap_wc().

			on   - Enable writecombine, use WUC for ioremap_wc()
			off  - Disable writecombine, use SUC for ioremap_wc()

	x2apic_phys	[X86-64,APIC] Use x2apic physical mode instead of
			default x2apic cluster mode on platforms
			supporting x2apic.
+16 −0
Original line number Diff line number Diff line
@@ -447,6 +447,22 @@ config ARCH_IOREMAP
	  protection support. However, you can enable LoongArch DMW-based
	  ioremap() for better performance.

config ARCH_WRITECOMBINE
	bool "Enable WriteCombine (WUC) for ioremap()"
	help
	  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.

	  You can override this setting via writecombine=on/off boot parameter.

config ARCH_STRICT_ALIGN
	bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT
	default y
+3 −1
Original line number Diff line number Diff line
@@ -54,8 +54,10 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
 * @offset:    bus address of the memory
 * @size:      size of the resource to map
 */
extern pgprot_t pgprot_wc;

#define ioremap_wc(offset, size)	\
	ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC))
	ioremap_prot((offset), (size), pgprot_val(pgprot_wc))

#define ioremap_cache(offset, size)	\
	ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
+21 −0
Original line number Diff line number Diff line
@@ -160,6 +160,27 @@ static void __init smbios_parse(void)
	dmi_walk(find_tokens, NULL);
}

#ifdef CONFIG_ARCH_WRITECOMBINE
pgprot_t pgprot_wc = PAGE_KERNEL_WUC;
#else
pgprot_t pgprot_wc = PAGE_KERNEL_SUC;
#endif

EXPORT_SYMBOL(pgprot_wc);

static int __init setup_writecombine(char *p)
{
	if (!strcmp(p, "on"))
		pgprot_wc = PAGE_KERNEL_WUC;
	else if (!strcmp(p, "off"))
		pgprot_wc = PAGE_KERNEL_SUC;
	else
		pr_warn("Unknown writecombine setting \"%s\".\n", p);

	return 0;
}
early_param("writecombine", setup_writecombine);

static int usermem __initdata;

static int __init early_parse_mem(char *p)