| .. | .. |
|---|
| 45 | 45 | /* See header file for descriptions of functions */ |
|---|
| 46 | 46 | |
|---|
| 47 | 47 | /** |
|---|
| 48 | | - * This macro returns the size of a member of a structure. |
|---|
| 49 | | - * Logically it is the same as "sizeof(s::field)" in C++, but |
|---|
| 50 | | - * C lacks the "::" operator. |
|---|
| 51 | | - */ |
|---|
| 52 | | -#define SIZEOF_FIELD(s, field) sizeof(((s *)NULL)->field) |
|---|
| 53 | | - |
|---|
| 54 | | -/** |
|---|
| 55 | 48 | * This macro returns a member of the |
|---|
| 56 | 49 | * cvmx_bootmem_named_block_desc_t structure. These members can't |
|---|
| 57 | 50 | * be directly addressed as they might be in memory not directly |
|---|
| .. | .. |
|---|
| 65 | 58 | #define CVMX_BOOTMEM_NAMED_GET_FIELD(addr, field) \ |
|---|
| 66 | 59 | __cvmx_bootmem_desc_get(addr, \ |
|---|
| 67 | 60 | offsetof(struct cvmx_bootmem_named_block_desc, field), \ |
|---|
| 68 | | - SIZEOF_FIELD(struct cvmx_bootmem_named_block_desc, field)) |
|---|
| 61 | + sizeof_field(struct cvmx_bootmem_named_block_desc, field)) |
|---|
| 69 | 62 | |
|---|
| 70 | 63 | /** |
|---|
| 71 | 64 | * This function is the implementation of the get macros defined |
|---|
| .. | .. |
|---|
| 122 | 115 | return cvmx_read64_uint64((addr + NEXT_OFFSET) | (1ull << 63)); |
|---|
| 123 | 116 | } |
|---|
| 124 | 117 | |
|---|
| 125 | | -void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment, |
|---|
| 126 | | - uint64_t min_addr, uint64_t max_addr) |
|---|
| 118 | +/** |
|---|
| 119 | + * Allocate a block of memory from the free list that was |
|---|
| 120 | + * passed to the application by the bootloader within a specified |
|---|
| 121 | + * address range. This is an allocate-only algorithm, so |
|---|
| 122 | + * freeing memory is not possible. Allocation will fail if |
|---|
| 123 | + * memory cannot be allocated in the requested range. |
|---|
| 124 | + * |
|---|
| 125 | + * @size: Size in bytes of block to allocate |
|---|
| 126 | + * @min_addr: defines the minimum address of the range |
|---|
| 127 | + * @max_addr: defines the maximum address of the range |
|---|
| 128 | + * @alignment: Alignment required - must be power of 2 |
|---|
| 129 | + * Returns pointer to block of memory, NULL on error |
|---|
| 130 | + */ |
|---|
| 131 | +static void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment, |
|---|
| 132 | + uint64_t min_addr, uint64_t max_addr) |
|---|
| 127 | 133 | { |
|---|
| 128 | 134 | int64_t address; |
|---|
| 129 | 135 | address = |
|---|
| .. | .. |
|---|
| 142 | 148 | address + size); |
|---|
| 143 | 149 | } |
|---|
| 144 | 150 | |
|---|
| 145 | | -void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment) |
|---|
| 146 | | -{ |
|---|
| 147 | | - return cvmx_bootmem_alloc_range(size, alignment, 0, 0); |
|---|
| 148 | | -} |
|---|
| 149 | | - |
|---|
| 150 | | -void *cvmx_bootmem_alloc_named_range_once(uint64_t size, uint64_t min_addr, |
|---|
| 151 | | - uint64_t max_addr, uint64_t align, |
|---|
| 152 | | - char *name, |
|---|
| 153 | | - void (*init) (void *)) |
|---|
| 154 | | -{ |
|---|
| 155 | | - int64_t addr; |
|---|
| 156 | | - void *ptr; |
|---|
| 157 | | - uint64_t named_block_desc_addr; |
|---|
| 158 | | - |
|---|
| 159 | | - named_block_desc_addr = (uint64_t) |
|---|
| 160 | | - cvmx_bootmem_phy_named_block_find(name, |
|---|
| 161 | | - (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING); |
|---|
| 162 | | - |
|---|
| 163 | | - if (named_block_desc_addr) { |
|---|
| 164 | | - addr = CVMX_BOOTMEM_NAMED_GET_FIELD(named_block_desc_addr, |
|---|
| 165 | | - base_addr); |
|---|
| 166 | | - return cvmx_phys_to_ptr(addr); |
|---|
| 167 | | - } |
|---|
| 168 | | - |
|---|
| 169 | | - addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, |
|---|
| 170 | | - align, name, |
|---|
| 171 | | - (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING); |
|---|
| 172 | | - |
|---|
| 173 | | - if (addr < 0) |
|---|
| 174 | | - return NULL; |
|---|
| 175 | | - ptr = cvmx_phys_to_ptr(addr); |
|---|
| 176 | | - |
|---|
| 177 | | - if (init) |
|---|
| 178 | | - init(ptr); |
|---|
| 179 | | - else |
|---|
| 180 | | - memset(ptr, 0, size); |
|---|
| 181 | | - |
|---|
| 182 | | - return ptr; |
|---|
| 183 | | -} |
|---|
| 184 | | -EXPORT_SYMBOL(cvmx_bootmem_alloc_named_range_once); |
|---|
| 185 | | - |
|---|
| 186 | 151 | void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, |
|---|
| 187 | 152 | uint64_t max_addr, uint64_t align, |
|---|
| 188 | 153 | char *name) |
|---|
| .. | .. |
|---|
| 197 | 162 | return NULL; |
|---|
| 198 | 163 | } |
|---|
| 199 | 164 | |
|---|
| 200 | | -void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, |
|---|
| 201 | | - char *name) |
|---|
| 202 | | -{ |
|---|
| 203 | | - return cvmx_bootmem_alloc_named_range(size, address, address + size, |
|---|
| 204 | | - 0, name); |
|---|
| 205 | | -} |
|---|
| 206 | | - |
|---|
| 207 | 165 | void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name) |
|---|
| 208 | 166 | { |
|---|
| 209 | 167 | return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name); |
|---|
| 210 | 168 | } |
|---|
| 211 | 169 | EXPORT_SYMBOL(cvmx_bootmem_alloc_named); |
|---|
| 212 | | - |
|---|
| 213 | | -int cvmx_bootmem_free_named(char *name) |
|---|
| 214 | | -{ |
|---|
| 215 | | - return cvmx_bootmem_phy_named_block_free(name, 0); |
|---|
| 216 | | -} |
|---|
| 217 | | - |
|---|
| 218 | | -struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name) |
|---|
| 219 | | -{ |
|---|
| 220 | | - return cvmx_bootmem_phy_named_block_find(name, 0); |
|---|
| 221 | | -} |
|---|
| 222 | | -EXPORT_SYMBOL(cvmx_bootmem_find_named_block); |
|---|
| 223 | 170 | |
|---|
| 224 | 171 | void cvmx_bootmem_lock(void) |
|---|
| 225 | 172 | { |
|---|
| .. | .. |
|---|
| 603 | 550 | |
|---|
| 604 | 551 | } |
|---|
| 605 | 552 | |
|---|
| 606 | | -struct cvmx_bootmem_named_block_desc * |
|---|
| 553 | +/** |
|---|
| 554 | + * Finds a named memory block by name. |
|---|
| 555 | + * Also used for finding an unused entry in the named block table. |
|---|
| 556 | + * |
|---|
| 557 | + * @name: Name of memory block to find. If NULL pointer given, then |
|---|
| 558 | + * finds unused descriptor, if available. |
|---|
| 559 | + * |
|---|
| 560 | + * @flags: Flags to control options for the allocation. |
|---|
| 561 | + * |
|---|
| 562 | + * Returns Pointer to memory block descriptor, NULL if not found. |
|---|
| 563 | + * If NULL returned when name parameter is NULL, then no memory |
|---|
| 564 | + * block descriptors are available. |
|---|
| 565 | + */ |
|---|
| 566 | +static struct cvmx_bootmem_named_block_desc * |
|---|
| 607 | 567 | cvmx_bootmem_phy_named_block_find(char *name, uint32_t flags) |
|---|
| 608 | 568 | { |
|---|
| 609 | 569 | unsigned int i; |
|---|
| .. | .. |
|---|
| 655 | 615 | return NULL; |
|---|
| 656 | 616 | } |
|---|
| 657 | 617 | |
|---|
| 658 | | -int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags) |
|---|
| 618 | +void *cvmx_bootmem_alloc_named_range_once(uint64_t size, uint64_t min_addr, |
|---|
| 619 | + uint64_t max_addr, uint64_t align, |
|---|
| 620 | + char *name, |
|---|
| 621 | + void (*init) (void *)) |
|---|
| 622 | +{ |
|---|
| 623 | + int64_t addr; |
|---|
| 624 | + void *ptr; |
|---|
| 625 | + uint64_t named_block_desc_addr; |
|---|
| 626 | + |
|---|
| 627 | + named_block_desc_addr = (uint64_t) |
|---|
| 628 | + cvmx_bootmem_phy_named_block_find(name, |
|---|
| 629 | + (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING); |
|---|
| 630 | + |
|---|
| 631 | + if (named_block_desc_addr) { |
|---|
| 632 | + addr = CVMX_BOOTMEM_NAMED_GET_FIELD(named_block_desc_addr, |
|---|
| 633 | + base_addr); |
|---|
| 634 | + return cvmx_phys_to_ptr(addr); |
|---|
| 635 | + } |
|---|
| 636 | + |
|---|
| 637 | + addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, |
|---|
| 638 | + align, name, |
|---|
| 639 | + (uint32_t)CVMX_BOOTMEM_FLAG_NO_LOCKING); |
|---|
| 640 | + |
|---|
| 641 | + if (addr < 0) |
|---|
| 642 | + return NULL; |
|---|
| 643 | + ptr = cvmx_phys_to_ptr(addr); |
|---|
| 644 | + |
|---|
| 645 | + if (init) |
|---|
| 646 | + init(ptr); |
|---|
| 647 | + else |
|---|
| 648 | + memset(ptr, 0, size); |
|---|
| 649 | + |
|---|
| 650 | + return ptr; |
|---|
| 651 | +} |
|---|
| 652 | +EXPORT_SYMBOL(cvmx_bootmem_alloc_named_range_once); |
|---|
| 653 | + |
|---|
| 654 | +struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name) |
|---|
| 655 | +{ |
|---|
| 656 | + return cvmx_bootmem_phy_named_block_find(name, 0); |
|---|
| 657 | +} |
|---|
| 658 | +EXPORT_SYMBOL(cvmx_bootmem_find_named_block); |
|---|
| 659 | + |
|---|
| 660 | +/** |
|---|
| 661 | + * Frees a named block. |
|---|
| 662 | + * |
|---|
| 663 | + * @name: name of block to free |
|---|
| 664 | + * @flags: flags for passing options |
|---|
| 665 | + * |
|---|
| 666 | + * Returns 0 on failure |
|---|
| 667 | + * 1 on success |
|---|
| 668 | + */ |
|---|
| 669 | +static int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags) |
|---|
| 659 | 670 | { |
|---|
| 660 | 671 | struct cvmx_bootmem_named_block_desc *named_block_ptr; |
|---|
| 661 | 672 | |
|---|
| .. | .. |
|---|
| 699 | 710 | return named_block_ptr != NULL; /* 0 on failure, 1 on success */ |
|---|
| 700 | 711 | } |
|---|
| 701 | 712 | |
|---|
| 713 | +int cvmx_bootmem_free_named(char *name) |
|---|
| 714 | +{ |
|---|
| 715 | + return cvmx_bootmem_phy_named_block_free(name, 0); |
|---|
| 716 | +} |
|---|
| 717 | + |
|---|
| 702 | 718 | int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, |
|---|
| 703 | 719 | uint64_t max_addr, |
|---|
| 704 | 720 | uint64_t alignment, |
|---|