diff options
Diffstat (limited to 'drivers/gpu')
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 50 |
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); | |||
50 | static void i915_gem_object_free_page_list(struct drm_gem_object *obj); | 50 | static void i915_gem_object_free_page_list(struct drm_gem_object *obj); |
51 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); | 51 | static int i915_gem_object_wait_rendering(struct drm_gem_object *obj); |
52 | 52 | ||
53 | static void | ||
54 | i915_gem_cleanup_ringbuffer(struct drm_device *dev); | ||
55 | |||
53 | int | 56 | int |
54 | i915_gem_init_ioctl(struct drm_device *dev, void *data, | 57 | i915_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 | ||
2517 | void | 2532 | void |
2518 | i915_gem_lastclose(struct drm_device *dev) | 2533 | i915_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 | ||
2536 | void | 2542 | void |