コード例 #1
0
void i915_gem_context_init(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	uint32_t ctx_size;

	if (!HAS_HW_CONTEXTS(dev)) {
		dev_priv->hw_contexts_disabled = true;
		return;
	}

	/* If called from reset, or thaw... we've been here already */
	if (dev_priv->hw_contexts_disabled ||
	    dev_priv->ring[RCS].default_context)
		return;

	ctx_size = get_context_size(dev);
	dev_priv->hw_context_size = get_context_size(dev);
	dev_priv->hw_context_size = round_up(dev_priv->hw_context_size, 4096);

	if (ctx_size <= 0 || ctx_size > (1<<20)) {
		dev_priv->hw_contexts_disabled = true;
		return;
	}

	if (create_default_context(dev_priv)) {
		dev_priv->hw_contexts_disabled = true;
		return;
	}

	DRM_DEBUG_DRIVER("HW context support initialized\n");
}
コード例 #2
0
int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
				  struct drm_file *file)
{
	struct drm_i915_gem_context_create *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;

	if (!HAS_HW_CONTEXTS(dev))
		return -ENODEV;

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

	ctx = create_hw_context(dev, file_priv);
	mutex_unlock(&dev->struct_mutex);
	if (IS_ERR(ctx))
		return PTR_ERR(ctx);

	args->ctx_id = ctx->id;
	DRM_DEBUG_DRIVER("HW context %d created\n", args->ctx_id);

	return 0;
}
コード例 #3
0
void i915_gem_context_init(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	if (!HAS_HW_CONTEXTS(dev)) {
		dev_priv->hw_contexts_disabled = true;
		DRM_DEBUG_DRIVER("Disabling HW Contexts; old hardware\n");
		return;
	}

	/* If called from reset, or thaw... we've been here already */
	if (dev_priv->hw_contexts_disabled ||
	    dev_priv->ring[RCS].default_context)
		return;

	dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);

	if (dev_priv->hw_context_size > (1<<20)) {
		dev_priv->hw_contexts_disabled = true;
		DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
		return;
	}

	if (create_default_context(dev_priv)) {
		dev_priv->hw_contexts_disabled = true;
		DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed\n");
		return;
	}

	DRM_DEBUG_DRIVER("HW context support initialized\n");
}
コード例 #4
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
 *
 * 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);
}
コード例 #5
0
void i915_gem_context_fini(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;

	if (!HAS_HW_CONTEXTS(dev))
		return;

	/* The only known way to stop the gpu from accessing the hw context is
	 * to reset it. Do this as the very last operation to avoid confusing
	 * other code, leading to spurious errors. */
	intel_gpu_reset(dev);

	/* When default context is created and switched to, base object refcount
	 * will be 2 (+1 from object creation and +1 from do_switch()).
	 * i915_gem_context_fini() will be called after gpu_idle() has switched
	 * to default context. So we need to unreference the base object once
	 * to offset the do_switch part, so that i915_gem_context_unreference()
	 * can then free the base object correctly. */
	WARN_ON(!dev_priv->ring[RCS].last_context);
	if (dev_priv->ring[RCS].last_context == dctx) {
		/* Fake switch to NULL context */
		WARN_ON(dctx->obj->active);
		i915_gem_object_unpin(dctx->obj);
		i915_gem_context_unreference(dctx);
	}

	i915_gem_object_unpin(dctx->obj);
	i915_gem_context_unreference(dctx);
	dev_priv->ring[RCS].default_context = NULL;
	dev_priv->ring[RCS].last_context = NULL;
}
コード例 #6
0
int i915_gem_context_init(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	int ret;

	if (!HAS_HW_CONTEXTS(dev))
		return 0;

	/* If called from reset, or thaw... we've been here already */
	if (dev_priv->ring[RCS].default_context)
		return 0;

	dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);

	if (dev_priv->hw_context_size > (1<<20)) {
		DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size\n");
		return -E2BIG;
	}

	ret = create_default_context(dev_priv);
	if (ret) {
		DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %d\n",
				 ret);
		return ret;
	}

	DRM_DEBUG_DRIVER("HW context support initialized\n");
	return 0;
}
コード例 #7
0
ファイル: i915_gem_context.c プロジェクト: asmalldev/linux
int i915_gem_context_init(struct drm_i915_private *dev_priv)
{
	struct i915_gem_context *ctx;

	/* Init should only be called once per module load. Eventually the
	 * restriction on the context_disabled check can be loosened. */
	if (WARN_ON(dev_priv->kernel_context))
		return 0;

	if (intel_vgpu_active(dev_priv) &&
	    HAS_LOGICAL_RING_CONTEXTS(dev_priv)) {
		if (!i915.enable_execlists) {
			DRM_INFO("Only EXECLIST mode is supported in vgpu.\n");
			return -EINVAL;
		}
	}

	/* Using the simple ida interface, the max is limited by sizeof(int) */
	BUILD_BUG_ON(MAX_CONTEXT_HW_ID > INT_MAX);
	ida_init(&dev_priv->context_hw_ida);

	if (i915.enable_execlists) {
		/* NB: intentionally left blank. We will allocate our own
		 * backing objects as we need them, thank you very much */
		dev_priv->hw_context_size = 0;
	} else if (HAS_HW_CONTEXTS(dev_priv)) {
		dev_priv->hw_context_size =
			round_up(get_context_size(dev_priv),
				 I915_GTT_PAGE_SIZE);
		if (dev_priv->hw_context_size > (1<<20)) {
			DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
					 dev_priv->hw_context_size);
			dev_priv->hw_context_size = 0;
		}
	}

	ctx = i915_gem_create_context(dev_priv, NULL);
	if (IS_ERR(ctx)) {
		DRM_ERROR("Failed to create default global context (error %ld)\n",
			  PTR_ERR(ctx));
		return PTR_ERR(ctx);
	}

	/* For easy recognisablity, we want the kernel context to be 0 and then
	 * all user contexts will have non-zero hw_id.
	 */
	GEM_BUG_ON(ctx->hw_id);

	i915_gem_context_clear_bannable(ctx);
	ctx->priority = I915_PRIORITY_MIN; /* lowest priority; idle task */
	dev_priv->kernel_context = ctx;

	GEM_BUG_ON(!i915_gem_context_is_kernel(ctx));

	DRM_DEBUG_DRIVER("%s context support initialized\n",
			i915.enable_execlists ? "LR" :
			dev_priv->hw_context_size ? "HW" : "fake");
	return 0;
}
コード例 #8
0
ファイル: i915_sysfs.c プロジェクト: 020gzh/linux
static ssize_t
i915_l3_write(struct file *filp, struct kobject *kobj,
	      struct bin_attribute *attr, char *buf,
	      loff_t offset, size_t count)
{
	struct device *dev = kobj_to_dev(kobj);
	struct drm_minor *dminor = dev_to_drm_minor(dev);
	struct drm_device *drm_dev = dminor->dev;
	struct drm_i915_private *dev_priv = drm_dev->dev_private;
	struct intel_context *ctx;
	u32 *temp = NULL; /* Just here to make handling failures easy */
	int slice = (int)(uintptr_t)attr->private;
	int ret;

	if (!HAS_HW_CONTEXTS(drm_dev))
		return -ENXIO;

	ret = l3_access_valid(drm_dev, offset);
	if (ret)
		return ret;

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

	if (!dev_priv->l3_parity.remap_info[slice]) {
		temp = kzalloc(GEN7_L3LOG_SIZE, GFP_KERNEL);
		if (!temp) {
			mutex_unlock(&drm_dev->struct_mutex);
			return -ENOMEM;
		}
	}

	ret = i915_gpu_idle(drm_dev);
	if (ret) {
		kfree(temp);
		mutex_unlock(&drm_dev->struct_mutex);
		return ret;
	}

	/* TODO: Ideally we really want a GPU reset here to make sure errors
	 * aren't propagated. Since I cannot find a stable way to reset the GPU
	 * at this point it is left as a TODO.
	*/
	if (temp)
		dev_priv->l3_parity.remap_info[slice] = temp;

	memcpy(dev_priv->l3_parity.remap_info[slice] + (offset/4), buf, count);

	/* NB: We defer the remapping until we switch to the context */
	list_for_each_entry(ctx, &dev_priv->context_list, link)
		ctx->remap_slice |= (1<<slice);

	mutex_unlock(&drm_dev->struct_mutex);

	return count;
}
コード例 #9
0
int i915_gem_context_init(struct drm_device *dev)
{
    struct drm_i915_private *dev_priv = dev->dev_private;
    struct intel_context *ctx;
    int i;

    /* Init should only be called once per module load. Eventually the
     * restriction on the context_disabled check can be loosened. */
    if (WARN_ON(dev_priv->ring[RCS].default_context))
        return 0;

    if (i915.enable_execlists) {
        /* NB: intentionally left blank. We will allocate our own
         * backing objects as we need them, thank you very much */
        dev_priv->hw_context_size = 0;
    } else if (HAS_HW_CONTEXTS(dev)) {
        dev_priv->hw_context_size = round_up(get_context_size(dev), 4096);
        if (dev_priv->hw_context_size > (1<<20)) {
            DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
                             dev_priv->hw_context_size);
            dev_priv->hw_context_size = 0;
        }
    }

    ctx = i915_gem_create_context(dev, NULL);
    if (IS_ERR(ctx)) {
        DRM_ERROR("Failed to create default global context (error %ld)\n",
                  PTR_ERR(ctx));
        return PTR_ERR(ctx);
    }

    for (i = 0; i < I915_NUM_RINGS; i++) {
        struct intel_engine_cs *ring = &dev_priv->ring[i];

        /* NB: RCS will hold a ref for all rings */
        ring->default_context = ctx;
    }

    DRM_DEBUG_DRIVER("%s context support initialized\n",
                     i915.enable_execlists ? "LR" :
                     dev_priv->hw_context_size ? "HW" : "fake");
    return 0;
}
コード例 #10
0
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;
}