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: Patrick Daly <pdaly@codeaurora.org>
[lmark@codeaurora.org: cleanup change]
Signed-off-by: Liam Mark <lmark@codeaurora.org>
This commit is contained in:
Patrick Daly 2019-12-05 15:38:46 -08:00 • committed by Liam Mark
commit 2281bbc545
5 changed files with 64 additions and 0 deletions

View file

@ -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

View file

@ -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.

View file

@ -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);

View file

@ -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 */

View file

@ -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)