Loading drivers/iommu/iommu.c +48 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) Loading Loading
drivers/iommu/iommu.c +48 −0 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -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) Loading