diff options
author | Eric Anholt <eric@anholt.net> | 2008-05-01 17:31:57 -0700 |
---|---|---|
committer | Eric Anholt <eric@anholt.net> | 2008-05-01 17:31:57 -0700 |
commit | c10695bb7ab44494badc21c822eac3140cf4e117 (patch) | |
tree | 84e5f689c936052ede796028370b2846d2abdbfe | |
parent | ddc80651d561ef3820e205255f34dc7c60dc2e7c (diff) |
Unbind objects when freeing, fix some error paths, and warn in others.
-rw-r--r-- | linux-core/i915_gem.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/linux-core/i915_gem.c b/linux-core/i915_gem.c index 5ba48512..29b2d894 100644 --- a/linux-core/i915_gem.c +++ b/linux-core/i915_gem.c @@ -78,6 +78,9 @@ i915_gem_object_unbind(struct drm_device *dev, struct drm_gem_object *obj) { struct drm_i915_gem_object *obj_priv = obj->driver_private; + if (obj_priv->gtt_space == NULL) + return; + if (obj_priv->agp_mem != NULL) { drm_unbind_agp(obj_priv->agp_mem); drm_free_agp(obj_priv->agp_mem, obj->size / PAGE_SIZE); @@ -86,6 +89,7 @@ i915_gem_object_unbind(struct drm_device *dev, struct drm_gem_object *obj) i915_gem_object_free_page_list(dev, obj); drm_memrange_put_block(obj_priv->gtt_space); + obj_priv->gtt_space = NULL; } /** @@ -102,13 +106,17 @@ i915_gem_object_bind_to_gtt(struct drm_device *dev, struct drm_gem_object *obj) free_space = drm_memrange_search_free(&dev_priv->mm.gtt_space, obj->size, PAGE_SIZE, 0); - + if (free_space == NULL) + return -ENOMEM; obj_priv->gtt_space = drm_memrange_get_block(free_space, obj->size, PAGE_SIZE); + if (obj_priv->gtt_space == NULL) + return -ENOMEM; + obj_priv->gtt_offset = obj_priv->gtt_space->start; - DRM_INFO("Binding object of size %d at 0x%08x\n", obj->size, obj_priv->gtt_offset); + DRM_DEBUG("Binding object of size %d at 0x%08x\n", obj->size, obj_priv->gtt_offset); /* Get the list of pages out of our struct file. They'll be pinned * at this point until we release them. @@ -117,6 +125,12 @@ i915_gem_object_bind_to_gtt(struct drm_device *dev, struct drm_gem_object *obj) BUG_ON(obj_priv->page_list != NULL); obj_priv->page_list = drm_calloc(page_count, sizeof(struct page *), DRM_MEM_DRIVER); + if (obj_priv->page_list == NULL) { + drm_memrange_put_block(obj_priv->gtt_space); + obj_priv->gtt_space = NULL; + return -ENOMEM; + } + for (i = 0; i < page_count; i++) { obj_priv->page_list[i] = find_or_create_page(obj->filp->f_mapping, i, GFP_HIGHUSER); @@ -345,12 +359,18 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data, int ret; obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) + if (obj == NULL) { + DRM_ERROR("Bad handle in i915_gem_pin_ioctl(): %d\n", + args->handle); return -EINVAL; + } ret = i915_gem_object_bind_to_gtt(dev, obj); - if (ret != 0) + if (ret != 0) { + DRM_ERROR("Failure to bind in i915_gem_pin_ioctl(): %d\n", + ret); return ret; + } obj_priv = obj->driver_private; obj_priv->pin_count++; @@ -368,8 +388,11 @@ i915_gem_unpin_ioctl(struct drm_device *dev, void *data, struct drm_i915_gem_object *obj_priv; obj = drm_gem_object_lookup(dev, file_priv, args->handle); - if (obj == NULL) + if (obj == NULL) { + DRM_ERROR("Bad handle in i915_gem_unpin_ioctl(): %d\n", + args->handle); return -EINVAL; + } obj_priv = obj->driver_private; obj_priv->pin_count--; @@ -392,5 +415,7 @@ int i915_gem_init_object(struct drm_device *dev, struct drm_gem_object *obj) void i915_gem_free_object(struct drm_device *dev, struct drm_gem_object *obj) { + i915_gem_object_unbind(dev, obj); + drm_free(obj->driver_private, 1, DRM_MEM_DRIVER); } |