Commit 7147573a authored by Daniel Vetter's avatar Daniel Vetter

drm/gma500: move fbcon restore to lastclose

Doing this within the fb->destroy callback leads to a locking
nightmare. And all other drm drivers that restore the fbcon do
it in lastclose, too.

With this adjustments all fb->destroy callbacks optionally drop
references to any gem objects used as backing storage, call
drm_framebuffer_cleanup and then kfree the struct. Which nicely
simplifies the locking for framebuffer unreferencing and freeing,
since this doesn't require that we hold the mode_config lock. A
slight exception is the vmwgfx surface backed framebuffer, it also
calls drm_master_put and removes the object from a device-private
framebuffer list. Both seem to have solid locking in place already.

Conclusion is that now it is no longer required to hold the
mode_config lock while freeing a framebuffer.

v2: Drop the corresponding mutex_lock WARN check from
drm_framebuffer_unreference.

v3: Use just the mode_config lock not modeset_lock_all, due to patch
reordering.
Acked-by: default avatarAlan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 80f0b5af
...@@ -317,9 +317,7 @@ static void drm_framebuffer_free(struct kref *kref) ...@@ -317,9 +317,7 @@ static void drm_framebuffer_free(struct kref *kref)
*/ */
void drm_framebuffer_unreference(struct drm_framebuffer *fb) void drm_framebuffer_unreference(struct drm_framebuffer *fb)
{ {
struct drm_device *dev = fb->dev;
DRM_DEBUG("FB ID: %d\n", fb->base.id); DRM_DEBUG("FB ID: %d\n", fb->base.id);
WARN_ON(!drm_modeset_is_locked(dev));
kref_put(&fb->refcount, drm_framebuffer_free); kref_put(&fb->refcount, drm_framebuffer_free);
} }
EXPORT_SYMBOL(drm_framebuffer_unreference); EXPORT_SYMBOL(drm_framebuffer_unreference);
......
...@@ -668,30 +668,6 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) ...@@ -668,30 +668,6 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb)
{ {
struct psb_framebuffer *psbfb = to_psb_fb(fb); struct psb_framebuffer *psbfb = to_psb_fb(fb);
struct gtt_range *r = psbfb->gtt; struct gtt_range *r = psbfb->gtt;
struct drm_device *dev = fb->dev;
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_fbdev *fbdev = dev_priv->fbdev;
struct drm_crtc *crtc;
int reset = 0;
/* Should never get stolen memory for a user fb */
WARN_ON(r->stolen);
/* Check if we are erroneously live */
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
if (crtc->fb == fb)
reset = 1;
if (reset)
/*
* Now force a sane response before we permit the DRM CRTC
* layer to do stupid things like blank the display. Instead
* we reset this framebuffer as if the user had forced a reset.
* We must do this before the cleanup so that the DRM layer
* doesn't get a chance to stick its oar in where it isn't
* wanted.
*/
drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
/* Let DRM do its clean up */ /* Let DRM do its clean up */
drm_framebuffer_cleanup(fb); drm_framebuffer_cleanup(fb);
......
...@@ -149,6 +149,16 @@ static struct drm_ioctl_desc psb_ioctls[] = { ...@@ -149,6 +149,16 @@ static struct drm_ioctl_desc psb_ioctls[] = {
static void psb_lastclose(struct drm_device *dev) static void psb_lastclose(struct drm_device *dev)
{ {
int ret;
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_fbdev *fbdev = dev_priv->fbdev;
mutex_lock(&dev->mode_config.mutex);
ret = drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
if (ret)
DRM_DEBUG("failed to restore crtc mode\n");
mutex_unlock(&dev->mode_config.mutex);
return; return;
} }
......
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