Commit aa8c3400 authored by Daniel Vetter's avatar Daniel Vetter Committed by Sasha Levin

drm: Fixup racy refcounting in plane_force_disable

[ Upstream commit 8218c3f4 ]

Originally it was impossible to be dropping the last refcount in this
function since there was always one around still from the idr. But in

commit 83f45fc3
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Wed Aug 6 09:10:18 2014 +0200

    drm: Don't grab an fb reference for the idr

we've switched to weak references, broke that assumption but forgot to
fix it up.

Since we still force-disable planes it's only possible to hit this
when racing multiple rmfb with fbdev restoring or similar evil things.
As long as userspace is nice it's impossible to hit the BUG_ON.

But the BUG_ON would most likely be hit from fbdev code, which usually
invovles the console_lock besides all modeset locks. So very likely
we'd never get the bug reports if this was hit in the wild, hence
better be safe than sorry and backport.

Spotted by Matt Roper while reviewing other patches.

[airlied: pull this back into 4.0 - the oops happens there]

Cc: stable@vger.kernel.org
Cc: Matt Roper <matthew.d.roper@intel.com>
Reviewed-by: default avatarMatt Roper <matthew.d.roper@intel.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@intel.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
Signed-off-by: default avatarSasha Levin <sasha.levin@oracle.com>
parent ff06e6e5
...@@ -531,17 +531,6 @@ void drm_framebuffer_reference(struct drm_framebuffer *fb) ...@@ -531,17 +531,6 @@ void drm_framebuffer_reference(struct drm_framebuffer *fb)
} }
EXPORT_SYMBOL(drm_framebuffer_reference); EXPORT_SYMBOL(drm_framebuffer_reference);
static void drm_framebuffer_free_bug(struct kref *kref)
{
BUG();
}
static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
kref_put(&fb->refcount, drm_framebuffer_free_bug);
}
/** /**
* drm_framebuffer_unregister_private - unregister a private fb from the lookup idr * drm_framebuffer_unregister_private - unregister a private fb from the lookup idr
* @fb: fb to unregister * @fb: fb to unregister
...@@ -1297,7 +1286,7 @@ void drm_plane_force_disable(struct drm_plane *plane) ...@@ -1297,7 +1286,7 @@ void drm_plane_force_disable(struct drm_plane *plane)
return; return;
} }
/* disconnect the plane from the fb and crtc: */ /* disconnect the plane from the fb and crtc: */
__drm_framebuffer_unreference(plane->old_fb); drm_framebuffer_unreference(plane->old_fb);
plane->old_fb = NULL; plane->old_fb = NULL;
plane->fb = NULL; plane->fb = NULL;
plane->crtc = NULL; plane->crtc = NULL;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment