diff options
-rw-r--r-- | drivers/iommu/dmar.c | 14 | ||||
-rw-r--r-- | drivers/iommu/intel-iommu.c | 100 | ||||
-rw-r--r-- | include/linux/dmar.h | 6 |
3 files changed, 64 insertions, 56 deletions
diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c index 58dde75c5229..4ae6df27ad5d 100644 --- a/drivers/iommu/dmar.c +++ b/drivers/iommu/dmar.c | |||
@@ -170,9 +170,12 @@ int __init dmar_parse_dev_scope(void *start, void *end, int *cnt, | |||
170 | 170 | ||
171 | void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt) | 171 | void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt) |
172 | { | 172 | { |
173 | int i; | ||
174 | struct pci_dev *tmp_dev; | ||
175 | |||
173 | if (*devices && *cnt) { | 176 | if (*devices && *cnt) { |
174 | while (--*cnt >= 0) | 177 | for_each_active_dev_scope(*devices, *cnt, i, tmp_dev) |
175 | pci_dev_put((*devices)[*cnt]); | 178 | pci_dev_put(tmp_dev); |
176 | kfree(*devices); | 179 | kfree(*devices); |
177 | *devices = NULL; | 180 | *devices = NULL; |
178 | *cnt = 0; | 181 | *cnt = 0; |
@@ -402,10 +405,11 @@ static int dmar_pci_device_match(struct pci_dev *devices[], int cnt, | |||
402 | struct pci_dev *dev) | 405 | struct pci_dev *dev) |
403 | { | 406 | { |
404 | int index; | 407 | int index; |
408 | struct pci_dev *tmp; | ||
405 | 409 | ||
406 | while (dev) { | 410 | while (dev) { |
407 | for (index = 0; index < cnt; index++) | 411 | for_each_active_dev_scope(devices, cnt, index, tmp) |
408 | if (dev == devices[index]) | 412 | if (dev == tmp) |
409 | return 1; | 413 | return 1; |
410 | 414 | ||
411 | /* Check our parent */ | 415 | /* Check our parent */ |
@@ -452,7 +456,7 @@ int __init dmar_dev_scope_init(void) | |||
452 | if (list_empty(&dmar_drhd_units)) | 456 | if (list_empty(&dmar_drhd_units)) |
453 | goto fail; | 457 | goto fail; |
454 | 458 | ||
455 | list_for_each_entry(drhd, &dmar_drhd_units, list) { | 459 | for_each_drhd_unit(drhd) { |
456 | ret = dmar_parse_dev(drhd); | 460 | ret = dmar_parse_dev(drhd); |
457 | if (ret) | 461 | if (ret) |
458 | goto fail; | 462 | goto fail; |
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c index 7732c43871fa..bb98e37f2cf7 100644 --- a/drivers/iommu/intel-iommu.c +++ b/drivers/iommu/intel-iommu.c | |||
@@ -654,29 +654,31 @@ static void domain_update_iommu_cap(struct dmar_domain *domain) | |||
654 | static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) | 654 | static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) |
655 | { | 655 | { |
656 | struct dmar_drhd_unit *drhd = NULL; | 656 | struct dmar_drhd_unit *drhd = NULL; |
657 | struct intel_iommu *iommu; | ||
658 | struct pci_dev *dev; | ||
657 | int i; | 659 | int i; |
658 | 660 | ||
659 | for_each_active_drhd_unit(drhd) { | 661 | for_each_active_iommu(iommu, drhd) { |
660 | if (segment != drhd->segment) | 662 | if (segment != drhd->segment) |
661 | continue; | 663 | continue; |
662 | 664 | ||
663 | for (i = 0; i < drhd->devices_cnt; i++) { | 665 | for_each_active_dev_scope(drhd->devices, |
664 | if (drhd->devices[i] && | 666 | drhd->devices_cnt, i, dev) { |
665 | drhd->devices[i]->bus->number == bus && | 667 | if (dev->bus->number == bus && dev->devfn == devfn) |
666 | drhd->devices[i]->devfn == devfn) | 668 | goto out; |
667 | return drhd->iommu; | 669 | if (dev->subordinate && |
668 | if (drhd->devices[i] && | 670 | dev->subordinate->number <= bus && |
669 | drhd->devices[i]->subordinate && | 671 | dev->subordinate->busn_res.end >= bus) |
670 | drhd->devices[i]->subordinate->number <= bus && | 672 | goto out; |
671 | drhd->devices[i]->subordinate->busn_res.end >= bus) | ||
672 | return drhd->iommu; | ||
673 | } | 673 | } |
674 | 674 | ||
675 | if (drhd->include_all) | 675 | if (drhd->include_all) |
676 | return drhd->iommu; | 676 | goto out; |
677 | } | 677 | } |
678 | iommu = NULL; | ||
679 | out: | ||
678 | 680 | ||
679 | return NULL; | 681 | return iommu; |
680 | } | 682 | } |
681 | 683 | ||
682 | static void domain_flush_cache(struct dmar_domain *domain, | 684 | static void domain_flush_cache(struct dmar_domain *domain, |
@@ -2333,17 +2335,19 @@ static int domain_add_dev_info(struct dmar_domain *domain, | |||
2333 | static bool device_has_rmrr(struct pci_dev *dev) | 2335 | static bool device_has_rmrr(struct pci_dev *dev) |
2334 | { | 2336 | { |
2335 | struct dmar_rmrr_unit *rmrr; | 2337 | struct dmar_rmrr_unit *rmrr; |
2338 | struct pci_dev *tmp; | ||
2336 | int i; | 2339 | int i; |
2337 | 2340 | ||
2338 | for_each_rmrr_units(rmrr) { | 2341 | for_each_rmrr_units(rmrr) { |
2339 | for (i = 0; i < rmrr->devices_cnt; i++) { | 2342 | /* |
2340 | /* | 2343 | * Return TRUE if this RMRR contains the device that |
2341 | * Return TRUE if this RMRR contains the device that | 2344 | * is passed in. |
2342 | * is passed in. | 2345 | */ |
2343 | */ | 2346 | for_each_active_dev_scope(rmrr->devices, |
2344 | if (rmrr->devices[i] == dev) | 2347 | rmrr->devices_cnt, i, tmp) |
2348 | if (tmp == dev) { | ||
2345 | return true; | 2349 | return true; |
2346 | } | 2350 | } |
2347 | } | 2351 | } |
2348 | return false; | 2352 | return false; |
2349 | } | 2353 | } |
@@ -2593,14 +2597,9 @@ static int __init init_dmars(void) | |||
2593 | */ | 2597 | */ |
2594 | printk(KERN_INFO "IOMMU: Setting RMRR:\n"); | 2598 | printk(KERN_INFO "IOMMU: Setting RMRR:\n"); |
2595 | for_each_rmrr_units(rmrr) { | 2599 | for_each_rmrr_units(rmrr) { |
2596 | for (i = 0; i < rmrr->devices_cnt; i++) { | 2600 | /* some BIOS lists non-exist devices in DMAR table. */ |
2597 | pdev = rmrr->devices[i]; | 2601 | for_each_active_dev_scope(rmrr->devices, rmrr->devices_cnt, |
2598 | /* | 2602 | i, pdev) { |
2599 | * some BIOS lists non-exist devices in DMAR | ||
2600 | * table. | ||
2601 | */ | ||
2602 | if (!pdev) | ||
2603 | continue; | ||
2604 | ret = iommu_prepare_rmrr_dev(rmrr, pdev); | 2603 | ret = iommu_prepare_rmrr_dev(rmrr, pdev); |
2605 | if (ret) | 2604 | if (ret) |
2606 | printk(KERN_ERR | 2605 | printk(KERN_ERR |
@@ -3288,13 +3287,14 @@ DECLARE_PCI_FIXUP_ENABLE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IOAT_SNB, quir | |||
3288 | static void __init init_no_remapping_devices(void) | 3287 | static void __init init_no_remapping_devices(void) |
3289 | { | 3288 | { |
3290 | struct dmar_drhd_unit *drhd; | 3289 | struct dmar_drhd_unit *drhd; |
3290 | struct pci_dev *dev; | ||
3291 | int i; | ||
3291 | 3292 | ||
3292 | for_each_drhd_unit(drhd) { | 3293 | for_each_drhd_unit(drhd) { |
3293 | if (!drhd->include_all) { | 3294 | if (!drhd->include_all) { |
3294 | int i; | 3295 | for_each_active_dev_scope(drhd->devices, |
3295 | for (i = 0; i < drhd->devices_cnt; i++) | 3296 | drhd->devices_cnt, i, dev) |
3296 | if (drhd->devices[i] != NULL) | 3297 | break; |
3297 | break; | ||
3298 | /* ignore DMAR unit if no pci devices exist */ | 3298 | /* ignore DMAR unit if no pci devices exist */ |
3299 | if (i == drhd->devices_cnt) | 3299 | if (i == drhd->devices_cnt) |
3300 | drhd->ignored = 1; | 3300 | drhd->ignored = 1; |
@@ -3302,15 +3302,13 @@ static void __init init_no_remapping_devices(void) | |||
3302 | } | 3302 | } |
3303 | 3303 | ||
3304 | for_each_active_drhd_unit(drhd) { | 3304 | for_each_active_drhd_unit(drhd) { |
3305 | int i; | ||
3306 | if (drhd->include_all) | 3305 | if (drhd->include_all) |
3307 | continue; | 3306 | continue; |
3308 | 3307 | ||
3309 | for (i = 0; i < drhd->devices_cnt; i++) | 3308 | for_each_active_dev_scope(drhd->devices, |
3310 | if (drhd->devices[i] && | 3309 | drhd->devices_cnt, i, dev) |
3311 | !IS_GFX_DEVICE(drhd->devices[i])) | 3310 | if (!IS_GFX_DEVICE(dev)) |
3312 | break; | 3311 | break; |
3313 | |||
3314 | if (i < drhd->devices_cnt) | 3312 | if (i < drhd->devices_cnt) |
3315 | continue; | 3313 | continue; |
3316 | 3314 | ||
@@ -3320,11 +3318,9 @@ static void __init init_no_remapping_devices(void) | |||
3320 | intel_iommu_gfx_mapped = 1; | 3318 | intel_iommu_gfx_mapped = 1; |
3321 | } else { | 3319 | } else { |
3322 | drhd->ignored = 1; | 3320 | drhd->ignored = 1; |
3323 | for (i = 0; i < drhd->devices_cnt; i++) { | 3321 | for_each_active_dev_scope(drhd->devices, |
3324 | if (!drhd->devices[i]) | 3322 | drhd->devices_cnt, i, dev) |
3325 | continue; | 3323 | dev->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; |
3326 | drhd->devices[i]->dev.archdata.iommu = DUMMY_DEVICE_DOMAIN_INFO; | ||
3327 | } | ||
3328 | } | 3324 | } |
3329 | } | 3325 | } |
3330 | } | 3326 | } |
@@ -3560,9 +3556,9 @@ static void intel_iommu_free_dmars(void) | |||
3560 | 3556 | ||
3561 | int dmar_find_matched_atsr_unit(struct pci_dev *dev) | 3557 | int dmar_find_matched_atsr_unit(struct pci_dev *dev) |
3562 | { | 3558 | { |
3563 | int i; | 3559 | int i, ret = 1; |
3564 | struct pci_bus *bus; | 3560 | struct pci_bus *bus; |
3565 | struct pci_dev *bridge = NULL; | 3561 | struct pci_dev *bridge = NULL, *tmp; |
3566 | struct acpi_dmar_atsr *atsr; | 3562 | struct acpi_dmar_atsr *atsr; |
3567 | struct dmar_atsr_unit *atsru; | 3563 | struct dmar_atsr_unit *atsru; |
3568 | 3564 | ||
@@ -3583,22 +3579,24 @@ int dmar_find_matched_atsr_unit(struct pci_dev *dev) | |||
3583 | if (atsr->segment != pci_domain_nr(dev->bus)) | 3579 | if (atsr->segment != pci_domain_nr(dev->bus)) |
3584 | continue; | 3580 | continue; |
3585 | 3581 | ||
3586 | for (i = 0; i < atsru->devices_cnt; i++) | 3582 | for_each_dev_scope(atsru->devices, atsru->devices_cnt, i, tmp) |
3587 | if (atsru->devices[i] == bridge) | 3583 | if (tmp == bridge) |
3588 | return 1; | 3584 | goto out; |
3589 | 3585 | ||
3590 | if (atsru->include_all) | 3586 | if (atsru->include_all) |
3591 | return 1; | 3587 | goto out; |
3592 | } | 3588 | } |
3589 | ret = 0; | ||
3590 | out: | ||
3593 | 3591 | ||
3594 | return 0; | 3592 | return ret; |
3595 | } | 3593 | } |
3596 | 3594 | ||
3597 | int __init dmar_parse_rmrr_atsr_dev(void) | 3595 | int __init dmar_parse_rmrr_atsr_dev(void) |
3598 | { | 3596 | { |
3599 | struct dmar_rmrr_unit *rmrr; | 3597 | struct dmar_rmrr_unit *rmrr; |
3600 | struct dmar_atsr_unit *atsr; | 3598 | struct dmar_atsr_unit *atsr; |
3601 | int ret = 0; | 3599 | int ret; |
3602 | 3600 | ||
3603 | list_for_each_entry(rmrr, &dmar_rmrr_units, list) { | 3601 | list_for_each_entry(rmrr, &dmar_rmrr_units, list) { |
3604 | ret = rmrr_parse_dev(rmrr); | 3602 | ret = rmrr_parse_dev(rmrr); |
@@ -3612,7 +3610,7 @@ int __init dmar_parse_rmrr_atsr_dev(void) | |||
3612 | return ret; | 3610 | return ret; |
3613 | } | 3611 | } |
3614 | 3612 | ||
3615 | return ret; | 3613 | return 0; |
3616 | } | 3614 | } |
3617 | 3615 | ||
3618 | /* | 3616 | /* |
diff --git a/include/linux/dmar.h b/include/linux/dmar.h index ea599d4ca9e0..4b77fd8fde76 100644 --- a/include/linux/dmar.h +++ b/include/linux/dmar.h | |||
@@ -65,6 +65,12 @@ extern struct list_head dmar_drhd_units; | |||
65 | list_for_each_entry(drhd, &dmar_drhd_units, list) \ | 65 | list_for_each_entry(drhd, &dmar_drhd_units, list) \ |
66 | if (i=drhd->iommu, 0) {} else | 66 | if (i=drhd->iommu, 0) {} else |
67 | 67 | ||
68 | #define for_each_dev_scope(a, c, p, d) \ | ||
69 | for ((p) = 0; ((d) = (p) < (c) ? (a)[(p)] : NULL, (p) < (c)); (p)++) | ||
70 | |||
71 | #define for_each_active_dev_scope(a, c, p, d) \ | ||
72 | for_each_dev_scope((a), (c), (p), (d)) if (!(d)) { continue; } else | ||
73 | |||
68 | extern int dmar_table_init(void); | 74 | extern int dmar_table_init(void); |
69 | extern int dmar_dev_scope_init(void); | 75 | extern int dmar_dev_scope_init(void); |
70 | extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, | 76 | extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, |