Browse Source

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/anholt/drm-intel

* '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
Linus Torvalds 16 years ago
parent
commit
932088b136

+ 1 - 1
drivers/gpu/drm/i915/i915_dma.c

@@ -1105,7 +1105,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
 					 1024 * 1024,
 					 1024 * 1024,
 					 MTRR_TYPE_WRCOMB, 1);
 					 MTRR_TYPE_WRCOMB, 1);
 	if (dev_priv->mm.gtt_mtrr < 0) {
 	if (dev_priv->mm.gtt_mtrr < 0) {
-		DRM_INFO("MTRR allocation failed\n.  Graphics "
+		DRM_INFO("MTRR allocation failed.  Graphics "
 			 "performance may suffer.\n");
 			 "performance may suffer.\n");
 	}
 	}
 
 

+ 6 - 1
drivers/gpu/drm/i915/i915_drv.h

@@ -279,7 +279,6 @@ typedef struct drm_i915_private {
 	u8 saveAR_INDEX;
 	u8 saveAR_INDEX;
 	u8 saveAR[21];
 	u8 saveAR[21];
 	u8 saveDACMASK;
 	u8 saveDACMASK;
-	u8 saveDACDATA[256*3]; /* 256 3-byte colors */
 	u8 saveCR[37];
 	u8 saveCR[37];
 
 
 	struct {
 	struct {
@@ -457,6 +456,12 @@ struct drm_i915_gem_object {
 
 
 	/** for phy allocated objects */
 	/** for phy allocated objects */
 	struct drm_i915_gem_phys_object *phys_obj;
 	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
drivers/gpu/drm/i915/i915_gem.c

@@ -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;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	int regnum = obj_priv->fence_reg;
 	int regnum = obj_priv->fence_reg;
 	int tile_width;
 	int tile_width;
-	uint32_t val;
+	uint32_t fence_reg, val;
 	uint32_t pitch_val;
 	uint32_t pitch_val;
 
 
 	if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
 	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 |= pitch_val << I830_FENCE_PITCH_SHIFT;
 	val |= I830_FENCE_REG_VALID;
 	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)
 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_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	struct drm_i915_fence_reg *reg = NULL;
 	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) {
 	switch (obj_priv->tiling_mode) {
 	case I915_TILING_NONE:
 	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 */
 	/* 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++) {
 	for (i = dev_priv->fence_reg_start; i < dev_priv->num_fence_regs; i++) {
 		reg = &dev_priv->fence_regs[i];
 		reg = &dev_priv->fence_regs[i];
 		if (!reg->obj)
 		if (!reg->obj)
 			break;
 			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 */
 	/* None available, try to steal one or wait for a user to finish */
 	if (i == dev_priv->num_fence_regs) {
 	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;
 		loff_t offset;
 
 
-try_again:
-		/* Could try to use LRU here instead... */
+		if (avail == 0)
+			return -ENOMEM;
+
 		for (i = dev_priv->fence_reg_start;
 		for (i = dev_priv->fence_reg_start;
 		     i < dev_priv->num_fence_regs; i++) {
 		     i < dev_priv->num_fence_regs; i++) {
+			uint32_t this_seqno;
+
 			reg = &dev_priv->fence_regs[i];
 			reg = &dev_priv->fence_regs[i];
 			old_obj_priv = reg->obj->driver_private;
 			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;
 				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 @@ try_again:
 		 * objects to finish before trying again.
 		 * objects to finish before trying again.
 		 */
 		 */
 		if (i == dev_priv->num_fence_regs) {
 		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;
 			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
 		 * Zap this virtual mapping so we can set up a fence again
 		 * for this object next time we need it.
 		 * 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))
 	if (IS_I965G(dev))
 		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
 		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
-	else
-		I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0);
+	else {
+		uint32_t fence_reg;
+
+		if (obj_priv->fence_reg < 8)
+			fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
+		else
+			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;
 	dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
 	obj_priv->fence_reg = I915_FENCE_REG_NONE;
 	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_i915_gem_exec_object *exec_list = NULL;
 	struct drm_gem_object **object_list = NULL;
 	struct drm_gem_object **object_list = NULL;
 	struct drm_gem_object *batch_obj;
 	struct drm_gem_object *batch_obj;
+	struct drm_i915_gem_object *obj_priv;
 	int ret, i, pinned = 0;
 	int ret, i, pinned = 0;
 	uint64_t exec_offset;
 	uint64_t exec_offset;
 	uint32_t seqno, flush_domains;
 	uint32_t seqno, flush_domains;
@@ -2533,6 +2579,15 @@ i915_gem_execbuffer(struct drm_device *dev, void *data,
 			ret = -EBADF;
 			ret = -EBADF;
 			goto err;
 			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 */
 	/* Pin and relocate */
@@ -2674,8 +2729,13 @@ err:
 	for (i = 0; i < pinned; i++)
 	for (i = 0; i < pinned; i++)
 		i915_gem_object_unpin(object_list[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]);
 		drm_gem_object_unreference(object_list[i]);
+	}
 
 
 	mutex_unlock(&dev->struct_mutex);
 	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);
 		ret = i915_gem_object_bind_to_gtt(obj, alignment);
 		if (ret != 0) {
 		if (ret != 0) {
 			if (ret != -EBUSY && ret != -ERESTARTSYS)
 			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) {
+		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;
 			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->pin_count++;
 	obj_priv->pin_count++;
 
 

+ 1 - 0
drivers/gpu/drm/i915/i915_reg.h

@@ -184,6 +184,7 @@
  * Fence registers
  * Fence registers
  */
  */
 #define FENCE_REG_830_0			0x2000
 #define FENCE_REG_830_0			0x2000
+#define FENCE_REG_945_8			0x3000
 #define   I830_FENCE_START_MASK		0x07f80000
 #define   I830_FENCE_START_MASK		0x07f80000
 #define   I830_FENCE_TILING_Y_SHIFT	12
 #define   I830_FENCE_TILING_Y_SHIFT	12
 #define   I830_FENCE_SIZE_BITS(size)	((ffs((size) >> 19) - 1) << 8)
 #define   I830_FENCE_SIZE_BITS(size)	((ffs((size) >> 19) - 1) << 8)

+ 0 - 11
drivers/gpu/drm/i915/i915_suspend.c

@@ -119,11 +119,6 @@ static void i915_save_vga(struct drm_device *dev)
 
 
 	/* VGA color palette registers */
 	/* VGA color palette registers */
 	dev_priv->saveDACMASK = I915_READ8(VGA_DACMASK);
 	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 */
 	/* MSR bits */
 	dev_priv->saveMSR = I915_READ8(VGA_MSR_READ);
 	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 */
 	/* VGA color palette registers */
 	I915_WRITE8(VGA_DACMASK, dev_priv->saveDACMASK);
 	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)
 int i915_save_state(struct drm_device *dev)