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

Commit ddeaeaf8 authored by Sudarshan Rajagopalan's avatar Sudarshan Rajagopalan
Browse files

arm64: Allow clients to use bitmap iova allocator



With the dma_map_ops defaulted to upstream ops, allow iommu
clients to revert back to previous functioning bitmap iova
allocator just in case, if the upstream dma ops starts to behave
improperly.

Change-Id: I21d1b4a882f0d6905b008e419b5d3a3e6446a4f2
Signed-off-by: default avatarSudarshan Rajagopalan <sudaraja@codeaurora.org>
parent d2833a2d
Loading
Loading
Loading
Loading
+31 −7
Original line number Diff line number Diff line
@@ -1930,11 +1930,34 @@ iommu_init_mapping(struct device *dev, struct dma_iommu_mapping *mapping)
	return -EINVAL;
}

static int
bitmap_iommu_init_mapping(struct device *dev, struct dma_iommu_mapping *mapping)
{
	unsigned int bitmap_size = BITS_TO_LONGS(mapping->bits) * sizeof(long);

	mapping->bitmap = kzalloc(bitmap_size, GFP_KERNEL | __GFP_NOWARN |
				__GFP_NORETRY);
	if (!mapping->bitmap)
		mapping->bitmap = vzalloc(bitmap_size);

	if (!mapping->bitmap)
		return -ENOMEM;

	spin_lock_init(&mapping->lock);
	mapping->ops = &iommu_ops;
	return 0;
}

static void release_iommu_mapping(struct kref *kref)
{
	int is_bitmap = 0;
	struct dma_iommu_mapping *mapping =
		container_of(kref, struct dma_iommu_mapping, kref);

	iommu_domain_get_attr(mapping->domain,
				DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR, &is_bitmap);
	if (is_bitmap)
		kfree(mapping->bitmap);
	iommu_domain_free(mapping->domain);
	kfree(mapping);
}
@@ -1948,7 +1971,7 @@ static void release_iommu_mapping(struct kref *kref)
 */
void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
{
	int s1_bypass = 0, is_fast = 0;
	int is_fast = 0;
	void (*release)(struct kref *kref);

	if (!mapping)
@@ -1960,8 +1983,6 @@ void arm_iommu_release_mapping(struct dma_iommu_mapping *mapping)
		return;
	}

	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS,
					&s1_bypass);
	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);

	if (is_fast)
@@ -1977,7 +1998,7 @@ static int arm_iommu_init_mapping(struct device *dev,
			    struct dma_iommu_mapping *mapping)
{
	int err = -EINVAL;
	int s1_bypass = 0, is_fast = 0;
	int s1_bypass = 0, is_fast = 0, is_bitmap = 0;
	dma_addr_t iova_end;

	if (mapping->init) {
@@ -1995,15 +2016,18 @@ static int arm_iommu_init_mapping(struct device *dev,
	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_S1_BYPASS,
					&s1_bypass);
	iommu_domain_get_attr(mapping->domain, DOMAIN_ATTR_FAST, &is_fast);
	iommu_domain_get_attr(mapping->domain,
			DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR, &is_bitmap);

	if (s1_bypass) {
		mapping->ops = &swiotlb_dma_ops;
		err = 0;
	} else if (is_fast) {
	} else if (is_fast)
		err = fast_smmu_init_mapping(dev, mapping);
	} else {
	else if (is_bitmap)
		err = bitmap_iommu_init_mapping(dev, mapping);
	else
		err = iommu_init_mapping(dev, mapping);
	}
	if (!err) {
		kref_init(&mapping->kref);
		mapping->init = true;
+11 −0
Original line number Diff line number Diff line
@@ -2739,6 +2739,11 @@ static int arm_smmu_domain_get_attr(struct iommu_domain *domain,
				    & (1 << DOMAIN_ATTR_EARLY_MAP));
		ret = 0;
		break;
	case DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR:
		*((int *)data) = !!(smmu_domain->attributes
				& (1 << DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR));
		ret = 0;
		break;
	case DOMAIN_ATTR_PAGE_TABLE_IS_COHERENT:
		if (!smmu_domain->smmu) {
			ret = -ENODEV;
@@ -2925,6 +2930,12 @@ static int arm_smmu_domain_set_attr(struct iommu_domain *domain,
		}
		break;
	}
	case DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR:
		if (*((int *)data))
			smmu_domain->attributes |=
				1 << DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR;
		ret = 0;
		break;
	case DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT: {
		int force_coherent = *((int *)data);

+1 −0
Original line number Diff line number Diff line
@@ -152,6 +152,7 @@ enum iommu_attr {
	DOMAIN_ATTR_PAGE_TABLE_IS_COHERENT,
	DOMAIN_ATTR_PAGE_TABLE_FORCE_COHERENT,
	DOMAIN_ATTR_CB_STALL_DISABLE,
	DOMAIN_ATTR_BITMAP_IOVA_ALLOCATOR,
	DOMAIN_ATTR_MAX,
};