@ -18,6 +18,7 @@
# include <linux/interrupt.h>
# include <linux/interrupt.h>
# include <linux/io.h>
# include <linux/io.h>
# include <linux/irq.h>
# include <linux/irq.h>
# include <linux/irq_work.h>
# include <linux/module.h>
# include <linux/module.h>
# include <asm/cacheflush.h>
# include <asm/cacheflush.h>
# include <asm/homecache.h>
# include <asm/homecache.h>
@ -33,6 +34,8 @@ EXPORT_SYMBOL(smp_topology);
static unsigned long __iomem * ipi_mappings [ NR_CPUS ] ;
static unsigned long __iomem * ipi_mappings [ NR_CPUS ] ;
# endif
# endif
/* Does messaging work correctly to the local cpu? */
bool self_interrupt_ok ;
/*
/*
* Top - level send_IPI * ( ) functions to send messages to other cpus .
* Top - level send_IPI * ( ) functions to send messages to other cpus .
@ -147,6 +150,10 @@ void evaluate_message(int tag)
generic_smp_call_function_single_interrupt ( ) ;
generic_smp_call_function_single_interrupt ( ) ;
break ;
break ;
case MSG_TAG_IRQ_WORK : /* Invoke IRQ work */
irq_work_run ( ) ;
break ;
default :
default :
panic ( " Unknown IPI message tag %d " , tag ) ;
panic ( " Unknown IPI message tag %d " , tag ) ;
break ;
break ;
@ -186,6 +193,15 @@ void flush_icache_range(unsigned long start, unsigned long end)
EXPORT_SYMBOL ( flush_icache_range ) ;
EXPORT_SYMBOL ( flush_icache_range ) ;
# ifdef CONFIG_IRQ_WORK
void arch_irq_work_raise ( void )
{
if ( arch_irq_work_has_interrupt ( ) )
send_IPI_single ( smp_processor_id ( ) , MSG_TAG_IRQ_WORK ) ;
}
# endif
/* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
/* Called when smp_send_reschedule() triggers IRQ_RESCHEDULE. */
static irqreturn_t handle_reschedule_ipi ( int irq , void * token )
static irqreturn_t handle_reschedule_ipi ( int irq , void * token )
{
{
@ -203,8 +219,22 @@ static struct irqaction resched_action = {
void __init ipi_init ( void )
void __init ipi_init ( void )
{
{
int cpu = smp_processor_id ( ) ;
HV_Recipient recip = { . y = cpu_y ( cpu ) , . x = cpu_x ( cpu ) ,
. state = HV_TO_BE_SENT } ;
int tag = MSG_TAG_CALL_FUNCTION_SINGLE ;
/*
* Test if we can message ourselves for arch_irq_work_raise .
* This functionality is only available in the Tilera hypervisor
* in versions 4.3 .4 and following .
*/
if ( hv_send_message ( & recip , 1 , ( HV_VirtAddr ) & tag , sizeof ( tag ) ) = = 1 )
self_interrupt_ok = true ;
else
pr_warn ( " Older hypervisor: disabling fast irq_work_raise \n " ) ;
# if CHIP_HAS_IPI()
# if CHIP_HAS_IPI()
int cpu ;
/* Map IPI trigger MMIO addresses. */
/* Map IPI trigger MMIO addresses. */
for_each_possible_cpu ( cpu ) {
for_each_possible_cpu ( cpu ) {
HV_Coord tile ;
HV_Coord tile ;