The branch main has been updated by wulf:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=98b129783c478616f59b3b9c9576a303f7ed67de

commit 98b129783c478616f59b3b9c9576a303f7ed67de
Author:     Vladimir Kondratyev <[email protected]>
AuthorDate: 2021-12-08 21:12:51 +0000
Commit:     Vladimir Kondratyev <[email protected]>
CommitDate: 2022-01-10 19:49:38 +0000

    LinuxKPI: Import MTRR support functions from drm-kmod
    
    They are superseded by PAT and mostly useless nowadays but still can be
    used on Pentium III/IV era processors. Unlike drm-kmod version, this one
    ignores MTRR if PAT is available that fixes confusing "Failed to add WC
    MTRR for [0xXXXX-0xYYYY]: 22; performance may suffer" message often
    appearing during drm-kmod initialization process.
    
    MFC after:      1 week
    Reviewed by:    hselasky, manu
    Differential Revision:  https://reviews.freebsd.org/D33561
---
 sys/compat/linuxkpi/common/include/linux/io.h |  8 +++
 sys/compat/linuxkpi/common/src/linux_page.c   | 72 +++++++++++++++++++++++++++
 2 files changed, 80 insertions(+)

diff --git a/sys/compat/linuxkpi/common/include/linux/io.h 
b/sys/compat/linuxkpi/common/include/linux/io.h
index e402ebed0665..08e1635b70ac 100644
--- a/sys/compat/linuxkpi/common/include/linux/io.h
+++ b/sys/compat/linuxkpi/common/include/linux/io.h
@@ -482,4 +482,12 @@ memunmap(void *addr)
        iounmap(addr);
 }
 
+#define        __MTRR_ID_BASE  1
+int lkpi_arch_phys_wc_add(unsigned long, unsigned long);
+void lkpi_arch_phys_wc_del(int);
+#define        arch_phys_wc_add(...)   lkpi_arch_phys_wc_add(__VA_ARGS__)
+#define        arch_phys_wc_del(...)   lkpi_arch_phys_wc_del(__VA_ARGS__)
+#define        arch_phys_wc_index(x)   \
+       (((x) < __MTRR_ID_BASE) ? -1 : ((x) - __MTRR_ID_BASE))
+
 #endif /* _LINUX_IO_H_ */
diff --git a/sys/compat/linuxkpi/common/src/linux_page.c 
b/sys/compat/linuxkpi/common/src/linux_page.c
index 3c8bc2bd3c5b..df4a124cf3e2 100644
--- a/sys/compat/linuxkpi/common/src/linux_page.c
+++ b/sys/compat/linuxkpi/common/src/linux_page.c
@@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/rwlock.h>
 #include <sys/proc.h>
 #include <sys/sched.h>
+#include <sys/memrange.h>
 
 #include <machine/bus.h>
 
@@ -63,6 +64,15 @@ __FBSDID("$FreeBSD$");
 #include <linux/preempt.h>
 #include <linux/fs.h>
 #include <linux/shmem_fs.h>
+#include <linux/kernel.h>
+#include <linux/idr.h>
+#include <linux/io.h>
+
+#ifdef __i386__
+DEFINE_IDR(mtrr_idr);
+static MALLOC_DEFINE(M_LKMTRR, "idr", "Linux MTRR compat");
+extern int pat_works;
+#endif
 
 void
 si_meminfo(struct sysinfo *si)
@@ -357,3 +367,65 @@ retry:
                vm_object_deallocate(devobj);
        }
 }
+
+int
+lkpi_arch_phys_wc_add(unsigned long base, unsigned long size)
+{
+#ifdef __i386__
+       struct mem_range_desc *mrdesc;
+       int error, id, act;
+
+       /* If PAT is available, do nothing */
+       if (pat_works)
+               return (0);
+
+       mrdesc = malloc(sizeof(*mrdesc), M_LKMTRR, M_WAITOK);
+       mrdesc->mr_base = base;
+       mrdesc->mr_len = size;
+       mrdesc->mr_flags = MDF_WRITECOMBINE;
+       strlcpy(mrdesc->mr_owner, "drm", sizeof(mrdesc->mr_owner));
+       act = MEMRANGE_SET_UPDATE;
+       error = mem_range_attr_set(mrdesc, &act);
+       if (error == 0) {
+               error = idr_get_new(&mtrr_idr, mrdesc, &id);
+               MPASS(idr_find(&mtrr_idr, id) == mrdesc);
+               if (error != 0) {
+                       act = MEMRANGE_SET_REMOVE;
+                       mem_range_attr_set(mrdesc, &act);
+               }
+       }
+       if (error != 0) {
+               free(mrdesc, M_LKMTRR);
+               pr_warn(
+                   "Failed to add WC MTRR for [%p-%p]: %d; "
+                   "performance may suffer\n",
+                   (void *)base, (void *)(base + size - 1), error);
+       } else
+               pr_warn("Successfully added WC MTRR for [%p-%p]\n",
+                   (void *)base, (void *)(base + size - 1));
+
+       return (error != 0 ? -error : id + __MTRR_ID_BASE);
+#else
+       return (0);
+#endif
+}
+
+void
+lkpi_arch_phys_wc_del(int reg)
+{
+#ifdef __i386__
+       struct mem_range_desc *mrdesc;
+       int act;
+
+       /* Check if arch_phys_wc_add() failed. */
+       if (reg < __MTRR_ID_BASE)
+               return;
+
+       mrdesc = idr_find(&mtrr_idr, reg - __MTRR_ID_BASE);
+       MPASS(mrdesc != NULL);
+       idr_remove(&mtrr_idr, reg - __MTRR_ID_BASE);
+       act = MEMRANGE_SET_REMOVE;
+       mem_range_attr_set(mrdesc, &act);
+       free(mrdesc, M_LKMTRR);
+#endif
+}

Reply via email to