]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
LoongArch: Disable WUC for pgprot_writecombine() like ioremap_wc()
authorIcenowy Zheng <uwu@icenowy.me>
Wed, 18 Oct 2023 00:42:52 +0000 (08:42 +0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 8 Nov 2023 13:09:02 +0000 (14:09 +0100)
[ Upstream commit 278be83601dd1725d4732241f066d528e160a39d ]

Currently the code disables WUC only disables it for ioremap_wc(), which
is only used when mapping writecombine pages like ioremap() (mapped to
the kernel space). But for VRAM mapped in TTM/GEM, it is mapped with a
crafted pgprot by the pgprot_writecombine() function, in which case WUC
isn't disabled now.

Disable WUC for pgprot_writecombine() (fallback to SUC) if needed, like
ioremap_wc().

This improves the AMDGPU driver's stability (solves some misrendering)
on Loongson-3A5000/3A6000 machines.

Signed-off-by: Icenowy Zheng <uwu@icenowy.me>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
Signed-off-by: Sasha Levin <sashal@kernel.org>
arch/loongarch/include/asm/io.h
arch/loongarch/include/asm/pgtable-bits.h
arch/loongarch/kernel/setup.c

index 1c94102200407f2f62f573bcbb923614db1b52e1..0355b64e90ed0c3ad7a43cf3381083b27667963c 100644 (file)
@@ -54,10 +54,9 @@ 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(pgprot_wc))
+       ioremap_prot((offset), (size),  \
+               pgprot_val(wc_enabled ? PAGE_KERNEL_WUC : PAGE_KERNEL_SUC))
 
 #define ioremap_cache(offset, size)    \
        ioremap_prot((offset), (size), pgprot_val(PAGE_KERNEL))
index de46a6b1e9f11c87d68ef526e30c4cf816b17a38..7b9ac012cd090e9c52fb60bedfd9ee70e685f1f7 100644 (file)
@@ -105,13 +105,15 @@ static inline pgprot_t pgprot_noncached(pgprot_t _prot)
        return __pgprot(prot);
 }
 
+extern bool wc_enabled;
+
 #define pgprot_writecombine pgprot_writecombine
 
 static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
 {
        unsigned long prot = pgprot_val(_prot);
 
-       prot = (prot & ~_CACHE_MASK) | _CACHE_WUC;
+       prot = (prot & ~_CACHE_MASK) | (wc_enabled ? _CACHE_WUC : _CACHE_SUC);
 
        return __pgprot(prot);
 }
index 9d830ab4e3025e8ab7afacfc21428dfa9665afde..1351614042d4e8818b1538eb6673effc3d505ad3 100644 (file)
@@ -161,19 +161,19 @@ static void __init smbios_parse(void)
 }
 
 #ifdef CONFIG_ARCH_WRITECOMBINE
-pgprot_t pgprot_wc = PAGE_KERNEL_WUC;
+bool wc_enabled = true;
 #else
-pgprot_t pgprot_wc = PAGE_KERNEL_SUC;
+bool wc_enabled = false;
 #endif
 
-EXPORT_SYMBOL(pgprot_wc);
+EXPORT_SYMBOL(wc_enabled);
 
 static int __init setup_writecombine(char *p)
 {
        if (!strcmp(p, "on"))
-               pgprot_wc = PAGE_KERNEL_WUC;
+               wc_enabled = true;
        else if (!strcmp(p, "off"))
-               pgprot_wc = PAGE_KERNEL_SUC;
+               wc_enabled = false;
        else
                pr_warn("Unknown writecombine setting \"%s\".\n", p);