2012-03-05 15:49:29 +04:00
/*
* Based on arch / arm / kernel / irq . c
*
* Copyright ( C ) 1992 Linus Torvalds
* Modifications for ARM processor Copyright ( C ) 1995 - 2000 Russell King .
* Support for Dynamic Tick Timer Copyright ( C ) 2004 - 2005 Nokia Corporation .
* Dynamic Tick Timer written by Tony Lindgren < tony @ atomide . com > and
* Tuukka Tikkanen < tuukka . tikkanen @ elektrobit . com > .
* Copyright ( C ) 2012 ARM Ltd .
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*/
# include <linux/kernel_stat.h>
# include <linux/irq.h>
2017-07-21 16:25:33 +03:00
# include <linux/memory.h>
2012-03-05 15:49:29 +04:00
# include <linux/smp.h>
# include <linux/init.h>
2013-01-14 16:39:31 +04:00
# include <linux/irqchip.h>
2012-03-05 15:49:29 +04:00
# include <linux/seq_file.h>
2017-07-21 16:25:33 +03:00
# include <linux/vmalloc.h>
2018-01-08 18:38:10 +03:00
# include <asm/vmap_stack.h>
2012-03-05 15:49:29 +04:00
unsigned long irq_err_count ;
2017-07-31 23:17:03 +03:00
DEFINE_PER_CPU ( unsigned long * , irq_stack_ptr ) ;
2015-12-04 14:02:26 +03:00
2012-03-05 15:49:29 +04:00
int arch_show_interrupts ( struct seq_file * p , int prec )
{
show_ipi_list ( p , prec ) ;
seq_printf ( p , " %*s: %10lu \n " , prec , " Err " , irq_err_count ) ;
return 0 ;
}
2014-11-22 00:50:38 +03:00
void ( * handle_arch_irq ) ( struct pt_regs * ) = NULL ;
2013-01-14 16:39:31 +04:00
void __init set_handle_irq ( void ( * handle_irq ) ( struct pt_regs * ) )
{
if ( handle_arch_irq )
return ;
handle_arch_irq = handle_irq ;
}
2012-03-05 15:49:29 +04:00
2017-07-21 16:25:33 +03:00
# ifdef CONFIG_VMAP_STACK
static void init_irq_stacks ( void )
{
int cpu ;
unsigned long * p ;
for_each_possible_cpu ( cpu ) {
2018-01-08 18:38:10 +03:00
p = arch_alloc_vmap_stack ( IRQ_STACK_SIZE , cpu_to_node ( cpu ) ) ;
2017-07-21 16:25:33 +03:00
per_cpu ( irq_stack_ptr , cpu ) = p ;
}
}
# else
/* irq stack only needs to be 16 byte aligned - not IRQ_STACK_SIZE aligned. */
DEFINE_PER_CPU_ALIGNED ( unsigned long [ IRQ_STACK_SIZE / sizeof ( long ) ] , irq_stack ) ;
2017-07-31 23:17:03 +03:00
static void init_irq_stacks ( void )
{
int cpu ;
for_each_possible_cpu ( cpu )
per_cpu ( irq_stack_ptr , cpu ) = per_cpu ( irq_stack , cpu ) ;
}
2017-07-21 16:25:33 +03:00
# endif
2017-07-31 23:17:03 +03:00
2012-03-05 15:49:29 +04:00
void __init init_IRQ ( void )
{
2017-07-31 23:17:03 +03:00
init_irq_stacks ( ) ;
2013-01-14 16:39:31 +04:00
irqchip_init ( ) ;
2012-03-05 15:49:29 +04:00
if ( ! handle_arch_irq )
panic ( " No interrupt controller found. " ) ;
}