aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile')
-rw-r--r--arch/tile/include/asm/Kbuild1
-rw-r--r--arch/tile/include/asm/irq_work.h14
-rw-r--r--arch/tile/include/asm/smp.h1
-rw-r--r--arch/tile/kernel/smp.c32
4 files changed, 46 insertions, 2 deletions
diff --git a/arch/tile/include/asm/Kbuild b/arch/tile/include/asm/Kbuild
index b4c488b65745..f5433e0e34e0 100644
--- a/arch/tile/include/asm/Kbuild
+++ b/arch/tile/include/asm/Kbuild
@@ -16,7 +16,6 @@ generic-y += ioctl.h
16generic-y += ioctls.h 16generic-y += ioctls.h
17generic-y += ipcbuf.h 17generic-y += ipcbuf.h
18generic-y += irq_regs.h 18generic-y += irq_regs.h
19generic-y += irq_work.h
20generic-y += local.h 19generic-y += local.h
21generic-y += local64.h 20generic-y += local64.h
22generic-y += mcs_spinlock.h 21generic-y += mcs_spinlock.h
diff --git a/arch/tile/include/asm/irq_work.h b/arch/tile/include/asm/irq_work.h
new file mode 100644
index 000000000000..48af33a61a2c
--- /dev/null
+++ b/arch/tile/include/asm/irq_work.h
@@ -0,0 +1,14 @@
1#ifndef __ASM_IRQ_WORK_H
2#define __ASM_IRQ_WORK_H
3
4static inline bool arch_irq_work_has_interrupt(void)
5{
6#ifdef CONFIG_SMP
7 extern bool self_interrupt_ok;
8 return self_interrupt_ok;
9#else
10 return false;
11#endif
12}
13
14#endif /* __ASM_IRQ_WORK_H */
diff --git a/arch/tile/include/asm/smp.h b/arch/tile/include/asm/smp.h
index 9a326b64f7ae..735e7f144733 100644
--- a/arch/tile/include/asm/smp.h
+++ b/arch/tile/include/asm/smp.h
@@ -69,6 +69,7 @@ static inline int xy_to_cpu(int x, int y)
69#define MSG_TAG_STOP_CPU 2 69#define MSG_TAG_STOP_CPU 2
70#define MSG_TAG_CALL_FUNCTION_MANY 3 70#define MSG_TAG_CALL_FUNCTION_MANY 3
71#define MSG_TAG_CALL_FUNCTION_SINGLE 4 71#define MSG_TAG_CALL_FUNCTION_SINGLE 4
72#define MSG_TAG_IRQ_WORK 5
72 73
73/* Hook for the generic smp_call_function_many() routine. */ 74/* Hook for the generic smp_call_function_many() routine. */
74static inline void arch_send_call_function_ipi_mask(struct cpumask *mask) 75static inline void arch_send_call_function_ipi_mask(struct cpumask *mask)
diff --git a/arch/tile/kernel/smp.c b/arch/tile/kernel/smp.c
index d3c4ed780ce2..07e3ff5cc740 100644
--- a/arch/tile/kernel/smp.c
+++ b/arch/tile/kernel/smp.c
@@ -18,6 +18,7 @@
18#include <linux/interrupt.h> 18#include <linux/interrupt.h>
19#include <linux/io.h> 19#include <linux/io.h>
20#include <linux/irq.h> 20#include <linux/irq.h>
21#include <linux/irq_work.h>
21#include <linux/module.h> 22#include <linux/module.h>
22#include <asm/cacheflush.h> 23#include <asm/cacheflush.h>
23#include <asm/homecache.h> 24#include <asm/homecache.h>
@@ -33,6 +34,8 @@ EXPORT_SYMBOL(smp_topology);
33static unsigned long __iomem *ipi_mappings[NR_CPUS]; 34static unsigned long __iomem *ipi_mappings[NR_CPUS];
34#endif 35#endif
35 36
37/* Does messaging work correctly to the local cpu? */
38bool self_interrupt_ok;
36 39
37/* 40/*
38 * Top-level send_IPI*() functions to send messages to other cpus. 41 * Top-level send_IPI*() functions to send messages to other cpus.
@@ -147,6 +150,10 @@ void evaluate_message(int tag)
147 generic_smp_call_function_single_interrupt(); 150 generic_smp_call_function_single_interrupt();
148 break; 151 break;
149 152
153 case MSG_TAG_IRQ_WORK: /* Invoke IRQ work */
154 irq_work_run();
155 break;
156
150 default: 157 default:
151 panic("Unknown IPI message tag %d", tag); 158 panic("Unknown IPI message tag %d", tag);
152 break; 159 break;
@@ -186,6 +193,15 @@ void flush_icache_range(unsigned long start, unsigned long end)
186EXPORT_SYMBOL(flush_icache_range); 193EXPORT_SYMBOL(flush_icache_range);
187 194
188 195
196#ifdef CONFIG_IRQ_WORK
197void arch_irq_work_raise(void)
198{
199 if (arch_irq_work_has_interrupt())
200 send_IPI_single(smp_processor_id(), MSG_TAG_IRQ_WORK);
201}
202#endif
203
204
189/* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */ 205/* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
190static irqreturn_t handle_reschedule_ipi(int irq, void *token) 206static irqreturn_t handle_reschedule_ipi(int irq, void *token)
191{ 207{
@@ -203,8 +219,22 @@ static struct irqaction resched_action = {
203 219
204void __init ipi_init(void) 220void __init ipi_init(void)
205{ 221{
222 int cpu = smp_processor_id();
223 HV_Recipient recip = { .y = cpu_y(cpu), .x = cpu_x(cpu),
224 .state = HV_TO_BE_SENT };
225 int tag = MSG_TAG_CALL_FUNCTION_SINGLE;
226
227 /*
228 * Test if we can message ourselves for arch_irq_work_raise.
229 * This functionality is only available in the Tilera hypervisor
230 * in versions 4.3.4 and following.
231 */
232 if (hv_send_message(&recip, 1, (HV_VirtAddr)&tag, sizeof(tag)) == 1)
233 self_interrupt_ok = true;
234 else
235 pr_warn("Older hypervisor: disabling fast irq_work_raise\n");
236
206#if CHIP_HAS_IPI() 237#if CHIP_HAS_IPI()
207 int cpu;
208 /* Map IPI trigger MMIO addresses. */ 238 /* Map IPI trigger MMIO addresses. */
209 for_each_possible_cpu(cpu) { 239 for_each_possible_cpu(cpu) {
210 HV_Coord tile; 240 HV_Coord tile;