mirror of
				git://git.openwrt.org/openwrt/openwrt.git
				synced 2025-10-30 21:44:27 -04:00 
			
		
		
		
	
		
			
				
	
	
		
			224 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
			
		
		
	
	
			224 lines
		
	
	
		
			7.8 KiB
		
	
	
	
		
			Diff
		
	
	
	
	
	
| The MGMT ethernet driver uses these new functions.
 | |
| 
 | |
| Signed-off-by: David Daney <ddaney@caviumnetworks.com>
 | |
| ---
 | |
|  arch/mips/cavium-octeon/executive/cvmx-bootmem.c |  101 ++++++++++++++++++++++
 | |
|  arch/mips/include/asm/octeon/cvmx-bootmem.h      |   85 ++++++++++++++++++
 | |
|  2 files changed, 186 insertions(+), 0 deletions(-)
 | |
| 
 | |
| --- a/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
 | |
| +++ b/arch/mips/cavium-octeon/executive/cvmx-bootmem.c
 | |
| @@ -97,6 +97,32 @@ void *cvmx_bootmem_alloc(uint64_t size, 
 | |
|  	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);
 | |
| +}
 | |
| +
 | |
|  int cvmx_bootmem_free_named(char *name)
 | |
|  {
 | |
|  	return cvmx_bootmem_phy_named_block_free(name, 0);
 | |
| @@ -584,3 +610,78 @@ int cvmx_bootmem_phy_named_block_free(ch
 | |
|  	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;
 | |
| +}
 | |
| --- 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(ui
 | |
|   * 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 
 | |
|  			       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.
 | |
|   *
 |