aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/iommu
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-19 22:07:27 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-19 22:07:27 -0500
commit5800700f66678ea5c85e7d62b138416070bf7f60 (patch)
tree4aeff1edb0429eb222ddea97701d1ab1efbca2d0 /drivers/iommu
parent266d7ad7f4fe2f44b91561f5b812115c1b3018ab (diff)
parentaf8d102f999a41c0189bd2cce488bac2ee88c29b (diff)
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86/apic changes from Ingo Molnar: "Main changes: - Multiple MSI support added to the APIC, PCI and AHCI code - acked by all relevant maintainers, by Alexander Gordeev. The advantage is that multiple AHCI ports can have multiple MSI irqs assigned, and can thus spread to multiple CPUs. [ Drivers can make use of this new facility via the pci_enable_msi_block_auto() method ] - x86 IOAPIC code from interrupt remapping cleanups from Joerg Roedel: These patches move all interrupt remapping specific checks out of the x86 core code and replaces the respective call-sites with function pointers. As a result the interrupt remapping code is better abstraced from x86 core interrupt handling code. - Various smaller improvements, fixes and cleanups." * 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (26 commits) x86/intel/irq_remapping: Clean up x2apic opt-out security warning mess x86, kvm: Fix intialization warnings in kvm.c x86, irq: Move irq_remapped out of x86 core code x86, io_apic: Introduce eoi_ioapic_pin call-back x86, msi: Introduce x86_msi.compose_msi_msg call-back x86, irq: Introduce setup_remapped_irq() x86, irq: Move irq_remapped() check into free_remapped_irq x86, io-apic: Remove !irq_remapped() check from __target_IO_APIC_irq() x86, io-apic: Move CONFIG_IRQ_REMAP code out of x86 core x86, irq: Add data structure to keep AMD specific irq remapping information x86, irq: Move irq_remapping_enabled declaration to iommu code x86, io_apic: Remove irq_remapping_enabled check in setup_timer_IRQ0_pin x86, io_apic: Move irq_remapping_enabled checks out of check_timer() x86, io_apic: Convert setup_ioapic_entry to function pointer x86, io_apic: Introduce set_affinity function pointer x86, msi: Use IRQ remapping specific setup_msi_irqs routine x86, hpet: Introduce x86_msi_ops.setup_hpet_msi x86, io_apic: Introduce x86_io_apic_ops.print_entries for debugging x86, io_apic: Introduce x86_io_apic_ops.disable() x86, apic: Mask IO-APIC and PIC unconditionally on LAPIC resume ...
Diffstat (limited to 'drivers/iommu')
-rw-r--r--drivers/iommu/amd_iommu.c8
-rw-r--r--drivers/iommu/dmar.c2
-rw-r--r--drivers/iommu/intel-iommu.c2
-rw-r--r--drivers/iommu/intel_irq_remapping.c48
-rw-r--r--drivers/iommu/irq_remapping.c231
-rw-r--r--drivers/iommu/irq_remapping.h1
6 files changed, 270 insertions, 22 deletions
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index c1c74e030a58..d33eaaf783ad 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -4017,10 +4017,10 @@ static int alloc_irq_index(struct irq_cfg *cfg, u16 devid, int count)
4017 4017
4018 index -= count - 1; 4018 index -= count - 1;
4019 4019
4020 cfg->remapped = 1;
4020 irte_info = &cfg->irq_2_iommu; 4021 irte_info = &cfg->irq_2_iommu;
4021 irte_info->sub_handle = devid; 4022 irte_info->sub_handle = devid;
4022 irte_info->irte_index = index; 4023 irte_info->irte_index = index;
4023 irte_info->iommu = (void *)cfg;
4024 4024
4025 goto out; 4025 goto out;
4026 } 4026 }
@@ -4127,9 +4127,9 @@ static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry,
4127 index = attr->ioapic_pin; 4127 index = attr->ioapic_pin;
4128 4128
4129 /* Setup IRQ remapping info */ 4129 /* Setup IRQ remapping info */
4130 cfg->remapped = 1;
4130 irte_info->sub_handle = devid; 4131 irte_info->sub_handle = devid;
4131 irte_info->irte_index = index; 4132 irte_info->irte_index = index;
4132 irte_info->iommu = (void *)cfg;
4133 4133
4134 /* Setup IRTE for IOMMU */ 4134 /* Setup IRTE for IOMMU */
4135 irte.val = 0; 4135 irte.val = 0;
@@ -4288,9 +4288,9 @@ static int msi_setup_irq(struct pci_dev *pdev, unsigned int irq,
4288 devid = get_device_id(&pdev->dev); 4288 devid = get_device_id(&pdev->dev);
4289 irte_info = &cfg->irq_2_iommu; 4289 irte_info = &cfg->irq_2_iommu;
4290 4290
4291 cfg->remapped = 1;
4291 irte_info->sub_handle = devid; 4292 irte_info->sub_handle = devid;
4292 irte_info->irte_index = index + offset; 4293 irte_info->irte_index = index + offset;
4293 irte_info->iommu = (void *)cfg;
4294 4294
4295 return 0; 4295 return 0;
4296} 4296}
@@ -4314,9 +4314,9 @@ static int setup_hpet_msi(unsigned int irq, unsigned int id)
4314 if (index < 0) 4314 if (index < 0)
4315 return index; 4315 return index;
4316 4316
4317 cfg->remapped = 1;
4317 irte_info->sub_handle = devid; 4318 irte_info->sub_handle = devid;
4318 irte_info->irte_index = index; 4319 irte_info->irte_index = index;
4319 irte_info->iommu = (void *)cfg;
4320 4320
4321 return 0; 4321 return 0;
4322} 4322}
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 86e2f4a62b9a..174bb654453d 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -41,6 +41,8 @@
41#include <asm/irq_remapping.h> 41#include <asm/irq_remapping.h>
42#include <asm/iommu_table.h> 42#include <asm/iommu_table.h>
43 43
44#include "irq_remapping.h"
45
44/* No locks are needed as DMA remapping hardware unit 46/* No locks are needed as DMA remapping hardware unit
45 * list is constructed at boot time and hotplug of 47 * list is constructed at boot time and hotplug of
46 * these units are not supported by the architecture. 48 * these units are not supported by the architecture.
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index eca28014ef3e..43d5c8b8e7ad 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -46,6 +46,8 @@
46#include <asm/cacheflush.h> 46#include <asm/cacheflush.h>
47#include <asm/iommu.h> 47#include <asm/iommu.h>
48 48
49#include "irq_remapping.h"
50
49#define ROOT_SIZE VTD_PAGE_SIZE 51#define ROOT_SIZE VTD_PAGE_SIZE
50#define CONTEXT_SIZE VTD_PAGE_SIZE 52#define CONTEXT_SIZE VTD_PAGE_SIZE
51 53
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index af8904de1d44..f3b8f23b5d8f 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -68,6 +68,7 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
68{ 68{
69 struct ir_table *table = iommu->ir_table; 69 struct ir_table *table = iommu->ir_table;
70 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); 70 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
71 struct irq_cfg *cfg = irq_get_chip_data(irq);
71 u16 index, start_index; 72 u16 index, start_index;
72 unsigned int mask = 0; 73 unsigned int mask = 0;
73 unsigned long flags; 74 unsigned long flags;
@@ -115,6 +116,7 @@ static int alloc_irte(struct intel_iommu *iommu, int irq, u16 count)
115 for (i = index; i < index + count; i++) 116 for (i = index; i < index + count; i++)
116 table->base[i].present = 1; 117 table->base[i].present = 1;
117 118
119 cfg->remapped = 1;
118 irq_iommu->iommu = iommu; 120 irq_iommu->iommu = iommu;
119 irq_iommu->irte_index = index; 121 irq_iommu->irte_index = index;
120 irq_iommu->sub_handle = 0; 122 irq_iommu->sub_handle = 0;
@@ -155,6 +157,7 @@ static int map_irq_to_irte_handle(int irq, u16 *sub_handle)
155static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle) 157static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subhandle)
156{ 158{
157 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq); 159 struct irq_2_iommu *irq_iommu = irq_2_iommu(irq);
160 struct irq_cfg *cfg = irq_get_chip_data(irq);
158 unsigned long flags; 161 unsigned long flags;
159 162
160 if (!irq_iommu) 163 if (!irq_iommu)
@@ -162,6 +165,7 @@ static int set_irte_irq(int irq, struct intel_iommu *iommu, u16 index, u16 subha
162 165
163 raw_spin_lock_irqsave(&irq_2_ir_lock, flags); 166 raw_spin_lock_irqsave(&irq_2_ir_lock, flags);
164 167
168 cfg->remapped = 1;
165 irq_iommu->iommu = iommu; 169 irq_iommu->iommu = iommu;
166 irq_iommu->irte_index = index; 170 irq_iommu->irte_index = index;
167 irq_iommu->sub_handle = subhandle; 171 irq_iommu->sub_handle = subhandle;
@@ -425,11 +429,22 @@ static void iommu_set_irq_remapping(struct intel_iommu *iommu, int mode)
425 429
426 /* Enable interrupt-remapping */ 430 /* Enable interrupt-remapping */
427 iommu->gcmd |= DMA_GCMD_IRE; 431 iommu->gcmd |= DMA_GCMD_IRE;
432 iommu->gcmd &= ~DMA_GCMD_CFI; /* Block compatibility-format MSIs */
428 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG); 433 writel(iommu->gcmd, iommu->reg + DMAR_GCMD_REG);
429 434
430 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, 435 IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG,
431 readl, (sts & DMA_GSTS_IRES), sts); 436 readl, (sts & DMA_GSTS_IRES), sts);
432 437
438 /*
439 * With CFI clear in the Global Command register, we should be
440 * protected from dangerous (i.e. compatibility) interrupts
441 * regardless of x2apic status. Check just to be sure.
442 */
443 if (sts & DMA_GSTS_CFIS)
444 WARN(1, KERN_WARNING
445 "Compatibility-format IRQs enabled despite intr remapping;\n"
446 "you are vulnerable to IRQ injection.\n");
447
433 raw_spin_unlock_irqrestore(&iommu->register_lock, flags); 448 raw_spin_unlock_irqrestore(&iommu->register_lock, flags);
434} 449}
435 450
@@ -526,20 +541,24 @@ static int __init intel_irq_remapping_supported(void)
526static int __init intel_enable_irq_remapping(void) 541static int __init intel_enable_irq_remapping(void)
527{ 542{
528 struct dmar_drhd_unit *drhd; 543 struct dmar_drhd_unit *drhd;
544 bool x2apic_present;
529 int setup = 0; 545 int setup = 0;
530 int eim = 0; 546 int eim = 0;
531 547
548 x2apic_present = x2apic_supported();
549
532 if (parse_ioapics_under_ir() != 1) { 550 if (parse_ioapics_under_ir() != 1) {
533 printk(KERN_INFO "Not enable interrupt remapping\n"); 551 printk(KERN_INFO "Not enable interrupt remapping\n");
534 return -1; 552 goto error;
535 } 553 }
536 554
537 if (x2apic_supported()) { 555 if (x2apic_present) {
538 eim = !dmar_x2apic_optout(); 556 eim = !dmar_x2apic_optout();
539 WARN(!eim, KERN_WARNING 557 if (!eim)
540 "Your BIOS is broken and requested that x2apic be disabled\n" 558 printk(KERN_WARNING
541 "This will leave your machine vulnerable to irq-injection attacks\n" 559 "Your BIOS is broken and requested that x2apic be disabled.\n"
542 "Use 'intremap=no_x2apic_optout' to override BIOS request\n"); 560 "This will slightly decrease performance.\n"
561 "Use 'intremap=no_x2apic_optout' to override BIOS request.\n");
543 } 562 }
544 563
545 for_each_drhd_unit(drhd) { 564 for_each_drhd_unit(drhd) {
@@ -578,7 +597,7 @@ static int __init intel_enable_irq_remapping(void)
578 if (eim && !ecap_eim_support(iommu->ecap)) { 597 if (eim && !ecap_eim_support(iommu->ecap)) {
579 printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, " 598 printk(KERN_INFO "DRHD %Lx: EIM not supported by DRHD, "
580 " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap); 599 " ecap %Lx\n", drhd->reg_base_addr, iommu->ecap);
581 return -1; 600 goto error;
582 } 601 }
583 } 602 }
584 603
@@ -594,7 +613,7 @@ static int __init intel_enable_irq_remapping(void)
594 printk(KERN_ERR "DRHD %Lx: failed to enable queued, " 613 printk(KERN_ERR "DRHD %Lx: failed to enable queued, "
595 " invalidation, ecap %Lx, ret %d\n", 614 " invalidation, ecap %Lx, ret %d\n",
596 drhd->reg_base_addr, iommu->ecap, ret); 615 drhd->reg_base_addr, iommu->ecap, ret);
597 return -1; 616 goto error;
598 } 617 }
599 } 618 }
600 619
@@ -617,6 +636,14 @@ static int __init intel_enable_irq_remapping(void)
617 goto error; 636 goto error;
618 637
619 irq_remapping_enabled = 1; 638 irq_remapping_enabled = 1;
639
640 /*
641 * VT-d has a different layout for IO-APIC entries when
642 * interrupt remapping is enabled. So it needs a special routine
643 * to print IO-APIC entries for debugging purposes too.
644 */
645 x86_io_apic_ops.print_entries = intel_ir_io_apic_print_entries;
646
620 pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic"); 647 pr_info("Enabled IRQ remapping in %s mode\n", eim ? "x2apic" : "xapic");
621 648
622 return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE; 649 return eim ? IRQ_REMAP_X2APIC_MODE : IRQ_REMAP_XAPIC_MODE;
@@ -625,6 +652,11 @@ error:
625 /* 652 /*
626 * handle error condition gracefully here! 653 * handle error condition gracefully here!
627 */ 654 */
655
656 if (x2apic_present)
657 WARN(1, KERN_WARNING
658 "Failed to enable irq remapping. You are vulnerable to irq-injection attacks.\n");
659
628 return -1; 660 return -1;
629} 661}
630 662
diff --git a/drivers/iommu/irq_remapping.c b/drivers/iommu/irq_remapping.c
index faf85d6e33fe..d56f8c17c5fe 100644
--- a/drivers/iommu/irq_remapping.c
+++ b/drivers/iommu/irq_remapping.c
@@ -1,11 +1,18 @@
1#include <linux/seq_file.h>
2#include <linux/cpumask.h>
1#include <linux/kernel.h> 3#include <linux/kernel.h>
2#include <linux/string.h> 4#include <linux/string.h>
3#include <linux/cpumask.h> 5#include <linux/cpumask.h>
4#include <linux/errno.h> 6#include <linux/errno.h>
5#include <linux/msi.h> 7#include <linux/msi.h>
8#include <linux/irq.h>
9#include <linux/pci.h>
6 10
7#include <asm/hw_irq.h> 11#include <asm/hw_irq.h>
8#include <asm/irq_remapping.h> 12#include <asm/irq_remapping.h>
13#include <asm/processor.h>
14#include <asm/x86_init.h>
15#include <asm/apic.h>
9 16
10#include "irq_remapping.h" 17#include "irq_remapping.h"
11 18
@@ -17,6 +24,152 @@ int no_x2apic_optout;
17 24
18static struct irq_remap_ops *remap_ops; 25static struct irq_remap_ops *remap_ops;
19 26
27static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec);
28static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
29 int index, int sub_handle);
30static int set_remapped_irq_affinity(struct irq_data *data,
31 const struct cpumask *mask,
32 bool force);
33
34static bool irq_remapped(struct irq_cfg *cfg)
35{
36 return (cfg->remapped == 1);
37}
38
39static void irq_remapping_disable_io_apic(void)
40{
41 /*
42 * With interrupt-remapping, for now we will use virtual wire A
43 * mode, as virtual wire B is little complex (need to configure
44 * both IOAPIC RTE as well as interrupt-remapping table entry).
45 * As this gets called during crash dump, keep this simple for
46 * now.
47 */
48 if (cpu_has_apic || apic_from_smp_config())
49 disconnect_bsp_APIC(0);
50}
51
52static int do_setup_msi_irqs(struct pci_dev *dev, int nvec)
53{
54 int node, ret, sub_handle, index = 0;
55 unsigned int irq;
56 struct msi_desc *msidesc;
57
58 nvec = __roundup_pow_of_two(nvec);
59
60 WARN_ON(!list_is_singular(&dev->msi_list));
61 msidesc = list_entry(dev->msi_list.next, struct msi_desc, list);
62 WARN_ON(msidesc->irq);
63 WARN_ON(msidesc->msi_attrib.multiple);
64
65 node = dev_to_node(&dev->dev);
66 irq = __create_irqs(get_nr_irqs_gsi(), nvec, node);
67 if (irq == 0)
68 return -ENOSPC;
69
70 msidesc->msi_attrib.multiple = ilog2(nvec);
71 for (sub_handle = 0; sub_handle < nvec; sub_handle++) {
72 if (!sub_handle) {
73 index = msi_alloc_remapped_irq(dev, irq, nvec);
74 if (index < 0) {
75 ret = index;
76 goto error;
77 }
78 } else {
79 ret = msi_setup_remapped_irq(dev, irq + sub_handle,
80 index, sub_handle);
81 if (ret < 0)
82 goto error;
83 }
84 ret = setup_msi_irq(dev, msidesc, irq, sub_handle);
85 if (ret < 0)
86 goto error;
87 }
88 return 0;
89
90error:
91 destroy_irqs(irq, nvec);
92
93 /*
94 * Restore altered MSI descriptor fields and prevent just destroyed
95 * IRQs from tearing down again in default_teardown_msi_irqs()
96 */
97 msidesc->irq = 0;
98 msidesc->msi_attrib.multiple = 0;
99
100 return ret;
101}
102
103static int do_setup_msix_irqs(struct pci_dev *dev, int nvec)
104{
105 int node, ret, sub_handle, index = 0;
106 struct msi_desc *msidesc;
107 unsigned int irq;
108
109 node = dev_to_node(&dev->dev);
110 irq = get_nr_irqs_gsi();
111 sub_handle = 0;
112
113 list_for_each_entry(msidesc, &dev->msi_list, list) {
114
115 irq = create_irq_nr(irq, node);
116 if (irq == 0)
117 return -1;
118
119 if (sub_handle == 0)
120 ret = index = msi_alloc_remapped_irq(dev, irq, nvec);
121 else
122 ret = msi_setup_remapped_irq(dev, irq, index, sub_handle);
123
124 if (ret < 0)
125 goto error;
126
127 ret = setup_msi_irq(dev, msidesc, irq, 0);
128 if (ret < 0)
129 goto error;
130
131 sub_handle += 1;
132 irq += 1;
133 }
134
135 return 0;
136
137error:
138 destroy_irq(irq);
139 return ret;
140}
141
142static int irq_remapping_setup_msi_irqs(struct pci_dev *dev,
143 int nvec, int type)
144{
145 if (type == PCI_CAP_ID_MSI)
146 return do_setup_msi_irqs(dev, nvec);
147 else
148 return do_setup_msix_irqs(dev, nvec);
149}
150
151void eoi_ioapic_pin_remapped(int apic, int pin, int vector)
152{
153 /*
154 * Intr-remapping uses pin number as the virtual vector
155 * in the RTE. Actual vector is programmed in
156 * intr-remapping table entry. Hence for the io-apic
157 * EOI we use the pin number.
158 */
159 io_apic_eoi(apic, pin);
160}
161
162static void __init irq_remapping_modify_x86_ops(void)
163{
164 x86_io_apic_ops.disable = irq_remapping_disable_io_apic;
165 x86_io_apic_ops.set_affinity = set_remapped_irq_affinity;
166 x86_io_apic_ops.setup_entry = setup_ioapic_remapped_entry;
167 x86_io_apic_ops.eoi_ioapic_pin = eoi_ioapic_pin_remapped;
168 x86_msi.setup_msi_irqs = irq_remapping_setup_msi_irqs;
169 x86_msi.setup_hpet_msi = setup_hpet_msi_remapped;
170 x86_msi.compose_msi_msg = compose_remapped_msi_msg;
171}
172
20static __init int setup_nointremap(char *str) 173static __init int setup_nointremap(char *str)
21{ 174{
22 disable_irq_remap = 1; 175 disable_irq_remap = 1;
@@ -79,15 +232,24 @@ int __init irq_remapping_prepare(void)
79 232
80int __init irq_remapping_enable(void) 233int __init irq_remapping_enable(void)
81{ 234{
235 int ret;
236
82 if (!remap_ops || !remap_ops->enable) 237 if (!remap_ops || !remap_ops->enable)
83 return -ENODEV; 238 return -ENODEV;
84 239
85 return remap_ops->enable(); 240 ret = remap_ops->enable();
241
242 if (irq_remapping_enabled)
243 irq_remapping_modify_x86_ops();
244
245 return ret;
86} 246}
87 247
88void irq_remapping_disable(void) 248void irq_remapping_disable(void)
89{ 249{
90 if (!remap_ops || !remap_ops->disable) 250 if (!irq_remapping_enabled ||
251 !remap_ops ||
252 !remap_ops->disable)
91 return; 253 return;
92 254
93 remap_ops->disable(); 255 remap_ops->disable();
@@ -95,7 +257,9 @@ void irq_remapping_disable(void)
95 257
96int irq_remapping_reenable(int mode) 258int irq_remapping_reenable(int mode)
97{ 259{
98 if (!remap_ops || !remap_ops->reenable) 260 if (!irq_remapping_enabled ||
261 !remap_ops ||
262 !remap_ops->reenable)
99 return 0; 263 return 0;
100 264
101 return remap_ops->reenable(mode); 265 return remap_ops->reenable(mode);
@@ -103,6 +267,9 @@ int irq_remapping_reenable(int mode)
103 267
104int __init irq_remap_enable_fault_handling(void) 268int __init irq_remap_enable_fault_handling(void)
105{ 269{
270 if (!irq_remapping_enabled)
271 return 0;
272
106 if (!remap_ops || !remap_ops->enable_faulting) 273 if (!remap_ops || !remap_ops->enable_faulting)
107 return -ENODEV; 274 return -ENODEV;
108 275
@@ -133,23 +300,28 @@ int set_remapped_irq_affinity(struct irq_data *data, const struct cpumask *mask,
133 300
134void free_remapped_irq(int irq) 301void free_remapped_irq(int irq)
135{ 302{
303 struct irq_cfg *cfg = irq_get_chip_data(irq);
304
136 if (!remap_ops || !remap_ops->free_irq) 305 if (!remap_ops || !remap_ops->free_irq)
137 return; 306 return;
138 307
139 remap_ops->free_irq(irq); 308 if (irq_remapped(cfg))
309 remap_ops->free_irq(irq);
140} 310}
141 311
142void compose_remapped_msi_msg(struct pci_dev *pdev, 312void compose_remapped_msi_msg(struct pci_dev *pdev,
143 unsigned int irq, unsigned int dest, 313 unsigned int irq, unsigned int dest,
144 struct msi_msg *msg, u8 hpet_id) 314 struct msi_msg *msg, u8 hpet_id)
145{ 315{
146 if (!remap_ops || !remap_ops->compose_msi_msg) 316 struct irq_cfg *cfg = irq_get_chip_data(irq);
147 return;
148 317
149 remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id); 318 if (!irq_remapped(cfg))
319 native_compose_msi_msg(pdev, irq, dest, msg, hpet_id);
320 else if (remap_ops && remap_ops->compose_msi_msg)
321 remap_ops->compose_msi_msg(pdev, irq, dest, msg, hpet_id);
150} 322}
151 323
152int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) 324static int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
153{ 325{
154 if (!remap_ops || !remap_ops->msi_alloc_irq) 326 if (!remap_ops || !remap_ops->msi_alloc_irq)
155 return -ENODEV; 327 return -ENODEV;
@@ -157,8 +329,8 @@ int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec)
157 return remap_ops->msi_alloc_irq(pdev, irq, nvec); 329 return remap_ops->msi_alloc_irq(pdev, irq, nvec);
158} 330}
159 331
160int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, 332static int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq,
161 int index, int sub_handle) 333 int index, int sub_handle)
162{ 334{
163 if (!remap_ops || !remap_ops->msi_setup_irq) 335 if (!remap_ops || !remap_ops->msi_setup_irq)
164 return -ENODEV; 336 return -ENODEV;
@@ -173,3 +345,42 @@ int setup_hpet_msi_remapped(unsigned int irq, unsigned int id)
173 345
174 return remap_ops->setup_hpet_msi(irq, id); 346 return remap_ops->setup_hpet_msi(irq, id);
175} 347}
348
349void panic_if_irq_remap(const char *msg)
350{
351 if (irq_remapping_enabled)
352 panic(msg);
353}
354
355static void ir_ack_apic_edge(struct irq_data *data)
356{
357 ack_APIC_irq();
358}
359
360static void ir_ack_apic_level(struct irq_data *data)
361{
362 ack_APIC_irq();
363 eoi_ioapic_irq(data->irq, data->chip_data);
364}
365
366static void ir_print_prefix(struct irq_data *data, struct seq_file *p)
367{
368 seq_printf(p, " IR-%s", data->chip->name);
369}
370
371void irq_remap_modify_chip_defaults(struct irq_chip *chip)
372{
373 chip->irq_print_chip = ir_print_prefix;
374 chip->irq_ack = ir_ack_apic_edge;
375 chip->irq_eoi = ir_ack_apic_level;
376 chip->irq_set_affinity = x86_io_apic_ops.set_affinity;
377}
378
379bool setup_remapped_irq(int irq, struct irq_cfg *cfg, struct irq_chip *chip)
380{
381 if (!irq_remapped(cfg))
382 return false;
383 irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
384 irq_remap_modify_chip_defaults(chip);
385 return true;
386}
diff --git a/drivers/iommu/irq_remapping.h b/drivers/iommu/irq_remapping.h
index 95363acb583f..ecb637670405 100644
--- a/drivers/iommu/irq_remapping.h
+++ b/drivers/iommu/irq_remapping.h
@@ -34,6 +34,7 @@ struct msi_msg;
34extern int disable_irq_remap; 34extern int disable_irq_remap;
35extern int disable_sourceid_checking; 35extern int disable_sourceid_checking;
36extern int no_x2apic_optout; 36extern int no_x2apic_optout;
37extern int irq_remapping_enabled;
37 38
38struct irq_remap_ops { 39struct irq_remap_ops {
39 /* Check whether Interrupt Remapping is supported */ 40 /* Check whether Interrupt Remapping is supported */