[PATCH 09/15] lib: provide stub Linux "generic" allocator API
Sascha Hauer
sha at pengutronix.de
Thu Jan 12 05:26:08 PST 2023
On Wed, Jan 11, 2023 at 06:40:17PM +0100, Ahmad Fatoum wrote:
> We may want to port the whole of the Linux generic allocator
> implementation in future as it would come in handy in drivers that need
> special memory for DMA. For now, support just the use case of the
> incoming Atmel NAND driver, which is mapping the whole of a mmio-sram.
>
> Signed-off-by: Ahmad Fatoum <a.fatoum at pengutronix.de>
> ---
> include/linux/genalloc.h | 36 ++++++++++++
> lib/Kconfig | 5 ++
> lib/Makefile | 1 +
> lib/genalloc.c | 118 +++++++++++++++++++++++++++++++++++++++
> 4 files changed, 160 insertions(+)
> create mode 100644 include/linux/genalloc.h
> create mode 100644 lib/genalloc.c
>
> diff --git a/include/linux/genalloc.h b/include/linux/genalloc.h
> new file mode 100644
> index 000000000000..566e62d1965c
> --- /dev/null
> +++ b/include/linux/genalloc.h
> @@ -0,0 +1,36 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +/*
> + * Basic general purpose allocator for managing special purpose
> + * memory, for example, memory that is not managed by the regular
> + * kmalloc/kfree interface. Uses for this includes on-device special
> + * memory, uncached memory etc.
> + */
> +
> +
> +#ifndef __GENALLOC_H__
> +#define __GENALLOC_H__
> +
> +#include <linux/types.h>
> +
> +struct device_node;
> +
> +struct gen_pool;
> +
> +extern phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long);
> +
> +extern void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size,
> + dma_addr_t *dma);
> +
> +extern void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma);
> +
> +#ifdef CONFIG_OFDEVICE
> +extern struct gen_pool *of_gen_pool_get(struct device_node *np,
> + const char *propname, int index);
> +#else
> +static inline struct gen_pool *of_gen_pool_get(struct device_node *np,
> + const char *propname, int index)
> +{
> + return NULL;
> +}
> +#endif
> +#endif /* __GENALLOC_H__ */
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 5af7ea33f27b..b8bc9d63d4f0 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -210,4 +210,9 @@ config ARCH_HAS_ZERO_PAGE
> config HAVE_EFFICIENT_UNALIGNED_ACCESS
> bool
>
> +config GENERIC_ALLOCATOR
> + bool
> + help
> + Support is curently limited to allocaing a complete mmio-sram at once.
> +
> endmenu
> diff --git a/lib/Makefile b/lib/Makefile
> index 4717b8aec364..38478625423b 100644
> --- a/lib/Makefile
> +++ b/lib/Makefile
> @@ -75,6 +75,7 @@ obj-$(CONFIG_CRC8) += crc8.o
> obj-$(CONFIG_NLS) += nls_base.o
> obj-$(CONFIG_FSL_QE_FIRMWARE) += fsl-qe-firmware.o
> obj-$(CONFIG_UBSAN) += ubsan.o
> +obj-$(CONFIG_GENERIC_ALLOCATOR) += genalloc.o
>
> # GCC library routines
> obj-$(CONFIG_GENERIC_LIB_ASHLDI3) += ashldi3.o
> diff --git a/lib/genalloc.c b/lib/genalloc.c
> new file mode 100644
> index 000000000000..906e2dd5f14b
> --- /dev/null
> +++ b/lib/genalloc.c
> @@ -0,0 +1,118 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +// SPDX-FileCopyrightText: 2005 Jes Sorensen <jes at trained-monkey.org>
> +/*
> + * Basic general purpose allocator for managing special purpose
> + * memory, for example, memory that is not managed by the regular
> + * kmalloc/kfree interface. Uses for this includes on-device special
> + * memory, uncached memory etc.
> + */
> +
> +#include <io.h>
> +#include <linux/ioport.h>
> +#include <linux/genalloc.h>
> +#include <linux/export.h>
> +#include <of.h>
> +#include <driver.h>
> +#include <linux/string.h>
> +
> +struct gen_pool {
> + struct resource res;
> +};
> +
> +#define res_to_gen_pool(res) \
> + container_of(res, struct gen_pool, res)
> +
> +/**
> + * gen_pool_virt_to_phys - return the physical address of memory
> + * @pool: pool to allocate from
> + * @addr: starting address of memory
> + *
> + * Returns the physical address on success, or -1 on error.
> + */
> +phys_addr_t gen_pool_virt_to_phys(struct gen_pool *pool, unsigned long addr)
> +{
> + return virt_to_phys((void *)addr);
> +}
> +EXPORT_SYMBOL(gen_pool_virt_to_phys);
> +
> +/**
> + * gen_pool_dma_alloc - allocate special memory from the pool for DMA usage
> + * @pool: pool to allocate from
> + * @size: number of bytes to allocate from the pool
> + * @dma: dma-view physical address return value. Use %NULL if unneeded.
> + *
> + * Allocate the requested number of bytes from the specified pool.
> + * Uses the pool allocation function (with first-fit algorithm by default).
> + * Can not be used in NMI handler on architectures without
> + * NMI-safe cmpxchg implementation.
> + *
> + * Return: virtual address of the allocated memory, or %NULL on failure
> + */
Maybe add a comment here that we currently only support allocating the
whole area?
Can be done as followup later.
Sascha
> +void *gen_pool_dma_alloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
> +{
> + unsigned long vaddr;
> +
> + if (!pool || resource_size(&pool->res) != size)
> + return NULL;
> +
> + vaddr = pool->res.start;
> +
> + if (dma)
> + *dma = gen_pool_virt_to_phys(pool, vaddr);
> +
> + return (void *)vaddr;
> +}
> +EXPORT_SYMBOL(gen_pool_dma_alloc);
> +
> +/**
> + * gen_pool_dma_zalloc - allocate special zeroed memory from the pool for
> + * DMA usage
> + * @pool: pool to allocate from
> + * @size: number of bytes to allocate from the pool
> + * @dma: dma-view physical address return value. Use %NULL if unneeded.
> + *
> + * Return: virtual address of the allocated zeroed memory, or %NULL on failure
> + */
> +void *gen_pool_dma_zalloc(struct gen_pool *pool, size_t size, dma_addr_t *dma)
> +{
> + void *vaddr = gen_pool_dma_alloc(pool, size, dma);
> +
> + if (vaddr)
> + memset(vaddr, 0, size);
> +
> + return vaddr;
> +}
> +EXPORT_SYMBOL(gen_pool_dma_zalloc);
> +
> +#ifdef CONFIG_OFDEVICE
> +/**
> + * of_gen_pool_get - find a pool by phandle property
> + * @np: device node
> + * @propname: property name containing phandle(s)
> + * @index: index into the phandle array
> + *
> + * Returns the pool that contains the chunk starting at the physical
> + * address of the device tree node pointed at by the phandle property,
> + * or NULL if not found.
> + */
> +struct gen_pool *of_gen_pool_get(struct device_node *np,
> + const char *propname, int index)
> +{
> + struct device *dev;
> + struct device_node *np_pool;
> +
> + np_pool = of_parse_phandle(np, propname, index);
> + if (!np_pool)
> + return NULL;
> +
> + if (!of_device_is_compatible(np_pool, "mmio-sram"))
> + return NULL;
> +
> + dev = of_find_device_by_node(np_pool);
> + if (!dev)
> + return NULL;
> +
> + return container_of(&dev->resource[0], struct gen_pool, res);
> +}
> +EXPORT_SYMBOL_GPL(of_gen_pool_get);
> +#endif /* CONFIG_OF */
> --
> 2.30.2
>
>
>
--
Pengutronix e.K. | |
Steuerwalder Str. 21 | http://www.pengutronix.de/ |
31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
More information about the barebox
mailing list