From 1608a0fbb6923bf6989c90f0466ca2b87c722871 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 4 Nov 2016 17:20:35 +1000 Subject: [PATCH] drm/nouveau/fbcon: refcount the drm_framebuffer Signed-off-by: Ben Skeggs --- drivers/gpu/drm/nouveau/nouveau_display.c | 53 +++++++++++------------ drivers/gpu/drm/nouveau/nouveau_display.h | 5 ++- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 13 +++--- drivers/gpu/drm/nouveau/nouveau_fbcon.h | 1 - 4 files changed, 34 insertions(+), 38 deletions(-) diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index b60ee21f4571..2b9e48679662 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c @@ -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); } diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h index 0420ee861ea4..7866df8c5c13 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.h +++ b/drivers/gpu/drm/nouveau/nouveau_display.h @@ -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; diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.c b/drivers/gpu/drm/nouveau/nouveau_fbcon.c index 392ed4761b7f..4192b7926769 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.c +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.c @@ -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; } diff --git a/drivers/gpu/drm/nouveau/nouveau_fbcon.h b/drivers/gpu/drm/nouveau/nouveau_fbcon.h index 35036a4baf3c..e2bca729721e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_fbcon.h +++ b/drivers/gpu/drm/nouveau/nouveau_fbcon.h @@ -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; -- 2.20.1