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

Commit 8a17ef31 authored by Liam Mark's avatar Liam Mark
Browse files

iommu/arm-smmu: add support to configure IOVA range



For IOMMU clients the DMA layer only allocates IOVA addresses within the
range specified by the qcom,iommu-dma-addr-pool DT property.
The remaining IOVA addresses outside of this range, but limited to
[0 - 4GB) for fastmap clients, can be used by calls such as iommu_map and
iommu_map_sg.

Fastmap pre-allocates the page tables for its fully supported IOVA range,
which is [0 - 4GB), and this consumes 8MB of memory. Because clients often
don't use most of the IOVA addresses outside of the DMA layer IOVA range
allow fastmap clients to use the qcom,iommu-geometry DT property to
specify only the IOVA range which needs to be supported in order to save
memory.

CRs-Fixed: 2035925
Change-Id: Ib389e019a022d98417884002de08115fb0fc9384
[lmark@codeaurora.org: removed support for DOMAIN_ATTR_GEOMETRY domain]
Signed-off-by: default avatarLiam Mark <lmark@codeaurora.org>
[guptap@codeaurora.org: update geometry.aperture with mapping]
Signed-off-by: default avatarPrakash Gupta <guptap@codeaurora.org>
parent 7416fc80
Loading
Loading
Loading
Loading
+37 −5
Original line number Original line Diff line number Diff line
@@ -1834,25 +1834,55 @@ static int arm_smmu_get_domain_iova_range(struct device *dev,
					   dma_addr_t *ret_end)
					   dma_addr_t *ret_end)
{
{
	dma_addr_t iova_base, iova_end;
	dma_addr_t iova_base, iova_end;
	dma_addr_t dma_base, dma_end, geometry_start, geometry_end;
	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
	struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
	dma_addr_t hw_base = 0;
	dma_addr_t hw_base = 0;
	dma_addr_t hw_end = (1UL << ias) - 1;
	dma_addr_t hw_end = (1UL << ias) - 1;
	bool is_fast = test_bit(DOMAIN_ATTR_FAST, smmu_domain->attributes);
	bool is_fast = test_bit(DOMAIN_ATTR_FAST, smmu_domain->attributes);
	int ret;


	if (is_fast) {
	if (!is_fast) {
		iova_base = hw_base;
		iova_end = hw_end;
		goto end;
	}

	ret = arm_smmu_get_domain_dma_range(dev, domain, hw_base, hw_end,
					    &dma_base, &dma_end);
	if (ret)
		return ret;

	ret = get_range_prop(dev, "qcom,iommu-geometry", &geometry_start,
			     &geometry_end);
	if (!ret) {
		if (geometry_start >= SZ_1G * 4ULL ||
		    geometry_end >= SZ_1G * 4ULL) {
			pr_err("fastmap geometry does not support IOVAs >= 4GB\n");
			return -EINVAL;
		}

		if (geometry_start < dma_base)
			iova_base = geometry_start;
		else
			iova_base = dma_base;

		if (geometry_end > dma_end)
			iova_end = geometry_end;
		else
			iova_end = dma_end;
	} else if (ret == -ENOENT) {
		iova_base = 0;
		iova_base = 0;
		iova_end = SZ_4G - 1;
		iova_end = SZ_4G - 1;
	} else {
	} else {
		iova_base = hw_base;
		return ret;
		iova_end = hw_end;
	}
	}


	if (!((hw_base <= iova_base) && (iova_end <= hw_end)))
	if (!((hw_base <= iova_base) && (iova_end <= hw_end)))
		return -EINVAL;
		return -EINVAL;


end:
	*ret_base = iova_base;
	*ret_base = iova_base;
	*ret_end = iova_end;
	*ret_end = iova_end;

	return 0;
	return 0;
}
}


@@ -2131,8 +2161,10 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,
	ret = arm_smmu_get_domain_iova_range(dev, domain, ias,
	ret = arm_smmu_get_domain_iova_range(dev, domain, ias,
					     &ttbr0_pgtbl_info->iova_base,
					     &ttbr0_pgtbl_info->iova_base,
					     &ttbr0_pgtbl_info->iova_end);
					     &ttbr0_pgtbl_info->iova_end);
	if (ret)
	if (ret) {
		dev_err(dev, "Failed to get domain IOVA range\n");
		goto out_clear_smmu;
		goto out_clear_smmu;
	}


	ttbr0_pgtbl_info->pgtbl_cfg = (struct io_pgtable_cfg) {
	ttbr0_pgtbl_info->pgtbl_cfg = (struct io_pgtable_cfg) {
		.quirks		= quirks,
		.quirks		= quirks,
+1 −1

File changed.

Contains only whitespace changes.