提交 736baef4 编写于 作者: J Joerg Roedel

iommu/vt-d: Make intr-remapping initialization generic

This patch introduces irq_remap_ops to hold implementation
specific function pointer to handle interrupt remapping. As
the first part the initialization functions for VT-d are
converted to these ops.
Signed-off-by: NJoerg Roedel <joerg.roedel@amd.com>
Acked-by: NYinghai Lu <yinghai@kernel.org>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: NSuresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: NJoerg Roedel <joerg.roedel@amd.com>
上级 eef93fdb
#ifndef __IA64_INTR_REMAPPING_H
#define __IA64_INTR_REMAPPING_H
#define intr_remapping_enabled 0
#endif
/*
* 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 the interface of the interrupt remapping code to
* the x86 interrupt management code.
*/
#ifndef __X86_INTR_REMAPPING_H
#define __X86_INTR_REMAPPING_H
#ifdef CONFIG_IRQ_REMAP
extern int intr_remapping_enabled;
extern void setup_intr_remapping(void);
extern int intr_remapping_supported(void);
extern int intr_hardware_init(void);
extern int intr_hardware_enable(void);
#else /* CONFIG_IRQ_REMAP */
#define intr_remapping_enabled 0
static inline void setup_intr_remapping(void) { }
static inline int intr_remapping_supported(void) { return 0; }
static inline int intr_hardware_init(void) { return -ENODEV; }
static inline int intr_hardware_enable(void) { return -ENODEV; }
#endif /* CONFIG_IRQ_REMAP */
#endif /* __X86_INTR_REMAPPING_H */
...@@ -35,6 +35,7 @@ ...@@ -35,6 +35,7 @@
#include <linux/smp.h> #include <linux/smp.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <asm/intr_remapping.h>
#include <asm/perf_event.h> #include <asm/perf_event.h>
#include <asm/x86_init.h> #include <asm/x86_init.h>
#include <asm/pgalloc.h> #include <asm/pgalloc.h>
...@@ -1528,7 +1529,7 @@ int __init enable_IR(void) ...@@ -1528,7 +1529,7 @@ int __init enable_IR(void)
return -1; return -1;
} }
return enable_intr_remapping(); return intr_hardware_enable();
#endif #endif
return -1; return -1;
} }
...@@ -1537,10 +1538,13 @@ void __init enable_IR_x2apic(void) ...@@ -1537,10 +1538,13 @@ void __init enable_IR_x2apic(void)
{ {
unsigned long flags; unsigned long flags;
int ret, x2apic_enabled = 0; int ret, x2apic_enabled = 0;
int dmar_table_init_ret; int hardware_init_ret;
dmar_table_init_ret = dmar_table_init(); /* Make sure irq_remap_ops are initialized */
if (dmar_table_init_ret && !x2apic_supported()) setup_intr_remapping();
hardware_init_ret = intr_hardware_init();
if (hardware_init_ret && !x2apic_supported())
return; return;
ret = save_ioapic_entries(); ret = save_ioapic_entries();
...@@ -1556,7 +1560,7 @@ void __init enable_IR_x2apic(void) ...@@ -1556,7 +1560,7 @@ void __init enable_IR_x2apic(void)
if (x2apic_preenabled && nox2apic) if (x2apic_preenabled && nox2apic)
disable_x2apic(); disable_x2apic();
if (dmar_table_init_ret) if (hardware_init_ret)
ret = -1; ret = -1;
else else
ret = enable_IR(); ret = enable_IR();
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include <asm/msidef.h> #include <asm/msidef.h>
#include <asm/hypertransport.h> #include <asm/hypertransport.h>
#include <asm/setup.h> #include <asm/setup.h>
#include <asm/intr_remapping.h>
#include <asm/irq_remapping.h> #include <asm/irq_remapping.h>
#include <asm/hpet.h> #include <asm/hpet.h>
#include <asm/hw_irq.h> #include <asm/hw_irq.h>
......
...@@ -4,7 +4,7 @@ obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o ...@@ -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_AMD_IOMMU_V2) += amd_iommu_v2.o
obj-$(CONFIG_DMAR_TABLE) += dmar.o obj-$(CONFIG_DMAR_TABLE) += dmar.o
obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.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_IOMMU) += omap-iommu.o
obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
......
...@@ -36,6 +36,7 @@ ...@@ -36,6 +36,7 @@
#include <linux/tboot.h> #include <linux/tboot.h>
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <asm/intr_remapping.h>
#include <asm/iommu_table.h> #include <asm/iommu_table.h>
#define PREFIX "DMAR: " #define PREFIX "DMAR: "
......
...@@ -42,6 +42,7 @@ ...@@ -42,6 +42,7 @@
#include <linux/dmi.h> #include <linux/dmi.h>
#include <linux/pci-ats.h> #include <linux/pci-ats.h>
#include <linux/memblock.h> #include <linux/memblock.h>
#include <asm/intr_remapping.h>
#include <asm/cacheflush.h> #include <asm/cacheflush.h>
#include <asm/iommu.h> #include <asm/iommu.h>
......
...@@ -11,8 +11,11 @@ ...@@ -11,8 +11,11 @@
#include <asm/cpu.h> #include <asm/cpu.h>
#include <linux/intel-iommu.h> #include <linux/intel-iommu.h>
#include <acpi/acpi.h> #include <acpi/acpi.h>
#include <asm/intr_remapping.h>
#include <asm/pci-direct.h> #include <asm/pci-direct.h>
#include "intr_remapping.h"
struct ioapic_scope { struct ioapic_scope {
struct intel_iommu *iommu; struct intel_iommu *iommu;
unsigned int id; unsigned int id;
...@@ -32,42 +35,6 @@ struct hpet_scope { ...@@ -32,42 +35,6 @@ struct hpet_scope {
static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
static struct hpet_scope ir_hpet[MAX_HPET_TBS]; static struct hpet_scope ir_hpet[MAX_HPET_TBS];
static int ir_ioapic_num, ir_hpet_num; 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); static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
...@@ -465,7 +432,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) ...@@ -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 ir_table *ir_table;
struct page *pages; struct page *pages;
...@@ -534,7 +501,7 @@ static int __init dmar_x2apic_optout(void) ...@@ -534,7 +501,7 @@ static int __init dmar_x2apic_optout(void)
return dmar->flags & DMAR_X2APIC_OPT_OUT; 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; struct dmar_drhd_unit *drhd;
...@@ -554,7 +521,7 @@ int __init intr_remapping_supported(void) ...@@ -554,7 +521,7 @@ int __init intr_remapping_supported(void)
return 1; return 1;
} }
int __init enable_intr_remapping(void) static int __init intel_enable_intr_remapping(void)
{ {
struct dmar_drhd_unit *drhd; struct dmar_drhd_unit *drhd;
int setup = 0; int setup = 0;
...@@ -638,7 +605,7 @@ int __init enable_intr_remapping(void) ...@@ -638,7 +605,7 @@ int __init enable_intr_remapping(void)
if (!ecap_ir_support(iommu->ecap)) if (!ecap_ir_support(iommu->ecap))
continue; continue;
if (setup_intr_remapping(iommu, eim)) if (intel_setup_intr_remapping(iommu, eim))
goto error; goto error;
setup = 1; setup = 1;
...@@ -847,3 +814,8 @@ int reenable_intr_remapping(int eim) ...@@ -847,3 +814,8 @@ int reenable_intr_remapping(int eim)
return -1; 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,
};
#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();
}
/*
* 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 */
...@@ -115,9 +115,6 @@ struct irte { ...@@ -115,9 +115,6 @@ struct irte {
}; };
#ifdef CONFIG_IRQ_REMAP #ifdef CONFIG_IRQ_REMAP
extern int intr_remapping_enabled;
extern int intr_remapping_supported(void);
extern int enable_intr_remapping(void);
extern void disable_intr_remapping(void); extern void disable_intr_remapping(void);
extern int reenable_intr_remapping(int); extern int reenable_intr_remapping(int);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册