summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2008-10-14 21:41:13 -0700
committerDave Airlie <airlied@linux.ie>2008-10-18 07:10:53 +1000
commit6dbe2772d6af067845bab57be490c302f4490ac7 (patch)
tree5d84600a5ff20a5c5390c02df2400b626ac9b140 /drivers/gpu
parentba1eb1d825fdef40f69871caf8e5842d00efbbc5 (diff)
downloadlinux-6dbe2772d6af067845bab57be490c302f4490ac7.tar.gz
linux-6dbe2772d6af067845bab57be490c302f4490ac7.tar.bz2
linux-6dbe2772d6af067845bab57be490c302f4490ac7.zip
i915: Don't run retire work handler while suspended
At leavevt and lastclose time, cancel any pending retire work handler invocation, and keep the retire work handler from requeuing itself if it is currently running. This patch restructures i915_gem_idle to perform all of these tasks instead of having both leavevt and lastclose call a sequence of functions. Signed-off-by: Keith Packard <keithp@keithp.com> Signed-off-by: Eric Anholt <eric@anholt.net> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c50
1 files changed, 28 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 99a86249bb1b..9ac73dd1b422 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -50,6 +50,9 @@ static int i915_gem_object_get_page_list(struct drm_gem_object *obj);
static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
+static void
+i915_gem_cleanup_ringbuffer(struct drm_device *dev);
+
int
i915_gem_init_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
@@ -582,7 +585,7 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains)
was_empty = list_empty(&dev_priv->mm.request_list);
list_add_tail(&request->list, &dev_priv->mm.request_list);
- if (was_empty)
+ if (was_empty && !dev_priv->mm.suspended)
schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
return seqno;
}
@@ -731,7 +734,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
mutex_lock(&dev->struct_mutex);
i915_gem_retire_requests(dev);
- if (!list_empty(&dev_priv->mm.request_list))
+ if (!dev_priv->mm.suspended &&
+ !list_empty(&dev_priv->mm.request_list))
schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
mutex_unlock(&dev->struct_mutex);
}
@@ -2227,14 +2231,24 @@ i915_gem_idle(struct drm_device *dev)
uint32_t seqno, cur_seqno, last_seqno;
int stuck, ret;
- if (dev_priv->mm.suspended)
+ mutex_lock(&dev->struct_mutex);
+
+ if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) {
+ mutex_unlock(&dev->struct_mutex);
return 0;
+ }
/* Hack! Don't let anybody do execbuf while we don't control the chip.
* We need to replace this with a semaphore, or something.
*/
dev_priv->mm.suspended = 1;
+ /* Cancel the retire work handler, wait for it to finish if running
+ */
+ mutex_unlock(&dev->struct_mutex);
+ cancel_delayed_work_sync(&dev_priv->mm.retire_work);
+ mutex_lock(&dev->struct_mutex);
+
i915_kernel_lost_context(dev);
/* Flush the GPU along with all non-CPU write domains
@@ -2284,13 +2298,19 @@ i915_gem_idle(struct drm_device *dev)
/* Move all buffers out of the GTT. */
ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
- if (ret)
+ if (ret) {
+ mutex_unlock(&dev->struct_mutex);
return ret;
+ }
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);
+ mutex_unlock(&dev->struct_mutex);
+
return 0;
}
@@ -2503,34 +2523,20 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
{
int ret;
- mutex_lock(&dev->struct_mutex);
ret = i915_gem_idle(dev);
- if (ret == 0)
- i915_gem_cleanup_ringbuffer(dev);
- mutex_unlock(&dev->struct_mutex);
-
drm_irq_uninstall(dev);
- return 0;
+ return ret;
}
void
i915_gem_lastclose(struct drm_device *dev)
{
int ret;
- drm_i915_private_t *dev_priv = dev->dev_private;
-
- mutex_lock(&dev->struct_mutex);
-
- if (dev_priv->ring.ring_obj != NULL) {
- ret = i915_gem_idle(dev);
- if (ret)
- DRM_ERROR("failed to idle hardware: %d\n", ret);
-
- i915_gem_cleanup_ringbuffer(dev);
- }
- mutex_unlock(&dev->struct_mutex);
+ ret = i915_gem_idle(dev);
+ if (ret)
+ DRM_ERROR("failed to idle hardware: %d\n", ret);
}
void