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

Commit 990b325a authored by Qingqing Zhou's avatar Qingqing Zhou
Browse files

arm: dma_mapping: Support for DOMAIN_ATTR_S1_BYPASS attribute



For iommus which do not use stage1 translation, stage2 may not be aware
of the device's dma_mask requirements. Choose the dma_ops such that
allocations are made within the dma_mask region and bounce buffers are
used as necessary.

Change-Id: I63ae3ff9e5ab608892d12db7a813264d234699ee
Signed-off-by: default avatarCharan Teja Reddy <charante@codeaurora.org>
Signed-off-by: default avatarQingqing Zhou <qqzhou@codeaurora.org>
parent 19736bfe
Loading
Loading
Loading
Loading
+20 −5
Original line number Diff line number Diff line
@@ -2467,6 +2467,7 @@ static bool arm_setup_iommu_dma_ops(struct device *dev, u64 dma_base, u64 size,
static void arm_teardown_iommu_dma_ops(struct device *dev)
{
	struct dma_iommu_mapping *mapping;
	int s1_bypass = 0;

	mapping = to_dma_iommu_mapping(dev);
	if (!mapping)
@@ -2474,6 +2475,13 @@ static void arm_teardown_iommu_dma_ops(struct device *dev)

	kref_put(&mapping->kref, arm_iommu_dma_release_mapping);
	to_dma_iommu_mapping(dev) = NULL;

	/* Let arch_setup_dma_ops() start again from scratch upon re-probe */
	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS,
			&s1_bypass);
	if (!s1_bypass)
		set_dma_ops(dev, NULL);

}
#else

@@ -2493,6 +2501,8 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
			const struct iommu_ops *iommu, bool coherent)
{
	const struct dma_map_ops *dma_ops;
	struct dma_iommu_mapping *mapping;
	int s1_bypass = 0;

	dev->archdata.dma_coherent = coherent;

@@ -2504,9 +2514,16 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
	if (dev->dma_ops)
		return;

	if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu))
		dma_ops = arm_get_iommu_dma_map_ops(coherent);
	if (arm_setup_iommu_dma_ops(dev, dma_base, size, iommu)) {
		mapping = to_dma_iommu_mapping(dev);
		if (mapping)
			iommu_domain_get_attr(mapping->domain,
				DOMAIN_ATTR_S1_BYPASS, &s1_bypass);
		if (s1_bypass)
			dma_ops = arm_get_dma_map_ops(coherent);
		else
			dma_ops = arm_get_iommu_dma_map_ops(coherent);
	} else
		dma_ops = arm_get_dma_map_ops(coherent);

	set_dma_ops(dev, dma_ops);
@@ -2526,6 +2543,4 @@ void arch_teardown_dma_ops(struct device *dev)
		return;

	arm_teardown_iommu_dma_ops(dev);
	/* Let arch_setup_dma_ops() start again from scratch upon re-probe */
	set_dma_ops(dev, NULL);
}