summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/drm_crtc.c37
1 files changed, 20 insertions, 17 deletions
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index bbf7ce4ead99..e1de47576143 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -364,6 +364,11 @@ static struct drm_mode_object *_object_find(struct drm_device *dev,
if (obj &&
obj->type == DRM_MODE_OBJECT_BLOB)
obj = NULL;
+
+ if (obj && obj->free_cb) {
+ if (!kref_get_unless_zero(&obj->refcount))
+ obj = NULL;
+ }
mutex_unlock(&dev->mode_config.idr_mutex);
return obj;
@@ -495,11 +500,8 @@ struct drm_framebuffer *drm_framebuffer_lookup(struct drm_device *dev,
mutex_lock(&dev->mode_config.fb_lock);
obj = _object_find(dev, id, DRM_MODE_OBJECT_FB);
- if (obj) {
+ if (obj)
fb = obj_to_fb(obj);
- if (!kref_get_unless_zero(&fb->base.refcount))
- fb = NULL;
- }
mutex_unlock(&dev->mode_config.fb_lock);
return fb;
@@ -3474,37 +3476,38 @@ int drm_mode_rmfb(struct drm_device *dev,
{
struct drm_framebuffer *fb = NULL;
struct drm_framebuffer *fbl = NULL;
- struct drm_mode_object *obj;
uint32_t *id = data;
int found = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
return -EINVAL;
+ fb = drm_framebuffer_lookup(dev, *id);
+ if (!fb)
+ return -ENOENT;
+
mutex_lock(&file_priv->fbs_lock);
- mutex_lock(&dev->mode_config.fb_lock);
- obj = _object_find(dev, *id, DRM_MODE_OBJECT_FB);
- if (!obj)
- goto fail_lookup;
- fb = obj_to_fb(obj);
list_for_each_entry(fbl, &file_priv->fbs, filp_head)
if (fb == fbl)
found = 1;
- if (!found)
- goto fail_lookup;
+ if (!found) {
+ mutex_unlock(&file_priv->fbs_lock);
+ goto fail_unref;
+ }
list_del_init(&fb->filp_head);
- mutex_unlock(&dev->mode_config.fb_lock);
mutex_unlock(&file_priv->fbs_lock);
+ /* we now own the reference that was stored in the fbs list */
drm_framebuffer_unreference(fb);
- return 0;
+ /* drop the reference we picked up in framebuffer lookup */
+ drm_framebuffer_unreference(fb);
-fail_lookup:
- mutex_unlock(&dev->mode_config.fb_lock);
- mutex_unlock(&file_priv->fbs_lock);
+ return 0;
+fail_unref:
+ drm_framebuffer_unreference(fb);
return -ENOENT;
}