Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6fa044ab authored by David Daney's avatar David Daney Committed by Ralf Baechle
Browse files

MIPS: Add named alloc functions to OCTEON boot monitor memory allocator.



The various Octeon ethernet drivers use these new functions.

Signed-off-by: default avatarDavid Daney <ddaney@caviumnetworks.com>
Signed-off-by: default avatarRalf Baechle <ralf@linux-mips.org>
parent ce65cc8f
Loading
Loading
Loading
Loading
+104 −0
Original line number Diff line number Diff line
@@ -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;
}
+85 −0
Original line number Diff line number Diff line
@@ -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);

/**
@@ -223,6 +281,33 @@ int64_t cvmx_bootmem_phy_alloc(uint64_t req_size, uint64_t address_min,
			       uint64_t address_max, uint64_t alignment,
			       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.