ANDROID: iommu: Add vendor hook to alloc_iova()

Add a vendor hook that allows overriding the default alloc_iova()
algorithm.

The vendor hook can use the iovad->android_vendor_data1 field, initialized
in the previous patch, to determine whether to use the best-fit algorithm
to allocate iova for this device. If an IOVA was successfully allocated,
the vendor hook returns 0. Otherwise it returns non-zero and we fallback
to the default, first-fit algorithm.

On some 32-bit devices, using a best-fit algorithm reduces chances of the
allocation failure due to fragmentation.

We submitted patches (listed in Links below) with two different approaches
to the community but they were not accepted in part, because we are not
able to reproduce the problem with upstream-only code.

Links:
[1] Use a DT property:
https://lore.kernel.org/lkml/20221213163506.GA2011062-robh@kernel.org/
[2] Add an API function to be called by user drivers:
https://lore.kernel.org/lkml/20200217080339.GC10342@infradead.org/

Bug: 263499813
Bug: 190519428
Bug: 149544392
Change-Id: I8e948a08e79089d3fb7356eeb7f85b58784688f2
Signed-off-by: Sukadev Bhattiprolu <quic_sukadev@quicinc.com>
This commit is contained in:
Sukadev Bhattiprolu
2022-12-22 14:00:46 -08:00
committed by Isaac Manjarres
parent 72b891ab7f
commit 7e3069667d
3 changed files with 17 additions and 3 deletions

View File

@@ -85,6 +85,7 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_send_tm_command);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_ufs_check_int_errors);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_cgroup_attach);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_iommu_setup_dma_ops);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_iommu_alloc_insert_iova);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_iommu_iovad_alloc_iova);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_vh_iommu_iovad_free_iova);
EXPORT_TRACEPOINT_SYMBOL_GPL(android_rvh_iommu_iovad_init_alloc_algo);

View File

@@ -11,6 +11,7 @@
#include <linux/smp.h>
#include <linux/bitops.h>
#include <linux/cpu.h>
#include <trace/hooks/iommu.h>
/* The anchor node sits above the top of the usable address space */
#define IOVA_ANCHOR ~0UL
@@ -317,14 +318,18 @@ alloc_iova(struct iova_domain *iovad, unsigned long size,
bool size_aligned)
{
struct iova *new_iova;
int ret;
int ret = -1;
new_iova = alloc_iova_mem();
if (!new_iova)
return NULL;
ret = __alloc_and_insert_iova_range(iovad, size, limit_pfn + 1,
new_iova, size_aligned);
trace_android_rvh_iommu_alloc_insert_iova(iovad, size, limit_pfn + 1,
new_iova, size_aligned, &ret);
if (ret) {
ret = __alloc_and_insert_iova_range(iovad, size,
limit_pfn + 1, new_iova, size_aligned);
}
if (ret) {
free_iova_mem(new_iova);

View File

@@ -14,6 +14,14 @@ DECLARE_RESTRICTED_HOOK(android_rvh_iommu_setup_dma_ops,
TP_ARGS(dev, dma_base, dma_limit), 1);
struct iova_domain;
struct iova;
DECLARE_RESTRICTED_HOOK(android_rvh_iommu_alloc_insert_iova,
TP_PROTO(struct iova_domain *iovad, unsigned long size,
unsigned long limit_pfn, struct iova *new_iova,
bool size_aligned, int *ret),
TP_ARGS(iovad, size, limit_pfn, new_iova, size_aligned, ret),
1);
DECLARE_HOOK(android_vh_iommu_iovad_alloc_iova,
TP_PROTO(struct device *dev, struct iova_domain *iovad, dma_addr_t iova, size_t size),