aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/kernel')
-rw-r--r--arch/tile/kernel/smp.c32
1 files changed, 31 insertions, 1 deletions
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;