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

Commit beed2821 authored by Joerg Roedel's avatar Joerg Roedel
Browse files

iommu: Create direct mappings in default domains



Use the information exported by the IOMMU drivers to create
direct mapped regions in the default domains.

Signed-off-by: default avatarJoerg Roedel <jroedel@suse.de>
parent a1015c2b
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -325,6 +325,52 @@ int iommu_group_set_name(struct iommu_group *group, const char *name)
}
EXPORT_SYMBOL_GPL(iommu_group_set_name);

static int iommu_group_create_direct_mappings(struct iommu_group *group,
					      struct device *dev)
{
	struct iommu_domain *domain = group->default_domain;
	struct iommu_dm_region *entry;
	struct list_head mappings;
	unsigned long pg_size;
	int ret = 0;

	if (!domain || domain->type != IOMMU_DOMAIN_DMA)
		return 0;

	BUG_ON(!domain->ops->pgsize_bitmap);

	pg_size = 1UL << __ffs(domain->ops->pgsize_bitmap);
	INIT_LIST_HEAD(&mappings);

	iommu_get_dm_regions(dev, &mappings);

	/* We need to consider overlapping regions for different devices */
	list_for_each_entry(entry, &mappings, list) {
		dma_addr_t start, end, addr;

		start = ALIGN(entry->start, pg_size);
		end   = ALIGN(entry->start + entry->length, pg_size);

		for (addr = start; addr < end; addr += pg_size) {
			phys_addr_t phys_addr;

			phys_addr = iommu_iova_to_phys(domain, addr);
			if (phys_addr)
				continue;

			ret = iommu_map(domain, addr, addr, pg_size, entry->prot);
			if (ret)
				goto out;
		}

	}

out:
	iommu_put_dm_regions(dev, &mappings);

	return ret;
}

/**
 * iommu_group_add_device - add a device to an iommu group
 * @group: the group into which to add the device (reference should be held)
@@ -381,6 +427,8 @@ int iommu_group_add_device(struct iommu_group *group, struct device *dev)

	dev->iommu_group = group;

	iommu_group_create_direct_mappings(group, dev);

	mutex_lock(&group->mutex);
	list_add_tail(&device->list, &group->devices);
	if (group->domain)