/** * adreno_drawctxt_wait() - sleep until a timestamp expires * @adreno_dev: pointer to the adreno_device struct * @drawctxt: Pointer to the draw context to sleep for * @timetamp: Timestamp to wait on * @timeout: Number of jiffies to wait (0 for infinite) * * Register an event to wait for a timestamp on a context and sleep until it * has past. Returns < 0 on error, -ETIMEDOUT if the timeout expires or 0 * on success */ int adreno_drawctxt_wait(struct adreno_device *adreno_dev, struct kgsl_context *context, uint32_t timestamp, unsigned int timeout) { static unsigned int io_cnt; struct kgsl_device *device = &adreno_dev->dev; struct kgsl_pwrctrl *pwr = &device->pwrctrl; struct adreno_context *drawctxt = ADRENO_CONTEXT(context); int ret, io; if (kgsl_context_detached(context)) return -EINVAL; if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) return -EDEADLK; /* Needs to hold the device mutex */ BUG_ON(!mutex_is_locked(&device->mutex)); trace_adreno_drawctxt_wait_start(context->id, timestamp); ret = kgsl_add_event(device, context->id, timestamp, wait_callback, drawctxt, NULL); if (ret) goto done; /* * For proper power accounting sometimes we need to call * io_wait_interruptible_timeout and sometimes we need to call * plain old wait_interruptible_timeout. We call the regular * timeout N times out of 100, where N is a number specified by * the current power level */ io_cnt = (io_cnt + 1) % 100; io = (io_cnt < pwr->pwrlevels[pwr->active_pwrlevel].io_fraction) ? 0 : 1; kgsl_mutex_unlock(&device->mutex, &device->mutex_owner); if (timeout) { ret = (int) adreno_wait_event_interruptible_timeout( drawctxt->waiting, _check_context_timestamp(device, drawctxt, timestamp), msecs_to_jiffies(timeout), io); if (ret == 0) ret = -ETIMEDOUT; else if (ret > 0) ret = 0; } else { ret = (int) adreno_wait_event_interruptible(drawctxt->waiting, _check_context_timestamp(device, drawctxt, timestamp), io); } kgsl_mutex_lock(&device->mutex, &device->mutex_owner); /* -EDEADLK if the context was invalidated while we were waiting */ if (drawctxt->state == ADRENO_CONTEXT_STATE_INVALID) ret = -EDEADLK; /* Return -EINVAL if the context was detached while we were waiting */ if (kgsl_context_detached(context)) ret = -EINVAL; done: trace_adreno_drawctxt_wait_done(context->id, timestamp, ret); return ret; }
/** * adreno_drawctxt_wait() - sleep until a timestamp expires * @adreno_dev: pointer to the adreno_device struct * @drawctxt: Pointer to the draw context to sleep for * @timetamp: Timestamp to wait on * @timeout: Number of jiffies to wait (0 for infinite) * * Register an event to wait for a timestamp on a context and sleep until it * has past. Returns < 0 on error, -ETIMEDOUT if the timeout expires or 0 * on success */ int adreno_drawctxt_wait(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; long ret_temp; if (kgsl_context_detached(context)) return -EINVAL; if (kgsl_context_invalid(context)) return -EDEADLK; /* Needs to hold the device mutex */ BUG_ON(!mutex_is_locked(&device->mutex)); trace_adreno_drawctxt_wait_start(context->id, timestamp); ret = kgsl_add_event(device, &context->events, timestamp, wait_callback, (void *) drawctxt); if (ret) goto done; mutex_unlock(&device->mutex); if (timeout) { ret_temp = msecs_to_jiffies(timeout); __wait_event_interruptible_timeout( drawctxt->waiting, _check_context_timestamp(device, drawctxt, timestamp), ret_temp); if (ret_temp == 0) ret = -ETIMEDOUT; else if (ret_temp > 0) ret = 0; else ret = (int) ret_temp; } else { __wait_event_interruptible(drawctxt->waiting, _check_context_timestamp(device, drawctxt, timestamp), ret_temp); ret = (int)ret_temp; } mutex_lock(&device->mutex); /* -EDEADLK if the context was invalidated while we were waiting */ if (kgsl_context_invalid(context)) ret = -EDEADLK; /* Return -EINVAL if the context was detached while we were waiting */ if (kgsl_context_detached(context)) ret = -EINVAL; done: trace_adreno_drawctxt_wait_done(context->id, timestamp, ret); return ret; }