amd-gpu: make fine-grained locking optional again (from Kconfig)

Obviously has some serious serialization issues making it not so
useful.
This commit is contained in:
Matt Sealey
2012-11-28 10:34:34 -08:00
parent ffa3b9a761
commit a5d27bcb79
6 changed files with 114 additions and 20 deletions

View File

@@ -21,6 +21,14 @@ config KGSL_MMU_ENABLE
depends on MXC_KGSL && MMU
default y
config KGSL_FINE_GRAINED_LOCKING
bool "Enable fine-grained locking in the KGSL driver"
depends on MXC_KGSL
default n
---help---
Currently has some serialization issues, only enable if
you are willing to solve them. For now, N!
config KGSL_PER_PROCESS_PAGE_TABLE
bool "Enable Per Process page tables for the KGSL driver"
default n

View File

@@ -28,19 +28,23 @@
int kgsl_cmdstream_init(struct kgsl_device *device)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
device->cmdstream_mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (!device->cmdstream_mutex)
return GSL_FAILURE;
mutex_init(device->cmdstream_mutex);
#endif
return GSL_SUCCESS;
}
int kgsl_cmdstream_close(struct kgsl_device *device)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
if (!device->cmdstream_mutex)
return GSL_FAILURE;
kfree(device->cmdstream_mutex);
device->cmdstream_mutex = NULL;
#endif
return GSL_SUCCESS;
}
@@ -144,12 +148,16 @@ kgsl_cmdstream_memqueue_drain(struct kgsl_device *device)
unsigned int timestamp, ts_processed;
gsl_memqueue_t *memqueue = &device->memqueue;
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(device->cmdstream_mutex);
#endif
// check head
if (memqueue->head == NULL)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->cmdstream_mutex);
#endif
return;
}
// get current EOP timestamp
@@ -158,7 +166,9 @@ kgsl_cmdstream_memqueue_drain(struct kgsl_device *device)
// check head timestamp
if (!(((ts_processed - timestamp) >= 0) || ((ts_processed - timestamp) < -GSL_TIMESTAMP_EPSILON)))
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->cmdstream_mutex);
#endif
return;
}
memnode = memqueue->head;
@@ -193,8 +203,9 @@ kgsl_cmdstream_memqueue_drain(struct kgsl_device *device)
kfree(memnode);
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->cmdstream_mutex);
#endif
}
//----------------------------------------------------------------------------
@@ -208,15 +219,18 @@ kgsl_cmdstream_freememontimestamp(unsigned int device_id, struct kgsl_memdesc *m
(void)type; // unref. For now just use EOP timestamp
mutex_lock(&gsl_driver.lock);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(device->cmdstream_mutex);
#endif
memqueue = &device->memqueue;
memnode = kmalloc(sizeof(gsl_memnode_t), GFP_KERNEL);
if (!memnode)
{
// other solution is to idle and free which given that the upper level driver probably wont check, probably a better idea
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->cmdstream_mutex);
#endif
mutex_unlock(&gsl_driver.lock);
return (GSL_FAILURE);
}
@@ -239,7 +253,9 @@ kgsl_cmdstream_freememontimestamp(unsigned int device_id, struct kgsl_memdesc *m
memqueue->tail = memnode;
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->cmdstream_mutex);
#endif
mutex_unlock(&gsl_driver.lock);
return (GSL_SUCCESS);

View File

@@ -29,19 +29,23 @@
int kgsl_cmdwindow_init(struct kgsl_device *device)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
device->cmdwindow_mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (!device->cmdwindow_mutex)
return GSL_FAILURE;
mutex_init(device->cmdwindow_mutex);
#endif
return GSL_SUCCESS;
}
int kgsl_cmdwindow_close(struct kgsl_device *device)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
if (!device->cmdwindow_mutex)
return GSL_FAILURE;
kfree(device->cmdwindow_mutex);
device->cmdwindow_mutex = NULL;
#endif
return GSL_SUCCESS;
}
@@ -92,7 +96,9 @@ kgsl_cmdwindow_write0(unsigned int device_id, enum kgsl_cmdwindow_type target, u
cmdwinaddr = ((target << GSL_CMDWINDOW_TARGET_SHIFT) & GSL_CMDWINDOW_TARGET_MASK);
cmdwinaddr |= ((addr << GSL_CMDWINDOW_ADDR_SHIFT) & GSL_CMDWINDOW_ADDR_MASK);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(device->cmdwindow_mutex);
#endif
#ifdef CONFIG_KGSL_MMU_ENABLE
// set mmu pagetable
@@ -105,8 +111,9 @@ kgsl_cmdwindow_write0(unsigned int device_id, enum kgsl_cmdwindow_type target, u
// write data
device->ftbl.regwrite(device, (cmdstream)>>2, data);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->cmdwindow_mutex);
#endif
kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_cmdwindow_write. Return value %B\n", GSL_SUCCESS );
return (GSL_SUCCESS);

View File

@@ -1391,10 +1391,12 @@ create_gmem_shadow(struct kgsl_device *device, gsl_drawctxt_t *drawctxt, ctx_t *
int kgsl_drawctxt_init(struct kgsl_device *device)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
device->drawctxt_mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (!device->drawctxt_mutex)
return GSL_FAILURE;
mutex_init(device->drawctxt_mutex);
#endif
return GSL_SUCCESS;
}
@@ -1404,10 +1406,12 @@ int kgsl_drawctxt_init(struct kgsl_device *device)
int kgsl_drawctxt_close(struct kgsl_device *device)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
if (!device->drawctxt_mutex)
return GSL_FAILURE;
kfree(device->drawctxt_mutex);
device->drawctxt_mutex = NULL;
#endif
return GSL_SUCCESS;
}
@@ -1424,10 +1428,14 @@ kgsl_drawctxt_create(struct kgsl_device* device, gsl_context_type_t type, unsign
kgsl_device_active(device);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(device->drawctxt_mutex);
#endif
if (device->drawctxt_count >= GSL_CONTEXT_MAX)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
return (GSL_FAILURE);
}
@@ -1443,7 +1451,9 @@ kgsl_drawctxt_create(struct kgsl_device* device, gsl_context_type_t type, unsign
if (index >= GSL_CONTEXT_MAX)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
return (GSL_FAILURE);
}
@@ -1463,7 +1473,9 @@ kgsl_drawctxt_create(struct kgsl_device* device, gsl_context_type_t type, unsign
if (create_gpustate_shadow(device, drawctxt, &ctx) != GSL_SUCCESS)
{
kgsl_drawctxt_destroy(device, index);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
return (GSL_FAILURE);
}
@@ -1477,7 +1489,9 @@ kgsl_drawctxt_create(struct kgsl_device* device, gsl_context_type_t type, unsign
if (create_gmem_shadow(device, drawctxt, &ctx) != GSL_SUCCESS)
{
kgsl_drawctxt_destroy(device, index);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
return (GSL_FAILURE);
}
@@ -1486,7 +1500,9 @@ kgsl_drawctxt_create(struct kgsl_device* device, gsl_context_type_t type, unsign
*drawctxt_id = index;
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
return (GSL_SUCCESS);
}
@@ -1500,7 +1516,9 @@ kgsl_drawctxt_destroy(struct kgsl_device* device, unsigned int drawctxt_id)
{
gsl_drawctxt_t *drawctxt;
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(device->drawctxt_mutex);
#endif
drawctxt = &device->drawctxt[drawctxt_id];
if (drawctxt->flags != CTXT_FLAGS_NOT_IN_USE)
@@ -1535,8 +1553,9 @@ kgsl_drawctxt_destroy(struct kgsl_device* device, unsigned int drawctxt_id)
DEBUG_ASSERT(device->drawctxt_count >= 0);
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
return (GSL_SUCCESS);
}
@@ -1570,8 +1589,9 @@ int kgsl_drawctxt_bind_gmem_shadow(unsigned int device_id, unsigned int drawctxt
unsigned int i;
mutex_lock(&gsl_driver.lock);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(device->drawctxt_mutex);
#endif
if( !shadow_buffer->enabled )
{
// Disable shadow
@@ -1641,7 +1661,9 @@ int kgsl_drawctxt_bind_gmem_shadow(unsigned int device_id, unsigned int drawctxt
}
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
mutex_unlock(&gsl_driver.lock);
return (GSL_SUCCESS);
@@ -1779,7 +1801,9 @@ kgsl_drawctxt_destroyall(struct kgsl_device *device)
int i;
gsl_drawctxt_t *drawctxt;
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(device->drawctxt_mutex);
#endif
for (i = 0; i < GSL_CONTEXT_MAX; i++)
{
@@ -1805,6 +1829,8 @@ kgsl_drawctxt_destroyall(struct kgsl_device *device)
}
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(device->drawctxt_mutex);
#endif
return (GSL_SUCCESS);
}

View File

@@ -390,7 +390,9 @@ kgsl_mmu_setpagetable(struct kgsl_device *device, unsigned int pid)
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE,
"--> struct kgsl_pagetable* kgsl_mmu_setpagetable(struct kgsl_device *device=0x%08x)\n", device );
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(mmu->mutex);
#endif
if (mmu->flags & GSL_FLAGS_STARTED)
{
@@ -430,8 +432,9 @@ kgsl_mmu_setpagetable(struct kgsl_device *device, unsigned int pid)
}
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_setpagetable. Return value %B\n", status );
return (status);
@@ -518,9 +521,10 @@ kgsl_mmu_init(struct kgsl_device *device)
if ((mmu->config & ~0x1) > 0)
{
// this needs to be error checked better
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mmu->mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
mutex_init(mmu->mutex);
#endif
// make sure virtual address range is a multiple of 64Kb
DEBUG_ASSERT((mmu->va_range & ((1 << 16)-1)) == 0);
@@ -613,12 +617,16 @@ kgsl_mmu_map(struct kgsl_mmu *mmu, uint32_t gpubaseaddr, const gsl_scatterlist_t
// get gpu access permissions
ap = GSL_PT_PAGE_AP[((flags & GSL_MEMFLAGS_GPUAP_MASK) >> GSL_MEMFLAGS_GPUAP_SHIFT)];
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(mmu->mutex);
#endif
pagetable = kgsl_mmu_getpagetableobject(mmu, pid);
if (!pagetable)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
return (GSL_FAILURE);
}
@@ -693,7 +701,9 @@ kgsl_mmu_map(struct kgsl_mmu *mmu, uint32_t gpubaseaddr, const gsl_scatterlist_t
status = GSL_FAILURE;
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_map. Return value %B\n", GSL_SUCCESS );
@@ -741,11 +751,15 @@ kgsl_mmu_unmap(struct kgsl_mmu *mmu, uint32_t gpubaseaddr, int range, unsigned i
numpages++;
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(mmu->mutex);
#endif
pagetable = kgsl_mmu_getpagetableobject(mmu, pid);
if (!pagetable)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
return (GSL_FAILURE);
}
@@ -800,8 +814,9 @@ kgsl_mmu_unmap(struct kgsl_mmu *mmu, uint32_t gpubaseaddr, int range, unsigned i
// invalidate tlb, debug only
KGSL_DEBUG(GSL_DBGFLAGS_MMU, mmu->device->ftbl.mmu_tlbinvalidate(mmu->device, gsl_cfg_mmu_reg[mmu->device->id-1].INVALIDATE, pagetable->pid));
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_unmap. Return value %B\n", GSL_SUCCESS );
return (status);
@@ -836,12 +851,15 @@ kgsl_mmu_getmap(struct kgsl_mmu *mmu, uint32_t gpubaseaddr, int range, gsl_scatt
return (GSL_FAILURE);
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(mmu->mutex);
#endif
pagetable = kgsl_mmu_getpagetableobject(mmu, pid);
if (!pagetable)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
return (GSL_FAILURE);
}
@@ -875,8 +893,9 @@ kgsl_mmu_getmap(struct kgsl_mmu *mmu, uint32_t gpubaseaddr, int range, gsl_scatt
scatterlist->pages[0] = GSL_PT_MAP_GETADDR(ptefirst);
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
scatterlist->contiguous = contiguous;
return (GSL_SUCCESS);
@@ -946,10 +965,11 @@ kgsl_mmu_close(struct kgsl_device *device)
kgsl_sharedmem_free0(&mmu->dummyspace, current->tgid);
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
// this needs to be error checked better!
kfree(mmu->mutex);
mmu->mutex = NULL;
#endif
mmu->flags &= ~GSL_FLAGS_STARTED;
mmu->flags &= ~GSL_FLAGS_INITIALIZED;
mmu->flags &= ~GSL_FLAGS_INITIALIZED0;
@@ -976,8 +996,9 @@ kgsl_mmu_attachcallback(struct kgsl_mmu *mmu, unsigned int pid)
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_attachcallback(struct kgsl_mmu *mmu=0x%08x, uint pid=0x%08x)\n", mmu, pid );
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(mmu->mutex);
#endif
if (mmu->flags & GSL_FLAGS_INITIALIZED0)
{
// attach to current device mmu
@@ -998,8 +1019,9 @@ kgsl_mmu_attachcallback(struct kgsl_mmu *mmu, unsigned int pid)
}
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_attachcallback. Return value %B\n", status );
return (status);
@@ -1018,8 +1040,9 @@ kgsl_mmu_detachcallback(struct kgsl_mmu *mmu, unsigned int pid)
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "--> int kgsl_mmu_detachcallback(struct kgsl_mmu *mmu=0x%08x, uint pid=0x%08x)\n", mmu, pid );
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(mmu->mutex);
#endif
if (mmu->flags & GSL_FLAGS_INITIALIZED0)
{
// detach from current device mmu
@@ -1040,8 +1063,9 @@ kgsl_mmu_detachcallback(struct kgsl_mmu *mmu, unsigned int pid)
}
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
kgsl_log_write( KGSL_LOG_GROUP_MEMORY | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_mmu_detachcallback. Return value %B\n", status );
return (status);
@@ -1057,8 +1081,9 @@ kgsl_mmu_querystats(struct kgsl_mmu *mmu, gsl_mmustats_t *stats)
DEBUG_ASSERT(stats);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(mmu->mutex);
#endif
if (mmu->flags & GSL_FLAGS_STARTED)
{
memcpy(stats, &mmu->stats, sizeof(gsl_mmustats_t));
@@ -1068,8 +1093,9 @@ kgsl_mmu_querystats(struct kgsl_mmu *mmu, gsl_mmustats_t *stats)
memset(stats, 0, sizeof(gsl_mmustats_t));
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(mmu->mutex);
#endif
return (status);
#else
// unreferenced formal parameters

View File

@@ -121,7 +121,9 @@ kgsl_ringbuffer_watchdog()
if (rb->flags & GSL_FLAGS_STARTED)
{
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(rb->mutex);
#endif
GSL_RB_GET_READPTR(rb, &rb->rptr);
// ringbuffer is currently not empty
@@ -152,8 +154,9 @@ kgsl_ringbuffer_watchdog()
rb->watchdog.flags &= ~GSL_FLAGS_ACTIVE;
}
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(rb->mutex);
#endif
}
kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE, "<-- kgsl_ringbuffer_watchdog.\n" );
}
@@ -671,10 +674,12 @@ kgsl_ringbuffer_init(struct kgsl_device *device)
rb->sizedwords = (2 << gsl_cfg_rb_sizelog2quadwords);
rb->blksizequadwords = gsl_cfg_rb_blksizequadwords;
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
rb->mutex = kmalloc(sizeof(struct mutex), GFP_KERNEL);
if (!rb->mutex)
return GSL_FAILURE;
mutex_init(rb->mutex);
#endif
// allocate memory for ringbuffer, needs to be double octword aligned
// align on page from contiguous physical memory
@@ -738,7 +743,9 @@ kgsl_ringbuffer_close(gsl_ringbuffer_t *rb)
kgsl_log_write( KGSL_LOG_GROUP_COMMAND | KGSL_LOG_LEVEL_TRACE,
"--> int kgsl_ringbuffer_close(gsl_ringbuffer_t *rb=0x%08x)\n", rb );
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(rb->mutex);
#endif
// stop ringbuffer
kgsl_ringbuffer_stop(rb);
@@ -756,8 +763,10 @@ kgsl_ringbuffer_close(gsl_ringbuffer_t *rb)
rb->flags &= ~GSL_FLAGS_INITIALIZED;
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(rb->mutex);
kfree(rb->mutex);
#endif
memset(rb, 0, sizeof(gsl_ringbuffer_t));
@@ -880,8 +889,9 @@ kgsl_ringbuffer_issueibcmds(struct kgsl_device *device, int drawctxt_index, uint
KGSL_DEBUG(GSL_DBGFLAGS_DUMPX, dumpx_swap = kgsl_dumpx_parse_ibs(ibaddr, sizedwords));
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_lock(rb->mutex);
#endif
// context switch if needed
kgsl_drawctxt_switch(device, &device->drawctxt[drawctxt_index], flags);
@@ -891,8 +901,9 @@ kgsl_ringbuffer_issueibcmds(struct kgsl_device *device, int drawctxt_index, uint
*timestamp = kgsl_ringbuffer_issuecmds(device, 0, &link[0], 3, current->tgid);
#ifdef CONFIG_KGSL_FINE_GRAINED_LOCKING
mutex_unlock(rb->mutex);
#endif
// idle device when running in safe mode
if (device->flags & GSL_FLAGS_SAFEMODE)
{