/** * adreno_drawctxt_detach(): detach a context from the GPU * @context: Generic KGSL context container for the context * */ int adreno_drawctxt_detach(struct kgsl_context *context) { struct kgsl_device *device; struct adreno_device *adreno_dev; struct adreno_context *drawctxt; int ret; if (context == NULL) return 0; device = context->device; adreno_dev = ADRENO_DEVICE(device); drawctxt = ADRENO_CONTEXT(context); /* deactivate context */ if (adreno_dev->drawctxt_active == drawctxt) adreno_drawctxt_switch(adreno_dev, NULL, 0); mutex_lock(&drawctxt->mutex); while (drawctxt->cmdqueue_head != drawctxt->cmdqueue_tail) { struct kgsl_cmdbatch *cmdbatch = drawctxt->cmdqueue[drawctxt->cmdqueue_head]; drawctxt->cmdqueue_head = (drawctxt->cmdqueue_head + 1) % ADRENO_CONTEXT_CMDQUEUE_SIZE; mutex_unlock(&drawctxt->mutex); /* * Don't hold the drawctxt mutex while the cmdbatch is being * destroyed because the cmdbatch destroy takes the device * mutex and the world falls in on itself */ kgsl_cmdbatch_destroy(cmdbatch); mutex_lock(&drawctxt->mutex); } mutex_unlock(&drawctxt->mutex); /* * internal_timestamp is set in adreno_ringbuffer_addcmds, * which holds the device mutex. The entire context destroy * process requires the device mutex as well. But lets * make sure we notice if the locking changes. */ BUG_ON(!mutex_is_locked(&device->mutex)); /* Wait for the last global timestamp to pass before continuing */ ret = adreno_drawctxt_wait_global(adreno_dev, context, drawctxt->internal_timestamp, 10 * 1000); /* * If the wait for global fails then nothing after this point is likely * to work very well - BUG_ON() so we can take advantage of the debug * tools to figure out what the h - e - double hockey sticks happened */ BUG_ON(ret); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(context->id, soptimestamp), drawctxt->timestamp); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), drawctxt->timestamp); adreno_profile_process_results(device); /* wake threads waiting to submit commands from this context */ wake_up_all(&drawctxt->waiting); wake_up_all(&drawctxt->wq); return ret; }
int adreno_drawctxt_detach(struct kgsl_context *context) { struct kgsl_device *device; struct adreno_device *adreno_dev; struct adreno_context *drawctxt; int ret; if (context == NULL) return 0; device = context->device; adreno_dev = ADRENO_DEVICE(device); drawctxt = ADRENO_CONTEXT(context); if (adreno_dev->drawctxt_active == drawctxt) adreno_drawctxt_switch(adreno_dev, NULL, 0); mutex_lock(&drawctxt->mutex); while (drawctxt->cmdqueue_head != drawctxt->cmdqueue_tail) { struct kgsl_cmdbatch *cmdbatch = drawctxt->cmdqueue[drawctxt->cmdqueue_head]; drawctxt->cmdqueue_head = (drawctxt->cmdqueue_head + 1) % ADRENO_CONTEXT_CMDQUEUE_SIZE; mutex_unlock(&drawctxt->mutex); kgsl_cmdbatch_destroy(cmdbatch); mutex_lock(&drawctxt->mutex); } mutex_unlock(&drawctxt->mutex); BUG_ON(!mutex_is_locked(&device->mutex)); ret = adreno_drawctxt_wait_global(adreno_dev, context, drawctxt->internal_timestamp, 10 * 1000); BUG_ON(ret); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(context->id, soptimestamp), drawctxt->timestamp); kgsl_sharedmem_writel(device, &device->memstore, KGSL_MEMSTORE_OFFSET(context->id, eoptimestamp), drawctxt->timestamp); adreno_profile_process_results(device); if (drawctxt->ops && drawctxt->ops->detach) drawctxt->ops->detach(drawctxt); wake_up_all(&drawctxt->waiting); wake_up_all(&drawctxt->wq); return ret; }