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
This commit is contained in:
parent
1456816425
commit
98b129783c
@ -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_ */
|
||||
|
@ -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 @@ lkpi_unmap_mapping_range(void *obj, loff_t const holebegin __unused,
|
||||
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
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user