diff options
author | Keith Packard <keithp@keithp.com> | 2008-05-06 21:59:06 -0700 |
---|---|---|
committer | Keith Packard <keithp@keithp.com> | 2008-05-06 21:59:06 -0700 |
commit | 6a6c37af9ecaabfe1399a1300cadaff730767013 (patch) | |
tree | 5fdcd7396aad7ab84cd523b5660ca8f80577853c | |
parent | 61253f4f677518537368103799c9510b8b5ad1e3 (diff) |
[intel-GEM] ref count objects in gtt-lru.
If objects on the lru aren't ref counted, they'll get pulled from the gtt as
soon as they are freed. This change does cause objects to get stuck in the
gtt until they're forced out by new requests. The lru should get cleaned
when the irq occurs.
-rw-r--r-- | linux-core/i915_gem.c | 62 | ||||
-rw-r--r-- | shared-core/i915_drv.h | 1 |
2 files changed, 50 insertions, 13 deletions
diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 911f9aa8..220d6179 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -30,8 +30,9 @@ #include "i915_drm.h" #include "i915_drv.h" -#define WATCH_BUF 1 -#define WATCH_EXEC 1 +#define WATCH_BUF 0 +#define WATCH_EXEC 0 +#define WATCH_LRU 0 int i915_gem_init_ioctl(struct drm_device *dev, void *data, @@ -165,11 +166,14 @@ i915_gem_object_unbind(struct drm_gem_object *obj) drm_memrange_put_block(obj_priv->gtt_space); obj_priv->gtt_space = NULL; - list_del_init(&obj_priv->gtt_lru_entry); - drm_gem_object_unreference (obj); + if (!list_empty (&obj_priv->gtt_lru_entry)) + { + list_del_init(&obj_priv->gtt_lru_entry); + drm_gem_object_unreference (obj); + } } -#if 0 +#if WATCH_BUF | WATCH_EXEC static void i915_gem_dump_page (struct page *page, uint32_t start, uint32_t end, uint32_t bias, uint32_t mark) { @@ -212,6 +216,21 @@ i915_gem_dump_object (struct drm_gem_object *obj, int len, const char *where, ui } #endif +#if WATCH_LRU +static void +i915_dump_lru (struct drm_device *dev, const char *where) +{ + drm_i915_private_t *dev_priv = dev->dev_private; + struct drm_i915_gem_object *obj_priv; + + DRM_INFO ("GTT LRU %s {\n", where); + list_for_each_entry (obj_priv, &dev_priv->mm.gtt_lru, gtt_lru_entry) { + DRM_INFO (" %p: %08x\n", obj_priv, obj_priv->last_rendering_cookie); + } + DRM_INFO ("}\n"); +} +#endif + static int i915_gem_evict_something(struct drm_device *dev) { @@ -221,11 +240,14 @@ i915_gem_evict_something(struct drm_device *dev) int ret; /* Find the LRU buffer. */ - BUG_ON(!list_empty(&dev_priv->mm.gtt_lru)); - obj_priv = list_entry(dev_priv->mm.gtt_lru.prev, - struct drm_i915_gem_object, - gtt_lru_entry); + BUG_ON(list_empty(&dev_priv->mm.gtt_lru)); + obj_priv = list_first_entry(&dev_priv->mm.gtt_lru, + struct drm_i915_gem_object, + gtt_lru_entry); obj = obj_priv->obj; +#if WATCH_LRU + DRM_INFO ("%s: evicting %p\n", __FUNCTION__, obj); +#endif /* Only unpinned buffers should be on this list. */ BUG_ON(obj_priv->pin_count != 0); @@ -240,6 +262,9 @@ i915_gem_evict_something(struct drm_device *dev) /* Wait on the rendering and unbind the buffer. */ i915_gem_object_unbind(obj); +#if WATCH_LRU + DRM_INFO ("%s: evicted %p\n", __FUNCTION__, obj); +#endif return 0; } @@ -280,8 +305,13 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment) /* If the gtt is empty and we're still having trouble * fitting our object in, we're out of memory. */ - if (list_empty(&dev_priv->mm.gtt_lru)) +#if WATCH_LRU + DRM_INFO ("%s: GTT full, evicting something\n", __FUNCTION__); +#endif + if (list_empty(&dev_priv->mm.gtt_lru)) { + DRM_ERROR ("GTT full, but LRU list empty\n"); return -ENOMEM; + } ret = i915_gem_evict_something(dev); if (ret != 0) @@ -431,9 +461,14 @@ i915_gem_reloc_and_validate_object(struct drm_gem_object *obj, if (obj_priv->pin_count == 0) { /* Move our buffer to the head of the LRU. */ - list_del_init(&obj_priv->gtt_lru_entry); - list_add(&obj_priv->gtt_lru_entry, &dev_priv->mm.gtt_lru); - drm_gem_object_reference (obj); + if (list_empty (&obj_priv->gtt_lru_entry)) { + drm_gem_object_reference (obj); + list_add_tail(&obj_priv->gtt_lru_entry, &dev_priv->mm.gtt_lru); + } else + list_move_tail(&obj_priv->gtt_lru_entry, &dev_priv->mm.gtt_lru); +#if WATCH_LRU && 0 + i915_dump_lru (dev, __FUNCTION__); +#endif } relocs = (struct drm_i915_gem_relocation_entry __user *) (uintptr_t) entry->relocs_ptr; @@ -784,6 +819,7 @@ int i915_gem_init_object(struct drm_gem_object *obj) return -ENOMEM; obj->driver_private = obj_priv; + obj_priv->obj = obj; INIT_LIST_HEAD(&obj_priv->gtt_lru_entry); return 0; } diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index bd6fa188..daa77f72 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -262,6 +262,7 @@ struct drm_i915_gem_object { /** Current space allocated to this object in the GTT, if any. */ struct drm_memrange_node *gtt_space; + /** This object's place on the GTT LRU list */ struct list_head gtt_lru_entry; |