|
@@ -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;
|
|
|
+}
|