mirror of
https://github.com/genesi/linux-legacy.git
synced 2026-02-03 23:54:40 +00:00
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>
This commit is contained in:
@@ -486,6 +486,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;
|
||||
int err;
|
||||
|
||||
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE,
|
||||
@@ -554,17 +556,33 @@ 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;
|
||||
@@ -573,52 +591,47 @@ 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;
|
||||
ptrfree = ptrbest->prev;
|
||||
kgsl_memarena_releasememblknode(memarena, p);
|
||||
}
|
||||
}
|
||||
|
||||
ptrfree = ptrfree->next;
|
||||
|
||||
} while (!freeblk && ptrfree != memarena->freelist.allocrover);
|
||||
|
||||
|
||||
mutex_unlock(&memarena->lock);
|
||||
|
||||
if (result == GSL_SUCCESS)
|
||||
|
||||
Reference in New Issue
Block a user