static int _add_fence_event(struct kgsl_device *device, struct kgsl_context *context, unsigned int timestamp) { struct kgsl_fence_event_priv *event; int ret; event = kmalloc(sizeof(*event), GFP_KERNEL); if (event == NULL) return -ENOMEM; /* * Increase the refcount for the context to keep it through the * callback */ _kgsl_context_get(context); event->context = context; event->timestamp = timestamp; event->context = context; ret = kgsl_add_event(device, context->id, timestamp, kgsl_fence_event_cb, event, context->dev_priv); if (ret) { kgsl_context_put(context); kfree(event); } return ret; }
static int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, struct kgsl_context *context, uint32_t timestamp, unsigned int timeout) { struct kgsl_device *device = &adreno_dev->dev; struct adreno_context *drawctxt = ADRENO_CONTEXT(context); int ret = 0; /* Needs to hold the device mutex */ BUG_ON(!mutex_is_locked(&device->mutex)); if (!_kgsl_context_get(context)) { ret = -EINVAL; goto done; } /* * If the context is invalid then return immediately - we may end up * waiting for a timestamp that will never come */ if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { kgsl_context_put(context); goto done; } trace_adreno_drawctxt_wait_start(KGSL_MEMSTORE_GLOBAL, timestamp); ret = kgsl_add_event(device, &device->global_events, timestamp, global_wait_callback, (void *) drawctxt); if (ret) { kgsl_context_put(context); goto done; } kgsl_mutex_unlock(&device->mutex, &device->mutex_owner); if (timeout) { ret = (int) wait_event_timeout(drawctxt->waiting, _check_global_timestamp(device, drawctxt, timestamp), msecs_to_jiffies(timeout)); if (ret == 0) ret = -ETIMEDOUT; else if (ret > 0) ret = 0; } else { wait_event(drawctxt->waiting, _check_global_timestamp(device, drawctxt, timestamp)); } kgsl_mutex_lock(&device->mutex, &device->mutex_owner); if (ret) kgsl_cancel_events_timestamp(device, &device->global_events, timestamp); done: trace_adreno_drawctxt_wait_done(KGSL_MEMSTORE_GLOBAL, timestamp, ret); return ret; }
int adreno_drawctxt_wait_global(struct adreno_device *adreno_dev, struct kgsl_context *context, uint32_t timestamp, unsigned int timeout) { struct kgsl_device *device = &adreno_dev->dev; struct adreno_context *drawctxt = ADRENO_CONTEXT(context); int ret = 0; BUG_ON(!mutex_is_locked(&device->mutex)); if (!_kgsl_context_get(context)) { ret = -EINVAL; goto done; } if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) { kgsl_context_put(context); goto done; } trace_adreno_drawctxt_wait_start(KGSL_MEMSTORE_GLOBAL, timestamp); ret = kgsl_add_event(device, KGSL_MEMSTORE_GLOBAL, timestamp, global_wait_callback, drawctxt, NULL); if (ret) { kgsl_context_put(context); goto done; } mutex_unlock(&device->mutex); if (timeout) { ret = (int) wait_event_timeout(drawctxt->waiting, _check_global_timestamp(device, drawctxt, timestamp), msecs_to_jiffies(timeout)); if (ret == 0) ret = -ETIMEDOUT; else if (ret > 0) ret = 0; } else { wait_event(drawctxt->waiting, _check_global_timestamp(device, drawctxt, timestamp)); } mutex_lock(&device->mutex); if (ret) kgsl_cancel_events_timestamp(device, NULL, timestamp); done: trace_adreno_drawctxt_wait_done(KGSL_MEMSTORE_GLOBAL, timestamp, ret); return ret; }
int adreno_drawctxt_switch(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, unsigned int flags) { struct kgsl_device *device = &adreno_dev->dev; int ret = 0; /* already current? */ if (adreno_dev->drawctxt_active == drawctxt) return ret; trace_adreno_drawctxt_switch(adreno_dev->drawctxt_active, drawctxt, flags); /* Get a refcount to the new instance */ if (drawctxt) { if (!_kgsl_context_get(&drawctxt->base)) return -EINVAL; ret = kgsl_mmu_setstate(&device->mmu, drawctxt->base.proc_priv->pagetable, adreno_dev->drawctxt_active ? adreno_dev->drawctxt_active->base.id : KGSL_CONTEXT_INVALID); /* Set the new context */ ret = adreno_context_restore(adreno_dev, drawctxt); if (ret) { KGSL_DRV_ERR(device, "Error in GPU context %d restore: %d\n", drawctxt->base.id, ret); return ret; } } else { /* * No context - set the default pagetable and thats it. * If there isn't a current context, the kgsl_mmu_setstate * will use the CPU path so we don't need to give * it a valid context id. */ ret = kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, adreno_dev->drawctxt_active->base.id); } /* Put the old instance of the active drawctxt */ if (adreno_dev->drawctxt_active) kgsl_context_put(&adreno_dev->drawctxt_active->base); adreno_dev->drawctxt_active = drawctxt; return 0; }
void adreno_drawctxt_switch(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, unsigned int flags) { struct kgsl_device *device = &adreno_dev->dev; if (drawctxt) { if (flags & KGSL_CONTEXT_SAVE_GMEM) /* Set the flag in context so that the save is done * when this context is switched out. */ drawctxt->flags |= CTXT_FLAGS_GMEM_SAVE; else /* Remove GMEM saving flag from the context */ drawctxt->flags &= ~CTXT_FLAGS_GMEM_SAVE; } /* already current? */ if (adreno_dev->drawctxt_active == drawctxt) { if (adreno_dev->gpudev->ctxt_draw_workaround && adreno_is_a225(adreno_dev)) adreno_dev->gpudev->ctxt_draw_workaround( adreno_dev, drawctxt); return; } KGSL_CTXT_INFO(device, "from %d to %d flags %d\n", adreno_dev->drawctxt_active ? adreno_dev->drawctxt_active->base.id : 0, drawctxt ? drawctxt->base.id : 0, flags); /* Save the old context */ adreno_dev->gpudev->ctxt_save(adreno_dev, adreno_dev->drawctxt_active); /* Put the old instance of the active drawctxt */ if (adreno_dev->drawctxt_active) { kgsl_context_put(&adreno_dev->drawctxt_active->base); adreno_dev->drawctxt_active = NULL; } /* Get a refcount to the new instance */ if (drawctxt) _kgsl_context_get(&drawctxt->base); /* Set the new context */ adreno_dev->gpudev->ctxt_restore(adreno_dev, drawctxt); adreno_dev->drawctxt_active = drawctxt; }
int adreno_drawctxt_switch(struct adreno_device *adreno_dev, struct adreno_ringbuffer *rb, struct adreno_context *drawctxt, unsigned int flags) { struct kgsl_device *device = &adreno_dev->dev; struct kgsl_pagetable *new_pt; int ret = 0; /* We always expect a valid rb */ BUG_ON(!rb); /* already current? */ if (rb->drawctxt_active == drawctxt) return ret; trace_adreno_drawctxt_switch(rb, drawctxt, flags); /* Get a refcount to the new instance */ if (drawctxt) { if (!_kgsl_context_get(&drawctxt->base)) return -EINVAL; new_pt = drawctxt->base.proc_priv->pagetable; } else { /* No context - set the default pagetable and thats it. */ new_pt = device->mmu.defaultpagetable; } ret = adreno_iommu_set_pt(rb, new_pt); if (ret) { KGSL_DRV_ERR(device, "Failed to set pagetable on rb %d\n", rb->id); return ret; } /* Put the old instance of the active drawctxt */ if (rb->drawctxt_active) kgsl_context_put(&rb->drawctxt_active->base); rb->drawctxt_active = drawctxt; /* Set the new context */ adreno_context_restore(rb); return 0; }
int adreno_drawctxt_switch(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, unsigned int flags) { struct kgsl_device *device = &adreno_dev->dev; int ret = 0; if (drawctxt) { if (flags & KGSL_CONTEXT_SAVE_GMEM) set_bit(ADRENO_CONTEXT_GMEM_SAVE, &drawctxt->priv); else clear_bit(ADRENO_CONTEXT_GMEM_SAVE, &drawctxt->priv); } if (adreno_dev->drawctxt_active == drawctxt) { if (drawctxt && drawctxt->ops->draw_workaround) ret = drawctxt->ops->draw_workaround(adreno_dev, drawctxt); return ret; } trace_adreno_drawctxt_switch(adreno_dev->drawctxt_active, drawctxt, flags); if (adreno_dev->drawctxt_active) { ret = context_save(adreno_dev, adreno_dev->drawctxt_active); if (ret) { KGSL_DRV_ERR(device, "Error in GPU context %d save: %d\n", adreno_dev->drawctxt_active->base.id, ret); return ret; } } if (drawctxt) { if (!_kgsl_context_get(&drawctxt->base)) return -EINVAL; ret = kgsl_mmu_setstate(&device->mmu, drawctxt->base.proc_priv->pagetable, adreno_dev->drawctxt_active ? adreno_dev->drawctxt_active->base.id : KGSL_CONTEXT_INVALID); ret = drawctxt->ops->restore(adreno_dev, drawctxt); if (ret) { KGSL_DRV_ERR(device, "Error in GPU context %d restore: %d\n", drawctxt->base.id, ret); return ret; } } else { ret = kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, adreno_dev->drawctxt_active->base.id); } if (adreno_dev->drawctxt_active) kgsl_context_put(&adreno_dev->drawctxt_active->base); adreno_dev->drawctxt_active = drawctxt; return 0; }
int adreno_drawctxt_switch(struct adreno_device *adreno_dev, struct adreno_context *drawctxt, unsigned int flags) { struct kgsl_device *device = &adreno_dev->dev; int ret = 0; if (drawctxt) { /* * Handle legacy gmem / save restore flag on each IB. * Userspace sets to guard IB sequences that require * gmem to be saved and clears it at the end of the * sequence. */ if (flags & KGSL_CONTEXT_SAVE_GMEM) /* Set the flag in context so that the save is done * when this context is switched out. */ set_bit(ADRENO_CONTEXT_GMEM_SAVE, &drawctxt->priv); else /* Remove GMEM saving flag from the context */ clear_bit(ADRENO_CONTEXT_GMEM_SAVE, &drawctxt->priv); } /* already current? */ if (adreno_dev->drawctxt_active == drawctxt) { if (drawctxt && drawctxt->ops->draw_workaround) ret = drawctxt->ops->draw_workaround(adreno_dev, drawctxt); return ret; } trace_adreno_drawctxt_switch(adreno_dev->drawctxt_active, drawctxt, flags); /* Get a refcount to the new instance */ if (drawctxt) { if (!_kgsl_context_get(&drawctxt->base)) return -EINVAL; ret = kgsl_mmu_setstate(&device->mmu, drawctxt->base.proc_priv->pagetable, adreno_dev->drawctxt_active ? adreno_dev->drawctxt_active->base.id : KGSL_CONTEXT_INVALID); /* Set the new context */ ret = drawctxt->ops->restore(adreno_dev, drawctxt); if (ret) { KGSL_DRV_ERR(device, "Error in GPU context %d restore: %d\n", drawctxt->base.id, ret); return ret; } } else { /* * No context - set the default pagetable and thats it. * If there isn't a current context, the kgsl_mmu_setstate * will use the CPU path so we don't need to give * it a valid context id. */ ret = kgsl_mmu_setstate(&device->mmu, device->mmu.defaultpagetable, adreno_dev->drawctxt_active->base.id); } /* Put the old instance of the active drawctxt */ if (adreno_dev->drawctxt_active) kgsl_context_put(&adreno_dev->drawctxt_active->base); adreno_dev->drawctxt_active = drawctxt; return 0; }