diff options
author | Joerg Roedel <joerg.roedel@amd.com> | 2012-03-30 14:47:00 -0400 |
---|---|---|
committer | Joerg Roedel <joerg.roedel@amd.com> | 2012-05-07 08:34:59 -0400 |
commit | 736baef4472d00574089f295bc759ac002b9558c (patch) | |
tree | d4c9c69b1a0eecd6d87b3378a27396384e4b08f0 /drivers/iommu | |
parent | eef93fdb7cd41ae36794db0e765059dc1039e940 (diff) |
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: Joerg Roedel <joerg.roedel@amd.com>
Acked-by: Yinghai Lu <yinghai@kernel.org>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Alex Williamson <alex.williamson@redhat.com>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: Joerg Roedel <joerg.roedel@amd.com>
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 | |||
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 */ | ||