drm/ttm: Fix buffer object metadata accounting regression v2
authorThomas Hellstrom <thellstrom@vmware.com>
Tue, 12 Jun 2012 11:28:42 +0000 (13:28 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 17 Jun 2012 18:21:24 +0000 (11:21 -0700)
commit a393c730ab69617c3291a3b0b2a228c9be2fc28c upstream.

A regression was introduced in the 3.3 rc series, commit
"drm/ttm: simplify memory accounting for ttm user v2",
causing the metadata of buffer objects created using the ttm_bo_create()
function to be accounted twice.
That causes massive leaks with the vmwgfx driver running for example
SpecViewperf Catia-03 test 2, eventually killing the app.

Furthermore, the same commit introduces a regression where
metadata accounting is leaked if a buffer object is
initialized with an illegal size. This is also fixed with this commit.

v2: Fixed an error path and removed an unused variable.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Konrad Rzeszutek Wilk <konrad.wilk@oracle.com>
Cc: Jerome Glisse <jglisse@redhat.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/gpu/drm/ttm/ttm_bo.c

index 18434186ed1ea5eeeac80c7c3bf8e0ee521da221..8b73ae84efe7d146099cdc972c582ff64a96a409 100644 (file)
@@ -1193,6 +1193,7 @@ int ttm_bo_init(struct ttm_bo_device *bdev,
                        (*destroy)(bo);
                else
                        kfree(bo);
+               ttm_mem_global_free(mem_glob, acc_size);
                return -EINVAL;
        }
        bo->destroy = destroy;
@@ -1294,22 +1295,14 @@ int ttm_bo_create(struct ttm_bo_device *bdev,
                        struct ttm_buffer_object **p_bo)
 {
        struct ttm_buffer_object *bo;
-       struct ttm_mem_global *mem_glob = bdev->glob->mem_glob;
        size_t acc_size;
        int ret;
 
-       acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object));
-       ret = ttm_mem_global_alloc(mem_glob, acc_size, false, false);
-       if (unlikely(ret != 0))
-               return ret;
-
        bo = kzalloc(sizeof(*bo), GFP_KERNEL);
-
-       if (unlikely(bo == NULL)) {
-               ttm_mem_global_free(mem_glob, acc_size);
+       if (unlikely(bo == NULL))
                return -ENOMEM;
-       }
 
+       acc_size = ttm_bo_acc_size(bdev, size, sizeof(struct ttm_buffer_object));
        ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
                                buffer_start, interruptible,
                                persistent_swap_storage, acc_size, NULL);