[Intel-gfx] [PATCH] drm/i915: Kill the active list spinlock

Chris Wilson chris at chris-wilson.co.uk
Wed Aug 4 15:09:45 CEST 2010


This spinlock only served debugging purposes in a time when we could not
be sure of the mutex ever being released upon a GPU hang. As we now
should be able rely on hangcheck to do the job for us (and that error
reporting should not itself require the struct mutex) we can kill the
incomplete and misleading attempt at protection.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/i915_debugfs.c   |   58 +++++++++++++++++++++++++-------
 drivers/gpu/drm/i915/i915_drv.h       |    2 -
 drivers/gpu/drm/i915/i915_gem.c       |   35 +------------------
 drivers/gpu/drm/i915/i915_gem_evict.c |    5 ---
 4 files changed, 47 insertions(+), 53 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 9214119..08f279b 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -71,12 +71,10 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv;
-	spinlock_t *lock = NULL;
 
 	switch (list) {
 	case ACTIVE_LIST:
 		seq_printf(m, "Active:\n");
-		lock = &dev_priv->mm.active_list_lock;
 		head = &dev_priv->render_ring.active_list;
 		break;
 	case INACTIVE_LIST:
@@ -89,11 +87,12 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 		break;
 	default:
 		DRM_INFO("Ooops, unexpected list\n");
-		return 0;
+		return -EINVAL;
 	}
 
-	if (lock)
-		spin_lock(lock);
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
+
 	list_for_each_entry(obj_priv, head, list)
 	{
 		seq_printf(m, "    %p: %s %8zd %08x %08x %d%s%s",
@@ -116,8 +115,8 @@ static int i915_gem_object_list_info(struct seq_file *m, void *data)
 		seq_printf(m, "\n");
 	}
 
-	if (lock)
-	    spin_unlock(lock);
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -128,6 +127,9 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_request *gem_request;
 
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
+
 	seq_printf(m, "Request:\n");
 	list_for_each_entry(gem_request, &dev_priv->render_ring.request_list,
 			list) {
@@ -135,6 +137,9 @@ static int i915_gem_request_info(struct seq_file *m, void *data)
 			   gem_request->seqno,
 			   (int) (jiffies - gem_request->emitted_jiffies));
 	}
+
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -144,6 +149,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
+
 	if (dev_priv->render_ring.status_page.page_addr != NULL) {
 		seq_printf(m, "Current sequence: %d\n",
 			   i915_get_gem_seqno(dev,  &dev_priv->render_ring));
@@ -153,6 +161,9 @@ static int i915_gem_seqno_info(struct seq_file *m, void *data)
 	seq_printf(m, "Waiter sequence:  %d\n",
 			dev_priv->mm.waiting_gem_seqno);
 	seq_printf(m, "IRQ sequence:     %d\n", dev_priv->mm.irq_gem_seqno);
+
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -216,6 +227,9 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int i;
 
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
+
 	seq_printf(m, "Reserved fences = %d\n", dev_priv->fence_reg_start);
 	seq_printf(m, "Total fences = %d\n", dev_priv->num_fence_regs);
 	for (i = 0; i < dev_priv->num_fence_regs; i++) {
@@ -241,6 +255,8 @@ static int i915_gem_fence_regs_info(struct seq_file *m, void *data)
 		}
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -284,9 +300,10 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_gem_object *obj;
 	struct drm_i915_gem_object *obj_priv;
-	int ret;
+	int ret = 0;
 
-	spin_lock(&dev_priv->mm.active_list_lock);
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
 
 	list_for_each_entry(obj_priv, &dev_priv->render_ring.active_list,
 			list) {
@@ -295,8 +312,7 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data)
 		    ret = i915_gem_object_get_pages(obj, 0);
 		    if (ret) {
 			    DRM_ERROR("Failed to get pages: %d\n", ret);
-			    spin_unlock(&dev_priv->mm.active_list_lock);
-			    return ret;
+			    break;
 		    }
 
 		    seq_printf(m, "--- gtt_offset = 0x%08x\n", obj_priv->gtt_offset);
@@ -306,9 +322,9 @@ static int i915_batchbuffer_info(struct seq_file *m, void *data)
 		}
 	}
 
-	spin_unlock(&dev_priv->mm.active_list_lock);
+	mutex_unlock(&dev->struct_mutex);
 
-	return 0;
+	return ret;
 }
 
 static int i915_ringbuffer_data(struct seq_file *m, void *data)
@@ -324,6 +340,9 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data)
 		return 0;
 	}
 
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
+
 	virt = dev_priv->render_ring.virtual_start;
 
 	for (off = 0; off < dev_priv->render_ring.size; off += 4) {
@@ -331,6 +350,8 @@ static int i915_ringbuffer_data(struct seq_file *m, void *data)
 		seq_printf(m, "%08x :  %08x\n", off, *ptr);
 	}
 
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -585,6 +606,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 		return 0;
 	}
 
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
+
 	if (intel_fbc_enabled(dev)) {
 		seq_printf(m, "FBC enabled\n");
 	} else {
@@ -613,6 +637,9 @@ static int i915_fbc_status(struct seq_file *m, void *unused)
 		}
 		seq_printf(m, "\n");
 	}
+
+	mutex_unlock(&dev->struct_mutex);
+
 	return 0;
 }
 
@@ -643,10 +670,15 @@ static int i915_emon_status(struct seq_file *m, void *unused)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	unsigned long temp, chipset, gfx;
 
+	if (!mutex_trylock(&dev->struct_mutex))
+		return -EBUSY;
+
 	temp = i915_mch_val(dev_priv);
 	chipset = i915_chipset_val(dev_priv);
 	gfx = i915_gfx_val(dev_priv);
 
+	mutex_unlock(&dev->struct_mutex);
+
 	seq_printf(m, "GMCH temp: %ld\n", temp);
 	seq_printf(m, "Chipset power: %ld\n", chipset);
 	seq_printf(m, "GFX power: %ld\n", gfx);
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 844d10e..ad8dab5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -518,8 +518,6 @@ typedef struct drm_i915_private {
 		 */
 		struct list_head shrink_list;
 
-		spinlock_t active_list_lock;
-
 		/**
 		 * List of objects which are not in the ringbuffer but which
 		 * still have a write_domain which needs to be flushed before
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 36d7e93..0f0c387 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1463,8 +1463,6 @@ static void
 i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno,
 			       struct intel_ring_buffer *ring)
 {
-	struct drm_device *dev = obj->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	BUG_ON(ring == NULL);
 	obj_priv->ring = ring;
@@ -1475,9 +1473,7 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno,
 		obj_priv->active = 1;
 	}
 	/* Move from whatever list we were on to the tail of execution. */
-	spin_lock(&dev_priv->mm.active_list_lock);
 	list_move_tail(&obj_priv->list, &ring->active_list);
-	spin_unlock(&dev_priv->mm.active_list_lock);
 	obj_priv->last_rendering_seqno = seqno;
 }
 
@@ -1648,14 +1644,11 @@ static void
 i915_gem_retire_request(struct drm_device *dev,
 			struct drm_i915_gem_request *request)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-
 	trace_i915_gem_request_retire(dev, request->seqno);
 
 	/* Move any buffers on the active list that are no longer referenced
 	 * by the ringbuffer to the flushing/inactive lists as appropriate.
 	 */
-	spin_lock(&dev_priv->mm.active_list_lock);
 	while (!list_empty(&request->ring->active_list)) {
 		struct drm_gem_object *obj;
 		struct drm_i915_gem_object *obj_priv;
@@ -1670,7 +1663,7 @@ i915_gem_retire_request(struct drm_device *dev,
 		 * this seqno.
 		 */
 		if (obj_priv->last_rendering_seqno != request->seqno)
-			goto out;
+			return;
 
 #if WATCH_LRU
 		DRM_INFO("%s: retire %d moves to inactive list %p\n",
@@ -1679,22 +1672,9 @@ i915_gem_retire_request(struct drm_device *dev,
 
 		if (obj->write_domain != 0)
 			i915_gem_object_move_to_flushing(obj);
-		else {
-			/* Take a reference on the object so it won't be
-			 * freed while the spinlock is held.  The list
-			 * protection for this spinlock is safe when breaking
-			 * the lock like this since the next thing we do
-			 * is just get the head of the list again.
-			 */
-			drm_gem_object_reference(obj);
+		else
 			i915_gem_object_move_to_inactive(obj);
-			spin_unlock(&dev_priv->mm.active_list_lock);
-			drm_gem_object_unreference(obj);
-			spin_lock(&dev_priv->mm.active_list_lock);
-		}
 	}
-out:
-	spin_unlock(&dev_priv->mm.active_list_lock);
 }
 
 /**
@@ -1934,7 +1914,6 @@ int
 i915_gem_object_unbind(struct drm_gem_object *obj)
 {
 	struct drm_device *dev = obj->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
 	int ret = 0;
 
@@ -1991,10 +1970,8 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
 	}
 
 	/* Remove ourselves from the LRU list if present. */
-	spin_lock(&dev_priv->mm.active_list_lock);
 	if (!list_empty(&obj_priv->list))
 		list_del_init(&obj_priv->list);
-	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	if (i915_gem_object_is_purgeable(obj_priv))
 		i915_gem_object_truncate(obj);
@@ -2012,13 +1989,10 @@ i915_gpu_idle(struct drm_device *dev)
 	uint32_t seqno1, seqno2;
 	int ret;
 
-	spin_lock(&dev_priv->mm.active_list_lock);
 	lists_empty = (list_empty(&dev_priv->mm.flushing_list) &&
 		       list_empty(&dev_priv->render_ring.active_list) &&
 		       (!HAS_BSD(dev) ||
 			list_empty(&dev_priv->bsd_ring.active_list)));
-	spin_unlock(&dev_priv->mm.active_list_lock);
-
 	if (lists_empty)
 		return 0;
 
@@ -4532,10 +4506,8 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
 		return ret;
 	}
 
-	spin_lock(&dev_priv->mm.active_list_lock);
 	BUG_ON(!list_empty(&dev_priv->render_ring.active_list));
 	BUG_ON(HAS_BSD(dev) && !list_empty(&dev_priv->bsd_ring.active_list));
-	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
 	BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
@@ -4588,7 +4560,6 @@ i915_gem_load(struct drm_device *dev)
 	int i;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
-	spin_lock_init(&dev_priv->mm.active_list_lock);
 	INIT_LIST_HEAD(&dev_priv->mm.flushing_list);
 	INIT_LIST_HEAD(&dev_priv->mm.gpu_write_list);
 	INIT_LIST_HEAD(&dev_priv->mm.inactive_list);
@@ -4843,12 +4814,10 @@ i915_gpu_is_active(struct drm_device *dev)
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	int lists_empty;
 
-	spin_lock(&dev_priv->mm.active_list_lock);
 	lists_empty = list_empty(&dev_priv->mm.flushing_list) &&
 		      list_empty(&dev_priv->render_ring.active_list);
 	if (HAS_BSD(dev))
 		lists_empty &= list_empty(&dev_priv->bsd_ring.active_list);
-	spin_unlock(&dev_priv->mm.active_list_lock);
 
 	return !lists_empty;
 }
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index 4e5af69..6804b34 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -180,14 +180,11 @@ i915_gem_evict_everything(struct drm_device *dev)
 	int ret;
 	bool lists_empty;
 
-	spin_lock(&dev_priv->mm.active_list_lock);
 	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
 		       list_empty(&dev_priv->mm.flushing_list) &&
 		       list_empty(&dev_priv->render_ring.active_list) &&
 		       (!HAS_BSD(dev)
 			|| list_empty(&dev_priv->bsd_ring.active_list)));
-	spin_unlock(&dev_priv->mm.active_list_lock);
-
 	if (lists_empty)
 		return -ENOSPC;
 
@@ -202,13 +199,11 @@ i915_gem_evict_everything(struct drm_device *dev)
 	if (ret)
 		return ret;
 
-	spin_lock(&dev_priv->mm.active_list_lock);
 	lists_empty = (list_empty(&dev_priv->mm.inactive_list) &&
 		       list_empty(&dev_priv->mm.flushing_list) &&
 		       list_empty(&dev_priv->render_ring.active_list) &&
 		       (!HAS_BSD(dev)
 			|| list_empty(&dev_priv->bsd_ring.active_list)));
-	spin_unlock(&dev_priv->mm.active_list_lock);
 	BUG_ON(!lists_empty);
 
 	return 0;
-- 
1.7.1




More information about the Intel-gfx mailing list