diff options
-rw-r--r-- | arch/ia64/include/asm/intr_remapping.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/intr_remapping.h | 45 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 14 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 1 | ||||
-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 | ||||
-rw-r--r-- | include/linux/dmar.h | 3 |
11 files changed, 196 insertions, 49 deletions
diff --git a/arch/ia64/include/asm/intr_remapping.h b/arch/ia64/include/asm/intr_remapping.h new file mode 100644 index 000000000000..095aa0d46c58 --- /dev/null +++ b/arch/ia64/include/asm/intr_remapping.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef __IA64_INTR_REMAPPING_H | ||
2 | #define __IA64_INTR_REMAPPING_H | ||
3 | #define intr_remapping_enabled 0 | ||
4 | #endif | ||
diff --git a/arch/x86/include/asm/intr_remapping.h b/arch/x86/include/asm/intr_remapping.h new file mode 100644 index 000000000000..207c605dbdf5 --- /dev/null +++ b/arch/x86/include/asm/intr_remapping.h | |||
@@ -0,0 +1,45 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Advanced Micro Devices, Inc. | ||
3 | * Author: Joerg Roedel <joerg.roedel@amd.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published | ||
7 | * by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * This header file contains the interface of the interrupt remapping code to | ||
19 | * the x86 interrupt management code. | ||
20 | */ | ||
21 | |||
22 | #ifndef __X86_INTR_REMAPPING_H | ||
23 | #define __X86_INTR_REMAPPING_H | ||
24 | |||
25 | #ifdef CONFIG_IRQ_REMAP | ||
26 | |||
27 | extern int intr_remapping_enabled; | ||
28 | |||
29 | extern void setup_intr_remapping(void); | ||
30 | extern int intr_remapping_supported(void); | ||
31 | extern int intr_hardware_init(void); | ||
32 | extern int intr_hardware_enable(void); | ||
33 | |||
34 | #else /* CONFIG_IRQ_REMAP */ | ||
35 | |||
36 | #define intr_remapping_enabled 0 | ||
37 | |||
38 | static inline void setup_intr_remapping(void) { } | ||
39 | static inline int intr_remapping_supported(void) { return 0; } | ||
40 | static inline int intr_hardware_init(void) { return -ENODEV; } | ||
41 | static inline int intr_hardware_enable(void) { return -ENODEV; } | ||
42 | |||
43 | #endif /* CONFIG_IRQ_REMAP */ | ||
44 | |||
45 | #endif /* __X86_INTR_REMAPPING_H */ | ||
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index edc24480469f..1db6f63a22ff 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <linux/smp.h> | 35 | #include <linux/smp.h> |
36 | #include <linux/mm.h> | 36 | #include <linux/mm.h> |
37 | 37 | ||
38 | #include <asm/intr_remapping.h> | ||
38 | #include <asm/perf_event.h> | 39 | #include <asm/perf_event.h> |
39 | #include <asm/x86_init.h> | 40 | #include <asm/x86_init.h> |
40 | #include <asm/pgalloc.h> | 41 | #include <asm/pgalloc.h> |
@@ -1528,7 +1529,7 @@ int __init enable_IR(void) | |||
1528 | return -1; | 1529 | return -1; |
1529 | } | 1530 | } |
1530 | 1531 | ||
1531 | return enable_intr_remapping(); | 1532 | return intr_hardware_enable(); |
1532 | #endif | 1533 | #endif |
1533 | return -1; | 1534 | return -1; |
1534 | } | 1535 | } |
@@ -1537,10 +1538,13 @@ void __init enable_IR_x2apic(void) | |||
1537 | { | 1538 | { |
1538 | unsigned long flags; | 1539 | unsigned long flags; |
1539 | int ret, x2apic_enabled = 0; | 1540 | int ret, x2apic_enabled = 0; |
1540 | int dmar_table_init_ret; | 1541 | int hardware_init_ret; |
1541 | 1542 | ||
1542 | dmar_table_init_ret = dmar_table_init(); | 1543 | /* Make sure irq_remap_ops are initialized */ |
1543 | if (dmar_table_init_ret && !x2apic_supported()) | 1544 | setup_intr_remapping(); |
1545 | |||
1546 | hardware_init_ret = intr_hardware_init(); | ||
1547 | if (hardware_init_ret && !x2apic_supported()) | ||
1544 | return; | 1548 | return; |
1545 | 1549 | ||
1546 | ret = save_ioapic_entries(); | 1550 | ret = save_ioapic_entries(); |
@@ -1556,7 +1560,7 @@ void __init enable_IR_x2apic(void) | |||
1556 | if (x2apic_preenabled && nox2apic) | 1560 | if (x2apic_preenabled && nox2apic) |
1557 | disable_x2apic(); | 1561 | disable_x2apic(); |
1558 | 1562 | ||
1559 | if (dmar_table_init_ret) | 1563 | if (hardware_init_ret) |
1560 | ret = -1; | 1564 | ret = -1; |
1561 | else | 1565 | else |
1562 | ret = enable_IR(); | 1566 | ret = enable_IR(); |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e88300d8e80a..1151fdccaad6 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <asm/msidef.h> | 57 | #include <asm/msidef.h> |
58 | #include <asm/hypertransport.h> | 58 | #include <asm/hypertransport.h> |
59 | #include <asm/setup.h> | 59 | #include <asm/setup.h> |
60 | #include <asm/intr_remapping.h> | ||
60 | #include <asm/irq_remapping.h> | 61 | #include <asm/irq_remapping.h> |
61 | #include <asm/hpet.h> | 62 | #include <asm/hpet.h> |
62 | #include <asm/hw_irq.h> | 63 | #include <asm/hw_irq.h> |
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 | |||
4 | obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o | 4 | obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o |
5 | obj-$(CONFIG_DMAR_TABLE) += dmar.o | 5 | obj-$(CONFIG_DMAR_TABLE) += dmar.o |
6 | obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o | 6 | obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o |
7 | obj-$(CONFIG_IRQ_REMAP) += intel_intr_remapping.o | 7 | obj-$(CONFIG_IRQ_REMAP) += intel_intr_remapping.o intr_remapping.o |
8 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o | 8 | obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o |
9 | obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o | 9 | obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o |
10 | obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o | 10 | 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 @@ | |||
36 | #include <linux/tboot.h> | 36 | #include <linux/tboot.h> |
37 | #include <linux/dmi.h> | 37 | #include <linux/dmi.h> |
38 | #include <linux/slab.h> | 38 | #include <linux/slab.h> |
39 | #include <asm/intr_remapping.h> | ||
39 | #include <asm/iommu_table.h> | 40 | #include <asm/iommu_table.h> |
40 | 41 | ||
41 | #define PREFIX "DMAR: " | 42 | #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 @@ | |||
42 | #include <linux/dmi.h> | 42 | #include <linux/dmi.h> |
43 | #include <linux/pci-ats.h> | 43 | #include <linux/pci-ats.h> |
44 | #include <linux/memblock.h> | 44 | #include <linux/memblock.h> |
45 | #include <asm/intr_remapping.h> | ||
45 | #include <asm/cacheflush.h> | 46 | #include <asm/cacheflush.h> |
46 | #include <asm/iommu.h> | 47 | #include <asm/iommu.h> |
47 | 48 | ||
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 @@ | |||
11 | #include <asm/cpu.h> | 11 | #include <asm/cpu.h> |
12 | #include <linux/intel-iommu.h> | 12 | #include <linux/intel-iommu.h> |
13 | #include <acpi/acpi.h> | 13 | #include <acpi/acpi.h> |
14 | #include <asm/intr_remapping.h> | ||
14 | #include <asm/pci-direct.h> | 15 | #include <asm/pci-direct.h> |
15 | 16 | ||
17 | #include "intr_remapping.h" | ||
18 | |||
16 | struct ioapic_scope { | 19 | struct ioapic_scope { |
17 | struct intel_iommu *iommu; | 20 | struct intel_iommu *iommu; |
18 | unsigned int id; | 21 | unsigned int id; |
@@ -32,42 +35,6 @@ struct hpet_scope { | |||
32 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; | 35 | static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; |
33 | static struct hpet_scope ir_hpet[MAX_HPET_TBS]; | 36 | static struct hpet_scope ir_hpet[MAX_HPET_TBS]; |
34 | static int ir_ioapic_num, ir_hpet_num; | 37 | static int ir_ioapic_num, ir_hpet_num; |
35 | int intr_remapping_enabled; | ||
36 | |||
37 | static int disable_intremap; | ||
38 | static int disable_sourceid_checking; | ||
39 | static int no_x2apic_optout; | ||
40 | |||
41 | static __init int setup_nointremap(char *str) | ||
42 | { | ||
43 | disable_intremap = 1; | ||
44 | return 0; | ||
45 | } | ||
46 | early_param("nointremap", setup_nointremap); | ||
47 | |||
48 | static __init int setup_intremap(char *str) | ||
49 | { | ||
50 | if (!str) | ||
51 | return -EINVAL; | ||
52 | |||
53 | while (*str) { | ||
54 | if (!strncmp(str, "on", 2)) | ||
55 | disable_intremap = 0; | ||
56 | else if (!strncmp(str, "off", 3)) | ||
57 | disable_intremap = 1; | ||
58 | else if (!strncmp(str, "nosid", 5)) | ||
59 | disable_sourceid_checking = 1; | ||
60 | else if (!strncmp(str, "no_x2apic_optout", 16)) | ||
61 | no_x2apic_optout = 1; | ||
62 | |||
63 | str += strcspn(str, ","); | ||
64 | while (*str == ',') | ||
65 | str++; | ||
66 | } | ||
67 | |||
68 | return 0; | ||
69 | } | ||
70 | early_param("intremap", setup_intremap); | ||
71 | 38 | ||
72 | static DEFINE_RAW_SPINLOCK(irq_2_ir_lock); | 39 | static DEFINE_RAW_SPINLOCK(irq_2_ir_lock); |
73 | 40 | ||
@@ -465,7 +432,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) | |||
465 | } | 432 | } |
466 | 433 | ||
467 | 434 | ||
468 | static int setup_intr_remapping(struct intel_iommu *iommu, int mode) | 435 | static int intel_setup_intr_remapping(struct intel_iommu *iommu, int mode) |
469 | { | 436 | { |
470 | struct ir_table *ir_table; | 437 | struct ir_table *ir_table; |
471 | struct page *pages; | 438 | struct page *pages; |
@@ -534,7 +501,7 @@ static int __init dmar_x2apic_optout(void) | |||
534 | return dmar->flags & DMAR_X2APIC_OPT_OUT; | 501 | return dmar->flags & DMAR_X2APIC_OPT_OUT; |
535 | } | 502 | } |
536 | 503 | ||
537 | int __init intr_remapping_supported(void) | 504 | static int __init intel_intr_remapping_supported(void) |
538 | { | 505 | { |
539 | struct dmar_drhd_unit *drhd; | 506 | struct dmar_drhd_unit *drhd; |
540 | 507 | ||
@@ -554,7 +521,7 @@ int __init intr_remapping_supported(void) | |||
554 | return 1; | 521 | return 1; |
555 | } | 522 | } |
556 | 523 | ||
557 | int __init enable_intr_remapping(void) | 524 | static int __init intel_enable_intr_remapping(void) |
558 | { | 525 | { |
559 | struct dmar_drhd_unit *drhd; | 526 | struct dmar_drhd_unit *drhd; |
560 | int setup = 0; | 527 | int setup = 0; |
@@ -638,7 +605,7 @@ int __init enable_intr_remapping(void) | |||
638 | if (!ecap_ir_support(iommu->ecap)) | 605 | if (!ecap_ir_support(iommu->ecap)) |
639 | continue; | 606 | continue; |
640 | 607 | ||
641 | if (setup_intr_remapping(iommu, eim)) | 608 | if (intel_setup_intr_remapping(iommu, eim)) |
642 | goto error; | 609 | goto error; |
643 | 610 | ||
644 | setup = 1; | 611 | setup = 1; |
@@ -847,3 +814,8 @@ error: | |||
847 | return -1; | 814 | return -1; |
848 | } | 815 | } |
849 | 816 | ||
817 | struct irq_remap_ops intel_irq_remap_ops = { | ||
818 | .supported = intel_intr_remapping_supported, | ||
819 | .hardware_init = dmar_table_init, | ||
820 | .hardware_enable = intel_enable_intr_remapping, | ||
821 | }; | ||
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 @@ | |||
1 | #include <linux/kernel.h> | ||
2 | #include <linux/string.h> | ||
3 | #include <linux/errno.h> | ||
4 | |||
5 | #include "intr_remapping.h" | ||
6 | |||
7 | int intr_remapping_enabled; | ||
8 | |||
9 | int disable_intremap; | ||
10 | int disable_sourceid_checking; | ||
11 | int no_x2apic_optout; | ||
12 | |||
13 | static struct irq_remap_ops *remap_ops; | ||
14 | |||
15 | static __init int setup_nointremap(char *str) | ||
16 | { | ||
17 | disable_intremap = 1; | ||
18 | return 0; | ||
19 | } | ||
20 | early_param("nointremap", setup_nointremap); | ||
21 | |||
22 | static __init int setup_intremap(char *str) | ||
23 | { | ||
24 | if (!str) | ||
25 | return -EINVAL; | ||
26 | |||
27 | while (*str) { | ||
28 | if (!strncmp(str, "on", 2)) | ||
29 | disable_intremap = 0; | ||
30 | else if (!strncmp(str, "off", 3)) | ||
31 | disable_intremap = 1; | ||
32 | else if (!strncmp(str, "nosid", 5)) | ||
33 | disable_sourceid_checking = 1; | ||
34 | else if (!strncmp(str, "no_x2apic_optout", 16)) | ||
35 | no_x2apic_optout = 1; | ||
36 | |||
37 | str += strcspn(str, ","); | ||
38 | while (*str == ',') | ||
39 | str++; | ||
40 | } | ||
41 | |||
42 | return 0; | ||
43 | } | ||
44 | early_param("intremap", setup_intremap); | ||
45 | |||
46 | void __init setup_intr_remapping(void) | ||
47 | { | ||
48 | remap_ops = &intel_irq_remap_ops; | ||
49 | } | ||
50 | |||
51 | int intr_remapping_supported(void) | ||
52 | { | ||
53 | if (disable_intremap) | ||
54 | return 0; | ||
55 | |||
56 | if (!remap_ops || !remap_ops->supported) | ||
57 | return 0; | ||
58 | |||
59 | return remap_ops->supported(); | ||
60 | } | ||
61 | |||
62 | int __init intr_hardware_init(void) | ||
63 | { | ||
64 | if (!remap_ops || !remap_ops->hardware_init) | ||
65 | return -ENODEV; | ||
66 | |||
67 | return remap_ops->hardware_init(); | ||
68 | } | ||
69 | |||
70 | int __init intr_hardware_enable(void) | ||
71 | { | ||
72 | if (!remap_ops || !remap_ops->hardware_enable) | ||
73 | return -ENODEV; | ||
74 | |||
75 | return remap_ops->hardware_enable(); | ||
76 | } | ||
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 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2012 Advanced Micro Devices, Inc. | ||
3 | * Author: Joerg Roedel <joerg.roedel@amd.com> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify it | ||
6 | * under the terms of the GNU General Public License version 2 as published | ||
7 | * by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the Free Software | ||
16 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
17 | * | ||
18 | * This header file contains stuff that is shared between different interrupt | ||
19 | * remapping drivers but with no need to be visible outside of the IOMMU layer. | ||
20 | */ | ||
21 | |||
22 | #ifndef __INTR_REMAPPING_H | ||
23 | #define __INTR_REMAPPING_H | ||
24 | |||
25 | #ifdef CONFIG_IRQ_REMAP | ||
26 | |||
27 | extern int disable_intremap; | ||
28 | extern int disable_sourceid_checking; | ||
29 | extern int no_x2apic_optout; | ||
30 | |||
31 | struct irq_remap_ops { | ||
32 | /* Check whether Interrupt Remapping is supported */ | ||
33 | int (*supported)(void); | ||
34 | |||
35 | /* Initializes hardware and makes it ready for remapping interrupts */ | ||
36 | int (*hardware_init)(void); | ||
37 | |||
38 | /* Enables the remapping hardware */ | ||
39 | int (*hardware_enable)(void); | ||
40 | }; | ||
41 | |||
42 | extern struct irq_remap_ops intel_irq_remap_ops; | ||
43 | |||
44 | #endif /* CONFIG_IRQ_REMAP */ | ||
45 | |||
46 | #endif /* __INTR_REMAPPING_H */ | ||
diff --git a/include/linux/dmar.h b/include/linux/dmar.h index 731a60975101..6d66c9c76e0a 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h | |||
@@ -115,9 +115,6 @@ struct irte { | |||
115 | }; | 115 | }; |
116 | 116 | ||
117 | #ifdef CONFIG_IRQ_REMAP | 117 | #ifdef CONFIG_IRQ_REMAP |
118 | extern int intr_remapping_enabled; | ||
119 | extern int intr_remapping_supported(void); | ||
120 | extern int enable_intr_remapping(void); | ||
121 | extern void disable_intr_remapping(void); | 118 | extern void disable_intr_remapping(void); |
122 | extern int reenable_intr_remapping(int); | 119 | extern int reenable_intr_remapping(int); |
123 | 120 | ||