diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-07 18:15:42 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2014-03-24 10:06:30 -0400 |
commit | ed40356b5fcf1ce28e026ab39c5b2b6939068b50 (patch) | |
tree | cb29ea716434701c0b155cd9e51f84b6f5b5af4c | |
parent | 832bd858674023b2415c7585db3beba345ef807f (diff) |
iommu/vt-d: Add ACPI devices into dmaru->devices[] array
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
-rw-r--r-- | drivers/iommu/dmar.c | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index c1e2e0c82e69..7ea086f61073 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -612,6 +612,79 @@ out: | |||
612 | return dmaru; | 612 | return dmaru; |
613 | } | 613 | } |
614 | 614 | ||
615 | static void __init dmar_acpi_insert_dev_scope(u8 device_number, | ||
616 | struct acpi_device *adev) | ||
617 | { | ||
618 | struct dmar_drhd_unit *dmaru; | ||
619 | struct acpi_dmar_hardware_unit *drhd; | ||
620 | struct acpi_dmar_device_scope *scope; | ||
621 | struct device *tmp; | ||
622 | int i; | ||
623 | struct acpi_dmar_pci_path *path; | ||
624 | |||
625 | for_each_drhd_unit(dmaru) { | ||
626 | drhd = container_of(dmaru->hdr, | ||
627 | struct acpi_dmar_hardware_unit, | ||
628 | header); | ||
629 | |||
630 | for (scope = (void *)(drhd + 1); | ||
631 | (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; | ||
632 | scope = ((void *)scope) + scope->length) { | ||
633 | if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_ACPI) | ||
634 | continue; | ||
635 | if (scope->enumeration_id != device_number) | ||
636 | continue; | ||
637 | |||
638 | path = (void *)(scope + 1); | ||
639 | pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n", | ||
640 | dev_name(&adev->dev), dmaru->reg_base_addr, | ||
641 | scope->bus, path->device, path->function); | ||
642 | for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp) | ||
643 | if (tmp == NULL) { | ||
644 | dmaru->devices[i].bus = scope->bus; | ||
645 | dmaru->devices[i].devfn = PCI_DEVFN(path->device, | ||
646 | path->function); | ||
647 | rcu_assign_pointer(dmaru->devices[i].dev, | ||
648 | get_device(&adev->dev)); | ||
649 | return; | ||
650 | } | ||
651 | BUG_ON(i >= dmaru->devices_cnt); | ||
652 | } | ||
653 | } | ||
654 | pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n", | ||
655 | device_number, dev_name(&adev->dev)); | ||
656 | } | ||
657 | |||
658 | static int __init dmar_acpi_dev_scope_init(void) | ||
659 | { | ||
660 | struct acpi_dmar_andd *andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar); | ||
661 | |||
662 | while (((unsigned long)andd) < | ||
663 | ((unsigned long)dmar_tbl) + dmar_tbl->length) { | ||
664 | if (andd->header.type == ACPI_DMAR_TYPE_ANDD) { | ||
665 | acpi_handle h; | ||
666 | struct acpi_device *adev; | ||
667 | |||
668 | if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, | ||
669 | andd->object_name, | ||
670 | &h))) { | ||
671 | pr_err("Failed to find handle for ACPI object %s\n", | ||
672 | andd->object_name); | ||
673 | continue; | ||
674 | } | ||
675 | acpi_bus_get_device(h, &adev); | ||
676 | if (!adev) { | ||
677 | pr_err("Failed to get device for ACPI object %s\n", | ||
678 | andd->object_name); | ||
679 | continue; | ||
680 | } | ||
681 | dmar_acpi_insert_dev_scope(andd->device_number, adev); | ||
682 | } | ||
683 | andd = ((void *)andd) + andd->header.length; | ||
684 | } | ||
685 | return 0; | ||
686 | } | ||
687 | |||
615 | int __init dmar_dev_scope_init(void) | 688 | int __init dmar_dev_scope_init(void) |
616 | { | 689 | { |
617 | struct pci_dev *dev = NULL; | 690 | struct pci_dev *dev = NULL; |
@@ -620,6 +693,8 @@ int __init dmar_dev_scope_init(void) | |||
620 | if (dmar_dev_scope_status != 1) | 693 | if (dmar_dev_scope_status != 1) |
621 | return dmar_dev_scope_status; | 694 | return dmar_dev_scope_status; |
622 | 695 | ||
696 | dmar_acpi_dev_scope_init(); | ||
697 | |||
623 | if (list_empty(&dmar_drhd_units)) { | 698 | if (list_empty(&dmar_drhd_units)) { |
624 | dmar_dev_scope_status = -ENODEV; | 699 | dmar_dev_scope_status = -ENODEV; |
625 | } else { | 700 | } else { |