|
@@ -1,533 +0,0 @@
|
|
-/*
|
|
|
|
- * dmm.c
|
|
|
|
- *
|
|
|
|
- * DSP-BIOS Bridge driver support functions for TI OMAP processors.
|
|
|
|
- *
|
|
|
|
- * The Dynamic Memory Manager (DMM) module manages the DSP Virtual address
|
|
|
|
- * space that can be directly mapped to any MPU buffer or memory region
|
|
|
|
- *
|
|
|
|
- * Notes:
|
|
|
|
- * Region: Generic memory entitiy having a start address and a size
|
|
|
|
- * Chunk: Reserved region
|
|
|
|
- *
|
|
|
|
- * Copyright (C) 2005-2006 Texas Instruments, Inc.
|
|
|
|
- *
|
|
|
|
- * This package is free software; you can redistribute it and/or modify
|
|
|
|
- * it under the terms of the GNU General Public License version 2 as
|
|
|
|
- * published by the Free Software Foundation.
|
|
|
|
- *
|
|
|
|
- * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
|
|
|
|
- * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
|
|
- * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
- */
|
|
|
|
-#include <linux/types.h>
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- Host OS */
|
|
|
|
-#include <dspbridge/host_os.h>
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- DSP/BIOS Bridge */
|
|
|
|
-#include <dspbridge/dbdefs.h>
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- Trace & Debug */
|
|
|
|
-#include <dspbridge/dbc.h>
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- OS Adaptation Layer */
|
|
|
|
-#include <dspbridge/sync.h>
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- Platform Manager */
|
|
|
|
-#include <dspbridge/dev.h>
|
|
|
|
-#include <dspbridge/proc.h>
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- This */
|
|
|
|
-#include <dspbridge/dmm.h>
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- Defines, Data Structures, Typedefs */
|
|
|
|
-#define DMM_ADDR_VIRTUAL(a) \
|
|
|
|
- (((struct map_page *)(a) - virtual_mapping_table) * PG_SIZE4K +\
|
|
|
|
- dyn_mem_map_beg)
|
|
|
|
-#define DMM_ADDR_TO_INDEX(a) (((a) - dyn_mem_map_beg) / PG_SIZE4K)
|
|
|
|
-
|
|
|
|
-/* DMM Mgr */
|
|
|
|
-struct dmm_object {
|
|
|
|
- /* Dmm Lock is used to serialize access mem manager for
|
|
|
|
- * multi-threads. */
|
|
|
|
- spinlock_t dmm_lock; /* Lock to access dmm mgr */
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- Globals */
|
|
|
|
-static u32 refs; /* module reference count */
|
|
|
|
-struct map_page {
|
|
|
|
- u32 region_size:15;
|
|
|
|
- u32 mapped_size:15;
|
|
|
|
- u32 reserved:1;
|
|
|
|
- u32 mapped:1;
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
-/* Create the free list */
|
|
|
|
-static struct map_page *virtual_mapping_table;
|
|
|
|
-static u32 free_region; /* The index of free region */
|
|
|
|
-static u32 free_size;
|
|
|
|
-static u32 dyn_mem_map_beg; /* The Beginning of dynamic memory mapping */
|
|
|
|
-static u32 table_size; /* The size of virt and phys pages tables */
|
|
|
|
-
|
|
|
|
-/* ----------------------------------- Function Prototypes */
|
|
|
|
-static struct map_page *get_region(u32 addr);
|
|
|
|
-static struct map_page *get_free_region(u32 len);
|
|
|
|
-static struct map_page *get_mapped_region(u32 addrs);
|
|
|
|
-
|
|
|
|
-/* ======== dmm_create_tables ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Create table to hold the information of physical address
|
|
|
|
- * the buffer pages that is passed by the user, and the table
|
|
|
|
- * to hold the information of the virtual memory that is reserved
|
|
|
|
- * for DSP.
|
|
|
|
- */
|
|
|
|
-int dmm_create_tables(struct dmm_object *dmm_mgr, u32 addr, u32 size)
|
|
|
|
-{
|
|
|
|
- struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
|
|
|
|
- int status = 0;
|
|
|
|
-
|
|
|
|
- status = dmm_delete_tables(dmm_obj);
|
|
|
|
- if (!status) {
|
|
|
|
- dyn_mem_map_beg = addr;
|
|
|
|
- table_size = PG_ALIGN_HIGH(size, PG_SIZE4K) / PG_SIZE4K;
|
|
|
|
- /* Create the free list */
|
|
|
|
- virtual_mapping_table = __vmalloc(table_size *
|
|
|
|
- sizeof(struct map_page), GFP_KERNEL |
|
|
|
|
- __GFP_HIGHMEM | __GFP_ZERO, PAGE_KERNEL);
|
|
|
|
- if (virtual_mapping_table == NULL)
|
|
|
|
- status = -ENOMEM;
|
|
|
|
- else {
|
|
|
|
- /* On successful allocation,
|
|
|
|
- * all entries are zero ('free') */
|
|
|
|
- free_region = 0;
|
|
|
|
- free_size = table_size * PG_SIZE4K;
|
|
|
|
- virtual_mapping_table[0].region_size = table_size;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- if (status)
|
|
|
|
- pr_err("%s: failure, status 0x%x\n", __func__, status);
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_create ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Create a dynamic memory manager object.
|
|
|
|
- */
|
|
|
|
-int dmm_create(struct dmm_object **dmm_manager,
|
|
|
|
- struct dev_object *hdev_obj,
|
|
|
|
- const struct dmm_mgrattrs *mgr_attrts)
|
|
|
|
-{
|
|
|
|
- struct dmm_object *dmm_obj = NULL;
|
|
|
|
- int status = 0;
|
|
|
|
- DBC_REQUIRE(refs > 0);
|
|
|
|
- DBC_REQUIRE(dmm_manager != NULL);
|
|
|
|
-
|
|
|
|
- *dmm_manager = NULL;
|
|
|
|
- /* create, zero, and tag a cmm mgr object */
|
|
|
|
- dmm_obj = kzalloc(sizeof(struct dmm_object), GFP_KERNEL);
|
|
|
|
- if (dmm_obj != NULL) {
|
|
|
|
- spin_lock_init(&dmm_obj->dmm_lock);
|
|
|
|
- *dmm_manager = dmm_obj;
|
|
|
|
- } else {
|
|
|
|
- status = -ENOMEM;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_destroy ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Release the communication memory manager resources.
|
|
|
|
- */
|
|
|
|
-int dmm_destroy(struct dmm_object *dmm_mgr)
|
|
|
|
-{
|
|
|
|
- struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
|
|
|
|
- int status = 0;
|
|
|
|
-
|
|
|
|
- DBC_REQUIRE(refs > 0);
|
|
|
|
- if (dmm_mgr) {
|
|
|
|
- status = dmm_delete_tables(dmm_obj);
|
|
|
|
- if (!status)
|
|
|
|
- kfree(dmm_obj);
|
|
|
|
- } else
|
|
|
|
- status = -EFAULT;
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_delete_tables ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Delete DMM Tables.
|
|
|
|
- */
|
|
|
|
-int dmm_delete_tables(struct dmm_object *dmm_mgr)
|
|
|
|
-{
|
|
|
|
- int status = 0;
|
|
|
|
-
|
|
|
|
- DBC_REQUIRE(refs > 0);
|
|
|
|
- /* Delete all DMM tables */
|
|
|
|
- if (dmm_mgr)
|
|
|
|
- vfree(virtual_mapping_table);
|
|
|
|
- else
|
|
|
|
- status = -EFAULT;
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_exit ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Discontinue usage of module; free resources when reference count
|
|
|
|
- * reaches 0.
|
|
|
|
- */
|
|
|
|
-void dmm_exit(void)
|
|
|
|
-{
|
|
|
|
- DBC_REQUIRE(refs > 0);
|
|
|
|
-
|
|
|
|
- refs--;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_get_handle ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Return the dynamic memory manager object for this device.
|
|
|
|
- * This is typically called from the client process.
|
|
|
|
- */
|
|
|
|
-int dmm_get_handle(void *hprocessor, struct dmm_object **dmm_manager)
|
|
|
|
-{
|
|
|
|
- int status = 0;
|
|
|
|
- struct dev_object *hdev_obj;
|
|
|
|
-
|
|
|
|
- DBC_REQUIRE(refs > 0);
|
|
|
|
- DBC_REQUIRE(dmm_manager != NULL);
|
|
|
|
- if (hprocessor != NULL)
|
|
|
|
- status = proc_get_dev_object(hprocessor, &hdev_obj);
|
|
|
|
- else
|
|
|
|
- hdev_obj = dev_get_first(); /* default */
|
|
|
|
-
|
|
|
|
- if (!status)
|
|
|
|
- status = dev_get_dmm_mgr(hdev_obj, dmm_manager);
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_init ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Initializes private state of DMM module.
|
|
|
|
- */
|
|
|
|
-bool dmm_init(void)
|
|
|
|
-{
|
|
|
|
- bool ret = true;
|
|
|
|
-
|
|
|
|
- DBC_REQUIRE(refs >= 0);
|
|
|
|
-
|
|
|
|
- if (ret)
|
|
|
|
- refs++;
|
|
|
|
-
|
|
|
|
- DBC_ENSURE((ret && (refs > 0)) || (!ret && (refs >= 0)));
|
|
|
|
-
|
|
|
|
- virtual_mapping_table = NULL;
|
|
|
|
- table_size = 0;
|
|
|
|
-
|
|
|
|
- return ret;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_map_memory ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Add a mapping block to the reserved chunk. DMM assumes that this block
|
|
|
|
- * will be mapped in the DSP/IVA's address space. DMM returns an error if a
|
|
|
|
- * mapping overlaps another one. This function stores the info that will be
|
|
|
|
- * required later while unmapping the block.
|
|
|
|
- */
|
|
|
|
-int dmm_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 size)
|
|
|
|
-{
|
|
|
|
- struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
|
|
|
|
- struct map_page *chunk;
|
|
|
|
- int status = 0;
|
|
|
|
-
|
|
|
|
- spin_lock(&dmm_obj->dmm_lock);
|
|
|
|
- /* Find the Reserved memory chunk containing the DSP block to
|
|
|
|
- * be mapped */
|
|
|
|
- chunk = (struct map_page *)get_region(addr);
|
|
|
|
- if (chunk != NULL) {
|
|
|
|
- /* Mark the region 'mapped', leave the 'reserved' info as-is */
|
|
|
|
- chunk->mapped = true;
|
|
|
|
- chunk->mapped_size = (size / PG_SIZE4K);
|
|
|
|
- } else
|
|
|
|
- status = -ENOENT;
|
|
|
|
- spin_unlock(&dmm_obj->dmm_lock);
|
|
|
|
-
|
|
|
|
- dev_dbg(bridge, "%s dmm_mgr %p, addr %x, size %x\n\tstatus %x, "
|
|
|
|
- "chunk %p", __func__, dmm_mgr, addr, size, status, chunk);
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_reserve_memory ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Reserve a chunk of virtually contiguous DSP/IVA address space.
|
|
|
|
- */
|
|
|
|
-int dmm_reserve_memory(struct dmm_object *dmm_mgr, u32 size,
|
|
|
|
- u32 *prsv_addr)
|
|
|
|
-{
|
|
|
|
- int status = 0;
|
|
|
|
- struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
|
|
|
|
- struct map_page *node;
|
|
|
|
- u32 rsv_addr = 0;
|
|
|
|
- u32 rsv_size = 0;
|
|
|
|
-
|
|
|
|
- spin_lock(&dmm_obj->dmm_lock);
|
|
|
|
-
|
|
|
|
- /* Try to get a DSP chunk from the free list */
|
|
|
|
- node = get_free_region(size);
|
|
|
|
- if (node != NULL) {
|
|
|
|
- /* DSP chunk of given size is available. */
|
|
|
|
- rsv_addr = DMM_ADDR_VIRTUAL(node);
|
|
|
|
- /* Calculate the number entries to use */
|
|
|
|
- rsv_size = size / PG_SIZE4K;
|
|
|
|
- if (rsv_size < node->region_size) {
|
|
|
|
- /* Mark remainder of free region */
|
|
|
|
- node[rsv_size].mapped = false;
|
|
|
|
- node[rsv_size].reserved = false;
|
|
|
|
- node[rsv_size].region_size =
|
|
|
|
- node->region_size - rsv_size;
|
|
|
|
- node[rsv_size].mapped_size = 0;
|
|
|
|
- }
|
|
|
|
- /* get_region will return first fit chunk. But we only use what
|
|
|
|
- is requested. */
|
|
|
|
- node->mapped = false;
|
|
|
|
- node->reserved = true;
|
|
|
|
- node->region_size = rsv_size;
|
|
|
|
- node->mapped_size = 0;
|
|
|
|
- /* Return the chunk's starting address */
|
|
|
|
- *prsv_addr = rsv_addr;
|
|
|
|
- } else
|
|
|
|
- /*dSP chunk of given size is not available */
|
|
|
|
- status = -ENOMEM;
|
|
|
|
-
|
|
|
|
- spin_unlock(&dmm_obj->dmm_lock);
|
|
|
|
-
|
|
|
|
- dev_dbg(bridge, "%s dmm_mgr %p, size %x, prsv_addr %p\n\tstatus %x, "
|
|
|
|
- "rsv_addr %x, rsv_size %x\n", __func__, dmm_mgr, size,
|
|
|
|
- prsv_addr, status, rsv_addr, rsv_size);
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_un_map_memory ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Remove the mapped block from the reserved chunk.
|
|
|
|
- */
|
|
|
|
-int dmm_un_map_memory(struct dmm_object *dmm_mgr, u32 addr, u32 *psize)
|
|
|
|
-{
|
|
|
|
- struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
|
|
|
|
- struct map_page *chunk;
|
|
|
|
- int status = 0;
|
|
|
|
-
|
|
|
|
- spin_lock(&dmm_obj->dmm_lock);
|
|
|
|
- chunk = get_mapped_region(addr);
|
|
|
|
- if (chunk == NULL)
|
|
|
|
- status = -ENOENT;
|
|
|
|
-
|
|
|
|
- if (!status) {
|
|
|
|
- /* Unmap the region */
|
|
|
|
- *psize = chunk->mapped_size * PG_SIZE4K;
|
|
|
|
- chunk->mapped = false;
|
|
|
|
- chunk->mapped_size = 0;
|
|
|
|
- }
|
|
|
|
- spin_unlock(&dmm_obj->dmm_lock);
|
|
|
|
-
|
|
|
|
- dev_dbg(bridge, "%s: dmm_mgr %p, addr %x, psize %p\n\tstatus %x, "
|
|
|
|
- "chunk %p\n", __func__, dmm_mgr, addr, psize, status, chunk);
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== dmm_un_reserve_memory ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Free a chunk of reserved DSP/IVA address space.
|
|
|
|
- */
|
|
|
|
-int dmm_un_reserve_memory(struct dmm_object *dmm_mgr, u32 rsv_addr)
|
|
|
|
-{
|
|
|
|
- struct dmm_object *dmm_obj = (struct dmm_object *)dmm_mgr;
|
|
|
|
- struct map_page *chunk;
|
|
|
|
- u32 i;
|
|
|
|
- int status = 0;
|
|
|
|
- u32 chunk_size;
|
|
|
|
-
|
|
|
|
- spin_lock(&dmm_obj->dmm_lock);
|
|
|
|
-
|
|
|
|
- /* Find the chunk containing the reserved address */
|
|
|
|
- chunk = get_mapped_region(rsv_addr);
|
|
|
|
- if (chunk == NULL)
|
|
|
|
- status = -ENOENT;
|
|
|
|
-
|
|
|
|
- if (!status) {
|
|
|
|
- /* Free all the mapped pages for this reserved region */
|
|
|
|
- i = 0;
|
|
|
|
- while (i < chunk->region_size) {
|
|
|
|
- if (chunk[i].mapped) {
|
|
|
|
- /* Remove mapping from the page tables. */
|
|
|
|
- chunk_size = chunk[i].mapped_size;
|
|
|
|
- /* Clear the mapping flags */
|
|
|
|
- chunk[i].mapped = false;
|
|
|
|
- chunk[i].mapped_size = 0;
|
|
|
|
- i += chunk_size;
|
|
|
|
- } else
|
|
|
|
- i++;
|
|
|
|
- }
|
|
|
|
- /* Clear the flags (mark the region 'free') */
|
|
|
|
- chunk->reserved = false;
|
|
|
|
- /* NOTE: We do NOT coalesce free regions here.
|
|
|
|
- * Free regions are coalesced in get_region(), as it traverses
|
|
|
|
- *the whole mapping table
|
|
|
|
- */
|
|
|
|
- }
|
|
|
|
- spin_unlock(&dmm_obj->dmm_lock);
|
|
|
|
-
|
|
|
|
- dev_dbg(bridge, "%s: dmm_mgr %p, rsv_addr %x\n\tstatus %x chunk %p",
|
|
|
|
- __func__, dmm_mgr, rsv_addr, status, chunk);
|
|
|
|
-
|
|
|
|
- return status;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== get_region ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Returns a region containing the specified memory region
|
|
|
|
- */
|
|
|
|
-static struct map_page *get_region(u32 addr)
|
|
|
|
-{
|
|
|
|
- struct map_page *curr_region = NULL;
|
|
|
|
- u32 i = 0;
|
|
|
|
-
|
|
|
|
- if (virtual_mapping_table != NULL) {
|
|
|
|
- /* find page mapped by this address */
|
|
|
|
- i = DMM_ADDR_TO_INDEX(addr);
|
|
|
|
- if (i < table_size)
|
|
|
|
- curr_region = virtual_mapping_table + i;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- dev_dbg(bridge, "%s: curr_region %p, free_region %d, free_size %d\n",
|
|
|
|
- __func__, curr_region, free_region, free_size);
|
|
|
|
- return curr_region;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== get_free_region ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Returns the requested free region
|
|
|
|
- */
|
|
|
|
-static struct map_page *get_free_region(u32 len)
|
|
|
|
-{
|
|
|
|
- struct map_page *curr_region = NULL;
|
|
|
|
- u32 i = 0;
|
|
|
|
- u32 region_size = 0;
|
|
|
|
- u32 next_i = 0;
|
|
|
|
-
|
|
|
|
- if (virtual_mapping_table == NULL)
|
|
|
|
- return curr_region;
|
|
|
|
- if (len > free_size) {
|
|
|
|
- /* Find the largest free region
|
|
|
|
- * (coalesce during the traversal) */
|
|
|
|
- while (i < table_size) {
|
|
|
|
- region_size = virtual_mapping_table[i].region_size;
|
|
|
|
- next_i = i + region_size;
|
|
|
|
- if (virtual_mapping_table[i].reserved == false) {
|
|
|
|
- /* Coalesce, if possible */
|
|
|
|
- if (next_i < table_size &&
|
|
|
|
- virtual_mapping_table[next_i].reserved
|
|
|
|
- == false) {
|
|
|
|
- virtual_mapping_table[i].region_size +=
|
|
|
|
- virtual_mapping_table
|
|
|
|
- [next_i].region_size;
|
|
|
|
- continue;
|
|
|
|
- }
|
|
|
|
- region_size *= PG_SIZE4K;
|
|
|
|
- if (region_size > free_size) {
|
|
|
|
- free_region = i;
|
|
|
|
- free_size = region_size;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- i = next_i;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- if (len <= free_size) {
|
|
|
|
- curr_region = virtual_mapping_table + free_region;
|
|
|
|
- free_region += (len / PG_SIZE4K);
|
|
|
|
- free_size -= len;
|
|
|
|
- }
|
|
|
|
- return curr_region;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-/*
|
|
|
|
- * ======== get_mapped_region ========
|
|
|
|
- * Purpose:
|
|
|
|
- * Returns the requestedmapped region
|
|
|
|
- */
|
|
|
|
-static struct map_page *get_mapped_region(u32 addrs)
|
|
|
|
-{
|
|
|
|
- u32 i = 0;
|
|
|
|
- struct map_page *curr_region = NULL;
|
|
|
|
-
|
|
|
|
- if (virtual_mapping_table == NULL)
|
|
|
|
- return curr_region;
|
|
|
|
-
|
|
|
|
- i = DMM_ADDR_TO_INDEX(addrs);
|
|
|
|
- if (i < table_size && (virtual_mapping_table[i].mapped ||
|
|
|
|
- virtual_mapping_table[i].reserved))
|
|
|
|
- curr_region = virtual_mapping_table + i;
|
|
|
|
- return curr_region;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-#ifdef DSP_DMM_DEBUG
|
|
|
|
-u32 dmm_mem_map_dump(struct dmm_object *dmm_mgr)
|
|
|
|
-{
|
|
|
|
- struct map_page *curr_node = NULL;
|
|
|
|
- u32 i;
|
|
|
|
- u32 freemem = 0;
|
|
|
|
- u32 bigsize = 0;
|
|
|
|
-
|
|
|
|
- spin_lock(&dmm_mgr->dmm_lock);
|
|
|
|
-
|
|
|
|
- if (virtual_mapping_table != NULL) {
|
|
|
|
- for (i = 0; i < table_size; i +=
|
|
|
|
- virtual_mapping_table[i].region_size) {
|
|
|
|
- curr_node = virtual_mapping_table + i;
|
|
|
|
- if (curr_node->reserved) {
|
|
|
|
- /*printk("RESERVED size = 0x%x, "
|
|
|
|
- "Map size = 0x%x\n",
|
|
|
|
- (curr_node->region_size * PG_SIZE4K),
|
|
|
|
- (curr_node->mapped == false) ? 0 :
|
|
|
|
- (curr_node->mapped_size * PG_SIZE4K));
|
|
|
|
- */
|
|
|
|
- } else {
|
|
|
|
-/* printk("UNRESERVED size = 0x%x\n",
|
|
|
|
- (curr_node->region_size * PG_SIZE4K));
|
|
|
|
- */
|
|
|
|
- freemem += (curr_node->region_size * PG_SIZE4K);
|
|
|
|
- if (curr_node->region_size > bigsize)
|
|
|
|
- bigsize = curr_node->region_size;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
- spin_unlock(&dmm_mgr->dmm_lock);
|
|
|
|
- printk(KERN_INFO "Total DSP VA FREE memory = %d Mbytes\n",
|
|
|
|
- freemem / (1024 * 1024));
|
|
|
|
- printk(KERN_INFO "Total DSP VA USED memory= %d Mbytes \n",
|
|
|
|
- (((table_size * PG_SIZE4K) - freemem)) / (1024 * 1024));
|
|
|
|
- printk(KERN_INFO "DSP VA - Biggest FREE block = %d Mbytes \n\n",
|
|
|
|
- (bigsize * PG_SIZE4K / (1024 * 1024)));
|
|
|
|
-
|
|
|
|
- return 0;
|
|
|
|
-}
|
|
|
|
-#endif
|
|
|