summaryrefslogtreecommitdiff
path: root/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2016-11-04 17:20:35 +1000
committerBen Skeggs <bskeggs@redhat.com>2016-11-07 10:06:21 +1000
commitf6ea9d0a3f90eaa177eb584de7c55dd0117c3e49 (patch)
treeedb29fe92cd13e6d588e6eae4ea66c14a1b1fe4f /drm
parentb8290a3168d102d2af82c33baf35ce9ca74af94e (diff)
downloadnouveau-f6ea9d0a3f90eaa177eb584de7c55dd0117c3e49.tar.gz
fbcon: refcount the drm_framebuffer
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drm')
-rw-r--r--drm/nouveau/nouveau_display.c53
-rw-r--r--drm/nouveau/nouveau_display.h5
-rw-r--r--drm/nouveau/nouveau_fbcon.c13
-rw-r--r--drm/nouveau/nouveau_fbcon.h1
4 files changed, 34 insertions, 38 deletions
diff --git a/drm/nouveau/nouveau_display.c b/drm/nouveau/nouveau_display.c
index b60ee21f4..2b9e48679 100644
--- a/drm/nouveau/nouveau_display.c
+++ b/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/drm/nouveau/nouveau_display.h b/drm/nouveau/nouveau_display.h
index 0420ee861..7866df8c5 100644
--- a/drm/nouveau/nouveau_display.h
+++ b/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/drm/nouveau/nouveau_fbcon.c b/drm/nouveau/nouveau_fbcon.c
index 392ed4761..4192b7926 100644
--- a/drm/nouveau/nouveau_fbcon.c
+++ b/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/drm/nouveau/nouveau_fbcon.h b/drm/nouveau/nouveau_fbcon.h
index 35036a4ba..e2bca7297 100644
--- a/drm/nouveau/nouveau_fbcon.h
+++ b/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;