Loading drivers/iommu/dmar.c +75 −0 Original line number Diff line number Diff line Loading @@ -612,6 +612,79 @@ out: return dmaru; } static void __init dmar_acpi_insert_dev_scope(u8 device_number, struct acpi_device *adev) { struct dmar_drhd_unit *dmaru; struct acpi_dmar_hardware_unit *drhd; struct acpi_dmar_device_scope *scope; struct device *tmp; int i; struct acpi_dmar_pci_path *path; for_each_drhd_unit(dmaru) { drhd = container_of(dmaru->hdr, struct acpi_dmar_hardware_unit, header); for (scope = (void *)(drhd + 1); (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; scope = ((void *)scope) + scope->length) { if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_ACPI) continue; if (scope->enumeration_id != device_number) continue; path = (void *)(scope + 1); pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n", dev_name(&adev->dev), dmaru->reg_base_addr, scope->bus, path->device, path->function); for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp) if (tmp == NULL) { dmaru->devices[i].bus = scope->bus; dmaru->devices[i].devfn = PCI_DEVFN(path->device, path->function); rcu_assign_pointer(dmaru->devices[i].dev, get_device(&adev->dev)); return; } BUG_ON(i >= dmaru->devices_cnt); } } pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n", device_number, dev_name(&adev->dev)); } static int __init dmar_acpi_dev_scope_init(void) { struct acpi_dmar_andd *andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar); while (((unsigned long)andd) < ((unsigned long)dmar_tbl) + dmar_tbl->length) { if (andd->header.type == ACPI_DMAR_TYPE_ANDD) { acpi_handle h; struct acpi_device *adev; if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, andd->object_name, &h))) { pr_err("Failed to find handle for ACPI object %s\n", andd->object_name); continue; } acpi_bus_get_device(h, &adev); if (!adev) { pr_err("Failed to get device for ACPI object %s\n", andd->object_name); continue; } dmar_acpi_insert_dev_scope(andd->device_number, adev); } andd = ((void *)andd) + andd->header.length; } return 0; } int __init dmar_dev_scope_init(void) { struct pci_dev *dev = NULL; Loading @@ -620,6 +693,8 @@ int __init dmar_dev_scope_init(void) if (dmar_dev_scope_status != 1) return dmar_dev_scope_status; dmar_acpi_dev_scope_init(); if (list_empty(&dmar_drhd_units)) { dmar_dev_scope_status = -ENODEV; } else { Loading Loading
drivers/iommu/dmar.c +75 −0 Original line number Diff line number Diff line Loading @@ -612,6 +612,79 @@ out: return dmaru; } static void __init dmar_acpi_insert_dev_scope(u8 device_number, struct acpi_device *adev) { struct dmar_drhd_unit *dmaru; struct acpi_dmar_hardware_unit *drhd; struct acpi_dmar_device_scope *scope; struct device *tmp; int i; struct acpi_dmar_pci_path *path; for_each_drhd_unit(dmaru) { drhd = container_of(dmaru->hdr, struct acpi_dmar_hardware_unit, header); for (scope = (void *)(drhd + 1); (unsigned long)scope < ((unsigned long)drhd) + drhd->header.length; scope = ((void *)scope) + scope->length) { if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_ACPI) continue; if (scope->enumeration_id != device_number) continue; path = (void *)(scope + 1); pr_info("ACPI device \"%s\" under DMAR at %llx as %02x:%02x.%d\n", dev_name(&adev->dev), dmaru->reg_base_addr, scope->bus, path->device, path->function); for_each_dev_scope(dmaru->devices, dmaru->devices_cnt, i, tmp) if (tmp == NULL) { dmaru->devices[i].bus = scope->bus; dmaru->devices[i].devfn = PCI_DEVFN(path->device, path->function); rcu_assign_pointer(dmaru->devices[i].dev, get_device(&adev->dev)); return; } BUG_ON(i >= dmaru->devices_cnt); } } pr_warn("No IOMMU scope found for ANDD enumeration ID %d (%s)\n", device_number, dev_name(&adev->dev)); } static int __init dmar_acpi_dev_scope_init(void) { struct acpi_dmar_andd *andd = (void *)dmar_tbl + sizeof(struct acpi_table_dmar); while (((unsigned long)andd) < ((unsigned long)dmar_tbl) + dmar_tbl->length) { if (andd->header.type == ACPI_DMAR_TYPE_ANDD) { acpi_handle h; struct acpi_device *adev; if (!ACPI_SUCCESS(acpi_get_handle(ACPI_ROOT_OBJECT, andd->object_name, &h))) { pr_err("Failed to find handle for ACPI object %s\n", andd->object_name); continue; } acpi_bus_get_device(h, &adev); if (!adev) { pr_err("Failed to get device for ACPI object %s\n", andd->object_name); continue; } dmar_acpi_insert_dev_scope(andd->device_number, adev); } andd = ((void *)andd) + andd->header.length; } return 0; } int __init dmar_dev_scope_init(void) { struct pci_dev *dev = NULL; Loading @@ -620,6 +693,8 @@ int __init dmar_dev_scope_init(void) if (dmar_dev_scope_status != 1) return dmar_dev_scope_status; dmar_acpi_dev_scope_init(); if (list_empty(&dmar_drhd_units)) { dmar_dev_scope_status = -ENODEV; } else { Loading