diff options
author | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-12-02 15:55:41 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2013-01-20 09:57:21 -0500 |
commit | 7147573a5ce499dec3979e6b524691d47e1288d5 (patch) | |
tree | b3c414243613b8aeee33921602d6b6363d4f2565 | |
parent | 80f0b5aff8f49f63eaf08bdae243de3a8ea3f77e (diff) |
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: Alan Cox <alan@lxorguk.ukuu.org.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/drm_crtc.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/framebuffer.c | 24 | ||||
-rw-r--r-- | drivers/gpu/drm/gma500/psb_drv.c | 10 |
3 files changed, 10 insertions, 26 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c index 81545540b2df..8d665fafc15e 100644 --- a/drivers/gpu/drm/drm_crtc.c +++ b/drivers/gpu/drm/drm_crtc.c | |||
@@ -317,9 +317,7 @@ static void drm_framebuffer_free(struct kref *kref) | |||
317 | */ | 317 | */ |
318 | void drm_framebuffer_unreference(struct drm_framebuffer *fb) | 318 | void drm_framebuffer_unreference(struct drm_framebuffer *fb) |
319 | { | 319 | { |
320 | struct drm_device *dev = fb->dev; | ||
321 | DRM_DEBUG("FB ID: %d\n", fb->base.id); | 320 | DRM_DEBUG("FB ID: %d\n", fb->base.id); |
322 | WARN_ON(!drm_modeset_is_locked(dev)); | ||
323 | kref_put(&fb->refcount, drm_framebuffer_free); | 321 | kref_put(&fb->refcount, drm_framebuffer_free); |
324 | } | 322 | } |
325 | EXPORT_SYMBOL(drm_framebuffer_unreference); | 323 | EXPORT_SYMBOL(drm_framebuffer_unreference); |
diff --git a/drivers/gpu/drm/gma500/framebuffer.c b/drivers/gpu/drm/gma500/framebuffer.c index 38e7e7597de2..49800d2b79dd 100644 --- a/drivers/gpu/drm/gma500/framebuffer.c +++ b/drivers/gpu/drm/gma500/framebuffer.c | |||
@@ -668,30 +668,6 @@ static void psb_user_framebuffer_destroy(struct drm_framebuffer *fb) | |||
668 | { | 668 | { |
669 | struct psb_framebuffer *psbfb = to_psb_fb(fb); | 669 | struct psb_framebuffer *psbfb = to_psb_fb(fb); |
670 | struct gtt_range *r = psbfb->gtt; | 670 | struct gtt_range *r = psbfb->gtt; |
671 | struct drm_device *dev = fb->dev; | ||
672 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
673 | struct psb_fbdev *fbdev = dev_priv->fbdev; | ||
674 | struct drm_crtc *crtc; | ||
675 | int reset = 0; | ||
676 | |||
677 | /* Should never get stolen memory for a user fb */ | ||
678 | WARN_ON(r->stolen); | ||
679 | |||
680 | /* Check if we are erroneously live */ | ||
681 | list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) | ||
682 | if (crtc->fb == fb) | ||
683 | reset = 1; | ||
684 | |||
685 | if (reset) | ||
686 | /* | ||
687 | * Now force a sane response before we permit the DRM CRTC | ||
688 | * layer to do stupid things like blank the display. Instead | ||
689 | * we reset this framebuffer as if the user had forced a reset. | ||
690 | * We must do this before the cleanup so that the DRM layer | ||
691 | * doesn't get a chance to stick its oar in where it isn't | ||
692 | * wanted. | ||
693 | */ | ||
694 | drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper); | ||
695 | 671 | ||
696 | /* Let DRM do its clean up */ | 672 | /* Let DRM do its clean up */ |
697 | drm_framebuffer_cleanup(fb); | 673 | drm_framebuffer_cleanup(fb); |
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c index dd1fbfa7e467..dbcefe9f78fa 100644 --- a/drivers/gpu/drm/gma500/psb_drv.c +++ b/drivers/gpu/drm/gma500/psb_drv.c | |||
@@ -149,6 +149,16 @@ static struct drm_ioctl_desc psb_ioctls[] = { | |||
149 | 149 | ||
150 | static void psb_lastclose(struct drm_device *dev) | 150 | static void psb_lastclose(struct drm_device *dev) |
151 | { | 151 | { |
152 | int ret; | ||
153 | struct drm_psb_private *dev_priv = dev->dev_private; | ||
154 | struct psb_fbdev *fbdev = dev_priv->fbdev; | ||
155 | |||
156 | mutex_lock(&dev->mode_config.mutex); | ||
157 | ret = drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper); | ||
158 | if (ret) | ||
159 | DRM_DEBUG("failed to restore crtc mode\n"); | ||
160 | mutex_unlock(&dev->mode_config.mutex); | ||
161 | |||
152 | return; | 162 | return; |
153 | } | 163 | } |
154 | 164 | ||