drm/nouveau: handle framebuffer pinning correctly
Subsystems (3)
PATCH 1/1 drm/nouveau: handle framebuffer pinning correctly
Unpinning wasn't always handled correctly. The crtc_disable and nouveau_fbcon_destroy calls needed to unpin but didn't, resulting in a pin leak.
While debugging this I found some leaks in the error paths of nouveau_user_framebuffer_create, so I fixed those too.
Signed-off-by Maarten Lankhorst <[email protected]>
--- drivers/gpu/drm/nouveau/nouveau_display.c | 15 ++++++++++----- drivers/gpu/drm/nouveau/nouveau_fbcon.c | 7 +++++++ drivers/gpu/drm/nouveau/nv50_display.c | 13 +++++++++++++ 3 files changed, 30 insertions(+), 5 deletions(-)
drivers/gpu/drm/nouveau/nouveau_display.c +10 -5
@@ -142,17 +142,22 @@ nouveau_user_framebuffer_create(struct drm_device *dev,if (!gem)return ERR_PTR (-ENOENT ); + ret = -ENOMEM ; nouveau_fb =kzalloc (sizeof (struct nouveau_framebuffer ),GFP_KERNEL );if (!nouveau_fb) -return ERR_PTR (-ENOMEM ); + goto err_unref; ret =nouveau_framebuffer_init (dev, nouveau_fb, mode_cmd,nouveau_gem_object (gem)); -if (ret) { -drm_gem_object_unreference (gem); -return ERR_PTR (ret); - } +if (ret) + goto err;return &nouveau_fb->base; + +err: +kfree (nouveau_fb); +err_unref: +drm_gem_object_unreference (gem); +return ERR_PTR (ret); }static const struct drm_mode_config_funcs nouveau_mode_config_funcs = {
drivers/gpu/drm/nouveau/nouveau_fbcon.c +7 -0
@@ -385,6 +385,7 @@ out_unlock:mutex_unlock (&dev->struct_mutex);if (chan)nouveau_bo_vma_del (nvbo, &fbcon->nouveau_fb.vma); +nouveau_bo_unmap (nvbo); out_unpin:nouveau_bo_unpin (nvbo); out_unref:
@@ -415,6 +416,12 @@ nouveau_fbcon_destroy(struct drm_device *dev, struct nouveau_fbdev *fbcon) }if (nouveau_fb->nvbo) { +struct drm_crtc *crtc; + +list_for_each_entry (crtc, &dev->mode_config.crtc_list, head) +if (nouveau_framebuffer (crtc->fb) == nouveau_fb) +nouveau_bo_unpin (nouveau_fb->nvbo); +nouveau_bo_unmap (nouveau_fb->nvbo);nouveau_bo_vma_del (nouveau_fb->nvbo, &nouveau_fb->vma);nouveau_bo_unpin (nouveau_fb->nvbo);
drivers/gpu/drm/nouveau/nv50_display.c +13 -0
@@ -1272,6 +1272,18 @@ nv50_crtc_gamma_set(struct drm_crtc *crtc, u16 *r, u16 *g, u16 *b, }static void +nv50_crtc_disable (struct drm_crtc *crtc) +{ +struct nouveau_framebuffer *nv_fb; + +if (!crtc->fb) +return ; + + nv_fb =nouveau_framebuffer (crtc->fb); +nouveau_bo_unpin (nv_fb->nvbo); +} + +static void nv50_crtc_destroy (struct drm_crtc *crtc) {struct nouveau_crtc *nv_crtc =nouveau_crtc (crtc);
@@ -1294,6 +1306,7 @@ nv50_crtc_destroy(struct drm_crtc *crtc) }static const struct drm_crtc_helper_funcs nv50_crtc_hfunc = { + .disable = nv50_crtc_disable, .dpms = nv50_crtc_dpms, .prepare = nv50_crtc_prepare, .commit = nv50_crtc_commit,