~ubuntu-branches/ubuntu/precise/linux-ti-omap4/precise

« back to all changes in this revision

Viewing changes to drivers/dsp/syslink/multicore_ipc/sysmemmgr.c

  • Committer: Package Import Robot
  • Author(s): Paolo Pisati, Paolo Pisati, Tim Gardner
  • Date: 2012-03-16 12:40:30 UTC
  • Revision ID: package-import@ubuntu.com-20120316124030-3ggslc72c897vl5k
Tags: 3.2.0-1409.12
[ Paolo Pisati ]

* [Config] updateconfigs following tilt import
* TI BSP update: kernel-tilt/tilt-3.2 @ c1db0c73d4f2185711d9d34a0c3bb55986781349

[ Tim Gardner ]

* [Config] Move kernels to Section: kernel
  - LP: #499557

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  sysmemmgr.c
 
3
 *
 
4
 *  Manager for the Slave system memory. Slave system level memory is allocated
 
5
 *  through this modules.
 
6
 *
 
7
 *  Copyright (C) 2008-2009 Texas Instruments, Inc.
 
8
 *
 
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.
 
12
 *
 
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
 
16
 *  PURPOSE.
 
17
 */
 
18
 
 
19
 
 
20
/* Standard headers */
 
21
#include <linux/types.h>
 
22
#include <linux/module.h>
 
23
#include <linux/slab.h>
 
24
/* Utils headers */
 
25
#include <linux/vmalloc.h>
 
26
#include <syslink/atomic_linux.h>
 
27
#include <syslink/platform_mem.h>
 
28
/*#include <GateMutex.h>
 
29
#include <Memory.h>
 
30
#include <Trace.h>*/
 
31
 
 
32
 
 
33
/* Module level headers */
 
34
#include <sysmemmgr.h>
 
35
/*#include <BuddyPageAllocator.h>*/
 
36
 
 
37
 
 
38
/* =============================================================================
 
39
 * Macros
 
40
 * =============================================================================
 
41
 */
 
42
/*! @brief Event reserved for System memory manager */
 
43
#define SYSMEMMGR_EVENTNO               12
 
44
 
 
45
/* Macro to make a correct module magic number with ref_count */
 
46
#define SYSMEMMGR_MAKE_MAGICSTAMP(x)    ((SYSMEMMGR_MODULEID << 12) | (x))
 
47
 
 
48
/* =============================================================================
 
49
 * Structs & Enums
 
50
 * =============================================================================
 
51
 */
 
52
/*! @brief Structure containing list of buffers. The list is kept sorted by
 
53
 * address. */
 
54
struct sysmemmgr_static_mem_struct {
 
55
        struct sysmemmgr_static_mem_struct *next;
 
56
        /*!< Pointer to next entry */
 
57
        u32 address;
 
58
        /*!< Address of this entry */
 
59
        u32 size;
 
60
        /*!< Size of this entry */
 
61
};
 
62
 
 
63
 
 
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 */
 
70
};
 
71
 
 
72
/*!
 
73
 *  @brief  Structure defining state object of system memory manager.
 
74
 */
 
75
struct sysmemmgr_module_object {
 
76
        atomic_t ref_count;
 
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 */
 
86
};
 
87
 
 
88
 
 
89
/*!
 
90
 *  @brief  Object containing state of the system memory manager.
 
91
 */
 
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,
 
97
};
 
98
 
 
99
 
 
100
/* =============================================================================
 
101
 * APIS
 
102
 * =============================================================================
 
103
 */
 
104
/*
 
105
 * ======== sysmemmgr_get_config ========
 
106
 *  Purpose:
 
107
 *  Function to get the default values for configuration.
 
108
 */
 
109
void sysmemmgr_get_config(struct sysmemmgr_config *config)
 
110
{
 
111
        if (WARN_ON(config == NULL))
 
112
                goto err_exit;
 
113
 
 
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));
 
119
        else
 
120
                memcpy((void *) config, (void *)(&sysmemmgr_state.cfg),
 
121
                                sizeof(struct sysmemmgr_config));
 
122
 
 
123
        return;
 
124
 
 
125
err_exit:
 
126
        pr_err("sysmemmgr_get_config: Argument of type "
 
127
                "(struct sysmemmgr_config *) passed is NULL\n");
 
128
        return;
 
129
}
 
130
 
 
131
 
 
132
/*
 
133
 * ======== sysmemmgr_setup ========
 
134
 *  Purpose:
 
135
 *  Function to get the default values for configuration.
 
136
 */
 
137
int sysmemmgr_setup(struct sysmemmgr_config *config)
 
138
{
 
139
        int status = 0;
 
140
        struct sysmemmgr_static_mem_mgr_obj *smmObj = NULL;
 
141
 
 
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.
 
144
         */
 
145
        atomic_cmpmask_and_set(&sysmemmgr_state.ref_count,
 
146
                SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(0));
 
147
 
 
148
        if (atomic_inc_return(&sysmemmgr_state.ref_count) != \
 
149
                        SYSMEMMGR_MAKE_MAGICSTAMP(1)) {
 
150
                status = SYSMEMMGR_S_ALREADYSETUP;
 
151
                goto exit;
 
152
        }
 
153
 
 
154
        if (WARN_ON(config == NULL)) {
 
155
                /* Config parameters are not provided */
 
156
                status = -EINVAL;
 
157
                goto err_config;
 
158
        }
 
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 */
 
162
                status = -EINVAL;
 
163
                goto err_virt_addr;
 
164
        }
 
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 */
 
168
                status = -EINVAL;
 
169
                goto err_phys_addr;
 
170
        }
 
171
 
 
172
        /* Copy the config parameters to the module state */
 
173
        memcpy((void *)(&sysmemmgr_state.cfg), (void *) config,
 
174
                sizeof(struct sysmemmgr_config));
 
175
 
 
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;
 
186
        }
 
187
 
 
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 */
 
192
                status = -ENOMEM;
 
193
                goto err_mem_gate;
 
194
        }
 
195
        return 0;
 
196
 
 
197
err_mem_gate:
 
198
        pr_err("sysmemmgr_setup: Failed to create gate handle\n");
 
199
        goto exit;
 
200
 
 
201
err_phys_addr:
 
202
        pr_err("sysmemmgr_setup: Physical Base address of static "
 
203
                "memory region is NULL\n");
 
204
        goto exit;
 
205
 
 
206
err_virt_addr:
 
207
        pr_err("sysmemmgr_setup: Virtual Base address of static "
 
208
                "memory region is NULL\n");
 
209
        goto exit;
 
210
 
 
211
err_config:
 
212
        pr_err("sysmemmgr_setup: Argument of type "
 
213
                "(struct sysmemmgr_config *) passed is NULL\n");
 
214
        goto exit;
 
215
 
 
216
exit:
 
217
        if (status < 0) {
 
218
                atomic_set(&sysmemmgr_state.ref_count,
 
219
                        SYSMEMMGR_MAKE_MAGICSTAMP(0));
 
220
        }
 
221
        return status;
 
222
}
 
223
 
 
224
 
 
225
/*
 
226
 * ======== sysmemmgr_destroy ========
 
227
 *  Purpose:
 
228
 *  Function to finalize the system memory manager module.
 
229
 */
 
230
int sysmemmgr_destroy(void)
 
231
{
 
232
        int status = 0;
 
233
 
 
234
        if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
 
235
                SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
 
236
                true) {
 
237
                /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
 
238
                 *  initialized */
 
239
                status = SYSMEMMGR_E_INVALIDSTATE;
 
240
                goto err_exit;
 
241
        }
 
242
 
 
243
        if (atomic_dec_return(&sysmemmgr_state.ref_count) == \
 
244
                SYSMEMMGR_MAKE_MAGICSTAMP(0)) {
 
245
                /* Delete the lock */
 
246
                kfree(sysmemmgr_state.gate_handle);
 
247
        }
 
248
        return 0;
 
249
 
 
250
err_exit:
 
251
        pr_err("sysmemgr_destroy: Module was not initialized\n");
 
252
        return status;
 
253
}
 
254
 
 
255
 
 
256
/*
 
257
 * ======== sysmemmgr_alloc ========
 
258
 *  Purpose:
 
259
 *  Function to allocate a memory block.
 
260
 */
 
261
void *sysmemmgr_alloc(u32 size, enum sysmemmgr_allocflag flag)
 
262
{
 
263
        int status = 0;
 
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;
 
268
 
 
269
        if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
 
270
                SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
 
271
                true) {
 
272
                /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
 
273
                 *  initialized */
 
274
                status = SYSMEMMGR_E_INVALIDSTATE;
 
275
                goto err_exit;
 
276
        }
 
277
 
 
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. */
 
286
                                status = -ENOMEM;
 
287
                                goto exit;
 
288
                        }
 
289
 
 
290
                        smObj = &sysmemmgr_state.static_mem_obj;
 
291
                        ptr = &smObj->head;
 
292
                        while (ptr && ptr->next) {
 
293
                                if (((ptr->next->address - \
 
294
                                        (ptr->address + ptr->size)) >= size))
 
295
                                        break;
 
296
                                ptr = ptr->next;
 
297
                        }
 
298
 
 
299
                        if (ptr->next == NULL) {
 
300
                                status = -ENOMEM;
 
301
                                goto exit;
 
302
                        }
 
303
 
 
304
                        newptr = vmalloc(
 
305
                                sizeof(struct sysmemmgr_static_mem_struct));
 
306
                        if (newptr != NULL) {
 
307
                                newptr->address = ptr->address + ptr->size;
 
308
                                newptr->size = size;
 
309
                                newptr->next = ptr->next;
 
310
                                ptr->next = newptr;
 
311
                                ret_ptr = (void *) newptr->address;
 
312
                        } else {
 
313
                                status = -ENOMEM;
 
314
                        }
 
315
                }
 
316
                goto exit;
 
317
        }
 
318
 
 
319
        if (flag & sysmemmgr_allocflag_physical) {
 
320
                ret_ptr = kmalloc(size, GFP_KERNEL);
 
321
                if (ret_ptr == NULL)
 
322
                        status = -ENOMEM;
 
323
                goto exit;
 
324
        }
 
325
 
 
326
        if (flag & sysmemmgr_allocflag_dma) {
 
327
                ret_ptr = kmalloc(size, GFP_KERNEL | GFP_DMA);
 
328
                if (ret_ptr == NULL)
 
329
                        status = -ENOMEM;
 
330
                goto exit;
 
331
        }
 
332
 
 
333
        ret_ptr = vmalloc(size);
 
334
        if (ret_ptr == NULL) {
 
335
                status = -ENOMEM;
 
336
                goto exit;
 
337
        }
 
338
 
 
339
err_exit:
 
340
        pr_err("sysmemgr_alloc: Module was not initialized\n");
 
341
exit:
 
342
        if (WARN_ON(ret_ptr == NULL))
 
343
                pr_err("sysmemmgr_alloc: Allocation failed\n");
 
344
        return ret_ptr;
 
345
}
 
346
 
 
347
 
 
348
/*
 
349
 * ======== sysmemmgr_free ========
 
350
 *  Purpose:
 
351
 *  Function to de-allocate a previous allocated memory block.
 
352
 */
 
353
int sysmemmgr_free(void *blk, u32 size, enum sysmemmgr_allocflag flag)
 
354
{
 
355
        int status = 0;
 
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;
 
359
 
 
360
        if (atomic_cmpmask_and_lt(&(sysmemmgr_state.ref_count),
 
361
                SYSMEMMGR_MAKE_MAGICSTAMP(0), SYSMEMMGR_MAKE_MAGICSTAMP(1)) == \
 
362
                true) {
 
363
                /*! @retval SYSMEMMGR_E_INVALIDSTATE Module was not
 
364
                 *  initialized */
 
365
                status = SYSMEMMGR_E_INVALIDSTATE;
 
366
                goto err_exit;
 
367
        }
 
368
 
 
369
        if ((flag & sysmemmgr_allocflag_physical) && \
 
370
                !(flag & sysmemmgr_allocflag_dma)) {
 
371
                if (((u32) blk >= sysmemmgr_state.cfg.static_virt_base_addr)
 
372
                        && ((u32) blk < \
 
373
                        (sysmemmgr_state.cfg.static_virt_base_addr + \
 
374
                        sysmemmgr_state.cfg.static_mem_size))) {
 
375
                        smObj = &sysmemmgr_state.static_mem_obj;
 
376
                        ptr = &smObj->head;
 
377
                        while (ptr && ptr->next) {
 
378
                                if (ptr->next->address == (u32) blk)
 
379
                                        break;
 
380
                                ptr = ptr->next;
 
381
                        }
 
382
                        prev = ptr;
 
383
                        ptr  = ptr->next;
 
384
                        prev->next = ptr->next;
 
385
 
 
386
                        /* Free the node */
 
387
                        vfree(ptr);
 
388
                } else {
 
389
                        kfree(blk);
 
390
                }
 
391
        } else if (flag & sysmemmgr_allocflag_physical) {
 
392
                kfree(blk);
 
393
        } else if (flag & sysmemmgr_allocflag_dma) {
 
394
                kfree(blk);
 
395
        } else {
 
396
                vfree(blk);
 
397
        }
 
398
        return 0;
 
399
 
 
400
err_exit:
 
401
        pr_err("sysmemgr_free: Module was not initialized\n");
 
402
        return status;
 
403
}
 
404
 
 
405
 
 
406
/*
 
407
 * ======== sysmemmgr_setup ========
 
408
 *  Purpose:
 
409
 *  Function to translate an address among different address spaces.
 
410
 */
 
411
void *sysmemmgr_translate(void *src_addr, enum sysmemmgr_xltflag flags)
 
412
{
 
413
        void *ret_ptr = NULL;
 
414
 
 
415
        switch (flags) {
 
416
        case sysmemmgr_xltflag_kvirt2phys:
 
417
        {
 
418
                if (((u32) src_addr >= \
 
419
                        sysmemmgr_state.cfg.static_virt_base_addr) && \
 
420
                        ((u32) src_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));
 
426
                } else {
 
427
                        ret_ptr = platform_mem_translate(src_addr,
 
428
                                        PLATFORM_MEM_XLT_FLAGS_VIRT2PHYS);
 
429
                }
 
430
        }
 
431
        break;
 
432
 
 
433
        case sysmemmgr_xltflag_phys2kvirt:
 
434
        {
 
435
                if (((u32) src_addr >= \
 
436
                        sysmemmgr_state.cfg.static_phys_base_addr) && \
 
437
                        ((u32) src_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));
 
443
                } else {
 
444
                        ret_ptr = platform_mem_translate(src_addr,
 
445
                                        PLATFORM_MEM_XLT_FLAGS_PHYS2VIRT);
 
446
                }
 
447
        }
 
448
        break;
 
449
 
 
450
        default:
 
451
        {
 
452
                pr_err("sysmemmgr_translate: Unhandled translation flag\n");
 
453
        }
 
454
        break;
 
455
        }
 
456
 
 
457
        return ret_ptr;
 
458
}