diff options
Diffstat (limited to 'drivers/iommu')
-rw-r--r-- | drivers/iommu/Makefile | 2 | ||||
-rw-r--r-- | drivers/iommu/dmar.c | 1 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 1 | ||||
-rw-r--r-- | drivers/iommu/intel_intr_remapping.c | 52 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.c | 76 | ||||
-rw-r--r-- | drivers/iommu/intr_remapping.h | 46 |
6 files changed, 137 insertions, 41 deletions
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile index 1533ebf1d68e..823e1cf8708f 100644 --- a/drivers/iommu/Makefile +++ b/drivers/iommu/Makefile @@ -4,7 +4,7 @@ obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o obj-$(CONFIG_DMAR_TABLE) += dmar.o obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o -obj-$(CONFIG_IRQ_REMAP) += intel_intr_remapping.o +obj-$(CONFIG_IRQ_REMAP) += intel_intr_remapping.o intr_remapping.o obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 35c1e17fce1d..647e366403dc 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c @@ -36,6 +36,7 @@ #include <linux/tboot.h> #include <linux/dmi.h> #include <linux/slab.h> +#include <asm/intr_remapping.h> #include <asm/iommu_table.h> #define PREFIX "DMAR: " diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index f93d5ac8f81c..e1439808192c 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c @@ -42,6 +42,7 @@ #include <linux/dmi.h> #include <linux/pci-ats.h> #include <linux/memblock.h> +#include <asm/intr_remapping.h> #include <asm/cacheflush.h> #include <asm/iommu.h> diff --git a/drivers/iommu/intel_intr_remapping.c b/drivers/iommu/intel_intr_remapping.c index 212fff0c24b5..9c742fb111b6 100644 --- a/drivers/iommu/intel_intr_remapping.c +++ b/drivers/iommu/intel_intr_remapping.c @@ -11,8 +11,11 @@ #include <asm/cpu.h> #include <linux/intel-iommu.h> #include <acpi/acpi.h> +#include <asm/intr_remapping.h> #include <asm/pci-direct.h> +#include "intr_remapping.h" + struct ioapic_scope { struct intel_iommu *iommu; unsigned int id; @@ -32,42 +35,6 @@ struct hpet_scope { static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; static struct hpet_scope ir_hpet[MAX_HPET_TBS]; static int ir_ioapic_num, ir_hpet_num; -int intr_remapping_enabled; - -static int disable_intremap; -static int disable_sourceid_checking; -static int no_x2apic_optout; - -static __init int setup_nointremap(char *str) -{ - disable_intremap = 1; - return 0; -} -early_param("nointremap", setup_nointremap); - -static __init int setup_intremap(char *str) -{ - if (!str) - return -EINVAL; - - while (*str) { - if (!strncmp(str, "on", 2)) - disable_intremap = 0; - else if (!strncmp(str, "off", 3)) - disable_intremap = 1; - 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; -} -early_param("intremap", setup_intremap); static DEFINE_RAW_SPINLOCK(irq_2_ir_lock); @@ -465,7 +432,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) } -static int setup_intr_remapping(struct intel_iommu *iommu, int mode) +static int intel_setup_intr_remapping(struct intel_iommu *iommu, int mode) { struct ir_table *ir_table; struct page *pages; @@ -534,7 +501,7 @@ static int __init dmar_x2apic_optout(void) return dmar->flags & DMAR_X2APIC_OPT_OUT; } -int __init intr_remapping_supported(void) +static int __init intel_intr_remapping_supported(void) { struct dmar_drhd_unit *drhd; @@ -554,7 +521,7 @@ int __init intr_remapping_supported(void) return 1; } -int __init enable_intr_remapping(void) +static int __init intel_enable_intr_remapping(void) { struct dmar_drhd_unit *drhd; int setup = 0; @@ -638,7 +605,7 @@ int __init enable_intr_remapping(void) if (!ecap_ir_support(iommu->ecap)) continue; - if (setup_intr_remapping(iommu, eim)) + if (intel_setup_intr_remapping(iommu, eim)) goto error; setup = 1; @@ -847,3 +814,8 @@ error: return -1; } +struct irq_remap_ops intel_irq_remap_ops = { + .supported = intel_intr_remapping_supported, + .hardware_init = dmar_table_init, + .hardware_enable = intel_enable_intr_remapping, +}; diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intr_remapping.c new file mode 100644 index 000000000000..670c69a80afd --- /dev/null +++ b/drivers/iommu/intr_remapping.c @@ -0,0 +1,76 @@ +#include <linux/kernel.h> +#include <linux/string.h> +#include <linux/errno.h> + +#include "intr_remapping.h" + +int intr_remapping_enabled; + +int disable_intremap; +int disable_sourceid_checking; +int no_x2apic_optout; + +static struct irq_remap_ops *remap_ops; + +static __init int setup_nointremap(char *str) +{ + disable_intremap = 1; + return 0; +} +early_param("nointremap", setup_nointremap); + +static __init int setup_intremap(char *str) +{ + if (!str) + return -EINVAL; + + while (*str) { + if (!strncmp(str, "on", 2)) + disable_intremap = 0; + else if (!strncmp(str, "off", 3)) + disable_intremap = 1; + 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; +} +early_param("intremap", setup_intremap); + +void __init setup_intr_remapping(void) +{ + remap_ops = &intel_irq_remap_ops; +} + +int intr_remapping_supported(void) +{ + if (disable_intremap) + return 0; + + if (!remap_ops || !remap_ops->supported) + return 0; + + return remap_ops->supported(); +} + +int __init intr_hardware_init(void) +{ + if (!remap_ops || !remap_ops->hardware_init) + return -ENODEV; + + return remap_ops->hardware_init(); +} + +int __init intr_hardware_enable(void) +{ + if (!remap_ops || !remap_ops->hardware_enable) + return -ENODEV; + + return remap_ops->hardware_enable(); +} diff --git a/drivers/iommu/intr_remapping.h b/drivers/iommu/intr_remapping.h new file mode 100644 index 000000000000..d6df732e001f --- /dev/null +++ b/drivers/iommu/intr_remapping.h @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2012 Advanced Micro Devices, Inc. + * Author: Joerg Roedel <joerg.roedel@amd.com> + * + * 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, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * This header file contains stuff that is shared between different interrupt + * remapping drivers but with no need to be visible outside of the IOMMU layer. + */ + +#ifndef __INTR_REMAPPING_H +#define __INTR_REMAPPING_H + +#ifdef CONFIG_IRQ_REMAP + +extern int disable_intremap; +extern int disable_sourceid_checking; +extern int no_x2apic_optout; + +struct irq_remap_ops { + /* Check whether Interrupt Remapping is supported */ + int (*supported)(void); + + /* Initializes hardware and makes it ready for remapping interrupts */ + int (*hardware_init)(void); + + /* Enables the remapping hardware */ + int (*hardware_enable)(void); +}; + +extern struct irq_remap_ops intel_irq_remap_ops; + +#endif /* CONFIG_IRQ_REMAP */ + +#endif /* __INTR_REMAPPING_H */ |