diff --git a/drivers/mxc/amd-gpu/gsl_memmgr.c b/drivers/mxc/amd-gpu/gsl_memmgr.c index ba1e3361c02..f2b0558c51c 100644 --- a/drivers/mxc/amd-gpu/gsl_memmgr.c +++ b/drivers/mxc/amd-gpu/gsl_memmgr.c @@ -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)