aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Zankel <chris@zankel.net>2016-01-21 00:17:09 -0500
committerChris Zankel <chris@zankel.net>2016-01-21 00:17:09 -0500
commitbb2f3486041aa126cb7ce4929f1e45ede85f0051 (patch)
tree144450f64cc6ad20d72026ed406ccedb524720d9
parentd1208404dd477c142680437137c9996b95bfd508 (diff)
parent5bb8def55dc562d81ec582368b4f27c8d432fbd5 (diff)
Merge tag 'xtensa-for-next-20160111' of git://github.com/jcmvbkbc/linux-xtensa
Xtensa improvements for 4.5: - control whether perf IRQ is treated as NMI from Kconfig; - implement ioremap for regions outside KIO segment.
-rw-r--r--arch/xtensa/Kconfig16
-rw-r--r--arch/xtensa/include/asm/io.h16
-rw-r--r--arch/xtensa/include/asm/processor.h12
-rw-r--r--arch/xtensa/include/asm/timex.h9
-rw-r--r--arch/xtensa/kernel/traps.c27
-rw-r--r--arch/xtensa/mm/Makefile2
-rw-r--r--arch/xtensa/mm/ioremap.c68
7 files changed, 133 insertions, 17 deletions
diff --git a/arch/xtensa/Kconfig b/arch/xtensa/Kconfig
index 82044f732323..128e63d3a632 100644
--- a/arch/xtensa/Kconfig
+++ b/arch/xtensa/Kconfig
@@ -139,6 +139,22 @@ config XTENSA_VARIANT_HAVE_PERF_EVENTS
139 139
140 If unsure, say N. 140 If unsure, say N.
141 141
142config XTENSA_FAKE_NMI
143 bool "Treat PMM IRQ as NMI"
144 depends on XTENSA_VARIANT_HAVE_PERF_EVENTS
145 default n
146 help
147 If PMM IRQ is the only IRQ at EXCM level it is safe to
148 treat it as NMI, which improves accuracy of profiling.
149
150 If there are other interrupts at or above PMM IRQ priority level
151 but not above the EXCM level, PMM IRQ still may be treated as NMI,
152 but only if these IRQs are not used. There will be a build warning
153 saying that this is not safe, and a bugcheck if one of these IRQs
154 actually fire.
155
156 If unsure, say N.
157
142config XTENSA_UNALIGNED_USER 158config XTENSA_UNALIGNED_USER
143 bool "Unaligned memory access in use space" 159 bool "Unaligned memory access in use space"
144 help 160 help
diff --git a/arch/xtensa/include/asm/io.h b/arch/xtensa/include/asm/io.h
index 74fed0b4e2c2..c38e5a732d86 100644
--- a/arch/xtensa/include/asm/io.h
+++ b/arch/xtensa/include/asm/io.h
@@ -25,9 +25,12 @@
25 25
26#ifdef CONFIG_MMU 26#ifdef CONFIG_MMU
27 27
28void __iomem *xtensa_ioremap_nocache(unsigned long addr, unsigned long size);
29void __iomem *xtensa_ioremap_cache(unsigned long addr, unsigned long size);
30void xtensa_iounmap(volatile void __iomem *addr);
31
28/* 32/*
29 * Return the virtual address for the specified bus memory. 33 * Return the virtual address for the specified bus memory.
30 * Note that we currently don't support any address outside the KIO segment.
31 */ 34 */
32static inline void __iomem *ioremap_nocache(unsigned long offset, 35static inline void __iomem *ioremap_nocache(unsigned long offset,
33 unsigned long size) 36 unsigned long size)
@@ -36,7 +39,7 @@ static inline void __iomem *ioremap_nocache(unsigned long offset,
36 && offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE) 39 && offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE)
37 return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_BYPASS_VADDR); 40 return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_BYPASS_VADDR);
38 else 41 else
39 BUG(); 42 return xtensa_ioremap_nocache(offset, size);
40} 43}
41 44
42static inline void __iomem *ioremap_cache(unsigned long offset, 45static inline void __iomem *ioremap_cache(unsigned long offset,
@@ -46,7 +49,7 @@ static inline void __iomem *ioremap_cache(unsigned long offset,
46 && offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE) 49 && offset - XCHAL_KIO_PADDR < XCHAL_KIO_SIZE)
47 return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_CACHED_VADDR); 50 return (void*)(offset-XCHAL_KIO_PADDR+XCHAL_KIO_CACHED_VADDR);
48 else 51 else
49 BUG(); 52 return xtensa_ioremap_cache(offset, size);
50} 53}
51#define ioremap_cache ioremap_cache 54#define ioremap_cache ioremap_cache
52 55
@@ -60,6 +63,13 @@ static inline void __iomem *ioremap(unsigned long offset, unsigned long size)
60 63
61static inline void iounmap(volatile void __iomem *addr) 64static inline void iounmap(volatile void __iomem *addr)
62{ 65{
66 unsigned long va = (unsigned long) addr;
67
68 if (!(va >= XCHAL_KIO_CACHED_VADDR &&
69 va - XCHAL_KIO_CACHED_VADDR < XCHAL_KIO_SIZE) &&
70 !(va >= XCHAL_KIO_BYPASS_VADDR &&
71 va - XCHAL_KIO_BYPASS_VADDR < XCHAL_KIO_SIZE))
72 xtensa_iounmap(addr);
63} 73}
64 74
65#define virt_to_bus virt_to_phys 75#define virt_to_bus virt_to_phys
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h
index 83e2e4bc01ba..744ecf0dc3a4 100644
--- a/arch/xtensa/include/asm/processor.h
+++ b/arch/xtensa/include/asm/processor.h
@@ -78,22 +78,20 @@
78#define XTENSA_INTLEVEL_MASK(level) _XTENSA_INTLEVEL_MASK(level) 78#define XTENSA_INTLEVEL_MASK(level) _XTENSA_INTLEVEL_MASK(level)
79#define _XTENSA_INTLEVEL_MASK(level) (XCHAL_INTLEVEL##level##_MASK) 79#define _XTENSA_INTLEVEL_MASK(level) (XCHAL_INTLEVEL##level##_MASK)
80 80
81#define IS_POW2(v) (((v) & ((v) - 1)) == 0) 81#define XTENSA_INTLEVEL_ANDBELOW_MASK(l) _XTENSA_INTLEVEL_ANDBELOW_MASK(l)
82#define _XTENSA_INTLEVEL_ANDBELOW_MASK(l) (XCHAL_INTLEVEL##l##_ANDBELOW_MASK)
82 83
83#define PROFILING_INTLEVEL XTENSA_INT_LEVEL(XCHAL_PROFILING_INTERRUPT) 84#define PROFILING_INTLEVEL XTENSA_INT_LEVEL(XCHAL_PROFILING_INTERRUPT)
84 85
85/* LOCKLEVEL defines the interrupt level that masks all 86/* LOCKLEVEL defines the interrupt level that masks all
86 * general-purpose interrupts. 87 * general-purpose interrupts.
87 */ 88 */
88#if defined(CONFIG_XTENSA_VARIANT_HAVE_PERF_EVENTS) && \ 89#if defined(CONFIG_XTENSA_FAKE_NMI) && defined(XCHAL_PROFILING_INTERRUPT)
89 defined(XCHAL_PROFILING_INTERRUPT) && \ 90#define LOCKLEVEL (PROFILING_INTLEVEL - 1)
90 PROFILING_INTLEVEL == XCHAL_EXCM_LEVEL && \
91 XCHAL_EXCM_LEVEL > 1 && \
92 IS_POW2(XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL))
93#define LOCKLEVEL (XCHAL_EXCM_LEVEL - 1)
94#else 91#else
95#define LOCKLEVEL XCHAL_EXCM_LEVEL 92#define LOCKLEVEL XCHAL_EXCM_LEVEL
96#endif 93#endif
94
97#define TOPLEVEL XCHAL_EXCM_LEVEL 95#define TOPLEVEL XCHAL_EXCM_LEVEL
98#define XTENSA_FAKE_NMI (LOCKLEVEL < TOPLEVEL) 96#define XTENSA_FAKE_NMI (LOCKLEVEL < TOPLEVEL)
99 97
diff --git a/arch/xtensa/include/asm/timex.h b/arch/xtensa/include/asm/timex.h
index ca929e6a38b5..f9b389d4e973 100644
--- a/arch/xtensa/include/asm/timex.h
+++ b/arch/xtensa/include/asm/timex.h
@@ -12,19 +12,16 @@
12#include <asm/processor.h> 12#include <asm/processor.h>
13#include <linux/stringify.h> 13#include <linux/stringify.h>
14 14
15#define _INTLEVEL(x) XCHAL_INT ## x ## _LEVEL
16#define INTLEVEL(x) _INTLEVEL(x)
17
18#if XCHAL_NUM_TIMERS > 0 && \ 15#if XCHAL_NUM_TIMERS > 0 && \
19 INTLEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL 16 XTENSA_INT_LEVEL(XCHAL_TIMER0_INTERRUPT) <= XCHAL_EXCM_LEVEL
20# define LINUX_TIMER 0 17# define LINUX_TIMER 0
21# define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT 18# define LINUX_TIMER_INT XCHAL_TIMER0_INTERRUPT
22#elif XCHAL_NUM_TIMERS > 1 && \ 19#elif XCHAL_NUM_TIMERS > 1 && \
23 INTLEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL 20 XTENSA_INT_LEVEL(XCHAL_TIMER1_INTERRUPT) <= XCHAL_EXCM_LEVEL
24# define LINUX_TIMER 1 21# define LINUX_TIMER 1
25# define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT 22# define LINUX_TIMER_INT XCHAL_TIMER1_INTERRUPT
26#elif XCHAL_NUM_TIMERS > 2 && \ 23#elif XCHAL_NUM_TIMERS > 2 && \
27 INTLEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL 24 XTENSA_INT_LEVEL(XCHAL_TIMER2_INTERRUPT) <= XCHAL_EXCM_LEVEL
28# define LINUX_TIMER 2 25# define LINUX_TIMER 2
29# define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT 26# define LINUX_TIMER_INT XCHAL_TIMER2_INTERRUPT
30#else 27#else
diff --git a/arch/xtensa/kernel/traps.c b/arch/xtensa/kernel/traps.c
index 42d441f7898b..be0cae8082c7 100644
--- a/arch/xtensa/kernel/traps.c
+++ b/arch/xtensa/kernel/traps.c
@@ -205,6 +205,32 @@ extern void do_IRQ(int, struct pt_regs *);
205 205
206#if XTENSA_FAKE_NMI 206#if XTENSA_FAKE_NMI
207 207
208#define IS_POW2(v) (((v) & ((v) - 1)) == 0)
209
210#if !(PROFILING_INTLEVEL == XCHAL_EXCM_LEVEL && \
211 IS_POW2(XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL)))
212#warning "Fake NMI is requested for PMM, but there are other IRQs at or above its level."
213#warning "Fake NMI will be used, but there will be a bugcheck if one of those IRQs fire."
214
215static inline void check_valid_nmi(void)
216{
217 unsigned intread = get_sr(interrupt);
218 unsigned intenable = get_sr(intenable);
219
220 BUG_ON(intread & intenable &
221 ~(XTENSA_INTLEVEL_ANDBELOW_MASK(PROFILING_INTLEVEL) ^
222 XTENSA_INTLEVEL_MASK(PROFILING_INTLEVEL) ^
223 BIT(XCHAL_PROFILING_INTERRUPT)));
224}
225
226#else
227
228static inline void check_valid_nmi(void)
229{
230}
231
232#endif
233
208irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id); 234irqreturn_t xtensa_pmu_irq_handler(int irq, void *dev_id);
209 235
210DEFINE_PER_CPU(unsigned long, nmi_count); 236DEFINE_PER_CPU(unsigned long, nmi_count);
@@ -219,6 +245,7 @@ void do_nmi(struct pt_regs *regs)
219 old_regs = set_irq_regs(regs); 245 old_regs = set_irq_regs(regs);
220 nmi_enter(); 246 nmi_enter();
221 ++*this_cpu_ptr(&nmi_count); 247 ++*this_cpu_ptr(&nmi_count);
248 check_valid_nmi();
222 xtensa_pmu_irq_handler(0, NULL); 249 xtensa_pmu_irq_handler(0, NULL);
223 nmi_exit(); 250 nmi_exit();
224 set_irq_regs(old_regs); 251 set_irq_regs(old_regs);
diff --git a/arch/xtensa/mm/Makefile b/arch/xtensa/mm/Makefile
index e601e2fbe8e6..0b3d296a016a 100644
--- a/arch/xtensa/mm/Makefile
+++ b/arch/xtensa/mm/Makefile
@@ -3,5 +3,5 @@
3# 3#
4 4
5obj-y := init.o misc.o 5obj-y := init.o misc.o
6obj-$(CONFIG_MMU) += cache.o fault.o mmu.o tlb.o 6obj-$(CONFIG_MMU) += cache.o fault.o ioremap.o mmu.o tlb.o
7obj-$(CONFIG_HIGHMEM) += highmem.o 7obj-$(CONFIG_HIGHMEM) += highmem.o
diff --git a/arch/xtensa/mm/ioremap.c b/arch/xtensa/mm/ioremap.c
new file mode 100644
index 000000000000..d89c3c5fd962
--- /dev/null
+++ b/arch/xtensa/mm/ioremap.c
@@ -0,0 +1,68 @@
1/*
2 * ioremap implementation.
3 *
4 * Copyright (C) 2015 Cadence Design Systems Inc.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 */
10
11#include <linux/io.h>
12#include <linux/vmalloc.h>
13#include <asm/cacheflush.h>
14#include <asm/io.h>
15#include <asm/pgtable.h>
16
17static void __iomem *xtensa_ioremap(unsigned long paddr, unsigned long size,
18 pgprot_t prot)
19{
20 unsigned long offset = paddr & ~PAGE_MASK;
21 unsigned long pfn = __phys_to_pfn(paddr);
22 struct vm_struct *area;
23 unsigned long vaddr;
24 int err;
25
26 paddr &= PAGE_MASK;
27
28 WARN_ON(pfn_valid(pfn));
29
30 size = PAGE_ALIGN(offset + size);
31
32 area = get_vm_area(size, VM_IOREMAP);
33 if (!area)
34 return NULL;
35
36 vaddr = (unsigned long)area->addr;
37 area->phys_addr = paddr;
38
39 err = ioremap_page_range(vaddr, vaddr + size, paddr, prot);
40
41 if (err) {
42 vunmap((void *)vaddr);
43 return NULL;
44 }
45
46 flush_cache_vmap(vaddr, vaddr + size);
47 return (void __iomem *)(offset + vaddr);
48}
49
50void __iomem *xtensa_ioremap_nocache(unsigned long addr, unsigned long size)
51{
52 return xtensa_ioremap(addr, size, pgprot_noncached(PAGE_KERNEL));
53}
54EXPORT_SYMBOL(xtensa_ioremap_nocache);
55
56void __iomem *xtensa_ioremap_cache(unsigned long addr, unsigned long size)
57{
58 return xtensa_ioremap(addr, size, PAGE_KERNEL);
59}
60EXPORT_SYMBOL(xtensa_ioremap_cache);
61
62void xtensa_iounmap(volatile void __iomem *io_addr)
63{
64 void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
65
66 vunmap(addr);
67}
68EXPORT_SYMBOL(xtensa_iounmap);