aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
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);
50static void i915_gem_object_free_page_list(struct drm_gem_object *obj); 50static void i915_gem_object_free_page_list(struct drm_gem_object *obj);
51static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); 51static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
52 52
53static void
54i915_gem_cleanup_ringbuffer(struct drm_device *dev);
55
53int 56int
54i915_gem_init_ioctl(struct drm_device *dev, void *data, 57i915_gem_init_ioctl(struct drm_device *dev, void *data,
55 struct drm_file *file_priv) 58 struct drm_file *file_priv)
@@ -582,7 +585,7 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains)
582 was_empty = list_empty(&dev_priv->mm.request_list); 585 was_empty = list_empty(&dev_priv->mm.request_list);
583 list_add_tail(&request->list, &dev_priv->mm.request_list); 586 list_add_tail(&request->list, &dev_priv->mm.request_list);
584 587
585 if (was_empty) 588 if (was_empty && !dev_priv->mm.suspended)
586 schedule_delayed_work(&dev_priv->mm.retire_work, HZ); 589 schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
587 return seqno; 590 return seqno;
588} 591}
@@ -731,7 +734,8 @@ i915_gem_retire_work_handler(struct work_struct *work)
731 734
732 mutex_lock(&dev->struct_mutex); 735 mutex_lock(&dev->struct_mutex);
733 i915_gem_retire_requests(dev); 736 i915_gem_retire_requests(dev);
734 if (!list_empty(&dev_priv->mm.request_list)) 737 if (!dev_priv->mm.suspended &&
738 !list_empty(&dev_priv->mm.request_list))
735 schedule_delayed_work(&dev_priv->mm.retire_work, HZ); 739 schedule_delayed_work(&dev_priv->mm.retire_work, HZ);
736 mutex_unlock(&dev->struct_mutex); 740 mutex_unlock(&dev->struct_mutex);
737} 741}
@@ -2227,14 +2231,24 @@ i915_gem_idle(struct drm_device *dev)
2227 uint32_t seqno, cur_seqno, last_seqno; 2231 uint32_t seqno, cur_seqno, last_seqno;
2228 int stuck, ret; 2232 int stuck, ret;
2229 2233
2230 if (dev_priv->mm.suspended) 2234 mutex_lock(&dev->struct_mutex);
2235
2236 if (dev_priv->mm.suspended || dev_priv->ring.ring_obj == NULL) {
2237 mutex_unlock(&dev->struct_mutex);
2231 return 0; 2238 return 0;
2239 }
2232 2240
2233 /* Hack! Don't let anybody do execbuf while we don't control the chip. 2241 /* Hack! Don't let anybody do execbuf while we don't control the chip.
2234 * We need to replace this with a semaphore, or something. 2242 * We need to replace this with a semaphore, or something.
2235 */ 2243 */
2236 dev_priv->mm.suspended = 1; 2244 dev_priv->mm.suspended = 1;
2237 2245
2246 /* Cancel the retire work handler, wait for it to finish if running
2247 */
2248 mutex_unlock(&dev->struct_mutex);
2249 cancel_delayed_work_sync(&dev_priv->mm.retire_work);
2250 mutex_lock(&dev->struct_mutex);
2251
2238 i915_kernel_lost_context(dev); 2252 i915_kernel_lost_context(dev);
2239 2253
2240 /* Flush the GPU along with all non-CPU write domains 2254 /* Flush the GPU along with all non-CPU write domains
@@ -2284,13 +2298,19 @@ i915_gem_idle(struct drm_device *dev)
2284 2298
2285 /* Move all buffers out of the GTT. */ 2299 /* Move all buffers out of the GTT. */
2286 ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list); 2300 ret = i915_gem_evict_from_list(dev, &dev_priv->mm.inactive_list);
2287 if (ret) 2301 if (ret) {
2302 mutex_unlock(&dev->struct_mutex);
2288 return ret; 2303 return ret;
2304 }
2289 2305
2290 BUG_ON(!list_empty(&dev_priv->mm.active_list)); 2306 BUG_ON(!list_empty(&dev_priv->mm.active_list));
2291 BUG_ON(!list_empty(&dev_priv->mm.flushing_list)); 2307 BUG_ON(!list_empty(&dev_priv->mm.flushing_list));
2292 BUG_ON(!list_empty(&dev_priv->mm.inactive_list)); 2308 BUG_ON(!list_empty(&dev_priv->mm.inactive_list));
2293 BUG_ON(!list_empty(&dev_priv->mm.request_list)); 2309 BUG_ON(!list_empty(&dev_priv->mm.request_list));
2310
2311 i915_gem_cleanup_ringbuffer(dev);
2312 mutex_unlock(&dev->struct_mutex);
2313
2294 return 0; 2314 return 0;
2295} 2315}
2296 2316
@@ -2503,34 +2523,20 @@ i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
2503{ 2523{
2504 int ret; 2524 int ret;
2505 2525
2506 mutex_lock(&dev->struct_mutex);
2507 ret = i915_gem_idle(dev); 2526 ret = i915_gem_idle(dev);
2508 if (ret == 0)
2509 i915_gem_cleanup_ringbuffer(dev);
2510 mutex_unlock(&dev->struct_mutex);
2511
2512 drm_irq_uninstall(dev); 2527 drm_irq_uninstall(dev);
2513 2528
2514 return 0; 2529 return ret;
2515} 2530}
2516 2531
2517void 2532void
2518i915_gem_lastclose(struct drm_device *dev) 2533i915_gem_lastclose(struct drm_device *dev)
2519{ 2534{
2520 int ret; 2535 int ret;
2521 drm_i915_private_t *dev_priv = dev->dev_private;
2522
2523 mutex_lock(&dev->struct_mutex);
2524
2525 if (dev_priv->ring.ring_obj != NULL) {
2526 ret = i915_gem_idle(dev);
2527 if (ret)
2528 DRM_ERROR("failed to idle hardware: %d\n", ret);
2529
2530 i915_gem_cleanup_ringbuffer(dev);
2531 }
2532 2536
2533 mutex_unlock(&dev->struct_mutex); 2537 ret = i915_gem_idle(dev);
2538 if (ret)
2539 DRM_ERROR("failed to idle hardware: %d\n", ret);
2534} 2540}
2535 2541
2536void 2542void