dect
/
linux-2.6
Archived
13
0
Fork 0

staging: tidspbridge: convert pmgr to list_head

Convert the pmgr module of the tidspbridge driver
to use struct list_head instead of struct lst_list.

Signed-off-by: Ionut Nicu <ionut.nicu@mindbit.ro>
Signed-off-by: Omar Ramirez Luna <omar.ramirez@ti.com>
This commit is contained in:
Ionut Nicu 2010-11-21 10:46:25 +00:00 committed by Omar Ramirez Luna
parent 3c6bf30f1e
commit 5fb45dac37
2 changed files with 100 additions and 198 deletions

View File

@ -12,7 +12,7 @@
* describes a block of physically contiguous shared memory used for
* future allocations by CMM.
*
* Memory is coelesced back to the appropriate heap when a buffer is
* Memory is coalesced back to the appropriate heap when a buffer is
* freed.
*
* Notes:
@ -30,6 +30,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <linux/types.h>
#include <linux/list.h>
/* ----------------------------------- DSP/BIOS Bridge */
#include <dspbridge/dbdefs.h>
@ -38,7 +39,6 @@
#include <dspbridge/dbc.h>
/* ----------------------------------- OS Adaptation Layer */
#include <dspbridge/list.h>
#include <dspbridge/sync.h>
/* ----------------------------------- Platform Manager */
@ -73,9 +73,9 @@ struct cmm_allocator { /* sma */
u32 ul_dsp_size; /* DSP seg size in bytes */
struct cmm_object *hcmm_mgr; /* back ref to parent mgr */
/* node list of available memory */
struct lst_list *free_list_head;
struct list_head free_list;
/* node list of memory in use */
struct lst_list *in_use_list_head;
struct list_head in_use_list;
};
struct cmm_xlator { /* Pa<->Va translator object */
@ -97,7 +97,7 @@ struct cmm_object {
* Cmm Lock is used to serialize access mem manager for multi-threads.
*/
struct mutex cmm_lock; /* Lock to access cmm mgr */
struct lst_list *node_free_list_head; /* Free list of memory nodes */
struct list_head node_free_list; /* Free list of memory nodes */
u32 ul_min_block_size; /* Min SM block; default 16 bytes */
u32 dw_page_size; /* Memory Page size (1k/4k) */
/* GPP SM segment ptrs */
@ -215,8 +215,7 @@ void *cmm_calloc_buf(struct cmm_object *hcmm_mgr, u32 usize,
pnode->client_proc = current->tgid;
/* put our node on InUse list */
lst_put_tail(allocator->in_use_list_head,
(struct list_head *)pnode);
list_add_tail(&pnode->link, &allocator->in_use_list);
buf_pa = (void *)pnode->dw_pa; /* physical address */
/* clear mem */
pbyte = (u8 *) pnode->dw_va;
@ -265,18 +264,9 @@ int cmm_create(struct cmm_object **ph_cmm_mgr,
* MEM_ALLOC_OBJECT */
/* create node free list */
cmm_obj->node_free_list_head =
kzalloc(sizeof(struct lst_list),
GFP_KERNEL);
if (cmm_obj->node_free_list_head == NULL) {
status = -ENOMEM;
cmm_destroy(cmm_obj, true);
} else {
INIT_LIST_HEAD(&cmm_obj->
node_free_list_head->head);
mutex_init(&cmm_obj->cmm_lock);
*ph_cmm_mgr = cmm_obj;
}
INIT_LIST_HEAD(&cmm_obj->node_free_list);
mutex_init(&cmm_obj->cmm_lock);
*ph_cmm_mgr = cmm_obj;
} else {
status = -ENOMEM;
}
@ -294,7 +284,7 @@ int cmm_destroy(struct cmm_object *hcmm_mgr, bool force)
struct cmm_info temp_info;
int status = 0;
s32 slot_seg;
struct cmm_mnode *pnode;
struct cmm_mnode *node, *tmp;
DBC_REQUIRE(refs > 0);
if (!hcmm_mgr) {
@ -324,15 +314,10 @@ int cmm_destroy(struct cmm_object *hcmm_mgr, bool force)
}
}
}
if (cmm_mgr_obj->node_free_list_head != NULL) {
/* Free the free nodes */
while (!LST_IS_EMPTY(cmm_mgr_obj->node_free_list_head)) {
pnode = (struct cmm_mnode *)
lst_get_head(cmm_mgr_obj->node_free_list_head);
kfree(pnode);
}
/* delete NodeFreeList list */
kfree(cmm_mgr_obj->node_free_list_head);
list_for_each_entry_safe(node, tmp, &cmm_mgr_obj->node_free_list,
link) {
list_del(&node->link);
kfree(node);
}
mutex_unlock(&cmm_mgr_obj->cmm_lock);
if (!status) {
@ -366,7 +351,7 @@ int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa,
{
struct cmm_object *cmm_mgr_obj = (struct cmm_object *)hcmm_mgr;
int status = -EFAULT;
struct cmm_mnode *mnode_obj = NULL;
struct cmm_mnode *curr, *tmp;
struct cmm_allocator *allocator = NULL;
struct cmm_attrs *pattrs;
@ -385,22 +370,14 @@ int cmm_free_buf(struct cmm_object *hcmm_mgr, void *buf_pa,
allocator = get_allocator(cmm_mgr_obj, ul_seg_id);
if (allocator != NULL) {
mutex_lock(&cmm_mgr_obj->cmm_lock);
mnode_obj =
(struct cmm_mnode *)lst_first(allocator->in_use_list_head);
while (mnode_obj) {
if ((u32) buf_pa == mnode_obj->dw_pa) {
/* Found it */
lst_remove_elem(allocator->in_use_list_head,
(struct list_head *)mnode_obj);
/* back to freelist */
add_to_free_list(allocator, mnode_obj);
status = 0; /* all right! */
list_for_each_entry_safe(curr, tmp, &allocator->in_use_list,
link) {
if (curr->dw_pa == (u32) buf_pa) {
list_del(&curr->link);
add_to_free_list(allocator, curr);
status = 0;
break;
}
/* next node. */
mnode_obj = (struct cmm_mnode *)
lst_next(allocator->in_use_list_head,
(struct list_head *)mnode_obj);
}
mutex_unlock(&cmm_mgr_obj->cmm_lock);
}
@ -443,7 +420,7 @@ int cmm_get_info(struct cmm_object *hcmm_mgr,
u32 ul_seg;
int status = 0;
struct cmm_allocator *altr;
struct cmm_mnode *mnode_obj = NULL;
struct cmm_mnode *curr;
DBC_REQUIRE(cmm_info_obj != NULL);
@ -478,17 +455,11 @@ int cmm_get_info(struct cmm_object *hcmm_mgr,
cmm_info_obj->seg_info[ul_seg - 1].dw_seg_base_va =
altr->dw_vm_base - altr->ul_dsp_size;
cmm_info_obj->seg_info[ul_seg - 1].ul_in_use_cnt = 0;
mnode_obj = (struct cmm_mnode *)
lst_first(altr->in_use_list_head);
/* Count inUse blocks */
while (mnode_obj) {
list_for_each_entry(curr, &altr->in_use_list, link) {
cmm_info_obj->ul_total_in_use_cnt++;
cmm_info_obj->seg_info[ul_seg -
1].ul_in_use_cnt++;
/* next node. */
mnode_obj = (struct cmm_mnode *)
lst_next(altr->in_use_list_head,
(struct list_head *)mnode_obj);
}
}
} /* end for */
@ -578,30 +549,17 @@ int cmm_register_gppsm_seg(struct cmm_object *hcmm_mgr,
/* return the actual segment identifier */
*sgmt_id = (u32) slot_seg + 1;
/* create memory free list */
psma->free_list_head = kzalloc(sizeof(struct lst_list),
GFP_KERNEL);
if (psma->free_list_head == NULL) {
status = -ENOMEM;
goto func_end;
}
INIT_LIST_HEAD(&psma->free_list_head->head);
INIT_LIST_HEAD(&psma->free_list);
/* create memory in-use list */
psma->in_use_list_head = kzalloc(sizeof(struct
lst_list), GFP_KERNEL);
if (psma->in_use_list_head == NULL) {
status = -ENOMEM;
goto func_end;
}
INIT_LIST_HEAD(&psma->in_use_list_head->head);
INIT_LIST_HEAD(&psma->in_use_list);
/* Get a mem node for this hunk-o-memory */
new_node = get_node(cmm_mgr_obj, dw_gpp_base_pa,
psma->dw_vm_base, ul_size);
/* Place node on the SM allocator's free list */
if (new_node) {
lst_put_tail(psma->free_list_head,
(struct list_head *)new_node);
list_add_tail(&new_node->link, &psma->free_list);
} else {
status = -ENOMEM;
goto func_end;
@ -680,41 +638,22 @@ int cmm_un_register_gppsm_seg(struct cmm_object *hcmm_mgr,
*/
static void un_register_gppsm_seg(struct cmm_allocator *psma)
{
struct cmm_mnode *mnode_obj = NULL;
struct cmm_mnode *next_node = NULL;
struct cmm_mnode *curr, *tmp;
DBC_REQUIRE(psma != NULL);
if (psma->free_list_head != NULL) {
/* free nodes on free list */
mnode_obj = (struct cmm_mnode *)lst_first(psma->free_list_head);
while (mnode_obj) {
next_node =
(struct cmm_mnode *)lst_next(psma->free_list_head,
(struct list_head *)
mnode_obj);
lst_remove_elem(psma->free_list_head,
(struct list_head *)mnode_obj);
kfree((void *)mnode_obj);
/* next node. */
mnode_obj = next_node;
}
kfree(psma->free_list_head); /* delete freelist */
/* free nodes on InUse list */
mnode_obj =
(struct cmm_mnode *)lst_first(psma->in_use_list_head);
while (mnode_obj) {
next_node =
(struct cmm_mnode *)lst_next(psma->in_use_list_head,
(struct list_head *)
mnode_obj);
lst_remove_elem(psma->in_use_list_head,
(struct list_head *)mnode_obj);
kfree((void *)mnode_obj);
/* next node. */
mnode_obj = next_node;
}
kfree(psma->in_use_list_head); /* delete InUse list */
/* free nodes on free list */
list_for_each_entry_safe(curr, tmp, &psma->free_list, link) {
list_del(&curr->link);
kfree(curr);
}
/* free nodes on InUse list */
list_for_each_entry_safe(curr, tmp, &psma->in_use_list, link) {
list_del(&curr->link);
kfree(curr);
}
if ((void *)psma->dw_vm_base != NULL)
MEM_UNMAP_LINEAR_ADDRESS((void *)psma->dw_vm_base);
@ -758,15 +697,15 @@ static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa,
DBC_REQUIRE(dw_va != 0);
DBC_REQUIRE(ul_size != 0);
/* Check cmm mgr's node freelist */
if (LST_IS_EMPTY(cmm_mgr_obj->node_free_list_head)) {
if (list_empty(&cmm_mgr_obj->node_free_list)) {
pnode = kzalloc(sizeof(struct cmm_mnode), GFP_KERNEL);
} else {
/* surely a valid element */
pnode = (struct cmm_mnode *)
lst_get_head(cmm_mgr_obj->node_free_list_head);
pnode = list_first_entry(&cmm_mgr_obj->node_free_list,
struct cmm_mnode, link);
list_del(&pnode->link);
}
if (pnode) {
lst_init_elem((struct list_head *)pnode); /* set self */
pnode->dw_pa = dw_pa; /* Physical addr of start of block */
pnode->dw_va = dw_va; /* Virtual " " */
pnode->ul_size = ul_size; /* Size of block */
@ -783,9 +722,7 @@ static struct cmm_mnode *get_node(struct cmm_object *cmm_mgr_obj, u32 dw_pa,
static void delete_node(struct cmm_object *cmm_mgr_obj, struct cmm_mnode *pnode)
{
DBC_REQUIRE(pnode != NULL);
lst_init_elem((struct list_head *)pnode); /* init .self ptr */
lst_put_tail(cmm_mgr_obj->node_free_list_head,
(struct list_head *)pnode);
list_add_tail(&pnode->link, &cmm_mgr_obj->node_free_list);
}
/*
@ -797,28 +734,26 @@ static void delete_node(struct cmm_object *cmm_mgr_obj, struct cmm_mnode *pnode)
static struct cmm_mnode *get_free_block(struct cmm_allocator *allocator,
u32 usize)
{
if (allocator) {
struct cmm_mnode *mnode_obj = (struct cmm_mnode *)
lst_first(allocator->free_list_head);
while (mnode_obj) {
if (usize <= (u32) mnode_obj->ul_size) {
lst_remove_elem(allocator->free_list_head,
(struct list_head *)mnode_obj);
return mnode_obj;
}
/* next node. */
mnode_obj = (struct cmm_mnode *)
lst_next(allocator->free_list_head,
(struct list_head *)mnode_obj);
struct cmm_mnode *node, *tmp;
if (!allocator)
return NULL;
list_for_each_entry_safe(node, tmp, &allocator->free_list, link) {
if (usize <= (u32) node->ul_size) {
list_del(&node->link);
return node;
}
}
return NULL;
}
/*
* ======== add_to_free_list ========
* Purpose:
* Coelesce node into the freelist in ascending size order.
* Coalesce node into the freelist in ascending size order.
*/
static void add_to_free_list(struct cmm_allocator *allocator,
struct cmm_mnode *pnode)
@ -829,71 +764,51 @@ static void add_to_free_list(struct cmm_allocator *allocator,
u32 dw_this_pa;
u32 dw_next_pa;
DBC_REQUIRE(pnode != NULL);
DBC_REQUIRE(allocator != NULL);
if (!pnode) {
pr_err("%s: failed - pnode is NULL\n", __func__);
return;
}
dw_this_pa = pnode->dw_pa;
dw_next_pa = NEXT_PA(pnode);
mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
while (mnode_obj) {
list_for_each_entry(mnode_obj, &allocator->free_list, link) {
if (dw_this_pa == NEXT_PA(mnode_obj)) {
/* found the block ahead of this one */
node_prev = mnode_obj;
} else if (dw_next_pa == mnode_obj->dw_pa) {
node_next = mnode_obj;
}
if ((node_prev == NULL) || (node_next == NULL)) {
/* next node. */
mnode_obj = (struct cmm_mnode *)
lst_next(allocator->free_list_head,
(struct list_head *)mnode_obj);
} else {
/* got 'em */
if ((node_prev != NULL) && (node_next != NULL))
break;
}
} /* while */
}
if (node_prev != NULL) {
/* combine with previous block */
lst_remove_elem(allocator->free_list_head,
(struct list_head *)node_prev);
list_del(&node_prev->link);
/* grow node to hold both */
pnode->ul_size += node_prev->ul_size;
pnode->dw_pa = node_prev->dw_pa;
pnode->dw_va = node_prev->dw_va;
/* place node on mgr nodeFreeList */
delete_node((struct cmm_object *)allocator->hcmm_mgr,
node_prev);
delete_node(allocator->hcmm_mgr, node_prev);
}
if (node_next != NULL) {
/* combine with next block */
lst_remove_elem(allocator->free_list_head,
(struct list_head *)node_next);
list_del(&node_next->link);
/* grow da node */
pnode->ul_size += node_next->ul_size;
/* place node on mgr nodeFreeList */
delete_node((struct cmm_object *)allocator->hcmm_mgr,
node_next);
delete_node(allocator->hcmm_mgr, node_next);
}
/* Now, let's add to freelist in increasing size order */
mnode_obj = (struct cmm_mnode *)lst_first(allocator->free_list_head);
while (mnode_obj) {
if (pnode->ul_size <= mnode_obj->ul_size)
break;
/* next node. */
mnode_obj =
(struct cmm_mnode *)lst_next(allocator->free_list_head,
(struct list_head *)mnode_obj);
}
/* if mnode_obj is NULL then add our pnode to the end of the freelist */
if (mnode_obj == NULL) {
lst_put_tail(allocator->free_list_head,
(struct list_head *)pnode);
} else {
/* insert our node before the current traversed node */
lst_insert_before(allocator->free_list_head,
(struct list_head *)pnode,
(struct list_head *)mnode_obj);
list_for_each_entry(mnode_obj, &allocator->free_list, link) {
if (pnode->ul_size <= mnode_obj->ul_size) {
/* insert our node before the current traversed node */
list_add_tail(&pnode->link, &mnode_obj->link);
return;
}
}
/* add our pnode to the end of the freelist */
list_add_tail(&pnode->link, &allocator->free_list);
}
/*

View File

@ -16,6 +16,7 @@
* WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#include <linux/types.h>
#include <linux/list.h>
/* ----------------------------------- Host OS */
#include <dspbridge/host_os.h>
@ -28,7 +29,6 @@
/* ----------------------------------- OS Adaptation Layer */
#include <dspbridge/ldr.h>
#include <dspbridge/list.h>
/* ----------------------------------- Platform Manager */
#include <dspbridge/cod.h>
@ -60,7 +60,6 @@
/* The Bridge device object: */
struct dev_object {
/* LST requires "link" to be first field! */
struct list_head link; /* Link to next dev_object. */
u8 dev_type; /* Device Type */
struct cfg_devnode *dev_node_obj; /* Platform specific dev id */
@ -79,7 +78,7 @@ struct dev_object {
struct ldr_module *module_obj; /* Bridge Module handle. */
u32 word_size; /* DSP word size: quick access. */
struct drv_object *hdrv_obj; /* Driver Object */
struct lst_list *proc_list; /* List of Proceeosr attached to
struct list_head proc_list; /* List of Processor attached to
* this device */
struct node_mgr *hnode_mgr;
};
@ -255,19 +254,12 @@ int dev_create_device(struct dev_object **device_obj,
(struct dev_object *)dev_obj, NULL);
}
/* Add the new DEV_Object to the global list: */
if (!status) {
lst_init_elem(&dev_obj->link);
if (!status)
status = drv_insert_dev_object(hdrv_obj, dev_obj);
}
/* Create the Processor List */
if (!status) {
dev_obj->proc_list = kzalloc(sizeof(struct lst_list),
GFP_KERNEL);
if (!(dev_obj->proc_list))
status = -EPERM;
else
INIT_LIST_HEAD(&dev_obj->proc_list->head);
}
if (!status)
INIT_LIST_HEAD(&dev_obj->proc_list);
leave:
/* If all went well, return a handle to the dev object;
* else, cleanup and return NULL in the OUT parameter. */
@ -275,7 +267,6 @@ leave:
*device_obj = dev_obj;
} else {
if (dev_obj) {
kfree(dev_obj->proc_list);
if (dev_obj->cod_mgr)
cod_delete(dev_obj->cod_mgr);
if (dev_obj->dmm_mgr)
@ -403,9 +394,6 @@ int dev_destroy_device(struct dev_object *hdev_obj)
} else
status = -EPERM;
if (!status) {
kfree(dev_obj->proc_list);
dev_obj->proc_list = NULL;
/* Remove this DEV_Object from the global list: */
drv_remove_dev_object(dev_obj->hdrv_obj, dev_obj);
/* Free The library * LDR_FreeModule
@ -801,18 +789,17 @@ bool dev_init(void)
*/
int dev_notify_clients(struct dev_object *hdev_obj, u32 ret)
{
int status = 0;
struct dev_object *dev_obj = hdev_obj;
void *proc_obj;
struct list_head *curr;
for (proc_obj = (void *)lst_first(dev_obj->proc_list);
proc_obj != NULL;
proc_obj = (void *)lst_next(dev_obj->proc_list,
(struct list_head *)proc_obj))
proc_notify_clients(proc_obj, (u32) ret);
/*
* FIXME: this code needs struct proc_object to have a list_head
* at the begining. If not, this can go horribly wrong.
*/
list_for_each(curr, &dev_obj->proc_list)
proc_notify_clients((void *)curr, (u32) ret);
return status;
return 0;
}
/*
@ -1000,15 +987,18 @@ int dev_insert_proc_object(struct dev_object *hdev_obj,
DBC_REQUIRE(refs > 0);
DBC_REQUIRE(dev_obj);
DBC_REQUIRE(proc_obj != 0);
DBC_REQUIRE(dev_obj->proc_list != NULL);
DBC_REQUIRE(already_attached != NULL);
if (!LST_IS_EMPTY(dev_obj->proc_list))
if (!list_empty(&dev_obj->proc_list))
*already_attached = true;
/* Add DevObject to tail. */
lst_put_tail(dev_obj->proc_list, (struct list_head *)proc_obj);
/*
* FIXME: this code needs struct proc_object to have a list_head
* at the begining. If not, this can go horribly wrong.
*/
list_add_tail((struct list_head *)proc_obj, &dev_obj->proc_list);
DBC_ENSURE(!status && !LST_IS_EMPTY(dev_obj->proc_list));
DBC_ENSURE(!status && !list_empty(&dev_obj->proc_list));
return status;
}
@ -1039,15 +1029,12 @@ int dev_remove_proc_object(struct dev_object *hdev_obj, u32 proc_obj)
DBC_REQUIRE(dev_obj);
DBC_REQUIRE(proc_obj != 0);
DBC_REQUIRE(dev_obj->proc_list != NULL);
DBC_REQUIRE(!LST_IS_EMPTY(dev_obj->proc_list));
DBC_REQUIRE(!list_empty(&dev_obj->proc_list));
/* Search list for dev_obj: */
for (cur_elem = lst_first(dev_obj->proc_list); cur_elem != NULL;
cur_elem = lst_next(dev_obj->proc_list, cur_elem)) {
/* If found, remove it. */
list_for_each(cur_elem, &dev_obj->proc_list) {
if ((u32) cur_elem == proc_obj) {
lst_remove_elem(dev_obj->proc_list, cur_elem);
list_del(cur_elem);
status = 0;
break;
}