aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/iommu/dmar.c14
-rw-r--r--drivers/iommu/intel-iommu.c100
-rw-r--r--include/linux/dmar.h6
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
171void dmar_free_dev_scope(struct pci_dev ***devices, int *cnt) 171void 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)
654static struct intel_iommu *device_to_iommu(int segment, u8 bus, u8 devfn) 654static 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;
679out:
678 680
679 return NULL; 681 return iommu;
680} 682}
681 683
682static void domain_flush_cache(struct dmar_domain *domain, 684static void domain_flush_cache(struct dmar_domain *domain,
@@ -2333,17 +2335,19 @@ static int domain_add_dev_info(struct dmar_domain *domain,
2333static bool device_has_rmrr(struct pci_dev *dev) 2335static 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
3288static void __init init_no_remapping_devices(void) 3287static 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
3561int dmar_find_matched_atsr_unit(struct pci_dev *dev) 3557int 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;
3590out:
3593 3591
3594 return 0; 3592 return ret;
3595} 3593}
3596 3594
3597int __init dmar_parse_rmrr_atsr_dev(void) 3595int __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
68extern int dmar_table_init(void); 74extern int dmar_table_init(void);
69extern int dmar_dev_scope_init(void); 75extern int dmar_dev_scope_init(void);
70extern int dmar_parse_dev_scope(void *start, void *end, int *cnt, 76extern int dmar_parse_dev_scope(void *start, void *end, int *cnt,