diff options
author | Eric Anholt <eric@anholt.net> | 2008-11-06 19:00:31 -0500 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2008-12-03 20:21:45 -0500 |
commit | ce44b0ea3dc04236d852d78a06f850d1f7b03f3d (patch) | |
tree | 8951c548a4c427d8daea1e304d97c3c4e161d83a | |
parent | a7f014f2de04893f95cfe40fe35f15c8dae4b36e (diff) |
drm/i915: Move flushing list cleanup from flush request retire to request emit.
obj_priv->write_domain is "write domain if the GPU went idle now", not
"write domain at this moment." By postponing the clear, we confused the
concept, required more storage, and potentially emitted more flushes than
are required.
Signed-off-by: Eric Anholt <eric@anholt.net>
Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 73 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem_proc.c | 5 |
3 files changed, 50 insertions, 39 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index 0a4f39b9a0ec..76d9a706d8fd 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -244,6 +244,10 @@ typedef struct drm_i915_private { | |||
244 | * List of objects currently involved in rendering from the | 244 | * List of objects currently involved in rendering from the |
245 | * ringbuffer. | 245 | * ringbuffer. |
246 | * | 246 | * |
247 | * Includes buffers having the contents of their GPU caches | ||
248 | * flushed, not necessarily primitives. last_rendering_seqno | ||
249 | * represents when the rendering involved will be completed. | ||
250 | * | ||
247 | * A reference is held on the buffer while on this list. | 251 | * A reference is held on the buffer while on this list. |
248 | */ | 252 | */ |
249 | struct list_head active_list; | 253 | struct list_head active_list; |
@@ -253,6 +257,8 @@ typedef struct drm_i915_private { | |||
253 | * still have a write_domain which needs to be flushed before | 257 | * still have a write_domain which needs to be flushed before |
254 | * unbinding. | 258 | * unbinding. |
255 | * | 259 | * |
260 | * last_rendering_seqno is 0 while an object is in this list. | ||
261 | * | ||
256 | * A reference is held on the buffer while on this list. | 262 | * A reference is held on the buffer while on this list. |
257 | */ | 263 | */ |
258 | struct list_head flushing_list; | 264 | struct list_head flushing_list; |
@@ -261,6 +267,8 @@ typedef struct drm_i915_private { | |||
261 | * LRU list of objects which are not in the ringbuffer and | 267 | * LRU list of objects which are not in the ringbuffer and |
262 | * are ready to unbind, but are still in the GTT. | 268 | * are ready to unbind, but are still in the GTT. |
263 | * | 269 | * |
270 | * last_rendering_seqno is 0 while an object is in this list. | ||
271 | * | ||
264 | * A reference is not held on the buffer while on this list, | 272 | * A reference is not held on the buffer while on this list, |
265 | * as merely being GTT-bound shouldn't prevent its being | 273 | * as merely being GTT-bound shouldn't prevent its being |
266 | * freed, and we'll pull it off the list in the free path. | 274 | * freed, and we'll pull it off the list in the free path. |
@@ -394,9 +402,6 @@ struct drm_i915_gem_request { | |||
394 | /** Time at which this request was emitted, in jiffies. */ | 402 | /** Time at which this request was emitted, in jiffies. */ |
395 | unsigned long emitted_jiffies; | 403 | unsigned long emitted_jiffies; |
396 | 404 | ||
397 | /** Cache domains that were flushed at the start of the request. */ | ||
398 | uint32_t flush_domains; | ||
399 | |||
400 | struct list_head list; | 405 | struct list_head list; |
401 | }; | 406 | }; |
402 | 407 | ||
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c index d58ddef468f8..9fd28ebe0aa3 100644 --- a/drivers/gpu/drm/i915/i915_gem.c +++ b/drivers/gpu/drm/i915/i915_gem.c | |||
@@ -532,7 +532,7 @@ i915_gem_object_free_page_list(struct drm_gem_object *obj) | |||
532 | } | 532 | } |
533 | 533 | ||
534 | static void | 534 | static void |
535 | i915_gem_object_move_to_active(struct drm_gem_object *obj) | 535 | i915_gem_object_move_to_active(struct drm_gem_object *obj, uint32_t seqno) |
536 | { | 536 | { |
537 | struct drm_device *dev = obj->dev; | 537 | struct drm_device *dev = obj->dev; |
538 | drm_i915_private_t *dev_priv = dev->dev_private; | 538 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -546,8 +546,20 @@ i915_gem_object_move_to_active(struct drm_gem_object *obj) | |||
546 | /* Move from whatever list we were on to the tail of execution. */ | 546 | /* Move from whatever list we were on to the tail of execution. */ |
547 | list_move_tail(&obj_priv->list, | 547 | list_move_tail(&obj_priv->list, |
548 | &dev_priv->mm.active_list); | 548 | &dev_priv->mm.active_list); |
549 | obj_priv->last_rendering_seqno = seqno; | ||
549 | } | 550 | } |
550 | 551 | ||
552 | static void | ||
553 | i915_gem_object_move_to_flushing(struct drm_gem_object *obj) | ||
554 | { | ||
555 | struct drm_device *dev = obj->dev; | ||
556 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
557 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
558 | |||
559 | BUG_ON(!obj_priv->active); | ||
560 | list_move_tail(&obj_priv->list, &dev_priv->mm.flushing_list); | ||
561 | obj_priv->last_rendering_seqno = 0; | ||
562 | } | ||
551 | 563 | ||
552 | static void | 564 | static void |
553 | i915_gem_object_move_to_inactive(struct drm_gem_object *obj) | 565 | i915_gem_object_move_to_inactive(struct drm_gem_object *obj) |
@@ -562,6 +574,7 @@ i915_gem_object_move_to_inactive(struct drm_gem_object *obj) | |||
562 | else | 574 | else |
563 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); | 575 | list_move_tail(&obj_priv->list, &dev_priv->mm.inactive_list); |
564 | 576 | ||
577 | obj_priv->last_rendering_seqno = 0; | ||
565 | if (obj_priv->active) { | 578 | if (obj_priv->active) { |
566 | obj_priv->active = 0; | 579 | obj_priv->active = 0; |
567 | drm_gem_object_unreference(obj); | 580 | drm_gem_object_unreference(obj); |
@@ -610,10 +623,28 @@ i915_add_request(struct drm_device *dev, uint32_t flush_domains) | |||
610 | 623 | ||
611 | request->seqno = seqno; | 624 | request->seqno = seqno; |
612 | request->emitted_jiffies = jiffies; | 625 | request->emitted_jiffies = jiffies; |
613 | request->flush_domains = flush_domains; | ||
614 | was_empty = list_empty(&dev_priv->mm.request_list); | 626 | was_empty = list_empty(&dev_priv->mm.request_list); |
615 | list_add_tail(&request->list, &dev_priv->mm.request_list); | 627 | list_add_tail(&request->list, &dev_priv->mm.request_list); |
616 | 628 | ||
629 | /* Associate any objects on the flushing list matching the write | ||
630 | * domain we're flushing with our flush. | ||
631 | */ | ||
632 | if (flush_domains != 0) { | ||
633 | struct drm_i915_gem_object *obj_priv, *next; | ||
634 | |||
635 | list_for_each_entry_safe(obj_priv, next, | ||
636 | &dev_priv->mm.flushing_list, list) { | ||
637 | struct drm_gem_object *obj = obj_priv->obj; | ||
638 | |||
639 | if ((obj->write_domain & flush_domains) == | ||
640 | obj->write_domain) { | ||
641 | obj->write_domain = 0; | ||
642 | i915_gem_object_move_to_active(obj, seqno); | ||
643 | } | ||
644 | } | ||
645 | |||
646 | } | ||
647 | |||
617 | if (was_empty && !dev_priv->mm.suspended) | 648 | if (was_empty && !dev_priv->mm.suspended) |
618 | schedule_delayed_work(&dev_priv->mm.retire_work, HZ); | 649 | schedule_delayed_work(&dev_priv->mm.retire_work, HZ); |
619 | return seqno; | 650 | return seqno; |
@@ -676,30 +707,10 @@ i915_gem_retire_request(struct drm_device *dev, | |||
676 | __func__, request->seqno, obj); | 707 | __func__, request->seqno, obj); |
677 | #endif | 708 | #endif |
678 | 709 | ||
679 | if (obj->write_domain != 0) { | 710 | if (obj->write_domain != 0) |
680 | list_move_tail(&obj_priv->list, | 711 | i915_gem_object_move_to_flushing(obj); |
681 | &dev_priv->mm.flushing_list); | 712 | else |
682 | } else { | ||
683 | i915_gem_object_move_to_inactive(obj); | 713 | i915_gem_object_move_to_inactive(obj); |
684 | } | ||
685 | } | ||
686 | |||
687 | if (request->flush_domains != 0) { | ||
688 | struct drm_i915_gem_object *obj_priv, *next; | ||
689 | |||
690 | /* Clear the write domain and activity from any buffers | ||
691 | * that are just waiting for a flush matching the one retired. | ||
692 | */ | ||
693 | list_for_each_entry_safe(obj_priv, next, | ||
694 | &dev_priv->mm.flushing_list, list) { | ||
695 | struct drm_gem_object *obj = obj_priv->obj; | ||
696 | |||
697 | if (obj->write_domain & request->flush_domains) { | ||
698 | obj->write_domain = 0; | ||
699 | i915_gem_object_move_to_inactive(obj); | ||
700 | } | ||
701 | } | ||
702 | |||
703 | } | 714 | } |
704 | } | 715 | } |
705 | 716 | ||
@@ -896,17 +907,15 @@ i915_gem_object_wait_rendering(struct drm_gem_object *obj) | |||
896 | * create a new seqno to wait for. | 907 | * create a new seqno to wait for. |
897 | */ | 908 | */ |
898 | if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) { | 909 | if (obj->write_domain & ~(I915_GEM_DOMAIN_CPU|I915_GEM_DOMAIN_GTT)) { |
899 | uint32_t write_domain = obj->write_domain; | 910 | uint32_t seqno, write_domain = obj->write_domain; |
900 | #if WATCH_BUF | 911 | #if WATCH_BUF |
901 | DRM_INFO("%s: flushing object %p from write domain %08x\n", | 912 | DRM_INFO("%s: flushing object %p from write domain %08x\n", |
902 | __func__, obj, write_domain); | 913 | __func__, obj, write_domain); |
903 | #endif | 914 | #endif |
904 | i915_gem_flush(dev, 0, write_domain); | 915 | i915_gem_flush(dev, 0, write_domain); |
905 | 916 | ||
906 | i915_gem_object_move_to_active(obj); | 917 | seqno = i915_add_request(dev, write_domain); |
907 | obj_priv->last_rendering_seqno = i915_add_request(dev, | 918 | i915_gem_object_move_to_active(obj, seqno); |
908 | write_domain); | ||
909 | BUG_ON(obj_priv->last_rendering_seqno == 0); | ||
910 | #if WATCH_LRU | 919 | #if WATCH_LRU |
911 | DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj); | 920 | DRM_INFO("%s: flush moves to exec list %p\n", __func__, obj); |
912 | #endif | 921 | #endif |
@@ -1927,10 +1936,8 @@ i915_gem_execbuffer(struct drm_device *dev, void *data, | |||
1927 | i915_file_priv->mm.last_gem_seqno = seqno; | 1936 | i915_file_priv->mm.last_gem_seqno = seqno; |
1928 | for (i = 0; i < args->buffer_count; i++) { | 1937 | for (i = 0; i < args->buffer_count; i++) { |
1929 | struct drm_gem_object *obj = object_list[i]; | 1938 | struct drm_gem_object *obj = object_list[i]; |
1930 | struct drm_i915_gem_object *obj_priv = obj->driver_private; | ||
1931 | 1939 | ||
1932 | i915_gem_object_move_to_active(obj); | 1940 | i915_gem_object_move_to_active(obj, seqno); |
1933 | obj_priv->last_rendering_seqno = seqno; | ||
1934 | #if WATCH_LRU | 1941 | #if WATCH_LRU |
1935 | DRM_INFO("%s: move to exec list %p\n", __func__, obj); | 1942 | DRM_INFO("%s: move to exec list %p\n", __func__, obj); |
1936 | #endif | 1943 | #endif |
diff --git a/drivers/gpu/drm/i915/i915_gem_proc.c b/drivers/gpu/drm/i915/i915_gem_proc.c index 93de15b4c9a7..e8d5abe1250e 100644 --- a/drivers/gpu/drm/i915/i915_gem_proc.c +++ b/drivers/gpu/drm/i915/i915_gem_proc.c | |||
@@ -166,10 +166,9 @@ static int i915_gem_request_info(char *buf, char **start, off_t offset, | |||
166 | list_for_each_entry(gem_request, &dev_priv->mm.request_list, | 166 | list_for_each_entry(gem_request, &dev_priv->mm.request_list, |
167 | list) | 167 | list) |
168 | { | 168 | { |
169 | DRM_PROC_PRINT(" %d @ %d %08x\n", | 169 | DRM_PROC_PRINT(" %d @ %d\n", |
170 | gem_request->seqno, | 170 | gem_request->seqno, |
171 | (int) (jiffies - gem_request->emitted_jiffies), | 171 | (int) (jiffies - gem_request->emitted_jiffies)); |
172 | gem_request->flush_domains); | ||
173 | } | 172 | } |
174 | if (len > request + offset) | 173 | if (len > request + offset) |
175 | return request; | 174 | return request; |