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