Merge master.kernel.org:/home/rmk/linux-2.6-arm
* master.kernel.org:/home/rmk/linux-2.6-arm: ARM: pxa: fix page table corruption on resume ARM: it8152: add IT8152_LAST_IRQ definition to fix build error ARM: pxa: PXA_ESERIES depends on FB_W100. ARM: 6605/1: Add missing include "asm/memory.h" ARM: 6540/1: Stop irqsoff trace on return to user ARM: 6537/1: update Nomadik, U300 and Ux500 maintainers ARM: 6536/1: Add missing SZ_{32,64,128} ARM: fix cache-feroceon-l2 after stack based kmap_atomic() ARM: fix cache-xsc3l2 after stack based kmap_atomic() ARM: get rid of kmap_high_l1_vipt() ARM: smp: avoid incrementing mm_users on CPU startup ARM: pxa: PXA_ESERIES depends on FB_W100.
This commit is contained in:
commit
989d873fc5
14 changed files with 78 additions and 157 deletions
17
MAINTAINERS
17
MAINTAINERS
|
@ -792,11 +792,14 @@ S: Maintained
|
||||||
|
|
||||||
ARM/NOMADIK ARCHITECTURE
|
ARM/NOMADIK ARCHITECTURE
|
||||||
M: Alessandro Rubini <rubini@unipv.it>
|
M: Alessandro Rubini <rubini@unipv.it>
|
||||||
|
M: Linus Walleij <linus.walleij@stericsson.com>
|
||||||
M: STEricsson <STEricsson_nomadik_linux@list.st.com>
|
M: STEricsson <STEricsson_nomadik_linux@list.st.com>
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: arch/arm/mach-nomadik/
|
F: arch/arm/mach-nomadik/
|
||||||
F: arch/arm/plat-nomadik/
|
F: arch/arm/plat-nomadik/
|
||||||
|
F: drivers/i2c/busses/i2c-nomadik.c
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
|
||||||
|
|
||||||
ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
|
ARM/OPENMOKO NEO FREERUNNER (GTA02) MACHINE SUPPORT
|
||||||
M: Nelson Castillo <arhuaco@freaks-unidos.net>
|
M: Nelson Castillo <arhuaco@freaks-unidos.net>
|
||||||
|
@ -998,12 +1001,24 @@ F: drivers/i2c/busses/i2c-stu300.c
|
||||||
F: drivers/rtc/rtc-coh901331.c
|
F: drivers/rtc/rtc-coh901331.c
|
||||||
F: drivers/watchdog/coh901327_wdt.c
|
F: drivers/watchdog/coh901327_wdt.c
|
||||||
F: drivers/dma/coh901318*
|
F: drivers/dma/coh901318*
|
||||||
|
F: drivers/mfd/ab3100*
|
||||||
|
F: drivers/rtc/rtc-ab3100.c
|
||||||
|
F: drivers/rtc/rtc-coh901331.c
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
|
||||||
|
|
||||||
ARM/U8500 ARM ARCHITECTURE
|
ARM/Ux500 ARM ARCHITECTURE
|
||||||
M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
|
M: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
|
||||||
|
M: Linus Walleij <linus.walleij@stericsson.com>
|
||||||
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
|
||||||
S: Maintained
|
S: Maintained
|
||||||
F: arch/arm/mach-ux500/
|
F: arch/arm/mach-ux500/
|
||||||
|
F: drivers/dma/ste_dma40*
|
||||||
|
F: drivers/mfd/ab3550*
|
||||||
|
F: drivers/mfd/abx500*
|
||||||
|
F: drivers/mfd/ab8500*
|
||||||
|
F: drivers/mfd/stmpe*
|
||||||
|
F: drivers/rtc/rtc-ab8500.c
|
||||||
|
T: git git://git.kernel.org/pub/scm/linux/kernel/git/linusw/linux-stericsson.git
|
||||||
|
|
||||||
ARM/VFP SUPPORT
|
ARM/VFP SUPPORT
|
||||||
M: Russell King <linux@arm.linux.org.uk>
|
M: Russell King <linux@arm.linux.org.uk>
|
||||||
|
|
|
@ -76,6 +76,7 @@ extern unsigned long it8152_base_address;
|
||||||
IT8152_PD_IRQ(0) Audio controller (ACR)
|
IT8152_PD_IRQ(0) Audio controller (ACR)
|
||||||
*/
|
*/
|
||||||
#define IT8152_IRQ(x) (IRQ_BOARD_START + (x))
|
#define IT8152_IRQ(x) (IRQ_BOARD_START + (x))
|
||||||
|
#define IT8152_LAST_IRQ (IRQ_BOARD_START + 40)
|
||||||
|
|
||||||
/* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
|
/* IRQ-sources in 3 groups - local devices, LPC (serial), and external PCI */
|
||||||
#define IT8152_LD_IRQ_COUNT 9
|
#define IT8152_LD_IRQ_COUNT 9
|
||||||
|
|
|
@ -25,9 +25,6 @@ extern void *kmap_high(struct page *page);
|
||||||
extern void *kmap_high_get(struct page *page);
|
extern void *kmap_high_get(struct page *page);
|
||||||
extern void kunmap_high(struct page *page);
|
extern void kunmap_high(struct page *page);
|
||||||
|
|
||||||
extern void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte);
|
|
||||||
extern void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The following functions are already defined by <linux/highmem.h>
|
* The following functions are already defined by <linux/highmem.h>
|
||||||
* when CONFIG_HIGHMEM is not set.
|
* when CONFIG_HIGHMEM is not set.
|
||||||
|
|
|
@ -13,9 +13,6 @@
|
||||||
* along with this program; if not, write to the Free Software
|
* along with this program; if not, write to the Free Software
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
/* DO NOT EDIT!! - this file automatically generated
|
|
||||||
* from .s file by awk -f s2h.awk
|
|
||||||
*/
|
|
||||||
/* Size definitions
|
/* Size definitions
|
||||||
* Copyright (C) ARM Limited 1998. All rights reserved.
|
* Copyright (C) ARM Limited 1998. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
@ -25,6 +22,9 @@
|
||||||
|
|
||||||
/* handy sizes */
|
/* handy sizes */
|
||||||
#define SZ_16 0x00000010
|
#define SZ_16 0x00000010
|
||||||
|
#define SZ_32 0x00000020
|
||||||
|
#define SZ_64 0x00000040
|
||||||
|
#define SZ_128 0x00000080
|
||||||
#define SZ_256 0x00000100
|
#define SZ_256 0x00000100
|
||||||
#define SZ_512 0x00000200
|
#define SZ_512 0x00000200
|
||||||
|
|
||||||
|
|
|
@ -150,6 +150,7 @@ extern unsigned int user_debug;
|
||||||
#define rmb() dmb()
|
#define rmb() dmb()
|
||||||
#define wmb() mb()
|
#define wmb() mb()
|
||||||
#else
|
#else
|
||||||
|
#include <asm/memory.h>
|
||||||
#define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
|
#define mb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
|
||||||
#define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
|
#define rmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
|
||||||
#define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
|
#define wmb() do { if (arch_is_coherent()) dmb(); else barrier(); } while (0)
|
||||||
|
|
|
@ -29,6 +29,9 @@ ret_fast_syscall:
|
||||||
ldr r1, [tsk, #TI_FLAGS]
|
ldr r1, [tsk, #TI_FLAGS]
|
||||||
tst r1, #_TIF_WORK_MASK
|
tst r1, #_TIF_WORK_MASK
|
||||||
bne fast_work_pending
|
bne fast_work_pending
|
||||||
|
#if defined(CONFIG_IRQSOFF_TRACER)
|
||||||
|
asm_trace_hardirqs_on
|
||||||
|
#endif
|
||||||
|
|
||||||
/* perform architecture specific actions before user return */
|
/* perform architecture specific actions before user return */
|
||||||
arch_ret_to_user r1, lr
|
arch_ret_to_user r1, lr
|
||||||
|
@ -65,6 +68,9 @@ ret_slow_syscall:
|
||||||
tst r1, #_TIF_WORK_MASK
|
tst r1, #_TIF_WORK_MASK
|
||||||
bne work_pending
|
bne work_pending
|
||||||
no_work_pending:
|
no_work_pending:
|
||||||
|
#if defined(CONFIG_IRQSOFF_TRACER)
|
||||||
|
asm_trace_hardirqs_on
|
||||||
|
#endif
|
||||||
/* perform architecture specific actions before user return */
|
/* perform architecture specific actions before user return */
|
||||||
arch_ret_to_user r1, lr
|
arch_ret_to_user r1, lr
|
||||||
|
|
||||||
|
|
|
@ -310,7 +310,6 @@ asmlinkage void __cpuinit secondary_start_kernel(void)
|
||||||
* All kernel threads share the same mm context; grab a
|
* All kernel threads share the same mm context; grab a
|
||||||
* reference and switch to it.
|
* reference and switch to it.
|
||||||
*/
|
*/
|
||||||
atomic_inc(&mm->mm_users);
|
|
||||||
atomic_inc(&mm->mm_count);
|
atomic_inc(&mm->mm_count);
|
||||||
current->active_mm = mm;
|
current->active_mm = mm;
|
||||||
cpumask_set_cpu(cpu, mm_cpumask(mm));
|
cpumask_set_cpu(cpu, mm_cpumask(mm));
|
||||||
|
|
|
@ -540,6 +540,7 @@ config MACH_ICONTROL
|
||||||
config ARCH_PXA_ESERIES
|
config ARCH_PXA_ESERIES
|
||||||
bool "PXA based Toshiba e-series PDAs"
|
bool "PXA based Toshiba e-series PDAs"
|
||||||
select PXA25x
|
select PXA25x
|
||||||
|
select FB_W100
|
||||||
|
|
||||||
config MACH_E330
|
config MACH_E330
|
||||||
bool "Toshiba e330"
|
bool "Toshiba e330"
|
||||||
|
|
|
@ -353,8 +353,8 @@ resume_turn_on_mmu:
|
||||||
|
|
||||||
@ Let us ensure we jump to resume_after_mmu only when the mcr above
|
@ Let us ensure we jump to resume_after_mmu only when the mcr above
|
||||||
@ actually took effect. They call it the "cpwait" operation.
|
@ actually took effect. They call it the "cpwait" operation.
|
||||||
mrc p15, 0, r1, c2, c0, 0 @ queue a dependency on CP15
|
mrc p15, 0, r0, c2, c0, 0 @ queue a dependency on CP15
|
||||||
sub pc, r2, r1, lsr #32 @ jump to virtual addr
|
sub pc, r2, r0, lsr #32 @ jump to virtual addr
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
nop
|
nop
|
||||||
|
|
|
@ -13,13 +13,9 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/highmem.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/kmap_types.h>
|
|
||||||
#include <asm/fixmap.h>
|
|
||||||
#include <asm/pgtable.h>
|
|
||||||
#include <asm/tlbflush.h>
|
|
||||||
#include <plat/cache-feroceon-l2.h>
|
#include <plat/cache-feroceon-l2.h>
|
||||||
#include "mm.h"
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Low-level cache maintenance operations.
|
* Low-level cache maintenance operations.
|
||||||
|
@ -39,27 +35,30 @@
|
||||||
* between which we don't want to be preempted.
|
* between which we don't want to be preempted.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static inline unsigned long l2_start_va(unsigned long paddr)
|
static inline unsigned long l2_get_va(unsigned long paddr)
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
/*
|
/*
|
||||||
* Let's do our own fixmap stuff in a minimal way here.
|
|
||||||
* Because range ops can't be done on physical addresses,
|
* Because range ops can't be done on physical addresses,
|
||||||
* we simply install a virtual mapping for it only for the
|
* we simply install a virtual mapping for it only for the
|
||||||
* TLB lookup to occur, hence no need to flush the untouched
|
* TLB lookup to occur, hence no need to flush the untouched
|
||||||
* memory mapping. This is protected with the disabling of
|
* memory mapping afterwards (note: a cache flush may happen
|
||||||
* interrupts by the caller.
|
* in some circumstances depending on the path taken in kunmap_atomic).
|
||||||
*/
|
*/
|
||||||
unsigned long idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
|
void *vaddr = kmap_atomic_pfn(paddr >> PAGE_SHIFT);
|
||||||
unsigned long vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
return (unsigned long)vaddr + (paddr & ~PAGE_MASK);
|
||||||
set_pte_ext(TOP_PTE(vaddr), pfn_pte(paddr >> PAGE_SHIFT, PAGE_KERNEL), 0);
|
|
||||||
local_flush_tlb_kernel_page(vaddr);
|
|
||||||
return vaddr + (paddr & ~PAGE_MASK);
|
|
||||||
#else
|
#else
|
||||||
return __phys_to_virt(paddr);
|
return __phys_to_virt(paddr);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void l2_put_va(unsigned long vaddr)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_HIGHMEM
|
||||||
|
kunmap_atomic((void *)vaddr);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline void l2_clean_pa(unsigned long addr)
|
static inline void l2_clean_pa(unsigned long addr)
|
||||||
{
|
{
|
||||||
__asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
|
__asm__("mcr p15, 1, %0, c15, c9, 3" : : "r" (addr));
|
||||||
|
@ -76,13 +75,14 @@ static inline void l2_clean_pa_range(unsigned long start, unsigned long end)
|
||||||
*/
|
*/
|
||||||
BUG_ON((start ^ end) >> PAGE_SHIFT);
|
BUG_ON((start ^ end) >> PAGE_SHIFT);
|
||||||
|
|
||||||
raw_local_irq_save(flags);
|
va_start = l2_get_va(start);
|
||||||
va_start = l2_start_va(start);
|
|
||||||
va_end = va_start + (end - start);
|
va_end = va_start + (end - start);
|
||||||
|
raw_local_irq_save(flags);
|
||||||
__asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
|
__asm__("mcr p15, 1, %0, c15, c9, 4\n\t"
|
||||||
"mcr p15, 1, %1, c15, c9, 5"
|
"mcr p15, 1, %1, c15, c9, 5"
|
||||||
: : "r" (va_start), "r" (va_end));
|
: : "r" (va_start), "r" (va_end));
|
||||||
raw_local_irq_restore(flags);
|
raw_local_irq_restore(flags);
|
||||||
|
l2_put_va(va_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void l2_clean_inv_pa(unsigned long addr)
|
static inline void l2_clean_inv_pa(unsigned long addr)
|
||||||
|
@ -106,13 +106,14 @@ static inline void l2_inv_pa_range(unsigned long start, unsigned long end)
|
||||||
*/
|
*/
|
||||||
BUG_ON((start ^ end) >> PAGE_SHIFT);
|
BUG_ON((start ^ end) >> PAGE_SHIFT);
|
||||||
|
|
||||||
raw_local_irq_save(flags);
|
va_start = l2_get_va(start);
|
||||||
va_start = l2_start_va(start);
|
|
||||||
va_end = va_start + (end - start);
|
va_end = va_start + (end - start);
|
||||||
|
raw_local_irq_save(flags);
|
||||||
__asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
|
__asm__("mcr p15, 1, %0, c15, c11, 4\n\t"
|
||||||
"mcr p15, 1, %1, c15, c11, 5"
|
"mcr p15, 1, %1, c15, c11, 5"
|
||||||
: : "r" (va_start), "r" (va_end));
|
: : "r" (va_start), "r" (va_end));
|
||||||
raw_local_irq_restore(flags);
|
raw_local_irq_restore(flags);
|
||||||
|
l2_put_va(va_start);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void l2_inv_all(void)
|
static inline void l2_inv_all(void)
|
||||||
|
|
|
@ -17,14 +17,10 @@
|
||||||
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
*/
|
*/
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
|
#include <linux/highmem.h>
|
||||||
#include <asm/system.h>
|
#include <asm/system.h>
|
||||||
#include <asm/cputype.h>
|
#include <asm/cputype.h>
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/kmap_types.h>
|
|
||||||
#include <asm/fixmap.h>
|
|
||||||
#include <asm/pgtable.h>
|
|
||||||
#include <asm/tlbflush.h>
|
|
||||||
#include "mm.h"
|
|
||||||
|
|
||||||
#define CR_L2 (1 << 26)
|
#define CR_L2 (1 << 26)
|
||||||
|
|
||||||
|
@ -71,16 +67,15 @@ static inline void xsc3_l2_inv_all(void)
|
||||||
dsb();
|
dsb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void l2_unmap_va(unsigned long va)
|
||||||
|
{
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
#define l2_map_save_flags(x) raw_local_save_flags(x)
|
if (va != -1)
|
||||||
#define l2_map_restore_flags(x) raw_local_irq_restore(x)
|
kunmap_atomic((void *)va);
|
||||||
#else
|
|
||||||
#define l2_map_save_flags(x) ((x) = 0)
|
|
||||||
#define l2_map_restore_flags(x) ((void)(x))
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
|
static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va)
|
||||||
unsigned long flags)
|
|
||||||
{
|
{
|
||||||
#ifdef CONFIG_HIGHMEM
|
#ifdef CONFIG_HIGHMEM
|
||||||
unsigned long va = prev_va & PAGE_MASK;
|
unsigned long va = prev_va & PAGE_MASK;
|
||||||
|
@ -89,17 +84,10 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
|
||||||
/*
|
/*
|
||||||
* Switching to a new page. Because cache ops are
|
* Switching to a new page. Because cache ops are
|
||||||
* using virtual addresses only, we must put a mapping
|
* using virtual addresses only, we must put a mapping
|
||||||
* in place for it. We also enable interrupts for a
|
* in place for it.
|
||||||
* short while and disable them again to protect this
|
|
||||||
* mapping.
|
|
||||||
*/
|
*/
|
||||||
unsigned long idx;
|
l2_unmap_va(prev_va);
|
||||||
raw_local_irq_restore(flags);
|
va = (unsigned long)kmap_atomic_pfn(pa >> PAGE_SHIFT);
|
||||||
idx = KM_L2_CACHE + KM_TYPE_NR * smp_processor_id();
|
|
||||||
va = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
|
||||||
raw_local_irq_restore(flags | PSR_I_BIT);
|
|
||||||
set_pte_ext(TOP_PTE(va), pfn_pte(pa >> PAGE_SHIFT, PAGE_KERNEL), 0);
|
|
||||||
local_flush_tlb_kernel_page(va);
|
|
||||||
}
|
}
|
||||||
return va + (pa_offset >> (32 - PAGE_SHIFT));
|
return va + (pa_offset >> (32 - PAGE_SHIFT));
|
||||||
#else
|
#else
|
||||||
|
@ -109,7 +97,7 @@ static inline unsigned long l2_map_va(unsigned long pa, unsigned long prev_va,
|
||||||
|
|
||||||
static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
|
static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
unsigned long vaddr, flags;
|
unsigned long vaddr;
|
||||||
|
|
||||||
if (start == 0 && end == -1ul) {
|
if (start == 0 && end == -1ul) {
|
||||||
xsc3_l2_inv_all();
|
xsc3_l2_inv_all();
|
||||||
|
@ -117,13 +105,12 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
|
||||||
}
|
}
|
||||||
|
|
||||||
vaddr = -1; /* to force the first mapping */
|
vaddr = -1; /* to force the first mapping */
|
||||||
l2_map_save_flags(flags);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clean and invalidate partial first cache line.
|
* Clean and invalidate partial first cache line.
|
||||||
*/
|
*/
|
||||||
if (start & (CACHE_LINE_SIZE - 1)) {
|
if (start & (CACHE_LINE_SIZE - 1)) {
|
||||||
vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr, flags);
|
vaddr = l2_map_va(start & ~(CACHE_LINE_SIZE - 1), vaddr);
|
||||||
xsc3_l2_clean_mva(vaddr);
|
xsc3_l2_clean_mva(vaddr);
|
||||||
xsc3_l2_inv_mva(vaddr);
|
xsc3_l2_inv_mva(vaddr);
|
||||||
start = (start | (CACHE_LINE_SIZE - 1)) + 1;
|
start = (start | (CACHE_LINE_SIZE - 1)) + 1;
|
||||||
|
@ -133,7 +120,7 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
|
||||||
* Invalidate all full cache lines between 'start' and 'end'.
|
* Invalidate all full cache lines between 'start' and 'end'.
|
||||||
*/
|
*/
|
||||||
while (start < (end & ~(CACHE_LINE_SIZE - 1))) {
|
while (start < (end & ~(CACHE_LINE_SIZE - 1))) {
|
||||||
vaddr = l2_map_va(start, vaddr, flags);
|
vaddr = l2_map_va(start, vaddr);
|
||||||
xsc3_l2_inv_mva(vaddr);
|
xsc3_l2_inv_mva(vaddr);
|
||||||
start += CACHE_LINE_SIZE;
|
start += CACHE_LINE_SIZE;
|
||||||
}
|
}
|
||||||
|
@ -142,31 +129,30 @@ static void xsc3_l2_inv_range(unsigned long start, unsigned long end)
|
||||||
* Clean and invalidate partial last cache line.
|
* Clean and invalidate partial last cache line.
|
||||||
*/
|
*/
|
||||||
if (start < end) {
|
if (start < end) {
|
||||||
vaddr = l2_map_va(start, vaddr, flags);
|
vaddr = l2_map_va(start, vaddr);
|
||||||
xsc3_l2_clean_mva(vaddr);
|
xsc3_l2_clean_mva(vaddr);
|
||||||
xsc3_l2_inv_mva(vaddr);
|
xsc3_l2_inv_mva(vaddr);
|
||||||
}
|
}
|
||||||
|
|
||||||
l2_map_restore_flags(flags);
|
l2_unmap_va(vaddr);
|
||||||
|
|
||||||
dsb();
|
dsb();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xsc3_l2_clean_range(unsigned long start, unsigned long end)
|
static void xsc3_l2_clean_range(unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
unsigned long vaddr, flags;
|
unsigned long vaddr;
|
||||||
|
|
||||||
vaddr = -1; /* to force the first mapping */
|
vaddr = -1; /* to force the first mapping */
|
||||||
l2_map_save_flags(flags);
|
|
||||||
|
|
||||||
start &= ~(CACHE_LINE_SIZE - 1);
|
start &= ~(CACHE_LINE_SIZE - 1);
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
vaddr = l2_map_va(start, vaddr, flags);
|
vaddr = l2_map_va(start, vaddr);
|
||||||
xsc3_l2_clean_mva(vaddr);
|
xsc3_l2_clean_mva(vaddr);
|
||||||
start += CACHE_LINE_SIZE;
|
start += CACHE_LINE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
l2_map_restore_flags(flags);
|
l2_unmap_va(vaddr);
|
||||||
|
|
||||||
dsb();
|
dsb();
|
||||||
}
|
}
|
||||||
|
@ -193,7 +179,7 @@ static inline void xsc3_l2_flush_all(void)
|
||||||
|
|
||||||
static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
|
static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
|
||||||
{
|
{
|
||||||
unsigned long vaddr, flags;
|
unsigned long vaddr;
|
||||||
|
|
||||||
if (start == 0 && end == -1ul) {
|
if (start == 0 && end == -1ul) {
|
||||||
xsc3_l2_flush_all();
|
xsc3_l2_flush_all();
|
||||||
|
@ -201,17 +187,16 @@ static void xsc3_l2_flush_range(unsigned long start, unsigned long end)
|
||||||
}
|
}
|
||||||
|
|
||||||
vaddr = -1; /* to force the first mapping */
|
vaddr = -1; /* to force the first mapping */
|
||||||
l2_map_save_flags(flags);
|
|
||||||
|
|
||||||
start &= ~(CACHE_LINE_SIZE - 1);
|
start &= ~(CACHE_LINE_SIZE - 1);
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
vaddr = l2_map_va(start, vaddr, flags);
|
vaddr = l2_map_va(start, vaddr);
|
||||||
xsc3_l2_clean_mva(vaddr);
|
xsc3_l2_clean_mva(vaddr);
|
||||||
xsc3_l2_inv_mva(vaddr);
|
xsc3_l2_inv_mva(vaddr);
|
||||||
start += CACHE_LINE_SIZE;
|
start += CACHE_LINE_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
l2_map_restore_flags(flags);
|
l2_unmap_va(vaddr);
|
||||||
|
|
||||||
dsb();
|
dsb();
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
#include <linux/highmem.h>
|
||||||
|
|
||||||
#include <asm/memory.h>
|
#include <asm/memory.h>
|
||||||
#include <asm/highmem.h>
|
#include <asm/highmem.h>
|
||||||
|
@ -480,10 +481,10 @@ static void dma_cache_maint_page(struct page *page, unsigned long offset,
|
||||||
op(vaddr, len, dir);
|
op(vaddr, len, dir);
|
||||||
kunmap_high(page);
|
kunmap_high(page);
|
||||||
} else if (cache_is_vipt()) {
|
} else if (cache_is_vipt()) {
|
||||||
pte_t saved_pte;
|
/* unmapped pages might still be cached */
|
||||||
vaddr = kmap_high_l1_vipt(page, &saved_pte);
|
vaddr = kmap_atomic(page);
|
||||||
op(vaddr + offset, len, dir);
|
op(vaddr + offset, len, dir);
|
||||||
kunmap_high_l1_vipt(page, saved_pte);
|
kunmap_atomic(vaddr);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
vaddr = page_address(page) + offset;
|
vaddr = page_address(page) + offset;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/pagemap.h>
|
#include <linux/pagemap.h>
|
||||||
|
#include <linux/highmem.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/cachetype.h>
|
#include <asm/cachetype.h>
|
||||||
|
@ -180,10 +181,10 @@ void __flush_dcache_page(struct address_space *mapping, struct page *page)
|
||||||
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
|
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
|
||||||
kunmap_high(page);
|
kunmap_high(page);
|
||||||
} else if (cache_is_vipt()) {
|
} else if (cache_is_vipt()) {
|
||||||
pte_t saved_pte;
|
/* unmapped pages might still be cached */
|
||||||
addr = kmap_high_l1_vipt(page, &saved_pte);
|
addr = kmap_atomic(page);
|
||||||
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
|
__cpuc_flush_dcache_area(addr, PAGE_SIZE);
|
||||||
kunmap_high_l1_vipt(page, saved_pte);
|
kunmap_atomic(addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -140,90 +140,3 @@ struct page *kmap_atomic_to_page(const void *ptr)
|
||||||
pte = TOP_PTE(vaddr);
|
pte = TOP_PTE(vaddr);
|
||||||
return pte_page(*pte);
|
return pte_page(*pte);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_CACHE_VIPT
|
|
||||||
|
|
||||||
#include <linux/percpu.h>
|
|
||||||
|
|
||||||
/*
|
|
||||||
* The VIVT cache of a highmem page is always flushed before the page
|
|
||||||
* is unmapped. Hence unmapped highmem pages need no cache maintenance
|
|
||||||
* in that case.
|
|
||||||
*
|
|
||||||
* However unmapped pages may still be cached with a VIPT cache, and
|
|
||||||
* it is not possible to perform cache maintenance on them using physical
|
|
||||||
* addresses unfortunately. So we have no choice but to set up a temporary
|
|
||||||
* virtual mapping for that purpose.
|
|
||||||
*
|
|
||||||
* Yet this VIPT cache maintenance may be triggered from DMA support
|
|
||||||
* functions which are possibly called from interrupt context. As we don't
|
|
||||||
* want to keep interrupt disabled all the time when such maintenance is
|
|
||||||
* taking place, we therefore allow for some reentrancy by preserving and
|
|
||||||
* restoring the previous fixmap entry before the interrupted context is
|
|
||||||
* resumed. If the reentrancy depth is 0 then there is no need to restore
|
|
||||||
* the previous fixmap, and leaving the current one in place allow it to
|
|
||||||
* be reused the next time without a TLB flush (common with DMA).
|
|
||||||
*/
|
|
||||||
|
|
||||||
static DEFINE_PER_CPU(int, kmap_high_l1_vipt_depth);
|
|
||||||
|
|
||||||
void *kmap_high_l1_vipt(struct page *page, pte_t *saved_pte)
|
|
||||||
{
|
|
||||||
unsigned int idx, cpu;
|
|
||||||
int *depth;
|
|
||||||
unsigned long vaddr, flags;
|
|
||||||
pte_t pte, *ptep;
|
|
||||||
|
|
||||||
if (!in_interrupt())
|
|
||||||
preempt_disable();
|
|
||||||
|
|
||||||
cpu = smp_processor_id();
|
|
||||||
depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
|
|
||||||
|
|
||||||
idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
|
|
||||||
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
|
||||||
ptep = TOP_PTE(vaddr);
|
|
||||||
pte = mk_pte(page, kmap_prot);
|
|
||||||
|
|
||||||
raw_local_irq_save(flags);
|
|
||||||
(*depth)++;
|
|
||||||
if (pte_val(*ptep) == pte_val(pte)) {
|
|
||||||
*saved_pte = pte;
|
|
||||||
} else {
|
|
||||||
*saved_pte = *ptep;
|
|
||||||
set_pte_ext(ptep, pte, 0);
|
|
||||||
local_flush_tlb_kernel_page(vaddr);
|
|
||||||
}
|
|
||||||
raw_local_irq_restore(flags);
|
|
||||||
|
|
||||||
return (void *)vaddr;
|
|
||||||
}
|
|
||||||
|
|
||||||
void kunmap_high_l1_vipt(struct page *page, pte_t saved_pte)
|
|
||||||
{
|
|
||||||
unsigned int idx, cpu = smp_processor_id();
|
|
||||||
int *depth = &per_cpu(kmap_high_l1_vipt_depth, cpu);
|
|
||||||
unsigned long vaddr, flags;
|
|
||||||
pte_t pte, *ptep;
|
|
||||||
|
|
||||||
idx = KM_L1_CACHE + KM_TYPE_NR * cpu;
|
|
||||||
vaddr = __fix_to_virt(FIX_KMAP_BEGIN + idx);
|
|
||||||
ptep = TOP_PTE(vaddr);
|
|
||||||
pte = mk_pte(page, kmap_prot);
|
|
||||||
|
|
||||||
BUG_ON(pte_val(*ptep) != pte_val(pte));
|
|
||||||
BUG_ON(*depth <= 0);
|
|
||||||
|
|
||||||
raw_local_irq_save(flags);
|
|
||||||
(*depth)--;
|
|
||||||
if (*depth != 0 && pte_val(pte) != pte_val(saved_pte)) {
|
|
||||||
set_pte_ext(ptep, saved_pte, 0);
|
|
||||||
local_flush_tlb_kernel_page(vaddr);
|
|
||||||
}
|
|
||||||
raw_local_irq_restore(flags);
|
|
||||||
|
|
||||||
if (!in_interrupt())
|
|
||||||
preempt_enable();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* CONFIG_CPU_CACHE_VIPT */
|
|
||||||
|
|
Loading…
Reference in a new issue