summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-06-13 19:49:47 -0700
committerKeith Packard <keithp@keithp.com>2008-06-13 19:49:47 -0700
commit3e48e144992fb11b31875989d45bc8a7c041cdef (patch)
treee7ae7a37d424041a33b99814af84c925a79734f4
parent19c3418848ccdbb163cd16b354b14b0559813d6c (diff)
[intel-gem] Execute MI_FLUSH in leavevt_ioctl
In leavevt_ioctl, queue an MI_FLUSH and then block waiting for it to complete. This will empty the active and flushing lists. That leaves only the inactive list to evict.
-rw-r--r--linux-core/i915_gem.c52
1 files changed, 33 insertions, 19 deletions
diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c
index 5e5c0ea1..308674d8 100644
--- a/linux-core/i915_gem.c
+++ b/linux-core/i915_gem.c
@@ -2127,6 +2127,10 @@ i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
return ret;
mutex_lock(&dev->struct_mutex);
+ BUG_ON(!list_empty(&dev_priv->mm.active_list));
+ BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
+ BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
+ BUG_ON(!list_empty(&dev_priv->mm.request_list));
dev_priv->mm.suspended = 0;
mutex_unlock(&dev->struct_mutex);
return 0;
@@ -2170,6 +2174,8 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
drm_i915_private_t *dev_priv = dev->dev_private;
+ uint32_t seqno;
+ int ret;
mutex_lock(&dev->struct_mutex);
/* Hack! Don't let anybody do execbuf while we don't control the chip.
@@ -2177,32 +2183,40 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
*/
dev_priv->mm.suspended = 1;
- /* Move all buffers out of the GTT. */
- i915_gem_evict_from_list(dev, &dev_priv->mm.active_list);
- i915_gem_evict_from_list(dev, &dev_priv->mm.flushing_list);
- i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
+ i915_kernel_lost_context(dev);
- /* Make sure the harware's idle. */
- while (!list_empty(&dev_priv->mm.request_list)) {
- struct drm_i915_gem_request *request;
- int ret;
+ /* Flush the GPU along with all non-CPU write domains
+ */
+ i915_gem_flush(dev, ~I915_GEM_DOMAIN_CPU, ~I915_GEM_DOMAIN_CPU);
+ seqno = i915_add_request(dev, ~I915_GEM_DOMAIN_CPU);
+ if (seqno == 0) {
+ mutex_unlock(&dev->struct_mutex);
+ return -ENOMEM;
+ }
+ ret = i915_wait_request(dev, seqno);
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
+ return ret;
+ }
- request = list_first_entry(&dev_priv->mm.request_list,
- struct drm_i915_gem_request,
- list);
+ /* Active and flushing should now be empty as we've
+ * waited for a sequence higher than any pending execbuffer
+ */
+ BUG_ON(!list_empty(&dev_priv->mm.active_list));
+ BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
- ret = i915_wait_request(dev, request->seqno);
- if (ret != 0) {
- DRM_ERROR("Error waiting for idle at LeaveVT: %d\n",
- ret);
- mutex_unlock(&dev->struct_mutex);
- return ret;
- }
- }
+ /* Request should now be empty as we've also waited
+ * for the last request in the list
+ */
+ BUG_ON(!list_empty(&dev_priv->mm.request_list));
+
+ /* Move all buffers out of the GTT. */
+ i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
BUG_ON(!list_empty(&dev_priv->mm.active_list));
BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
+ BUG_ON(!list_empty(&dev_priv->mm.request_list));
i915_gem_cleanup_ringbuffer(dev);