drm/omap: gem: Fix omap_gem_new() error path
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Wed, 2 Mar 2016 10:51:19 +0000 (12:51 +0200)
committerTomi Valkeinen <tomi.valkeinen@ti.com>
Thu, 3 Mar 2016 15:38:46 +0000 (17:38 +0200)
When an error occurs in omap_gem_new() the function calls
omap_gem_free_object() to clean up. However, that function expects to be
called on a fully initialized GEM object and thus crashes.

Replace it by manual cleanup.

Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
drivers/gpu/drm/omapdrm/omap_gem.c

index 9ac30560e9b103bec909b16e061fa420a8171648..cc36a8dc9bd4c1b47bff9a73042ebdd448111624 100644 (file)
@@ -1398,35 +1398,37 @@ struct drm_gem_object *omap_gem_new(struct drm_device *dev,
                size = PAGE_ALIGN(gsize.bytes);
        }
 
-       spin_lock(&priv->list_lock);
-       list_add(&omap_obj->mm_list, &priv->obj_list);
-       spin_unlock(&priv->list_lock);
-
-       /* Allocate memory if needed. */
-       if (flags & OMAP_BO_MEM_DMA_API) {
-               omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size,
-                                                        &omap_obj->paddr,
-                                                        GFP_KERNEL);
-               if (!omap_obj->vaddr)
-                       goto fail;
-       }
-
        /* Initialize the GEM object. */
        if (!(flags & OMAP_BO_MEM_SHMEM)) {
                drm_gem_private_object_init(dev, obj, size);
        } else {
                ret = drm_gem_object_init(dev, obj, size);
                if (ret)
-                       goto fail;
+                       goto err_free;
 
                mapping = file_inode(obj->filp)->i_mapping;
                mapping_set_gfp_mask(mapping, GFP_USER | __GFP_DMA32);
        }
 
+       /* Allocate memory if needed. */
+       if (flags & OMAP_BO_MEM_DMA_API) {
+               omap_obj->vaddr = dma_alloc_writecombine(dev->dev, size,
+                                                        &omap_obj->paddr,
+                                                        GFP_KERNEL);
+               if (!omap_obj->vaddr)
+                       goto err_release;
+       }
+
+       spin_lock(&priv->list_lock);
+       list_add(&omap_obj->mm_list, &priv->obj_list);
+       spin_unlock(&priv->list_lock);
+
        return obj;
 
-fail:
-       omap_gem_free_object(obj);
+err_release:
+       drm_gem_object_release(obj);
+err_free:
+       kfree(omap_obj);
        return NULL;
 }