From: Hauke Mehrtens Date: Thu, 6 Jun 2013 11:48:04 +0000 (+0200) Subject: backports: backport some memory functions X-Git-Url: http://git.lede-project.org./?a=commitdiff_plain;h=2ce5c22448bb45998318267c00b5d6ef9cff3170;p=openwrt%2Fstaging%2Fblogic.git backports: backport some memory functions This includes the following functions needed by some drm drivers: arch_phys_wc_add() arch_phys_wc_del() phys_wc_to_mtrr_index() This backports the following commit form mainline kernel: commit d0d98eedee2178c803dd824bb09f52b0e2ac1811 Author: Andy Lutomirski Date: Mon May 13 23:58:40 2013 +0000 Add arch_phys_wc_{add, del} to manipulate WC MTRRs if needed Signed-off-by: Hauke Mehrtens Signed-off-by: Luis R. Rodriguez --- diff --git a/backport/backport-include/asm/mtrr.h b/backport/backport-include/asm/mtrr.h new file mode 100644 index 000000000000..cf0f6fd30e69 --- /dev/null +++ b/backport/backport-include/asm/mtrr.h @@ -0,0 +1,20 @@ +#ifndef __BACKPORT_ASM_MTRR_H +#define __BACKPORT_ASM_MTRR_H +#include_next + +#if (LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)) +/* + * The following functions are for use by other drivers that cannot use + * arch_phys_wc_add and arch_phys_wc_del. + */ +#ifdef CONFIG_MTRR +extern int phys_wc_to_mtrr_index(int handle); +#else +static inline int phys_wc_to_mtrr_index(int handle) +{ + return -1; +} +#endif /* CONFIG_MTRR */ +#endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0)) */ + +#endif /* __BACKPORT_ASM_MTRR_H */ diff --git a/backport/backport-include/linux/io.h b/backport/backport-include/linux/io.h new file mode 100644 index 000000000000..9a5b308a9524 --- /dev/null +++ b/backport/backport-include/linux/io.h @@ -0,0 +1,36 @@ +#ifndef __BACKPORT_LINUX_IO_H +#define __BACKPORT_LINUX_IO_H +#include_next + +/* + * Some systems (x86 without PAT) have a somewhat reliable way to mark a + * physical address range such that uncached mappings will actually + * end up write-combining. This facility should be used in conjunction + * with pgprot_writecombine, ioremap-wc, or set_memory_wc, since it has + * no effect if the per-page mechanisms are functional. + * (On x86 without PAT, these functions manipulate MTRRs.) + * + * arch_phys_del_wc(0) or arch_phys_del_wc(any error code) is guaranteed + * to have no effect. + */ +#ifndef arch_phys_wc_add +#ifdef CONFIG_MTRR +extern int __must_check arch_phys_wc_add(unsigned long base, + unsigned long size); +extern void arch_phys_wc_del(int handle); +#else +static inline int __must_check arch_phys_wc_add(unsigned long base, + unsigned long size) +{ + return 0; /* It worked (i.e. did nothing). */ +} + +static inline void arch_phys_wc_del(int handle) +{ +} +#endif /* CONFIG_MTRR */ + +#define arch_phys_wc_add arch_phys_wc_add +#endif + +#endif /* __BACKPORT_LINUX_IO_H */ diff --git a/backport/compat/Makefile b/backport/compat/Makefile index 18df1561121d..252290e315c5 100644 --- a/backport/compat/Makefile +++ b/backport/compat/Makefile @@ -35,6 +35,7 @@ compat-$(CPTCFG_BACKPORT_KERNEL_3_7) += compat-3.7.o compat-$(CPTCFG_BACKPORT_KERNEL_3_8) += compat-3.8.o compat-$(CPTCFG_BACKPORT_KERNEL_3_9) += compat-3.9.o compat-$(CPTCFG_BACKPORT_KERNEL_3_10) += backport-3.10.o +compat-$(CPTCFG_BACKPORT_KERNEL_3_11) += backport-3.11.o compat-$(CPTCFG_BACKPORT_BUILD_KFIFO) += kfifo.o compat-$(CPTCFG_BACKPORT_BUILD_GENERIC_ATOMIC64) += compat_atomic.o diff --git a/backport/compat/backport-3.11.c b/backport/compat/backport-3.11.c new file mode 100644 index 000000000000..72e0800c60e5 --- /dev/null +++ b/backport/compat/backport-3.11.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2013 Hauke Mehrtens + * + * Compatibility file for Linux wireless for kernels 3.11. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include + +#ifdef CONFIG_MTRR + +#include +#include +#include + +/* arch_phys_wc_add returns an MTRR register index plus this offset. */ +#define MTRR_TO_PHYS_WC_OFFSET 1000 + +/** + * arch_phys_wc_add - add a WC MTRR and handle errors if PAT is unavailable + * @base: Physical base address + * @size: Size of region + * + * If PAT is available, this does nothing. If PAT is unavailable, it + * attempts to add a WC MTRR covering size bytes starting at base and + * logs an error if this fails. + * + * Drivers must store the return value to pass to mtrr_del_wc_if_needed, + * but drivers should not try to interpret that return value. + */ +int arch_phys_wc_add(unsigned long base, unsigned long size) +{ + int ret; + +#if defined(CONFIG_X86_PAT) + if (cpu_has_pat) + return 0; +#endif + + ret = mtrr_add(base, size, MTRR_TYPE_WRCOMB, true); + if (ret < 0) { + pr_warn("Failed to add WC MTRR for [%p-%p]; performance may suffer.", + (void *)base, (void *)(base + size - 1)); + return ret; + } + return ret + MTRR_TO_PHYS_WC_OFFSET; +} +EXPORT_SYMBOL(arch_phys_wc_add); + +/* + * arch_phys_wc_del - undoes arch_phys_wc_add + * @handle: Return value from arch_phys_wc_add + * + * This cleans up after mtrr_add_wc_if_needed. + * + * The API guarantees that mtrr_del_wc_if_needed(error code) and + * mtrr_del_wc_if_needed(0) do nothing. + */ +void arch_phys_wc_del(int handle) +{ + if (handle >= 1) { + WARN_ON(handle < MTRR_TO_PHYS_WC_OFFSET); + mtrr_del(handle - MTRR_TO_PHYS_WC_OFFSET, 0, 0); + } +} +EXPORT_SYMBOL(arch_phys_wc_del); + +/* + * phys_wc_to_mtrr_index - translates arch_phys_wc_add's return value + * @handle: Return value from arch_phys_wc_add + * + * This will turn the return value from arch_phys_wc_add into an mtrr + * index suitable for debugging. + * + * Note: There is no legitimate use for this function, except possibly + * in printk line. Alas there is an illegitimate use in some ancient + * drm ioctls. + */ +int phys_wc_to_mtrr_index(int handle) +{ + if (handle < MTRR_TO_PHYS_WC_OFFSET) + return -1; + else + return handle - MTRR_TO_PHYS_WC_OFFSET; +} +EXPORT_SYMBOL_GPL(phys_wc_to_mtrr_index); + +#endif /* CONFIG_MTRR */