4
* Manager for the Slave system memory. Slave system level memory is allocated
5
* through this modules.
7
* Copyright (C) 2008-2009 Texas Instruments, Inc.
9
* This package is free software; you can redistribute it and/or modify
10
* it under the terms of the GNU General Public License version 2 as
11
* published by the Free Software Foundation.
13
* THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
20
/* Standard headers */
21
#include <linux/types.h>
22
#include <linux/module.h>
23
#include <linux/slab.h>
25
#include <linux/vmalloc.h>
26
#include <syslink/atomic_linux.h>
27
#include <syslink/platform_mem.h>
28
/*#include <GateMutex.h>
33
/* Module level headers */
34
#include <sysmemmgr.h>
35
/*#include <BuddyPageAllocator.h>*/
38
/* =============================================================================
40
* =============================================================================
42
/*! @brief Event reserved for System memory manager */
43
#define SYSMEMMGR_EVENTNO 12
45
/* Macro to make a correct module magic number with ref_count */
46
#define SYSMEMMGR_MAKE_MAGICSTAMP(x) ((SYSMEMMGR_MODULEID << 12) | (x))
48
/* =============================================================================
50
* =============================================================================
52
/*! @brief Structure containing list of buffers. The list is kept sorted by
54
struct sysmemmgr_static_mem_struct {
55
struct sysmemmgr_static_mem_struct *next;
56
/*!< Pointer to next entry */
58
/*!< Address of this entry */
60
/*!< Size of this entry */
64
/*! @brief Static memory manager object. */
65
struct sysmemmgr_static_mem_mgr_obj {
66
struct sysmemmgr_static_mem_struct head;
67
/*!< Pointer to head entry */
68
struct sysmemmgr_static_mem_struct tail;
69
/*!< Pointer to tail entry */
73
* @brief Structure defining state object of system memory manager.
75
struct sysmemmgr_module_object {
77
/*!< Reference count */
78
struct sysmemmgr_static_mem_mgr_obj static_mem_obj;
79
/*!< Static memory manager object */
80
struct mutex *gate_handle;
81
/*!< Pointer to lock */
82
struct sysmemmgr_config cfg;
83
/*!< Current configuration values */
84
struct sysmemmgr_config default_cfg;
85
/*!< Default configuration values */
90
* @brief Object containing state of the system memory manager.
92
static struct sysmemmgr_module_object sysmemmgr_state = {
93
.default_cfg.sizeof_valloc = 0x100000,
94
.default_cfg.sizeof_palloc = 0x100000,
95
.default_cfg.page_size = 0x1000,
96
.default_cfg.event_no = SYSMEMMGR_EVENTNO,
100
/* =============================================================================
102
* =============================================================================
105
* ======== sysmemmgr_get_config ========
107
* Function to get the default values for configuration.
109
void sysmemmgr_get_config(struct sysmemmgr_config *config)
111
if (WARN_ON(config == NULL))
114
if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
115
SYSMEMMGR_MAKE_MAGICSTAMP(0),
116
SYSMEMMGR_MAKE_MAGICSTAMP(1)) == true)
117
memcpy((void *) config, (void *)(&sysmemmgr_state.default_cfg),
118
sizeof(struct sysmemmgr_config));
120
memcpy((void *) config, (void *)(&sysmemmgr_state.cfg),
121
sizeof(struct sysmemmgr_config));
126
pr_err("sysmemmgr_get_config: Argument of type "
127
"(struct sysmemmgr_config *) passed is NULL\n");
133
* ======== sysmemmgr_setup ========
135
* Function to get the default values for configuration.
137
int sysmemmgr_setup(struct sysmemmgr_config *config)
140
struct sysmemmgr_static_mem_mgr_obj *smmObj = NULL;
142
/* This sets the ref_count variable is not initialized, upper 16 bits is
143
* written with module Id to ensure correctness of ref_count variable.
145
atomic_cmpmask_and_set(&sysmemmgr_state.ref_count,
146
SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(0));
148
if (atomic_inc_return(&sysmemmgr_state.ref_count) != \
149
SYSMEMMGR_MAKE_MAGICSTAMP(1)) {
150
status = SYSMEMMGR_S_ALREADYSETUP;
154
if (WARN_ON(config == NULL)) {
155
/* Config parameters are not provided */
159
if (WARN_ON((config->static_virt_base_addr == (u32) NULL)
160
&& (config->static_mem_size != 0))) {
161
/* Virtual Base address of static memory region is NULL */
165
if (WARN_ON((config->static_phys_base_addr == (u32) NULL)
166
&& (config->static_mem_size != 0))) {
167
/*Physical Base address of static memory region is NULL */
172
/* Copy the config parameters to the module state */
173
memcpy((void *)(&sysmemmgr_state.cfg), (void *) config,
174
sizeof(struct sysmemmgr_config));
176
/* Create the static memory allocator */
177
if (config->static_mem_size != 0) {
178
smmObj = &sysmemmgr_state.static_mem_obj;
179
smmObj->head.address = config->static_virt_base_addr;
180
smmObj->head.size = 0;
181
smmObj->tail.address = (config->static_virt_base_addr + \
182
config->static_mem_size);
183
smmObj->tail.size = 0;
184
smmObj->head.next = &smmObj->tail;
185
smmObj->tail.next = NULL;
188
/* Create the lock */
189
sysmemmgr_state.gate_handle = kzalloc(sizeof(struct mutex), GFP_KERNEL);
190
if (sysmemmgr_state.gate_handle == NULL) {
191
/* Failed to create gate handle */
198
pr_err("sysmemmgr_setup: Failed to create gate handle\n");
202
pr_err("sysmemmgr_setup: Physical Base address of static "
203
"memory region is NULL\n");
207
pr_err("sysmemmgr_setup: Virtual Base address of static "
208
"memory region is NULL\n");
212
pr_err("sysmemmgr_setup: Argument of type "
213
"(struct sysmemmgr_config *) passed is NULL\n");
218
atomic_set(&sysmemmgr_state.ref_count,
219
SYSMEMMGR_MAKE_MAGICSTAMP(0));
226
* ======== sysmemmgr_destroy ========
228
* Function to finalize the system memory manager module.
230
int sysmemmgr_destroy(void)
234
if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
235
SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
237
/*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
239
status = SYSMEMMGR_E_INVALIDSTATE;
243
if (atomic_dec_return(&sysmemmgr_state.ref_count) == \
244
SYSMEMMGR_MAKE_MAGICSTAMP(0)) {
245
/* Delete the lock */
246
kfree(sysmemmgr_state.gate_handle);
251
pr_err("sysmemgr_destroy: Module was not initialized\n");
257
* ======== sysmemmgr_alloc ========
259
* Function to allocate a memory block.
261
void *sysmemmgr_alloc(u32 size, enum sysmemmgr_allocflag flag)
264
struct sysmemmgr_static_mem_mgr_obj *smObj = NULL;
265
struct sysmemmgr_static_mem_struct *ptr = NULL;
266
struct sysmemmgr_static_mem_struct *newptr = NULL;
267
void *ret_ptr = NULL;
269
if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
270
SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
272
/*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
274
status = SYSMEMMGR_E_INVALIDSTATE;
278
if ((flag & sysmemmgr_allocflag_physical) && \
279
!(flag & sysmemmgr_allocflag_dma)) {
280
/* TBD: works with DMM
281
ret_ptr = platform_mem_alloc (size, 0,
282
MemoryOS_MemTypeFlags_Physical); */
283
if (ret_ptr == NULL) {
284
if (sysmemmgr_state.cfg.static_mem_size == 0) {
285
/* Memory pool is not configured. */
290
smObj = &sysmemmgr_state.static_mem_obj;
292
while (ptr && ptr->next) {
293
if (((ptr->next->address - \
294
(ptr->address + ptr->size)) >= size))
299
if (ptr->next == NULL) {
305
sizeof(struct sysmemmgr_static_mem_struct));
306
if (newptr != NULL) {
307
newptr->address = ptr->address + ptr->size;
309
newptr->next = ptr->next;
311
ret_ptr = (void *) newptr->address;
319
if (flag & sysmemmgr_allocflag_physical) {
320
ret_ptr = kmalloc(size, GFP_KERNEL);
326
if (flag & sysmemmgr_allocflag_dma) {
327
ret_ptr = kmalloc(size, GFP_KERNEL | GFP_DMA);
333
ret_ptr = vmalloc(size);
334
if (ret_ptr == NULL) {
340
pr_err("sysmemgr_alloc: Module was not initialized\n");
342
if (WARN_ON(ret_ptr == NULL))
343
pr_err("sysmemmgr_alloc: Allocation failed\n");
349
* ======== sysmemmgr_free ========
351
* Function to de-allocate a previous allocated memory block.
353
int sysmemmgr_free(void *blk, u32 size, enum sysmemmgr_allocflag flag)
356
struct sysmemmgr_static_mem_mgr_obj *smObj = NULL;
357
struct sysmemmgr_static_mem_struct *ptr = NULL;
358
struct sysmemmgr_static_mem_struct *prev = NULL;
360
if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
361
SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
363
/*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
365
status = SYSMEMMGR_E_INVALIDSTATE;
369
if ((flag & sysmemmgr_allocflag_physical) && \
370
!(flag & sysmemmgr_allocflag_dma)) {
371
if (((u32) blk >= sysmemmgr_state.cfg.static_virt_base_addr)
373
(sysmemmgr_state.cfg.static_virt_base_addr + \
374
sysmemmgr_state.cfg.static_mem_size))) {
375
smObj = &sysmemmgr_state.static_mem_obj;
377
while (ptr && ptr->next) {
378
if (ptr->next->address == (u32) blk)
384
prev->next = ptr->next;
391
} else if (flag & sysmemmgr_allocflag_physical) {
393
} else if (flag & sysmemmgr_allocflag_dma) {
401
pr_err("sysmemgr_free: Module was not initialized\n");
407
* ======== sysmemmgr_setup ========
409
* Function to translate an address among different address spaces.
411
void *sysmemmgr_translate(void *src_addr, enum sysmemmgr_xltflag flags)
413
void *ret_ptr = NULL;
416
case sysmemmgr_xltflag_kvirt2phys:
418
if (((u32) src_addr >= \
419
sysmemmgr_state.cfg.static_virt_base_addr) && \
421
(sysmemmgr_state.cfg.static_virt_base_addr + \
422
sysmemmgr_state.cfg.static_mem_size))) {
423
ret_ptr = (void *)(((u32) src_addr - \
424
sysmemmgr_state.cfg.static_virt_base_addr) + \
425
(sysmemmgr_state.cfg.static_phys_base_addr));
427
ret_ptr = platform_mem_translate(src_addr,
428
PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS);
433
case sysmemmgr_xltflag_phys2kvirt:
435
if (((u32) src_addr >= \
436
sysmemmgr_state.cfg.static_phys_base_addr) && \
438
(sysmemmgr_state.cfg.static_phys_base_addr + \
439
sysmemmgr_state.cfg.static_mem_size))) {
440
ret_ptr = (void *)(((u32) src_addr - \
441
sysmemmgr_state.cfg.static_phys_base_addr) + \
442
(sysmemmgr_state.cfg.static_virt_base_addr));
444
ret_ptr = platform_mem_translate(src_addr,
445
PLATFORM_MEM_XLT_FLAGS_PHYS2VIRT);
452
pr_err("sysmemmgr_translate: Unhandled translation flag\n");