Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7d331595 authored by Daniel Vetter's avatar Daniel Vetter
Browse files

drm: nest modeset locks within fpriv->fbs_lock



Atm we still need to unconditionally take the modeset locks in the
rmfb paths. But eventually we only want to take them if there are
other users around as a slow-path. This way sane userspace avoids
blocking on edid reads and other stuff in rmfb if it ensures that the
fb isn't used anywhere by a crtc/plane.

We can do a quick check for such other users once framebuffers are
properly refcounting by locking at the refcount - if it's more than 1,
there are other users left. Again, rmfb racing against other ioctls
isn't a real problem, userspace is allowed to shoot its foot.

This patch just prepares this by moving the modeset locks to nest
within fpriv->fbs_lock. Now the distinction between the fbs_lock and
the device-global fb_lock is clear, since we need to hold the fbs_lock
outside of any modeset_locks in fb_release.

Reviewed-by: default avatarRob Clark <rob@ti.com>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 2b677e8c
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -2282,13 +2282,13 @@ int drm_mode_addfb(struct drm_device *dev,
		drm_modeset_unlock_all(dev);
		return PTR_ERR(fb);
	}
	drm_modeset_unlock_all(dev);

	mutex_lock(&file_priv->fbs_lock);
	or->fb_id = fb->base.id;
	list_add(&fb->filp_head, &file_priv->fbs);
	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
	mutex_unlock(&file_priv->fbs_lock);
	drm_modeset_unlock_all(dev);

	return ret;
}
@@ -2465,6 +2465,7 @@ int drm_mode_addfb2(struct drm_device *dev,
		drm_modeset_unlock_all(dev);
		return PTR_ERR(fb);
	}
	drm_modeset_unlock_all(dev);

	mutex_lock(&file_priv->fbs_lock);
	r->fb_id = fb->base.id;
@@ -2472,7 +2473,6 @@ int drm_mode_addfb2(struct drm_device *dev,
	DRM_DEBUG_KMS("[FB:%d]\n", fb->base.id);
	mutex_unlock(&file_priv->fbs_lock);

	drm_modeset_unlock_all(dev);

	return ret;
}
@@ -2670,7 +2670,6 @@ void drm_fb_release(struct drm_file *priv)
	struct drm_device *dev = priv->minor->dev;
	struct drm_framebuffer *fb, *tfb;

	drm_modeset_lock_all(dev);
	mutex_lock(&priv->fbs_lock);
	list_for_each_entry_safe(fb, tfb, &priv->fbs, filp_head) {

@@ -2682,10 +2681,11 @@ void drm_fb_release(struct drm_file *priv)
		list_del_init(&fb->filp_head);

		/* This will also drop the fpriv->fbs reference. */
		drm_modeset_lock_all(dev);
		drm_framebuffer_remove(fb);
		drm_modeset_unlock_all(dev);
	}
	mutex_unlock(&priv->fbs_lock);
	drm_modeset_unlock_all(dev);
}

/**