参照元

説明

引数

返り値

参考

実装

/**
 * iommu_dma_init_domain - Initialise a DMA mapping domain
 * @domain: IOMMU domain previously prepared by iommu_get_dma_cookie()
 * @base: IOVA at which the mappable address space starts
 * @size: Size of IOVA space
 *
 * @base and @size should be exact multiples of IOMMU page granularity to
 * avoid rounding surprises. If necessary, we reserve the page at address 0
 * to ensure it is an invalid IOVA. It is safe to reinitialise a domain, but
 * any change which could make prior IOVAs invalid will fail.
 */
int iommu_dma_init_domain(struct iommu_domain *domain, dma_addr_t base, u64 size)
{
	struct iova_domain *iovad = domain->iova_cookie;
	unsigned long order, base_pfn, end_pfn;
	if (!iovad)
		return -ENODEV;

	/* Use the smallest supported page size for IOVA granularity */
	order = __ffs(domain->ops->pgsize_bitmap);
	base_pfn = max_t(unsigned long, 1, base >> order);
	end_pfn = (base + size - 1) >> order;
	/* Check the domain allows at least some access to the device... */
	if (domain->geometry.force_aperture) {
		if (base > domain->geometry.aperture_end ||
		    base + size <= domain->geometry.aperture_start) {
			pr_warn("specified DMA range outside IOMMU capability\n");
			return -EFAULT;
		}
		/* ...then finally give it a kicking to make sure it fits */
		base_pfn = max_t(unsigned long, base_pfn,
				domain->geometry.aperture_start >> order);
		end_pfn = min_t(unsigned long, end_pfn,
				domain->geometry.aperture_end >> order);
	}
	/* All we can safely do with an existing domain is enlarge it */
	if (iovad->start_pfn) {
		if (1UL << order != iovad->granule ||
		    base_pfn != iovad->start_pfn ||
		    end_pfn < iovad->dma_32bit_pfn) {
			pr_warn("Incompatible range for DMA domain\n");
			return -EFAULT;
		}
		iovad->dma_32bit_pfn = end_pfn;
	} else {
		init_iova_domain(iovad, 1UL << order, base_pfn, end_pfn);
	}
	return 0;
}
EXPORT_SYMBOL(iommu_dma_init_domain);

コメント


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS