2012-03-30 22:47:00 +04:00
# include <linux/kernel.h>
# include <linux/string.h>
2012-07-06 15:28:37 +04:00
# include <linux/cpumask.h>
2012-03-30 22:47:00 +04:00
# include <linux/errno.h>
2012-07-06 15:28:37 +04:00
# include <linux/msi.h>
# include <asm/hw_irq.h>
# include <asm/irq_remapping.h>
2012-03-30 22:47:00 +04:00
2012-03-30 22:47:08 +04:00
# include "irq_remapping.h"
2012-03-30 22:47:00 +04:00
2012-03-30 22:47:07 +04:00
int irq_remapping_enabled ;
2012-03-30 22:47:00 +04:00
2012-03-30 22:47:07 +04:00
int disable_irq_remap ;
2012-03-30 22:47:00 +04:00
int disable_sourceid_checking ;
int no_x2apic_optout ;
static struct irq_remap_ops * remap_ops ;
static __init int setup_nointremap ( char * str )
{
2012-03-30 22:47:07 +04:00
disable_irq_remap = 1 ;
2012-03-30 22:47:00 +04:00
return 0 ;
}
early_param ( " nointremap " , setup_nointremap ) ;
2012-03-30 22:47:07 +04:00
static __init int setup_irqremap ( char * str )
2012-03-30 22:47:00 +04:00
{
if ( ! str )
return - EINVAL ;
while ( * str ) {
if ( ! strncmp ( str , " on " , 2 ) )
2012-03-30 22:47:07 +04:00
disable_irq_remap = 0 ;
2012-03-30 22:47:00 +04:00
else if ( ! strncmp ( str , " off " , 3 ) )
2012-03-30 22:47:07 +04:00
disable_irq_remap = 1 ;
2012-03-30 22:47:00 +04:00
else if ( ! strncmp ( str , " nosid " , 5 ) )
disable_sourceid_checking = 1 ;
else if ( ! strncmp ( str , " no_x2apic_optout " , 16 ) )
no_x2apic_optout = 1 ;
str + = strcspn ( str , " , " ) ;
while ( * str = = ' , ' )
str + + ;
}
return 0 ;
}
2012-03-30 22:47:07 +04:00
early_param ( " intremap " , setup_irqremap ) ;
2012-03-30 22:47:00 +04:00
2012-03-30 22:47:07 +04:00
void __init setup_irq_remapping_ops ( void )
2012-03-30 22:47:00 +04:00
{
remap_ops = & intel_irq_remap_ops ;
}
2012-03-30 22:47:07 +04:00
int irq_remapping_supported ( void )
2012-03-30 22:47:00 +04:00
{
2012-03-30 22:47:07 +04:00
if ( disable_irq_remap )
2012-03-30 22:47:00 +04:00
return 0 ;
if ( ! remap_ops | | ! remap_ops - > supported )
return 0 ;
return remap_ops - > supported ( ) ;
}
2012-03-30 22:47:07 +04:00
int __init irq_remapping_prepare ( void )
2012-03-30 22:47:00 +04:00
{
2012-03-30 22:47:07 +04:00
if ( ! remap_ops | | ! remap_ops - > prepare )
2012-03-30 22:47:00 +04:00
return - ENODEV ;
2012-03-30 22:47:07 +04:00
return remap_ops - > prepare ( ) ;
2012-03-30 22:47:00 +04:00
}
2012-03-30 22:47:07 +04:00
int __init irq_remapping_enable ( void )
2012-03-30 22:47:00 +04:00
{
2012-03-30 22:47:07 +04:00
if ( ! remap_ops | | ! remap_ops - > enable )
2012-03-30 22:47:00 +04:00
return - ENODEV ;
2012-03-30 22:47:07 +04:00
return remap_ops - > enable ( ) ;
2012-03-30 22:47:00 +04:00
}
2012-03-30 22:47:01 +04:00
2012-03-30 22:47:07 +04:00
void irq_remapping_disable ( void )
2012-03-30 22:47:01 +04:00
{
2012-03-30 22:47:07 +04:00
if ( ! remap_ops | | ! remap_ops - > disable )
2012-03-30 22:47:01 +04:00
return ;
2012-03-30 22:47:07 +04:00
remap_ops - > disable ( ) ;
2012-03-30 22:47:01 +04:00
}
2012-03-30 22:47:07 +04:00
int irq_remapping_reenable ( int mode )
2012-03-30 22:47:01 +04:00
{
2012-03-30 22:47:07 +04:00
if ( ! remap_ops | | ! remap_ops - > reenable )
2012-03-30 22:47:01 +04:00
return 0 ;
2012-03-30 22:47:07 +04:00
return remap_ops - > reenable ( mode ) ;
2012-03-30 22:47:01 +04:00
}
2012-03-30 22:47:07 +04:00
int __init irq_remap_enable_fault_handling ( void )
2012-03-30 22:47:01 +04:00
{
if ( ! remap_ops | | ! remap_ops - > enable_faulting )
return - ENODEV ;
return remap_ops - > enable_faulting ( ) ;
}
2012-03-30 22:47:02 +04:00
2012-03-30 22:47:07 +04:00
int setup_ioapic_remapped_entry ( int irq ,
struct IO_APIC_route_entry * entry ,
unsigned int destination , int vector ,
struct io_apic_irq_attr * attr )
2012-03-30 22:47:02 +04:00
{
if ( ! remap_ops | | ! remap_ops - > setup_ioapic_entry )
return - ENODEV ;
return remap_ops - > setup_ioapic_entry ( irq , entry , destination ,
vector , attr ) ;
}
2012-03-30 22:47:03 +04:00
2012-03-30 22:47:07 +04:00
int set_remapped_irq_affinity ( struct irq_data * data , const struct cpumask * mask ,
bool force )
2012-03-30 22:47:03 +04:00
{
2012-06-15 05:28:49 +04:00
if ( ! config_enabled ( CONFIG_SMP ) | | ! remap_ops | |
! remap_ops - > set_affinity )
2012-03-30 22:47:03 +04:00
return 0 ;
return remap_ops - > set_affinity ( data , mask , force ) ;
}
2012-03-30 22:47:04 +04:00
2012-03-30 22:47:07 +04:00
void free_remapped_irq ( int irq )
2012-03-30 22:47:04 +04:00
{
if ( ! remap_ops | | ! remap_ops - > free_irq )
return ;
remap_ops - > free_irq ( irq ) ;
}
2012-03-30 22:47:05 +04:00
2012-03-30 22:47:07 +04:00
void compose_remapped_msi_msg ( struct pci_dev * pdev ,
unsigned int irq , unsigned int dest ,
struct msi_msg * msg , u8 hpet_id )
2012-03-30 22:47:05 +04:00
{
if ( ! remap_ops | | ! remap_ops - > compose_msi_msg )
return ;
remap_ops - > compose_msi_msg ( pdev , irq , dest , msg , hpet_id ) ;
}
2012-03-30 22:47:07 +04:00
int msi_alloc_remapped_irq ( struct pci_dev * pdev , int irq , int nvec )
2012-03-30 22:47:05 +04:00
{
if ( ! remap_ops | | ! remap_ops - > msi_alloc_irq )
return - ENODEV ;
return remap_ops - > msi_alloc_irq ( pdev , irq , nvec ) ;
}
2012-03-30 22:47:07 +04:00
int msi_setup_remapped_irq ( struct pci_dev * pdev , unsigned int irq ,
int index , int sub_handle )
2012-03-30 22:47:05 +04:00
{
if ( ! remap_ops | | ! remap_ops - > msi_setup_irq )
return - ENODEV ;
return remap_ops - > msi_setup_irq ( pdev , irq , index , sub_handle ) ;
}
2012-03-30 22:47:07 +04:00
int setup_hpet_msi_remapped ( unsigned int irq , unsigned int id )
2012-03-30 22:47:05 +04:00
{
if ( ! remap_ops | | ! remap_ops - > setup_hpet_msi )
return - ENODEV ;
return remap_ops - > setup_hpet_msi ( irq , id ) ;
}