Skip to content

Commit 16c52e5

Browse files
committed
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: [email protected] Suggested-by: WANG Xuerui <[email protected]> Reviewed-by: WANG Xuerui <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 6a8f57a commit 16c52e5

File tree

5 files changed

+47
-1
lines changed

5 files changed

+47
-1
lines changed

Documentation/admin-guide/kernel-parameters.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ parameter is applicable::
128128
KVM Kernel Virtual Machine support is enabled.
129129
LIBATA Libata driver is enabled
130130
LP Printer support is enabled.
131+
LOONGARCH LoongArch architecture is enabled.
131132
LOOP Loopback device support is enabled.
132133
M68k M68k architecture is enabled.
133134
These options have more detailed description inside of

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6933,6 +6933,12 @@
69336933
When enabled, memory and cache locality will be
69346934
impacted.
69356935

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+
69366942
x2apic_phys [X86-64,APIC] Use x2apic physical mode instead of
69376943
default x2apic cluster mode on platforms
69386944
supporting x2apic.

arch/loongarch/Kconfig

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,22 @@ config ARCH_IOREMAP
447447
protection support. However, you can enable LoongArch DMW-based
448448
ioremap() for better performance.
449449

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+
450466
config ARCH_STRICT_ALIGN
451467
bool "Enable -mstrict-align to prevent unaligned accesses" if EXPERT
452468
default y

arch/loongarch/include/asm/io.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,10 @@ static inline void __iomem *ioremap_prot(phys_addr_t offset, unsigned long size,
5454
* @offset: bus address of the memory
5555
* @size: size of the resource to map
5656
*/
57+
extern pgprot_t pgprot_wc;
58+
5759
#define ioremap_wc(offset, size) \
58-
ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL_WUC))
60+
ioremap_prot((offset), (size), pgprot_val(pgprot_wc))
5961

6062
#define ioremap_cache(offset, size) \
6163
ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))

arch/loongarch/kernel/setup.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,27 @@ static void __init smbios_parse(void)
160160
dmi_walk(find_tokens, NULL);
161161
}
162162

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+
163184
static int usermem __initdata;
164185

165186
static int __init early_parse_mem(char *p)

0 commit comments

Comments
 (0)