Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5df5242d authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'drm-intel-fixes-2014-04-11' of git://anongit.freedesktop.org/drm-intel into drm-next

Some fixes from Intel.

* tag 'drm-intel-fixes-2014-04-11' of git://anongit.freedesktop.org/drm-intel:
  drm/i915: Always use kref tracking for all contexts.
  drm/i915: do not setup backlight if not available according to VBT
  drm/i915: check VBT for supported backlight type
  drm/i915: Disable self-refresh for untiled fbs on i915gm
  drm/mm: Don't WARN if drm_mm_reserve_node
parents 55101e2d 691e6415
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -207,8 +207,6 @@ int drm_mm_reserve_node(struct drm_mm *mm, struct drm_mm_node *node)
		return 0;
	}

	WARN(1, "no hole found for node 0x%lx + 0x%lx\n",
	     node->start, node->size);
	return -ENOSPC;
}
EXPORT_SYMBOL(drm_mm_reserve_node);
+4 −5
Original line number Diff line number Diff line
@@ -1308,6 +1308,7 @@ struct intel_vbt_data {

	struct {
		u16 pwm_freq_hz;
		bool present;
		bool active_low_pwm;
	} backlight;

@@ -2431,19 +2432,17 @@ int i915_gem_context_open(struct drm_device *dev, struct drm_file *file);
int i915_gem_context_enable(struct drm_i915_private *dev_priv);
void i915_gem_context_close(struct drm_device *dev, struct drm_file *file);
int i915_switch_context(struct intel_ring_buffer *ring,
			struct drm_file *file, struct i915_hw_context *to);
			struct i915_hw_context *to);
struct i915_hw_context *
i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id);
void i915_gem_context_free(struct kref *ctx_ref);
static inline void i915_gem_context_reference(struct i915_hw_context *ctx)
{
	if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
	kref_get(&ctx->ref);
}

static inline void i915_gem_context_unreference(struct i915_hw_context *ctx)
{
	if (ctx->obj && HAS_HW_CONTEXTS(ctx->obj->base.dev))
	kref_put(&ctx->ref, i915_gem_context_free);
}

+1 −1
Original line number Diff line number Diff line
@@ -2790,7 +2790,7 @@ int i915_gpu_idle(struct drm_device *dev)

	/* Flush everything onto the inactive list. */
	for_each_ring(ring, dev_priv, i) {
		ret = i915_switch_context(ring, NULL, ring->default_context);
		ret = i915_switch_context(ring, ring->default_context);
		if (ret)
			return ret;

+88 −130
Original line number Diff line number Diff line
@@ -96,9 +96,6 @@
#define GEN6_CONTEXT_ALIGN (64<<10)
#define GEN7_CONTEXT_ALIGN 4096

static int do_switch(struct intel_ring_buffer *ring,
		     struct i915_hw_context *to);

static void do_ppgtt_cleanup(struct i915_hw_ppgtt *ppgtt)
{
	struct drm_device *dev = ppgtt->base.dev;
@@ -185,6 +182,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
						   typeof(*ctx), ref);
	struct i915_hw_ppgtt *ppgtt = NULL;

	if (ctx->obj) {
		/* We refcount even the aliasing PPGTT to keep the code symmetric */
		if (USES_PPGTT(ctx->obj->base.dev))
			ppgtt = ctx_to_ppgtt(ctx);
@@ -192,6 +190,7 @@ void i915_gem_context_free(struct kref *ctx_ref)
		/* XXX: Free up the object before tearing down the address space, in
		 * case we're bound in the PPGTT */
		drm_gem_object_unreference(&ctx->obj->base);
	}

	if (ppgtt)
		kref_put(&ppgtt->ref, ppgtt_release);
@@ -232,12 +231,13 @@ __create_hw_context(struct drm_device *dev,
		return ERR_PTR(-ENOMEM);

	kref_init(&ctx->ref);
	list_add_tail(&ctx->link, &dev_priv->context_list);

	if (dev_priv->hw_context_size) {
		ctx->obj = i915_gem_alloc_object(dev, dev_priv->hw_context_size);
	INIT_LIST_HEAD(&ctx->link);
		if (ctx->obj == NULL) {
		kfree(ctx);
		DRM_DEBUG_DRIVER("Context object allocated failed\n");
		return ERR_PTR(-ENOMEM);
			ret = -ENOMEM;
			goto err_out;
		}

		if (INTEL_INFO(dev)->gen >= 7) {
@@ -247,17 +247,16 @@ __create_hw_context(struct drm_device *dev,
			if (WARN_ON(ret))
				goto err_out;
		}

	list_add_tail(&ctx->link, &dev_priv->context_list);
	}

	/* Default context will never have a file_priv */
	if (file_priv == NULL)
		return ctx;

	ret = idr_alloc(&file_priv->context_idr, ctx, DEFAULT_CONTEXT_ID, 0,
			GFP_KERNEL);
	if (file_priv != NULL) {
		ret = idr_alloc(&file_priv->context_idr, ctx,
				DEFAULT_CONTEXT_ID, 0, GFP_KERNEL);
		if (ret < 0)
			goto err_out;
	} else
		ret = DEFAULT_CONTEXT_ID;

	ctx->file_priv = file_priv;
	ctx->id = ret;
@@ -294,7 +293,7 @@ i915_gem_create_context(struct drm_device *dev,
	if (IS_ERR(ctx))
		return ctx;

	if (is_global_default_ctx) {
	if (is_global_default_ctx && ctx->obj) {
		/* We may need to do things with the shrinker which
		 * require us to immediately switch back to the default
		 * context. This can cause a problem as pinning the
@@ -342,7 +341,7 @@ i915_gem_create_context(struct drm_device *dev,
	return ctx;

err_unpin:
	if (is_global_default_ctx)
	if (is_global_default_ctx && ctx->obj)
		i915_gem_object_ggtt_unpin(ctx->obj);
err_destroy:
	i915_gem_context_unreference(ctx);
@@ -352,32 +351,22 @@ i915_gem_create_context(struct drm_device *dev,
void i915_gem_context_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_ring_buffer *ring;
	int i;

	if (!HAS_HW_CONTEXTS(dev))
		return;

	/* Prevent the hardware from restoring the last context (which hung) on
	 * the next switch */
	for (i = 0; i < I915_NUM_RINGS; i++) {
		struct i915_hw_context *dctx;
		if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
			continue;
		struct intel_ring_buffer *ring = &dev_priv->ring[i];
		struct i915_hw_context *dctx = ring->default_context;

		/* Do a fake switch to the default context */
		ring = &dev_priv->ring[i];
		dctx = ring->default_context;
		if (WARN_ON(!dctx))
		if (ring->last_context == dctx)
			continue;

		if (!ring->last_context)
			continue;

		if (ring->last_context == dctx)
			continue;

		if (i == RCS) {
		if (dctx->obj && i == RCS) {
			WARN_ON(i915_gem_obj_ggtt_pin(dctx->obj,
						      get_context_alignment(dev), 0));
			/* Fake a finish/inactive */
@@ -394,44 +383,35 @@ void i915_gem_context_reset(struct drm_device *dev)
int i915_gem_context_init(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct intel_ring_buffer *ring;
	struct i915_hw_context *ctx;
	int i;

	if (!HAS_HW_CONTEXTS(dev))
		return 0;

	/* 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 (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\n");
		return -E2BIG;
			DRM_DEBUG_DRIVER("Disabling HW Contexts; invalid size %d\n",
					 dev_priv->hw_context_size);
			dev_priv->hw_context_size = 0;
		}

	dev_priv->ring[RCS].default_context =
		i915_gem_create_context(dev, NULL, USES_PPGTT(dev));

	if (IS_ERR_OR_NULL(dev_priv->ring[RCS].default_context)) {
		DRM_DEBUG_DRIVER("Disabling HW Contexts; create failed %ld\n",
				 PTR_ERR(dev_priv->ring[RCS].default_context));
		return PTR_ERR(dev_priv->ring[RCS].default_context);
	}

	for (i = RCS + 1; i < I915_NUM_RINGS; i++) {
		if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
			continue;

		ring = &dev_priv->ring[i];
	ctx = i915_gem_create_context(dev, NULL, USES_PPGTT(dev));
	if (IS_ERR(ctx)) {
		DRM_ERROR("Failed to create default global context (error %ld)\n",
			  PTR_ERR(ctx));
		return PTR_ERR(ctx);
	}

	/* NB: RCS will hold a ref for all rings */
		ring->default_context = dev_priv->ring[RCS].default_context;
	}
	for (i = 0; i < I915_NUM_RINGS; i++)
		dev_priv->ring[i].default_context = ctx;

	DRM_DEBUG_DRIVER("HW context support initialized\n");
	DRM_DEBUG_DRIVER("%s context support initialized\n", dev_priv->hw_context_size ? "HW" : "fake");
	return 0;
}

@@ -441,9 +421,7 @@ void i915_gem_context_fini(struct drm_device *dev)
	struct i915_hw_context *dctx = dev_priv->ring[RCS].default_context;
	int i;

	if (!HAS_HW_CONTEXTS(dev))
		return;

	if (dctx->obj) {
		/* 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. */
@@ -463,11 +441,10 @@ void i915_gem_context_fini(struct drm_device *dev)
			i915_gem_context_unreference(dctx);
			dev_priv->ring[RCS].last_context = NULL;
		}
	}

	for (i = 0; i < I915_NUM_RINGS; i++) {
		struct intel_ring_buffer *ring = &dev_priv->ring[i];
		if (!(INTEL_INFO(dev)->ring_mask & (1<<i)))
			continue;

		if (ring->last_context)
			i915_gem_context_unreference(ring->last_context);
@@ -478,7 +455,6 @@ void i915_gem_context_fini(struct drm_device *dev)

	i915_gem_object_ggtt_unpin(dctx->obj);
	i915_gem_context_unreference(dctx);
	dev_priv->mm.aliasing_ppgtt = NULL;
}

int i915_gem_context_enable(struct drm_i915_private *dev_priv)
@@ -486,9 +462,6 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
	struct intel_ring_buffer *ring;
	int ret, i;

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

	/* This is the only place the aliasing PPGTT gets enabled, which means
	 * it has to happen before we bail on reset */
	if (dev_priv->mm.aliasing_ppgtt) {
@@ -503,7 +476,7 @@ int i915_gem_context_enable(struct drm_i915_private *dev_priv)
	BUG_ON(!dev_priv->ring[RCS].default_context);

	for_each_ring(ring, dev_priv, i) {
		ret = do_switch(ring, ring->default_context);
		ret = i915_switch_context(ring, ring->default_context);
		if (ret)
			return ret;
	}
@@ -526,19 +499,6 @@ static int context_idr_cleanup(int id, void *p, void *data)
int i915_gem_context_open(struct drm_device *dev, struct drm_file *file)
{
	struct drm_i915_file_private *file_priv = file->driver_priv;
	struct drm_i915_private *dev_priv = dev->dev_private;

	if (!HAS_HW_CONTEXTS(dev)) {
		/* Cheat for hang stats */
		file_priv->private_default_ctx =
			kzalloc(sizeof(struct i915_hw_context), GFP_KERNEL);

		if (file_priv->private_default_ctx == NULL)
			return -ENOMEM;

		file_priv->private_default_ctx->vm = &dev_priv->gtt.base;
		return 0;
	}

	idr_init(&file_priv->context_idr);

@@ -559,14 +519,10 @@ void i915_gem_context_close(struct drm_device *dev, struct drm_file *file)
{
	struct drm_i915_file_private *file_priv = file->driver_priv;

	if (!HAS_HW_CONTEXTS(dev)) {
		kfree(file_priv->private_default_ctx);
		return;
	}

	idr_for_each(&file_priv->context_idr, context_idr_cleanup, NULL);
	i915_gem_context_unreference(file_priv->private_default_ctx);
	idr_destroy(&file_priv->context_idr);

	i915_gem_context_unreference(file_priv->private_default_ctx);
}

struct i915_hw_context *
@@ -574,9 +530,6 @@ i915_gem_context_get(struct drm_i915_file_private *file_priv, u32 id)
{
	struct i915_hw_context *ctx;

	if (!HAS_HW_CONTEXTS(file_priv->dev_priv->dev))
		return file_priv->private_default_ctx;

	ctx = (struct i915_hw_context *)idr_find(&file_priv->context_idr, id);
	if (!ctx)
		return ERR_PTR(-ENOENT);
@@ -758,7 +711,6 @@ static int do_switch(struct intel_ring_buffer *ring,
/**
 * 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
 * @to: the context to switch to
 *
 * The context life cycle is simple. The context refcount is incremented and
@@ -767,24 +719,30 @@ static int do_switch(struct intel_ring_buffer *ring,
 * object while letting the normal object tracking destroy the backing BO.
 */
int i915_switch_context(struct intel_ring_buffer *ring,
			struct drm_file *file,
			struct i915_hw_context *to)
{
	struct drm_i915_private *dev_priv = ring->dev->dev_private;

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

	BUG_ON(file && to == NULL);

	/* We have the fake context */
	if (!HAS_HW_CONTEXTS(ring->dev)) {
	if (to->obj == NULL) { /* We have the fake context */
		if (to != ring->last_context) {
			i915_gem_context_reference(to);
			if (ring->last_context)
				i915_gem_context_unreference(ring->last_context);
			ring->last_context = to;
		}
		return 0;
	}

	return do_switch(ring, to);
}

static bool hw_context_enabled(struct drm_device *dev)
{
	return to_i915(dev)->hw_context_size;
}

int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
				  struct drm_file *file)
{
@@ -793,7 +751,7 @@ int i915_gem_context_create_ioctl(struct drm_device *dev, void *data,
	struct i915_hw_context *ctx;
	int ret;

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

	ret = i915_mutex_lock_interruptible(dev);
+1 −1
Original line number Diff line number Diff line
@@ -1221,7 +1221,7 @@ i915_gem_do_execbuffer(struct drm_device *dev, void *data,
	if (ret)
		goto err;

	ret = i915_switch_context(ring, file, ctx);
	ret = i915_switch_context(ring, ctx);
	if (ret)
		goto err;

Loading