aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/iommu/Makefile2
-rw-r--r--drivers/iommu/dmar.c11
-rw-r--r--drivers/iommu/intel-iommu.c3
-rw-r--r--drivers/iommu/intel_irq_remapping.c (renamed from drivers/iommu/intr_remapping.c)359
-rw-r--r--drivers/iommu/intr_remapping.h17
-rw-r--r--drivers/iommu/irq_remapping.c166
-rw-r--r--drivers/iommu/irq_remapping.h90
7 files changed, 562 insertions, 86 deletions
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 7ad7a3bc1242..3e5e82ae9f0d 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
4obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o 4obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
5obj-$(CONFIG_DMAR_TABLE) += dmar.o 5obj-$(CONFIG_DMAR_TABLE) += dmar.o
6obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o 6obj-$(CONFIG_INTEL_IOMMU) += iova.o intel-iommu.o
7obj-$(CONFIG_IRQ_REMAP) += intr_remapping.o 7obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
8obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o 8obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
9obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o 9obj-$(CONFIG_OMAP_IOVMM) += omap-iovmm.o
10obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o 10obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 35c1e17fce1d..3a74e4410fc0 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/irq_remapping.h>
39#include <asm/iommu_table.h> 40#include <asm/iommu_table.h>
40 41
41#define PREFIX "DMAR: " 42#define PREFIX "DMAR: "
@@ -555,7 +556,7 @@ int __init detect_intel_iommu(void)
555 556
556 dmar = (struct acpi_table_dmar *) dmar_tbl; 557 dmar = (struct acpi_table_dmar *) dmar_tbl;
557 558
558 if (ret && intr_remapping_enabled && cpu_has_x2apic && 559 if (ret && irq_remapping_enabled && cpu_has_x2apic &&
559 dmar->flags & 0x1) 560 dmar->flags & 0x1)
560 printk(KERN_INFO 561 printk(KERN_INFO
561 "Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); 562 "Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
@@ -1041,7 +1042,7 @@ static const char *dma_remap_fault_reasons[] =
1041 "non-zero reserved fields in PTE", 1042 "non-zero reserved fields in PTE",
1042}; 1043};
1043 1044
1044static const char *intr_remap_fault_reasons[] = 1045static const char *irq_remap_fault_reasons[] =
1045{ 1046{
1046 "Detected reserved fields in the decoded interrupt-remapped request", 1047 "Detected reserved fields in the decoded interrupt-remapped request",
1047 "Interrupt index exceeded the interrupt-remapping table size", 1048 "Interrupt index exceeded the interrupt-remapping table size",
@@ -1056,10 +1057,10 @@ static const char *intr_remap_fault_reasons[] =
1056 1057
1057const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type) 1058const char *dmar_get_fault_reason(u8 fault_reason, int *fault_type)
1058{ 1059{
1059 if (fault_reason >= 0x20 && (fault_reason <= 0x20 + 1060 if (fault_reason >= 0x20 && (fault_reason - 0x20 <
1060 ARRAY_SIZE(intr_remap_fault_reasons))) { 1061 ARRAY_SIZE(irq_remap_fault_reasons))) {
1061 *fault_type = INTR_REMAP; 1062 *fault_type = INTR_REMAP;
1062 return intr_remap_fault_reasons[fault_reason - 0x20]; 1063 return irq_remap_fault_reasons[fault_reason - 0x20];
1063 } else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) { 1064 } else if (fault_reason < ARRAY_SIZE(dma_remap_fault_reasons)) {
1064 *fault_type = DMA_REMAP; 1065 *fault_type = DMA_REMAP;
1065 return dma_remap_fault_reasons[fault_reason]; 1066 return dma_remap_fault_reasons[fault_reason];
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index f93d5ac8f81c..bf2fbaad5e22 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/irq_remapping.h>
45#include <asm/cacheflush.h> 46#include <asm/cacheflush.h>
46#include <asm/iommu.h> 47#include <asm/iommu.h>
47 48
@@ -4082,7 +4083,7 @@ static int intel_iommu_domain_has_cap(struct iommu_domain *domain,
4082 if (cap == IOMMU_CAP_CACHE_COHERENCY) 4083 if (cap == IOMMU_CAP_CACHE_COHERENCY)
4083 return dmar_domain->iommu_snooping; 4084 return dmar_domain->iommu_snooping;
4084 if (cap == IOMMU_CAP_INTR_REMAP) 4085 if (cap == IOMMU_CAP_INTR_REMAP)
4085 return intr_remapping_enabled; 4086 return irq_remapping_enabled;
4086 4087
4087 return 0; 4088 return 0;
4088} 4089}
diff --git a/drivers/iommu/intr_remapping.c b/drivers/iommu/intel_irq_remapping.c
index 6777ca049471..6d347064b8b0 100644
--- a/drivers/iommu/intr_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -10,49 +10,33 @@
10#include <asm/smp.h> 10#include <asm/smp.h>
11#include <asm/cpu.h> 11#include <asm/cpu.h>
12#include <linux/intel-iommu.h> 12#include <linux/intel-iommu.h>
13#include "intr_remapping.h"
14#include <acpi/acpi.h> 13#include <acpi/acpi.h>
14#include <asm/irq_remapping.h>
15#include <asm/pci-direct.h> 15#include <asm/pci-direct.h>
16#include <asm/msidef.h>
16 17
17static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; 18#include "irq_remapping.h"
18static struct hpet_scope ir_hpet[MAX_HPET_TBS];
19static int ir_ioapic_num, ir_hpet_num;
20int intr_remapping_enabled;
21
22static int disable_intremap;
23static int disable_sourceid_checking;
24static int no_x2apic_optout;
25 19
26static __init int setup_nointremap(char *str) 20struct ioapic_scope {
27{ 21 struct intel_iommu *iommu;
28 disable_intremap = 1; 22 unsigned int id;
29 return 0; 23 unsigned int bus; /* PCI bus number */
30} 24 unsigned int devfn; /* PCI devfn number */
31early_param("nointremap", setup_nointremap); 25};
32 26
33static __init int setup_intremap(char *str) 27struct hpet_scope {
34{ 28 struct intel_iommu *iommu;
35 if (!str) 29 u8 id;
36 return -EINVAL; 30 unsigned int bus;
31 unsigned int devfn;
32};
37 33
38 while (*str) { 34#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
39 if (!strncmp(str, "on", 2)) 35#define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8)
40 disable_intremap = 0;
41 else if (!strncmp(str, "off", 3))
42 disable_intremap = 1;
43 else if (!strncmp(str, "nosid", 5))
44 disable_sourceid_checking = 1;
45 else if (!strncmp(str, "no_x2apic_optout", 16))
46 no_x2apic_optout = 1;
47
48 str += strcspn(str, ",");
49 while (*str == ',')
50 str++;
51 }
52 36
53 return 0; 37static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
54} 38static struct hpet_scope ir_hpet[MAX_HPET_TBS];
55early_param("intremap", setup_intremap); 39static int ir_ioapic_num, ir_hpet_num;
56 40
57static DEFINE_RAW_SPINLOCK(irq_2_ir_lock); 41static DEFINE_RAW_SPINLOCK(irq_2_ir_lock);
58 42
@@ -80,7 +64,7 @@ int get_irte(int irq, struct irte *entry)
80 return 0; 64 return 0;
81} 65}
82 66
83int alloc_irte(struct intel_iommu *iommu, int irq, u16 count) 67static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
84{ 68{
85 struct ir_table *table = iommu->ir_table; 69 struct ir_table *table = iommu->ir_table;
86 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); 70 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
@@ -152,7 +136,7 @@ static int qi_flush_iec(struct intel_iommu *iommu, int index, int mask)
152 return qi_submit_sync(&desc, iommu); 136 return qi_submit_sync(&desc, iommu);
153} 137}
154 138
155int map_irq_to_irte_handle(int irq, u16 *sub_handle) 139static int map_irq_to_irte_handle(int irq, u16 *sub_handle)
156{ 140{
157 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); 141 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
158 unsigned long flags; 142 unsigned long flags;
@@ -168,7 +152,7 @@ int map_irq_to_irte_handle(int irq, u16 *sub_handle)
168 return index; 152 return index;
169} 153}
170 154
171int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) 155static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
172{ 156{
173 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); 157 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
174 unsigned long flags; 158 unsigned long flags;
@@ -188,7 +172,7 @@ int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
188 return 0; 172 return 0;
189} 173}
190 174
191int modify_irte(int irq, struct irte *irte_modified) 175static int modify_irte(int irq, struct irte *irte_modified)
192{ 176{
193 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); 177 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
194 struct intel_iommu *iommu; 178 struct intel_iommu *iommu;
@@ -216,7 +200,7 @@ int modify_irte(int irq, struct irte *irte_modified)
216 return rc; 200 return rc;
217} 201}
218 202
219struct intel_iommu *map_hpet_to_ir(u8 hpet_id) 203static struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
220{ 204{
221 int i; 205 int i;
222 206
@@ -226,7 +210,7 @@ struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
226 return NULL; 210 return NULL;
227} 211}
228 212
229struct intel_iommu *map_ioapic_to_ir(int apic) 213static struct intel_iommu *map_ioapic_to_ir(int apic)
230{ 214{
231 int i; 215 int i;
232 216
@@ -236,7 +220,7 @@ struct intel_iommu *map_ioapic_to_ir(int apic)
236 return NULL; 220 return NULL;
237} 221}
238 222
239struct intel_iommu *map_dev_to_ir(struct pci_dev *dev) 223static struct intel_iommu *map_dev_to_ir(struct pci_dev *dev)
240{ 224{
241 struct dmar_drhd_unit *drhd; 225 struct dmar_drhd_unit *drhd;
242 226
@@ -270,7 +254,7 @@ static int clear_entries(struct irq_2_iommu *irq_iommu)
270 return qi_flush_iec(iommu, index, irq_iommu->irte_mask); 254 return qi_flush_iec(iommu, index, irq_iommu->irte_mask);
271} 255}
272 256
273int free_irte(int irq) 257static int free_irte(int irq)
274{ 258{
275 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); 259 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
276 unsigned long flags; 260 unsigned long flags;
@@ -328,7 +312,7 @@ static void set_irte_sid(struct irte *irte, unsigned int svt,
328 irte->sid = sid; 312 irte->sid = sid;
329} 313}
330 314
331int set_ioapic_sid(struct irte *irte, int apic) 315static int set_ioapic_sid(struct irte *irte, int apic)
332{ 316{
333 int i; 317 int i;
334 u16 sid = 0; 318 u16 sid = 0;
@@ -353,7 +337,7 @@ int set_ioapic_sid(struct irte *irte, int apic)
353 return 0; 337 return 0;
354} 338}
355 339
356int set_hpet_sid(struct irte *irte, u8 id) 340static int set_hpet_sid(struct irte *irte, u8 id)
357{ 341{
358 int i; 342 int i;
359 u16 sid = 0; 343 u16 sid = 0;
@@ -383,7 +367,7 @@ int set_hpet_sid(struct irte *irte, u8 id)
383 return 0; 367 return 0;
384} 368}
385 369
386int set_msi_sid(struct irte *irte, struct pci_dev *dev) 370static int set_msi_sid(struct irte *irte, struct pci_dev *dev)
387{ 371{
388 struct pci_dev *bridge; 372 struct pci_dev *bridge;
389 373
@@ -410,7 +394,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
410 return 0; 394 return 0;
411} 395}
412 396
413static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode) 397static void iommu_set_irq_remapping(struct intel_iommu *iommu, int mode)
414{ 398{
415 u64 addr; 399 u64 addr;
416 u32 sts; 400 u32 sts;
@@ -450,7 +434,7 @@ static void iommu_set_intr_remapping(struct intel_iommu *iommu, int mode)
450} 434}
451 435
452 436
453static int setup_intr_remapping(struct intel_iommu *iommu, int mode) 437static int intel_setup_irq_remapping(struct intel_iommu *iommu, int mode)
454{ 438{
455 struct ir_table *ir_table; 439 struct ir_table *ir_table;
456 struct page *pages; 440 struct page *pages;
@@ -473,14 +457,14 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
473 457
474 ir_table->base = page_address(pages); 458 ir_table->base = page_address(pages);
475 459
476 iommu_set_intr_remapping(iommu, mode); 460 iommu_set_irq_remapping(iommu, mode);
477 return 0; 461 return 0;
478} 462}
479 463
480/* 464/*
481 * Disable Interrupt Remapping. 465 * Disable Interrupt Remapping.
482 */ 466 */
483static void iommu_disable_intr_remapping(struct intel_iommu *iommu) 467static void iommu_disable_irq_remapping(struct intel_iommu *iommu)
484{ 468{
485 unsigned long flags; 469 unsigned long flags;
486 u32 sts; 470 u32 sts;
@@ -519,11 +503,11 @@ static int __init dmar_x2apic_optout(void)
519 return dmar->flags & DMAR_X2APIC_OPT_OUT; 503 return dmar->flags & DMAR_X2APIC_OPT_OUT;
520} 504}
521 505
522int __init intr_remapping_supported(void) 506static int __init intel_irq_remapping_supported(void)
523{ 507{
524 struct dmar_drhd_unit *drhd; 508 struct dmar_drhd_unit *drhd;
525 509
526 if (disable_intremap) 510 if (disable_irq_remap)
527 return 0; 511 return 0;
528 512
529 if (!dmar_ir_support()) 513 if (!dmar_ir_support())
@@ -539,7 +523,7 @@ int __init intr_remapping_supported(void)
539 return 1; 523 return 1;
540} 524}
541 525
542int __init enable_intr_remapping(void) 526static int __init intel_enable_irq_remapping(void)
543{ 527{
544 struct dmar_drhd_unit *drhd; 528 struct dmar_drhd_unit *drhd;
545 int setup = 0; 529 int setup = 0;
@@ -577,7 +561,7 @@ int __init enable_intr_remapping(void)
577 * Disable intr remapping and queued invalidation, if already 561 * Disable intr remapping and queued invalidation, if already
578 * enabled prior to OS handover. 562 * enabled prior to OS handover.
579 */ 563 */
580 iommu_disable_intr_remapping(iommu); 564 iommu_disable_irq_remapping(iommu);
581 565
582 dmar_disable_qi(iommu); 566 dmar_disable_qi(iommu);
583 } 567 }
@@ -623,7 +607,7 @@ int __init enable_intr_remapping(void)
623 if (!ecap_ir_support(iommu->ecap)) 607 if (!ecap_ir_support(iommu->ecap))
624 continue; 608 continue;
625 609
626 if (setup_intr_remapping(iommu, eim)) 610 if (intel_setup_irq_remapping(iommu, eim))
627 goto error; 611 goto error;
628 612
629 setup = 1; 613 setup = 1;
@@ -632,7 +616,7 @@ int __init enable_intr_remapping(void)
632 if (!setup) 616 if (!setup)
633 goto error; 617 goto error;
634 618
635 intr_remapping_enabled = 1; 619 irq_remapping_enabled = 1;
636 pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic"); 620 pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
637 621
638 return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; 622 return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
@@ -775,14 +759,14 @@ int __init parse_ioapics_under_ir(void)
775 759
776int __init ir_dev_scope_init(void) 760int __init ir_dev_scope_init(void)
777{ 761{
778 if (!intr_remapping_enabled) 762 if (!irq_remapping_enabled)
779 return 0; 763 return 0;
780 764
781 return dmar_dev_scope_init(); 765 return dmar_dev_scope_init();
782} 766}
783rootfs_initcall(ir_dev_scope_init); 767rootfs_initcall(ir_dev_scope_init);
784 768
785void disable_intr_remapping(void) 769static void disable_irq_remapping(void)
786{ 770{
787 struct dmar_drhd_unit *drhd; 771 struct dmar_drhd_unit *drhd;
788 struct intel_iommu *iommu = NULL; 772 struct intel_iommu *iommu = NULL;
@@ -794,11 +778,11 @@ void disable_intr_remapping(void)
794 if (!ecap_ir_support(iommu->ecap)) 778 if (!ecap_ir_support(iommu->ecap))
795 continue; 779 continue;
796 780
797 iommu_disable_intr_remapping(iommu); 781 iommu_disable_irq_remapping(iommu);
798 } 782 }
799} 783}
800 784
801int reenable_intr_remapping(int eim) 785static int reenable_irq_remapping(int eim)
802{ 786{
803 struct dmar_drhd_unit *drhd; 787 struct dmar_drhd_unit *drhd;
804 int setup = 0; 788 int setup = 0;
@@ -816,7 +800,7 @@ int reenable_intr_remapping(int eim)
816 continue; 800 continue;
817 801
818 /* Set up interrupt remapping for iommu.*/ 802 /* Set up interrupt remapping for iommu.*/
819 iommu_set_intr_remapping(iommu, eim); 803 iommu_set_irq_remapping(iommu, eim);
820 setup = 1; 804 setup = 1;
821 } 805 }
822 806
@@ -832,3 +816,254 @@ error:
832 return -1; 816 return -1;
833} 817}
834 818
819static void prepare_irte(struct irte *irte, int vector,
820 unsigned int dest)
821{
822 memset(irte, 0, sizeof(*irte));
823
824 irte->present = 1;
825 irte->dst_mode = apic->irq_dest_mode;
826 /*
827 * Trigger mode in the IRTE will always be edge, and for IO-APIC, the
828 * actual level or edge trigger will be setup in the IO-APIC
829 * RTE. This will help simplify level triggered irq migration.
830 * For more details, see the comments (in io_apic.c) explainig IO-APIC
831 * irq migration in the presence of interrupt-remapping.
832 */
833 irte->trigger_mode = 0;
834 irte->dlvry_mode = apic->irq_delivery_mode;
835 irte->vector = vector;
836 irte->dest_id = IRTE_DEST(dest);
837 irte->redir_hint = 1;
838}
839
840static int intel_setup_ioapic_entry(int irq,
841 struct IO_APIC_route_entry *route_entry,
842 unsigned int destination, int vector,
843 struct io_apic_irq_attr *attr)
844{
845 int ioapic_id = mpc_ioapic_id(attr->ioapic);
846 struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id);
847 struct IR_IO_APIC_route_entry *entry;
848 struct irte irte;
849 int index;
850
851 if (!iommu) {
852 pr_warn("No mapping iommu for ioapic %d\n", ioapic_id);
853 return -ENODEV;
854 }
855
856 entry = (struct IR_IO_APIC_route_entry *)route_entry;
857
858 index = alloc_irte(iommu, irq, 1);
859 if (index < 0) {
860 pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id);
861 return -ENOMEM;
862 }
863
864 prepare_irte(&irte, vector, destination);
865
866 /* Set source-id of interrupt request */
867 set_ioapic_sid(&irte, ioapic_id);
868
869 modify_irte(irq, &irte);
870
871 apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: "
872 "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d "
873 "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X "
874 "Avail:%X Vector:%02X Dest:%08X "
875 "SID:%04X SQ:%X SVT:%X)\n",
876 attr->ioapic, irte.present, irte.fpd, irte.dst_mode,
877 irte.redir_hint, irte.trigger_mode, irte.dlvry_mode,
878 irte.avail, irte.vector, irte.dest_id,
879 irte.sid, irte.sq, irte.svt);
880
881 memset(entry, 0, sizeof(*entry));
882
883 entry->index2 = (index >> 15) & 0x1;
884 entry->zero = 0;
885 entry->format = 1;
886 entry->index = (index & 0x7fff);
887 /*
888 * IO-APIC RTE will be configured with virtual vector.
889 * irq handler will do the explicit EOI to the io-apic.
890 */
891 entry->vector = attr->ioapic_pin;
892 entry->mask = 0; /* enable IRQ */
893 entry->trigger = attr->trigger;
894 entry->polarity = attr->polarity;
895
896 /* Mask level triggered irqs.
897 * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
898 */
899 if (attr->trigger)
900 entry->mask = 1;
901
902 return 0;
903}
904
905#ifdef CONFIG_SMP
906/*
907 * Migrate the IO-APIC irq in the presence of intr-remapping.
908 *
909 * For both level and edge triggered, irq migration is a simple atomic
910 * update(of vector and cpu destination) of IRTE and flush the hardware cache.
911 *
912 * For level triggered, we eliminate the io-apic RTE modification (with the
913 * updated vector information), by using a virtual vector (io-apic pin number).
914 * Real vector that is used for interrupting cpu will be coming from
915 * the interrupt-remapping table entry.
916 *
917 * As the migration is a simple atomic update of IRTE, the same mechanism
918 * is used to migrate MSI irq's in the presence of interrupt-remapping.
919 */
920static int
921intel_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
922 bool force)
923{
924 struct irq_cfg *cfg = data->chip_data;
925 unsigned int dest, irq = data->irq;
926 struct irte irte;
927
928 if (!cpumask_intersects(mask, cpu_online_mask))
929 return -EINVAL;
930
931 if (get_irte(irq, &irte))
932 return -EBUSY;
933
934 if (assign_irq_vector(irq, cfg, mask))
935 return -EBUSY;
936
937 dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask);
938
939 irte.vector = cfg->vector;
940 irte.dest_id = IRTE_DEST(dest);
941
942 /*
943 * Atomically updates the IRTE with the new destination, vector
944 * and flushes the interrupt entry cache.
945 */
946 modify_irte(irq, &irte);
947
948 /*
949 * After this point, all the interrupts will start arriving
950 * at the new destination. So, time to cleanup the previous
951 * vector allocation.
952 */
953 if (cfg->move_in_progress)
954 send_cleanup_vector(cfg);
955
956 cpumask_copy(data->affinity, mask);
957 return 0;
958}
959#endif
960
961static void intel_compose_msi_msg(struct pci_dev *pdev,
962 unsigned int irq, unsigned int dest,
963 struct msi_msg *msg, u8 hpet_id)
964{
965 struct irq_cfg *cfg;
966 struct irte irte;
967 u16 sub_handle = 0;
968 int ir_index;
969
970 cfg = irq_get_chip_data(irq);
971
972 ir_index = map_irq_to_irte_handle(irq, &sub_handle);
973 BUG_ON(ir_index == -1);
974
975 prepare_irte(&irte, cfg->vector, dest);
976
977 /* Set source-id of interrupt request */
978 if (pdev)
979 set_msi_sid(&irte, pdev);
980 else
981 set_hpet_sid(&irte, hpet_id);
982
983 modify_irte(irq, &irte);
984
985 msg->address_hi = MSI_ADDR_BASE_HI;
986 msg->data = sub_handle;
987 msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT |
988 MSI_ADDR_IR_SHV |
989 MSI_ADDR_IR_INDEX1(ir_index) |
990 MSI_ADDR_IR_INDEX2(ir_index);
991}
992
993/*
994 * Map the PCI dev to the corresponding remapping hardware unit
995 * and allocate 'nvec' consecutive interrupt-remapping table entries
996 * in it.
997 */
998static int intel_msi_alloc_irq(struct pci_dev *dev, int irq, int nvec)
999{
1000 struct intel_iommu *iommu;
1001 int index;
1002
1003 iommu = map_dev_to_ir(dev);
1004 if (!iommu) {
1005 printk(KERN_ERR
1006 "Unable to map PCI %s to iommu\n", pci_name(dev));
1007 return -ENOENT;
1008 }
1009
1010 index = alloc_irte(iommu, irq, nvec);
1011 if (index < 0) {
1012 printk(KERN_ERR
1013 "Unable to allocate %d IRTE for PCI %s\n", nvec,
1014 pci_name(dev));
1015 return -ENOSPC;
1016 }
1017 return index;
1018}
1019
1020static int intel_msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
1021 int index, int sub_handle)
1022{
1023 struct intel_iommu *iommu;
1024
1025 iommu = map_dev_to_ir(pdev);
1026 if (!iommu)
1027 return -ENOENT;
1028 /*
1029 * setup the mapping between the irq and the IRTE
1030 * base index, the sub_handle pointing to the
1031 * appropriate interrupt remap table entry.
1032 */
1033 set_irte_irq(irq, iommu, index, sub_handle);
1034
1035 return 0;
1036}
1037
1038static int intel_setup_hpet_msi(unsigned int irq, unsigned int id)
1039{
1040 struct intel_iommu *iommu = map_hpet_to_ir(id);
1041 int index;
1042
1043 if (!iommu)
1044 return -1;
1045
1046 index = alloc_irte(iommu, irq, 1);
1047 if (index < 0)
1048 return -1;
1049
1050 return 0;
1051}
1052
1053struct irq_remap_ops intel_irq_remap_ops = {
1054 .supported = intel_irq_remapping_supported,
1055 .prepare = dmar_table_init,
1056 .enable = intel_enable_irq_remapping,
1057 .disable = disable_irq_remapping,
1058 .reenable = reenable_irq_remapping,
1059 .enable_faulting = enable_drhd_fault_handling,
1060 .setup_ioapic_entry = intel_setup_ioapic_entry,
1061#ifdef CONFIG_SMP
1062 .set_affinity = intel_ioapic_set_affinity,
1063#endif
1064 .free_irq = free_irte,
1065 .compose_msi_msg = intel_compose_msi_msg,
1066 .msi_alloc_irq = intel_msi_alloc_irq,
1067 .msi_setup_irq = intel_msi_setup_irq,
1068 .setup_hpet_msi = intel_setup_hpet_msi,
1069};
diff --git a/drivers/iommu/intr_remapping.h b/drivers/iommu/intr_remapping.h
deleted file mode 100644
index 5662fecfee60..000000000000
--- a/drivers/iommu/intr_remapping.h
+++ /dev/null
@@ -1,17 +0,0 @@
1#include <linux/intel-iommu.h>
2
3struct ioapic_scope {
4 struct intel_iommu *iommu;
5 unsigned int id;
6 unsigned int bus; /* PCI bus number */
7 unsigned int devfn; /* PCI devfn number */
8};
9
10struct hpet_scope {
11 struct intel_iommu *iommu;
12 u8 id;
13 unsigned int bus;
14 unsigned int devfn;
15};
16
17#define IR_X2APIC_MODE(mode) (mode ? (1 << 11) : 0)
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
new file mode 100644
index 000000000000..40cda8e98d87
--- /dev/null
+++ b/drivers/iommu/irq_remapping.c
@@ -0,0 +1,166 @@
1#include <linux/kernel.h>
2#include <linux/string.h>
3#include <linux/errno.h>
4
5#include "irq_remapping.h"
6
7int irq_remapping_enabled;
8
9int disable_irq_remap;
10int disable_sourceid_checking;
11int no_x2apic_optout;
12
13static struct irq_remap_ops *remap_ops;
14
15static __init int setup_nointremap(char *str)
16{
17 disable_irq_remap = 1;
18 return 0;
19}
20early_param("nointremap", setup_nointremap);
21
22static __init int setup_irqremap(char *str)
23{
24 if (!str)
25 return -EINVAL;
26
27 while (*str) {
28 if (!strncmp(str, "on", 2))
29 disable_irq_remap = 0;
30 else if (!strncmp(str, "off", 3))
31 disable_irq_remap = 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}
44early_param("intremap", setup_irqremap);
45
46void __init setup_irq_remapping_ops(void)
47{
48 remap_ops = &intel_irq_remap_ops;
49}
50
51int irq_remapping_supported(void)
52{
53 if (disable_irq_remap)
54 return 0;
55
56 if (!remap_ops || !remap_ops->supported)
57 return 0;
58
59 return remap_ops->supported();
60}
61
62int __init irq_remapping_prepare(void)
63{
64 if (!remap_ops || !remap_ops->prepare)
65 return -ENODEV;
66
67 return remap_ops->prepare();
68}
69
70int __init irq_remapping_enable(void)
71{
72 if (!remap_ops || !remap_ops->enable)
73 return -ENODEV;
74
75 return remap_ops->enable();
76}
77
78void irq_remapping_disable(void)
79{
80 if (!remap_ops || !remap_ops->disable)
81 return;
82
83 remap_ops->disable();
84}
85
86int irq_remapping_reenable(int mode)
87{
88 if (!remap_ops || !remap_ops->reenable)
89 return 0;
90
91 return remap_ops->reenable(mode);
92}
93
94int __init irq_remap_enable_fault_handling(void)
95{
96 if (!remap_ops || !remap_ops->enable_faulting)
97 return -ENODEV;
98
99 return remap_ops->enable_faulting();
100}
101
102int setup_ioapic_remapped_entry(int irq,
103 struct IO_APIC_route_entry *entry,
104 unsigned int destination, int vector,
105 struct io_apic_irq_attr *attr)
106{
107 if (!remap_ops || !remap_ops->setup_ioapic_entry)
108 return -ENODEV;
109
110 return remap_ops->setup_ioapic_entry(irq, entry, destination,
111 vector, attr);
112}
113
114#ifdef CONFIG_SMP
115int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask,
116 bool force)
117{
118 if (!remap_ops || !remap_ops->set_affinity)
119 return 0;
120
121 return remap_ops->set_affinity(data, mask, force);
122}
123#endif
124
125void free_remapped_irq(int irq)
126{
127 if (!remap_ops || !remap_ops->free_irq)
128 return;
129
130 remap_ops->free_irq(irq);
131}
132
133void compose_remapped_msi_msg(struct pci_dev *pdev,
134 unsigned int irq, unsigned int dest,
135 struct msi_msg *msg, u8 hpet_id)
136{
137 if (!remap_ops || !remap_ops->compose_msi_msg)
138 return;
139
140 remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
141}
142
143int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
144{
145 if (!remap_ops || !remap_ops->msi_alloc_irq)
146 return -ENODEV;
147
148 return remap_ops->msi_alloc_irq(pdev, irq, nvec);
149}
150
151int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
152 int index, int sub_handle)
153{
154 if (!remap_ops || !remap_ops->msi_setup_irq)
155 return -ENODEV;
156
157 return remap_ops->msi_setup_irq(pdev, irq, index, sub_handle);
158}
159
160int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
161{
162 if (!remap_ops || !remap_ops->setup_hpet_msi)
163 return -ENODEV;
164
165 return remap_ops->setup_hpet_msi(irq, id);
166}
diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h
new file mode 100644
index 000000000000..be9d72950c51
--- /dev/null
+++ b/drivers/iommu/irq_remapping.h
@@ -0,0 +1,90 @@
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 __IRQ_REMAPPING_H
23#define __IRQ_REMAPPING_H
24
25#ifdef CONFIG_IRQ_REMAP
26
27struct IO_APIC_route_entry;
28struct io_apic_irq_attr;
29struct irq_data;
30struct cpumask;
31struct pci_dev;
32struct msi_msg;
33
34extern int disable_irq_remap;
35extern int disable_sourceid_checking;
36extern int no_x2apic_optout;
37
38struct irq_remap_ops {
39 /* Check whether Interrupt Remapping is supported */
40 int (*supported)(void);
41
42 /* Initializes hardware and makes it ready for remapping interrupts */
43 int (*prepare)(void);
44
45 /* Enables the remapping hardware */
46 int (*enable)(void);
47
48 /* Disables the remapping hardware */
49 void (*disable)(void);
50
51 /* Reenables the remapping hardware */
52 int (*reenable)(int);
53
54 /* Enable fault handling */
55 int (*enable_faulting)(void);
56
57 /* IO-APIC setup routine */
58 int (*setup_ioapic_entry)(int irq, struct IO_APIC_route_entry *,
59 unsigned int, int,
60 struct io_apic_irq_attr *);
61
62#ifdef CONFIG_SMP
63 /* Set the CPU affinity of a remapped interrupt */
64 int (*set_affinity)(struct irq_data *data, const struct cpumask *mask,
65 bool force);
66#endif
67
68 /* Free an IRQ */
69 int (*free_irq)(int);
70
71 /* Create MSI msg to use for interrupt remapping */
72 void (*compose_msi_msg)(struct pci_dev *,
73 unsigned int, unsigned int,
74 struct msi_msg *, u8);
75
76 /* Allocate remapping resources for MSI */
77 int (*msi_alloc_irq)(struct pci_dev *, int, int);
78
79 /* Setup the remapped MSI irq */
80 int (*msi_setup_irq)(struct pci_dev *, unsigned int, int, int);
81
82 /* Setup interrupt remapping for an HPET MSI */
83 int (*setup_hpet_msi)(unsigned int, unsigned int);
84};
85
86extern struct irq_remap_ops intel_irq_remap_ops;
87
88#endif /* CONFIG_IRQ_REMAP */
89
90#endif /* __IRQ_REMAPPING_H */