git: 98b129783c47 - main - LinuxKPI: Import MTRR support functions from drm-kmod
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 10 Jan 2022 19:50:51 UTC
The branch main has been updated by wulf:
URL: https://cgit.FreeBSD.org/src/commit/?id=98b129783c478616f59b3b9c9576a303f7ed67de
commit 98b129783c478616f59b3b9c9576a303f7ed67de
Author: Vladimir Kondratyev <wulf@FreeBSD.org>
AuthorDate: 2021-12-08 21:12:51 +0000
Commit: Vladimir Kondratyev <wulf@FreeBSD.org>
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
+}