diff mbox series

[v4,2/7] lmb: replace the lmb_alloc() and lmb_alloc_base() API's

Message ID 20250612065624.751014-3-sughosh.ganu@linaro.org
State New
Headers show
Series lmb: use a single API for all allocations | expand

Commit Message

Sughosh Ganu June 12, 2025, 6:56 a.m. UTC
There currently are two API's for requesting memory from the LMB
module, lmb_alloc() and lmb_alloc_base(). The function which does the
actual allocation is the same. Use the earlier introduced API
lmb_alloc_mem() for both types of allocation requests.

Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>
---
Changes since V3:
* mach-apple: Check the return value of the lmb allocation API, and
  set the env variables only when the API returns success
* mach-snapdragon: Check the return value of the lmb allocation API,
  and set the env variables only when the API returns success

 arch/arm/mach-apple/board.c      | 27 ++++++++++++------
 arch/arm/mach-snapdragon/board.c | 30 ++++++++++++-------
 boot/bootm.c                     | 12 +++++---
 boot/image-board.c               | 49 +++++++++++++++++---------------
 boot/image-fdt.c                 | 35 +++++++++++++----------
 include/lmb.h                    | 22 +++-----------
 lib/efi_loader/efi_memory.c      | 14 +++++----
 lib/lmb.c                        | 28 ++++++++----------
 test/lib/lmb.c                   | 26 +++++++++++++++++
 9 files changed, 141 insertions(+), 102 deletions(-)

Comments

Ilias Apalodimas June 16, 2025, 10:17 a.m. UTC | #1
Thanks Sughosh

This is a nice cleanup, we only have lmb_alloc_mem() now right? (Apart
from the io_xxx versions)


On Thu, 12 Jun 2025 at 09:56, Sughosh Ganu <sughosh.ganu@linaro.org> wrote:
>
> There currently are two API's for requesting memory from the LMB
> module, lmb_alloc() and lmb_alloc_base(). The function which does the
> actual allocation is the same. Use the earlier introduced API
> lmb_alloc_mem() for both types of allocation requests.
>
> Signed-off-by: Sughosh Ganu <sughosh.ganu@linaro.org>

Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>

Cheers
/Ilias
> ---
> Changes since V3:
> * mach-apple: Check the return value of the lmb allocation API, and
>   set the env variables only when the API returns success
> * mach-snapdragon: Check the return value of the lmb allocation API,
>   and set the env variables only when the API returns success
>
>  arch/arm/mach-apple/board.c      | 27 ++++++++++++------
>  arch/arm/mach-snapdragon/board.c | 30 ++++++++++++-------
>  boot/bootm.c                     | 12 +++++---
>  boot/image-board.c               | 49 +++++++++++++++++---------------
>  boot/image-fdt.c                 | 35 +++++++++++++----------
>  include/lmb.h                    | 22 +++-----------
>  lib/efi_loader/efi_memory.c      | 14 +++++----
>  lib/lmb.c                        | 28 ++++++++----------
>  test/lib/lmb.c                   | 26 +++++++++++++++++
>  9 files changed, 141 insertions(+), 102 deletions(-)
>
> diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
> index 2604c5a710e..4cd8979bdc2 100644
> --- a/arch/arm/mach-apple/board.c
> +++ b/arch/arm/mach-apple/board.c
> @@ -773,22 +773,31 @@ u64 get_page_table_size(void)
>
>  #define KERNEL_COMP_SIZE       SZ_128M
>
> +#define lmb_alloc(size, addr) lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
> +
>  int board_late_init(void)
>  {
>         u32 status = 0;
> +       phys_addr_t addr;
>
>         /* somewhat based on the Linux Kernel boot requirements:
>          * align by 2M and maximal FDT size 2M
>          */
> -       status |= env_set_hex("loadaddr", lmb_alloc(SZ_1G, SZ_2M));
> -       status |= env_set_hex("fdt_addr_r", lmb_alloc(SZ_2M, SZ_2M));
> -       status |= env_set_hex("kernel_addr_r", lmb_alloc(SZ_128M, SZ_2M));
> -       status |= env_set_hex("ramdisk_addr_r", lmb_alloc(SZ_1G, SZ_2M));
> -       status |= env_set_hex("kernel_comp_addr_r",
> -                             lmb_alloc(KERNEL_COMP_SIZE, SZ_2M));
> -       status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
> -       status |= env_set_hex("scriptaddr", lmb_alloc(SZ_4M, SZ_2M));
> -       status |= env_set_hex("pxefile_addr_r", lmb_alloc(SZ_4M, SZ_2M));
> +       status |= !lmb_alloc(SZ_1G, &addr) ? env_set_hex("loadaddr", addr) : 1;
> +       status |= !lmb_alloc(SZ_2M, &addr) ?
> +               env_set_hex("fdt_addr_r", addr) : 1;
> +       status |= !lmb_alloc(SZ_128M, &addr) ?
> +               env_set_hex("kernel_addr_r", addr) : 1;
> +       status |= !lmb_alloc(SZ_1G, &addr) ?
> +               env_set_hex("ramdisk_addr_r", addr) : 1;
> +       status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
> +               env_set_hex("kernel_comp_addr_r", addr) : 1;
> +       status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
> +               env_set_hex("kernel_comp_size", addr) : 1;
> +       status |= !lmb_alloc(SZ_4M, &addr) ?
> +               env_set_hex("scriptaddr", addr) : 1;
> +       status |= !lmb_alloc(SZ_4M, &addr) ?
> +               env_set_hex("pxefile_addr_r", addr) : 1;
>
>         if (status)
>                 log_warning("late_init: Failed to set run time variables\n");
> diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
> index 5547d6d054f..87a173e0acb 100644
> --- a/arch/arm/mach-snapdragon/board.c
> +++ b/arch/arm/mach-snapdragon/board.c
> @@ -492,7 +492,7 @@ void __weak qcom_late_init(void)
>  #define FASTBOOT_BUF_SIZE 0
>  #endif
>
> -#define addr_alloc(size) lmb_alloc(size, SZ_2M)
> +#define lmb_alloc(size, addr) lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
>
>  /* Stolen from arch/arm/mach-apple/board.c */
>  int board_late_init(void)
> @@ -502,18 +502,26 @@ int board_late_init(void)
>         struct fdt_header *fdt_blob = (struct fdt_header *)gd->fdt_blob;
>
>         /* We need to be fairly conservative here as we support boards with just 1G of TOTAL RAM */
> -       addr = addr_alloc(SZ_128M);
> +       status |= !lmb_alloc(SZ_128M, &addr) ?
> +               env_set_hex("loadaddr", addr) : 1;
>         status |= env_set_hex("kernel_addr_r", addr);
> -       status |= env_set_hex("loadaddr", addr);
> -       status |= env_set_hex("ramdisk_addr_r", addr_alloc(SZ_128M));
> -       status |= env_set_hex("kernel_comp_addr_r", addr_alloc(KERNEL_COMP_SIZE));
> -       status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
> +       status |= !lmb_alloc(SZ_128M, &addr) ?
> +               env_set_hex("ramdisk_addr_r", addr) : 1;
> +       status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
> +               env_set_hex("kernel_comp_addr_r", addr) : 1;
> +       status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
> +               env_set_hex("kernel_comp_size", addr) : 1;
> +       status |= !lmb_alloc(SZ_4M, &addr) ?
> +               env_set_hex("scriptaddr", addr) : 1;
> +       status |= !lmb_alloc(SZ_4M, &addr) ?
> +               env_set_hex("pxefile_addr_r", addr) : 1;
> +
>         if (IS_ENABLED(CONFIG_FASTBOOT))
> -               status |= env_set_hex("fastboot_addr_r", addr_alloc(FASTBOOT_BUF_SIZE));
> -       status |= env_set_hex("scriptaddr", addr_alloc(SZ_4M));
> -       status |= env_set_hex("pxefile_addr_r", addr_alloc(SZ_4M));
> -       addr = addr_alloc(SZ_2M);
> -       status |= env_set_hex("fdt_addr_r", addr);
> +               status |= !lmb_alloc(FASTBOOT_BUF_SIZE, &addr) ?
> +                       env_set_hex("fastboot_addr_r", addr) : 1;
> +
> +       status |= !lmb_alloc(SZ_2M, &addr) ?
> +               env_set_hex("fdt_addr_r", addr) : 1;
>
>         if (status)
>                 log_warning("%s: Failed to set run time variables\n", __func__);
> diff --git a/boot/bootm.c b/boot/bootm.c
> index 3282bfc0b4b..4bdca22ea8c 100644
> --- a/boot/bootm.c
> +++ b/boot/bootm.c
> @@ -623,12 +623,16 @@ static int bootm_load_os(struct bootm_headers *images, int boot_progress)
>          */
>         if (os.type == IH_TYPE_KERNEL_NOLOAD && os.comp != IH_COMP_NONE) {
>                 ulong req_size = ALIGN(image_len * 4, SZ_1M);
> +               phys_addr_t addr;
>
> -               load = lmb_alloc(req_size, SZ_2M);
> -               if (!load)
> +               err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, &addr,
> +                                   req_size, LMB_NONE);
> +               if (err)
>                         return 1;
> -               os.load = load;
> -               images->ep = load;
> +
> +               load = (ulong)addr;
> +               os.load = (ulong)addr;
> +               images->ep = (ulong)addr;
>                 debug("Allocated %lx bytes at %lx for kernel (size %lx) decompression\n",
>                       req_size, load, image_len);
>         }
> diff --git a/boot/image-board.c b/boot/image-board.c
> index b0fa028ceac..005d60caf5c 100644
> --- a/boot/image-board.c
> +++ b/boot/image-board.c
> @@ -16,6 +16,7 @@
>  #include <fpga.h>
>  #include <image.h>
>  #include <init.h>
> +#include <lmb.h>
>  #include <log.h>
>  #include <mapmem.h>
>  #include <rtc.h>
> @@ -566,27 +567,24 @@ int boot_ramdisk_high(ulong rd_data, ulong rd_len, ulong *initrd_start,
>                         *initrd_start = rd_data;
>                         *initrd_end = rd_data + rd_len;
>                         initrd_addr = (phys_addr_t)rd_data;
> -                       err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0,
> -                                           &initrd_addr, rd_len, LMB_NONE);
> +                       err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &initrd_addr,
> +                                           rd_len, LMB_NONE);
>                         if (err) {
>                                 puts("in-place initrd alloc failed\n");
>                                 goto error;
>                         }
>                 } else {
> -                       if (initrd_high)
> -                               *initrd_start =
> -                                       (ulong)lmb_alloc_base(rd_len,
> -                                                                   0x1000,
> -                                                                   initrd_high,
> -                                                                   LMB_NONE);
> -                       else
> -                               *initrd_start = (ulong)lmb_alloc(rd_len,
> -                                                                0x1000);
> +                       enum lmb_mem_type type = initrd_high ?
> +                               LMB_MEM_ALLOC_MAX : LMB_MEM_ALLOC_ANY;
>
> -                       if (*initrd_start == 0) {
> +                       err = lmb_alloc_mem(type, 0x1000, &initrd_high, rd_len,
> +                                           LMB_NONE);
> +                       if (err) {
>                                 puts("ramdisk - allocation error\n");
>                                 goto error;
>                         }
> +
> +                       *initrd_start = (ulong)initrd_high;
>                         bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);
>
>                         *initrd_end = *initrd_start + rd_len;
> @@ -837,9 +835,10 @@ int boot_get_loadable(struct bootm_headers *images)
>   */
>  int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
>  {
> -       int barg;
> +       int barg, err;
>         char *cmdline;
>         char *s;
> +       phys_addr_t addr;
>
>         /*
>          * Help the compiler detect that this function is only called when
> @@ -849,12 +848,14 @@ int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
>                 return 0;
>
>         barg = IF_ENABLED_INT(CONFIG_SYS_BOOT_GET_CMDLINE, CONFIG_SYS_BARGSIZE);
> -       cmdline = (char *)(ulong)lmb_alloc_base(barg, 0xf,
> -                               env_get_bootm_mapsize() + env_get_bootm_low(),
> -                               LMB_NONE);
> -       if (!cmdline)
> +       addr = env_get_bootm_mapsize() + env_get_bootm_low();
> +
> +       err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0xf, &addr, barg, LMB_NONE);
> +       if (err)
>                 return -1;
>
> +       cmdline = (char *)(uintptr_t)addr;
> +
>         s = env_get("bootargs");
>         if (!s)
>                 s = "";
> @@ -883,14 +884,16 @@ int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
>   */
>  int boot_get_kbd(struct bd_info **kbd)
>  {
> -       *kbd = (struct bd_info *)(ulong)lmb_alloc_base(sizeof(struct bd_info),
> -                                                            0xf,
> -                                                            env_get_bootm_mapsize() +
> -                                                            env_get_bootm_low(),
> -                                                            LMB_NONE);
> -       if (!*kbd)
> +       int err;
> +       phys_addr_t addr;
> +
> +       addr = env_get_bootm_mapsize() + env_get_bootm_low();
> +       err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0xf, &addr,
> +                           sizeof(struct bd_info), LMB_NONE);
> +       if (err)
>                 return -1;
>
> +       *kbd = (struct bd_info *)(uintptr_t)addr;
>         **kbd = *gd->bd;
>
>         debug("## kernel board info at 0x%08lx\n", (ulong)*kbd);
> diff --git a/boot/image-fdt.c b/boot/image-fdt.c
> index bd5a6231140..2720ce6f6f3 100644
> --- a/boot/image-fdt.c
> +++ b/boot/image-fdt.c
> @@ -183,9 +183,9 @@ int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
>         /* If fdt_high is set use it to select the relocation address */
>         fdt_high = env_get("fdt_high");
>         if (fdt_high) {
> -               ulong desired_addr = hextoul(fdt_high, NULL);
> +               ulong high_addr = hextoul(fdt_high, NULL);
>
> -               if (desired_addr == ~0UL) {
> +               if (high_addr == ~0UL) {
>                         /* All ones means use fdt in place */
>                         of_start = fdt_blob;
>                         addr = map_to_sysmem(fdt_blob);
> @@ -198,16 +198,17 @@ int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
>                         }
>
>                         disable_relocation = 1;
> -               } else if (desired_addr) {
> -                       addr = lmb_alloc_base(of_len, 0x1000, desired_addr,
> -                                             LMB_NONE);
> -                       of_start = map_sysmem(addr, of_len);
> -                       if (of_start == NULL) {
> -                               puts("Failed using fdt_high value for Device Tree");
> +               } else {
> +                       enum lmb_mem_type type = high_addr ?
> +                               LMB_MEM_ALLOC_MAX : LMB_MEM_ALLOC_ANY;
> +
> +                       addr = high_addr;
> +                       err = lmb_alloc_mem(type, 0x1000, &addr, of_len,
> +                                           LMB_NONE);
> +                       if (err) {
> +                               puts("Failed to allocate memory for Device Tree relocation\n");
>                                 goto error;
>                         }
> -               } else {
> -                       addr = lmb_alloc(of_len, 0x1000);
>                         of_start = map_sysmem(addr, of_len);
>                 }
>         } else {
> @@ -229,11 +230,15 @@ int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
>                          * for LMB allocation.
>                          */
>                         usable = min(start + size, low + mapsize);
> -                       addr = lmb_alloc_base(of_len, 0x1000, usable, LMB_NONE);
> -                       of_start = map_sysmem(addr, of_len);
> -                       /* Allocation succeeded, use this block. */
> -                       if (of_start != NULL)
> -                               break;
> +                       addr = usable;
> +                       err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0x1000,
> +                                           &addr, of_len, LMB_NONE);
> +                       if (!err) {
> +                               of_start = map_sysmem(addr, of_len);
> +                               /* Allocation succeeded, use this block. */
> +                               if (of_start)
> +                                       break;
> +                       }
>
>                         /*
>                          * Reduce the mapping size in the next bank
> diff --git a/include/lmb.h b/include/lmb.h
> index 8906b42181f..34dbc25759d 100644
> --- a/include/lmb.h
> +++ b/include/lmb.h
> @@ -34,9 +34,13 @@
>  /**
>   * enum lmb_mem_type - type of memory allocation request
>   * @LMB_MEM_ALLOC_ADDR:        request for a particular region of memory
> + * @LMB_MEM_ALLOC_ANY: allocate any available memory region
> + * @LMB_MEM_ALLOC_MAX: allocate memory below a particular address
>   */
>  enum lmb_mem_type {
>         LMB_MEM_ALLOC_ADDR = 1,
> +       LMB_MEM_ALLOC_ANY,
> +       LMB_MEM_ALLOC_MAX,
>  };
>
>  /**
> @@ -130,26 +134,8 @@ void lmb_add_memory(void);
>
>  long lmb_add(phys_addr_t base, phys_size_t size);
>
> -phys_addr_t lmb_alloc(phys_size_t size, ulong align);
>  phys_size_t lmb_get_free_size(phys_addr_t addr);
>
> -/**
> - * lmb_alloc_base() - Allocate specified memory region with specified
> - *                         attributes
> - * @size: Size of the region requested
> - * @align: Alignment of the memory region requested
> - * @max_addr: Maximum address of the requested region
> - * @flags: Memory region attributes to be set
> - *
> - * Allocate a region of memory with the attributes specified through the
> - * parameter. The max_addr parameter is used to specify the maximum address
> - * below which the requested region should be allocated.
> - *
> - * Return: Base address on success, 0 on error.
> - */
> -phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr,
> -                          uint flags);
> -
>  /**
>   * lmb_is_reserved_flags() - Test if address is in reserved region with flag
>   *                          bits set
> diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
> index 77950a267cc..466f45c98b1 100644
> --- a/lib/efi_loader/efi_memory.c
> +++ b/lib/efi_loader/efi_memory.c
> @@ -454,6 +454,7 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
>                                 enum efi_memory_type memory_type,
>                                 efi_uintn_t pages, uint64_t *memory)
>  {
> +       int err;
>         u64 efi_addr, len;
>         uint flags;
>         efi_status_t ret;
> @@ -475,17 +476,18 @@ efi_status_t efi_allocate_pages(enum efi_allocate_type type,
>         switch (type) {
>         case EFI_ALLOCATE_ANY_PAGES:
>                 /* Any page */
> -               addr = (u64)lmb_alloc_base(len, EFI_PAGE_SIZE,
> -                                                LMB_ALLOC_ANYWHERE, flags);
> -               if (!addr)
> +               err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, EFI_PAGE_SIZE, &addr,
> +                                   len, flags);
> +               if (err)
>                         return EFI_OUT_OF_RESOURCES;
>                 break;
>         case EFI_ALLOCATE_MAX_ADDRESS:
>                 /* Max address */
>                 addr = map_to_sysmem((void *)(uintptr_t)*memory);
> -               addr = (u64)lmb_alloc_base(len, EFI_PAGE_SIZE, addr,
> -                                                flags);
> -               if (!addr)
> +
> +               err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, EFI_PAGE_SIZE, &addr,
> +                                   len, flags);
> +               if (err)
>                         return EFI_OUT_OF_RESOURCES;
>                 break;
>         case EFI_ALLOCATE_ADDRESS:
> diff --git a/lib/lmb.c b/lib/lmb.c
> index 72d4edacff0..29603335f66 100644
> --- a/lib/lmb.c
> +++ b/lib/lmb.c
> @@ -672,16 +672,18 @@ long lmb_free(phys_addr_t base, phys_size_t size)
>         return lmb_free_flags(base, size, LMB_NONE);
>  }
>
> -static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
> -                                  phys_addr_t max_addr, u32 flags)
> +static int _lmb_alloc_base(phys_size_t size, ulong align,
> +                          phys_addr_t *addr, u32 flags)
>  {
>         int ret;
>         long i, rgn;
> +       phys_addr_t max_addr;
>         phys_addr_t base = 0;
>         phys_addr_t res_base;
>         struct lmb_region *lmb_used = lmb.used_mem.data;
>         struct lmb_region *lmb_memory = lmb.available_mem.data;
>
> +       max_addr = *addr;
>         for (i = lmb.available_mem.count - 1; i >= 0; i--) {
>                 phys_addr_t lmbbase = lmb_memory[i].base;
>                 phys_size_t lmbsize = lmb_memory[i].size;
> @@ -714,8 +716,8 @@ static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
>                                                             flags);
>                                 if (ret)
>                                         return ret;
> -
> -                               return base;
> +                               *addr = base;
> +                               return 0;
>                         }
>
>                         res_base = lmb_used[rgn].base;
> @@ -728,18 +730,7 @@ static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
>         log_debug("%s: Failed to allocate 0x%lx bytes below 0x%lx\n",
>                   __func__, (ulong)size, (ulong)max_addr);
>
> -       return 0;
> -}
> -
> -phys_addr_t lmb_alloc(phys_size_t size, ulong align)
> -{
> -       return _lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE, LMB_NONE);
> -}
> -
> -phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr,
> -                          uint flags)
> -{
> -       return _lmb_alloc_base(size, align, max_addr, flags);
> +       return -1;
>  }
>
>  static int _lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags)
> @@ -778,6 +769,11 @@ int lmb_alloc_mem(enum lmb_mem_type type, u64 align, phys_addr_t *addr,
>                 return -EINVAL;
>
>         switch (type) {
> +       case LMB_MEM_ALLOC_ANY:
> +               *addr = LMB_ALLOC_ANYWHERE;
> +       case LMB_MEM_ALLOC_MAX:
> +               ret = _lmb_alloc_base(size, align, addr, flags);
> +               break;
>         case LMB_MEM_ALLOC_ADDR:
>                 ret = _lmb_alloc_addr(*addr, size, flags);
>                 break;
> diff --git a/test/lib/lmb.c b/test/lib/lmb.c
> index 751909fc2cf..d8eab96527a 100644
> --- a/test/lib/lmb.c
> +++ b/test/lib/lmb.c
> @@ -82,6 +82,32 @@ static int lmb_reserve(phys_addr_t addr, phys_size_t size, u32 flags)
>         return 0;
>  }
>
> +static phys_addr_t lmb_alloc(phys_size_t size, ulong align)
> +{
> +       int err;
> +       phys_addr_t addr;
> +
> +       err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, align, &addr, size, LMB_NONE);
> +       if (err)
> +               return 0;
> +
> +       return addr;
> +}
> +
> +static phys_addr_t lmb_alloc_base(phys_size_t size, ulong align,
> +                                 phys_addr_t max_addr, u32 flags)
> +{
> +       int err;
> +       phys_addr_t addr;
> +
> +       addr = max_addr;
> +       err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, align, &addr, size, flags);
> +       if (err)
> +               return 0;
> +
> +       return addr;
> +}
> +
>  #define lmb_alloc_addr(addr, size, flags) lmb_reserve(addr, size, flags)
>
>  static int test_multi_alloc(struct unit_test_state *uts, const phys_addr_t ram,
> --
> 2.34.1
>
diff mbox series

Patch

diff --git a/arch/arm/mach-apple/board.c b/arch/arm/mach-apple/board.c
index 2604c5a710e..4cd8979bdc2 100644
--- a/arch/arm/mach-apple/board.c
+++ b/arch/arm/mach-apple/board.c
@@ -773,22 +773,31 @@  u64 get_page_table_size(void)
 
 #define KERNEL_COMP_SIZE	SZ_128M
 
+#define lmb_alloc(size, addr) lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
+
 int board_late_init(void)
 {
 	u32 status = 0;
+	phys_addr_t addr;
 
 	/* somewhat based on the Linux Kernel boot requirements:
 	 * align by 2M and maximal FDT size 2M
 	 */
-	status |= env_set_hex("loadaddr", lmb_alloc(SZ_1G, SZ_2M));
-	status |= env_set_hex("fdt_addr_r", lmb_alloc(SZ_2M, SZ_2M));
-	status |= env_set_hex("kernel_addr_r", lmb_alloc(SZ_128M, SZ_2M));
-	status |= env_set_hex("ramdisk_addr_r", lmb_alloc(SZ_1G, SZ_2M));
-	status |= env_set_hex("kernel_comp_addr_r",
-			      lmb_alloc(KERNEL_COMP_SIZE, SZ_2M));
-	status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
-	status |= env_set_hex("scriptaddr", lmb_alloc(SZ_4M, SZ_2M));
-	status |= env_set_hex("pxefile_addr_r", lmb_alloc(SZ_4M, SZ_2M));
+	status |= !lmb_alloc(SZ_1G, &addr) ? env_set_hex("loadaddr", addr) : 1;
+	status |= !lmb_alloc(SZ_2M, &addr) ?
+		env_set_hex("fdt_addr_r", addr) : 1;
+	status |= !lmb_alloc(SZ_128M, &addr) ?
+		env_set_hex("kernel_addr_r", addr) : 1;
+	status |= !lmb_alloc(SZ_1G, &addr) ?
+		env_set_hex("ramdisk_addr_r", addr) : 1;
+	status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+		env_set_hex("kernel_comp_addr_r", addr) : 1;
+	status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+		env_set_hex("kernel_comp_size", addr) : 1;
+	status |= !lmb_alloc(SZ_4M, &addr) ?
+		env_set_hex("scriptaddr", addr) : 1;
+	status |= !lmb_alloc(SZ_4M, &addr) ?
+		env_set_hex("pxefile_addr_r", addr) : 1;
 
 	if (status)
 		log_warning("late_init: Failed to set run time variables\n");
diff --git a/arch/arm/mach-snapdragon/board.c b/arch/arm/mach-snapdragon/board.c
index 5547d6d054f..87a173e0acb 100644
--- a/arch/arm/mach-snapdragon/board.c
+++ b/arch/arm/mach-snapdragon/board.c
@@ -492,7 +492,7 @@  void __weak qcom_late_init(void)
 #define FASTBOOT_BUF_SIZE 0
 #endif
 
-#define addr_alloc(size) lmb_alloc(size, SZ_2M)
+#define lmb_alloc(size, addr) lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, addr, size, LMB_NONE)
 
 /* Stolen from arch/arm/mach-apple/board.c */
 int board_late_init(void)
@@ -502,18 +502,26 @@  int board_late_init(void)
 	struct fdt_header *fdt_blob = (struct fdt_header *)gd->fdt_blob;
 
 	/* We need to be fairly conservative here as we support boards with just 1G of TOTAL RAM */
-	addr = addr_alloc(SZ_128M);
+	status |= !lmb_alloc(SZ_128M, &addr) ?
+		env_set_hex("loadaddr", addr) : 1;
 	status |= env_set_hex("kernel_addr_r", addr);
-	status |= env_set_hex("loadaddr", addr);
-	status |= env_set_hex("ramdisk_addr_r", addr_alloc(SZ_128M));
-	status |= env_set_hex("kernel_comp_addr_r", addr_alloc(KERNEL_COMP_SIZE));
-	status |= env_set_hex("kernel_comp_size", KERNEL_COMP_SIZE);
+	status |= !lmb_alloc(SZ_128M, &addr) ?
+		env_set_hex("ramdisk_addr_r", addr) : 1;
+	status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+		env_set_hex("kernel_comp_addr_r", addr) : 1;
+	status |= !lmb_alloc(KERNEL_COMP_SIZE, &addr) ?
+		env_set_hex("kernel_comp_size", addr) : 1;
+	status |= !lmb_alloc(SZ_4M, &addr) ?
+		env_set_hex("scriptaddr", addr) : 1;
+	status |= !lmb_alloc(SZ_4M, &addr) ?
+		env_set_hex("pxefile_addr_r", addr) : 1;
+
 	if (IS_ENABLED(CONFIG_FASTBOOT))
-		status |= env_set_hex("fastboot_addr_r", addr_alloc(FASTBOOT_BUF_SIZE));
-	status |= env_set_hex("scriptaddr", addr_alloc(SZ_4M));
-	status |= env_set_hex("pxefile_addr_r", addr_alloc(SZ_4M));
-	addr = addr_alloc(SZ_2M);
-	status |= env_set_hex("fdt_addr_r", addr);
+		status |= !lmb_alloc(FASTBOOT_BUF_SIZE, &addr) ?
+			env_set_hex("fastboot_addr_r", addr) : 1;
+
+	status |= !lmb_alloc(SZ_2M, &addr) ?
+		env_set_hex("fdt_addr_r", addr) : 1;
 
 	if (status)
 		log_warning("%s: Failed to set run time variables\n", __func__);
diff --git a/boot/bootm.c b/boot/bootm.c
index 3282bfc0b4b..4bdca22ea8c 100644
--- a/boot/bootm.c
+++ b/boot/bootm.c
@@ -623,12 +623,16 @@  static int bootm_load_os(struct bootm_headers *images, int boot_progress)
 	 */
 	if (os.type == IH_TYPE_KERNEL_NOLOAD && os.comp != IH_COMP_NONE) {
 		ulong req_size = ALIGN(image_len * 4, SZ_1M);
+		phys_addr_t addr;
 
-		load = lmb_alloc(req_size, SZ_2M);
-		if (!load)
+		err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, SZ_2M, &addr,
+				    req_size, LMB_NONE);
+		if (err)
 			return 1;
-		os.load = load;
-		images->ep = load;
+
+		load = (ulong)addr;
+		os.load = (ulong)addr;
+		images->ep = (ulong)addr;
 		debug("Allocated %lx bytes at %lx for kernel (size %lx) decompression\n",
 		      req_size, load, image_len);
 	}
diff --git a/boot/image-board.c b/boot/image-board.c
index b0fa028ceac..005d60caf5c 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -16,6 +16,7 @@ 
 #include <fpga.h>
 #include <image.h>
 #include <init.h>
+#include <lmb.h>
 #include <log.h>
 #include <mapmem.h>
 #include <rtc.h>
@@ -566,27 +567,24 @@  int boot_ramdisk_high(ulong rd_data, ulong rd_len, ulong *initrd_start,
 			*initrd_start = rd_data;
 			*initrd_end = rd_data + rd_len;
 			initrd_addr = (phys_addr_t)rd_data;
-			err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0,
-					    &initrd_addr, rd_len, LMB_NONE);
+			err = lmb_alloc_mem(LMB_MEM_ALLOC_ADDR, 0, &initrd_addr,
+					    rd_len, LMB_NONE);
 			if (err) {
 				puts("in-place initrd alloc failed\n");
 				goto error;
 			}
 		} else {
-			if (initrd_high)
-				*initrd_start =
-					(ulong)lmb_alloc_base(rd_len,
-								    0x1000,
-								    initrd_high,
-								    LMB_NONE);
-			else
-				*initrd_start = (ulong)lmb_alloc(rd_len,
-								 0x1000);
+			enum lmb_mem_type type = initrd_high ?
+				LMB_MEM_ALLOC_MAX : LMB_MEM_ALLOC_ANY;
 
-			if (*initrd_start == 0) {
+			err = lmb_alloc_mem(type, 0x1000, &initrd_high, rd_len,
+					    LMB_NONE);
+			if (err) {
 				puts("ramdisk - allocation error\n");
 				goto error;
 			}
+
+			*initrd_start = (ulong)initrd_high;
 			bootstage_mark(BOOTSTAGE_ID_COPY_RAMDISK);
 
 			*initrd_end = *initrd_start + rd_len;
@@ -837,9 +835,10 @@  int boot_get_loadable(struct bootm_headers *images)
  */
 int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
 {
-	int barg;
+	int barg, err;
 	char *cmdline;
 	char *s;
+	phys_addr_t addr;
 
 	/*
 	 * Help the compiler detect that this function is only called when
@@ -849,12 +848,14 @@  int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
 		return 0;
 
 	barg = IF_ENABLED_INT(CONFIG_SYS_BOOT_GET_CMDLINE, CONFIG_SYS_BARGSIZE);
-	cmdline = (char *)(ulong)lmb_alloc_base(barg, 0xf,
-				env_get_bootm_mapsize() + env_get_bootm_low(),
-				LMB_NONE);
-	if (!cmdline)
+	addr = env_get_bootm_mapsize() + env_get_bootm_low();
+
+	err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0xf, &addr, barg, LMB_NONE);
+	if (err)
 		return -1;
 
+	cmdline = (char *)(uintptr_t)addr;
+
 	s = env_get("bootargs");
 	if (!s)
 		s = "";
@@ -883,14 +884,16 @@  int boot_get_cmdline(ulong *cmd_start, ulong *cmd_end)
  */
 int boot_get_kbd(struct bd_info **kbd)
 {
-	*kbd = (struct bd_info *)(ulong)lmb_alloc_base(sizeof(struct bd_info),
-							     0xf,
-							     env_get_bootm_mapsize() +
-							     env_get_bootm_low(),
-							     LMB_NONE);
-	if (!*kbd)
+	int err;
+	phys_addr_t addr;
+
+	addr = env_get_bootm_mapsize() + env_get_bootm_low();
+	err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0xf, &addr,
+			    sizeof(struct bd_info), LMB_NONE);
+	if (err)
 		return -1;
 
+	*kbd = (struct bd_info *)(uintptr_t)addr;
 	**kbd = *gd->bd;
 
 	debug("## kernel board info at 0x%08lx\n", (ulong)*kbd);
diff --git a/boot/image-fdt.c b/boot/image-fdt.c
index bd5a6231140..2720ce6f6f3 100644
--- a/boot/image-fdt.c
+++ b/boot/image-fdt.c
@@ -183,9 +183,9 @@  int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
 	/* If fdt_high is set use it to select the relocation address */
 	fdt_high = env_get("fdt_high");
 	if (fdt_high) {
-		ulong desired_addr = hextoul(fdt_high, NULL);
+		ulong high_addr = hextoul(fdt_high, NULL);
 
-		if (desired_addr == ~0UL) {
+		if (high_addr == ~0UL) {
 			/* All ones means use fdt in place */
 			of_start = fdt_blob;
 			addr = map_to_sysmem(fdt_blob);
@@ -198,16 +198,17 @@  int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
 			}
 
 			disable_relocation = 1;
-		} else if (desired_addr) {
-			addr = lmb_alloc_base(of_len, 0x1000, desired_addr,
-					      LMB_NONE);
-			of_start = map_sysmem(addr, of_len);
-			if (of_start == NULL) {
-				puts("Failed using fdt_high value for Device Tree");
+		} else {
+			enum lmb_mem_type type = high_addr ?
+				LMB_MEM_ALLOC_MAX : LMB_MEM_ALLOC_ANY;
+
+			addr = high_addr;
+			err = lmb_alloc_mem(type, 0x1000, &addr, of_len,
+					    LMB_NONE);
+			if (err) {
+				puts("Failed to allocate memory for Device Tree relocation\n");
 				goto error;
 			}
-		} else {
-			addr = lmb_alloc(of_len, 0x1000);
 			of_start = map_sysmem(addr, of_len);
 		}
 	} else {
@@ -229,11 +230,15 @@  int boot_relocate_fdt(char **of_flat_tree, ulong *of_size)
 			 * for LMB allocation.
 			 */
 			usable = min(start + size, low + mapsize);
-			addr = lmb_alloc_base(of_len, 0x1000, usable, LMB_NONE);
-			of_start = map_sysmem(addr, of_len);
-			/* Allocation succeeded, use this block. */
-			if (of_start != NULL)
-				break;
+			addr = usable;
+			err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, 0x1000,
+					    &addr, of_len, LMB_NONE);
+			if (!err) {
+				of_start = map_sysmem(addr, of_len);
+				/* Allocation succeeded, use this block. */
+				if (of_start)
+					break;
+			}
 
 			/*
 			 * Reduce the mapping size in the next bank
diff --git a/include/lmb.h b/include/lmb.h
index 8906b42181f..34dbc25759d 100644
--- a/include/lmb.h
+++ b/include/lmb.h
@@ -34,9 +34,13 @@ 
 /**
  * enum lmb_mem_type - type of memory allocation request
  * @LMB_MEM_ALLOC_ADDR:	request for a particular region of memory
+ * @LMB_MEM_ALLOC_ANY:	allocate any available memory region
+ * @LMB_MEM_ALLOC_MAX:	allocate memory below a particular address
  */
 enum lmb_mem_type {
 	LMB_MEM_ALLOC_ADDR = 1,
+	LMB_MEM_ALLOC_ANY,
+	LMB_MEM_ALLOC_MAX,
 };
 
 /**
@@ -130,26 +134,8 @@  void lmb_add_memory(void);
 
 long lmb_add(phys_addr_t base, phys_size_t size);
 
-phys_addr_t lmb_alloc(phys_size_t size, ulong align);
 phys_size_t lmb_get_free_size(phys_addr_t addr);
 
-/**
- * lmb_alloc_base() - Allocate specified memory region with specified
- *			    attributes
- * @size: Size of the region requested
- * @align: Alignment of the memory region requested
- * @max_addr: Maximum address of the requested region
- * @flags: Memory region attributes to be set
- *
- * Allocate a region of memory with the attributes specified through the
- * parameter. The max_addr parameter is used to specify the maximum address
- * below which the requested region should be allocated.
- *
- * Return: Base address on success, 0 on error.
- */
-phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr,
-			   uint flags);
-
 /**
  * lmb_is_reserved_flags() - Test if address is in reserved region with flag
  *			     bits set
diff --git a/lib/efi_loader/efi_memory.c b/lib/efi_loader/efi_memory.c
index 77950a267cc..466f45c98b1 100644
--- a/lib/efi_loader/efi_memory.c
+++ b/lib/efi_loader/efi_memory.c
@@ -454,6 +454,7 @@  efi_status_t efi_allocate_pages(enum efi_allocate_type type,
 				enum efi_memory_type memory_type,
 				efi_uintn_t pages, uint64_t *memory)
 {
+	int err;
 	u64 efi_addr, len;
 	uint flags;
 	efi_status_t ret;
@@ -475,17 +476,18 @@  efi_status_t efi_allocate_pages(enum efi_allocate_type type,
 	switch (type) {
 	case EFI_ALLOCATE_ANY_PAGES:
 		/* Any page */
-		addr = (u64)lmb_alloc_base(len, EFI_PAGE_SIZE,
-						 LMB_ALLOC_ANYWHERE, flags);
-		if (!addr)
+		err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, EFI_PAGE_SIZE, &addr,
+				    len, flags);
+		if (err)
 			return EFI_OUT_OF_RESOURCES;
 		break;
 	case EFI_ALLOCATE_MAX_ADDRESS:
 		/* Max address */
 		addr = map_to_sysmem((void *)(uintptr_t)*memory);
-		addr = (u64)lmb_alloc_base(len, EFI_PAGE_SIZE, addr,
-						 flags);
-		if (!addr)
+
+		err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, EFI_PAGE_SIZE, &addr,
+				    len, flags);
+		if (err)
 			return EFI_OUT_OF_RESOURCES;
 		break;
 	case EFI_ALLOCATE_ADDRESS:
diff --git a/lib/lmb.c b/lib/lmb.c
index 72d4edacff0..29603335f66 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -672,16 +672,18 @@  long lmb_free(phys_addr_t base, phys_size_t size)
 	return lmb_free_flags(base, size, LMB_NONE);
 }
 
-static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
-				   phys_addr_t max_addr, u32 flags)
+static int _lmb_alloc_base(phys_size_t size, ulong align,
+			   phys_addr_t *addr, u32 flags)
 {
 	int ret;
 	long i, rgn;
+	phys_addr_t max_addr;
 	phys_addr_t base = 0;
 	phys_addr_t res_base;
 	struct lmb_region *lmb_used = lmb.used_mem.data;
 	struct lmb_region *lmb_memory = lmb.available_mem.data;
 
+	max_addr = *addr;
 	for (i = lmb.available_mem.count - 1; i >= 0; i--) {
 		phys_addr_t lmbbase = lmb_memory[i].base;
 		phys_size_t lmbsize = lmb_memory[i].size;
@@ -714,8 +716,8 @@  static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
 							    flags);
 				if (ret)
 					return ret;
-
-				return base;
+				*addr = base;
+				return 0;
 			}
 
 			res_base = lmb_used[rgn].base;
@@ -728,18 +730,7 @@  static phys_addr_t _lmb_alloc_base(phys_size_t size, ulong align,
 	log_debug("%s: Failed to allocate 0x%lx bytes below 0x%lx\n",
 		  __func__, (ulong)size, (ulong)max_addr);
 
-	return 0;
-}
-
-phys_addr_t lmb_alloc(phys_size_t size, ulong align)
-{
-	return _lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE, LMB_NONE);
-}
-
-phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr,
-			   uint flags)
-{
-	return _lmb_alloc_base(size, align, max_addr, flags);
+	return -1;
 }
 
 static int _lmb_alloc_addr(phys_addr_t base, phys_size_t size, u32 flags)
@@ -778,6 +769,11 @@  int lmb_alloc_mem(enum lmb_mem_type type, u64 align, phys_addr_t *addr,
 		return -EINVAL;
 
 	switch (type) {
+	case LMB_MEM_ALLOC_ANY:
+		*addr = LMB_ALLOC_ANYWHERE;
+	case LMB_MEM_ALLOC_MAX:
+		ret = _lmb_alloc_base(size, align, addr, flags);
+		break;
 	case LMB_MEM_ALLOC_ADDR:
 		ret = _lmb_alloc_addr(*addr, size, flags);
 		break;
diff --git a/test/lib/lmb.c b/test/lib/lmb.c
index 751909fc2cf..d8eab96527a 100644
--- a/test/lib/lmb.c
+++ b/test/lib/lmb.c
@@ -82,6 +82,32 @@  static int lmb_reserve(phys_addr_t addr, phys_size_t size, u32 flags)
 	return 0;
 }
 
+static phys_addr_t lmb_alloc(phys_size_t size, ulong align)
+{
+	int err;
+	phys_addr_t addr;
+
+	err = lmb_alloc_mem(LMB_MEM_ALLOC_ANY, align, &addr, size, LMB_NONE);
+	if (err)
+		return 0;
+
+	return addr;
+}
+
+static phys_addr_t lmb_alloc_base(phys_size_t size, ulong align,
+				  phys_addr_t max_addr, u32 flags)
+{
+	int err;
+	phys_addr_t addr;
+
+	addr = max_addr;
+	err = lmb_alloc_mem(LMB_MEM_ALLOC_MAX, align, &addr, size, flags);
+	if (err)
+		return 0;
+
+	return addr;
+}
+
 #define lmb_alloc_addr(addr, size, flags) lmb_reserve(addr, size, flags)
 
 static int test_multi_alloc(struct unit_test_state *uts, const phys_addr_t ram,