aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/cavium-octeon/executive/cvmx-bootmem.c')
-rw-r--r--arch/mips/cavium-octeon/executive/cvmx-bootmem.c104
1 files changed, 104 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
101void *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
115void *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
122void *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}
126EXPORT_SYMBOL(cvmx_bootmem_alloc_named);
127
100int cvmx_bootmem_free_named(char *name) 128int 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}
137EXPORT_SYMBOL(cvmx_bootmem_find_named_block);
109 138
110void cvmx_bootmem_lock(void) 139void 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
617int64_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}