Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9e4e49df authored by Joerg Roedel's avatar Joerg Roedel
Browse files

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: default avatarZhenHua Li <zhen-hual@hp.com>
Tested-by: default avatarBaoquan He <bhe@redhat.com>
Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent 23256d0b
Loading
Loading
Loading
Loading
+35 −57
Original line number Original line Diff line number Diff line
@@ -507,12 +507,35 @@ static int intel_setup_irq_remapping(struct intel_iommu *iommu)
	ir_table->base = page_address(pages);
	ir_table->base = page_address(pages);
	ir_table->bitmap = bitmap;
	ir_table->bitmap = bitmap;
	iommu->ir_table = ir_table;
	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;
	return 0;


out_free_bitmap:
	kfree(bitmap);
out_free_pages:
out_free_pages:
	__free_pages(pages, INTR_REMAP_PAGE_ORDER);
	__free_pages(pages, INTR_REMAP_PAGE_ORDER);
out_free_table:
out_free_table:
	kfree(ir_table);
	kfree(ir_table);

	iommu->ir_table  = NULL;

	return -ENOMEM;
	return -ENOMEM;
}
}


@@ -637,10 +660,14 @@ static int __init intel_prepare_irq_remapping(void)
	if (eim)
	if (eim)
		pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");
		pr_info("Queued invalidation will be enabled to support x2apic and Intr-remapping.\n");


	/* Do the allocations early */
	/* Do the initializations early */
	for_each_iommu(iommu, drhd)
	for_each_iommu(iommu, drhd) {
		if (intel_setup_irq_remapping(iommu))
		if (intel_setup_irq_remapping(iommu)) {
			pr_err("Failed to setup irq remapping for %s\n",
			       iommu->name);
			goto error;
			goto error;
		}
	}


	return 0;
	return 0;


@@ -655,42 +682,9 @@ static int __init intel_enable_irq_remapping(void)
	struct intel_iommu *iommu;
	struct intel_iommu *iommu;
	bool setup = false;
	bool setup = false;


	for_each_iommu(iommu, drhd) {
	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.
		 */
		iommu_disable_irq_remapping(iommu);
		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.
	 * 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. */
	/* Setup Interrupt-remapping now. */
	ret = intel_setup_irq_remapping(iommu);
	ret = intel_setup_irq_remapping(iommu);
	if (ret) {
	if (ret) {
		pr_err("DRHD %Lx: failed to allocate resource\n",
		pr_err("Failed to setup irq remapping for %s\n",
		       iommu->reg_phys);
		       iommu->name);
		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);
		intel_teardown_irq_remapping(iommu);
		intel_teardown_irq_remapping(iommu);
		ir_remove_ioapic_hpet_scope(iommu);
		ir_remove_ioapic_hpet_scope(iommu);
	} else {
		iommu_set_irq_remapping(iommu, eim);
	}
	}


	return ret;
	return ret;