aboutsummaryrefslogtreecommitdiff
path: root/arch/mips
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2009-05-05 17:35:16 -0700
committerRalf Baechle <ralf@linux-mips.org>2009-06-17 11:06:29 +0100
commit6fa044ab8ab609bf95423b2841e20a2f4bb3a86d (patch)
tree666130477775132de1058596cabc17646ce03ed7 /arch/mips
parentce65cc8fe22a572ea9ec88e203388558b6b863af (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.c104
-rw-r--r--arch/mips/include/asm/octeon/cvmx-bootmem.h85
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 4f5a08b37cc..25666da17b2 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
@@ -31,6 +31,7 @@
*/
#include <linux/kernel.h>
+#include <linux/module.h>
#include <asm/octeon/cvmx.h>
#include <asm/octeon/cvmx-spinlock.h>
@@ -97,6 +98,33 @@ void *cvmx_bootmem_alloc(uint64_t size, uint64_t alignment)
return cvmx_bootmem_alloc_range(size, alignment, 0, 0);
}
+void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
+ uint64_t max_addr, uint64_t align,
+ char *name)
+{
+ int64_t addr;
+
+ addr = cvmx_bootmem_phy_named_block_alloc(size, min_addr, max_addr,
+ align, name, 0);
+ if (addr >= 0)
+ return cvmx_phys_to_ptr(addr);
+ else
+ return NULL;
+}
+
+void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address,
+ char *name)
+{
+ return cvmx_bootmem_alloc_named_range(size, address, address + size,
+ 0, name);
+}
+
+void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment, char *name)
+{
+ return cvmx_bootmem_alloc_named_range(size, 0, 0, alignment, name);
+}
+EXPORT_SYMBOL(cvmx_bootmem_alloc_named);
+
int cvmx_bootmem_free_named(char *name)
{
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)
{
return cvmx_bootmem_phy_named_block_find(name, 0);
}
+EXPORT_SYMBOL(cvmx_bootmem_find_named_block);
void cvmx_bootmem_lock(void)
{
@@ -584,3 +613,78 @@ int cvmx_bootmem_phy_named_block_free(char *name, uint32_t flags)
cvmx_bootmem_unlock();
return named_block_ptr != NULL; /* 0 on failure, 1 on success */
}
+
+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
+ uint64_t max_addr,
+ uint64_t alignment,
+ char *name,
+ uint32_t flags)
+{
+ int64_t addr_allocated;
+ struct cvmx_bootmem_named_block_desc *named_block_desc_ptr;
+
+#ifdef DEBUG
+ cvmx_dprintf("cvmx_bootmem_phy_named_block_alloc: size: 0x%llx, min: "
+ "0x%llx, max: 0x%llx, align: 0x%llx, name: %s\n",
+ (unsigned long long)size,
+ (unsigned long long)min_addr,
+ (unsigned long long)max_addr,
+ (unsigned long long)alignment,
+ name);
+#endif
+ if (cvmx_bootmem_desc->major_version != 3) {
+ cvmx_dprintf("ERROR: Incompatible bootmem descriptor version: "
+ "%d.%d at addr: %p\n",
+ (int)cvmx_bootmem_desc->major_version,
+ (int)cvmx_bootmem_desc->minor_version,
+ cvmx_bootmem_desc);
+ return -1;
+ }
+
+ /*
+ * Take lock here, as name lookup/block alloc/name add need to
+ * be atomic.
+ */
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_spinlock_lock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
+
+ /* Get pointer to first available named block descriptor */
+ named_block_desc_ptr =
+ cvmx_bootmem_phy_named_block_find(NULL,
+ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
+
+ /*
+ * Check to see if name already in use, return error if name
+ * not available or no more room for blocks.
+ */
+ if (cvmx_bootmem_phy_named_block_find(name,
+ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING) || !named_block_desc_ptr) {
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
+ return -1;
+ }
+
+
+ /*
+ * Round size up to mult of minimum alignment bytes We need
+ * the actual size allocated to allow for blocks to be
+ * coallesced when they are freed. The alloc routine does the
+ * same rounding up on all allocations.
+ */
+ size = __ALIGN_MASK(size, (CVMX_BOOTMEM_ALIGNMENT_SIZE - 1));
+
+ addr_allocated = cvmx_bootmem_phy_alloc(size, min_addr, max_addr,
+ alignment,
+ flags | CVMX_BOOTMEM_FLAG_NO_LOCKING);
+ if (addr_allocated >= 0) {
+ named_block_desc_ptr->base_addr = addr_allocated;
+ named_block_desc_ptr->size = size;
+ strncpy(named_block_desc_ptr->name, name,
+ cvmx_bootmem_desc->named_block_name_len);
+ named_block_desc_ptr->name[cvmx_bootmem_desc->named_block_name_len - 1] = 0;
+ }
+
+ if (!(flags & CVMX_BOOTMEM_FLAG_NO_LOCKING))
+ cvmx_spinlock_unlock((cvmx_spinlock_t *)&(cvmx_bootmem_desc->lock));
+ return addr_allocated;
+}
diff --git a/arch/mips/include/asm/octeon/cvmx-bootmem.h b/arch/mips/include/asm/octeon/cvmx-bootmem.h
index 1cbe4b55889..8e708bdb43f 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,
* Returns 0 on failure,
* !0 on success
*/
+
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader, and assign it a name in the
+ * global named block table. (part of the cvmx_bootmem_descriptor_t structure)
+ * Named blocks can later be freed.
+ *
+ * @size: Size in bytes of block to allocate
+ * @alignment: Alignment required - must be power of 2
+ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ *
+ * Returns a pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named(uint64_t size, uint64_t alignment,
+ char *name);
+
+
+
+/**
+ * Allocate a block of memory from the free list that was passed
+ * to the application by the bootloader, and assign it a name in the
+ * global named block table. (part of the cvmx_bootmem_descriptor_t structure)
+ * Named blocks can later be freed.
+ *
+ * @size: Size in bytes of block to allocate
+ * @address: Physical address to allocate memory at. If this
+ * memory is not available, the allocation fails.
+ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN
+ * bytes
+ *
+ * Returns a pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named_address(uint64_t size, uint64_t address,
+ char *name);
+
+
+
+/**
+ * Allocate a block of memory from a specific range of the free list
+ * that was passed to the application by the bootloader, and assign it
+ * a name in the global named block table. (part of the
+ * cvmx_bootmem_descriptor_t structure) Named blocks can later be
+ * freed. If request cannot be satisfied within the address range
+ * specified, NULL is returned
+ *
+ * @size: Size in bytes of block to allocate
+ * @min_addr: minimum address of range
+ * @max_addr: maximum address of range
+ * @align: Alignment of memory to be allocated. (must be a power of 2)
+ * @name: name of block - must be less than CVMX_BOOTMEM_NAME_LEN bytes
+ *
+ * Returns a pointer to block of memory, NULL on error
+ */
+extern void *cvmx_bootmem_alloc_named_range(uint64_t size, uint64_t min_addr,
+ uint64_t max_addr, uint64_t align,
+ char *name);
+
extern int cvmx_bootmem_free_named(char *name);
/**
@@ -224,6 +282,33 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
uint32_t flags);
/**
+ * Allocates a named block of physical memory from the free list, at
+ * (optional) requested address and alignment.
+ *
+ * @param size size of region to allocate. All requests are rounded
+ * up to be a multiple CVMX_BOOTMEM_ALIGNMENT_SIZE
+ * bytes size
+ * @param min_addr Minimum address that block can occupy.
+ * @param max_addr Specifies the maximum address_min (inclusive) that
+ * the allocation can use.
+ * @param alignment Requested alignment of the block. If this
+ * alignment cannot be met, the allocation fails.
+ * This must be a power of 2. (Note: Alignment of
+ * CVMX_BOOTMEM_ALIGNMENT_SIZE bytes is required, and
+ * internally enforced. Requested alignments of less
+ * than CVMX_BOOTMEM_ALIGNMENT_SIZE are set to
+ * CVMX_BOOTMEM_ALIGNMENT_SIZE.)
+ * @param name name to assign to named block
+ * @param flags Flags to control options for the allocation.
+ *
+ * @return physical address of block allocated, or -1 on failure
+ */
+int64_t cvmx_bootmem_phy_named_block_alloc(uint64_t size, uint64_t min_addr,
+ uint64_t max_addr,
+ uint64_t alignment,
+ char *name, uint32_t flags);
+
+/**
* Finds a named memory block by name.
* Also used for finding an unused entry in the named block table.
*