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

Commit 932088b1 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel:
  drm/i915: fix 945 fence register writes for fence 8 and above.
  drm/i915: Protect active fences on i915
  drm/i915: Check to see if we've pinned all available fences
  drm/i915: Check fence status on every pin.
  drm/i915: First recheck for an empty fence register.
  drm/i915: Fix bad \n in MTRR failure notice.
  drm/i915: Don't restore palettes through VGA registers.
  i915: add newline to i915_gem_object_pin failure msg
  drm: Return EINVAL on duplicate objects in execbuffer object list
parents f809e5a2 dc529a4f
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1105,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
					 1024 * 1024,
					 MTRR_TYPE_WRCOMB, 1);
	if (dev_priv->mm.gtt_mtrr < 0) {
		DRM_INFO("MTRR allocation failed\n.  Graphics "
		DRM_INFO("MTRR allocation failed.  Graphics "
			 "performance may suffer.\n");
	}

+6 −1
Original line number Diff line number Diff line
@@ -279,7 +279,6 @@ typedef struct drm_i915_private {
	u8 saveAR_INDEX;
	u8 saveAR[21];
	u8 saveDACMASK;
	u8 saveDACDATA[256*3]; /* 256 3-byte colors */
	u8 saveCR[37];

	struct {
@@ -457,6 +456,12 @@ struct drm_i915_gem_object {

	/** for phy allocated objects */
	struct drm_i915_gem_phys_object *phys_obj;

	/**
	 * Used for checking the object doesn't appear more than once
	 * in an execbuffer object list.
	 */
	int in_execbuffer;
};

/**
+91 −24
Original line number Diff line number Diff line
@@ -1476,7 +1476,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
	struct drm_i915_gem_object *obj_priv = obj->driver_private;
	int regnum = obj_priv->fence_reg;
	int tile_width;
	uint32_t val;
	uint32_t fence_reg, val;
	uint32_t pitch_val;

	if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
@@ -1503,7 +1503,11 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
	val |= pitch_val << I830_FENCE_PITCH_SHIFT;
	val |= I830_FENCE_REG_VALID;

	I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
	if (regnum < 8)
		fence_reg = FENCE_REG_830_0 + (regnum * 4);
	else
		fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
	I915_WRITE(fence_reg, val);
}

static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
@@ -1557,7 +1561,8 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_gem_object *obj_priv = obj->driver_private;
	struct drm_i915_fence_reg *reg = NULL;
	int i, ret;
	struct drm_i915_gem_object *old_obj_priv = NULL;
	int i, ret, avail;

	switch (obj_priv->tiling_mode) {
	case I915_TILING_NONE:
@@ -1580,25 +1585,46 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
	}

	/* First try to find a free reg */
try_again:
	avail = 0;
	for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
		reg = &dev_priv->fence_regs[i];
		if (!reg->obj)
			break;

		old_obj_priv = reg->obj->driver_private;
		if (!old_obj_priv->pin_count)
		    avail++;
	}

	/* None available, try to steal one or wait for a user to finish */
	if (i == dev_priv->num_fence_regs) {
		struct drm_i915_gem_object *old_obj_priv = NULL;
		uint32_t seqno = dev_priv->mm.next_gem_seqno;
		loff_t offset;

try_again:
		/* Could try to use LRU here instead... */
		if (avail == 0)
			return -ENOMEM;

		for (i = dev_priv->fence_reg_start;
		     i < dev_priv->num_fence_regs; i++) {
			uint32_t this_seqno;

			reg = &dev_priv->fence_regs[i];
			old_obj_priv = reg->obj->driver_private;
			if (!old_obj_priv->pin_count)

			if (old_obj_priv->pin_count)
				continue;

			/* i915 uses fences for GPU access to tiled buffers */
			if (IS_I965G(dev) || !old_obj_priv->active)
				break;

			/* find the seqno of the first available fence */
			this_seqno = old_obj_priv->last_rendering_seqno;
			if (this_seqno != 0 &&
			    reg->obj->write_domain == 0 &&
			    i915_seqno_passed(seqno, this_seqno))
				seqno = this_seqno;
		}

		/*
@@ -1606,15 +1632,25 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, bool write)
		 * objects to finish before trying again.
		 */
		if (i == dev_priv->num_fence_regs) {
			ret = i915_gem_object_set_to_gtt_domain(reg->obj, 0);
			if (ret) {
				WARN(ret != -ERESTARTSYS,
				     "switch to GTT domain failed: %d\n", ret);
				return ret;
			if (seqno == dev_priv->mm.next_gem_seqno) {
				i915_gem_flush(dev,
					       I915_GEM_GPU_DOMAINS,
					       I915_GEM_GPU_DOMAINS);
				seqno = i915_add_request(dev,
							 I915_GEM_GPU_DOMAINS);
				if (seqno == 0)
					return -ENOMEM;
			}

			ret = i915_wait_request(dev, seqno);
			if (ret)
				return ret;
			goto try_again;
		}

		BUG_ON(old_obj_priv->active ||
		       (reg->obj->write_domain & I915_GEM_GPU_DOMAINS));

		/*
		 * Zap this virtual mapping so we can set up a fence again
		 * for this object next time we need it.
@@ -1655,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)

	if (IS_I965G(dev))
		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
	else {
		uint32_t fence_reg;

		if (obj_priv->fence_reg < 8)
			fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
		else
		I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0);
			fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg -
						       8) * 4;

		I915_WRITE(fence_reg, 0);
	}

	dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
	obj_priv->fence_reg = I915_FENCE_REG_NONE;
@@ -2469,6 +2514,7 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
	struct drm_i915_gem_exec_object *exec_list = NULL;
	struct drm_gem_object **object_list = NULL;
	struct drm_gem_object *batch_obj;
	struct drm_i915_gem_object *obj_priv;
	int ret, i, pinned = 0;
	uint64_t exec_offset;
	uint32_t seqno, flush_domains;
@@ -2533,6 +2579,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
			ret = -EBADF;
			goto err;
		}

		obj_priv = object_list[i]->driver_private;
		if (obj_priv->in_execbuffer) {
			DRM_ERROR("Object %p appears more than once in object list\n",
				   object_list[i]);
			ret = -EBADF;
			goto err;
		}
		obj_priv->in_execbuffer = true;
	}

	/* Pin and relocate */
@@ -2674,8 +2729,13 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
	for (i = 0; i < pinned; i++)
		i915_gem_object_unpin(object_list[i]);

	for (i = 0; i < args->buffer_count; i++)
	for (i = 0; i < args->buffer_count; i++) {
		if (object_list[i]) {
			obj_priv = object_list[i]->driver_private;
			obj_priv->in_execbuffer = false;
		}
		drm_gem_object_unreference(object_list[i]);
	}

	mutex_unlock(&dev->struct_mutex);

@@ -2712,17 +2772,24 @@ i915_gem_object_pin(struct drm_gem_object *obj, uint32_t alignment)
		ret = i915_gem_object_bind_to_gtt(obj, alignment);
		if (ret != 0) {
			if (ret != -EBUSY && ret != -ERESTARTSYS)
				DRM_ERROR("Failure to bind: %d", ret);
				DRM_ERROR("Failure to bind: %d\n", ret);
			return ret;
		}
	}
	/*
	 * Pre-965 chips need a fence register set up in order to
	 * properly handle tiled surfaces.
	 */
	if (!IS_I965G(dev) &&
	    obj_priv->fence_reg == I915_FENCE_REG_NONE &&
		    obj_priv->tiling_mode != I915_TILING_NONE)
			i915_gem_object_get_fence_reg(obj, true);
	    obj_priv->tiling_mode != I915_TILING_NONE) {
		ret = i915_gem_object_get_fence_reg(obj, true);
		if (ret != 0) {
			if (ret != -EBUSY && ret != -ERESTARTSYS)
				DRM_ERROR("Failure to install fence: %d\n",
					  ret);
			return ret;
		}
	}
	obj_priv->pin_count++;

+1 −0
Original line number Diff line number Diff line
@@ -184,6 +184,7 @@
 * Fence registers
 */
#define FENCE_REG_830_0			0x2000
#define FENCE_REG_945_8			0x3000
#define   I830_FENCE_START_MASK		0x07f80000
#define   I830_FENCE_TILING_Y_SHIFT	12
#define   I830_FENCE_SIZE_BITS(size)	((ffs((size) >> 19) - 1) << 8)
+0 −11
Original line number Diff line number Diff line
@@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev)

	/* VGA color palette registers */
	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
	/* DACCRX automatically increments during read */
	I915_WRITE8(VGA_DACRX, 0);
	/* Read 3 bytes of color data from each index */
	for (i = 0; i < 256 * 3; i++)
		dev_priv->saveDACDATA[i] = I915_READ8(VGA_DACDATA);

	/* MSR bits */
	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
@@ -225,12 +220,6 @@ static void i915_restore_vga(struct drm_device *dev)

	/* VGA color palette registers */
	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
	/* DACCRX automatically increments during read */
	I915_WRITE8(VGA_DACWX, 0);
	/* Read 3 bytes of color data from each index */
	for (i = 0; i < 256 * 3; i++)
		I915_WRITE8(VGA_DACDATA, dev_priv->saveDACDATA[i]);

}

int i915_save_state(struct drm_device *dev)