aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorFelipe Contreras <felipe.contreras@gmail.com>2010-11-10 13:09:04 -0500
committerOmar Ramirez Luna <omar.ramirez@ti.com>2010-11-10 19:34:42 -0500
commit677f2ded8179c8d5d49cfea0d5217691182b48f2 (patch)
treecd86a5425c72e8bc8e9c930bea43488c1253223d /drivers
parent3fc59af631643c9ea2d600e5a07b3fcaf4e38cbd (diff)
Revert "staging: tidspbridge - remove dmm custom module"
This reverts commit 2ab573487a98c06fdfb34308f641f09369d61fa2. Signed-off-by: Felipe Contreras <felipe.contreras@gmail.com> Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/staging/tidspbridge/Makefile2
-rw-r--r--drivers/staging/tidspbridge/core/tiomap3430.c1
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dev.h24
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/dmm.h75
-rw-r--r--drivers/staging/tidspbridge/include/dspbridge/drv.h6
-rw-r--r--drivers/staging/tidspbridge/pmgr/dev.c61
-rw-r--r--drivers/staging/tidspbridge/pmgr/dmm.c533
-rw-r--r--drivers/staging/tidspbridge/rmgr/node.c28
-rw-r--r--drivers/staging/tidspbridge/rmgr/proc.c23
9 files changed, 747 insertions, 6 deletions
diff --git a/drivers/staging/tidspbridge/Makefile b/drivers/staging/tidspbridge/Makefile
index 50decc2935c..37bd3bcc03a 100644
--- a/drivers/staging/tidspbridge/Makefile
+++ b/drivers/staging/tidspbridge/Makefile
@@ -5,7 +5,7 @@ libcore = core/chnl_sm.o core/msg_sm.o core/io_sm.o core/tiomap3430.o \
5 core/tiomap3430_pwr.o core/tiomap_io.o core/dsp-mmu.o \ 5 core/tiomap3430_pwr.o core/tiomap_io.o core/dsp-mmu.o \
6 core/ue_deh.o core/wdt.o core/dsp-clock.o core/sync.o 6 core/ue_deh.o core/wdt.o core/dsp-clock.o core/sync.o
7libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/dspapi.o \ 7libpmgr = pmgr/chnl.o pmgr/io.o pmgr/msg.o pmgr/cod.o pmgr/dev.o pmgr/dspapi.o \
8 pmgr/cmm.o pmgr/dbll.o 8 pmgr/dmm.o pmgr/cmm.o pmgr/dbll.o
9librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \ 9librmgr = rmgr/dbdcd.o rmgr/disp.o rmgr/drv.o rmgr/mgr.o rmgr/node.o \
10 rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \ 10 rmgr/proc.o rmgr/pwr.o rmgr/rmm.o rmgr/strm.o rmgr/dspdrv.o \
11 rmgr/nldr.o rmgr/drv_interface.o 11 rmgr/nldr.o rmgr/drv_interface.o
diff --git a/drivers/staging/tidspbridge/core/tiomap3430.c b/drivers/staging/tidspbridge/core/tiomap3430.c
index d302e30443a..1425c50e72b 100644
--- a/drivers/staging/tidspbridge/core/tiomap3430.c
+++ b/drivers/staging/tidspbridge/core/tiomap3430.c
@@ -46,6 +46,7 @@
46/* ----------------------------------- Platform Manager */ 46/* ----------------------------------- Platform Manager */
47#include <dspbridge/dev.h> 47#include <dspbridge/dev.h>
48#include <dspbridge/dspapi.h> 48#include <dspbridge/dspapi.h>
49#include <dspbridge/dmm.h>
49#include <dspbridge/wdt.h> 50#include <dspbridge/wdt.h>
50 51
51/* ----------------------------------- Local */ 52/* ----------------------------------- Local */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dev.h b/drivers/staging/tidspbridge/include/dspbridge/dev.h
index 9bdd48f5742..357458fadd2 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/dev.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/dev.h
@@ -27,6 +27,7 @@
27#include <dspbridge/nodedefs.h> 27#include <dspbridge/nodedefs.h>
28#include <dspbridge/dispdefs.h> 28#include <dspbridge/dispdefs.h>
29#include <dspbridge/dspdefs.h> 29#include <dspbridge/dspdefs.h>
30#include <dspbridge/dmm.h>
30#include <dspbridge/host_os.h> 31#include <dspbridge/host_os.h>
31 32
32/* ----------------------------------- This */ 33/* ----------------------------------- This */
@@ -233,6 +234,29 @@ extern int dev_get_cmm_mgr(struct dev_object *hdev_obj,
233 struct cmm_object **mgr); 234 struct cmm_object **mgr);
234 235
235/* 236/*
237 * ======== dev_get_dmm_mgr ========
238 * Purpose:
239 * Retrieve the handle to the dynamic memory manager created for this
240 * device.
241 * Parameters:
242 * hdev_obj: Handle to device object created with
243 * dev_create_device().
244 * *mgr: Ptr to location to store handle.
245 * Returns:
246 * 0: Success.
247 * -EFAULT: Invalid hdev_obj.
248 * Requires:
249 * mgr != NULL.
250 * DEV Initialized.
251 * Ensures:
252 * 0: *mgr contains a handle to a channel manager object,
253 * or NULL.
254 * else: *mgr is NULL.
255 */
256extern int dev_get_dmm_mgr(struct dev_object *hdev_obj,
257 struct dmm_object **mgr);
258
259/*
236 * ======== dev_get_cod_mgr ======== 260 * ======== dev_get_cod_mgr ========
237 * Purpose: 261 * Purpose:
238 * Retrieve the COD manager create for this device. 262 * Retrieve the COD manager create for this device.
diff --git a/drivers/staging/tidspbridge/include/dspbridge/dmm.h b/drivers/staging/tidspbridge/include/dspbridge/dmm.h
new file mode 100644
index 00000000000..6c58335c5f6
--- /dev/null
+++ b/drivers/staging/tidspbridge/include/dspbridge/dmm.h
@@ -0,0 +1,75 @@
1/*
2 * dmm.h
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * The Dynamic Memory Mapping(DMM) module manages the DSP Virtual address
7 * space that can be directly mapped to any MPU buffer or memory region.
8 *
9 * Copyright (C) 2005-2006 Texas Instruments, Inc.
10 *
11 * This package is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 *
15 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18 */
19
20#ifndef DMM_
21#define DMM_
22
23#include <dspbridge/dbdefs.h>
24
25struct dmm_object;
26
27/* DMM attributes used in dmm_create() */
28struct dmm_mgrattrs {
29 u32 reserved;
30};
31
32#define DMMPOOLSIZE 0x4000000
33
34/*
35 * ======== dmm_get_handle ========
36 * Purpose:
37 * Return the dynamic memory manager object for this device.
38 * This is typically called from the client process.
39 */
40
41extern int dmm_get_handle(void *hprocessor,
42 struct dmm_object **dmm_manager);
43
44extern int dmm_reserve_memory(struct dmm_object *dmm_mgr,
45 u32 size, u32 *prsv_addr);
46
47extern int dmm_un_reserve_memory(struct dmm_object *dmm_mgr,
48 u32 rsv_addr);
49
50extern int dmm_map_memory(struct dmm_object *dmm_mgr, u32 addr,
51 u32 size);
52
53extern int dmm_un_map_memory(struct dmm_object *dmm_mgr,
54 u32 addr, u32 *psize);
55
56extern int dmm_destroy(struct dmm_object *dmm_mgr);
57
58extern int dmm_delete_tables(struct dmm_object *dmm_mgr);
59
60extern int dmm_create(struct dmm_object **dmm_manager,
61 struct dev_object *hdev_obj,
62 const struct dmm_mgrattrs *mgr_attrts);
63
64extern bool dmm_init(void);
65
66extern void dmm_exit(void);
67
68extern int dmm_create_tables(struct dmm_object *dmm_mgr,
69 u32 addr, u32 size);
70
71#ifdef DSP_DMM_DEBUG
72u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr);
73#endif
74
75#endif /* DMM_ */
diff --git a/drivers/staging/tidspbridge/include/dspbridge/drv.h b/drivers/staging/tidspbridge/include/dspbridge/drv.h
index 75a2c9b5c6f..427f38b7b43 100644
--- a/drivers/staging/tidspbridge/include/dspbridge/drv.h
+++ b/drivers/staging/tidspbridge/include/dspbridge/drv.h
@@ -108,6 +108,12 @@ struct dmm_map_object {
108 struct bridge_dma_map_info dma_info; 108 struct bridge_dma_map_info dma_info;
109}; 109};
110 110
111/* Used for DMM reserved memory accounting */
112struct dmm_rsv_object {
113 struct list_head link;
114 u32 dsp_reserved_addr;
115};
116
111/* New structure (member of process context) abstracts DMM resource info */ 117/* New structure (member of process context) abstracts DMM resource info */
112struct dspheap_res_object { 118struct dspheap_res_object {
113 s32 heap_allocated; /* DMM status */ 119 s32 heap_allocated; /* DMM status */
diff --git a/drivers/staging/tidspbridge/pmgr/dev.c b/drivers/staging/tidspbridge/pmgr/dev.c
index 7b30267ef0e..e3c78fbfb3c 100644
--- a/drivers/staging/tidspbridge/pmgr/dev.c
+++ b/drivers/staging/tidspbridge/pmgr/dev.c
@@ -34,6 +34,7 @@
34#include <dspbridge/cod.h> 34#include <dspbridge/cod.h>
35#include <dspbridge/drv.h> 35#include <dspbridge/drv.h>
36#include <dspbridge/proc.h> 36#include <dspbridge/proc.h>
37#include <dspbridge/dmm.h>
37 38
38/* ----------------------------------- Resource Manager */ 39/* ----------------------------------- Resource Manager */
39#include <dspbridge/mgr.h> 40#include <dspbridge/mgr.h>
@@ -74,6 +75,7 @@ struct dev_object {
74 struct msg_mgr *hmsg_mgr; /* Message manager. */ 75 struct msg_mgr *hmsg_mgr; /* Message manager. */
75 struct io_mgr *hio_mgr; /* IO manager (CHNL, msg_ctrl) */ 76 struct io_mgr *hio_mgr; /* IO manager (CHNL, msg_ctrl) */
76 struct cmm_object *hcmm_mgr; /* SM memory manager. */ 77 struct cmm_object *hcmm_mgr; /* SM memory manager. */
78 struct dmm_object *dmm_mgr; /* Dynamic memory manager. */
77 struct ldr_module *module_obj; /* Bridge Module handle. */ 79 struct ldr_module *module_obj; /* Bridge Module handle. */
78 u32 word_size; /* DSP word size: quick access. */ 80 u32 word_size; /* DSP word size: quick access. */
79 struct drv_object *hdrv_obj; /* Driver Object */ 81 struct drv_object *hdrv_obj; /* Driver Object */
@@ -248,6 +250,9 @@ int dev_create_device(struct dev_object **device_obj,
248 /* Instantiate the DEH module */ 250 /* Instantiate the DEH module */
249 status = bridge_deh_create(&dev_obj->hdeh_mgr, dev_obj); 251 status = bridge_deh_create(&dev_obj->hdeh_mgr, dev_obj);
250 } 252 }
253 /* Create DMM mgr . */
254 status = dmm_create(&dev_obj->dmm_mgr,
255 (struct dev_object *)dev_obj, NULL);
251 } 256 }
252 /* Add the new DEV_Object to the global list: */ 257 /* Add the new DEV_Object to the global list: */
253 if (!status) { 258 if (!status) {
@@ -273,6 +278,8 @@ leave:
273 kfree(dev_obj->proc_list); 278 kfree(dev_obj->proc_list);
274 if (dev_obj->cod_mgr) 279 if (dev_obj->cod_mgr)
275 cod_delete(dev_obj->cod_mgr); 280 cod_delete(dev_obj->cod_mgr);
281 if (dev_obj->dmm_mgr)
282 dmm_destroy(dev_obj->dmm_mgr);
276 kfree(dev_obj); 283 kfree(dev_obj);
277 } 284 }
278 285
@@ -382,6 +389,11 @@ int dev_destroy_device(struct dev_object *hdev_obj)
382 dev_obj->hcmm_mgr = NULL; 389 dev_obj->hcmm_mgr = NULL;
383 } 390 }
384 391
392 if (dev_obj->dmm_mgr) {
393 dmm_destroy(dev_obj->dmm_mgr);
394 dev_obj->dmm_mgr = NULL;
395 }
396
385 /* Call the driver's bridge_dev_destroy() function: */ 397 /* Call the driver's bridge_dev_destroy() function: */
386 /* Require of DevDestroy */ 398 /* Require of DevDestroy */
387 if (dev_obj->hbridge_context) { 399 if (dev_obj->hbridge_context) {
@@ -462,6 +474,32 @@ int dev_get_cmm_mgr(struct dev_object *hdev_obj,
462} 474}
463 475
464/* 476/*
477 * ======== dev_get_dmm_mgr ========
478 * Purpose:
479 * Retrieve the handle to the dynamic memory manager created for this
480 * device.
481 */
482int dev_get_dmm_mgr(struct dev_object *hdev_obj,
483 struct dmm_object **mgr)
484{
485 int status = 0;
486 struct dev_object *dev_obj = hdev_obj;
487
488 DBC_REQUIRE(refs > 0);
489 DBC_REQUIRE(mgr != NULL);
490
491 if (hdev_obj) {
492 *mgr = dev_obj->dmm_mgr;
493 } else {
494 *mgr = NULL;
495 status = -EFAULT;
496 }
497
498 DBC_ENSURE(!status || (mgr != NULL && *mgr == NULL));
499 return status;
500}
501
502/*
465 * ======== dev_get_cod_mgr ======== 503 * ======== dev_get_cod_mgr ========
466 * Purpose: 504 * Purpose:
467 * Retrieve the COD manager create for this device. 505 * Retrieve the COD manager create for this device.
@@ -713,8 +751,10 @@ void dev_exit(void)
713 751
714 refs--; 752 refs--;
715 753
716 if (refs == 0) 754 if (refs == 0) {
717 cmm_exit(); 755 cmm_exit();
756 dmm_exit();
757 }
718 758
719 DBC_ENSURE(refs >= 0); 759 DBC_ENSURE(refs >= 0);
720} 760}
@@ -726,12 +766,25 @@ void dev_exit(void)
726 */ 766 */
727bool dev_init(void) 767bool dev_init(void)
728{ 768{
729 bool ret = true; 769 bool cmm_ret, dmm_ret, ret = true;
730 770
731 DBC_REQUIRE(refs >= 0); 771 DBC_REQUIRE(refs >= 0);
732 772
733 if (refs == 0) 773 if (refs == 0) {
734 ret = cmm_init(); 774 cmm_ret = cmm_init();
775 dmm_ret = dmm_init();
776
777 ret = cmm_ret && dmm_ret;
778
779 if (!ret) {
780 if (cmm_ret)
781 cmm_exit();
782
783 if (dmm_ret)
784 dmm_exit();
785
786 }
787 }
735 788
736 if (ret) 789 if (ret)
737 refs++; 790 refs++;
diff --git a/drivers/staging/tidspbridge/pmgr/dmm.c b/drivers/staging/tidspbridge/pmgr/dmm.c
new file mode 100644
index 00000000000..8685233d762
--- /dev/null
+++ b/drivers/staging/tidspbridge/pmgr/dmm.c
@@ -0,0 +1,533 @@
1/*
2 * dmm.c
3 *
4 * DSP-BIOS Bridge driver support functions for TI OMAP processors.
5 *
6 * The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
7 * space that can be directly mapped to any MPU buffer or memory region
8 *
9 * Notes:
10 * Region: Generic memory entitiy having a start address and a size
11 * Chunk: Reserved region
12 *
13 * Copyright (C) 2005-2006 Texas Instruments, Inc.
14 *
15 * This package is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License version 2 as
17 * published by the Free Software Foundation.
18 *
19 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
20 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
21 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 */
23#include <linux/types.h>
24
25/* ----------------------------------- Host OS */
26#include <dspbridge/host_os.h>
27
28/* ----------------------------------- DSP/BIOS Bridge */
29#include <dspbridge/dbdefs.h>
30
31/* ----------------------------------- Trace & Debug */
32#include <dspbridge/dbc.h>
33
34/* ----------------------------------- OS Adaptation Layer */
35#include <dspbridge/sync.h>
36
37/* ----------------------------------- Platform Manager */
38#include <dspbridge/dev.h>
39#include <dspbridge/proc.h>
40
41/* ----------------------------------- This */
42#include <dspbridge/dmm.h>
43
44/* ----------------------------------- Defines, Data Structures, Typedefs */
45#define DMM_ADDR_VIRTUAL(a) \
46 (((struct map_page *)(a) - virtual_mapping_table) * PG_SIZE4K +\
47 dyn_mem_map_beg)
48#define DMM_ADDR_TO_INDEX(a) (((a) - dyn_mem_map_beg) / PG_SIZE4K)
49
50/* DMM Mgr */
51struct dmm_object {
52 /* Dmm Lock is used to serialize access mem manager for
53 * multi-threads. */
54 spinlock_t dmm_lock; /* Lock to access dmm mgr */
55};
56
57/* ----------------------------------- Globals */
58static u32 refs; /* module reference count */
59struct map_page {
60 u32 region_size:15;
61 u32 mapped_size:15;
62 u32 reserved:1;
63 u32 mapped:1;
64};
65
66/* Create the free list */
67static struct map_page *virtual_mapping_table;
68static u32 free_region; /* The index of free region */
69static u32 free_size;
70static u32 dyn_mem_map_beg; /* The Beginning of dynamic memory mapping */
71static u32 table_size; /* The size of virt and phys pages tables */
72
73/* ----------------------------------- Function Prototypes */
74static struct map_page *get_region(u32 addr);
75static struct map_page *get_free_region(u32 len);
76static struct map_page *get_mapped_region(u32 addrs);
77
78/* ======== dmm_create_tables ========
79 * Purpose:
80 * Create table to hold the information of physical address
81 * the buffer pages that is passed by the user, and the table
82 * to hold the information of the virtual memory that is reserved
83 * for DSP.
84 */
85int dmm_create_tables(struct dmm_object *dmm_mgr, u32 addr, u32 size)
86{
87 struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
88 int status = 0;
89
90 status = dmm_delete_tables(dmm_obj);
91 if (!status) {
92 dyn_mem_map_beg = addr;
93 table_size = PG_ALIGN_HIGH(size, PG_SIZE4K) / PG_SIZE4K;
94 /* Create the free list */
95 virtual_mapping_table = __vmalloc(table_size *
96 sizeof(struct map_page), GFP_KERNEL |
97 __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
98 if (virtual_mapping_table == NULL)
99 status = -ENOMEM;
100 else {
101 /* On successful allocation,
102 * all entries are zero ('free') */
103 free_region = 0;
104 free_size = table_size * PG_SIZE4K;
105 virtual_mapping_table[0].region_size = table_size;
106 }
107 }
108
109 if (status)
110 pr_err("%s: failure, status 0x%x\n", __func__, status);
111
112 return status;
113}
114
115/*
116 * ======== dmm_create ========
117 * Purpose:
118 * Create a dynamic memory manager object.
119 */
120int dmm_create(struct dmm_object **dmm_manager,
121 struct dev_object *hdev_obj,
122 const struct dmm_mgrattrs *mgr_attrts)
123{
124 struct dmm_object *dmm_obj = NULL;
125 int status = 0;
126 DBC_REQUIRE(refs > 0);
127 DBC_REQUIRE(dmm_manager != NULL);
128
129 *dmm_manager = NULL;
130 /* create, zero, and tag a cmm mgr object */
131 dmm_obj = kzalloc(sizeof(struct dmm_object), GFP_KERNEL);
132 if (dmm_obj != NULL) {
133 spin_lock_init(&dmm_obj->dmm_lock);
134 *dmm_manager = dmm_obj;
135 } else {
136 status = -ENOMEM;
137 }
138
139 return status;
140}
141
142/*
143 * ======== dmm_destroy ========
144 * Purpose:
145 * Release the communication memory manager resources.
146 */
147int dmm_destroy(struct dmm_object *dmm_mgr)
148{
149 struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
150 int status = 0;
151
152 DBC_REQUIRE(refs > 0);
153 if (dmm_mgr) {
154 status = dmm_delete_tables(dmm_obj);
155 if (!status)
156 kfree(dmm_obj);
157 } else
158 status = -EFAULT;
159
160 return status;
161}
162
163/*
164 * ======== dmm_delete_tables ========
165 * Purpose:
166 * Delete DMM Tables.
167 */
168int dmm_delete_tables(struct dmm_object *dmm_mgr)
169{
170 int status = 0;
171
172 DBC_REQUIRE(refs > 0);
173 /* Delete all DMM tables */
174 if (dmm_mgr)
175 vfree(virtual_mapping_table);
176 else
177 status = -EFAULT;
178 return status;
179}
180
181/*
182 * ======== dmm_exit ========
183 * Purpose:
184 * Discontinue usage of module; free resources when reference count
185 * reaches 0.
186 */
187void dmm_exit(void)
188{
189 DBC_REQUIRE(refs > 0);
190
191 refs--;
192}
193
194/*
195 * ======== dmm_get_handle ========
196 * Purpose:
197 * Return the dynamic memory manager object for this device.
198 * This is typically called from the client process.
199 */
200int dmm_get_handle(void *hprocessor, struct dmm_object **dmm_manager)
201{
202 int status = 0;
203 struct dev_object *hdev_obj;
204
205 DBC_REQUIRE(refs > 0);
206 DBC_REQUIRE(dmm_manager != NULL);
207 if (hprocessor != NULL)
208 status = proc_get_dev_object(hprocessor, &hdev_obj);
209 else
210 hdev_obj = dev_get_first(); /* default */
211
212 if (!status)
213 status = dev_get_dmm_mgr(hdev_obj, dmm_manager);
214
215 return status;
216}
217
218/*
219 * ======== dmm_init ========
220 * Purpose:
221 * Initializes private state of DMM module.
222 */
223bool dmm_init(void)
224{
225 bool ret = true;
226
227 DBC_REQUIRE(refs >= 0);
228
229 if (ret)
230 refs++;
231
232 DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
233
234 virtual_mapping_table = NULL;
235 table_size = 0;
236
237 return ret;
238}
239
240/*
241 * ======== dmm_map_memory ========
242 * Purpose:
243 * Add a mapping block to the reserved chunk. DMM assumes that this block
244 * will be mapped in the DSP/IVA's address space. DMM returns an error if a
245 * mapping overlaps another one. This function stores the info that will be
246 * required later while unmapping the block.
247 */
248int dmm_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 size)
249{
250 struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
251 struct map_page *chunk;
252 int status = 0;
253
254 spin_lock(&dmm_obj->dmm_lock);
255 /* Find the Reserved memory chunk containing the DSP block to
256 * be mapped */
257 chunk = (struct map_page *)get_region(addr);
258 if (chunk != NULL) {
259 /* Mark the region 'mapped', leave the 'reserved' info as-is */
260 chunk->mapped = true;
261 chunk->mapped_size = (size / PG_SIZE4K);
262 } else
263 status = -ENOENT;
264 spin_unlock(&dmm_obj->dmm_lock);
265
266 dev_dbg(bridge, "%s dmm_mgr %p, addr %x, size %x\n\tstatus %x, "
267 "chunk %p", __func__, dmm_mgr, addr, size, status, chunk);
268
269 return status;
270}
271
272/*
273 * ======== dmm_reserve_memory ========
274 * Purpose:
275 * Reserve a chunk of virtually contiguous DSP/IVA address space.
276 */
277int dmm_reserve_memory(struct dmm_object *dmm_mgr, u32 size,
278 u32 *prsv_addr)
279{
280 int status = 0;
281 struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
282 struct map_page *node;
283 u32 rsv_addr = 0;
284 u32 rsv_size = 0;
285
286 spin_lock(&dmm_obj->dmm_lock);
287
288 /* Try to get a DSP chunk from the free list */
289 node = get_free_region(size);
290 if (node != NULL) {
291 /* DSP chunk of given size is available. */
292 rsv_addr = DMM_ADDR_VIRTUAL(node);
293 /* Calculate the number entries to use */
294 rsv_size = size / PG_SIZE4K;
295 if (rsv_size < node->region_size) {
296 /* Mark remainder of free region */
297 node[rsv_size].mapped = false;
298 node[rsv_size].reserved = false;
299 node[rsv_size].region_size =
300 node->region_size - rsv_size;
301 node[rsv_size].mapped_size = 0;
302 }
303 /* get_region will return first fit chunk. But we only use what
304 is requested. */
305 node->mapped = false;
306 node->reserved = true;
307 node->region_size = rsv_size;
308 node->mapped_size = 0;
309 /* Return the chunk's starting address */
310 *prsv_addr = rsv_addr;
311 } else
312 /*dSP chunk of given size is not available */
313 status = -ENOMEM;
314
315 spin_unlock(&dmm_obj->dmm_lock);
316
317 dev_dbg(bridge, "%s dmm_mgr %p, size %x, prsv_addr %p\n\tstatus %x, "
318 "rsv_addr %x, rsv_size %x\n", __func__, dmm_mgr, size,
319 prsv_addr, status, rsv_addr, rsv_size);
320
321 return status;
322}
323
324/*
325 * ======== dmm_un_map_memory ========
326 * Purpose:
327 * Remove the mapped block from the reserved chunk.
328 */
329int dmm_un_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 *psize)
330{
331 struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
332 struct map_page *chunk;
333 int status = 0;
334
335 spin_lock(&dmm_obj->dmm_lock);
336 chunk = get_mapped_region(addr);
337 if (chunk == NULL)
338 status = -ENOENT;
339
340 if (!status) {
341 /* Unmap the region */
342 *psize = chunk->mapped_size * PG_SIZE4K;
343 chunk->mapped = false;
344 chunk->mapped_size = 0;
345 }
346 spin_unlock(&dmm_obj->dmm_lock);
347
348 dev_dbg(bridge, "%s: dmm_mgr %p, addr %x, psize %p\n\tstatus %x, "
349 "chunk %p\n", __func__, dmm_mgr, addr, psize, status, chunk);
350
351 return status;
352}
353
354/*
355 * ======== dmm_un_reserve_memory ========
356 * Purpose:
357 * Free a chunk of reserved DSP/IVA address space.
358 */
359int dmm_un_reserve_memory(struct dmm_object *dmm_mgr, u32 rsv_addr)
360{
361 struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
362 struct map_page *chunk;
363 u32 i;
364 int status = 0;
365 u32 chunk_size;
366
367 spin_lock(&dmm_obj->dmm_lock);
368
369 /* Find the chunk containing the reserved address */
370 chunk = get_mapped_region(rsv_addr);
371 if (chunk == NULL)
372 status = -ENOENT;
373
374 if (!status) {
375 /* Free all the mapped pages for this reserved region */
376 i = 0;
377 while (i < chunk->region_size) {
378 if (chunk[i].mapped) {
379 /* Remove mapping from the page tables. */
380 chunk_size = chunk[i].mapped_size;
381 /* Clear the mapping flags */
382 chunk[i].mapped = false;
383 chunk[i].mapped_size = 0;
384 i += chunk_size;
385 } else
386 i++;
387 }
388 /* Clear the flags (mark the region 'free') */
389 chunk->reserved = false;
390 /* NOTE: We do NOT coalesce free regions here.
391 * Free regions are coalesced in get_region(), as it traverses
392 *the whole mapping table
393 */
394 }
395 spin_unlock(&dmm_obj->dmm_lock);
396
397 dev_dbg(bridge, "%s: dmm_mgr %p, rsv_addr %x\n\tstatus %x chunk %p",
398 __func__, dmm_mgr, rsv_addr, status, chunk);
399
400 return status;
401}
402
403/*
404 * ======== get_region ========
405 * Purpose:
406 * Returns a region containing the specified memory region
407 */
408static struct map_page *get_region(u32 addr)
409{
410 struct map_page *curr_region = NULL;
411 u32 i = 0;
412
413 if (virtual_mapping_table != NULL) {
414 /* find page mapped by this address */
415 i = DMM_ADDR_TO_INDEX(addr);
416 if (i < table_size)
417 curr_region = virtual_mapping_table + i;
418 }
419
420 dev_dbg(bridge, "%s: curr_region %p, free_region %d, free_size %d\n",
421 __func__, curr_region, free_region, free_size);
422 return curr_region;
423}
424
425/*
426 * ======== get_free_region ========
427 * Purpose:
428 * Returns the requested free region
429 */
430static struct map_page *get_free_region(u32 len)
431{
432 struct map_page *curr_region = NULL;
433 u32 i = 0;
434 u32 region_size = 0;
435 u32 next_i = 0;
436
437 if (virtual_mapping_table == NULL)
438 return curr_region;
439 if (len > free_size) {
440 /* Find the largest free region
441 * (coalesce during the traversal) */
442 while (i < table_size) {
443 region_size = virtual_mapping_table[i].region_size;
444 next_i = i + region_size;
445 if (virtual_mapping_table[i].reserved == false) {
446 /* Coalesce, if possible */
447 if (next_i < table_size &&
448 virtual_mapping_table[next_i].reserved
449 == false) {
450 virtual_mapping_table[i].region_size +=
451 virtual_mapping_table
452 [next_i].region_size;
453 continue;
454 }
455 region_size *= PG_SIZE4K;
456 if (region_size > free_size) {
457 free_region = i;
458 free_size = region_size;
459 }
460 }
461 i = next_i;
462 }
463 }
464 if (len <= free_size) {
465 curr_region = virtual_mapping_table + free_region;
466 free_region += (len / PG_SIZE4K);
467 free_size -= len;
468 }
469 return curr_region;
470}
471
472/*
473 * ======== get_mapped_region ========
474 * Purpose:
475 * Returns the requestedmapped region
476 */
477static struct map_page *get_mapped_region(u32 addrs)
478{
479 u32 i = 0;
480 struct map_page *curr_region = NULL;
481
482 if (virtual_mapping_table == NULL)
483 return curr_region;
484
485 i = DMM_ADDR_TO_INDEX(addrs);
486 if (i < table_size && (virtual_mapping_table[i].mapped ||
487 virtual_mapping_table[i].reserved))
488 curr_region = virtual_mapping_table + i;
489 return curr_region;
490}
491
492#ifdef DSP_DMM_DEBUG
493u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr)
494{
495 struct map_page *curr_node = NULL;
496 u32 i;
497 u32 freemem = 0;
498 u32 bigsize = 0;
499
500 spin_lock(&dmm_mgr->dmm_lock);
501
502 if (virtual_mapping_table != NULL) {
503 for (i = 0; i < table_size; i +=
504 virtual_mapping_table[i].region_size) {
505 curr_node = virtual_mapping_table + i;
506 if (curr_node->reserved) {
507 /*printk("RESERVED size = 0x%x, "
508 "Map size = 0x%x\n",
509 (curr_node->region_size * PG_SIZE4K),
510 (curr_node->mapped == false) ? 0 :
511 (curr_node->mapped_size * PG_SIZE4K));
512 */
513 } else {
514/* printk("UNRESERVED size = 0x%x\n",
515 (curr_node->region_size * PG_SIZE4K));
516 */
517 freemem += (curr_node->region_size * PG_SIZE4K);
518 if (curr_node->region_size > bigsize)
519 bigsize = curr_node->region_size;
520 }
521 }
522 }
523 spin_unlock(&dmm_mgr->dmm_lock);
524 printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
525 freemem / (1024 * 1024));
526 printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
527 (((table_size * PG_SIZE4K) - freemem)) / (1024 * 1024));
528 printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
529 (bigsize * PG_SIZE4K / (1024 * 1024)));
530
531 return 0;
532}
533#endif
diff --git a/drivers/staging/tidspbridge/rmgr/node.c b/drivers/staging/tidspbridge/rmgr/node.c
index a660247f527..ccb1811a470 100644
--- a/drivers/staging/tidspbridge/rmgr/node.c
+++ b/drivers/staging/tidspbridge/rmgr/node.c
@@ -56,6 +56,7 @@
56/* ----------------------------------- This */ 56/* ----------------------------------- This */
57#include <dspbridge/nodepriv.h> 57#include <dspbridge/nodepriv.h>
58#include <dspbridge/node.h> 58#include <dspbridge/node.h>
59#include <dspbridge/dmm.h>
59 60
60/* Static/Dynamic Loader includes */ 61/* Static/Dynamic Loader includes */
61#include <dspbridge/dbll.h> 62#include <dspbridge/dbll.h>
@@ -316,6 +317,10 @@ int node_allocate(struct proc_object *hprocessor,
316 u32 mapped_addr = 0; 317 u32 mapped_addr = 0;
317 u32 map_attrs = 0x0; 318 u32 map_attrs = 0x0;
318 struct dsp_processorstate proc_state; 319 struct dsp_processorstate proc_state;
320#ifdef DSP_DMM_DEBUG
321 struct dmm_object *dmm_mgr;
322 struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
323#endif
319 324
320 void *node_res; 325 void *node_res;
321 326
@@ -425,6 +430,16 @@ int node_allocate(struct proc_object *hprocessor,
425 if (status) 430 if (status)
426 goto func_cont; 431 goto func_cont;
427 432
433#ifdef DSP_DMM_DEBUG
434 status = dmm_get_handle(p_proc_object, &dmm_mgr);
435 if (!dmm_mgr) {
436 status = DSP_EHANDLE;
437 goto func_cont;
438 }
439
440 dmm_mem_map_dump(dmm_mgr);
441#endif
442
428 map_attrs |= DSP_MAPLITTLEENDIAN; 443 map_attrs |= DSP_MAPLITTLEENDIAN;
429 map_attrs |= DSP_MAPELEMSIZE32; 444 map_attrs |= DSP_MAPELEMSIZE32;
430 map_attrs |= DSP_MAPVIRTUALADDR; 445 map_attrs |= DSP_MAPVIRTUALADDR;
@@ -2484,7 +2499,11 @@ static void delete_node(struct node_object *hnode,
2484 struct stream_chnl stream; 2499 struct stream_chnl stream;
2485 struct node_msgargs node_msg_args; 2500 struct node_msgargs node_msg_args;
2486 struct node_taskargs task_arg_obj; 2501 struct node_taskargs task_arg_obj;
2487 2502#ifdef DSP_DMM_DEBUG
2503 struct dmm_object *dmm_mgr;
2504 struct proc_object *p_proc_object =
2505 (struct proc_object *)hnode->hprocessor;
2506#endif
2488 int status; 2507 int status;
2489 if (!hnode) 2508 if (!hnode)
2490 goto func_end; 2509 goto func_end;
@@ -2545,6 +2564,13 @@ static void delete_node(struct node_object *hnode,
2545 status = proc_un_map(hnode->hprocessor, (void *) 2564 status = proc_un_map(hnode->hprocessor, (void *)
2546 task_arg_obj.udsp_heap_addr, 2565 task_arg_obj.udsp_heap_addr,
2547 pr_ctxt); 2566 pr_ctxt);
2567#ifdef DSP_DMM_DEBUG
2568 status = dmm_get_handle(p_proc_object, &dmm_mgr);
2569 if (dmm_mgr)
2570 dmm_mem_map_dump(dmm_mgr);
2571 else
2572 status = DSP_EHANDLE;
2573#endif
2548 } 2574 }
2549 } 2575 }
2550 if (node_type != NODE_MESSAGE) { 2576 if (node_type != NODE_MESSAGE) {
diff --git a/drivers/staging/tidspbridge/rmgr/proc.c b/drivers/staging/tidspbridge/rmgr/proc.c
index 7a15a02efed..429f3549965 100644
--- a/drivers/staging/tidspbridge/rmgr/proc.c
+++ b/drivers/staging/tidspbridge/rmgr/proc.c
@@ -39,6 +39,7 @@
39#include <dspbridge/cod.h> 39#include <dspbridge/cod.h>
40#include <dspbridge/dev.h> 40#include <dspbridge/dev.h>
41#include <dspbridge/procpriv.h> 41#include <dspbridge/procpriv.h>
42#include <dspbridge/dmm.h>
42 43
43/* ----------------------------------- Resource Manager */ 44/* ----------------------------------- Resource Manager */
44#include <dspbridge/mgr.h> 45#include <dspbridge/mgr.h>
@@ -1077,6 +1078,7 @@ int proc_load(void *hprocessor, const s32 argc_index,
1077 s32 cnew_envp; /* " " in new_envp[] */ 1078 s32 cnew_envp; /* " " in new_envp[] */
1078 s32 nproc_id = 0; /* Anticipate MP version. */ 1079 s32 nproc_id = 0; /* Anticipate MP version. */
1079 struct dcd_manager *hdcd_handle; 1080 struct dcd_manager *hdcd_handle;
1081 struct dmm_object *dmm_mgr;
1080 u32 dw_ext_end; 1082 u32 dw_ext_end;
1081 u32 proc_id; 1083 u32 proc_id;
1082 int brd_state; 1084 int brd_state;
@@ -1267,6 +1269,25 @@ int proc_load(void *hprocessor, const s32 argc_index,
1267 if (!status) 1269 if (!status)
1268 status = cod_get_sym_value(cod_mgr, EXTEND, 1270 status = cod_get_sym_value(cod_mgr, EXTEND,
1269 &dw_ext_end); 1271 &dw_ext_end);
1272
1273 /* Reset DMM structs and add an initial free chunk */
1274 if (!status) {
1275 status =
1276 dev_get_dmm_mgr(p_proc_object->hdev_obj,
1277 &dmm_mgr);
1278 if (dmm_mgr) {
1279 /* Set dw_ext_end to DMM START u8
1280 * address */
1281 dw_ext_end =
1282 (dw_ext_end + 1) * DSPWORDSIZE;
1283 /* DMM memory is from EXT_END */
1284 status = dmm_create_tables(dmm_mgr,
1285 dw_ext_end,
1286 DMMPOOLSIZE);
1287 } else {
1288 status = -EFAULT;
1289 }
1290 }
1270 } 1291 }
1271 } 1292 }
1272 /* Restore the original argv[0] */ 1293 /* Restore the original argv[0] */
@@ -1369,6 +1390,7 @@ int proc_map(void *hprocessor, void *pmpu_addr, u32 ul_size,
1369 map_obj->dsp_addr = (va_align | 1390 map_obj->dsp_addr = (va_align |
1370 ((u32)pmpu_addr & (PG_SIZE4K - 1))); 1391 ((u32)pmpu_addr & (PG_SIZE4K - 1)));
1371 *pp_map_addr = (void *)map_obj->dsp_addr; 1392 *pp_map_addr = (void *)map_obj->dsp_addr;
1393 pr_err("%s: mapped address %x\n", __func__, *pp_map_addr);
1372 } else { 1394 } else {
1373 remove_mapping_information(pr_ctxt, va_align); 1395 remove_mapping_information(pr_ctxt, va_align);
1374 } 1396 }
@@ -1611,6 +1633,7 @@ int proc_un_map(void *hprocessor, void *map_addr,
1611 int status = 0; 1633 int status = 0;
1612 struct proc_object *p_proc_object = (struct proc_object *)hprocessor; 1634 struct proc_object *p_proc_object = (struct proc_object *)hprocessor;
1613 u32 va_align; 1635 u32 va_align;
1636 u32 size_align;
1614 1637
1615 va_align = PG_ALIGN_LOW((u32) map_addr, PG_SIZE4K); 1638 va_align = PG_ALIGN_LOW((u32) map_addr, PG_SIZE4K);
1616 if (!p_proc_object) { 1639 if (!p_proc_object) {