mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
iommu: Allow passing custom allocators to pgtable drivers
This will be useful for GPU drivers who want to keep page tables in a pool so they can: - keep freed page tables in a free pool and speed-up upcoming page table allocations - batch page table allocation instead of allocating one page at a time - pre-reserve pages for page tables needed for map/unmap operations, to ensure map/unmap operations don't try to allocate memory in paths they're allowed to block or fail It might also be valuable for other aspects of GPU and similar use-cases, like fine-grained memory accounting and resource limiting. We will extend the Arm LPAE format to support custom allocators in a separate commit. Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com> Reviewed-by: Steven Price <steven.price@arm.com> Reviewed-by: Robin Murphy <robin.murphy@arm.com> Link: https://lore.kernel.org/r/20231124142434.1577550-2-boris.brezillon@collabora.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
e7080665c9
commit
17b226dcf8
|
@ -34,6 +34,26 @@ io_pgtable_init_table[IO_PGTABLE_NUM_FMTS] = {
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int check_custom_allocator(enum io_pgtable_fmt fmt,
|
||||||
|
struct io_pgtable_cfg *cfg)
|
||||||
|
{
|
||||||
|
/* No custom allocator, no need to check the format. */
|
||||||
|
if (!cfg->alloc && !cfg->free)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* When passing a custom allocator, both the alloc and free
|
||||||
|
* functions should be provided.
|
||||||
|
*/
|
||||||
|
if (!cfg->alloc || !cfg->free)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
/* Make sure the format supports custom allocators. */
|
||||||
|
if (io_pgtable_init_table[fmt]->caps & IO_PGTABLE_CAP_CUSTOM_ALLOCATOR)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
|
struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
|
||||||
struct io_pgtable_cfg *cfg,
|
struct io_pgtable_cfg *cfg,
|
||||||
void *cookie)
|
void *cookie)
|
||||||
|
@ -44,6 +64,9 @@ struct io_pgtable_ops *alloc_io_pgtable_ops(enum io_pgtable_fmt fmt,
|
||||||
if (fmt >= IO_PGTABLE_NUM_FMTS)
|
if (fmt >= IO_PGTABLE_NUM_FMTS)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
if (check_custom_allocator(fmt, cfg))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
fns = io_pgtable_init_table[fmt];
|
fns = io_pgtable_init_table[fmt];
|
||||||
if (!fns)
|
if (!fns)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -100,6 +100,30 @@ struct io_pgtable_cfg {
|
||||||
const struct iommu_flush_ops *tlb;
|
const struct iommu_flush_ops *tlb;
|
||||||
struct device *iommu_dev;
|
struct device *iommu_dev;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @alloc: Custom page allocator.
|
||||||
|
*
|
||||||
|
* Optional hook used to allocate page tables. If this function is NULL,
|
||||||
|
* @free must be NULL too.
|
||||||
|
*
|
||||||
|
* Memory returned should be zeroed and suitable for dma_map_single() and
|
||||||
|
* virt_to_phys().
|
||||||
|
*
|
||||||
|
* Not all formats support custom page allocators. Before considering
|
||||||
|
* passing a non-NULL value, make sure the chosen page format supports
|
||||||
|
* this feature.
|
||||||
|
*/
|
||||||
|
void *(*alloc)(void *cookie, size_t size, gfp_t gfp);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @free: Custom page de-allocator.
|
||||||
|
*
|
||||||
|
* Optional hook used to free page tables allocated with the @alloc
|
||||||
|
* hook. Must be non-NULL if @alloc is not NULL, must be NULL
|
||||||
|
* otherwise.
|
||||||
|
*/
|
||||||
|
void (*free)(void *cookie, void *pages, size_t size);
|
||||||
|
|
||||||
/* Low-level data specific to the table format */
|
/* Low-level data specific to the table format */
|
||||||
union {
|
union {
|
||||||
struct {
|
struct {
|
||||||
|
@ -241,16 +265,26 @@ io_pgtable_tlb_add_page(struct io_pgtable *iop,
|
||||||
iop->cfg.tlb->tlb_add_page(gather, iova, granule, iop->cookie);
|
iop->cfg.tlb->tlb_add_page(gather, iova, granule, iop->cookie);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enum io_pgtable_caps - IO page table backend capabilities.
|
||||||
|
*/
|
||||||
|
enum io_pgtable_caps {
|
||||||
|
/** @IO_PGTABLE_CAP_CUSTOM_ALLOCATOR: Backend accepts custom page table allocators. */
|
||||||
|
IO_PGTABLE_CAP_CUSTOM_ALLOCATOR = BIT(0),
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* struct io_pgtable_init_fns - Alloc/free a set of page tables for a
|
* struct io_pgtable_init_fns - Alloc/free a set of page tables for a
|
||||||
* particular format.
|
* particular format.
|
||||||
*
|
*
|
||||||
* @alloc: Allocate a set of page tables described by cfg.
|
* @alloc: Allocate a set of page tables described by cfg.
|
||||||
* @free: Free the page tables associated with iop.
|
* @free: Free the page tables associated with iop.
|
||||||
|
* @caps: Combination of @io_pgtable_caps flags encoding the backend capabilities.
|
||||||
*/
|
*/
|
||||||
struct io_pgtable_init_fns {
|
struct io_pgtable_init_fns {
|
||||||
struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie);
|
struct io_pgtable *(*alloc)(struct io_pgtable_cfg *cfg, void *cookie);
|
||||||
void (*free)(struct io_pgtable *iop);
|
void (*free)(struct io_pgtable *iop);
|
||||||
|
u32 caps;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns;
|
extern struct io_pgtable_init_fns io_pgtable_arm_32_lpae_s1_init_fns;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user