aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/intr_remapping.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/intr_remapping.c')
-rw-r--r--drivers/pci/intr_remapping.c97
1 files changed, 90 insertions, 7 deletions
diff --git a/drivers/pci/intr_remapping.c b/drivers/pci/intr_remapping.c
index 0ed78a764ded..6ee98a56946f 100644
--- a/drivers/pci/intr_remapping.c
+++ b/drivers/pci/intr_remapping.c
@@ -1,7 +1,9 @@
1#include <linux/interrupt.h> 1#include <linux/interrupt.h>
2#include <linux/dmar.h> 2#include <linux/dmar.h>
3#include <linux/spinlock.h> 3#include <linux/spinlock.h>
4#include <linux/slab.h>
4#include <linux/jiffies.h> 5#include <linux/jiffies.h>
6#include <linux/hpet.h>
5#include <linux/pci.h> 7#include <linux/pci.h>
6#include <linux/irq.h> 8#include <linux/irq.h>
7#include <asm/io_apic.h> 9#include <asm/io_apic.h>
@@ -14,7 +16,8 @@
14#include "pci.h" 16#include "pci.h"
15 17
16static struct ioapic_scope ir_ioapic[MAX_IO_APICS]; 18static struct ioapic_scope ir_ioapic[MAX_IO_APICS];
17static int ir_ioapic_num; 19static struct hpet_scope ir_hpet[MAX_HPET_TBS];
20static int ir_ioapic_num, ir_hpet_num;
18int intr_remapping_enabled; 21int intr_remapping_enabled;
19 22
20static int disable_intremap; 23static int disable_intremap;
@@ -343,6 +346,16 @@ int flush_irte(int irq)
343 return rc; 346 return rc;
344} 347}
345 348
349struct intel_iommu *map_hpet_to_ir(u8 hpet_id)
350{
351 int i;
352
353 for (i = 0; i < MAX_HPET_TBS; i++)
354 if (ir_hpet[i].id == hpet_id)
355 return ir_hpet[i].iommu;
356 return NULL;
357}
358
346struct intel_iommu *map_ioapic_to_ir(int apic) 359struct intel_iommu *map_ioapic_to_ir(int apic)
347{ 360{
348 int i; 361 int i;
@@ -470,6 +483,36 @@ int set_ioapic_sid(struct irte *irte, int apic)
470 return 0; 483 return 0;
471} 484}
472 485
486int set_hpet_sid(struct irte *irte, u8 id)
487{
488 int i;
489 u16 sid = 0;
490
491 if (!irte)
492 return -1;
493
494 for (i = 0; i < MAX_HPET_TBS; i++) {
495 if (ir_hpet[i].id == id) {
496 sid = (ir_hpet[i].bus << 8) | ir_hpet[i].devfn;
497 break;
498 }
499 }
500
501 if (sid == 0) {
502 pr_warning("Failed to set source-id of HPET block (%d)\n", id);
503 return -1;
504 }
505
506 /*
507 * Should really use SQ_ALL_16. Some platforms are broken.
508 * While we figure out the right quirks for these broken platforms, use
509 * SQ_13_IGNORE_3 for now.
510 */
511 set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_13_IGNORE_3, sid);
512
513 return 0;
514}
515
473int set_msi_sid(struct irte *irte, struct pci_dev *dev) 516int set_msi_sid(struct irte *irte, struct pci_dev *dev)
474{ 517{
475 struct pci_dev *bridge; 518 struct pci_dev *bridge;
@@ -478,7 +521,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
478 return -1; 521 return -1;
479 522
480 /* PCIe device or Root Complex integrated PCI device */ 523 /* PCIe device or Root Complex integrated PCI device */
481 if (dev->is_pcie || !dev->bus->parent) { 524 if (pci_is_pcie(dev) || !dev->bus->parent) {
482 set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16, 525 set_irte_sid(irte, SVT_VERIFY_SID_SQ, SQ_ALL_16,
483 (dev->bus->number << 8) | dev->devfn); 526 (dev->bus->number << 8) | dev->devfn);
484 return 0; 527 return 0;
@@ -486,7 +529,7 @@ int set_msi_sid(struct irte *irte, struct pci_dev *dev)
486 529
487 bridge = pci_find_upstream_pcie_bridge(dev); 530 bridge = pci_find_upstream_pcie_bridge(dev);
488 if (bridge) { 531 if (bridge) {
489 if (bridge->is_pcie) /* this is a PCIE-to-PCI/PCIX bridge */ 532 if (pci_is_pcie(bridge))/* this is a PCIe-to-PCI/PCIX bridge */
490 set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16, 533 set_irte_sid(irte, SVT_VERIFY_BUS, SQ_ALL_16,
491 (bridge->bus->number << 8) | dev->bus->number); 534 (bridge->bus->number << 8) | dev->bus->number);
492 else /* this is a legacy PCI bridge */ 535 else /* this is a legacy PCI bridge */
@@ -548,7 +591,8 @@ static int setup_intr_remapping(struct intel_iommu *iommu, int mode)
548 if (!iommu->ir_table) 591 if (!iommu->ir_table)
549 return -ENOMEM; 592 return -ENOMEM;
550 593
551 pages = alloc_pages(GFP_ATOMIC | __GFP_ZERO, INTR_REMAP_PAGE_ORDER); 594 pages = alloc_pages_node(iommu->node, GFP_ATOMIC | __GFP_ZERO,
595 INTR_REMAP_PAGE_ORDER);
552 596
553 if (!pages) { 597 if (!pages) {
554 printk(KERN_ERR "failed to allocate pages of order %d\n", 598 printk(KERN_ERR "failed to allocate pages of order %d\n",
@@ -711,6 +755,34 @@ error:
711 return -1; 755 return -1;
712} 756}
713 757
758static void ir_parse_one_hpet_scope(struct acpi_dmar_device_scope *scope,
759 struct intel_iommu *iommu)
760{
761 struct acpi_dmar_pci_path *path;
762 u8 bus;
763 int count;
764
765 bus = scope->bus;
766 path = (struct acpi_dmar_pci_path *)(scope + 1);
767 count = (scope->length - sizeof(struct acpi_dmar_device_scope))
768 / sizeof(struct acpi_dmar_pci_path);
769
770 while (--count > 0) {
771 /*
772 * Access PCI directly due to the PCI
773 * subsystem isn't initialized yet.
774 */
775 bus = read_pci_config_byte(bus, path->dev, path->fn,
776 PCI_SECONDARY_BUS);
777 path++;
778 }
779 ir_hpet[ir_hpet_num].bus = bus;
780 ir_hpet[ir_hpet_num].devfn = PCI_DEVFN(path->dev, path->fn);
781 ir_hpet[ir_hpet_num].iommu = iommu;
782 ir_hpet[ir_hpet_num].id = scope->enumeration_id;
783 ir_hpet_num++;
784}
785
714static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope, 786static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
715 struct intel_iommu *iommu) 787 struct intel_iommu *iommu)
716{ 788{
@@ -740,8 +812,8 @@ static void ir_parse_one_ioapic_scope(struct acpi_dmar_device_scope *scope,
740 ir_ioapic_num++; 812 ir_ioapic_num++;
741} 813}
742 814
743static int ir_parse_ioapic_scope(struct acpi_dmar_header *header, 815static int ir_parse_ioapic_hpet_scope(struct acpi_dmar_header *header,
744 struct intel_iommu *iommu) 816 struct intel_iommu *iommu)
745{ 817{
746 struct acpi_dmar_hardware_unit *drhd; 818 struct acpi_dmar_hardware_unit *drhd;
747 struct acpi_dmar_device_scope *scope; 819 struct acpi_dmar_device_scope *scope;
@@ -765,6 +837,17 @@ static int ir_parse_ioapic_scope(struct acpi_dmar_header *header,
765 drhd->address); 837 drhd->address);
766 838
767 ir_parse_one_ioapic_scope(scope, iommu); 839 ir_parse_one_ioapic_scope(scope, iommu);
840 } else if (scope->entry_type == ACPI_DMAR_SCOPE_TYPE_HPET) {
841 if (ir_hpet_num == MAX_HPET_TBS) {
842 printk(KERN_WARNING "Exceeded Max HPET blocks\n");
843 return -1;
844 }
845
846 printk(KERN_INFO "HPET id %d under DRHD base"
847 " 0x%Lx\n", scope->enumeration_id,
848 drhd->address);
849
850 ir_parse_one_hpet_scope(scope, iommu);
768 } 851 }
769 start += scope->length; 852 start += scope->length;
770 } 853 }
@@ -785,7 +868,7 @@ int __init parse_ioapics_under_ir(void)
785 struct intel_iommu *iommu = drhd->iommu; 868 struct intel_iommu *iommu = drhd->iommu;
786 869
787 if (ecap_ir_support(iommu->ecap)) { 870 if (ecap_ir_support(iommu->ecap)) {
788 if (ir_parse_ioapic_scope(drhd->hdr, iommu)) 871 if (ir_parse_ioapic_hpet_scope(drhd->hdr, iommu))
789 return -1; 872 return -1;
790 873
791 ir_supported = 1; 874 ir_supported = 1;