diff options
author | Joerg Roedel <jroedel@suse.de> | 2015-06-12 14:23:56 +0200 |
---|---|---|
committer | Joerg Roedel <jroedel@suse.de> | 2015-06-16 10:59:35 +0200 |
commit | 9e4e49dfde3bfac48d431893863ac3b9d3f3774a (patch) | |
tree | 3ec8089e65b19fd15b52367dba7eb8d8d1593b8d /drivers/iommu/intel_irq_remapping.c | |
parent | iommu/vt-d: Move EIM detection to intel_prepare_irq_remapping (diff) | |
download | linux-9e4e49dfde3bfac48d431893863ac3b9d3f3774a.tar.xz linux-9e4e49dfde3bfac48d431893863ac3b9d3f3774a.zip |
iommu/vt-d: Move QI initializationt to intel_setup_irq_remapping
QI needs to be enabled when we program the irq remapping
table to hardware in the prepare phase later.
Tested-by: ZhenHua Li <zhen-hual@hp.com>
Tested-by: Baoquan He <bhe@redhat.com>
Signed-off-by: Joerg Roedel <jroedel@suse.de>
Diffstat (limited to 'drivers/iommu/intel_irq_remapping.c')
-rw-r--r-- | drivers/iommu/intel_irq_remapping.c | 92 |
1 files changed, 35 insertions, 57 deletions
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c index 12250f72be0b..46d17e19a461 100644 --- a/drivers/iommu/intel_irq_remapping.c +++ b/drivers/iommu/intel_irq_remapping.c @@ -507,12 +507,35 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu) ir_table->base = page_address(pages); ir_table->bitmap = bitmap; iommu->ir_table = ir_table; + + /* + * If the queued invalidation is already initialized, + * shouldn't disable it. + */ + if (!iommu->qi) { + /* + * Clear previous faults. + */ + dmar_fault(-1, iommu); + dmar_disable_qi(iommu); + + if (dmar_enable_qi(iommu)) { + pr_err("Failed to enable queued invalidation\n"); + goto out_free_bitmap; + } + } + return 0; +out_free_bitmap: + kfree(bitmap); out_free_pages: __free_pages(pages, INTR_REMAP_PAGE_ORDER); out_free_table: kfree(ir_table); + + iommu->ir_table = NULL; + return -ENOMEM; } @@ -637,10 +660,14 @@ static int __init intel_prepare_irq_remapping(void) if (eim) pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n"); - /* Do the allocations early */ - for_each_iommu(iommu, drhd) - if (intel_setup_irq_remapping(iommu)) + /* Do the initializations early */ + for_each_iommu(iommu, drhd) { + if (intel_setup_irq_remapping(iommu)) { + pr_err("Failed to setup irq remapping for %s\n", + iommu->name); goto error; + } + } return 0; @@ -655,42 +682,9 @@ static int __init intel_enable_irq_remapping(void) struct intel_iommu *iommu; bool setup = false; - for_each_iommu(iommu, drhd) { - /* - * If the queued invalidation is already initialized, - * shouldn't disable it. - */ - if (iommu->qi) - continue; - - /* - * Clear previous faults. - */ - dmar_fault(-1, iommu); - - /* - * Disable intr remapping and queued invalidation, if already - * enabled prior to OS handover. - */ + for_each_iommu(iommu, drhd) iommu_disable_irq_remapping(iommu); - dmar_disable_qi(iommu); - } - - /* - * Enable queued invalidation for all the DRHD's. - */ - for_each_iommu(iommu, drhd) { - int ret = dmar_enable_qi(iommu); - - if (ret) { - pr_err("DRHD %Lx: failed to enable queued, " - " invalidation, ecap %Lx, ret %d\n", - drhd->reg_base_addr, iommu->ecap, ret); - goto error; - } - } - /* * Setup Interrupt-remapping for all the DRHD's now. */ @@ -1242,28 +1236,12 @@ static int dmar_ir_add(struct dmar_drhd_unit *dmaru, struct intel_iommu *iommu) /* Setup Interrupt-remapping now. */ ret = intel_setup_irq_remapping(iommu); if (ret) { - pr_err("DRHD %Lx: failed to allocate resource\n", - iommu->reg_phys); - ir_remove_ioapic_hpet_scope(iommu); - return ret; - } - - if (!iommu->qi) { - /* Clear previous faults. */ - dmar_fault(-1, iommu); - iommu_disable_irq_remapping(iommu); - dmar_disable_qi(iommu); - } - - /* Enable queued invalidation */ - ret = dmar_enable_qi(iommu); - if (!ret) { - iommu_set_irq_remapping(iommu, eim); - } else { - pr_err("DRHD %Lx: failed to enable queued invalidation, ecap %Lx, ret %d\n", - iommu->reg_phys, iommu->ecap, ret); + pr_err("Failed to setup irq remapping for %s\n", + iommu->name); intel_teardown_irq_remapping(iommu); ir_remove_ioapic_hpet_scope(iommu); + } else { + iommu_set_irq_remapping(iommu, eim); } return ret; |