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

Commit 2281bbc5 authored by Patrick Daly's avatar Patrick Daly Committed by Liam Mark
Browse files

iommu/iova: Support disabling domain iova alignment



Currently the IOVA framework automatically applies IOVA alignment to
provided IOVAs based on the requested IOVA size and the alignment configs
which are enabled.

Some clients who don't require any IOVA alignment would benefit from the
reduced fragmentation that would result from disabling IOVA alignment.

Add support to allow clients to disable IOVA alignment on an IOMMU domain.

Change-Id: Ifa6a75576e7a084c443abf38726d790b883f00b3
Signed-off-by: default avatarPatrick Daly <pdaly@codeaurora.org>
[lmark@codeaurora.org: cleanup change]
Signed-off-by: default avatarLiam Mark <lmark@codeaurora.org>
parent ed0190d5
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -35,6 +35,22 @@ config IOMMU_IOVA_ALIGNMENT
	  The order is expressed a power of two multiplied by the PAGE_SIZE.

	  If unsure, leave the default value "9".

config DMA_CONFIGURE_ALIGNMENT
        bool "Configure IOVA alignment"
        help
	  Currently the IOVA framework automatically applies IOVA
	  alignment to provided IOVAs based on the requested IOVA size and
	  the alignment configs which are enabled.

	  Some clients who don't require any IOVA alignment would
	  benefit from the reduced fragmentation that would result from
	  disabling IOVA alignment.

	  Enable this option to allow clients to disable IOVA alignment on
	  an IOMMU domain.

	  If unsure, say N.
endif

menuconfig IOMMU_SUPPORT
+21 −0
Original line number Diff line number Diff line
@@ -400,6 +400,27 @@ int iommu_dma_enable_best_fit_algo(struct device *dev)
}
EXPORT_SYMBOL(iommu_dma_enable_best_fit_algo);

#ifdef CONFIG_DMA_CONFIGURE_ALIGNMENT
/*
 * Should be called prior to using dma-apis.
 */
int iommu_dma_configure_alignment(struct device *dev, bool force_no_align)
{
	struct iommu_domain *domain;
	struct iova_domain *iovad;

	domain = iommu_get_domain_for_dev(dev);
	if (!domain || !domain->iova_cookie)
		return -EINVAL;

	iovad = &((struct iommu_dma_cookie *)domain->iova_cookie)->iovad;

	iovad->force_no_align = force_no_align;
	return 0;
}
EXPORT_SYMBOL(iommu_dma_configure_alignment);
#endif

/**
 * dma_info_to_prot - Translate DMA API directions and attributes to IOMMU API
 *                    page flags.
+8 −0
Original line number Diff line number Diff line
@@ -51,6 +51,9 @@ init_iova_domain(struct iova_domain *iovad, unsigned long granule,
	rb_link_node(&iovad->anchor.node, NULL, &iovad->rbroot.rb_node);
	rb_insert_color(&iovad->anchor.node, &iovad->rbroot);
	iovad->best_fit = false;
#ifdef CONFIG_DMA_CONFIGURE_ALIGNMENT
	iovad->force_no_align = false;
#endif
	init_iova_rcaches(iovad);
}
EXPORT_SYMBOL_GPL(init_iova_domain);
@@ -385,6 +388,11 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
	if (!new_iova)
		return NULL;

#ifdef CONFIG_DMA_CONFIGURE_ALIGNMENT
	if (iovad->force_no_align)
		size_aligned = false;
#endif

	if (iovad->best_fit) {
		ret = __alloc_and_insert_iova_best_fit(iovad, size,
				limit_pfn + 1, new_iova, size_aligned);
+16 −0
Original line number Diff line number Diff line
@@ -58,6 +58,16 @@ int iommu_dma_reserve_iova(struct device *dev, dma_addr_t base,

int iommu_dma_enable_best_fit_algo(struct device *dev);

#ifdef CONFIG_DMA_CONFIGURE_ALIGNMENT
int iommu_dma_configure_alignment(struct device *dev, bool force_no_align);
#else /* CONFIG_DMA_CONFIGURE_ALIGNMENT */
static inline int iommu_dma_configure_alignment(struct device *dev,
						bool force_no_align)
{
	return -ENOTSUPP;
}
#endif

#else /* CONFIG_IOMMU_DMA */

struct iommu_domain;
@@ -110,5 +120,11 @@ static inline int iommu_dma_enable_best_fit_algo(struct device *dev)
	return -ENODEV;
}

static inline int iommu_dma_configure_alignment(struct device *dev,
						bool force_no_align)
{
	return -ENODEV;
}

#endif	/* CONFIG_IOMMU_DMA */
#endif	/* __DMA_IOMMU_H */
+3 −0
Original line number Diff line number Diff line
@@ -96,6 +96,9 @@ struct iova_domain {
	atomic_t fq_timer_on;			/* 1 when timer is active, 0
						   when not */
	bool best_fit;
#ifdef CONFIG_DMA_CONFIGURE_ALIGNMENT
	bool force_no_align;
#endif
};

static inline unsigned long iova_size(struct iova *iova)