summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorXinyu Chen <b03824@freescale.com>2011-10-25 15:43:54 +0800
committerXinyu Chen <b03824@freescale.com>2011-10-26 10:14:32 +0800
commitf670cbc12d28a642c8b73080684115c57f0cdd98 (patch)
tree8f9c47db3e4d8a40e809ae449afa596b9d4e026b /drivers
parentbc1aa21f870e3afb3a7444d50b9ad1a8175aa87b (diff)
ENGR00160722 amd gpu: add best fit algorithm to memory manager
The AMD gpu driver memory manager is stupid to allocating a memory block from the first free block. Neither check the best fit free block. Here just add a little codes to let allocation to find a best size fitted free block. To avoid memory fragement. Signed-off-by: Xinyu Chen <xinyu.chen@freescale.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/mxc/amd-gpu/common/gsl_memmgr.c73
1 files changed, 44 insertions, 29 deletions
diff --git a/drivers/mxc/amd-gpu/common/gsl_memmgr.c b/drivers/mxc/amd-gpu/common/gsl_memmgr.c
index 75f250ae59b1..f331bb547542 100644
--- a/drivers/mxc/amd-gpu/common/gsl_memmgr.c
+++ b/drivers/mxc/amd-gpu/common/gsl_memmgr.c
@@ -479,6 +479,8 @@ kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_m
unsigned int blksize;
unsigned int baseaddr, alignedbaseaddr, alignfragment;
int freeblk, alignmentshift;
+ memblk_t *ptrbest = NULL;
+ unsigned int fitsize = ~0UL;
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE,
"--> int kgsl_memarena_alloc(gsl_memarena_t *memarena=0x%08x, gsl_flags_t flags=0x%08x, int size=%d, gsl_memdesc_t *memdesc=%M)\n", memarena, flags, size, memdesc );
@@ -542,17 +544,34 @@ kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_m
do
{
+ int aba;
// align base address
baseaddr = ptrfree->blkaddr + memarena->gpubaseaddr;
- alignedbaseaddr = gsl_memarena_alignaddr(baseaddr, alignmentshift);
+ aba = gsl_memarena_alignaddr(baseaddr, alignmentshift);
- alignfragment = alignedbaseaddr - baseaddr;
+ if (aba - baseaddr == 0 && ptrfree->blksize == blksize) {
+ ptrbest = ptrfree;
+ alignfragment = aba - baseaddr;
+ alignedbaseaddr = aba;
+ result = GSL_SUCCESS;
+ break;
+ }
- if (ptrfree->blksize >= blksize + alignfragment)
+ if ((ptrfree->blksize >= blksize + aba - baseaddr) &&
+ (fitsize > ptrfree->blksize))
{
+ fitsize = ptrfree->blksize;
+ alignfragment = aba - baseaddr;
+ alignedbaseaddr = aba;
result = GSL_SUCCESS;
- freeblk = 1;
+ ptrbest = ptrfree;
+ }
+
+ ptrfree = ptrfree->next;
+
+ } while (ptrfree != memarena->freelist.allocrover);
+ if (ptrbest) {
memdesc->gpuaddr = alignedbaseaddr;
memdesc->hostptr = kgsl_memarena_gethostptr(memarena, memdesc->gpuaddr);
memdesc->size = blksize;
@@ -561,50 +580,46 @@ kgsl_memarena_alloc(gsl_memarena_t *memarena, gsl_flags_t flags, int size, gsl_m
{
// insert new node to handle newly created (small) fragment
p = kgsl_memarena_getmemblknode(memarena);
- p->blkaddr = ptrfree->blkaddr;
+ p->blkaddr = ptrbest->blkaddr;
p->blksize = alignfragment;
- p->next = ptrfree;
- p->prev = ptrfree->prev;
- ptrfree->prev->next = p;
- ptrfree->prev = p;
+ p->next = ptrbest;
+ p->prev = ptrbest->prev;
+ ptrbest->prev->next = p;
+ ptrbest->prev = p;
- if (ptrfree == memarena->freelist.head)
+ if (ptrbest == memarena->freelist.head)
{
memarena->freelist.head = p;
}
}
- ptrfree->blkaddr += alignfragment + blksize;
- ptrfree->blksize -= alignfragment + blksize;
+ ptrbest->blkaddr += alignfragment + blksize;
+ ptrbest->blksize -= alignfragment + blksize;
- memarena->freelist.allocrover = ptrfree;
+ memarena->freelist.allocrover = ptrbest;
- if (ptrfree->blksize == 0 && ptrfree != ptrlast)
+ if (ptrbest->blksize == 0 && ptrbest != ptrlast)
{
- ptrfree->prev->next = ptrfree->next;
- ptrfree->next->prev = ptrfree->prev;
- if (ptrfree == memarena->freelist.head)
+ ptrbest->prev->next = ptrbest->next;
+ ptrbest->next->prev = ptrbest->prev;
+ if (ptrbest == memarena->freelist.head)
{
- memarena->freelist.head = ptrfree->next;
+ memarena->freelist.head = ptrbest->next;
}
- if (ptrfree == memarena->freelist.allocrover)
+ if (ptrbest == memarena->freelist.allocrover)
{
- memarena->freelist.allocrover = ptrfree->next;
+ memarena->freelist.allocrover = ptrbest->next;
}
- if (ptrfree == memarena->freelist.freerover)
+ if (ptrbest == memarena->freelist.freerover)
{
- memarena->freelist.freerover = ptrfree->prev;
+ memarena->freelist.freerover = ptrbest->prev;
}
- p = ptrfree;
- ptrfree = ptrfree->prev;
+ p = ptrbest;
+ ptrbest = ptrbest->prev;
kgsl_memarena_releasememblknode(memarena, p);
}
- }
-
- ptrfree = ptrfree->next;
-
- } while (!freeblk && ptrfree != memarena->freelist.allocrover);
+ }
GSL_MEMARENA_UNLOCK();