Commit 023e62ce authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'iommu-fixes-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux

Pull iommu fixes from Joerg Roedel:

 - Fix two crashes, one in core code and a NULL-ptr dereference in the
   Mediatek IOMMU driver

 - Dma_ops cleanup fix for core code

 - Two fixes for Intel VT-d driver:
     - Fix posted MSI issue when users change cpu affinity
     - Remove invalid set_dma_ops() call in the iommu driver

 - Warning fix for Tegra IOMMU driver

 - Suspend/Resume fix for Exynos IOMMU driver

 - Probe failure fix for Renesas IOMMU driver

 - Cosmetic fix

* tag 'iommu-fixes-v6.15-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/iommu/linux:
  iommu/tegra241-cmdqv: Fix warnings due to dmam_free_coherent()
  iommu: remove unneeded semicolon
  iommu/mediatek: Fix NULL pointer deference in mtk_iommu_device_group
  iommu/exynos: Fix suspend/resume with IDENTITY domain
  iommu/ipmmu-vmsa: Register in a sensible order
  iommu: Clear iommu-dma ops on cleanup
  iommu/vt-d: Remove an unnecessary call set_dma_ops()
  iommu/vt-d: Wire up irq_ack() to irq_move_irq() for posted MSIs
  iommu: Fix crash in report_iommu_fault()
parents c86e5b56 767e2200
Loading
Loading
Loading
Loading
+5 −27
Original line number Diff line number Diff line
@@ -487,17 +487,6 @@ static int tegra241_cmdqv_hw_reset(struct arm_smmu_device *smmu)

/* VCMDQ Resource Helpers */

static void tegra241_vcmdq_free_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
{
	struct arm_smmu_queue *q = &vcmdq->cmdq.q;
	size_t nents = 1 << q->llq.max_n_shift;
	size_t qsz = nents << CMDQ_ENT_SZ_SHIFT;

	if (!q->base)
		return;
	dmam_free_coherent(vcmdq->cmdqv->smmu.dev, qsz, q->base, q->base_dma);
}

static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
{
	struct arm_smmu_device *smmu = &vcmdq->cmdqv->smmu;
@@ -560,7 +549,8 @@ static void tegra241_vintf_free_lvcmdq(struct tegra241_vintf *vintf, u16 lidx)
	struct tegra241_vcmdq *vcmdq = vintf->lvcmdqs[lidx];
	char header[64];

	tegra241_vcmdq_free_smmu_cmdq(vcmdq);
	/* Note that the lvcmdq queue memory space is managed by devres */

	tegra241_vintf_deinit_lvcmdq(vintf, lidx);

	dev_dbg(vintf->cmdqv->dev,
@@ -768,13 +758,13 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu)

	vintf = kzalloc(sizeof(*vintf), GFP_KERNEL);
	if (!vintf)
		goto out_fallback;
		return -ENOMEM;

	/* Init VINTF0 for in-kernel use */
	ret = tegra241_cmdqv_init_vintf(cmdqv, 0, vintf);
	if (ret) {
		dev_err(cmdqv->dev, "failed to init vintf0: %d\n", ret);
		goto free_vintf;
		return ret;
	}

	/* Preallocate logical VCMDQs to VINTF0 */
@@ -783,24 +773,12 @@ static int tegra241_cmdqv_init_structures(struct arm_smmu_device *smmu)

		vcmdq = tegra241_vintf_alloc_lvcmdq(vintf, lidx);
		if (IS_ERR(vcmdq))
			goto free_lvcmdq;
			return PTR_ERR(vcmdq);
	}

	/* Now, we are ready to run all the impl ops */
	smmu->impl_ops = &tegra241_cmdqv_impl_ops;
	return 0;

free_lvcmdq:
	for (lidx--; lidx >= 0; lidx--)
		tegra241_vintf_free_lvcmdq(vintf, lidx);
	tegra241_cmdqv_deinit_vintf(cmdqv, vintf->idx);
free_vintf:
	kfree(vintf);
out_fallback:
	dev_info(smmu->impl_dev, "Falling back to standard SMMU CMDQ\n");
	smmu->options &= ~ARM_SMMU_OPT_TEGRA241_CMDQV;
	tegra241_cmdqv_remove(smmu);
	return 0;
}

#ifdef CONFIG_IOMMU_DEBUGFS
+2 −2
Original line number Diff line number Diff line
@@ -1754,7 +1754,7 @@ static size_t cookie_msi_granule(const struct iommu_domain *domain)
		return PAGE_SIZE;
	default:
		BUG();
	};
	}
}

static struct list_head *cookie_msi_pages(const struct iommu_domain *domain)
@@ -1766,7 +1766,7 @@ static struct list_head *cookie_msi_pages(const struct iommu_domain *domain)
		return &domain->msi_cookie->msi_page_list;
	default:
		BUG();
	};
	}
}

static struct iommu_dma_msi_page *iommu_dma_get_msi_page(struct device *dev,
+2 −2
Original line number Diff line number Diff line
@@ -832,7 +832,7 @@ static int __maybe_unused exynos_sysmmu_suspend(struct device *dev)
		struct exynos_iommu_owner *owner = dev_iommu_priv_get(master);

		mutex_lock(&owner->rpm_lock);
		if (&data->domain->domain != &exynos_identity_domain) {
		if (data->domain) {
			dev_dbg(data->sysmmu, "saving state\n");
			__sysmmu_disable(data);
		}
@@ -850,7 +850,7 @@ static int __maybe_unused exynos_sysmmu_resume(struct device *dev)
		struct exynos_iommu_owner *owner = dev_iommu_priv_get(master);

		mutex_lock(&owner->rpm_lock);
		if (&data->domain->domain != &exynos_identity_domain) {
		if (data->domain) {
			dev_dbg(data->sysmmu, "restoring state\n");
			__sysmmu_enable(data);
		}
+0 −1
Original line number Diff line number Diff line
@@ -3835,7 +3835,6 @@ static void intel_iommu_release_device(struct device *dev)
	intel_pasid_free_table(dev);
	intel_iommu_debugfs_remove_dev(info);
	kfree(info);
	set_dma_ops(dev, NULL);
}

static void intel_iommu_get_resv_regions(struct device *device,
+15 −14
Original line number Diff line number Diff line
@@ -1287,43 +1287,44 @@ static struct irq_chip intel_ir_chip = {
};

/*
 * With posted MSIs, all vectors are multiplexed into a single notification
 * vector. Devices MSIs are then dispatched in a demux loop where
 * EOIs can be coalesced as well.
 * With posted MSIs, the MSI vectors are multiplexed into a single notification
 * vector, and only the notification vector is sent to the APIC IRR.  Device
 * MSIs are then dispatched in a demux loop that harvests the MSIs from the
 * CPU's Posted Interrupt Request bitmap.  I.e. Posted MSIs never get sent to
 * the APIC IRR, and thus do not need an EOI.  The notification handler instead
 * performs a single EOI after processing the PIR.
 *
 * "INTEL-IR-POST" IRQ chip does not do EOI on ACK, thus the dummy irq_ack()
 * function. Instead EOI is performed by the posted interrupt notification
 * handler.
 * Note!  Pending SMP/CPU affinity changes, which are per MSI, must still be
 * honored, only the APIC EOI is omitted.
 *
 * For the example below, 3 MSIs are coalesced into one CPU notification. Only
 * one apic_eoi() is needed.
 * one apic_eoi() is needed, but each MSI needs to process pending changes to
 * its CPU affinity.
 *
 * __sysvec_posted_msi_notification()
 *	irq_enter();
 *		handle_edge_irq()
 *			irq_chip_ack_parent()
 *				dummy(); // No EOI
 *				irq_move_irq(); // No EOI
 *			handle_irq_event()
 *				driver_handler()
 *		handle_edge_irq()
 *			irq_chip_ack_parent()
 *				dummy(); // No EOI
 *				irq_move_irq(); // No EOI
 *			handle_irq_event()
 *				driver_handler()
 *		handle_edge_irq()
 *			irq_chip_ack_parent()
 *				dummy(); // No EOI
 *				irq_move_irq(); // No EOI
 *			handle_irq_event()
 *				driver_handler()
 *	apic_eoi()
 *	irq_exit()
 *
 */

static void dummy_ack(struct irq_data *d) { }

static struct irq_chip intel_ir_chip_post_msi = {
	.name			= "INTEL-IR-POST",
	.irq_ack		= dummy_ack,
	.irq_ack		= irq_move_irq,
	.irq_set_affinity	= intel_ir_set_affinity,
	.irq_compose_msi_msg	= intel_ir_compose_msi_msg,
	.irq_set_vcpu_affinity	= intel_ir_set_vcpu_affinity,
Loading