int i915_gem_context_destroy_ioctl(struct drm_device *dev, void *data,
				   struct drm_file *file)
{
	struct drm_i915_gem_context_destroy *args = data;
	struct drm_i915_file_private *file_priv = file->driver_priv;
	struct i915_hw_context *ctx;
	int ret;

	if (!(dev->driver->driver_features & DRIVER_GEM))
		return -ENODEV;

	ret = i915_mutex_lock_interruptible(dev);
	if (ret)
		return ret;

	ctx = i915_gem_context_get(file_priv, args->ctx_id);
	if (!ctx) {
		mutex_unlock(&dev->struct_mutex);
		return -ENOENT;
	}

	do_destroy(ctx);

	mutex_unlock(&dev->struct_mutex);

	DRM_DEBUG_DRIVER("HW context %d destroyed\n", args->ctx_id);
	return 0;
}
Exemplo n.º 2
0
/**
 * i915_switch_context() - perform a GPU context switch.
 * @ring: ring for which we'll execute the context switch
 * @file_priv: file_priv associated with the context, may be NULL
 * @id: context id number
 * @seqno: sequence number by which the new context will be switched to
 * @flags:
 *
 * The context life cycle is simple. The context refcount is incremented and
 * decremented by 1 and create and destroy. If the context is in use by the GPU,
 * it will have a refoucnt > 1. This allows us to destroy the context abstract
 * object while letting the normal object tracking destroy the backing BO.
 */
int i915_switch_context(struct intel_ring_buffer *ring,
			struct drm_file *file,
			int to_id)
{
	struct drm_i915_private *dev_priv = ring->dev->dev_private;
	struct i915_hw_context *to;

	if (dev_priv->hw_contexts_disabled)
		return 0;

	if (ring != &dev_priv->rings[RCS])
		return 0;

	if (to_id == DEFAULT_CONTEXT_ID) {
		to = ring->default_context;
	} else {
		if (file == NULL)
			return -EINVAL;

		to = i915_gem_context_get(file->driver_priv, to_id);
		if (to == NULL)
			return -ENOENT;
	}

	return do_switch(to);
}
/**
 * i915_switch_context() - perform a GPU context switch.
 * @ring: ring for which we'll execute the context switch
 * @file_priv: file_priv associated with the context, may be NULL
 * @id: context id number
 * @seqno: sequence number by which the new context will be switched to
 * @flags:
 *
 * The context life cycle is simple. The context refcount is incremented and
 * decremented by 1 and create and destroy. If the context is in use by the GPU,
 * it will have a refoucnt > 1. This allows us to destroy the context abstract
 * object while letting the normal object tracking destroy the backing BO.
 */
int i915_switch_context(struct intel_ring_buffer *ring,
			struct drm_file *file,
			int to_id)
{
	struct drm_i915_private *dev_priv = ring->dev->dev_private;
	struct drm_i915_file_private *file_priv = NULL;
	struct i915_hw_context *to;
	struct drm_i915_gem_object *from_obj = ring->last_context_obj;

	if (dev_priv->hw_contexts_disabled)
		return 0;

	if (ring != &dev_priv->ring[RCS])
		return 0;

	if (file)
		file_priv = file->driver_priv;

	if (to_id == DEFAULT_CONTEXT_ID) {
		to = ring->default_context;
	} else {
		to = i915_gem_context_get(file_priv, to_id);
		if (to == NULL)
			return -ENOENT;
	}

	if (from_obj == to->obj)
		return 0;

	return do_switch(from_obj, to, i915_gem_next_request_seqno(to->ring));
}
Exemplo n.º 4
0
struct i915_ctx_hang_stats *
i915_gem_context_get_hang_stats(struct intel_ring_buffer *ring,
				struct drm_file *file,
				u32 id)
{
	struct drm_i915_private *dev_priv = ring->dev->dev_private;
	struct drm_i915_file_private *file_priv = file->driver_priv;
	struct i915_hw_context *to;

	if (dev_priv->hw_contexts_disabled)
		return ERR_PTR(-ENOENT);

	if (ring->id != RCS)
		return ERR_PTR(-EINVAL);

	if (file == NULL)
		return ERR_PTR(-EINVAL);

	if (id == DEFAULT_CONTEXT_ID)
		return &file_priv->hang_stats;

	to = i915_gem_context_get(file->driver_priv, id);
	if (to == NULL)
		return ERR_PTR(-ENOENT);

	return &to->hang_stats;
}
/**
 * i915_switch_context() - perform a GPU context switch.
 * @ring: ring for which we'll execute the context switch
 * @file_priv: file_priv associated with the context, may be NULL
 * @id: context id number
 *
 * The context life cycle is simple. The context refcount is incremented and
 * decremented by 1 and create and destroy. If the context is in use by the GPU,
 * it will have a refoucnt > 1. This allows us to destroy the context abstract
 * object while letting the normal object tracking destroy the backing BO.
 */
int i915_switch_context(struct intel_ring_buffer *ring,
			struct drm_file *file,
			int to_id)
{
	struct drm_i915_private *dev_priv = ring->dev->dev_private;
	struct i915_hw_context *to;

	if (!HAS_HW_CONTEXTS(ring->dev))
		return 0;

	WARN_ON(!mutex_is_locked(&dev_priv->dev->struct_mutex));

	if (ring != &dev_priv->ring[RCS])
		return 0;

	if (to_id == DEFAULT_CONTEXT_ID) {
		to = ring->default_context;
	} else {
		if (file == NULL)
			return -EINVAL;

		to = i915_gem_context_get(file->driver_priv, to_id);
		if (to == NULL)
			return -ENOENT;
	}

	return do_switch(to);
}
Exemplo n.º 6
0
int __intel_context_do_pin(struct intel_context *ce)
{
	int err;

	if (mutex_lock_interruptible(&ce->pin_mutex))
		return -EINTR;

	if (likely(!atomic_read(&ce->pin_count))) {
		intel_wakeref_t wakeref;

		err = 0;
		with_intel_runtime_pm(ce->engine->i915, wakeref)
			err = ce->ops->pin(ce);
		if (err)
			goto err;

		i915_gem_context_get(ce->gem_context); /* for ctx->ppgtt */

		intel_context_get(ce);
		smp_mb__before_atomic(); /* flush pin before it is visible */
	}

	atomic_inc(&ce->pin_count);
	GEM_BUG_ON(!intel_context_is_pinned(ce)); /* no overflow! */

	mutex_unlock(&ce->pin_mutex);
	return 0;

err:
	mutex_unlock(&ce->pin_mutex);
	return err;
}
struct i915_ctx_hang_stats *
i915_gem_context_get_hang_stats(struct drm_device *dev,
				struct drm_file *file,
				u32 id)
{
	struct drm_i915_file_private *file_priv = file->driver_priv;
	struct i915_hw_context *ctx;

	if (id == DEFAULT_CONTEXT_ID)
		return &file_priv->hang_stats;

	if (!HAS_HW_CONTEXTS(dev))
		return ERR_PTR(-ENOENT);

	ctx = i915_gem_context_get(file->driver_priv, id);
	if (ctx == NULL)
		return ERR_PTR(-ENOENT);

	return &ctx->hang_stats;
}
Exemplo n.º 8
0
int i915_get_reset_stats_ioctl(struct drm_device *dev,
			       void *data, struct drm_file *file)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_reset_stats *args = data;
	struct i915_ctx_hang_stats *hs;
	struct intel_context *ctx;
	int ret;

	if (args->flags || args->pad)
		return -EINVAL;

	if (args->ctx_id == DEFAULT_CONTEXT_HANDLE && !capable(CAP_SYS_ADMIN))
		return -EPERM;

	ret = mutex_lock_interruptible(&dev->struct_mutex);
	if (ret)
		return ret;

	ctx = i915_gem_context_get(file->driver_priv, args->ctx_id);
	if (IS_ERR(ctx)) {
		mutex_unlock(&dev->struct_mutex);
		return PTR_ERR(ctx);
	}
	hs = &ctx->hang_stats;

	if (capable(CAP_SYS_ADMIN))
		args->reset_count = i915_reset_count(&dev_priv->gpu_error);
	else
		args->reset_count = 0;

	args->batch_active = hs->batch_active;
	args->batch_pending = hs->batch_pending;

	mutex_unlock(&dev->struct_mutex);

	return 0;
}