diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 22:23:41 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-21 22:23:41 -0400 |
commit | abd209b7083b2f3a2a19e522f688e7569f284e5d (patch) | |
tree | 51b0d86562c2293df27ba8b6effc7a5ddd7c30f0 /arch | |
parent | 513de477a09f770e42ad042bf830565d9c73a158 (diff) | |
parent | fefe1ed1398b81e3fadc92d11d91162d343c8836 (diff) |
Merge branch 'core-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull iommu core changes from Ingo Molnar:
"The IOMMU changes in this cycle are mostly about factoring out
Intel-VT-d specific IRQ remapping details and introducing struct
irq_remap_ops, in preparation for AMD specific hardware."
* 'core-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
iommu: Fix off by one in dmar_get_fault_reason()
irq_remap: Fix the 'sub_handle' uninitialized warning
irq_remap: Fix UP build failure
irq_remap: Fix compiler warning with CONFIG_IRQ_REMAP=y
iommu: rename intr_remapping.[ch] to irq_remapping.[ch]
iommu: rename intr_remapping references to irq_remapping
x86, iommu/vt-d: Clean up interfaces for interrupt remapping
iommu/vt-d: Convert MSI remapping setup to remap_ops
iommu/vt-d: Convert free_irte into a remap_ops callback
iommu/vt-d: Convert IR set_affinity function to remap_ops
iommu/vt-d: Convert IR ioapic-setup to use remap_ops
iommu/vt-d: Convert missing apic.c intr-remapping call to remap_ops
iommu/vt-d: Make intr-remapping initialization generic
iommu: Rename intr_remapping files to intel_intr_remapping
Diffstat (limited to 'arch')
-rw-r--r-- | arch/ia64/include/asm/irq_remapping.h | 4 | ||||
-rw-r--r-- | arch/x86/include/asm/irq_remapping.h | 118 | ||||
-rw-r--r-- | arch/x86/kernel/apic/apic.c | 30 | ||||
-rw-r--r-- | arch/x86/kernel/apic/io_apic.c | 297 |
4 files changed, 169 insertions, 280 deletions
diff --git a/arch/ia64/include/asm/irq_remapping.h b/arch/ia64/include/asm/irq_remapping.h new file mode 100644 index 000000000000..a8687b1d8906 --- /dev/null +++ b/arch/ia64/include/asm/irq_remapping.h | |||
@@ -0,0 +1,4 @@ | |||
1 | #ifndef __IA64_INTR_REMAPPING_H | ||
2 | #define __IA64_INTR_REMAPPING_H | ||
3 | #define irq_remapping_enabled 0 | ||
4 | #endif | ||
diff --git a/arch/x86/include/asm/irq_remapping.h b/arch/x86/include/asm/irq_remapping.h index 47d99934580f..5fb9bbbd2f14 100644 --- a/arch/x86/include/asm/irq_remapping.h +++ b/arch/x86/include/asm/irq_remapping.h | |||
@@ -1,45 +1,101 @@ | |||
1 | #ifndef _ASM_X86_IRQ_REMAPPING_H | 1 | /* |
2 | #define _ASM_X86_IRQ_REMAPPING_H | 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 | */ | ||
3 | 21 | ||
4 | #define IRTE_DEST(dest) ((x2apic_mode) ? dest : dest << 8) | 22 | #ifndef __X86_IRQ_REMAPPING_H |
23 | #define __X86_IRQ_REMAPPING_H | ||
24 | |||
25 | #include <asm/io_apic.h> | ||
5 | 26 | ||
6 | #ifdef CONFIG_IRQ_REMAP | 27 | #ifdef CONFIG_IRQ_REMAP |
7 | static void irq_remap_modify_chip_defaults(struct irq_chip *chip); | 28 | |
8 | static inline void prepare_irte(struct irte *irte, int vector, | 29 | extern int irq_remapping_enabled; |
9 | unsigned int dest) | 30 | |
31 | extern void setup_irq_remapping_ops(void); | ||
32 | extern int irq_remapping_supported(void); | ||
33 | extern int irq_remapping_prepare(void); | ||
34 | extern int irq_remapping_enable(void); | ||
35 | extern void irq_remapping_disable(void); | ||
36 | extern int irq_remapping_reenable(int); | ||
37 | extern int irq_remap_enable_fault_handling(void); | ||
38 | extern int setup_ioapic_remapped_entry(int irq, | ||
39 | struct IO_APIC_route_entry *entry, | ||
40 | unsigned int destination, | ||
41 | int vector, | ||
42 | struct io_apic_irq_attr *attr); | ||
43 | extern int set_remapped_irq_affinity(struct irq_data *data, | ||
44 | const struct cpumask *mask, | ||
45 | bool force); | ||
46 | extern void free_remapped_irq(int irq); | ||
47 | extern void compose_remapped_msi_msg(struct pci_dev *pdev, | ||
48 | unsigned int irq, unsigned int dest, | ||
49 | struct msi_msg *msg, u8 hpet_id); | ||
50 | extern int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec); | ||
51 | extern int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, | ||
52 | int index, int sub_handle); | ||
53 | extern int setup_hpet_msi_remapped(unsigned int irq, unsigned int id); | ||
54 | |||
55 | #else /* CONFIG_IRQ_REMAP */ | ||
56 | |||
57 | #define irq_remapping_enabled 0 | ||
58 | |||
59 | static inline void setup_irq_remapping_ops(void) { } | ||
60 | static inline int irq_remapping_supported(void) { return 0; } | ||
61 | static inline int irq_remapping_prepare(void) { return -ENODEV; } | ||
62 | static inline int irq_remapping_enable(void) { return -ENODEV; } | ||
63 | static inline void irq_remapping_disable(void) { } | ||
64 | static inline int irq_remapping_reenable(int eim) { return -ENODEV; } | ||
65 | static inline int irq_remap_enable_fault_handling(void) { return -ENODEV; } | ||
66 | static inline int setup_ioapic_remapped_entry(int irq, | ||
67 | struct IO_APIC_route_entry *entry, | ||
68 | unsigned int destination, | ||
69 | int vector, | ||
70 | struct io_apic_irq_attr *attr) | ||
71 | { | ||
72 | return -ENODEV; | ||
73 | } | ||
74 | static inline int set_remapped_irq_affinity(struct irq_data *data, | ||
75 | const struct cpumask *mask, | ||
76 | bool force) | ||
10 | { | 77 | { |
11 | memset(irte, 0, sizeof(*irte)); | 78 | return 0; |
12 | |||
13 | irte->present = 1; | ||
14 | irte->dst_mode = apic->irq_dest_mode; | ||
15 | /* | ||
16 | * Trigger mode in the IRTE will always be edge, and for IO-APIC, the | ||
17 | * actual level or edge trigger will be setup in the IO-APIC | ||
18 | * RTE. This will help simplify level triggered irq migration. | ||
19 | * For more details, see the comments (in io_apic.c) explainig IO-APIC | ||
20 | * irq migration in the presence of interrupt-remapping. | ||
21 | */ | ||
22 | irte->trigger_mode = 0; | ||
23 | irte->dlvry_mode = apic->irq_delivery_mode; | ||
24 | irte->vector = vector; | ||
25 | irte->dest_id = IRTE_DEST(dest); | ||
26 | irte->redir_hint = 1; | ||
27 | } | 79 | } |
28 | static inline bool irq_remapped(struct irq_cfg *cfg) | 80 | static inline void free_remapped_irq(int irq) { } |
81 | static inline void compose_remapped_msi_msg(struct pci_dev *pdev, | ||
82 | unsigned int irq, unsigned int dest, | ||
83 | struct msi_msg *msg, u8 hpet_id) | ||
29 | { | 84 | { |
30 | return cfg->irq_2_iommu.iommu != NULL; | ||
31 | } | 85 | } |
32 | #else | 86 | static inline int msi_alloc_remapped_irq(struct pci_dev *pdev, int irq, int nvec) |
33 | static void prepare_irte(struct irte *irte, int vector, unsigned int dest) | ||
34 | { | 87 | { |
88 | return -ENODEV; | ||
35 | } | 89 | } |
36 | static inline bool irq_remapped(struct irq_cfg *cfg) | 90 | static inline int msi_setup_remapped_irq(struct pci_dev *pdev, unsigned int irq, |
91 | int index, int sub_handle) | ||
37 | { | 92 | { |
38 | return false; | 93 | return -ENODEV; |
39 | } | 94 | } |
40 | static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip) | 95 | static inline int setup_hpet_msi_remapped(unsigned int irq, unsigned int id) |
41 | { | 96 | { |
97 | return -ENODEV; | ||
42 | } | 98 | } |
43 | #endif | 99 | #endif /* CONFIG_IRQ_REMAP */ |
44 | 100 | ||
45 | #endif /* _ASM_X86_IRQ_REMAPPING_H */ | 101 | #endif /* __X86_IRQ_REMAPPING_H */ |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index edc24480469f..3722179a49db 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/irq_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> |
@@ -1441,8 +1442,8 @@ void __init bsp_end_local_APIC_setup(void) | |||
1441 | * Now that local APIC setup is completed for BP, configure the fault | 1442 | * Now that local APIC setup is completed for BP, configure the fault |
1442 | * handling for interrupt remapping. | 1443 | * handling for interrupt remapping. |
1443 | */ | 1444 | */ |
1444 | if (intr_remapping_enabled) | 1445 | if (irq_remapping_enabled) |
1445 | enable_drhd_fault_handling(); | 1446 | irq_remap_enable_fault_handling(); |
1446 | 1447 | ||
1447 | } | 1448 | } |
1448 | 1449 | ||
@@ -1517,7 +1518,7 @@ void enable_x2apic(void) | |||
1517 | int __init enable_IR(void) | 1518 | int __init enable_IR(void) |
1518 | { | 1519 | { |
1519 | #ifdef CONFIG_IRQ_REMAP | 1520 | #ifdef CONFIG_IRQ_REMAP |
1520 | if (!intr_remapping_supported()) { | 1521 | if (!irq_remapping_supported()) { |
1521 | pr_debug("intr-remapping not supported\n"); | 1522 | pr_debug("intr-remapping not supported\n"); |
1522 | return -1; | 1523 | return -1; |
1523 | } | 1524 | } |
@@ -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 irq_remapping_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_irq_remapping_ops(); |
1545 | |||
1546 | hardware_init_ret = irq_remapping_prepare(); | ||
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(); |
@@ -2176,8 +2180,8 @@ static int lapic_suspend(void) | |||
2176 | local_irq_save(flags); | 2180 | local_irq_save(flags); |
2177 | disable_local_APIC(); | 2181 | disable_local_APIC(); |
2178 | 2182 | ||
2179 | if (intr_remapping_enabled) | 2183 | if (irq_remapping_enabled) |
2180 | disable_intr_remapping(); | 2184 | irq_remapping_disable(); |
2181 | 2185 | ||
2182 | local_irq_restore(flags); | 2186 | local_irq_restore(flags); |
2183 | return 0; | 2187 | return 0; |
@@ -2193,7 +2197,7 @@ static void lapic_resume(void) | |||
2193 | return; | 2197 | return; |
2194 | 2198 | ||
2195 | local_irq_save(flags); | 2199 | local_irq_save(flags); |
2196 | if (intr_remapping_enabled) { | 2200 | if (irq_remapping_enabled) { |
2197 | /* | 2201 | /* |
2198 | * IO-APIC and PIC have their own resume routines. | 2202 | * IO-APIC and PIC have their own resume routines. |
2199 | * We just mask them here to make sure the interrupt | 2203 | * We just mask them here to make sure the interrupt |
@@ -2245,8 +2249,8 @@ static void lapic_resume(void) | |||
2245 | apic_write(APIC_ESR, 0); | 2249 | apic_write(APIC_ESR, 0); |
2246 | apic_read(APIC_ESR); | 2250 | apic_read(APIC_ESR); |
2247 | 2251 | ||
2248 | if (intr_remapping_enabled) | 2252 | if (irq_remapping_enabled) |
2249 | reenable_intr_remapping(x2apic_mode); | 2253 | irq_remapping_reenable(x2apic_mode); |
2250 | 2254 | ||
2251 | local_irq_restore(flags); | 2255 | local_irq_restore(flags); |
2252 | } | 2256 | } |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index e88300d8e80a..ef0648cd7084 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -86,6 +86,22 @@ void __init set_io_apic_ops(const struct io_apic_ops *ops) | |||
86 | io_apic_ops = *ops; | 86 | io_apic_ops = *ops; |
87 | } | 87 | } |
88 | 88 | ||
89 | #ifdef CONFIG_IRQ_REMAP | ||
90 | static void irq_remap_modify_chip_defaults(struct irq_chip *chip); | ||
91 | static inline bool irq_remapped(struct irq_cfg *cfg) | ||
92 | { | ||
93 | return cfg->irq_2_iommu.iommu != NULL; | ||
94 | } | ||
95 | #else | ||
96 | static inline bool irq_remapped(struct irq_cfg *cfg) | ||
97 | { | ||
98 | return false; | ||
99 | } | ||
100 | static inline void irq_remap_modify_chip_defaults(struct irq_chip *chip) | ||
101 | { | ||
102 | } | ||
103 | #endif | ||
104 | |||
89 | /* | 105 | /* |
90 | * Is the SiS APIC rmw bug present ? | 106 | * Is the SiS APIC rmw bug present ? |
91 | * -1 = don't know, 0 = no, 1 = yes | 107 | * -1 = don't know, 0 = no, 1 = yes |
@@ -1361,77 +1377,13 @@ static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg, | |||
1361 | fasteoi ? "fasteoi" : "edge"); | 1377 | fasteoi ? "fasteoi" : "edge"); |
1362 | } | 1378 | } |
1363 | 1379 | ||
1364 | |||
1365 | static int setup_ir_ioapic_entry(int irq, | ||
1366 | struct IR_IO_APIC_route_entry *entry, | ||
1367 | unsigned int destination, int vector, | ||
1368 | struct io_apic_irq_attr *attr) | ||
1369 | { | ||
1370 | int index; | ||
1371 | struct irte irte; | ||
1372 | int ioapic_id = mpc_ioapic_id(attr->ioapic); | ||
1373 | struct intel_iommu *iommu = map_ioapic_to_ir(ioapic_id); | ||
1374 | |||
1375 | if (!iommu) { | ||
1376 | pr_warn("No mapping iommu for ioapic %d\n", ioapic_id); | ||
1377 | return -ENODEV; | ||
1378 | } | ||
1379 | |||
1380 | index = alloc_irte(iommu, irq, 1); | ||
1381 | if (index < 0) { | ||
1382 | pr_warn("Failed to allocate IRTE for ioapic %d\n", ioapic_id); | ||
1383 | return -ENOMEM; | ||
1384 | } | ||
1385 | |||
1386 | prepare_irte(&irte, vector, destination); | ||
1387 | |||
1388 | /* Set source-id of interrupt request */ | ||
1389 | set_ioapic_sid(&irte, ioapic_id); | ||
1390 | |||
1391 | modify_irte(irq, &irte); | ||
1392 | |||
1393 | apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: " | ||
1394 | "Set IRTE entry (P:%d FPD:%d Dst_Mode:%d " | ||
1395 | "Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X " | ||
1396 | "Avail:%X Vector:%02X Dest:%08X " | ||
1397 | "SID:%04X SQ:%X SVT:%X)\n", | ||
1398 | attr->ioapic, irte.present, irte.fpd, irte.dst_mode, | ||
1399 | irte.redir_hint, irte.trigger_mode, irte.dlvry_mode, | ||
1400 | irte.avail, irte.vector, irte.dest_id, | ||
1401 | irte.sid, irte.sq, irte.svt); | ||
1402 | |||
1403 | memset(entry, 0, sizeof(*entry)); | ||
1404 | |||
1405 | entry->index2 = (index >> 15) & 0x1; | ||
1406 | entry->zero = 0; | ||
1407 | entry->format = 1; | ||
1408 | entry->index = (index & 0x7fff); | ||
1409 | /* | ||
1410 | * IO-APIC RTE will be configured with virtual vector. | ||
1411 | * irq handler will do the explicit EOI to the io-apic. | ||
1412 | */ | ||
1413 | entry->vector = attr->ioapic_pin; | ||
1414 | entry->mask = 0; /* enable IRQ */ | ||
1415 | entry->trigger = attr->trigger; | ||
1416 | entry->polarity = attr->polarity; | ||
1417 | |||
1418 | /* Mask level triggered irqs. | ||
1419 | * Use IRQ_DELAYED_DISABLE for edge triggered irqs. | ||
1420 | */ | ||
1421 | if (attr->trigger) | ||
1422 | entry->mask = 1; | ||
1423 | |||
1424 | return 0; | ||
1425 | } | ||
1426 | |||
1427 | static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry, | 1380 | static int setup_ioapic_entry(int irq, struct IO_APIC_route_entry *entry, |
1428 | unsigned int destination, int vector, | 1381 | unsigned int destination, int vector, |
1429 | struct io_apic_irq_attr *attr) | 1382 | struct io_apic_irq_attr *attr) |
1430 | { | 1383 | { |
1431 | if (intr_remapping_enabled) | 1384 | if (irq_remapping_enabled) |
1432 | return setup_ir_ioapic_entry(irq, | 1385 | return setup_ioapic_remapped_entry(irq, entry, destination, |
1433 | (struct IR_IO_APIC_route_entry *)entry, | 1386 | vector, attr); |
1434 | destination, vector, attr); | ||
1435 | 1387 | ||
1436 | memset(entry, 0, sizeof(*entry)); | 1388 | memset(entry, 0, sizeof(*entry)); |
1437 | 1389 | ||
@@ -1588,7 +1540,7 @@ static void __init setup_timer_IRQ0_pin(unsigned int ioapic_idx, | |||
1588 | { | 1540 | { |
1589 | struct IO_APIC_route_entry entry; | 1541 | struct IO_APIC_route_entry entry; |
1590 | 1542 | ||
1591 | if (intr_remapping_enabled) | 1543 | if (irq_remapping_enabled) |
1592 | return; | 1544 | return; |
1593 | 1545 | ||
1594 | memset(&entry, 0, sizeof(entry)); | 1546 | memset(&entry, 0, sizeof(entry)); |
@@ -1674,7 +1626,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx) | |||
1674 | 1626 | ||
1675 | printk(KERN_DEBUG ".... IRQ redirection table:\n"); | 1627 | printk(KERN_DEBUG ".... IRQ redirection table:\n"); |
1676 | 1628 | ||
1677 | if (intr_remapping_enabled) { | 1629 | if (irq_remapping_enabled) { |
1678 | printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR" | 1630 | printk(KERN_DEBUG " NR Indx Fmt Mask Trig IRR" |
1679 | " Pol Stat Indx2 Zero Vect:\n"); | 1631 | " Pol Stat Indx2 Zero Vect:\n"); |
1680 | } else { | 1632 | } else { |
@@ -1683,7 +1635,7 @@ __apicdebuginit(void) print_IO_APIC(int ioapic_idx) | |||
1683 | } | 1635 | } |
1684 | 1636 | ||
1685 | for (i = 0; i <= reg_01.bits.entries; i++) { | 1637 | for (i = 0; i <= reg_01.bits.entries; i++) { |
1686 | if (intr_remapping_enabled) { | 1638 | if (irq_remapping_enabled) { |
1687 | struct IO_APIC_route_entry entry; | 1639 | struct IO_APIC_route_entry entry; |
1688 | struct IR_IO_APIC_route_entry *ir_entry; | 1640 | struct IR_IO_APIC_route_entry *ir_entry; |
1689 | 1641 | ||
@@ -2050,7 +2002,7 @@ void disable_IO_APIC(void) | |||
2050 | * IOAPIC RTE as well as interrupt-remapping table entry). | 2002 | * IOAPIC RTE as well as interrupt-remapping table entry). |
2051 | * As this gets called during crash dump, keep this simple for now. | 2003 | * As this gets called during crash dump, keep this simple for now. |
2052 | */ | 2004 | */ |
2053 | if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) { | 2005 | if (ioapic_i8259.pin != -1 && !irq_remapping_enabled) { |
2054 | struct IO_APIC_route_entry entry; | 2006 | struct IO_APIC_route_entry entry; |
2055 | 2007 | ||
2056 | memset(&entry, 0, sizeof(entry)); | 2008 | memset(&entry, 0, sizeof(entry)); |
@@ -2074,7 +2026,7 @@ void disable_IO_APIC(void) | |||
2074 | * Use virtual wire A mode when interrupt remapping is enabled. | 2026 | * Use virtual wire A mode when interrupt remapping is enabled. |
2075 | */ | 2027 | */ |
2076 | if (cpu_has_apic || apic_from_smp_config()) | 2028 | if (cpu_has_apic || apic_from_smp_config()) |
2077 | disconnect_bsp_APIC(!intr_remapping_enabled && | 2029 | disconnect_bsp_APIC(!irq_remapping_enabled && |
2078 | ioapic_i8259.pin != -1); | 2030 | ioapic_i8259.pin != -1); |
2079 | } | 2031 | } |
2080 | 2032 | ||
@@ -2390,71 +2342,6 @@ ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, | |||
2390 | return ret; | 2342 | return ret; |
2391 | } | 2343 | } |
2392 | 2344 | ||
2393 | #ifdef CONFIG_IRQ_REMAP | ||
2394 | |||
2395 | /* | ||
2396 | * Migrate the IO-APIC irq in the presence of intr-remapping. | ||
2397 | * | ||
2398 | * For both level and edge triggered, irq migration is a simple atomic | ||
2399 | * update(of vector and cpu destination) of IRTE and flush the hardware cache. | ||
2400 | * | ||
2401 | * For level triggered, we eliminate the io-apic RTE modification (with the | ||
2402 | * updated vector information), by using a virtual vector (io-apic pin number). | ||
2403 | * Real vector that is used for interrupting cpu will be coming from | ||
2404 | * the interrupt-remapping table entry. | ||
2405 | * | ||
2406 | * As the migration is a simple atomic update of IRTE, the same mechanism | ||
2407 | * is used to migrate MSI irq's in the presence of interrupt-remapping. | ||
2408 | */ | ||
2409 | static int | ||
2410 | ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, | ||
2411 | bool force) | ||
2412 | { | ||
2413 | struct irq_cfg *cfg = data->chip_data; | ||
2414 | unsigned int dest, irq = data->irq; | ||
2415 | struct irte irte; | ||
2416 | |||
2417 | if (!cpumask_intersects(mask, cpu_online_mask)) | ||
2418 | return -EINVAL; | ||
2419 | |||
2420 | if (get_irte(irq, &irte)) | ||
2421 | return -EBUSY; | ||
2422 | |||
2423 | if (assign_irq_vector(irq, cfg, mask)) | ||
2424 | return -EBUSY; | ||
2425 | |||
2426 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, mask); | ||
2427 | |||
2428 | irte.vector = cfg->vector; | ||
2429 | irte.dest_id = IRTE_DEST(dest); | ||
2430 | |||
2431 | /* | ||
2432 | * Atomically updates the IRTE with the new destination, vector | ||
2433 | * and flushes the interrupt entry cache. | ||
2434 | */ | ||
2435 | modify_irte(irq, &irte); | ||
2436 | |||
2437 | /* | ||
2438 | * After this point, all the interrupts will start arriving | ||
2439 | * at the new destination. So, time to cleanup the previous | ||
2440 | * vector allocation. | ||
2441 | */ | ||
2442 | if (cfg->move_in_progress) | ||
2443 | send_cleanup_vector(cfg); | ||
2444 | |||
2445 | cpumask_copy(data->affinity, mask); | ||
2446 | return 0; | ||
2447 | } | ||
2448 | |||
2449 | #else | ||
2450 | static inline int | ||
2451 | ir_ioapic_set_affinity(struct irq_data *data, const struct cpumask *mask, | ||
2452 | bool force) | ||
2453 | { | ||
2454 | return 0; | ||
2455 | } | ||
2456 | #endif | ||
2457 | |||
2458 | asmlinkage void smp_irq_move_cleanup_interrupt(void) | 2345 | asmlinkage void smp_irq_move_cleanup_interrupt(void) |
2459 | { | 2346 | { |
2460 | unsigned vector, me; | 2347 | unsigned vector, me; |
@@ -2699,7 +2586,7 @@ static void irq_remap_modify_chip_defaults(struct irq_chip *chip) | |||
2699 | chip->irq_eoi = ir_ack_apic_level; | 2586 | chip->irq_eoi = ir_ack_apic_level; |
2700 | 2587 | ||
2701 | #ifdef CONFIG_SMP | 2588 | #ifdef CONFIG_SMP |
2702 | chip->irq_set_affinity = ir_ioapic_set_affinity; | 2589 | chip->irq_set_affinity = set_remapped_irq_affinity; |
2703 | #endif | 2590 | #endif |
2704 | } | 2591 | } |
2705 | #endif /* CONFIG_IRQ_REMAP */ | 2592 | #endif /* CONFIG_IRQ_REMAP */ |
@@ -2912,7 +2799,7 @@ static inline void __init check_timer(void) | |||
2912 | * 8259A. | 2799 | * 8259A. |
2913 | */ | 2800 | */ |
2914 | if (pin1 == -1) { | 2801 | if (pin1 == -1) { |
2915 | if (intr_remapping_enabled) | 2802 | if (irq_remapping_enabled) |
2916 | panic("BIOS bug: timer not connected to IO-APIC"); | 2803 | panic("BIOS bug: timer not connected to IO-APIC"); |
2917 | pin1 = pin2; | 2804 | pin1 = pin2; |
2918 | apic1 = apic2; | 2805 | apic1 = apic2; |
@@ -2945,7 +2832,7 @@ static inline void __init check_timer(void) | |||
2945 | clear_IO_APIC_pin(0, pin1); | 2832 | clear_IO_APIC_pin(0, pin1); |
2946 | goto out; | 2833 | goto out; |
2947 | } | 2834 | } |
2948 | if (intr_remapping_enabled) | 2835 | if (irq_remapping_enabled) |
2949 | panic("timer doesn't work through Interrupt-remapped IO-APIC"); | 2836 | panic("timer doesn't work through Interrupt-remapped IO-APIC"); |
2950 | local_irq_disable(); | 2837 | local_irq_disable(); |
2951 | clear_IO_APIC_pin(apic1, pin1); | 2838 | clear_IO_APIC_pin(apic1, pin1); |
@@ -3169,7 +3056,7 @@ void destroy_irq(unsigned int irq) | |||
3169 | irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE); | 3056 | irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE); |
3170 | 3057 | ||
3171 | if (irq_remapped(cfg)) | 3058 | if (irq_remapped(cfg)) |
3172 | free_irte(irq); | 3059 | free_remapped_irq(irq); |
3173 | raw_spin_lock_irqsave(&vector_lock, flags); | 3060 | raw_spin_lock_irqsave(&vector_lock, flags); |
3174 | __clear_irq_vector(irq, cfg); | 3061 | __clear_irq_vector(irq, cfg); |
3175 | raw_spin_unlock_irqrestore(&vector_lock, flags); | 3062 | raw_spin_unlock_irqrestore(&vector_lock, flags); |
@@ -3198,54 +3085,34 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, | |||
3198 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); | 3085 | dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus()); |
3199 | 3086 | ||
3200 | if (irq_remapped(cfg)) { | 3087 | if (irq_remapped(cfg)) { |
3201 | struct irte irte; | 3088 | compose_remapped_msi_msg(pdev, irq, dest, msg, hpet_id); |
3202 | int ir_index; | 3089 | return err; |
3203 | u16 sub_handle; | 3090 | } |
3204 | |||
3205 | ir_index = map_irq_to_irte_handle(irq, &sub_handle); | ||
3206 | BUG_ON(ir_index == -1); | ||
3207 | |||
3208 | prepare_irte(&irte, cfg->vector, dest); | ||
3209 | |||
3210 | /* Set source-id of interrupt request */ | ||
3211 | if (pdev) | ||
3212 | set_msi_sid(&irte, pdev); | ||
3213 | else | ||
3214 | set_hpet_sid(&irte, hpet_id); | ||
3215 | |||
3216 | modify_irte(irq, &irte); | ||
3217 | 3091 | ||
3092 | if (x2apic_enabled()) | ||
3093 | msg->address_hi = MSI_ADDR_BASE_HI | | ||
3094 | MSI_ADDR_EXT_DEST_ID(dest); | ||
3095 | else | ||
3218 | msg->address_hi = MSI_ADDR_BASE_HI; | 3096 | msg->address_hi = MSI_ADDR_BASE_HI; |
3219 | msg->data = sub_handle; | ||
3220 | msg->address_lo = MSI_ADDR_BASE_LO | MSI_ADDR_IR_EXT_INT | | ||
3221 | MSI_ADDR_IR_SHV | | ||
3222 | MSI_ADDR_IR_INDEX1(ir_index) | | ||
3223 | MSI_ADDR_IR_INDEX2(ir_index); | ||
3224 | } else { | ||
3225 | if (x2apic_enabled()) | ||
3226 | msg->address_hi = MSI_ADDR_BASE_HI | | ||
3227 | MSI_ADDR_EXT_DEST_ID(dest); | ||
3228 | else | ||
3229 | msg->address_hi = MSI_ADDR_BASE_HI; | ||
3230 | 3097 | ||
3231 | msg->address_lo = | 3098 | msg->address_lo = |
3232 | MSI_ADDR_BASE_LO | | 3099 | MSI_ADDR_BASE_LO | |
3233 | ((apic->irq_dest_mode == 0) ? | 3100 | ((apic->irq_dest_mode == 0) ? |
3234 | MSI_ADDR_DEST_MODE_PHYSICAL: | 3101 | MSI_ADDR_DEST_MODE_PHYSICAL: |
3235 | MSI_ADDR_DEST_MODE_LOGICAL) | | 3102 | MSI_ADDR_DEST_MODE_LOGICAL) | |
3236 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | 3103 | ((apic->irq_delivery_mode != dest_LowestPrio) ? |
3237 | MSI_ADDR_REDIRECTION_CPU: | 3104 | MSI_ADDR_REDIRECTION_CPU: |
3238 | MSI_ADDR_REDIRECTION_LOWPRI) | | 3105 | MSI_ADDR_REDIRECTION_LOWPRI) | |
3239 | MSI_ADDR_DEST_ID(dest); | 3106 | MSI_ADDR_DEST_ID(dest); |
3107 | |||
3108 | msg->data = | ||
3109 | MSI_DATA_TRIGGER_EDGE | | ||
3110 | MSI_DATA_LEVEL_ASSERT | | ||
3111 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
3112 | MSI_DATA_DELIVERY_FIXED: | ||
3113 | MSI_DATA_DELIVERY_LOWPRI) | | ||
3114 | MSI_DATA_VECTOR(cfg->vector); | ||
3240 | 3115 | ||
3241 | msg->data = | ||
3242 | MSI_DATA_TRIGGER_EDGE | | ||
3243 | MSI_DATA_LEVEL_ASSERT | | ||
3244 | ((apic->irq_delivery_mode != dest_LowestPrio) ? | ||
3245 | MSI_DATA_DELIVERY_FIXED: | ||
3246 | MSI_DATA_DELIVERY_LOWPRI) | | ||
3247 | MSI_DATA_VECTOR(cfg->vector); | ||
3248 | } | ||
3249 | return err; | 3116 | return err; |
3250 | } | 3117 | } |
3251 | 3118 | ||
@@ -3288,33 +3155,6 @@ static struct irq_chip msi_chip = { | |||
3288 | .irq_retrigger = ioapic_retrigger_irq, | 3155 | .irq_retrigger = ioapic_retrigger_irq, |
3289 | }; | 3156 | }; |
3290 | 3157 | ||
3291 | /* | ||
3292 | * Map the PCI dev to the corresponding remapping hardware unit | ||
3293 | * and allocate 'nvec' consecutive interrupt-remapping table entries | ||
3294 | * in it. | ||
3295 | */ | ||
3296 | static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec) | ||
3297 | { | ||
3298 | struct intel_iommu *iommu; | ||
3299 | int index; | ||
3300 | |||
3301 | iommu = map_dev_to_ir(dev); | ||
3302 | if (!iommu) { | ||
3303 | printk(KERN_ERR | ||
3304 | "Unable to map PCI %s to iommu\n", pci_name(dev)); | ||
3305 | return -ENOENT; | ||
3306 | } | ||
3307 | |||
3308 | index = alloc_irte(iommu, irq, nvec); | ||
3309 | if (index < 0) { | ||
3310 | printk(KERN_ERR | ||
3311 | "Unable to allocate %d IRTE for PCI %s\n", nvec, | ||
3312 | pci_name(dev)); | ||
3313 | return -ENOSPC; | ||
3314 | } | ||
3315 | return index; | ||
3316 | } | ||
3317 | |||
3318 | static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) | 3158 | static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq) |
3319 | { | 3159 | { |
3320 | struct irq_chip *chip = &msi_chip; | 3160 | struct irq_chip *chip = &msi_chip; |
@@ -3345,7 +3185,6 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
3345 | int node, ret, sub_handle, index = 0; | 3185 | int node, ret, sub_handle, index = 0; |
3346 | unsigned int irq, irq_want; | 3186 | unsigned int irq, irq_want; |
3347 | struct msi_desc *msidesc; | 3187 | struct msi_desc *msidesc; |
3348 | struct intel_iommu *iommu = NULL; | ||
3349 | 3188 | ||
3350 | /* x86 doesn't support multiple MSI yet */ | 3189 | /* x86 doesn't support multiple MSI yet */ |
3351 | if (type == PCI_CAP_ID_MSI && nvec > 1) | 3190 | if (type == PCI_CAP_ID_MSI && nvec > 1) |
@@ -3359,7 +3198,7 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
3359 | if (irq == 0) | 3198 | if (irq == 0) |
3360 | return -1; | 3199 | return -1; |
3361 | irq_want = irq + 1; | 3200 | irq_want = irq + 1; |
3362 | if (!intr_remapping_enabled) | 3201 | if (!irq_remapping_enabled) |
3363 | goto no_ir; | 3202 | goto no_ir; |
3364 | 3203 | ||
3365 | if (!sub_handle) { | 3204 | if (!sub_handle) { |
@@ -3367,23 +3206,16 @@ int native_setup_msi_irqs(struct pci_dev *dev, int nvec, int type) | |||
3367 | * allocate the consecutive block of IRTE's | 3206 | * allocate the consecutive block of IRTE's |
3368 | * for 'nvec' | 3207 | * for 'nvec' |
3369 | */ | 3208 | */ |
3370 | index = msi_alloc_irte(dev, irq, nvec); | 3209 | index = msi_alloc_remapped_irq(dev, irq, nvec); |
3371 | if (index < 0) { | 3210 | if (index < 0) { |
3372 | ret = index; | 3211 | ret = index; |
3373 | goto error; | 3212 | goto error; |
3374 | } | 3213 | } |
3375 | } else { | 3214 | } else { |
3376 | iommu = map_dev_to_ir(dev); | 3215 | ret = msi_setup_remapped_irq(dev, irq, index, |
3377 | if (!iommu) { | 3216 | sub_handle); |
3378 | ret = -ENOENT; | 3217 | if (ret < 0) |
3379 | goto error; | 3218 | goto error; |
3380 | } | ||
3381 | /* | ||
3382 | * setup the mapping between the irq and the IRTE | ||
3383 | * base index, the sub_handle pointing to the | ||
3384 | * appropriate interrupt remap table entry. | ||
3385 | */ | ||
3386 | set_irte_irq(irq, iommu, index, sub_handle); | ||
3387 | } | 3219 | } |
3388 | no_ir: | 3220 | no_ir: |
3389 | ret = setup_msi_irq(dev, msidesc, irq); | 3221 | ret = setup_msi_irq(dev, msidesc, irq); |
@@ -3501,15 +3333,8 @@ int arch_setup_hpet_msi(unsigned int irq, unsigned int id) | |||
3501 | struct msi_msg msg; | 3333 | struct msi_msg msg; |
3502 | int ret; | 3334 | int ret; |
3503 | 3335 | ||
3504 | if (intr_remapping_enabled) { | 3336 | if (irq_remapping_enabled) { |
3505 | struct intel_iommu *iommu = map_hpet_to_ir(id); | 3337 | if (!setup_hpet_msi_remapped(irq, id)) |
3506 | int index; | ||
3507 | |||
3508 | if (!iommu) | ||
3509 | return -1; | ||
3510 | |||
3511 | index = alloc_irte(iommu, irq, 1); | ||
3512 | if (index < 0) | ||
3513 | return -1; | 3338 | return -1; |
3514 | } | 3339 | } |
3515 | 3340 | ||
@@ -3888,8 +3713,8 @@ void __init setup_ioapic_dest(void) | |||
3888 | else | 3713 | else |
3889 | mask = apic->target_cpus(); | 3714 | mask = apic->target_cpus(); |
3890 | 3715 | ||
3891 | if (intr_remapping_enabled) | 3716 | if (irq_remapping_enabled) |
3892 | ir_ioapic_set_affinity(idata, mask, false); | 3717 | set_remapped_irq_affinity(idata, mask, false); |
3893 | else | 3718 | else |
3894 | ioapic_set_affinity(idata, mask, false); | 3719 | ioapic_set_affinity(idata, mask, false); |
3895 | } | 3720 | } |