]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - processor-sdk/open-amp.git/blob - lib/common/sh_mem.c
hil: add API to enable vdev IPI
[processor-sdk/open-amp.git] / lib / common / sh_mem.c
1 /*
2  * Copyright (c) 2014, Mentor Graphics Corporation
3  * All rights reserved.
4  * Copyright (c) 2016 Freescale Semiconductor, Inc. All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice,
10  *    this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  *    this list of conditions and the following disclaimer in the documentation
13  *    and/or other materials provided with the distribution.
14  * 3. Neither the name of Mentor Graphics Corporation nor the names of its
15  *    contributors may be used to endorse or promote products derived from this
16  *    software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
22  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28  * POSSIBILITY OF SUCH DAMAGE.
29  */
30 /**************************************************************************
31  * FILE NAME
32  *
33  *       sh_mem.c
34  *
35  * COMPONENT
36  *
37  *         OpenAMP stack.
38  *
39  * DESCRIPTION
40  *
41  *       Source file for fixed buffer size memory management service. Currently
42  *       it is only being used to manage shared memory.
43  *
44  **************************************************************************/
45 #include <string.h>
46 #include "openamp/sh_mem.h"
47 #include "metal/alloc.h"
49 /**
50  * sh_mem_create_pool
51  *
52  * Creates new memory pool with the given parameters.
53  *
54  * @param start_addr - start address of the memory region
55  * @param size       - size of the memory
56  * @param buff_size  - fixed buffer size
57  *
58  * @return - pointer to memory pool
59  *
60  */
61 struct sh_mem_pool *sh_mem_create_pool(void *start_addr, unsigned int size,
62                                        unsigned int buff_size)
63 {
64         struct sh_mem_pool *mem_pool;
65         int pool_size;
66         int num_buffs, bmp_size;
68         if (!start_addr || !size || !buff_size)
69                 return NULL;
71         /* Word align the buffer size */
72         buff_size = WORD_ALIGN(buff_size);
74         /* Get number of buffers. */
75         num_buffs = (size / buff_size) + ((size % buff_size) == 0 ? 0 : 1);
77         /*
78          * Size of the bitmap required to maintain buffers info. One word(32 bit) can
79          * keep track of 32 buffers.
80          */
81         bmp_size = (num_buffs / BITMAP_WORD_SIZE)
82             + ((num_buffs % BITMAP_WORD_SIZE) == 0 ? 0 : 1);
84         /* Total size required for pool control block. */
85         pool_size = sizeof(struct sh_mem_pool) + BITMAP_WORD_SIZE * bmp_size;
87         /* Create pool control block. */
88         mem_pool = metal_allocate_memory(pool_size);
90         if (mem_pool) {
91                 /* Initialize pool parameters */
92                 memset(mem_pool, 0x00, pool_size);
93                 metal_mutex_init(&mem_pool->lock);
94                 mem_pool->start_addr = start_addr;
95                 mem_pool->buff_size = buff_size;
96                 mem_pool->bmp_size = bmp_size;
97                 mem_pool->total_buffs = num_buffs;
98         }
100         return mem_pool;
103 /**
104  * sh_mem_get_buffer
105  *
106  * Allocates fixed size buffer from the given memory pool.
107  *
108  * @param pool - pointer to memory pool
109  *
110  * @return - pointer to allocated buffer
111  *
112  */
113 void *sh_mem_get_buffer(struct sh_mem_pool *pool)
115         void *buff = NULL;
116         int idx, bit_idx;
118         if (!pool)
119                 return NULL;
121         metal_mutex_acquire(&pool->lock);
123         if (pool->used_buffs >= pool->total_buffs) {
124                 metal_mutex_release(&pool->lock);
125                 return NULL;
126         }
128         for (idx = 0; idx < pool->bmp_size; idx++) {
129                 /*
130                  * Find the first 0 bit in the buffers bitmap. The 0th bit
131                  * represents a free buffer.
132                  */
133                 bit_idx = get_first_zero_bit(
134                         *(unsigned long*)SH_MEM_POOL_LOCATE_BITMAP(pool,idx));
135                 if (bit_idx >= 0) {
136                         /* Set bit to mark it as consumed. */
137                         *(unsigned long*)(SH_MEM_POOL_LOCATE_BITMAP(pool,idx))
138                                 |= ((unsigned long)1 << (unsigned long)bit_idx);
139                         buff = (char *)pool->start_addr +
140                             pool->buff_size * (idx * BITMAP_WORD_SIZE +
141                                                bit_idx);
142                         pool->used_buffs++;
143                         break;
144                 }
145         }
147         metal_mutex_release(&pool->lock);
149         return buff;
152 /**
153  * sh_mem_free_buffer
154  *
155  * Frees the given buffer.
156  *
157  * @param pool - pointer to memory pool
158  * @param buff - pointer to buffer
159  *
160  * @return  - none
161  */
162 void sh_mem_free_buffer(void *buff, struct sh_mem_pool *pool)
164         unsigned long *bitmask;
165         int bmp_idx, bit_idx, buff_idx;
167         if (!pool || !buff)
168                 return;
170         /* Acquire the pool lock */
171         metal_mutex_acquire(&pool->lock);
173         /* Map the buffer address to its index. */
174         buff_idx = ((char *)buff - (char *)pool->start_addr) / pool->buff_size;
176         /* Translate the buffer index to bitmap index. */
177         bmp_idx = buff_idx / BITMAP_WORD_SIZE;
178         bit_idx = buff_idx % BITMAP_WORD_SIZE;
179         bitmask = (unsigned long*)(SH_MEM_POOL_LOCATE_BITMAP(pool, bmp_idx));
181         /* Mark the buffer as free */
182         *bitmask ^= (1 << bit_idx);
184         pool->used_buffs--;
186         /* Release the pool lock. */
187         metal_mutex_release(&pool->lock);
191 /**
192  * sh_mem_delete_pool
193  *
194  * Deletes the given memory pool.
195  *
196  * @param pool - pointer to memory pool
197  *
198  * @return  - none
199  */
200 void sh_mem_delete_pool(struct sh_mem_pool *pool)
203         if (pool) {
204                 metal_mutex_deinit(&pool->lock);
205                 metal_free_memory(pool);
206         }
209 /**
210  * get_first_zero_bit
211  *
212  * Provides position of first 0 bit in a 32 bit value
213  *
214  * @param value - given value
215  *
216  * @return - 0th bit position
217  */
218 int get_first_zero_bit(unsigned long value)
220         unsigned int idx = 0;
221         value = ((~value) & (value + 1));
222         while (value) {
223                 idx++;
224                 value >>= 1;
225         }
226         return ((int)idx-1);