drm/nouveau/fbcon: refcount the drm_framebuffer
authorBen Skeggs <bskeggs@redhat.com>
Fri, 4 Nov 2016 07:20:35 +0000 (17:20 +1000)
committerBen Skeggs <bskeggs@redhat.com>
Mon, 7 Nov 2016 04:04:44 +0000 (14:04 +1000)
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_display.h
drivers/gpu/drm/nouveau/nouveau_fbcon.c
drivers/gpu/drm/nouveau/nouveau_fbcon.h

index b60ee21..2b9e486 100644 (file)
@@ -245,28 +245,32 @@ static const struct drm_framebuffer_funcs nouveau_framebuffer_funcs = {
 };
 
 int
-nouveau_framebuffer_init(struct drm_device *dev,
-                        struct nouveau_framebuffer *nv_fb,
-                        const struct drm_mode_fb_cmd2 *mode_cmd,
-                        struct nouveau_bo *nvbo)
+nouveau_framebuffer_new(struct drm_device *dev,
+                       const struct drm_mode_fb_cmd2 *mode_cmd,
+                       struct nouveau_bo *nvbo,
+                       struct nouveau_framebuffer **pfb)
 {
        struct nouveau_display *disp = nouveau_display(dev);
-       struct drm_framebuffer *fb = &nv_fb->base;
+       struct nouveau_framebuffer *fb;
        int ret;
 
-       drm_helper_mode_fill_fb_struct(fb, mode_cmd);
-       nv_fb->nvbo = nvbo;
+       if (!(fb = kzalloc(sizeof(*fb), GFP_KERNEL)))
+               return -ENOMEM;
 
-       ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
-       if (ret)
-               return ret;
+       drm_helper_mode_fill_fb_struct(&fb->base, mode_cmd);
+       fb->nvbo = nvbo;
 
-       if (disp->fb_ctor) {
-               ret = disp->fb_ctor(fb);
-               if (ret)
-                       disp->fb_dtor(fb);
+       ret = drm_framebuffer_init(dev, &fb->base, &nouveau_framebuffer_funcs);
+       if (ret == 0) {
+               if (!disp->fb_ctor || !(ret = disp->fb_ctor(&fb->base))) {
+                       *pfb = fb;
+                       return 0;
+               }
+               disp->fb_dtor(&fb->base);
+               drm_framebuffer_cleanup(&fb->base);
        }
 
+       kfree(fb);
        return ret;
 }
 
@@ -275,27 +279,20 @@ nouveau_user_framebuffer_create(struct drm_device *dev,
                                struct drm_file *file_priv,
                                const struct drm_mode_fb_cmd2 *mode_cmd)
 {
-       struct nouveau_framebuffer *nouveau_fb;
+       struct nouveau_framebuffer *fb;
+       struct nouveau_bo *nvbo;
        struct drm_gem_object *gem;
-       int ret = -ENOMEM;
+       int ret;
 
        gem = drm_gem_object_lookup(file_priv, mode_cmd->handles[0]);
        if (!gem)
                return ERR_PTR(-ENOENT);
+       nvbo = nouveau_gem_object(gem);
 
-       nouveau_fb = kzalloc(sizeof(struct nouveau_framebuffer), GFP_KERNEL);
-       if (!nouveau_fb)
-               goto err_unref;
-
-       ret = nouveau_framebuffer_init(dev, nouveau_fb, mode_cmd, nouveau_gem_object(gem));
-       if (ret)
-               goto err;
-
-       return &nouveau_fb->base;
+       ret = nouveau_framebuffer_new(dev, mode_cmd, nvbo, &fb);
+       if (ret == 0)
+               return &fb->base;
 
-err:
-       kfree(nouveau_fb);
-err_unref:
        drm_gem_object_unreference_unlocked(gem);
        return ERR_PTR(ret);
 }
index 0420ee8..7866df8 100644 (file)
@@ -22,8 +22,9 @@ nouveau_framebuffer(struct drm_framebuffer *fb)
        return container_of(fb, struct nouveau_framebuffer, base);
 }
 
-int nouveau_framebuffer_init(struct drm_device *, struct nouveau_framebuffer *,
-                            const struct drm_mode_fb_cmd2 *, struct nouveau_bo *);
+int nouveau_framebuffer_new(struct drm_device *,
+                           const struct drm_mode_fb_cmd2 *,
+                           struct nouveau_bo *, struct nouveau_framebuffer **);
 
 struct nouveau_page_flip_state {
        struct list_head head;
index 392ed47..4192b79 100644 (file)
@@ -359,8 +359,9 @@ nouveau_fbcon_create(struct drm_fb_helper *helper,
                goto out;
        }
 
-       nouveau_framebuffer_init(dev, &fbcon->fb, &mode_cmd, nvbo);
-       fb = &fbcon->fb;
+       ret = nouveau_framebuffer_new(dev, &mode_cmd, nvbo, &fb);
+       if (ret)
+               goto out_unref;
 
        ret = nouveau_bo_pin(nvbo, TTM_PL_FLAG_VRAM, false);
        if (ret) {
@@ -454,17 +455,15 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon)
 
        drm_fb_helper_unregister_fbi(&fbcon->helper);
        drm_fb_helper_release_fbi(&fbcon->helper);
+       drm_fb_helper_fini(&fbcon->helper);
 
        if (nouveau_fb->nvbo) {
                nouveau_bo_vma_del(nouveau_fb->nvbo, &nouveau_fb->vma);
                nouveau_bo_unmap(nouveau_fb->nvbo);
                nouveau_bo_unpin(nouveau_fb->nvbo);
-               drm_gem_object_unreference_unlocked(&nouveau_fb->nvbo->gem);
-               nouveau_fb->nvbo = NULL;
+               drm_framebuffer_unreference(&nouveau_fb->base);
        }
-       drm_fb_helper_fini(&fbcon->helper);
-       drm_framebuffer_unregister_private(&nouveau_fb->base);
-       drm_framebuffer_cleanup(&nouveau_fb->base);
+
        return 0;
 }
 
index 35036a4..e2bca72 100644 (file)
@@ -33,7 +33,6 @@
 
 struct nouveau_fbdev {
        struct drm_fb_helper helper;
-       struct nouveau_framebuffer fb;
        unsigned int saved_flags;
        struct nvif_object surf2d;
        struct nvif_object clip;