diff options
author | David Daney <ddaney@caviumnetworks.com> | 2009-05-05 20:35:16 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2009-06-17 06:06:29 -0400 |
commit | 6fa044ab8ab609bf95423b2841e20a2f4bb3a86d (patch) | |
tree | 666130477775132de1058596cabc17646ce03ed7 /arch/mips | |
parent | ce65cc8fe22a572ea9ec88e203388558b6b863af (diff) |
MIPS: Add named alloc functions to OCTEON boot monitor memory allocator.
The various Octeon ethernet drivers use these new functions.
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 104 | ||||
-rw-r--r-- | arch/mips/include/asm/octeon/cvmx-bootmem.h | 85 |
2 files changed, 189 insertions, 0 deletions
diff --git a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c index 4f5a08b37ccd..25666da17b22 100644 --- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c | |||
@@ -31,6 +31,7 @@ | |||
31 | */ | 31 | */ |
32 | 32 | ||
33 | #include <linux/kernel.h> | 33 | #include <linux/kernel.h> |
34 | #include <linux/module.h> | ||
34 | 35 | ||
35 | #include <asm/octeon/cvmx.h> | 36 | #include <asm/octeon/cvmx.h> |
36 | #include <asm/octeon/cvmx-spinlock.h> | 37 | #include <asm/octeon/cvmx-spinlock.h> |
@@ -97,6 +98,33 @@ void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment) | |||
97 | return cvmx_bootmem_alloc_range(size, alignment, 0, 0); | 98 | return cvmx_bootmem_alloc_range(size, alignment, 0, 0); |
98 | } | 99 | } |
99 | 100 | ||
101 | void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, | ||
102 | uint64_t max_addr, uint64_t align, | ||
103 | char *name) | ||
104 | { | ||
105 | int64_t addr; | ||
106 | |||
107 | addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr, | ||
108 | align, name, 0); | ||
109 | if (addr >= 0) | ||
110 | return cvmx_phys_to_ptr(addr); | ||
111 | else | ||
112 | return NULL; | ||
113 | } | ||
114 | |||
115 | void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, | ||
116 | char *name) | ||
117 | { | ||
118 | return cvmx_bootmem_alloc_named_range(size, address, address + size, | ||
119 | 0, name); | ||
120 | } | ||
121 | |||
122 | void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name) | ||
123 | { | ||
124 | return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name); | ||
125 | } | ||
126 | EXPORT_SYMBOL(cvmx_bootmem_alloc_named); | ||
127 | |||
100 | int cvmx_bootmem_free_named(char *name) | 128 | int cvmx_bootmem_free_named(char *name) |
101 | { | 129 | { |
102 | return cvmx_bootmem_phy_named_block_free(name, 0); | 130 | return cvmx_bootmem_phy_named_block_free(name, 0); |
@@ -106,6 +134,7 @@ struct cvmx_bootmem_named_block_desc *cvmx_bootmem_find_named_block(char *name) | |||
106 | { | 134 | { |
107 | return cvmx_bootmem_phy_named_block_find(name, 0); | 135 | return cvmx_bootmem_phy_named_block_find(name, 0); |
108 | } | 136 | } |
137 | EXPORT_SYMBOL(cvmx_bootmem_find_named_block); | ||
109 | 138 | ||
110 | void cvmx_bootmem_lock(void) | 139 | void cvmx_bootmem_lock(void) |
111 | { | 140 | { |
@@ -584,3 +613,78 @@ int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags) | |||
584 | cvmx_bootmem_unlock(); | 613 | cvmx_bootmem_unlock(); |
585 | return named_block_ptr != NULL; /* 0 on failure, 1 on success */ | 614 | return named_block_ptr != NULL; /* 0 on failure, 1 on success */ |
586 | } | 615 | } |
616 | |||
617 | int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, | ||
618 | uint64_t max_addr, | ||
619 | uint64_t alignment, | ||
620 | char *name, | ||
621 | uint32_t flags) | ||
622 | { | ||
623 | int64_t addr_allocated; | ||
624 | struct cvmx_bootmem_named_block_desc *named_block_desc_ptr; | ||
625 | |||
626 | #ifdef DEBUG | ||
627 | cvmx_dprintf("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: " | ||
628 | "0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n", | ||
629 | (unsigned long long)size, | ||
630 | (unsigned long long)min_addr, | ||
631 | (unsigned long long)max_addr, | ||
632 | (unsigned long long)alignment, | ||
633 | name); | ||
634 | #endif | ||
635 | if (cvmx_bootmem_desc->major_version != 3) { | ||
636 | cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: " | ||
637 | "%d.%d at addr: %p\n", | ||
638 | (int)cvmx_bootmem_desc->major_version, | ||
639 | (int)cvmx_bootmem_desc->minor_version, | ||
640 | cvmx_bootmem_desc); | ||
641 | return -1; | ||
642 | } | ||
643 | |||
644 | /* | ||
645 | * Take lock here, as name lookup/block alloc/name add need to | ||
646 | * be atomic. | ||
647 | */ | ||
648 | if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) | ||
649 | cvmx_spinlock_lock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); | ||
650 | |||
651 | /* Get pointer to first available named block descriptor */ | ||
652 | named_block_desc_ptr = | ||
653 | cvmx_bootmem_phy_named_block_find(NULL, | ||
654 | flags | CVMX_BOOTMEM_FLAG_NO_LOCKING); | ||
655 | |||
656 | /* | ||
657 | * Check to see if name already in use, return error if name | ||
658 | * not available or no more room for blocks. | ||
659 | */ | ||
660 | if (cvmx_bootmem_phy_named_block_find(name, | ||
661 | flags | CVMX_BOOTMEM_FLAG_NO_LOCKING) || !named_block_desc_ptr) { | ||
662 | if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) | ||
663 | cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); | ||
664 | return -1; | ||
665 | } | ||
666 | |||
667 | |||
668 | /* | ||
669 | * Round size up to mult of minimum alignment bytes We need | ||
670 | * the actual size allocated to allow for blocks to be | ||
671 | * coallesced when they are freed. The alloc routine does the | ||
672 | * same rounding up on all allocations. | ||
673 | */ | ||
674 | size = __ALIGN_MASK(size, (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1)); | ||
675 | |||
676 | addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr, | ||
677 | alignment, | ||
678 | flags | CVMX_BOOTMEM_FLAG_NO_LOCKING); | ||
679 | if (addr_allocated >= 0) { | ||
680 | named_block_desc_ptr->base_addr = addr_allocated; | ||
681 | named_block_desc_ptr->size = size; | ||
682 | strncpy(named_block_desc_ptr->name, name, | ||
683 | cvmx_bootmem_desc->named_block_name_len); | ||
684 | named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0; | ||
685 | } | ||
686 | |||
687 | if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING)) | ||
688 | cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock)); | ||
689 | return addr_allocated; | ||
690 | } | ||
diff --git a/arch/mips/include/asm/octeon/cvmx-bootmem.h b/arch/mips/include/asm/octeon/cvmx-bootmem.h index 1cbe4b55889d..8e708bdb43f7 100644 --- a/arch/mips/include/asm/octeon/cvmx-bootmem.h +++ b/arch/mips/include/asm/octeon/cvmx-bootmem.h | |||
@@ -183,6 +183,64 @@ extern void *cvmx_bootmem_alloc_range(uint64_t size, uint64_t alignment, | |||
183 | * Returns 0 on failure, | 183 | * Returns 0 on failure, |
184 | * !0 on success | 184 | * !0 on success |
185 | */ | 185 | */ |
186 | |||
187 | |||
188 | /** | ||
189 | * Allocate a block of memory from the free list that was passed | ||
190 | * to the application by the bootloader, and assign it a name in the | ||
191 | * global named block table. (part of the cvmx_bootmem_descriptor_t structure) | ||
192 | * Named blocks can later be freed. | ||
193 | * | ||
194 | * @size: Size in bytes of block to allocate | ||
195 | * @alignment: Alignment required - must be power of 2 | ||
196 | * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes | ||
197 | * | ||
198 | * Returns a pointer to block of memory, NULL on error | ||
199 | */ | ||
200 | extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, | ||
201 | char *name); | ||
202 | |||
203 | |||
204 | |||
205 | /** | ||
206 | * Allocate a block of memory from the free list that was passed | ||
207 | * to the application by the bootloader, and assign it a name in the | ||
208 | * global named block table. (part of the cvmx_bootmem_descriptor_t structure) | ||
209 | * Named blocks can later be freed. | ||
210 | * | ||
211 | * @size: Size in bytes of block to allocate | ||
212 | * @address: Physical address to allocate memory at. If this | ||
213 | * memory is not available, the allocation fails. | ||
214 | * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN | ||
215 | * bytes | ||
216 | * | ||
217 | * Returns a pointer to block of memory, NULL on error | ||
218 | */ | ||
219 | extern void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address, | ||
220 | char *name); | ||
221 | |||
222 | |||
223 | |||
224 | /** | ||
225 | * Allocate a block of memory from a specific range of the free list | ||
226 | * that was passed to the application by the bootloader, and assign it | ||
227 | * a name in the global named block table. (part of the | ||
228 | * cvmx_bootmem_descriptor_t structure) Named blocks can later be | ||
229 | * freed. If request cannot be satisfied within the address range | ||
230 | * specified, NULL is returned | ||
231 | * | ||
232 | * @size: Size in bytes of block to allocate | ||
233 | * @min_addr: minimum address of range | ||
234 | * @max_addr: maximum address of range | ||
235 | * @align: Alignment of memory to be allocated. (must be a power of 2) | ||
236 | * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes | ||
237 | * | ||
238 | * Returns a pointer to block of memory, NULL on error | ||
239 | */ | ||
240 | extern void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr, | ||
241 | uint64_t max_addr, uint64_t align, | ||
242 | char *name); | ||
243 | |||
186 | extern int cvmx_bootmem_free_named(char *name); | 244 | extern int cvmx_bootmem_free_named(char *name); |
187 | 245 | ||
188 | /** | 246 | /** |
@@ -224,6 +282,33 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min, | |||
224 | uint32_t flags); | 282 | uint32_t flags); |
225 | 283 | ||
226 | /** | 284 | /** |
285 | * Allocates a named block of physical memory from the free list, at | ||
286 | * (optional) requested address and alignment. | ||
287 | * | ||
288 | * @param size size of region to allocate. All requests are rounded | ||
289 | * up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE | ||
290 | * bytes size | ||
291 | * @param min_addr Minimum address that block can occupy. | ||
292 | * @param max_addr Specifies the maximum address_min (inclusive) that | ||
293 | * the allocation can use. | ||
294 | * @param alignment Requested alignment of the block. If this | ||
295 | * alignment cannot be met, the allocation fails. | ||
296 | * This must be a power of 2. (Note: Alignment of | ||
297 | * CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and | ||
298 | * internally enforced. Requested alignments of less | ||
299 | * than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to | ||
300 | * CVMX_BOOTMEM_ALIGNMENT_SIZE.) | ||
301 | * @param name name to assign to named block | ||
302 | * @param flags Flags to control options for the allocation. | ||
303 | * | ||
304 | * @return physical address of block allocated, or -1 on failure | ||
305 | */ | ||
306 | int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr, | ||
307 | uint64_t max_addr, | ||
308 | uint64_t alignment, | ||
309 | char *name, uint32_t flags); | ||
310 | |||
311 | /** | ||
227 | * Finds a named memory block by name. | 312 | * Finds a named memory block by name. |
228 | * Also used for finding an unused entry in the named block table. | 313 | * Also used for finding an unused entry in the named block table. |
229 | * | 314 | * |