aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJiang Liu <jiang.liu@linux.intel.com>2014-01-06 01:18:27 -0500
committerJoerg Roedel <joro@8bytes.org>2014-01-09 06:44:30 -0500
commit9bdc531ec63bf894c5e3b7b5a766ce342eb2f52e (patch)
tree39facee7d5df268b651c5ec1b877313185c955bc
parentb707cb027edf5b7ff1b8637c184b9a58d74e5159 (diff)
iommu/vt-d: free all resources if failed to initialize DMARs
Enhance intel_iommu_init() to free all resources if failed to initialize DMAR hardware. Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com> Signed-off-by: Joerg Roedel <joro@8bytes.org>
-rw-r--r--drivers/iommu/intel-iommu.c81
1 files changed, 49 insertions, 32 deletions
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 948c6a0d0f5a..5ac7efc70ca9 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2624,6 +2624,7 @@ static int __init init_dmars(void)
2624error: 2624error:
2625 for_each_active_iommu(iommu, drhd) 2625 for_each_active_iommu(iommu, drhd)
2626 free_dmar_iommu(iommu); 2626 free_dmar_iommu(iommu);
2627 kfree(deferred_flush);
2627 kfree(g_iommus); 2628 kfree(g_iommus);
2628 return ret; 2629 return ret;
2629} 2630}
@@ -3467,18 +3468,12 @@ static int __init
3467rmrr_parse_dev(struct dmar_rmrr_unit *rmrru) 3468rmrr_parse_dev(struct dmar_rmrr_unit *rmrru)
3468{ 3469{
3469 struct acpi_dmar_reserved_memory *rmrr; 3470 struct acpi_dmar_reserved_memory *rmrr;
3470 int ret;
3471 3471
3472 rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr; 3472 rmrr = (struct acpi_dmar_reserved_memory *) rmrru->hdr;
3473 ret = dmar_parse_dev_scope((void *)(rmrr + 1), 3473 return dmar_parse_dev_scope((void *)(rmrr + 1),
3474 ((void *)rmrr) + rmrr->header.length, 3474 ((void *)rmrr) + rmrr->header.length,
3475 &rmrru->devices_cnt, &rmrru->devices, rmrr->segment); 3475 &rmrru->devices_cnt, &rmrru->devices,
3476 3476 rmrr->segment);
3477 if (ret || (rmrru->devices_cnt == 0)) {
3478 list_del(&rmrru->list);
3479 kfree(rmrru);
3480 }
3481 return ret;
3482} 3477}
3483 3478
3484static LIST_HEAD(dmar_atsr_units); 3479static LIST_HEAD(dmar_atsr_units);
@@ -3503,23 +3498,39 @@ int __init dmar_parse_one_atsr(struct acpi_dmar_header *hdr)
3503 3498
3504static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru) 3499static int __init atsr_parse_dev(struct dmar_atsr_unit *atsru)
3505{ 3500{
3506 int rc;
3507 struct acpi_dmar_atsr *atsr; 3501 struct acpi_dmar_atsr *atsr;
3508 3502
3509 if (atsru->include_all) 3503 if (atsru->include_all)
3510 return 0; 3504 return 0;
3511 3505
3512 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header); 3506 atsr = container_of(atsru->hdr, struct acpi_dmar_atsr, header);
3513 rc = dmar_parse_dev_scope((void *)(atsr + 1), 3507 return dmar_parse_dev_scope((void *)(atsr + 1),
3514 (void *)atsr + atsr->header.length, 3508 (void *)atsr + atsr->header.length,
3515 &atsru->devices_cnt, &atsru->devices, 3509 &atsru->devices_cnt, &atsru->devices,
3516 atsr->segment); 3510 atsr->segment);
3517 if (rc || !atsru->devices_cnt) { 3511}
3518 list_del(&atsru->list); 3512
3519 kfree(atsru); 3513static void intel_iommu_free_atsr(struct dmar_atsr_unit *atsru)
3514{
3515 dmar_free_dev_scope(&atsru->devices, &atsru->devices_cnt);
3516 kfree(atsru);
3517}
3518
3519static void intel_iommu_free_dmars(void)
3520{
3521 struct dmar_rmrr_unit *rmrru, *rmrr_n;
3522 struct dmar_atsr_unit *atsru, *atsr_n;
3523
3524 list_for_each_entry_safe(rmrru, rmrr_n, &dmar_rmrr_units, list) {
3525 list_del(&rmrru->list);
3526 dmar_free_dev_scope(&rmrru->devices, &rmrru->devices_cnt);
3527 kfree(rmrru);
3520 } 3528 }
3521 3529
3522 return rc; 3530 list_for_each_entry_safe(atsru, atsr_n, &dmar_atsr_units, list) {
3531 list_del(&atsru->list);
3532 intel_iommu_free_atsr(atsru);
3533 }
3523} 3534}
3524 3535
3525int dmar_find_matched_atsr_unit(struct pci_dev *dev) 3536int dmar_find_matched_atsr_unit(struct pci_dev *dev)
@@ -3563,17 +3574,17 @@ found:
3563 3574
3564int __init dmar_parse_rmrr_atsr_dev(void) 3575int __init dmar_parse_rmrr_atsr_dev(void)
3565{ 3576{
3566 struct dmar_rmrr_unit *rmrr, *rmrr_n; 3577 struct dmar_rmrr_unit *rmrr;
3567 struct dmar_atsr_unit *atsr, *atsr_n; 3578 struct dmar_atsr_unit *atsr;
3568 int ret = 0; 3579 int ret = 0;
3569 3580
3570 list_for_each_entry_safe(rmrr, rmrr_n, &dmar_rmrr_units, list) { 3581 list_for_each_entry(rmrr, &dmar_rmrr_units, list) {
3571 ret = rmrr_parse_dev(rmrr); 3582 ret = rmrr_parse_dev(rmrr);
3572 if (ret) 3583 if (ret)
3573 return ret; 3584 return ret;
3574 } 3585 }
3575 3586
3576 list_for_each_entry_safe(atsr, atsr_n, &dmar_atsr_units, list) { 3587 list_for_each_entry(atsr, &dmar_atsr_units, list) {
3577 ret = atsr_parse_dev(atsr); 3588 ret = atsr_parse_dev(atsr);
3578 if (ret) 3589 if (ret)
3579 return ret; 3590 return ret;
@@ -3620,7 +3631,7 @@ static struct notifier_block device_nb = {
3620 3631
3621int __init intel_iommu_init(void) 3632int __init intel_iommu_init(void)
3622{ 3633{
3623 int ret = 0; 3634 int ret = -ENODEV;
3624 struct dmar_drhd_unit *drhd; 3635 struct dmar_drhd_unit *drhd;
3625 struct intel_iommu *iommu; 3636 struct intel_iommu *iommu;
3626 3637
@@ -3630,7 +3641,7 @@ int __init intel_iommu_init(void)
3630 if (dmar_table_init()) { 3641 if (dmar_table_init()) {
3631 if (force_on) 3642 if (force_on)
3632 panic("tboot: Failed to initialize DMAR table\n"); 3643 panic("tboot: Failed to initialize DMAR table\n");
3633 return -ENODEV; 3644 goto out_free_dmar;
3634 } 3645 }
3635 3646
3636 /* 3647 /*
@@ -3643,16 +3654,16 @@ int __init intel_iommu_init(void)
3643 if (dmar_dev_scope_init() < 0) { 3654 if (dmar_dev_scope_init() < 0) {
3644 if (force_on) 3655 if (force_on)
3645 panic("tboot: Failed to initialize DMAR device scope\n"); 3656 panic("tboot: Failed to initialize DMAR device scope\n");
3646 return -ENODEV; 3657 goto out_free_dmar;
3647 } 3658 }
3648 3659
3649 if (no_iommu || dmar_disabled) 3660 if (no_iommu || dmar_disabled)
3650 return -ENODEV; 3661 goto out_free_dmar;
3651 3662
3652 if (iommu_init_mempool()) { 3663 if (iommu_init_mempool()) {
3653 if (force_on) 3664 if (force_on)
3654 panic("tboot: Failed to initialize iommu memory\n"); 3665 panic("tboot: Failed to initialize iommu memory\n");
3655 return -ENODEV; 3666 goto out_free_dmar;
3656 } 3667 }
3657 3668
3658 if (list_empty(&dmar_rmrr_units)) 3669 if (list_empty(&dmar_rmrr_units))
@@ -3664,7 +3675,7 @@ int __init intel_iommu_init(void)
3664 if (dmar_init_reserved_ranges()) { 3675 if (dmar_init_reserved_ranges()) {
3665 if (force_on) 3676 if (force_on)
3666 panic("tboot: Failed to reserve iommu ranges\n"); 3677 panic("tboot: Failed to reserve iommu ranges\n");
3667 return -ENODEV; 3678 goto out_free_mempool;
3668 } 3679 }
3669 3680
3670 init_no_remapping_devices(); 3681 init_no_remapping_devices();
@@ -3674,9 +3685,7 @@ int __init intel_iommu_init(void)
3674 if (force_on) 3685 if (force_on)
3675 panic("tboot: Failed to initialize DMARs\n"); 3686 panic("tboot: Failed to initialize DMARs\n");
3676 printk(KERN_ERR "IOMMU: dmar init failed\n"); 3687 printk(KERN_ERR "IOMMU: dmar init failed\n");
3677 put_iova_domain(&reserved_iova_list); 3688 goto out_free_reserved_range;
3678 iommu_exit_mempool();
3679 return ret;
3680 } 3689 }
3681 printk(KERN_INFO 3690 printk(KERN_INFO
3682 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n"); 3691 "PCI-DMA: Intel(R) Virtualization Technology for Directed I/O\n");
@@ -3696,6 +3705,14 @@ int __init intel_iommu_init(void)
3696 intel_iommu_enabled = 1; 3705 intel_iommu_enabled = 1;
3697 3706
3698 return 0; 3707 return 0;
3708
3709out_free_reserved_range:
3710 put_iova_domain(&reserved_iova_list);
3711out_free_mempool:
3712 iommu_exit_mempool();
3713out_free_dmar:
3714 intel_iommu_free_dmars();
3715 return ret;
3699} 3716}
3700 3717
3701static void iommu_detach_dependent_devices(struct intel_iommu *iommu, 3718static void iommu_detach_dependent_devices(struct intel_iommu *iommu,