* [PATCH 5/8] drm: spiff out FB refcnting traces
2014-05-28 23:57 [PATCH 0/8] prepare for preparing for atomic Rob Clark
@ 2014-05-28 23:57 ` Rob Clark
2014-05-29 8:36 ` David Herrmann
0 siblings, 1 reply; 21+ messages in thread
From: Rob Clark @ 2014-05-28 23:57 UTC (permalink / raw)
To: dri-devel
I find myself making this change locally whenever debugging FB reference
counting. Which seems a bit silly.
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/drm_crtc.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index b975575..4d243fd 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -519,7 +519,7 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
*/
void drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
- DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, fb->refcount.refcount.counter);
kref_put(&fb->refcount, drm_framebuffer_free);
}
EXPORT_SYMBOL(drm_framebuffer_unreference);
@@ -532,7 +532,7 @@ EXPORT_SYMBOL(drm_framebuffer_unreference);
*/
void drm_framebuffer_reference(struct drm_framebuffer *fb)
{
- DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, fb->refcount.refcount.counter);
kref_get(&fb->refcount);
}
EXPORT_SYMBOL(drm_framebuffer_reference);
@@ -544,7 +544,7 @@ static void drm_framebuffer_free_bug(struct kref *kref)
static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
- DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, fb->refcount.refcount.counter);
kref_put(&fb->refcount, drm_framebuffer_free_bug);
}
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 5/8] drm: spiff out FB refcnting traces
2014-05-28 23:57 ` [PATCH 5/8] drm: spiff out FB refcnting traces Rob Clark
@ 2014-05-29 8:36 ` David Herrmann
0 siblings, 0 replies; 21+ messages in thread
From: David Herrmann @ 2014-05-29 8:36 UTC (permalink / raw)
To: Rob Clark; +Cc: dri-devel@lists.freedesktop.org
Hi
On Thu, May 29, 2014 at 1:57 AM, Rob Clark <robdclark@gmail.com> wrote:
> I find myself making this change locally whenever debugging FB reference
> counting. Which seems a bit silly.
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
> ---
> drivers/gpu/drm/drm_crtc.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index b975575..4d243fd 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -519,7 +519,7 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
> */
> void drm_framebuffer_unreference(struct drm_framebuffer *fb)
> {
> - DRM_DEBUG("FB ID: %d\n", fb->base.id);
> + DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, fb->refcount.refcount.counter);
atomic_read()!!!
With that fixed, this is:
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
Thanks
David
> kref_put(&fb->refcount, drm_framebuffer_free);
> }
> EXPORT_SYMBOL(drm_framebuffer_unreference);
> @@ -532,7 +532,7 @@ EXPORT_SYMBOL(drm_framebuffer_unreference);
> */
> void drm_framebuffer_reference(struct drm_framebuffer *fb)
> {
> - DRM_DEBUG("FB ID: %d\n", fb->base.id);
> + DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, fb->refcount.refcount.counter);
> kref_get(&fb->refcount);
> }
> EXPORT_SYMBOL(drm_framebuffer_reference);
> @@ -544,7 +544,7 @@ static void drm_framebuffer_free_bug(struct kref *kref)
>
> static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
> {
> - DRM_DEBUG("FB ID: %d\n", fb->base.id);
> + DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, fb->refcount.refcount.counter);
> kref_put(&fb->refcount, drm_framebuffer_free_bug);
> }
>
> --
> 1.9.3
>
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 0/8] prepare for preparing for atomic (v2)
@ 2014-05-30 17:12 Rob Clark
2014-05-30 17:12 ` [PATCH 1/8] drm: helpers to find mode objects Rob Clark
` (8 more replies)
0 siblings, 9 replies; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
As suggested by Daniel, splitting out ww_mutex conversion and a few
other bits out. Updated connection_mutex which fixes a few things,
plus split up addition of extended property types from adding object
property and pull in addition of _restore_fbdev_mode_unlocked() as
it does not depend on atomic.
Can be found at:
http://cgit.freedesktop.org/~robclark/linux/log/?h=atomic-prep
git://people.freedesktop.org/~robclark/linux atomic-prep
Daniel Vetter (1):
drm: Split connection_mutex out of mode_config.mutex (v3)
Rob Clark (7):
drm: helpers to find mode objects
drm: add extended property types
drm: add object property type
drm: add signed-range property type
drm: spiff out FB refcnting traces
drm: convert crtc and connection_mutex to ww_mutex (v3)
drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
drivers/gpu/drm/Makefile | 2 +-
drivers/gpu/drm/armada/armada_fbdev.c | 4 +-
drivers/gpu/drm/drm_crtc.c | 295 +++++++++++++++++++----------
drivers/gpu/drm/drm_crtc_helper.c | 1 +
drivers/gpu/drm/drm_edid.c | 2 +
drivers/gpu/drm/drm_fb_cma_helper.c | 9 +-
drivers/gpu/drm/drm_fb_helper.c | 55 ++++--
drivers/gpu/drm/drm_modeset_lock.c | 179 +++++++++++++++++
drivers/gpu/drm/drm_plane_helper.c | 7 +
drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +-
drivers/gpu/drm/gma500/psb_drv.c | 4 +-
drivers/gpu/drm/i915/i915_debugfs.c | 4 +-
drivers/gpu/drm/i915/i915_drv.c | 4 +-
drivers/gpu/drm/i915/intel_crt.c | 5 +-
drivers/gpu/drm/i915/intel_display.c | 60 ++++--
drivers/gpu/drm/i915/intel_dp.c | 15 +-
drivers/gpu/drm/i915/intel_drv.h | 6 +-
drivers/gpu/drm/i915/intel_fbdev.c | 6 +-
drivers/gpu/drm/i915/intel_opregion.c | 4 +-
drivers/gpu/drm/i915/intel_overlay.c | 4 +-
drivers/gpu/drm/i915/intel_panel.c | 8 +-
drivers/gpu/drm/i915/intel_sprite.c | 2 +-
drivers/gpu/drm/i915/intel_tv.c | 5 +-
drivers/gpu/drm/msm/msm_drv.c | 7 +-
drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +-
drivers/gpu/drm/omapdrm/omap_drv.c | 4 +-
drivers/gpu/drm/omapdrm/omap_fb.c | 1 +
drivers/gpu/drm/radeon/radeon_connectors.c | 1 +
drivers/gpu/drm/tegra/fb.c | 7 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +-
include/drm/drmP.h | 5 -
include/drm/drm_crtc.h | 81 +++++++-
include/drm/drm_fb_helper.h | 1 +
include/drm/drm_modeset_lock.h | 103 ++++++++++
include/uapi/drm/drm_mode.h | 15 ++
35 files changed, 716 insertions(+), 212 deletions(-)
create mode 100644 drivers/gpu/drm/drm_modeset_lock.c
create mode 100644 include/drm/drm_modeset_lock.h
--
1.9.3
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH 1/8] drm: helpers to find mode objects
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-06-03 13:22 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 2/8] drm: add extended property types Rob Clark
` (7 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
Add a few more useful helpers to find mode objects.
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/drm_crtc.c | 90 +++++++++++++++-------------------------------
include/drm/drm_crtc.h | 33 +++++++++++++++++
2 files changed, 61 insertions(+), 62 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 37a3e07..02872af 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -1711,7 +1711,6 @@ int drm_mode_getcrtc(struct drm_device *dev,
{
struct drm_mode_crtc *crtc_resp = data;
struct drm_crtc *crtc;
- struct drm_mode_object *obj;
int ret = 0;
if (!drm_core_check_feature(dev, DRIVER_MODESET))
@@ -1719,13 +1718,11 @@ int drm_mode_getcrtc(struct drm_device *dev,
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
+ if (!crtc) {
ret = -ENOENT;
goto out;
}
- crtc = obj_to_crtc(obj);
crtc_resp->x = crtc->x;
crtc_resp->y = crtc->y;
@@ -1779,7 +1776,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_get_connector *out_resp = data;
- struct drm_mode_object *obj;
struct drm_connector *connector;
struct drm_display_mode *mode;
int mode_count = 0;
@@ -1803,13 +1799,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
mutex_lock(&dev->mode_config.mutex);
- obj = drm_mode_object_find(dev, out_resp->connector_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
+ connector = drm_connector_find(dev, out_resp->connector_id);
+ if (!connector) {
ret = -ENOENT;
goto out;
}
- connector = obj_to_connector(obj);
props_count = connector->properties.count;
@@ -1924,7 +1918,6 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_get_encoder *enc_resp = data;
- struct drm_mode_object *obj;
struct drm_encoder *encoder;
int ret = 0;
@@ -1932,13 +1925,11 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
return -EINVAL;
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, enc_resp->encoder_id,
- DRM_MODE_OBJECT_ENCODER);
- if (!obj) {
+ encoder = drm_encoder_find(dev, enc_resp->encoder_id);
+ if (!encoder) {
ret = -ENOENT;
goto out;
}
- encoder = obj_to_encoder(obj);
if (encoder->crtc)
enc_resp->crtc_id = encoder->crtc->base.id;
@@ -2036,7 +2027,6 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_get_plane *plane_resp = data;
- struct drm_mode_object *obj;
struct drm_plane *plane;
uint32_t __user *format_ptr;
int ret = 0;
@@ -2045,13 +2035,11 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
return -EINVAL;
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, plane_resp->plane_id,
- DRM_MODE_OBJECT_PLANE);
- if (!obj) {
+ plane = drm_plane_find(dev, plane_resp->plane_id);
+ if (!plane) {
ret = -ENOENT;
goto out;
}
- plane = obj_to_plane(obj);
if (plane->crtc)
plane_resp->crtc_id = plane->crtc->base.id;
@@ -2104,7 +2092,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_mode_set_plane *plane_req = data;
- struct drm_mode_object *obj;
struct drm_plane *plane;
struct drm_crtc *crtc;
struct drm_framebuffer *fb = NULL, *old_fb = NULL;
@@ -2119,14 +2106,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
* First, find the plane, crtc, and fb objects. If not available,
* we don't bother to call the driver.
*/
- obj = drm_mode_object_find(dev, plane_req->plane_id,
- DRM_MODE_OBJECT_PLANE);
- if (!obj) {
+ plane = drm_plane_find(dev, plane_req->plane_id);
+ if (!plane) {
DRM_DEBUG_KMS("Unknown plane ID %d\n",
plane_req->plane_id);
return -ENOENT;
}
- plane = obj_to_plane(obj);
/* No fb means shut it down */
if (!plane_req->fb_id) {
@@ -2143,15 +2128,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
goto out;
}
- obj = drm_mode_object_find(dev, plane_req->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(dev, plane_req->crtc_id);
+ if (!crtc) {
DRM_DEBUG_KMS("Unknown crtc ID %d\n",
plane_req->crtc_id);
ret = -ENOENT;
goto out;
}
- crtc = obj_to_crtc(obj);
fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
if (!fb) {
@@ -2338,7 +2321,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
{
struct drm_mode_config *config = &dev->mode_config;
struct drm_mode_crtc *crtc_req = data;
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct drm_connector **connector_set = NULL, *connector;
struct drm_framebuffer *fb = NULL;
@@ -2356,14 +2338,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
return -ERANGE;
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, crtc_req->crtc_id,
- DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(dev, crtc_req->crtc_id);
+ if (!crtc) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
ret = -ENOENT;
goto out;
}
- crtc = obj_to_crtc(obj);
DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
if (crtc_req->mode_valid) {
@@ -2446,15 +2426,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
goto out;
}
- obj = drm_mode_object_find(dev, out_id,
- DRM_MODE_OBJECT_CONNECTOR);
- if (!obj) {
+ connector = drm_connector_find(dev, out_id);
+ if (!connector) {
DRM_DEBUG_KMS("Connector id %d unknown\n",
out_id);
ret = -ENOENT;
goto out;
}
- connector = obj_to_connector(obj);
DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
connector->base.id,
drm_get_connector_name(connector));
@@ -2486,7 +2464,6 @@ static int drm_mode_cursor_common(struct drm_device *dev,
struct drm_mode_cursor2 *req,
struct drm_file *file_priv)
{
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
int ret = 0;
@@ -2496,12 +2473,11 @@ static int drm_mode_cursor_common(struct drm_device *dev,
if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
return -EINVAL;
- obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(dev, req->crtc_id);
+ if (!crtc) {
DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
return -ENOENT;
}
- crtc = obj_to_crtc(obj);
mutex_lock(&crtc->mutex);
if (req->flags & DRM_MODE_CURSOR_BO) {
@@ -3458,7 +3434,6 @@ EXPORT_SYMBOL(drm_object_property_get_value);
int drm_mode_getproperty_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
- struct drm_mode_object *obj;
struct drm_mode_get_property *out_resp = data;
struct drm_property *property;
int enum_count = 0;
@@ -3477,12 +3452,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
return -EINVAL;
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
- if (!obj) {
+ property = drm_property_find(dev, out_resp->prop_id);
+ if (!property) {
ret = -ENOENT;
goto done;
}
- property = obj_to_property(obj);
if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
list_for_each_entry(prop_enum, &property->enum_blob_list, head)
@@ -3610,7 +3584,6 @@ static void drm_property_destroy_blob(struct drm_device *dev,
int drm_mode_getblob_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
- struct drm_mode_object *obj;
struct drm_mode_get_blob *out_resp = data;
struct drm_property_blob *blob;
int ret = 0;
@@ -3620,12 +3593,11 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
return -EINVAL;
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
- if (!obj) {
+ blob = drm_property_blob_find(dev, out_resp->blob_id);
+ if (!blob) {
ret = -ENOENT;
goto done;
}
- blob = obj_to_blob(obj);
if (out_resp->length == blob->length) {
blob_ptr = (void __user *)(unsigned long)out_resp->data;
@@ -4007,7 +3979,6 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_crtc_lut *crtc_lut = data;
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
void *r_base, *g_base, *b_base;
int size;
@@ -4017,12 +3988,11 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
return -EINVAL;
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
+ if (!crtc) {
ret = -ENOENT;
goto out;
}
- crtc = obj_to_crtc(obj);
if (crtc->funcs->gamma_set == NULL) {
ret = -ENOSYS;
@@ -4081,7 +4051,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_crtc_lut *crtc_lut = data;
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
void *r_base, *g_base, *b_base;
int size;
@@ -4091,12 +4060,11 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
return -EINVAL;
drm_modeset_lock_all(dev);
- obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj) {
+ crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
+ if (!crtc) {
ret = -ENOENT;
goto out;
}
- crtc = obj_to_crtc(obj);
/* memcpy into gamma store */
if (crtc_lut->gamma_size != crtc->gamma_size) {
@@ -4149,7 +4117,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
void *data, struct drm_file *file_priv)
{
struct drm_mode_crtc_page_flip *page_flip = data;
- struct drm_mode_object *obj;
struct drm_crtc *crtc;
struct drm_framebuffer *fb = NULL, *old_fb = NULL;
struct drm_pending_vblank_event *e = NULL;
@@ -4163,10 +4130,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
return -EINVAL;
- obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
- if (!obj)
+ crtc = drm_crtc_find(dev, page_flip->crtc_id);
+ if (!crtc)
return -ENOENT;
- crtc = obj_to_crtc(obj);
mutex_lock(&crtc->mutex);
if (crtc->primary->fb == NULL) {
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 5c1c31c..cdd5687 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -1063,6 +1063,15 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);
extern const char *drm_get_format_name(uint32_t format);
/* Helpers */
+
+static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
+ uint32_t id)
+{
+ struct drm_mode_object *mo;
+ mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PLANE);
+ return mo ? obj_to_plane(mo) : NULL;
+}
+
static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
uint32_t id)
{
@@ -1079,6 +1088,30 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
return mo ? obj_to_encoder(mo) : NULL;
}
+static inline struct drm_connector *drm_connector_find(struct drm_device *dev,
+ uint32_t id)
+{
+ struct drm_mode_object *mo;
+ mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR);
+ return mo ? obj_to_connector(mo) : NULL;
+}
+
+static inline struct drm_property *drm_property_find(struct drm_device *dev,
+ uint32_t id)
+{
+ struct drm_mode_object *mo;
+ mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
+ return mo ? obj_to_property(mo) : NULL;
+}
+
+static inline struct drm_property_blob *
+drm_property_blob_find(struct drm_device *dev, uint32_t id)
+{
+ struct drm_mode_object *mo;
+ mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
+ return mo ? obj_to_blob(mo) : NULL;
+}
+
/* Plane list iterator for legacy (overlay only) planes. */
#define drm_for_each_legacy_plane(plane, planelist) \
list_for_each_entry(plane, planelist, head) \
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 2/8] drm: add extended property types
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
2014-05-30 17:12 ` [PATCH 1/8] drm: helpers to find mode objects Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-06-03 13:25 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 3/8] drm: add object property type Rob Clark
` (6 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
If we continue to use bitmask for type, we will quickly run out of room
to add new types. Split this up so existing part of bitmask range
continues to function as before, but reserve a chunk of the remaining
space for an integer type-id. Wrap this all up in some type-check
helpers to keep the backwards-compat uglyness contained.
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/drm_crtc.c | 26 +++++++++++++++++---------
include/drm/drm_crtc.h | 17 +++++++++++++++++
include/uapi/drm/drm_mode.h | 13 +++++++++++++
3 files changed, 47 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 02872af..0dbd6e0 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3113,6 +3113,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
}
list_add_tail(&property->head, &dev->mode_config.property_list);
+
+ WARN_ON(!drm_property_type_valid(property));
+
return property;
fail:
kfree(property->values);
@@ -3270,14 +3273,16 @@ int drm_property_add_enum(struct drm_property *property, int index,
{
struct drm_property_enum *prop_enum;
- if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
+ if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
+ drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
return -EINVAL;
/*
* Bitmask enum properties have the additional constraint of values
* from 0 to 63
*/
- if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
+ if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
+ (value > 63))
return -EINVAL;
if (!list_empty(&property->enum_blob_list)) {
@@ -3458,10 +3463,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
goto done;
}
- if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
+ if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
+ drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
list_for_each_entry(prop_enum, &property->enum_blob_list, head)
enum_count++;
- } else if (property->flags & DRM_MODE_PROP_BLOB) {
+ } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
list_for_each_entry(prop_blob, &property->enum_blob_list, head)
blob_count++;
}
@@ -3483,7 +3489,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
}
out_resp->count_values = value_count;
- if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
+ if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
+ drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
copied = 0;
enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
@@ -3505,7 +3512,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
out_resp->count_enum_blobs = enum_count;
}
- if (property->flags & DRM_MODE_PROP_BLOB) {
+ if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
copied = 0;
blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
@@ -3659,17 +3666,18 @@ static bool drm_property_change_is_valid(struct drm_property *property,
{
if (property->flags & DRM_MODE_PROP_IMMUTABLE)
return false;
- if (property->flags & DRM_MODE_PROP_RANGE) {
+
+ if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
if (value < property->values[0] || value > property->values[1])
return false;
return true;
- } else if (property->flags & DRM_MODE_PROP_BITMASK) {
+ } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
int i;
uint64_t valid_mask = 0;
for (i = 0; i < property->num_values; i++)
valid_mask |= (1ULL << property->values[i]);
return !(value & ~valid_mask);
- } else if (property->flags & DRM_MODE_PROP_BLOB) {
+ } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
/* Only the driver knows */
return true;
} else {
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index cdd5687..0ff9558 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -931,6 +931,23 @@ extern void drm_mode_config_cleanup(struct drm_device *dev);
extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
struct edid *edid);
+
+static inline bool drm_property_type_is(struct drm_property *property,
+ uint32_t type)
+{
+ /* instanceof for props.. handles extended type vs original types: */
+ if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
+ return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
+ return property->flags & type;
+}
+
+static inline bool drm_property_type_valid(struct drm_property *property)
+{
+ if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
+ return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
+ return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
+}
+
extern int drm_object_property_set_value(struct drm_mode_object *obj,
struct drm_property *property,
uint64_t val);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index f104c26..a7f546e 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -251,6 +251,19 @@ struct drm_mode_get_connector {
#define DRM_MODE_PROP_BLOB (1<<4)
#define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */
+/* non-extended types: legacy bitmask, one bit per type: */
+#define DRM_MODE_PROP_LEGACY_TYPE ( \
+ DRM_MODE_PROP_RANGE | \
+ DRM_MODE_PROP_ENUM | \
+ DRM_MODE_PROP_BLOB | \
+ DRM_MODE_PROP_BITMASK)
+
+/* extended-types: rather than continue to consume a bit per type,
+ * grab a chunk of the bits to use as integer type id.
+ */
+#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
+#define DRM_MODE_PROP_TYPE(n) ((n) << 6)
+
struct drm_mode_property_enum {
__u64 value;
char name[DRM_PROP_NAME_LEN];
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 3/8] drm: add object property type
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
2014-05-30 17:12 ` [PATCH 1/8] drm: helpers to find mode objects Rob Clark
2014-05-30 17:12 ` [PATCH 2/8] drm: add extended property types Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-06-03 13:24 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 4/8] drm: add signed-range " Rob Clark
` (5 subsequent siblings)
8 siblings, 1 reply; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
An object property is an id (idr) for a drm mode object. This
will allow a property to be used set/get a framebuffer, CRTC, etc.
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/drm_crtc.c | 61 +++++++++++++++++++++++++++++++++++++++------
include/drm/drm_crtc.h | 5 ++++
include/uapi/drm/drm_mode.h | 1 +
3 files changed, 60 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 0dbd6e0..8fdd5b3 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -389,6 +389,21 @@ void drm_mode_object_put(struct drm_device *dev,
mutex_unlock(&dev->mode_config.idr_mutex);
}
+static struct drm_mode_object *_object_find(struct drm_device *dev,
+ uint32_t id, uint32_t type)
+{
+ struct drm_mode_object *obj = NULL;
+
+ mutex_lock(&dev->mode_config.idr_mutex);
+ obj = idr_find(&dev->mode_config.crtc_idr, id);
+ if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) ||
+ (obj->id != id))
+ obj = NULL;
+ mutex_unlock(&dev->mode_config.idr_mutex);
+
+ return obj;
+}
+
/**
* drm_mode_object_find - look up a drm object with static lifetime
* @dev: drm device
@@ -396,7 +411,9 @@ void drm_mode_object_put(struct drm_device *dev,
* @type: type of the mode object
*
* Note that framebuffers cannot be looked up with this functions - since those
- * are reference counted, they need special treatment.
+ * are reference counted, they need special treatment. Even with
+ * DRM_MODE_OBJECT_ANY (although that will simply return NULL
+ * rather than WARN_ON()).
*/
struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
uint32_t id, uint32_t type)
@@ -406,13 +423,10 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
/* Framebuffers are reference counted and need their own lookup
* function.*/
WARN_ON(type == DRM_MODE_OBJECT_FB);
-
- mutex_lock(&dev->mode_config.idr_mutex);
- obj = idr_find(&dev->mode_config.crtc_idr, id);
- if (!obj || (obj->type != type) || (obj->id != id))
+ obj = _object_find(dev, id, type);
+ /* don't leak out unref'd fb's */
+ if (obj && (obj->type == DRM_MODE_OBJECT_FB))
obj = NULL;
- mutex_unlock(&dev->mode_config.idr_mutex);
-
return obj;
}
EXPORT_SYMBOL(drm_mode_object_find);
@@ -3093,6 +3107,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
if (!property)
return NULL;
+ property->dev = dev;
+
if (num_values) {
property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
if (!property->values)
@@ -3253,6 +3269,23 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
}
EXPORT_SYMBOL(drm_property_create_range);
+struct drm_property *drm_property_create_object(struct drm_device *dev,
+ int flags, const char *name, uint32_t type)
+{
+ struct drm_property *property;
+
+ flags |= DRM_MODE_PROP_OBJECT;
+
+ property = drm_property_create(dev, flags, name, 1);
+ if (!property)
+ return NULL;
+
+ property->values[0] = type;
+
+ return property;
+}
+EXPORT_SYMBOL(drm_property_create_object);
+
/**
* drm_property_add_enum - add a possible value to an enumeration property
* @property: enumeration property to change
@@ -3680,6 +3713,20 @@ static bool drm_property_change_is_valid(struct drm_property *property,
} else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
/* Only the driver knows */
return true;
+ } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
+ struct drm_mode_object *obj;
+ /* a zero value for an object property translates to null: */
+ if (value == 0)
+ return true;
+ /*
+ * NOTE: use _object_find() directly to bypass restriction on
+ * looking up refcnt'd objects (ie. fb's). For a refcnt'd
+ * object this could race against object finalization, so it
+ * simply tells us that the object *was* valid. Which is good
+ * enough.
+ */
+ obj = _object_find(property->dev, value, property->values[0]);
+ return obj != NULL;
} else {
int i;
for (i = 0; i < property->num_values; i++)
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 0ff9558..c63df87 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -50,6 +50,7 @@ struct drm_clip_rect;
#define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
#define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
#define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd
+#define DRM_MODE_OBJECT_ANY 0
struct drm_mode_object {
uint32_t id;
@@ -190,6 +191,7 @@ struct drm_property {
char name[DRM_PROP_NAME_LEN];
uint32_t num_values;
uint64_t *values;
+ struct drm_device *dev;
struct list_head enum_blob_list;
};
@@ -981,6 +983,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
const char *name,
uint64_t min, uint64_t max);
+struct drm_property *drm_property_create_object(struct drm_device *dev,
+ int flags, const char *name, uint32_t type);
extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
extern int drm_property_add_enum(struct drm_property *property, int index,
uint64_t value, const char *name);
@@ -997,6 +1001,7 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
int gamma_size);
extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
uint32_t id, uint32_t type);
+
/* IOCTLs */
extern int drm_mode_getresources(struct drm_device *dev,
void *data, struct drm_file *file_priv);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index a7f546e..5b530c7 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -263,6 +263,7 @@ struct drm_mode_get_connector {
*/
#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
#define DRM_MODE_PROP_TYPE(n) ((n) << 6)
+#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)
struct drm_mode_property_enum {
__u64 value;
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 4/8] drm: add signed-range property type
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
` (2 preceding siblings ...)
2014-05-30 17:12 ` [PATCH 3/8] drm: add object property type Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-05-30 17:12 ` [PATCH 5/8] drm: spiff out FB refcnting traces Rob Clark
` (4 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
Like range, but values are signed.
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/gpu/drm/drm_crtc.c | 45 +++++++++++++++++++++++++++++++++------------
include/drm/drm_crtc.h | 12 ++++++++++++
include/uapi/drm/drm_mode.h | 1 +
3 files changed, 46 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index 8fdd5b3..ae3d302 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -3232,6 +3232,22 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
}
EXPORT_SYMBOL(drm_property_create_bitmask);
+static struct drm_property *property_create_range(struct drm_device *dev,
+ int flags, const char *name,
+ uint64_t min, uint64_t max)
+{
+ struct drm_property *property;
+
+ property = drm_property_create(dev, flags, name, 2);
+ if (!property)
+ return NULL;
+
+ property->values[0] = min;
+ property->values[1] = max;
+
+ return property;
+}
+
/**
* drm_property_create - create a new ranged property type
* @dev: drm device
@@ -3254,21 +3270,20 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
const char *name,
uint64_t min, uint64_t max)
{
- struct drm_property *property;
-
- flags |= DRM_MODE_PROP_RANGE;
-
- property = drm_property_create(dev, flags, name, 2);
- if (!property)
- return NULL;
-
- property->values[0] = min;
- property->values[1] = max;
-
- return property;
+ return property_create_range(dev, DRM_MODE_PROP_RANGE | flags,
+ name, min, max);
}
EXPORT_SYMBOL(drm_property_create_range);
+struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
+ int flags, const char *name,
+ int64_t min, int64_t max)
+{
+ return property_create_range(dev, DRM_MODE_PROP_SIGNED_RANGE | flags,
+ name, I642U64(min), I642U64(max));
+}
+EXPORT_SYMBOL(drm_property_create_signed_range);
+
struct drm_property *drm_property_create_object(struct drm_device *dev,
int flags, const char *name, uint32_t type)
{
@@ -3704,6 +3719,12 @@ static bool drm_property_change_is_valid(struct drm_property *property,
if (value < property->values[0] || value > property->values[1])
return false;
return true;
+ } else if (drm_property_type_is(property, DRM_MODE_PROP_SIGNED_RANGE)) {
+ int64_t svalue = U642I64(value);
+ if (svalue < U642I64(property->values[0]) ||
+ svalue > U642I64(property->values[1]))
+ return false;
+ return true;
} else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
int i;
uint64_t valid_mask = 0;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index c63df87..f7dd3c6 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -65,6 +65,15 @@ struct drm_object_properties {
uint64_t values[DRM_OBJECT_MAX_PROPERTY];
};
+static inline int64_t U642I64(uint64_t val)
+{
+ return (int64_t)*((int64_t *)&val);
+}
+static inline uint64_t I642U64(int64_t val)
+{
+ return (uint64_t)*((uint64_t *)&val);
+}
+
enum drm_connector_force {
DRM_FORCE_UNSPECIFIED,
DRM_FORCE_OFF,
@@ -983,6 +992,9 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
const char *name,
uint64_t min, uint64_t max);
+struct drm_property *drm_property_create_signed_range(struct drm_device *dev,
+ int flags, const char *name,
+ int64_t min, int64_t max);
struct drm_property *drm_property_create_object(struct drm_device *dev,
int flags, const char *name, uint32_t type);
extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
index 5b530c7..ded505e 100644
--- a/include/uapi/drm/drm_mode.h
+++ b/include/uapi/drm/drm_mode.h
@@ -264,6 +264,7 @@ struct drm_mode_get_connector {
#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
#define DRM_MODE_PROP_TYPE(n) ((n) << 6)
#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)
+#define DRM_MODE_PROP_SIGNED_RANGE DRM_MODE_PROP_TYPE(2)
struct drm_mode_property_enum {
__u64 value;
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 5/8] drm: spiff out FB refcnting traces
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
` (3 preceding siblings ...)
2014-05-30 17:12 ` [PATCH 4/8] drm: add signed-range " Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-05-30 17:12 ` [PATCH 6/8] drm: Split connection_mutex out of mode_config.mutex (v3) Rob Clark
` (3 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
I find myself making this change locally whenever debugging FB reference
counting. Which seems a bit silly.
Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: David Herrmann <dh.herrmann@gmail.com>
---
drivers/gpu/drm/drm_crtc.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index ae3d302..eaf21a0 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -532,7 +532,7 @@ EXPORT_SYMBOL(drm_framebuffer_lookup);
*/
void drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
- DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
kref_put(&fb->refcount, drm_framebuffer_free);
}
EXPORT_SYMBOL(drm_framebuffer_unreference);
@@ -545,7 +545,7 @@ EXPORT_SYMBOL(drm_framebuffer_unreference);
*/
void drm_framebuffer_reference(struct drm_framebuffer *fb)
{
- DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ DRM_DEBUG("%p: FB ID: %d (%d)\n", fb, fb->base.id, atomic_read(&fb->refcount.refcount));
kref_get(&fb->refcount);
}
EXPORT_SYMBOL(drm_framebuffer_reference);
@@ -557,7 +557,7 @@ static void drm_framebuffer_free_bug(struct kref *kref)
static void __drm_framebuffer_unreference(struct drm_framebuffer *fb)
{
- DRM_DEBUG("FB ID: %d\n", fb->base.id);
+ 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);
}
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 6/8] drm: Split connection_mutex out of mode_config.mutex (v3)
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
` (4 preceding siblings ...)
2014-05-30 17:12 ` [PATCH 5/8] drm: spiff out FB refcnting traces Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-05-30 17:12 ` [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3) Rob Clark
` (2 subsequent siblings)
8 siblings, 0 replies; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel; +Cc: Daniel Vetter
From: Daniel Vetter <daniel.vetter@ffwll.ch>
After the split-out of crtc locks from the big mode_config.mutex
there's still two major areas it protects:
- Various connector probe states, like connector->status, EDID
properties, probed mode lists and similar information.
- The links from connector->encoder and encoder->crtc and other
modeset-relevant connector state (e.g. properties which control the
panel fitter).
The later is used by modeset operations. But they don't really care
about the former since it's allowed to e.g. enable a disconnected VGA
output or with a mode not in the probed list.
Thus far this hasn't been a problem, but for the atomic modeset
conversion Rob Clark needs to convert all modeset relevant locks into
w/w locks. This is required because the order of acquisition is
determined by how userspace supplies the atomic modeset data. This has
run into troubles in the detect path since the i915 load detect code
needs _both_ protections offered by the mode_config.mutex: It updates
probe state and it needs to change the modeset configuration to enable
the temporary load detect pipe.
The big deal here is that for the probe/detect users of this lock a
plain mutex fits best, but for atomic modesets we really want a w/w
mutex. To fix this lets split out a new connection_mutex lock for the
modeset relevant parts.
For simplicity I've decided to only add one additional lock for all
connector/encoder links and modeset configuration states. We have
piles of different modeset objects in addition to those (like bridges
or panels), so adding per-object locks would be much more effort.
Also, we're guaranteed (at least for now) to do a full modeset if we
need to acquire this lock. Which means that fine-grained locking is
fairly irrelevant compared to the amount of time the full modeset will
take.
I've done a full audit, and there's just a few things that justify
special focus:
- Locking in drm_sysfs.c is almost completely absent. We should
sprinkle mode_config.connection_mutex over this file a bit, but
since it already lacks mode_config.mutex this patch wont make the
situation any worse. This is material for a follow-up patch.
- omap has a omap_framebuffer_flush function which walks the
connector->encoder->crtc links and is called from many contexts.
Some look like they don't acquire mode_config.mutex, so this is
already racy. Again fixing this is material for a separate patch.
- The radeon hot_plug function to retrain DP links looks at
connector->dpms. Currently this happens without any locking, so is
already racy. I think radeon_hotplug_work_func should gain
mutex_lock/unlock calls for the mode_config.connection_mutex.
- Same applies to i915's intel_dp_hot_plug. But again, this is already
racy.
- i915 load_detect code needs to acquire this lock. Which means the
w/w dance due to Rob's work will be nicely contained to _just_ this
function.
I've added fixme comments everywhere where it looks suspicious but in
the sysfs code. After a quick irc discussion with Dave Airlie it
sounds like the lack of locking in there is due to sysfs cleanup fun
at module unload.
v1: original (only compile tested)
v2: missing mutex_init(), etc (from Rob Clark)
v3: i915 needs more care in the conversion:
- Protect the edp pp logic with the connection_mutex.
- Use connection_mutex in the backlight code due to
get_pipe_from_connector.
- Use drm_modeset_lock_all in suspend/resume paths.
- Update lock checks in the overlay code.
Cc: Alex Deucher <alexdeucher@gmail.com>
Cc: Rob Clark <robdclark@gmail.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
drivers/gpu/drm/drm_crtc.c | 8 ++++++++
drivers/gpu/drm/drm_crtc_helper.c | 2 ++
drivers/gpu/drm/drm_edid.c | 2 ++
drivers/gpu/drm/drm_plane_helper.c | 7 +++++++
drivers/gpu/drm/i915/i915_debugfs.c | 4 ++--
drivers/gpu/drm/i915/i915_drv.c | 4 ++--
drivers/gpu/drm/i915/intel_display.c | 16 ++++++++++++----
drivers/gpu/drm/i915/intel_dp.c | 15 ++++++++-------
drivers/gpu/drm/i915/intel_opregion.c | 4 ++--
drivers/gpu/drm/i915/intel_overlay.c | 4 ++--
drivers/gpu/drm/i915/intel_panel.c | 8 ++++----
drivers/gpu/drm/omapdrm/omap_fb.c | 1 +
drivers/gpu/drm/radeon/radeon_connectors.c | 1 +
include/drm/drm_crtc.h | 1 +
14 files changed, 54 insertions(+), 23 deletions(-)
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index eaf21a0..bbb329f 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -54,6 +54,8 @@ void drm_modeset_lock_all(struct drm_device *dev)
mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
+
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
}
@@ -72,6 +74,8 @@ void drm_modeset_unlock_all(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
mutex_unlock(&crtc->mutex);
+ mutex_unlock(&dev->mode_config.connection_mutex);
+
mutex_unlock(&dev->mode_config.mutex);
}
EXPORT_SYMBOL(drm_modeset_unlock_all);
@@ -93,6 +97,7 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
WARN_ON(!mutex_is_locked(&crtc->mutex));
+ WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
}
EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
@@ -1812,6 +1817,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
connector = drm_connector_find(dev, out_resp->connector_id);
if (!connector) {
@@ -1910,6 +1916,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
out_resp->count_encoders = encoders_count;
out:
+ mutex_unlock(&dev->mode_config.connection_mutex);
mutex_unlock(&dev->mode_config.mutex);
return ret;
@@ -4659,6 +4666,7 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
void drm_mode_config_init(struct drm_device *dev)
{
mutex_init(&dev->mode_config.mutex);
+ mutex_init(&dev->mode_config.connection_mutex);
mutex_init(&dev->mode_config.idr_mutex);
mutex_init(&dev->mode_config.fb_lock);
INIT_LIST_HEAD(&dev->mode_config.fb_list);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 54e8fdb..5b93caf 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -89,6 +89,8 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
struct drm_device *dev = encoder->dev;
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+ WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder == encoder)
return true;
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index d74239f..e3bc051 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -3299,6 +3299,8 @@ struct drm_connector *drm_select_eld(struct drm_encoder *encoder,
struct drm_connector *connector;
struct drm_device *dev = encoder->dev;
+ WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder == encoder && connector->eld[0])
return connector;
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index d966afa..458d9bf 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -54,6 +54,13 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
struct drm_connector *connector;
int count = 0;
+ /*
+ * Note: Once we change the plane hooks to more fine-grained locking we
+ * need to grab the connection_mutex here to be able to make these
+ * checks.
+ */
+ WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder && connector->encoder->crtc == crtc) {
if (connector_list != NULL && count < num_connectors)
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index 18b3565..c269adc 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -2573,7 +2573,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe,
*source = INTEL_PIPE_CRC_SOURCE_PIPE;
- mutex_lock(&dev->mode_config.mutex);
+ drm_modeset_lock_all(dev);
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
base.head) {
if (!encoder->base.crtc)
@@ -2609,7 +2609,7 @@ static int i9xx_pipe_crc_auto_source(struct drm_device *dev, enum pipe pipe,
break;
}
}
- mutex_unlock(&dev->mode_config.mutex);
+ drm_modeset_unlock_all(dev);
return ret;
}
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 208e185..284e748 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -475,10 +475,10 @@ static int i915_drm_freeze(struct drm_device *dev)
* Disable CRTCs directly since we want to preserve sw state
* for _thaw.
*/
- mutex_lock(&dev->mode_config.mutex);
+ drm_modeset_lock_all(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
dev_priv->display.crtc_disable(crtc);
- mutex_unlock(&dev->mode_config.mutex);
+ drm_modeset_unlock_all(dev);
intel_modeset_suspend_hw(dev);
}
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 72b5c34..8cf4bde 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -7988,6 +7988,8 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
connector->base.id, drm_get_connector_name(connector),
encoder->base.id, drm_get_encoder_name(encoder));
+ mutex_lock(&dev->mode_config.connection_mutex);
+
/*
* Algorithm gets a little messy:
*
@@ -8030,7 +8032,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
*/
if (!crtc) {
DRM_DEBUG_KMS("no pipe available for load-detect\n");
- return false;
+ goto fail_unlock_connector;
}
mutex_lock(&crtc->mutex);
@@ -8084,6 +8086,9 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
else
intel_crtc->new_config = NULL;
mutex_unlock(&crtc->mutex);
+fail_unlock_connector:
+ mutex_unlock(&dev->mode_config.connection_mutex);
+
return false;
}
@@ -8113,6 +8118,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
}
mutex_unlock(&crtc->mutex);
+ mutex_unlock(&connector->dev->mode_config.connection_mutex);
return;
}
@@ -8121,6 +8127,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
connector->funcs->dpms(connector, old->dpms_mode);
mutex_unlock(&crtc->mutex);
+ mutex_unlock(&connector->dev->mode_config.connection_mutex);
}
static int i9xx_pll_refclk(struct drm_device *dev,
@@ -10577,8 +10584,9 @@ static void intel_crtc_init(struct drm_device *dev, int pipe)
enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
{
struct drm_encoder *encoder = connector->base.encoder;
+ struct drm_device *dev = connector->base.dev;
- WARN_ON(!mutex_is_locked(&connector->base.dev->mode_config.mutex));
+ WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
if (!encoder)
return INVALID_PIPE;
@@ -11336,9 +11344,9 @@ void intel_modeset_init(struct drm_device *dev)
/* Just in case the BIOS is doing something questionable. */
intel_disable_fbc(dev);
- mutex_lock(&dev->mode_config.mutex);
+ drm_modeset_lock_all(dev);
intel_modeset_setup_hw_state(dev, false);
- mutex_unlock(&dev->mode_config.mutex);
+ drm_modeset_unlock_all(dev);
list_for_each_entry(crtc, &dev->mode_config.crtc_list,
base.head) {
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 34ed143..89fd1dd 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1131,7 +1131,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
u32 pp;
u32 pp_stat_reg, pp_ctrl_reg;
- WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+ WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
struct intel_digital_port *intel_dig_port =
@@ -1168,9 +1168,9 @@ static void edp_panel_vdd_work(struct work_struct *__work)
struct intel_dp, panel_vdd_work);
struct drm_device *dev = intel_dp_to_dev(intel_dp);
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
edp_panel_vdd_off_sync(intel_dp);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.connection_mutex);
}
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
@@ -2953,6 +2953,7 @@ intel_dp_check_link_status(struct intel_dp *intel_dp)
u8 sink_irq_vector;
u8 link_status[DP_LINK_STATUS_SIZE];
+ /* FIXME: This access isn't protected by any locks. */
if (!intel_encoder->connectors_active)
return;
@@ -3383,9 +3384,9 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
edp_panel_vdd_off_sync(intel_dp);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.connection_mutex);
}
kfree(intel_dig_port);
}
@@ -3964,9 +3965,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
edp_panel_vdd_off_sync(intel_dp);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.connection_mutex);
}
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index acde294..b812e9d 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -410,7 +410,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
if (bclp > 255)
return ASLC_BACKLIGHT_FAILED;
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
/*
* Update backlight on all connectors that support backlight (usually
@@ -421,7 +421,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
intel_panel_set_backlight(intel_connector, bclp, 255);
iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.connection_mutex);
return 0;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index d8adc91..88249c4 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -688,7 +688,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
u32 swidth, swidthsw, sheight, ostride;
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
- BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
+ BUG_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
BUG_ON(!overlay);
ret = intel_overlay_release_old_vid(overlay);
@@ -793,7 +793,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
int ret;
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
- BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
+ BUG_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
ret = intel_overlay_recover_from_interrupt(overlay);
if (ret != 0)
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index 44ad415..f3df527 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -823,12 +823,12 @@ static int intel_backlight_device_update_status(struct backlight_device *bd)
struct intel_connector *connector = bl_get_data(bd);
struct drm_device *dev = connector->base.dev;
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
bd->props.brightness, bd->props.max_brightness);
intel_panel_set_backlight(connector, bd->props.brightness,
bd->props.max_brightness);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.connection_mutex);
return 0;
}
@@ -840,9 +840,9 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
int ret;
intel_runtime_pm_get(dev_priv);
- mutex_lock(&dev->mode_config.mutex);
+ mutex_lock(&dev->mode_config.connection_mutex);
ret = intel_panel_get_backlight(connector);
- mutex_unlock(&dev->mode_config.mutex);
+ mutex_unlock(&dev->mode_config.connection_mutex);
intel_runtime_pm_put(dev_priv);
return ret;
diff --git a/drivers/gpu/drm/omapdrm/omap_fb.c b/drivers/gpu/drm/omapdrm/omap_fb.c
index 8b01960..2a5cacd 100644
--- a/drivers/gpu/drm/omapdrm/omap_fb.c
+++ b/drivers/gpu/drm/omapdrm/omap_fb.c
@@ -346,6 +346,7 @@ void omap_framebuffer_flush(struct drm_framebuffer *fb,
VERB("flush: %d,%d %dx%d, fb=%p", x, y, w, h, fb);
+ /* FIXME: This is racy - no protection against modeset config changes. */
while ((connector = omap_framebuffer_get_next_connector(fb, connector))) {
/* only consider connectors that are part of a chain */
if (connector->encoder && connector->encoder->crtc) {
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index ea50e0a..bcfe5d5 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -48,6 +48,7 @@ void radeon_connector_hotplug(struct drm_connector *connector)
radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd);
/* if the connector is already off, don't turn it back on */
+ /* FIXME: This access isn't protected by any locks. */
if (connector->dpms != DRM_MODE_DPMS_ON)
return;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index f7dd3c6..56dffc6 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -738,6 +738,7 @@ struct drm_mode_group {
*/
struct drm_mode_config {
struct mutex mutex; /* protects configuration (mode lists etc.) */
+ struct mutex connection_mutex; /* protects connector->encoder and encoder->crtc links */
struct mutex idr_mutex; /* for IDR management */
struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
/* this is limited to one for now */
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3)
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
` (5 preceding siblings ...)
2014-05-30 17:12 ` [PATCH 6/8] drm: Split connection_mutex out of mode_config.mutex (v3) Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-06-03 13:29 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked() Rob Clark
2014-06-02 8:11 ` [PATCH 0/8] prepare for preparing for atomic (v2) Daniel Vetter
8 siblings, 1 reply; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
For atomic, it will be quite necessary to not need to care so much
about locking order. And 'state' gives us a convenient place to stash a
ww_ctx for any sort of update that needs to grab multiple crtc locks.
Because we will want to eventually make locking even more fine grained
(giving locks to planes, connectors, etc), split out drm_modeset_lock
and drm_modeset_acquire_ctx to track acquired locks.
Atomic will use this to keep track of which locks have been acquired
in a transaction.
v1: original
v2: remove a few things not needed until atomic, for now
v3: update for v3 of connection_mutex patch..
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/Makefile | 2 +-
drivers/gpu/drm/drm_crtc.c | 85 +++++++++++-----
drivers/gpu/drm/drm_crtc_helper.c | 3 +-
drivers/gpu/drm/drm_fb_helper.c | 4 +
drivers/gpu/drm/drm_modeset_lock.c | 179 ++++++++++++++++++++++++++++++++++
drivers/gpu/drm/drm_plane_helper.c | 2 +-
drivers/gpu/drm/i915/intel_crt.c | 5 +-
drivers/gpu/drm/i915/intel_display.c | 58 +++++++----
drivers/gpu/drm/i915/intel_dp.c | 14 +--
drivers/gpu/drm/i915/intel_drv.h | 6 +-
drivers/gpu/drm/i915/intel_opregion.c | 4 +-
drivers/gpu/drm/i915/intel_overlay.c | 4 +-
drivers/gpu/drm/i915/intel_panel.c | 8 +-
drivers/gpu/drm/i915/intel_sprite.c | 2 +-
drivers/gpu/drm/i915/intel_tv.c | 5 +-
drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +-
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +-
include/drm/drmP.h | 5 -
include/drm/drm_crtc.h | 15 +--
include/drm/drm_modeset_lock.h | 103 +++++++++++++++++++
20 files changed, 434 insertions(+), 88 deletions(-)
create mode 100644 drivers/gpu/drm/drm_modeset_lock.c
create mode 100644 include/drm/drm_modeset_lock.h
diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
index 48e38ba..bf4c12d 100644
--- a/drivers/gpu/drm/Makefile
+++ b/drivers/gpu/drm/Makefile
@@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
drm_info.o drm_debugfs.o drm_encoder_slave.o \
drm_trace_points.o drm_global.o drm_prime.o \
drm_rect.o drm_vma_manager.o drm_flip_work.o \
- drm_plane_helper.o
+ drm_plane_helper.o drm_modeset_lock.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index bbb329f..186bed4 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -37,6 +37,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_modeset_lock.h>
#include "drm_crtc_internal.h"
@@ -50,14 +51,42 @@
*/
void drm_modeset_lock_all(struct drm_device *dev)
{
- struct drm_crtc *crtc;
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_modeset_acquire_ctx *ctx;
+ int ret;
- mutex_lock(&dev->mode_config.mutex);
+ ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+ if (WARN_ON(!ctx))
+ return;
- mutex_lock(&dev->mode_config.connection_mutex);
+ mutex_lock(&config->mutex);
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
+ drm_modeset_acquire_init(ctx, 0);
+
+retry:
+ ret = drm_modeset_lock(&config->connection_mutex, ctx);
+ if (ret)
+ goto fail;
+ ret = drm_modeset_lock_all_crtcs(dev, ctx);
+ if (ret)
+ goto fail;
+
+ WARN_ON(config->acquire_ctx);
+
+ /* now we hold the locks, so now that it is safe, stash the
+ * ctx for drm_modeset_unlock_all():
+ */
+ config->acquire_ctx = ctx;
+
+ drm_warn_on_modeset_not_all_locked(dev);
+
+ return;
+
+fail:
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(ctx);
+ goto retry;
+ }
}
EXPORT_SYMBOL(drm_modeset_lock_all);
@@ -69,12 +98,17 @@ EXPORT_SYMBOL(drm_modeset_lock_all);
*/
void drm_modeset_unlock_all(struct drm_device *dev)
{
- struct drm_crtc *crtc;
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
- list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- mutex_unlock(&crtc->mutex);
+ if (WARN_ON(!ctx))
+ return;
+
+ config->acquire_ctx = NULL;
+ drm_modeset_drop_locks(ctx);
+ drm_modeset_acquire_fini(ctx);
- mutex_unlock(&dev->mode_config.connection_mutex);
+ kfree(ctx);
mutex_unlock(&dev->mode_config.mutex);
}
@@ -95,9 +129,9 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
return;
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
- WARN_ON(!mutex_is_locked(&crtc->mutex));
+ WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
- WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
}
EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
@@ -690,6 +724,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
}
EXPORT_SYMBOL(drm_framebuffer_remove);
+DEFINE_WW_CLASS(crtc_ww_class);
+
/**
* drm_crtc_init_with_planes - Initialise a new CRTC object with
* specified primary and cursor planes.
@@ -709,6 +745,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
void *cursor,
const struct drm_crtc_funcs *funcs)
{
+ struct drm_mode_config *config = &dev->mode_config;
int ret;
crtc->dev = dev;
@@ -716,8 +753,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
crtc->invert_dimensions = false;
drm_modeset_lock_all(dev);
- mutex_init(&crtc->mutex);
- mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
+ drm_modeset_lock_init(&crtc->mutex);
+ /* dropped by _unlock_all(): */
+ drm_modeset_lock(&crtc->mutex, config->acquire_ctx);
ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
if (ret)
@@ -725,8 +763,8 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
crtc->base.properties = &crtc->properties;
- list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
- dev->mode_config.num_crtc++;
+ list_add_tail(&crtc->head, &config->crtc_list);
+ config->num_crtc++;
crtc->primary = primary;
if (primary)
@@ -754,6 +792,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
kfree(crtc->gamma_store);
crtc->gamma_store = NULL;
+ drm_modeset_lock_fini(&crtc->mutex);
+
drm_mode_object_put(dev, &crtc->base);
list_del(&crtc->head);
dev->mode_config.num_crtc--;
@@ -1817,7 +1857,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
mutex_lock(&dev->mode_config.mutex);
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
connector = drm_connector_find(dev, out_resp->connector_id);
if (!connector) {
@@ -1916,7 +1956,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
out_resp->count_encoders = encoders_count;
out:
- mutex_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
mutex_unlock(&dev->mode_config.mutex);
return ret;
@@ -2500,7 +2540,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
return -ENOENT;
}
- mutex_lock(&crtc->mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
if (req->flags & DRM_MODE_CURSOR_BO) {
if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
ret = -ENXIO;
@@ -2524,7 +2564,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
}
}
out:
- mutex_unlock(&crtc->mutex);
+ drm_modeset_unlock(&crtc->mutex);
return ret;
@@ -4217,7 +4257,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
if (!crtc)
return -ENOENT;
- mutex_lock(&crtc->mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
if (crtc->primary->fb == NULL) {
/* The framebuffer is currently unbound, presumably
* due to a hotplug event, that userspace has not
@@ -4301,7 +4341,7 @@ out:
drm_framebuffer_unreference(fb);
if (old_fb)
drm_framebuffer_unreference(old_fb);
- mutex_unlock(&crtc->mutex);
+ drm_modeset_unlock(&crtc->mutex);
return ret;
}
@@ -4666,7 +4706,7 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
void drm_mode_config_init(struct drm_device *dev)
{
mutex_init(&dev->mode_config.mutex);
- mutex_init(&dev->mode_config.connection_mutex);
+ drm_modeset_lock_init(&dev->mode_config.connection_mutex);
mutex_init(&dev->mode_config.idr_mutex);
mutex_init(&dev->mode_config.fb_lock);
INIT_LIST_HEAD(&dev->mode_config.fb_list);
@@ -4766,5 +4806,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
}
idr_destroy(&dev->mode_config.crtc_idr);
+ drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
}
EXPORT_SYMBOL(drm_mode_config_cleanup);
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index 5b93caf..4eaded8 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -89,8 +89,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
struct drm_device *dev = encoder->dev;
WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
- WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
-
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder == encoder)
return true;
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index e95ed58..b891f4c 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -331,6 +331,10 @@ static bool drm_fb_helper_force_kernel_mode(void)
if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
continue;
+ /* NOTE: we use lockless flag below to avoid grabbing other
+ * modeset locks. So just trylock the underlying mutex
+ * directly:
+ */
if (!mutex_trylock(&dev->mode_config.mutex)) {
error = true;
continue;
diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
new file mode 100644
index 0000000..edd8508
--- /dev/null
+++ b/drivers/gpu/drm/drm_modeset_lock.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <drm/drmP.h>
+#include <drm/drm_crtc.h>
+#include <drm/drm_modeset_lock.h>
+
+
+void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
+ uint32_t flags)
+{
+ ww_acquire_init(&ctx->ww_ctx, &crtc_ww_class);
+ INIT_LIST_HEAD(&ctx->locked);
+}
+EXPORT_SYMBOL(drm_modeset_acquire_init);
+
+void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx)
+{
+ ww_acquire_fini(&ctx->ww_ctx);
+}
+EXPORT_SYMBOL(drm_modeset_acquire_fini);
+
+void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx)
+{
+ WARN_ON(ctx->contended);
+ while (!list_empty(&ctx->locked)) {
+ struct drm_modeset_lock *lock;
+
+ lock = list_first_entry(&ctx->locked,
+ struct drm_modeset_lock, head);
+
+ drm_modeset_unlock(lock);
+ }
+}
+EXPORT_SYMBOL(drm_modeset_drop_locks);
+
+static inline int modeset_lock(struct drm_modeset_lock *lock,
+ struct drm_modeset_acquire_ctx *ctx,
+ bool interruptible, bool slow)
+{
+ int ret;
+
+ WARN_ON(ctx->contended);
+
+ if (interruptible && slow) {
+ ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx);
+ } else if (interruptible) {
+ ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx);
+ } else if (slow) {
+ ww_mutex_lock_slow(&lock->mutex, &ctx->ww_ctx);
+ ret = 0;
+ } else {
+ ret = ww_mutex_lock(&lock->mutex, &ctx->ww_ctx);
+ }
+ if (!ret) {
+ WARN_ON(!list_empty(&lock->head));
+ list_add(&lock->head, &ctx->locked);
+ } else if (ret == -EALREADY) {
+ /* we already hold the lock.. this is fine. For atomic
+ * we will need to be able to drm_modeset_lock() things
+ * without having to keep track of what is already locked
+ * or not.
+ */
+ ret = 0;
+ } else if (ret == -EDEADLK) {
+ ctx->contended = lock;
+ }
+
+ return ret;
+}
+
+static int modeset_backoff(struct drm_modeset_acquire_ctx *ctx,
+ bool interruptible)
+{
+ struct drm_modeset_lock *contended = ctx->contended;
+
+ ctx->contended = NULL;
+
+ if (WARN_ON(!contended))
+ return 0;
+
+ drm_modeset_drop_locks(ctx);
+
+ return modeset_lock(contended, ctx, interruptible, true);
+}
+
+void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx)
+{
+ modeset_backoff(ctx, false);
+}
+EXPORT_SYMBOL(drm_modeset_backoff);
+
+int drm_modeset_backoff_interruptable(struct drm_modeset_acquire_ctx *ctx)
+{
+ return modeset_backoff(ctx, true);
+}
+EXPORT_SYMBOL(drm_modeset_backoff_interruptable);
+
+/**
+ * drm_modeset_lock - take modeset lock
+ * @lock: lock to take
+ * @ctx: acquire ctx
+ *
+ * If ctx is not NULL, then then it's acquire context is used
+ * and the lock does not need to be explicitly unlocked, it
+ * will be automatically unlocked when the atomic update is
+ * complete
+ */
+int drm_modeset_lock(struct drm_modeset_lock *lock,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ if (ctx)
+ return modeset_lock(lock, ctx, false, false);
+
+ ww_mutex_lock(&lock->mutex, NULL);
+ return 0;
+}
+EXPORT_SYMBOL(drm_modeset_lock);
+
+int drm_modeset_lock_interruptible(struct drm_modeset_lock *lock,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ if (ctx)
+ return modeset_lock(lock, ctx, true, false);
+
+ return ww_mutex_lock_interruptible(&lock->mutex, NULL);
+}
+EXPORT_SYMBOL(drm_modeset_lock_interruptible);
+
+/**
+ * drm_modeset_unlock - drop modeset lock
+ * @lock: lock to release
+ */
+void drm_modeset_unlock(struct drm_modeset_lock *lock)
+{
+ list_del_init(&lock->head);
+ ww_mutex_unlock(&lock->mutex);
+}
+EXPORT_SYMBOL(drm_modeset_unlock);
+
+/**
+ * drm_modeset_lock_all_crtcs - helper to drm_modeset_lock() all CRTCs
+ */
+int drm_modeset_lock_all_crtcs(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx)
+{
+ struct drm_mode_config *config = &dev->mode_config;
+ struct drm_crtc *crtc;
+ int ret = 0;
+
+ list_for_each_entry(crtc, &config->crtc_list, head) {
+ ret = drm_modeset_lock(&crtc->mutex, ctx);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(drm_modeset_lock_all_crtcs);
diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
index 458d9bf..6301ec6 100644
--- a/drivers/gpu/drm/drm_plane_helper.c
+++ b/drivers/gpu/drm/drm_plane_helper.c
@@ -59,7 +59,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
* need to grab the connection_mutex here to be able to make these
* checks.
*/
- WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
list_for_each_entry(connector, &dev->mode_config.connector_list, head)
if (connector->encoder && connector->encoder->crtc == crtc) {
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 22d8347..33328fc 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -630,6 +630,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
enum intel_display_power_domain power_domain;
enum drm_connector_status status;
struct intel_load_detect_pipe tmp;
+ struct drm_modeset_acquire_ctx ctx;
intel_runtime_pm_get(dev_priv);
@@ -673,12 +674,12 @@ intel_crt_detect(struct drm_connector *connector, bool force)
}
/* for pre-945g platforms use load detect */
- if (intel_get_load_detect_pipe(connector, NULL, &tmp)) {
+ if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
if (intel_crt_detect_ddc(connector))
status = connector_status_connected;
else
status = intel_crt_load_detect(crt);
- intel_release_load_detect_pipe(connector, &tmp);
+ intel_release_load_detect_pipe(connector, &tmp, &ctx);
} else
status = connector_status_unknown;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 8cf4bde..f5a49f8 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2363,7 +2363,7 @@ void intel_display_handle_reset(struct drm_device *dev)
list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
- mutex_lock(&crtc->mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
/*
* FIXME: Once we have proper support for primary planes (and
* disabling them without disabling the entire crtc) allow again
@@ -2374,7 +2374,7 @@ void intel_display_handle_reset(struct drm_device *dev)
crtc->primary->fb,
crtc->x,
crtc->y);
- mutex_unlock(&crtc->mutex);
+ drm_modeset_unlock(&crtc->mutex);
}
}
@@ -7972,7 +7972,8 @@ mode_fits_in_fbdev(struct drm_device *dev,
bool intel_get_load_detect_pipe(struct drm_connector *connector,
struct drm_display_mode *mode,
- struct intel_load_detect_pipe *old)
+ struct intel_load_detect_pipe *old,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct intel_crtc *intel_crtc;
struct intel_encoder *intel_encoder =
@@ -7982,13 +7983,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
struct drm_crtc *crtc = NULL;
struct drm_device *dev = encoder->dev;
struct drm_framebuffer *fb;
- int i = -1;
+ struct drm_mode_config *config = &dev->mode_config;
+ int ret, i = -1;
DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
connector->base.id, drm_get_connector_name(connector),
encoder->base.id, drm_get_encoder_name(encoder));
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_acquire_init(ctx, 0);
+
+retry:
+ ret = drm_modeset_lock(&config->connection_mutex, ctx);
+ if (ret)
+ goto fail_unlock;
/*
* Algorithm gets a little messy:
@@ -8004,7 +8011,9 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
if (encoder->crtc) {
crtc = encoder->crtc;
- mutex_lock(&crtc->mutex);
+ ret = drm_modeset_lock(&crtc->mutex, ctx);
+ if (ret)
+ goto fail_unlock;
old->dpms_mode = connector->dpms;
old->load_detect_temp = false;
@@ -8017,7 +8026,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
}
/* Find an unused one (if possible) */
- list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) {
+ list_for_each_entry(possible_crtc, &config->crtc_list, head) {
i++;
if (!(encoder->possible_crtcs & (1 << i)))
continue;
@@ -8032,10 +8041,12 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
*/
if (!crtc) {
DRM_DEBUG_KMS("no pipe available for load-detect\n");
- goto fail_unlock_connector;
+ goto fail_unlock;
}
- mutex_lock(&crtc->mutex);
+ ret = drm_modeset_lock(&crtc->mutex, ctx);
+ if (ret)
+ goto fail_unlock;
intel_encoder->new_crtc = to_intel_crtc(crtc);
to_intel_connector(connector)->new_encoder = intel_encoder;
@@ -8085,15 +8096,21 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
intel_crtc->new_config = &intel_crtc->config;
else
intel_crtc->new_config = NULL;
- mutex_unlock(&crtc->mutex);
-fail_unlock_connector:
- mutex_unlock(&dev->mode_config.connection_mutex);
+fail_unlock:
+ if (ret == -EDEADLK) {
+ drm_modeset_backoff(ctx);
+ goto retry;
+ }
+
+ drm_modeset_drop_locks(ctx);
+ drm_modeset_acquire_fini(ctx);
return false;
}
void intel_release_load_detect_pipe(struct drm_connector *connector,
- struct intel_load_detect_pipe *old)
+ struct intel_load_detect_pipe *old,
+ struct drm_modeset_acquire_ctx *ctx)
{
struct intel_encoder *intel_encoder =
intel_attached_encoder(connector);
@@ -8117,8 +8134,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
drm_framebuffer_unreference(old->release_fb);
}
- mutex_unlock(&crtc->mutex);
- mutex_unlock(&connector->dev->mode_config.connection_mutex);
+ goto unlock;
return;
}
@@ -8126,8 +8142,9 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
if (old->dpms_mode != DRM_MODE_DPMS_ON)
connector->funcs->dpms(connector, old->dpms_mode);
- mutex_unlock(&crtc->mutex);
- mutex_unlock(&connector->dev->mode_config.connection_mutex);
+unlock:
+ drm_modeset_drop_locks(ctx);
+ drm_modeset_acquire_fini(ctx);
}
static int i9xx_pll_refclk(struct drm_device *dev,
@@ -10586,7 +10603,7 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
struct drm_encoder *encoder = connector->base.encoder;
struct drm_device *dev = connector->base.dev;
- WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
if (!encoder)
return INVALID_PIPE;
@@ -11386,6 +11403,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
struct intel_connector *connector;
struct drm_connector *crt = NULL;
struct intel_load_detect_pipe load_detect_temp;
+ struct drm_modeset_acquire_ctx ctx;
/* We can't just switch on the pipe A, we need to set things up with a
* proper mode and output configuration. As a gross hack, enable pipe A
@@ -11402,8 +11420,8 @@ static void intel_enable_pipe_a(struct drm_device *dev)
if (!crt)
return;
- if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp))
- intel_release_load_detect_pipe(crt, &load_detect_temp);
+ if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx))
+ intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx);
}
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 89fd1dd..9926dc1 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1131,7 +1131,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
u32 pp;
u32 pp_stat_reg, pp_ctrl_reg;
- WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+ WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
struct intel_digital_port *intel_dig_port =
@@ -1168,9 +1168,9 @@ static void edp_panel_vdd_work(struct work_struct *__work)
struct intel_dp, panel_vdd_work);
struct drm_device *dev = intel_dp_to_dev(intel_dp);
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
edp_panel_vdd_off_sync(intel_dp);
- mutex_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
@@ -3384,9 +3384,9 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
drm_encoder_cleanup(encoder);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
edp_panel_vdd_off_sync(intel_dp);
- mutex_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
kfree(intel_dig_port);
}
@@ -3965,9 +3965,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
if (is_edp(intel_dp)) {
cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
edp_panel_vdd_off_sync(intel_dp);
- mutex_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
}
drm_sysfs_connector_remove(connector);
drm_connector_cleanup(connector);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index d8b540b..824f8ae 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -721,9 +721,11 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
struct intel_digital_port *dport);
bool intel_get_load_detect_pipe(struct drm_connector *connector,
struct drm_display_mode *mode,
- struct intel_load_detect_pipe *old);
+ struct intel_load_detect_pipe *old,
+ struct drm_modeset_acquire_ctx *ctx);
void intel_release_load_detect_pipe(struct drm_connector *connector,
- struct intel_load_detect_pipe *old);
+ struct intel_load_detect_pipe *old,
+ struct drm_modeset_acquire_ctx *ctx);
int intel_pin_and_fence_fb_obj(struct drm_device *dev,
struct drm_i915_gem_object *obj,
struct intel_ring_buffer *pipelined);
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index b812e9d..2e2c71f 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -410,7 +410,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
if (bclp > 255)
return ASLC_BACKLIGHT_FAILED;
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
/*
* Update backlight on all connectors that support backlight (usually
@@ -421,7 +421,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
intel_panel_set_backlight(intel_connector, bclp, 255);
iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
- mutex_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
return 0;
diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
index 88249c4..961164d 100644
--- a/drivers/gpu/drm/i915/intel_overlay.c
+++ b/drivers/gpu/drm/i915/intel_overlay.c
@@ -688,7 +688,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
u32 swidth, swidthsw, sheight, ostride;
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
- BUG_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+ BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
BUG_ON(!overlay);
ret = intel_overlay_release_old_vid(overlay);
@@ -793,7 +793,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
int ret;
BUG_ON(!mutex_is_locked(&dev->struct_mutex));
- BUG_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
+ BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
ret = intel_overlay_recover_from_interrupt(overlay);
if (ret != 0)
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index f3df527..f45d874 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -823,12 +823,12 @@ static int intel_backlight_device_update_status(struct backlight_device *bd)
struct intel_connector *connector = bl_get_data(bd);
struct drm_device *dev = connector->base.dev;
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
bd->props.brightness, bd->props.max_brightness);
intel_panel_set_backlight(connector, bd->props.brightness,
bd->props.max_brightness);
- mutex_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
return 0;
}
@@ -840,9 +840,9 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
int ret;
intel_runtime_pm_get(dev_priv);
- mutex_lock(&dev->mode_config.connection_mutex);
+ drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
ret = intel_panel_get_backlight(connector);
- mutex_unlock(&dev->mode_config.connection_mutex);
+ drm_modeset_unlock(&dev->mode_config.connection_mutex);
intel_runtime_pm_put(dev_priv);
return ret;
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 213cd58..c235546 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -55,7 +55,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
int scanline, min, max, vblank_start;
DEFINE_WAIT(wait);
- WARN_ON(!mutex_is_locked(&crtc->base.mutex));
+ WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
vblank_start = mode->crtc_vblank_start;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index e0193e8..97d9fc9 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1321,10 +1321,11 @@ intel_tv_detect(struct drm_connector *connector, bool force)
if (force) {
struct intel_load_detect_pipe tmp;
+ struct drm_modeset_acquire_ctx ctx;
- if (intel_get_load_detect_pipe(connector, &mode, &tmp)) {
+ if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
type = intel_tv_detect_type(intel_tv, connector);
- intel_release_load_detect_pipe(connector, &tmp);
+ intel_release_load_detect_pipe(connector, &tmp, &ctx);
} else
return connector_status_unknown;
} else
diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
index e3c47a8..2d28dc3 100644
--- a/drivers/gpu/drm/omapdrm/omap_crtc.c
+++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
@@ -319,13 +319,13 @@ static void page_flip_worker(struct work_struct *work)
struct drm_display_mode *mode = &crtc->mode;
struct drm_gem_object *bo;
- mutex_lock(&crtc->mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
0, 0, mode->hdisplay, mode->vdisplay,
crtc->x << 16, crtc->y << 16,
mode->hdisplay << 16, mode->vdisplay << 16,
vblank_cb, crtc);
- mutex_unlock(&crtc->mutex);
+ drm_modeset_unlock(&crtc->mutex);
bo = omap_framebuffer_bo(crtc->primary->fb, 0);
drm_gem_object_unreference_unlocked(bo);
@@ -465,7 +465,7 @@ static void apply_worker(struct work_struct *work)
* the callbacks and list modification all serialized
* with respect to modesetting ioctls from userspace.
*/
- mutex_lock(&crtc->mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
dispc_runtime_get();
/*
@@ -510,7 +510,7 @@ static void apply_worker(struct work_struct *work)
out:
dispc_runtime_put();
- mutex_unlock(&crtc->mutex);
+ drm_modeset_unlock(&crtc->mutex);
}
int omap_crtc_apply(struct drm_crtc *crtc,
@@ -518,7 +518,7 @@ int omap_crtc_apply(struct drm_crtc *crtc,
{
struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
- WARN_ON(!mutex_is_locked(&crtc->mutex));
+ WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
/* no need to queue it again if it is already queued: */
if (apply->queued)
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
index e7199b4..8f3edc4 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
@@ -187,7 +187,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
* can do this since the caller in the drm core doesn't check anything
* which is protected by any looks.
*/
- mutex_unlock(&crtc->mutex);
+ drm_modeset_unlock(&crtc->mutex);
drm_modeset_lock_all(dev_priv->dev);
/* A lot of the code assumes this */
@@ -252,7 +252,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
ret = 0;
out:
drm_modeset_unlock_all(dev_priv->dev);
- mutex_lock(&crtc->mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
return ret;
}
@@ -273,7 +273,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
* can do this since the caller in the drm core doesn't check anything
* which is protected by any looks.
*/
- mutex_unlock(&crtc->mutex);
+ drm_modeset_unlock(&crtc->mutex);
drm_modeset_lock_all(dev_priv->dev);
vmw_cursor_update_position(dev_priv, shown,
@@ -281,7 +281,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
du->cursor_y + du->hotspot_y);
drm_modeset_unlock_all(dev_priv->dev);
- mutex_lock(&crtc->mutex);
+ drm_modeset_lock(&crtc->mutex, NULL);
return 0;
}
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index 12f10bc..a9b8a5d 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -1184,11 +1184,6 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)
return ret;
}
-static inline bool drm_modeset_is_locked(struct drm_device *dev)
-{
- return mutex_is_locked(&dev->mode_config.mutex);
-}
-
static inline bool drm_is_render_client(const struct drm_file *file_priv)
{
return file_priv->minor->type == DRM_MINOR_RENDER;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index 56dffc6..3a3f7da 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -33,6 +33,7 @@
#include <linux/hdmi.h>
#include <drm/drm_mode.h>
#include <drm/drm_fourcc.h>
+#include <drm/drm_modeset_lock.h>
struct drm_device;
struct drm_mode_set;
@@ -205,6 +206,10 @@ struct drm_property {
struct list_head enum_blob_list;
};
+void drm_modeset_lock_all(struct drm_device *dev);
+void drm_modeset_unlock_all(struct drm_device *dev);
+void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
+
struct drm_crtc;
struct drm_connector;
struct drm_encoder;
@@ -280,6 +285,7 @@ struct drm_crtc_funcs {
* drm_crtc - central CRTC control structure
* @dev: parent DRM device
* @head: list management
+ * @mutex: per-CRTC locking
* @base: base KMS object for ID tracking etc.
* @primary: primary plane for this CRTC
* @cursor: cursor plane for this CRTC
@@ -314,7 +320,7 @@ struct drm_crtc {
* state, ...) and a write lock for everything which can be update
* without a full modeset (fb, cursor data, ...)
*/
- struct mutex mutex;
+ struct drm_modeset_lock mutex;
struct drm_mode_object base;
@@ -738,7 +744,8 @@ struct drm_mode_group {
*/
struct drm_mode_config {
struct mutex mutex; /* protects configuration (mode lists etc.) */
- struct mutex connection_mutex; /* protects connector->encoder and encoder->crtc links */
+ struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */
+ struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
struct mutex idr_mutex; /* for IDR management */
struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
/* this is limited to one for now */
@@ -839,10 +846,6 @@ struct drm_prop_enum_list {
char *name;
};
-extern void drm_modeset_lock_all(struct drm_device *dev);
-extern void drm_modeset_unlock_all(struct drm_device *dev);
-extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
-
extern int drm_crtc_init_with_planes(struct drm_device *dev,
struct drm_crtc *crtc,
struct drm_plane *primary,
diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
new file mode 100644
index 0000000..cfb1dc1
--- /dev/null
+++ b/include/drm/drm_modeset_lock.h
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2014 Red Hat
+ * Author: Rob Clark <robdclark@gmail.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#ifndef DRM_MODESET_LOCK_H_
+#define DRM_MODESET_LOCK_H_
+
+#include <linux/ww_mutex.h>
+
+struct drm_modeset_lock;
+
+struct drm_modeset_acquire_ctx {
+
+ struct ww_acquire_ctx ww_ctx;
+
+ /* contended lock: if a lock is contended you should only call
+ * drm_modeset_backoff() which drops locks and slow-locks the
+ * contended lock.
+ */
+ struct drm_modeset_lock *contended;
+
+ /* list of 'struct drm_modeset_lock': */
+ struct list_head locked;
+};
+
+/**
+ * drm_modeset_lock - used for locking modeset resources.
+ * @mutex: resource locking
+ * @atomic_pending: is this resource part of a still-pending
+ * atomic update
+ * @head: used to hold it's place on state->locked list when
+ * part of an atomic update
+ *
+ * Used for locking CRTCs and other modeset resources.
+ */
+struct drm_modeset_lock {
+ /**
+ * modeset lock
+ */
+ struct ww_mutex mutex;
+
+ /**
+ * Resources that are locked as part of an atomic update are added
+ * to a list (so we know what to unlock at the end).
+ */
+ struct list_head head;
+};
+
+extern struct ww_class crtc_ww_class;
+
+void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
+ uint32_t flags);
+void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx);
+void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx);
+void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx);
+int drm_modeset_backoff_interruptable(struct drm_modeset_acquire_ctx *ctx);
+
+static inline void drm_modeset_lock_init(struct drm_modeset_lock *lock)
+{
+ ww_mutex_init(&lock->mutex, &crtc_ww_class);
+ INIT_LIST_HEAD(&lock->head);
+}
+
+static inline void drm_modeset_lock_fini(struct drm_modeset_lock *lock)
+{
+ WARN_ON(!list_empty(&lock->head));
+}
+
+static inline bool drm_modeset_is_locked(struct drm_modeset_lock *lock)
+{
+ return ww_mutex_is_locked(&lock->mutex);
+}
+
+int drm_modeset_lock(struct drm_modeset_lock *lock,
+ struct drm_modeset_acquire_ctx *ctx);
+int drm_modeset_lock_interruptible(struct drm_modeset_lock *lock,
+ struct drm_modeset_acquire_ctx *ctx);
+void drm_modeset_unlock(struct drm_modeset_lock *lock);
+
+struct drm_device;
+int drm_modeset_lock_all_crtcs(struct drm_device *dev,
+ struct drm_modeset_acquire_ctx *ctx);
+
+#endif /* DRM_MODESET_LOCK_H_ */
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
` (6 preceding siblings ...)
2014-05-30 17:12 ` [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3) Rob Clark
@ 2014-05-30 17:12 ` Rob Clark
2014-06-03 13:33 ` Daniel Vetter
2014-06-02 8:11 ` [PATCH 0/8] prepare for preparing for atomic (v2) Daniel Vetter
8 siblings, 1 reply; 21+ messages in thread
From: Rob Clark @ 2014-05-30 17:12 UTC (permalink / raw)
To: dri-devel
All drm_fb_helper_restore_fbdev_mode() call sites, save one, do the same
locking. Simplify this into drm_fb_helper_restore_fbdev_mode_unlocked().
Signed-off-by: Rob Clark <robdclark@gmail.com>
---
drivers/gpu/drm/armada/armada_fbdev.c | 4 +--
drivers/gpu/drm/drm_fb_cma_helper.c | 9 ++----
drivers/gpu/drm/drm_fb_helper.c | 51 +++++++++++++++++++++++--------
drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +--
drivers/gpu/drm/gma500/psb_drv.c | 4 +--
drivers/gpu/drm/i915/intel_fbdev.c | 6 +---
drivers/gpu/drm/msm/msm_drv.c | 7 ++---
drivers/gpu/drm/omapdrm/omap_drv.c | 4 +--
drivers/gpu/drm/tegra/fb.c | 7 ++---
include/drm/drm_fb_helper.h | 1 +
10 files changed, 50 insertions(+), 47 deletions(-)
diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
index 948cb14..fd166f5 100644
--- a/drivers/gpu/drm/armada/armada_fbdev.c
+++ b/drivers/gpu/drm/armada/armada_fbdev.c
@@ -181,10 +181,8 @@ void armada_fbdev_lastclose(struct drm_device *dev)
{
struct armada_private *priv = dev->dev_private;
- drm_modeset_lock_all(dev);
if (priv->fbdev)
- drm_fb_helper_restore_fbdev_mode(priv->fbdev);
- drm_modeset_unlock_all(dev);
+ drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
}
void armada_fbdev_fini(struct drm_device *dev)
diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
index 61b5a47..f27c883 100644
--- a/drivers/gpu/drm/drm_fb_cma_helper.c
+++ b/drivers/gpu/drm/drm_fb_cma_helper.c
@@ -429,13 +429,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);
*/
void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma)
{
- if (fbdev_cma) {
- struct drm_device *dev = fbdev_cma->fb_helper.dev;
-
- drm_modeset_lock_all(dev);
- drm_fb_helper_restore_fbdev_mode(&fbdev_cma->fb_helper);
- drm_modeset_unlock_all(dev);
- }
+ if (fbdev_cma)
+ drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev_cma->fb_helper);
}
EXPORT_SYMBOL_GPL(drm_fbdev_cma_restore_mode);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index b891f4c..dc861a1 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -273,15 +273,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
}
EXPORT_SYMBOL(drm_fb_helper_debug_leave);
-/**
- * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
- * @fb_helper: fbcon to restore
- *
- * This should be called from driver's drm ->lastclose callback
- * when implementing an fbcon on top of kms using this helper. This ensures that
- * the user isn't greeted with a black screen when e.g. X dies.
- */
-bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
{
struct drm_device *dev = fb_helper->dev;
struct drm_plane *plane;
@@ -311,8 +303,44 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
}
return error;
}
+/**
+ * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
+ * @fb_helper: fbcon to restore
+ * @lockless: true in drm_fb_helper_force_kernel_mode() path, to avoid
+ * blocking in panic case, everywhere else should use false
+ *
+ * This should be called from driver's drm ->lastclose callback
+ * when implementing an fbcon on top of kms using this helper. This ensures that
+ * the user isn't greeted with a black screen when e.g. X dies.
+ *
+ * Use this variant if you need to bypass locking (panic), or already
+ * hold all modeset locks. Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked()
+ */
+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+{
+ return restore_fbdev_mode(fb_helper);
+}
EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
+/**
+ * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
+ * @fb_helper: fbcon to restore
+ *
+ * This should be called from driver's drm ->lastclose callback
+ * when implementing an fbcon on top of kms using this helper. This ensures that
+ * the user isn't greeted with a black screen when e.g. X dies.
+ */
+bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
+{
+ struct drm_device *dev = fb_helper->dev;
+ bool ret;
+ drm_modeset_lock_all(dev);
+ ret = restore_fbdev_mode(fb_helper);
+ drm_modeset_unlock_all(dev);
+ return ret;
+}
+EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
+
/*
* restore fbcon display for all kms driver's using this helper, used for sysrq
* and panic handling.
@@ -824,7 +852,6 @@ EXPORT_SYMBOL(drm_fb_helper_check_var);
int drm_fb_helper_set_par(struct fb_info *info)
{
struct drm_fb_helper *fb_helper = info->par;
- struct drm_device *dev = fb_helper->dev;
struct fb_var_screeninfo *var = &info->var;
if (var->pixclock != 0) {
@@ -832,9 +859,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
return -EINVAL;
}
- drm_modeset_lock_all(dev);
- drm_fb_helper_restore_fbdev_mode(fb_helper);
- drm_modeset_unlock_all(dev);
+ drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
if (fb_helper->delayed_hotplug) {
fb_helper->delayed_hotplug = false;
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
index addbf75..93e7ba6 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
@@ -375,7 +375,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
if (!private || !private->fb_helper)
return;
- drm_modeset_lock_all(dev);
- drm_fb_helper_restore_fbdev_mode(private->fb_helper);
- drm_modeset_unlock_all(dev);
+ drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper);
}
diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
index 0a3101a..59ea45e 100644
--- a/drivers/gpu/drm/gma500/psb_drv.c
+++ b/drivers/gpu/drm/gma500/psb_drv.c
@@ -112,11 +112,9 @@ static void psb_driver_lastclose(struct drm_device *dev)
struct drm_psb_private *dev_priv = dev->dev_private;
struct psb_fbdev *fbdev = dev_priv->fbdev;
- drm_modeset_lock_all(dev);
- ret = drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->psb_fb_helper);
if (ret)
DRM_DEBUG("failed to restore crtc mode\n");
- drm_modeset_unlock_all(dev);
return;
}
diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
index fce4a0d..f8258ab 100644
--- a/drivers/gpu/drm/i915/intel_fbdev.c
+++ b/drivers/gpu/drm/i915/intel_fbdev.c
@@ -683,11 +683,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
if (!dev_priv->fbdev)
return;
- drm_modeset_lock_all(dev);
-
- ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(&dev_priv->fbdev->helper);
if (ret)
DRM_DEBUG("failed to restore crtc mode\n");
-
- drm_modeset_unlock_all(dev);
}
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index 50ec1be..afedd8b 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -382,11 +382,8 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
static void msm_lastclose(struct drm_device *dev)
{
struct msm_drm_private *priv = dev->dev_private;
- if (priv->fbdev) {
- drm_modeset_lock_all(dev);
- drm_fb_helper_restore_fbdev_mode(priv->fbdev);
- drm_modeset_unlock_all(dev);
- }
+ if (priv->fbdev)
+ drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
}
static irqreturn_t msm_irq(int irq, void *arg)
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index c8270e4..002b972 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -588,9 +588,7 @@ static void dev_lastclose(struct drm_device *dev)
}
}
- drm_modeset_lock_all(dev);
- ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
- drm_modeset_unlock_all(dev);
+ ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
if (ret)
DBG("failed to restore crtc mode");
}
diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
index f7fca09..9798a70 100644
--- a/drivers/gpu/drm/tegra/fb.c
+++ b/drivers/gpu/drm/tegra/fb.c
@@ -346,11 +346,8 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
{
- if (fbdev) {
- drm_modeset_lock_all(fbdev->base.dev);
- drm_fb_helper_restore_fbdev_mode(&fbdev->base);
- drm_modeset_unlock_all(fbdev->base.dev);
- }
+ if (fbdev)
+ drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->base);
}
static void tegra_fb_output_poll_changed(struct drm_device *drm)
diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
index 6e622f7..0630b51 100644
--- a/include/drm/drm_fb_helper.h
+++ b/include/drm/drm_fb_helper.h
@@ -109,6 +109,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
struct fb_info *info);
bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper);
+bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
uint32_t fb_width, uint32_t fb_height);
void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
--
1.9.3
^ permalink raw reply related [flat|nested] 21+ messages in thread
* Re: [PATCH 0/8] prepare for preparing for atomic (v2)
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
` (7 preceding siblings ...)
2014-05-30 17:12 ` [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked() Rob Clark
@ 2014-06-02 8:11 ` Daniel Vetter
2014-06-02 15:33 ` Rob Clark
8 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2014-06-02 8:11 UTC (permalink / raw)
To: Rob Clark; +Cc: dri-devel
On Fri, May 30, 2014 at 01:12:02PM -0400, Rob Clark wrote:
> As suggested by Daniel, splitting out ww_mutex conversion and a few
> other bits out. Updated connection_mutex which fixes a few things,
> plus split up addition of extended property types from adding object
> property and pull in addition of _restore_fbdev_mode_unlocked() as
> it does not depend on atomic.
Just a quick note for merging: I prefer we don't pull this into 3.16, at
least not the locking changes. Due to the rushed merge window I didn't
have any chances yet to give the connection_mutex patch a real spin in
drm-intel-nightly, and none of the other drm driver maintainers have
chimed in about it yet either.
-Daniel
>
> Can be found at:
>
> http://cgit.freedesktop.org/~robclark/linux/log/?h=atomic-prep
> git://people.freedesktop.org/~robclark/linux atomic-prep
>
> Daniel Vetter (1):
> drm: Split connection_mutex out of mode_config.mutex (v3)
>
> Rob Clark (7):
> drm: helpers to find mode objects
> drm: add extended property types
> drm: add object property type
> drm: add signed-range property type
> drm: spiff out FB refcnting traces
> drm: convert crtc and connection_mutex to ww_mutex (v3)
> drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
>
> drivers/gpu/drm/Makefile | 2 +-
> drivers/gpu/drm/armada/armada_fbdev.c | 4 +-
> drivers/gpu/drm/drm_crtc.c | 295 +++++++++++++++++++----------
> drivers/gpu/drm/drm_crtc_helper.c | 1 +
> drivers/gpu/drm/drm_edid.c | 2 +
> drivers/gpu/drm/drm_fb_cma_helper.c | 9 +-
> drivers/gpu/drm/drm_fb_helper.c | 55 ++++--
> drivers/gpu/drm/drm_modeset_lock.c | 179 +++++++++++++++++
> drivers/gpu/drm/drm_plane_helper.c | 7 +
> drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +-
> drivers/gpu/drm/gma500/psb_drv.c | 4 +-
> drivers/gpu/drm/i915/i915_debugfs.c | 4 +-
> drivers/gpu/drm/i915/i915_drv.c | 4 +-
> drivers/gpu/drm/i915/intel_crt.c | 5 +-
> drivers/gpu/drm/i915/intel_display.c | 60 ++++--
> drivers/gpu/drm/i915/intel_dp.c | 15 +-
> drivers/gpu/drm/i915/intel_drv.h | 6 +-
> drivers/gpu/drm/i915/intel_fbdev.c | 6 +-
> drivers/gpu/drm/i915/intel_opregion.c | 4 +-
> drivers/gpu/drm/i915/intel_overlay.c | 4 +-
> drivers/gpu/drm/i915/intel_panel.c | 8 +-
> drivers/gpu/drm/i915/intel_sprite.c | 2 +-
> drivers/gpu/drm/i915/intel_tv.c | 5 +-
> drivers/gpu/drm/msm/msm_drv.c | 7 +-
> drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +-
> drivers/gpu/drm/omapdrm/omap_drv.c | 4 +-
> drivers/gpu/drm/omapdrm/omap_fb.c | 1 +
> drivers/gpu/drm/radeon/radeon_connectors.c | 1 +
> drivers/gpu/drm/tegra/fb.c | 7 +-
> drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +-
> include/drm/drmP.h | 5 -
> include/drm/drm_crtc.h | 81 +++++++-
> include/drm/drm_fb_helper.h | 1 +
> include/drm/drm_modeset_lock.h | 103 ++++++++++
> include/uapi/drm/drm_mode.h | 15 ++
> 35 files changed, 716 insertions(+), 212 deletions(-)
> create mode 100644 drivers/gpu/drm/drm_modeset_lock.c
> create mode 100644 include/drm/drm_modeset_lock.h
>
> --
> 1.9.3
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 0/8] prepare for preparing for atomic (v2)
2014-06-02 8:11 ` [PATCH 0/8] prepare for preparing for atomic (v2) Daniel Vetter
@ 2014-06-02 15:33 ` Rob Clark
0 siblings, 0 replies; 21+ messages in thread
From: Rob Clark @ 2014-06-02 15:33 UTC (permalink / raw)
To: Daniel Vetter; +Cc: Thomas Hellstrom, dri-devel@lists.freedesktop.org
On Mon, Jun 2, 2014 at 4:11 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Fri, May 30, 2014 at 01:12:02PM -0400, Rob Clark wrote:
>> As suggested by Daniel, splitting out ww_mutex conversion and a few
>> other bits out. Updated connection_mutex which fixes a few things,
>> plus split up addition of extended property types from adding object
>> property and pull in addition of _restore_fbdev_mode_unlocked() as
>> it does not depend on atomic.
>
> Just a quick note for merging: I prefer we don't pull this into 3.16, at
> least not the locking changes. Due to the rushed merge window I didn't
> have any chances yet to give the connection_mutex patch a real spin in
> drm-intel-nightly, and none of the other drm driver maintainers have
> chimed in about it yet either.
Well, it is at least worth a try.. I'd hate for another merge window
to go by without at least making some progress towards atomic.
Perhaps the other driver maintainers could have a look at the locking
change and lend their r-b and/or t-b?
I think the locking changes should be sound.. maybe we have to fix up
one or two things during the -rc's, but not like the concept to split
out connection_mutex, or usage of ww_mutex, is fundamentally broken.
The other drivers make somewhat less heavy use of mode_config.mutex
directly, and should be protected from the change by
drm_modeset_lock_all().. most of the other references outside of i915
are gma500/vmwgfx, plus few places that need to grab it to call
drm_framebuffer_unreference() (which perhaps deserves a
drm_framebuffer_unreference_unlocked() helper).
BR,
-R
> -Daniel
>
>>
>> Can be found at:
>>
>> http://cgit.freedesktop.org/~robclark/linux/log/?h=atomic-prep
>> git://people.freedesktop.org/~robclark/linux atomic-prep
>>
>> Daniel Vetter (1):
>> drm: Split connection_mutex out of mode_config.mutex (v3)
>>
>> Rob Clark (7):
>> drm: helpers to find mode objects
>> drm: add extended property types
>> drm: add object property type
>> drm: add signed-range property type
>> drm: spiff out FB refcnting traces
>> drm: convert crtc and connection_mutex to ww_mutex (v3)
>> drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
>>
>> drivers/gpu/drm/Makefile | 2 +-
>> drivers/gpu/drm/armada/armada_fbdev.c | 4 +-
>> drivers/gpu/drm/drm_crtc.c | 295 +++++++++++++++++++----------
>> drivers/gpu/drm/drm_crtc_helper.c | 1 +
>> drivers/gpu/drm/drm_edid.c | 2 +
>> drivers/gpu/drm/drm_fb_cma_helper.c | 9 +-
>> drivers/gpu/drm/drm_fb_helper.c | 55 ++++--
>> drivers/gpu/drm/drm_modeset_lock.c | 179 +++++++++++++++++
>> drivers/gpu/drm/drm_plane_helper.c | 7 +
>> drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +-
>> drivers/gpu/drm/gma500/psb_drv.c | 4 +-
>> drivers/gpu/drm/i915/i915_debugfs.c | 4 +-
>> drivers/gpu/drm/i915/i915_drv.c | 4 +-
>> drivers/gpu/drm/i915/intel_crt.c | 5 +-
>> drivers/gpu/drm/i915/intel_display.c | 60 ++++--
>> drivers/gpu/drm/i915/intel_dp.c | 15 +-
>> drivers/gpu/drm/i915/intel_drv.h | 6 +-
>> drivers/gpu/drm/i915/intel_fbdev.c | 6 +-
>> drivers/gpu/drm/i915/intel_opregion.c | 4 +-
>> drivers/gpu/drm/i915/intel_overlay.c | 4 +-
>> drivers/gpu/drm/i915/intel_panel.c | 8 +-
>> drivers/gpu/drm/i915/intel_sprite.c | 2 +-
>> drivers/gpu/drm/i915/intel_tv.c | 5 +-
>> drivers/gpu/drm/msm/msm_drv.c | 7 +-
>> drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +-
>> drivers/gpu/drm/omapdrm/omap_drv.c | 4 +-
>> drivers/gpu/drm/omapdrm/omap_fb.c | 1 +
>> drivers/gpu/drm/radeon/radeon_connectors.c | 1 +
>> drivers/gpu/drm/tegra/fb.c | 7 +-
>> drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +-
>> include/drm/drmP.h | 5 -
>> include/drm/drm_crtc.h | 81 +++++++-
>> include/drm/drm_fb_helper.h | 1 +
>> include/drm/drm_modeset_lock.h | 103 ++++++++++
>> include/uapi/drm/drm_mode.h | 15 ++
>> 35 files changed, 716 insertions(+), 212 deletions(-)
>> create mode 100644 drivers/gpu/drm/drm_modeset_lock.c
>> create mode 100644 include/drm/drm_modeset_lock.h
>>
>> --
>> 1.9.3
>>
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 1/8] drm: helpers to find mode objects
2014-05-30 17:12 ` [PATCH 1/8] drm: helpers to find mode objects Rob Clark
@ 2014-06-03 13:22 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2014-06-03 13:22 UTC (permalink / raw)
To: Rob Clark; +Cc: dri-devel
On Fri, May 30, 2014 at 01:12:03PM -0400, Rob Clark wrote:
> Add a few more useful helpers to find mode objects.
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
Still a pile of these in drivers and still a perfect use-case for cocci.
Patch itself looks good.
-Daniel
> ---
> drivers/gpu/drm/drm_crtc.c | 90 +++++++++++++++-------------------------------
> include/drm/drm_crtc.h | 33 +++++++++++++++++
> 2 files changed, 61 insertions(+), 62 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 37a3e07..02872af 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -1711,7 +1711,6 @@ int drm_mode_getcrtc(struct drm_device *dev,
> {
> struct drm_mode_crtc *crtc_resp = data;
> struct drm_crtc *crtc;
> - struct drm_mode_object *obj;
> int ret = 0;
>
> if (!drm_core_check_feature(dev, DRIVER_MODESET))
> @@ -1719,13 +1718,11 @@ int drm_mode_getcrtc(struct drm_device *dev,
>
> drm_modeset_lock_all(dev);
>
> - obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
> - DRM_MODE_OBJECT_CRTC);
> - if (!obj) {
> + crtc = drm_crtc_find(dev, crtc_resp->crtc_id);
> + if (!crtc) {
> ret = -ENOENT;
> goto out;
> }
> - crtc = obj_to_crtc(obj);
>
> crtc_resp->x = crtc->x;
> crtc_resp->y = crtc->y;
> @@ -1779,7 +1776,6 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
> struct drm_file *file_priv)
> {
> struct drm_mode_get_connector *out_resp = data;
> - struct drm_mode_object *obj;
> struct drm_connector *connector;
> struct drm_display_mode *mode;
> int mode_count = 0;
> @@ -1803,13 +1799,11 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
>
> mutex_lock(&dev->mode_config.mutex);
>
> - obj = drm_mode_object_find(dev, out_resp->connector_id,
> - DRM_MODE_OBJECT_CONNECTOR);
> - if (!obj) {
> + connector = drm_connector_find(dev, out_resp->connector_id);
> + if (!connector) {
> ret = -ENOENT;
> goto out;
> }
> - connector = obj_to_connector(obj);
>
> props_count = connector->properties.count;
>
> @@ -1924,7 +1918,6 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
> struct drm_file *file_priv)
> {
> struct drm_mode_get_encoder *enc_resp = data;
> - struct drm_mode_object *obj;
> struct drm_encoder *encoder;
> int ret = 0;
>
> @@ -1932,13 +1925,11 @@ int drm_mode_getencoder(struct drm_device *dev, void *data,
> return -EINVAL;
>
> drm_modeset_lock_all(dev);
> - obj = drm_mode_object_find(dev, enc_resp->encoder_id,
> - DRM_MODE_OBJECT_ENCODER);
> - if (!obj) {
> + encoder = drm_encoder_find(dev, enc_resp->encoder_id);
> + if (!encoder) {
> ret = -ENOENT;
> goto out;
> }
> - encoder = obj_to_encoder(obj);
>
> if (encoder->crtc)
> enc_resp->crtc_id = encoder->crtc->base.id;
> @@ -2036,7 +2027,6 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
> struct drm_file *file_priv)
> {
> struct drm_mode_get_plane *plane_resp = data;
> - struct drm_mode_object *obj;
> struct drm_plane *plane;
> uint32_t __user *format_ptr;
> int ret = 0;
> @@ -2045,13 +2035,11 @@ int drm_mode_getplane(struct drm_device *dev, void *data,
> return -EINVAL;
>
> drm_modeset_lock_all(dev);
> - obj = drm_mode_object_find(dev, plane_resp->plane_id,
> - DRM_MODE_OBJECT_PLANE);
> - if (!obj) {
> + plane = drm_plane_find(dev, plane_resp->plane_id);
> + if (!plane) {
> ret = -ENOENT;
> goto out;
> }
> - plane = obj_to_plane(obj);
>
> if (plane->crtc)
> plane_resp->crtc_id = plane->crtc->base.id;
> @@ -2104,7 +2092,6 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
> struct drm_file *file_priv)
> {
> struct drm_mode_set_plane *plane_req = data;
> - struct drm_mode_object *obj;
> struct drm_plane *plane;
> struct drm_crtc *crtc;
> struct drm_framebuffer *fb = NULL, *old_fb = NULL;
> @@ -2119,14 +2106,12 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
> * First, find the plane, crtc, and fb objects. If not available,
> * we don't bother to call the driver.
> */
> - obj = drm_mode_object_find(dev, plane_req->plane_id,
> - DRM_MODE_OBJECT_PLANE);
> - if (!obj) {
> + plane = drm_plane_find(dev, plane_req->plane_id);
> + if (!plane) {
> DRM_DEBUG_KMS("Unknown plane ID %d\n",
> plane_req->plane_id);
> return -ENOENT;
> }
> - plane = obj_to_plane(obj);
>
> /* No fb means shut it down */
> if (!plane_req->fb_id) {
> @@ -2143,15 +2128,13 @@ int drm_mode_setplane(struct drm_device *dev, void *data,
> goto out;
> }
>
> - obj = drm_mode_object_find(dev, plane_req->crtc_id,
> - DRM_MODE_OBJECT_CRTC);
> - if (!obj) {
> + crtc = drm_crtc_find(dev, plane_req->crtc_id);
> + if (!crtc) {
> DRM_DEBUG_KMS("Unknown crtc ID %d\n",
> plane_req->crtc_id);
> ret = -ENOENT;
> goto out;
> }
> - crtc = obj_to_crtc(obj);
>
> fb = drm_framebuffer_lookup(dev, plane_req->fb_id);
> if (!fb) {
> @@ -2338,7 +2321,6 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
> {
> struct drm_mode_config *config = &dev->mode_config;
> struct drm_mode_crtc *crtc_req = data;
> - struct drm_mode_object *obj;
> struct drm_crtc *crtc;
> struct drm_connector **connector_set = NULL, *connector;
> struct drm_framebuffer *fb = NULL;
> @@ -2356,14 +2338,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
> return -ERANGE;
>
> drm_modeset_lock_all(dev);
> - obj = drm_mode_object_find(dev, crtc_req->crtc_id,
> - DRM_MODE_OBJECT_CRTC);
> - if (!obj) {
> + crtc = drm_crtc_find(dev, crtc_req->crtc_id);
> + if (!crtc) {
> DRM_DEBUG_KMS("Unknown CRTC ID %d\n", crtc_req->crtc_id);
> ret = -ENOENT;
> goto out;
> }
> - crtc = obj_to_crtc(obj);
> DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
>
> if (crtc_req->mode_valid) {
> @@ -2446,15 +2426,13 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
> goto out;
> }
>
> - obj = drm_mode_object_find(dev, out_id,
> - DRM_MODE_OBJECT_CONNECTOR);
> - if (!obj) {
> + connector = drm_connector_find(dev, out_id);
> + if (!connector) {
> DRM_DEBUG_KMS("Connector id %d unknown\n",
> out_id);
> ret = -ENOENT;
> goto out;
> }
> - connector = obj_to_connector(obj);
> DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
> connector->base.id,
> drm_get_connector_name(connector));
> @@ -2486,7 +2464,6 @@ static int drm_mode_cursor_common(struct drm_device *dev,
> struct drm_mode_cursor2 *req,
> struct drm_file *file_priv)
> {
> - struct drm_mode_object *obj;
> struct drm_crtc *crtc;
> int ret = 0;
>
> @@ -2496,12 +2473,11 @@ static int drm_mode_cursor_common(struct drm_device *dev,
> if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
> return -EINVAL;
>
> - obj = drm_mode_object_find(dev, req->crtc_id, DRM_MODE_OBJECT_CRTC);
> - if (!obj) {
> + crtc = drm_crtc_find(dev, req->crtc_id);
> + if (!crtc) {
> DRM_DEBUG_KMS("Unknown CRTC ID %d\n", req->crtc_id);
> return -ENOENT;
> }
> - crtc = obj_to_crtc(obj);
>
> mutex_lock(&crtc->mutex);
> if (req->flags & DRM_MODE_CURSOR_BO) {
> @@ -3458,7 +3434,6 @@ EXPORT_SYMBOL(drm_object_property_get_value);
> int drm_mode_getproperty_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file_priv)
> {
> - struct drm_mode_object *obj;
> struct drm_mode_get_property *out_resp = data;
> struct drm_property *property;
> int enum_count = 0;
> @@ -3477,12 +3452,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
> return -EINVAL;
>
> drm_modeset_lock_all(dev);
> - obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
> - if (!obj) {
> + property = drm_property_find(dev, out_resp->prop_id);
> + if (!property) {
> ret = -ENOENT;
> goto done;
> }
> - property = obj_to_property(obj);
>
> if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
> list_for_each_entry(prop_enum, &property->enum_blob_list, head)
> @@ -3610,7 +3584,6 @@ static void drm_property_destroy_blob(struct drm_device *dev,
> int drm_mode_getblob_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file_priv)
> {
> - struct drm_mode_object *obj;
> struct drm_mode_get_blob *out_resp = data;
> struct drm_property_blob *blob;
> int ret = 0;
> @@ -3620,12 +3593,11 @@ int drm_mode_getblob_ioctl(struct drm_device *dev,
> return -EINVAL;
>
> drm_modeset_lock_all(dev);
> - obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
> - if (!obj) {
> + blob = drm_property_blob_find(dev, out_resp->blob_id);
> + if (!blob) {
> ret = -ENOENT;
> goto done;
> }
> - blob = obj_to_blob(obj);
>
> if (out_resp->length == blob->length) {
> blob_ptr = (void __user *)(unsigned long)out_resp->data;
> @@ -4007,7 +3979,6 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file_priv)
> {
> struct drm_mode_crtc_lut *crtc_lut = data;
> - struct drm_mode_object *obj;
> struct drm_crtc *crtc;
> void *r_base, *g_base, *b_base;
> int size;
> @@ -4017,12 +3988,11 @@ int drm_mode_gamma_set_ioctl(struct drm_device *dev,
> return -EINVAL;
>
> drm_modeset_lock_all(dev);
> - obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
> - if (!obj) {
> + crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
> + if (!crtc) {
> ret = -ENOENT;
> goto out;
> }
> - crtc = obj_to_crtc(obj);
>
> if (crtc->funcs->gamma_set == NULL) {
> ret = -ENOSYS;
> @@ -4081,7 +4051,6 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file_priv)
> {
> struct drm_mode_crtc_lut *crtc_lut = data;
> - struct drm_mode_object *obj;
> struct drm_crtc *crtc;
> void *r_base, *g_base, *b_base;
> int size;
> @@ -4091,12 +4060,11 @@ int drm_mode_gamma_get_ioctl(struct drm_device *dev,
> return -EINVAL;
>
> drm_modeset_lock_all(dev);
> - obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
> - if (!obj) {
> + crtc = drm_crtc_find(dev, crtc_lut->crtc_id);
> + if (!crtc) {
> ret = -ENOENT;
> goto out;
> }
> - crtc = obj_to_crtc(obj);
>
> /* memcpy into gamma store */
> if (crtc_lut->gamma_size != crtc->gamma_size) {
> @@ -4149,7 +4117,6 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> void *data, struct drm_file *file_priv)
> {
> struct drm_mode_crtc_page_flip *page_flip = data;
> - struct drm_mode_object *obj;
> struct drm_crtc *crtc;
> struct drm_framebuffer *fb = NULL, *old_fb = NULL;
> struct drm_pending_vblank_event *e = NULL;
> @@ -4163,10 +4130,9 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> if ((page_flip->flags & DRM_MODE_PAGE_FLIP_ASYNC) && !dev->mode_config.async_page_flip)
> return -EINVAL;
>
> - obj = drm_mode_object_find(dev, page_flip->crtc_id, DRM_MODE_OBJECT_CRTC);
> - if (!obj)
> + crtc = drm_crtc_find(dev, page_flip->crtc_id);
> + if (!crtc)
> return -ENOENT;
> - crtc = obj_to_crtc(obj);
>
> mutex_lock(&crtc->mutex);
> if (crtc->primary->fb == NULL) {
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 5c1c31c..cdd5687 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -1063,6 +1063,15 @@ extern int drm_format_vert_chroma_subsampling(uint32_t format);
> extern const char *drm_get_format_name(uint32_t format);
>
> /* Helpers */
> +
> +static inline struct drm_plane *drm_plane_find(struct drm_device *dev,
> + uint32_t id)
> +{
> + struct drm_mode_object *mo;
> + mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PLANE);
> + return mo ? obj_to_plane(mo) : NULL;
> +}
> +
> static inline struct drm_crtc *drm_crtc_find(struct drm_device *dev,
> uint32_t id)
> {
> @@ -1079,6 +1088,30 @@ static inline struct drm_encoder *drm_encoder_find(struct drm_device *dev,
> return mo ? obj_to_encoder(mo) : NULL;
> }
>
> +static inline struct drm_connector *drm_connector_find(struct drm_device *dev,
> + uint32_t id)
> +{
> + struct drm_mode_object *mo;
> + mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_CONNECTOR);
> + return mo ? obj_to_connector(mo) : NULL;
> +}
> +
> +static inline struct drm_property *drm_property_find(struct drm_device *dev,
> + uint32_t id)
> +{
> + struct drm_mode_object *mo;
> + mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_PROPERTY);
> + return mo ? obj_to_property(mo) : NULL;
> +}
> +
> +static inline struct drm_property_blob *
> +drm_property_blob_find(struct drm_device *dev, uint32_t id)
> +{
> + struct drm_mode_object *mo;
> + mo = drm_mode_object_find(dev, id, DRM_MODE_OBJECT_BLOB);
> + return mo ? obj_to_blob(mo) : NULL;
> +}
> +
> /* Plane list iterator for legacy (overlay only) planes. */
> #define drm_for_each_legacy_plane(plane, planelist) \
> list_for_each_entry(plane, planelist, head) \
> --
> 1.9.3
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 3/8] drm: add object property type
2014-05-30 17:12 ` [PATCH 3/8] drm: add object property type Rob Clark
@ 2014-06-03 13:24 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2014-06-03 13:24 UTC (permalink / raw)
To: Rob Clark; +Cc: dri-devel
On Fri, May 30, 2014 at 01:12:05PM -0400, Rob Clark wrote:
> An object property is an id (idr) for a drm mode object. This
> will allow a property to be used set/get a framebuffer, CRTC, etc.
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
> drivers/gpu/drm/drm_crtc.c | 61 +++++++++++++++++++++++++++++++++++++++------
> include/drm/drm_crtc.h | 5 ++++
> include/uapi/drm/drm_mode.h | 1 +
> 3 files changed, 60 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 0dbd6e0..8fdd5b3 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -389,6 +389,21 @@ void drm_mode_object_put(struct drm_device *dev,
> mutex_unlock(&dev->mode_config.idr_mutex);
> }
>
> +static struct drm_mode_object *_object_find(struct drm_device *dev,
> + uint32_t id, uint32_t type)
> +{
> + struct drm_mode_object *obj = NULL;
> +
> + mutex_lock(&dev->mode_config.idr_mutex);
> + obj = idr_find(&dev->mode_config.crtc_idr, id);
> + if (!obj || (type != DRM_MODE_OBJECT_ANY && obj->type != type) ||
> + (obj->id != id))
> + obj = NULL;
> + mutex_unlock(&dev->mode_config.idr_mutex);
> +
> + return obj;
> +}
> +
> /**
> * drm_mode_object_find - look up a drm object with static lifetime
> * @dev: drm device
> @@ -396,7 +411,9 @@ void drm_mode_object_put(struct drm_device *dev,
> * @type: type of the mode object
> *
> * Note that framebuffers cannot be looked up with this functions - since those
> - * are reference counted, they need special treatment.
> + * are reference counted, they need special treatment. Even with
> + * DRM_MODE_OBJECT_ANY (although that will simply return NULL
> + * rather than WARN_ON()).
> */
> struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
> uint32_t id, uint32_t type)
> @@ -406,13 +423,10 @@ struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
> /* Framebuffers are reference counted and need their own lookup
> * function.*/
> WARN_ON(type == DRM_MODE_OBJECT_FB);
> -
> - mutex_lock(&dev->mode_config.idr_mutex);
> - obj = idr_find(&dev->mode_config.crtc_idr, id);
> - if (!obj || (obj->type != type) || (obj->id != id))
> + obj = _object_find(dev, id, type);
> + /* don't leak out unref'd fb's */
> + if (obj && (obj->type == DRM_MODE_OBJECT_FB))
> obj = NULL;
> - mutex_unlock(&dev->mode_config.idr_mutex);
> -
> return obj;
> }
> EXPORT_SYMBOL(drm_mode_object_find);
> @@ -3093,6 +3107,8 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
> if (!property)
> return NULL;
>
> + property->dev = dev;
> +
> if (num_values) {
> property->values = kzalloc(sizeof(uint64_t)*num_values, GFP_KERNEL);
> if (!property->values)
> @@ -3253,6 +3269,23 @@ struct drm_property *drm_property_create_range(struct drm_device *dev, int flags
> }
> EXPORT_SYMBOL(drm_property_create_range);
>
> +struct drm_property *drm_property_create_object(struct drm_device *dev,
> + int flags, const char *name, uint32_t type)
> +{
> + struct drm_property *property;
> +
> + flags |= DRM_MODE_PROP_OBJECT;
> +
> + property = drm_property_create(dev, flags, name, 1);
> + if (!property)
> + return NULL;
> +
> + property->values[0] = type;
> +
> + return property;
> +}
> +EXPORT_SYMBOL(drm_property_create_object);
> +
> /**
> * drm_property_add_enum - add a possible value to an enumeration property
> * @property: enumeration property to change
> @@ -3680,6 +3713,20 @@ static bool drm_property_change_is_valid(struct drm_property *property,
> } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
> /* Only the driver knows */
> return true;
> + } else if (drm_property_type_is(property, DRM_MODE_PROP_OBJECT)) {
> + struct drm_mode_object *obj;
> + /* a zero value for an object property translates to null: */
> + if (value == 0)
> + return true;
> + /*
> + * NOTE: use _object_find() directly to bypass restriction on
> + * looking up refcnt'd objects (ie. fb's). For a refcnt'd
> + * object this could race against object finalization, so it
> + * simply tells us that the object *was* valid. Which is good
> + * enough.
> + */
> + obj = _object_find(property->dev, value, property->values[0]);
> + return obj != NULL;
> } else {
> int i;
> for (i = 0; i < property->num_values; i++)
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 0ff9558..c63df87 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -50,6 +50,7 @@ struct drm_clip_rect;
> #define DRM_MODE_OBJECT_BLOB 0xbbbbbbbb
> #define DRM_MODE_OBJECT_PLANE 0xeeeeeeee
> #define DRM_MODE_OBJECT_BRIDGE 0xbdbdbdbd
> +#define DRM_MODE_OBJECT_ANY 0
>
> struct drm_mode_object {
> uint32_t id;
> @@ -190,6 +191,7 @@ struct drm_property {
> char name[DRM_PROP_NAME_LEN];
> uint32_t num_values;
> uint64_t *values;
> + struct drm_device *dev;
>
> struct list_head enum_blob_list;
> };
> @@ -981,6 +983,8 @@ struct drm_property *drm_property_create_bitmask(struct drm_device *dev,
> struct drm_property *drm_property_create_range(struct drm_device *dev, int flags,
> const char *name,
> uint64_t min, uint64_t max);
> +struct drm_property *drm_property_create_object(struct drm_device *dev,
> + int flags, const char *name, uint32_t type);
> extern void drm_property_destroy(struct drm_device *dev, struct drm_property *property);
> extern int drm_property_add_enum(struct drm_property *property, int index,
> uint64_t value, const char *name);
> @@ -997,6 +1001,7 @@ extern int drm_mode_crtc_set_gamma_size(struct drm_crtc *crtc,
> int gamma_size);
> extern struct drm_mode_object *drm_mode_object_find(struct drm_device *dev,
> uint32_t id, uint32_t type);
> +
> /* IOCTLs */
> extern int drm_mode_getresources(struct drm_device *dev,
> void *data, struct drm_file *file_priv);
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index a7f546e..5b530c7 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -263,6 +263,7 @@ struct drm_mode_get_connector {
> */
> #define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
> #define DRM_MODE_PROP_TYPE(n) ((n) << 6)
> +#define DRM_MODE_PROP_OBJECT DRM_MODE_PROP_TYPE(1)
>
> struct drm_mode_property_enum {
> __u64 value;
> --
> 1.9.3
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 2/8] drm: add extended property types
2014-05-30 17:12 ` [PATCH 2/8] drm: add extended property types Rob Clark
@ 2014-06-03 13:25 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2014-06-03 13:25 UTC (permalink / raw)
To: Rob Clark; +Cc: dri-devel
On Fri, May 30, 2014 at 01:12:04PM -0400, Rob Clark wrote:
> If we continue to use bitmask for type, we will quickly run out of room
> to add new types. Split this up so existing part of bitmask range
> continues to function as before, but reserve a chunk of the remaining
> space for an integer type-id. Wrap this all up in some type-check
> helpers to keep the backwards-compat uglyness contained.
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
I kinda liked David's idea to just continue the enumeration, but instead
of continuing with flags we'll just start at last_flag+1, +2, ...
With or without that this is Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
> ---
> drivers/gpu/drm/drm_crtc.c | 26 +++++++++++++++++---------
> include/drm/drm_crtc.h | 17 +++++++++++++++++
> include/uapi/drm/drm_mode.h | 13 +++++++++++++
> 3 files changed, 47 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index 02872af..0dbd6e0 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -3113,6 +3113,9 @@ struct drm_property *drm_property_create(struct drm_device *dev, int flags,
> }
>
> list_add_tail(&property->head, &dev->mode_config.property_list);
> +
> + WARN_ON(!drm_property_type_valid(property));
> +
> return property;
> fail:
> kfree(property->values);
> @@ -3270,14 +3273,16 @@ int drm_property_add_enum(struct drm_property *property, int index,
> {
> struct drm_property_enum *prop_enum;
>
> - if (!(property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)))
> + if (!(drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
> + drm_property_type_is(property, DRM_MODE_PROP_BITMASK)))
> return -EINVAL;
>
> /*
> * Bitmask enum properties have the additional constraint of values
> * from 0 to 63
> */
> - if ((property->flags & DRM_MODE_PROP_BITMASK) && (value > 63))
> + if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK) &&
> + (value > 63))
> return -EINVAL;
>
> if (!list_empty(&property->enum_blob_list)) {
> @@ -3458,10 +3463,11 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
> goto done;
> }
>
> - if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
> + if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
> + drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
> list_for_each_entry(prop_enum, &property->enum_blob_list, head)
> enum_count++;
> - } else if (property->flags & DRM_MODE_PROP_BLOB) {
> + } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
> list_for_each_entry(prop_blob, &property->enum_blob_list, head)
> blob_count++;
> }
> @@ -3483,7 +3489,8 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
> }
> out_resp->count_values = value_count;
>
> - if (property->flags & (DRM_MODE_PROP_ENUM | DRM_MODE_PROP_BITMASK)) {
> + if (drm_property_type_is(property, DRM_MODE_PROP_ENUM) ||
> + drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
> if ((out_resp->count_enum_blobs >= enum_count) && enum_count) {
> copied = 0;
> enum_ptr = (struct drm_mode_property_enum __user *)(unsigned long)out_resp->enum_blob_ptr;
> @@ -3505,7 +3512,7 @@ int drm_mode_getproperty_ioctl(struct drm_device *dev,
> out_resp->count_enum_blobs = enum_count;
> }
>
> - if (property->flags & DRM_MODE_PROP_BLOB) {
> + if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
> if ((out_resp->count_enum_blobs >= blob_count) && blob_count) {
> copied = 0;
> blob_id_ptr = (uint32_t __user *)(unsigned long)out_resp->enum_blob_ptr;
> @@ -3659,17 +3666,18 @@ static bool drm_property_change_is_valid(struct drm_property *property,
> {
> if (property->flags & DRM_MODE_PROP_IMMUTABLE)
> return false;
> - if (property->flags & DRM_MODE_PROP_RANGE) {
> +
> + if (drm_property_type_is(property, DRM_MODE_PROP_RANGE)) {
> if (value < property->values[0] || value > property->values[1])
> return false;
> return true;
> - } else if (property->flags & DRM_MODE_PROP_BITMASK) {
> + } else if (drm_property_type_is(property, DRM_MODE_PROP_BITMASK)) {
> int i;
> uint64_t valid_mask = 0;
> for (i = 0; i < property->num_values; i++)
> valid_mask |= (1ULL << property->values[i]);
> return !(value & ~valid_mask);
> - } else if (property->flags & DRM_MODE_PROP_BLOB) {
> + } else if (drm_property_type_is(property, DRM_MODE_PROP_BLOB)) {
> /* Only the driver knows */
> return true;
> } else {
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index cdd5687..0ff9558 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -931,6 +931,23 @@ extern void drm_mode_config_cleanup(struct drm_device *dev);
>
> extern int drm_mode_connector_update_edid_property(struct drm_connector *connector,
> struct edid *edid);
> +
> +static inline bool drm_property_type_is(struct drm_property *property,
> + uint32_t type)
> +{
> + /* instanceof for props.. handles extended type vs original types: */
> + if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
> + return (property->flags & DRM_MODE_PROP_EXTENDED_TYPE) == type;
> + return property->flags & type;
> +}
> +
> +static inline bool drm_property_type_valid(struct drm_property *property)
> +{
> + if (property->flags & DRM_MODE_PROP_EXTENDED_TYPE)
> + return !(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
> + return !!(property->flags & DRM_MODE_PROP_LEGACY_TYPE);
> +}
> +
> extern int drm_object_property_set_value(struct drm_mode_object *obj,
> struct drm_property *property,
> uint64_t val);
> diff --git a/include/uapi/drm/drm_mode.h b/include/uapi/drm/drm_mode.h
> index f104c26..a7f546e 100644
> --- a/include/uapi/drm/drm_mode.h
> +++ b/include/uapi/drm/drm_mode.h
> @@ -251,6 +251,19 @@ struct drm_mode_get_connector {
> #define DRM_MODE_PROP_BLOB (1<<4)
> #define DRM_MODE_PROP_BITMASK (1<<5) /* bitmask of enumerated types */
>
> +/* non-extended types: legacy bitmask, one bit per type: */
> +#define DRM_MODE_PROP_LEGACY_TYPE ( \
> + DRM_MODE_PROP_RANGE | \
> + DRM_MODE_PROP_ENUM | \
> + DRM_MODE_PROP_BLOB | \
> + DRM_MODE_PROP_BITMASK)
> +
> +/* extended-types: rather than continue to consume a bit per type,
> + * grab a chunk of the bits to use as integer type id.
> + */
> +#define DRM_MODE_PROP_EXTENDED_TYPE 0x0000ffc0
> +#define DRM_MODE_PROP_TYPE(n) ((n) << 6)
> +
> struct drm_mode_property_enum {
> __u64 value;
> char name[DRM_PROP_NAME_LEN];
> --
> 1.9.3
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3)
2014-05-30 17:12 ` [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3) Rob Clark
@ 2014-06-03 13:29 ` Daniel Vetter
2014-06-04 3:38 ` Dave Airlie
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2014-06-03 13:29 UTC (permalink / raw)
To: Rob Clark; +Cc: dri-devel
On Fri, May 30, 2014 at 01:12:09PM -0400, Rob Clark wrote:
> For atomic, it will be quite necessary to not need to care so much
> about locking order. And 'state' gives us a convenient place to stash a
> ww_ctx for any sort of update that needs to grab multiple crtc locks.
>
> Because we will want to eventually make locking even more fine grained
> (giving locks to planes, connectors, etc), split out drm_modeset_lock
> and drm_modeset_acquire_ctx to track acquired locks.
>
> Atomic will use this to keep track of which locks have been acquired
> in a transaction.
>
> v1: original
> v2: remove a few things not needed until atomic, for now
> v3: update for v3 of connection_mutex patch..
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
Still meh about the lock_all_crtcs helper, imo that one should die. But
one todo you've missed from my fixup patch is to add kerneldoc for all the
locking helpers (maybe that convinces you to inline lock_all_crtcs ;-) and
pull it into the drm docbook template. Otherwise nothing stuck out any
more.
-Daniel
> ---
> drivers/gpu/drm/Makefile | 2 +-
> drivers/gpu/drm/drm_crtc.c | 85 +++++++++++-----
> drivers/gpu/drm/drm_crtc_helper.c | 3 +-
> drivers/gpu/drm/drm_fb_helper.c | 4 +
> drivers/gpu/drm/drm_modeset_lock.c | 179 ++++++++++++++++++++++++++++++++++
> drivers/gpu/drm/drm_plane_helper.c | 2 +-
> drivers/gpu/drm/i915/intel_crt.c | 5 +-
> drivers/gpu/drm/i915/intel_display.c | 58 +++++++----
> drivers/gpu/drm/i915/intel_dp.c | 14 +--
> drivers/gpu/drm/i915/intel_drv.h | 6 +-
> drivers/gpu/drm/i915/intel_opregion.c | 4 +-
> drivers/gpu/drm/i915/intel_overlay.c | 4 +-
> drivers/gpu/drm/i915/intel_panel.c | 8 +-
> drivers/gpu/drm/i915/intel_sprite.c | 2 +-
> drivers/gpu/drm/i915/intel_tv.c | 5 +-
> drivers/gpu/drm/omapdrm/omap_crtc.c | 10 +-
> drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | 8 +-
> include/drm/drmP.h | 5 -
> include/drm/drm_crtc.h | 15 +--
> include/drm/drm_modeset_lock.h | 103 +++++++++++++++++++
> 20 files changed, 434 insertions(+), 88 deletions(-)
> create mode 100644 drivers/gpu/drm/drm_modeset_lock.c
> create mode 100644 include/drm/drm_modeset_lock.h
>
> diff --git a/drivers/gpu/drm/Makefile b/drivers/gpu/drm/Makefile
> index 48e38ba..bf4c12d 100644
> --- a/drivers/gpu/drm/Makefile
> +++ b/drivers/gpu/drm/Makefile
> @@ -14,7 +14,7 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
> drm_info.o drm_debugfs.o drm_encoder_slave.o \
> drm_trace_points.o drm_global.o drm_prime.o \
> drm_rect.o drm_vma_manager.o drm_flip_work.o \
> - drm_plane_helper.o
> + drm_plane_helper.o drm_modeset_lock.o
>
> drm-$(CONFIG_COMPAT) += drm_ioc32.o
> drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> index bbb329f..186bed4 100644
> --- a/drivers/gpu/drm/drm_crtc.c
> +++ b/drivers/gpu/drm/drm_crtc.c
> @@ -37,6 +37,7 @@
> #include <drm/drm_crtc.h>
> #include <drm/drm_edid.h>
> #include <drm/drm_fourcc.h>
> +#include <drm/drm_modeset_lock.h>
>
> #include "drm_crtc_internal.h"
>
> @@ -50,14 +51,42 @@
> */
> void drm_modeset_lock_all(struct drm_device *dev)
> {
> - struct drm_crtc *crtc;
> + struct drm_mode_config *config = &dev->mode_config;
> + struct drm_modeset_acquire_ctx *ctx;
> + int ret;
>
> - mutex_lock(&dev->mode_config.mutex);
> + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
> + if (WARN_ON(!ctx))
> + return;
>
> - mutex_lock(&dev->mode_config.connection_mutex);
> + mutex_lock(&config->mutex);
>
> - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> - mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
> + drm_modeset_acquire_init(ctx, 0);
> +
> +retry:
> + ret = drm_modeset_lock(&config->connection_mutex, ctx);
> + if (ret)
> + goto fail;
> + ret = drm_modeset_lock_all_crtcs(dev, ctx);
> + if (ret)
> + goto fail;
> +
> + WARN_ON(config->acquire_ctx);
> +
> + /* now we hold the locks, so now that it is safe, stash the
> + * ctx for drm_modeset_unlock_all():
> + */
> + config->acquire_ctx = ctx;
> +
> + drm_warn_on_modeset_not_all_locked(dev);
> +
> + return;
> +
> +fail:
> + if (ret == -EDEADLK) {
> + drm_modeset_backoff(ctx);
> + goto retry;
> + }
> }
> EXPORT_SYMBOL(drm_modeset_lock_all);
>
> @@ -69,12 +98,17 @@ EXPORT_SYMBOL(drm_modeset_lock_all);
> */
> void drm_modeset_unlock_all(struct drm_device *dev)
> {
> - struct drm_crtc *crtc;
> + struct drm_mode_config *config = &dev->mode_config;
> + struct drm_modeset_acquire_ctx *ctx = config->acquire_ctx;
>
> - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> - mutex_unlock(&crtc->mutex);
> + if (WARN_ON(!ctx))
> + return;
> +
> + config->acquire_ctx = NULL;
> + drm_modeset_drop_locks(ctx);
> + drm_modeset_acquire_fini(ctx);
>
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + kfree(ctx);
>
> mutex_unlock(&dev->mode_config.mutex);
> }
> @@ -95,9 +129,9 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
> return;
>
> list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
> - WARN_ON(!mutex_is_locked(&crtc->mutex));
> + WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
>
> - WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
> + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
> }
> EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
> @@ -690,6 +724,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
> }
> EXPORT_SYMBOL(drm_framebuffer_remove);
>
> +DEFINE_WW_CLASS(crtc_ww_class);
> +
> /**
> * drm_crtc_init_with_planes - Initialise a new CRTC object with
> * specified primary and cursor planes.
> @@ -709,6 +745,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
> void *cursor,
> const struct drm_crtc_funcs *funcs)
> {
> + struct drm_mode_config *config = &dev->mode_config;
> int ret;
>
> crtc->dev = dev;
> @@ -716,8 +753,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
> crtc->invert_dimensions = false;
>
> drm_modeset_lock_all(dev);
> - mutex_init(&crtc->mutex);
> - mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);
> + drm_modeset_lock_init(&crtc->mutex);
> + /* dropped by _unlock_all(): */
> + drm_modeset_lock(&crtc->mutex, config->acquire_ctx);
>
> ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
> if (ret)
> @@ -725,8 +763,8 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
>
> crtc->base.properties = &crtc->properties;
>
> - list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
> - dev->mode_config.num_crtc++;
> + list_add_tail(&crtc->head, &config->crtc_list);
> + config->num_crtc++;
>
> crtc->primary = primary;
> if (primary)
> @@ -754,6 +792,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
> kfree(crtc->gamma_store);
> crtc->gamma_store = NULL;
>
> + drm_modeset_lock_fini(&crtc->mutex);
> +
> drm_mode_object_put(dev, &crtc->base);
> list_del(&crtc->head);
> dev->mode_config.num_crtc--;
> @@ -1817,7 +1857,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
> DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
>
> mutex_lock(&dev->mode_config.mutex);
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
>
> connector = drm_connector_find(dev, out_resp->connector_id);
> if (!connector) {
> @@ -1916,7 +1956,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
> out_resp->count_encoders = encoders_count;
>
> out:
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + drm_modeset_unlock(&dev->mode_config.connection_mutex);
> mutex_unlock(&dev->mode_config.mutex);
>
> return ret;
> @@ -2500,7 +2540,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
> return -ENOENT;
> }
>
> - mutex_lock(&crtc->mutex);
> + drm_modeset_lock(&crtc->mutex, NULL);
> if (req->flags & DRM_MODE_CURSOR_BO) {
> if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
> ret = -ENXIO;
> @@ -2524,7 +2564,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
> }
> }
> out:
> - mutex_unlock(&crtc->mutex);
> + drm_modeset_unlock(&crtc->mutex);
>
> return ret;
>
> @@ -4217,7 +4257,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
> if (!crtc)
> return -ENOENT;
>
> - mutex_lock(&crtc->mutex);
> + drm_modeset_lock(&crtc->mutex, NULL);
> if (crtc->primary->fb == NULL) {
> /* The framebuffer is currently unbound, presumably
> * due to a hotplug event, that userspace has not
> @@ -4301,7 +4341,7 @@ out:
> drm_framebuffer_unreference(fb);
> if (old_fb)
> drm_framebuffer_unreference(old_fb);
> - mutex_unlock(&crtc->mutex);
> + drm_modeset_unlock(&crtc->mutex);
>
> return ret;
> }
> @@ -4666,7 +4706,7 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
> void drm_mode_config_init(struct drm_device *dev)
> {
> mutex_init(&dev->mode_config.mutex);
> - mutex_init(&dev->mode_config.connection_mutex);
> + drm_modeset_lock_init(&dev->mode_config.connection_mutex);
> mutex_init(&dev->mode_config.idr_mutex);
> mutex_init(&dev->mode_config.fb_lock);
> INIT_LIST_HEAD(&dev->mode_config.fb_list);
> @@ -4766,5 +4806,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
> }
>
> idr_destroy(&dev->mode_config.crtc_idr);
> + drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
> }
> EXPORT_SYMBOL(drm_mode_config_cleanup);
> diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
> index 5b93caf..4eaded8 100644
> --- a/drivers/gpu/drm/drm_crtc_helper.c
> +++ b/drivers/gpu/drm/drm_crtc_helper.c
> @@ -89,8 +89,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
> struct drm_device *dev = encoder->dev;
>
> WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
> - WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
> -
> + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> list_for_each_entry(connector, &dev->mode_config.connector_list, head)
> if (connector->encoder == encoder)
> return true;
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index e95ed58..b891f4c 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -331,6 +331,10 @@ static bool drm_fb_helper_force_kernel_mode(void)
> if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
> continue;
>
> + /* NOTE: we use lockless flag below to avoid grabbing other
> + * modeset locks. So just trylock the underlying mutex
> + * directly:
> + */
> if (!mutex_trylock(&dev->mode_config.mutex)) {
> error = true;
> continue;
> diff --git a/drivers/gpu/drm/drm_modeset_lock.c b/drivers/gpu/drm/drm_modeset_lock.c
> new file mode 100644
> index 0000000..edd8508
> --- /dev/null
> +++ b/drivers/gpu/drm/drm_modeset_lock.c
> @@ -0,0 +1,179 @@
> +/*
> + * Copyright (C) 2014 Red Hat
> + * Author: Rob Clark <robdclark@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#include <drm/drmP.h>
> +#include <drm/drm_crtc.h>
> +#include <drm/drm_modeset_lock.h>
> +
> +
> +void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
> + uint32_t flags)
> +{
> + ww_acquire_init(&ctx->ww_ctx, &crtc_ww_class);
> + INIT_LIST_HEAD(&ctx->locked);
> +}
> +EXPORT_SYMBOL(drm_modeset_acquire_init);
> +
> +void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx)
> +{
> + ww_acquire_fini(&ctx->ww_ctx);
> +}
> +EXPORT_SYMBOL(drm_modeset_acquire_fini);
> +
> +void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx)
> +{
> + WARN_ON(ctx->contended);
> + while (!list_empty(&ctx->locked)) {
> + struct drm_modeset_lock *lock;
> +
> + lock = list_first_entry(&ctx->locked,
> + struct drm_modeset_lock, head);
> +
> + drm_modeset_unlock(lock);
> + }
> +}
> +EXPORT_SYMBOL(drm_modeset_drop_locks);
> +
> +static inline int modeset_lock(struct drm_modeset_lock *lock,
> + struct drm_modeset_acquire_ctx *ctx,
> + bool interruptible, bool slow)
> +{
> + int ret;
> +
> + WARN_ON(ctx->contended);
> +
> + if (interruptible && slow) {
> + ret = ww_mutex_lock_slow_interruptible(&lock->mutex, &ctx->ww_ctx);
> + } else if (interruptible) {
> + ret = ww_mutex_lock_interruptible(&lock->mutex, &ctx->ww_ctx);
> + } else if (slow) {
> + ww_mutex_lock_slow(&lock->mutex, &ctx->ww_ctx);
> + ret = 0;
> + } else {
> + ret = ww_mutex_lock(&lock->mutex, &ctx->ww_ctx);
> + }
> + if (!ret) {
> + WARN_ON(!list_empty(&lock->head));
> + list_add(&lock->head, &ctx->locked);
> + } else if (ret == -EALREADY) {
> + /* we already hold the lock.. this is fine. For atomic
> + * we will need to be able to drm_modeset_lock() things
> + * without having to keep track of what is already locked
> + * or not.
> + */
> + ret = 0;
> + } else if (ret == -EDEADLK) {
> + ctx->contended = lock;
> + }
> +
> + return ret;
> +}
> +
> +static int modeset_backoff(struct drm_modeset_acquire_ctx *ctx,
> + bool interruptible)
> +{
> + struct drm_modeset_lock *contended = ctx->contended;
> +
> + ctx->contended = NULL;
> +
> + if (WARN_ON(!contended))
> + return 0;
> +
> + drm_modeset_drop_locks(ctx);
> +
> + return modeset_lock(contended, ctx, interruptible, true);
> +}
> +
> +void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx)
> +{
> + modeset_backoff(ctx, false);
> +}
> +EXPORT_SYMBOL(drm_modeset_backoff);
> +
> +int drm_modeset_backoff_interruptable(struct drm_modeset_acquire_ctx *ctx)
> +{
> + return modeset_backoff(ctx, true);
> +}
> +EXPORT_SYMBOL(drm_modeset_backoff_interruptable);
> +
> +/**
> + * drm_modeset_lock - take modeset lock
> + * @lock: lock to take
> + * @ctx: acquire ctx
> + *
> + * If ctx is not NULL, then then it's acquire context is used
> + * and the lock does not need to be explicitly unlocked, it
> + * will be automatically unlocked when the atomic update is
> + * complete
> + */
> +int drm_modeset_lock(struct drm_modeset_lock *lock,
> + struct drm_modeset_acquire_ctx *ctx)
> +{
> + if (ctx)
> + return modeset_lock(lock, ctx, false, false);
> +
> + ww_mutex_lock(&lock->mutex, NULL);
> + return 0;
> +}
> +EXPORT_SYMBOL(drm_modeset_lock);
> +
> +int drm_modeset_lock_interruptible(struct drm_modeset_lock *lock,
> + struct drm_modeset_acquire_ctx *ctx)
> +{
> + if (ctx)
> + return modeset_lock(lock, ctx, true, false);
> +
> + return ww_mutex_lock_interruptible(&lock->mutex, NULL);
> +}
> +EXPORT_SYMBOL(drm_modeset_lock_interruptible);
> +
> +/**
> + * drm_modeset_unlock - drop modeset lock
> + * @lock: lock to release
> + */
> +void drm_modeset_unlock(struct drm_modeset_lock *lock)
> +{
> + list_del_init(&lock->head);
> + ww_mutex_unlock(&lock->mutex);
> +}
> +EXPORT_SYMBOL(drm_modeset_unlock);
> +
> +/**
> + * drm_modeset_lock_all_crtcs - helper to drm_modeset_lock() all CRTCs
> + */
> +int drm_modeset_lock_all_crtcs(struct drm_device *dev,
> + struct drm_modeset_acquire_ctx *ctx)
> +{
> + struct drm_mode_config *config = &dev->mode_config;
> + struct drm_crtc *crtc;
> + int ret = 0;
> +
> + list_for_each_entry(crtc, &config->crtc_list, head) {
> + ret = drm_modeset_lock(&crtc->mutex, ctx);
> + if (ret)
> + return ret;
> + }
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(drm_modeset_lock_all_crtcs);
> diff --git a/drivers/gpu/drm/drm_plane_helper.c b/drivers/gpu/drm/drm_plane_helper.c
> index 458d9bf..6301ec6 100644
> --- a/drivers/gpu/drm/drm_plane_helper.c
> +++ b/drivers/gpu/drm/drm_plane_helper.c
> @@ -59,7 +59,7 @@ static int get_connectors_for_crtc(struct drm_crtc *crtc,
> * need to grab the connection_mutex here to be able to make these
> * checks.
> */
> - WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
> + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
>
> list_for_each_entry(connector, &dev->mode_config.connector_list, head)
> if (connector->encoder && connector->encoder->crtc == crtc) {
> diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
> index 22d8347..33328fc 100644
> --- a/drivers/gpu/drm/i915/intel_crt.c
> +++ b/drivers/gpu/drm/i915/intel_crt.c
> @@ -630,6 +630,7 @@ intel_crt_detect(struct drm_connector *connector, bool force)
> enum intel_display_power_domain power_domain;
> enum drm_connector_status status;
> struct intel_load_detect_pipe tmp;
> + struct drm_modeset_acquire_ctx ctx;
>
> intel_runtime_pm_get(dev_priv);
>
> @@ -673,12 +674,12 @@ intel_crt_detect(struct drm_connector *connector, bool force)
> }
>
> /* for pre-945g platforms use load detect */
> - if (intel_get_load_detect_pipe(connector, NULL, &tmp)) {
> + if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) {
> if (intel_crt_detect_ddc(connector))
> status = connector_status_connected;
> else
> status = intel_crt_load_detect(crt);
> - intel_release_load_detect_pipe(connector, &tmp);
> + intel_release_load_detect_pipe(connector, &tmp, &ctx);
> } else
> status = connector_status_unknown;
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
> index 8cf4bde..f5a49f8 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -2363,7 +2363,7 @@ void intel_display_handle_reset(struct drm_device *dev)
> list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
> struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
>
> - mutex_lock(&crtc->mutex);
> + drm_modeset_lock(&crtc->mutex, NULL);
> /*
> * FIXME: Once we have proper support for primary planes (and
> * disabling them without disabling the entire crtc) allow again
> @@ -2374,7 +2374,7 @@ void intel_display_handle_reset(struct drm_device *dev)
> crtc->primary->fb,
> crtc->x,
> crtc->y);
> - mutex_unlock(&crtc->mutex);
> + drm_modeset_unlock(&crtc->mutex);
> }
> }
>
> @@ -7972,7 +7972,8 @@ mode_fits_in_fbdev(struct drm_device *dev,
>
> bool intel_get_load_detect_pipe(struct drm_connector *connector,
> struct drm_display_mode *mode,
> - struct intel_load_detect_pipe *old)
> + struct intel_load_detect_pipe *old,
> + struct drm_modeset_acquire_ctx *ctx)
> {
> struct intel_crtc *intel_crtc;
> struct intel_encoder *intel_encoder =
> @@ -7982,13 +7983,19 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
> struct drm_crtc *crtc = NULL;
> struct drm_device *dev = encoder->dev;
> struct drm_framebuffer *fb;
> - int i = -1;
> + struct drm_mode_config *config = &dev->mode_config;
> + int ret, i = -1;
>
> DRM_DEBUG_KMS("[CONNECTOR:%d:%s], [ENCODER:%d:%s]\n",
> connector->base.id, drm_get_connector_name(connector),
> encoder->base.id, drm_get_encoder_name(encoder));
>
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_acquire_init(ctx, 0);
> +
> +retry:
> + ret = drm_modeset_lock(&config->connection_mutex, ctx);
> + if (ret)
> + goto fail_unlock;
>
> /*
> * Algorithm gets a little messy:
> @@ -8004,7 +8011,9 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
> if (encoder->crtc) {
> crtc = encoder->crtc;
>
> - mutex_lock(&crtc->mutex);
> + ret = drm_modeset_lock(&crtc->mutex, ctx);
> + if (ret)
> + goto fail_unlock;
>
> old->dpms_mode = connector->dpms;
> old->load_detect_temp = false;
> @@ -8017,7 +8026,7 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
> }
>
> /* Find an unused one (if possible) */
> - list_for_each_entry(possible_crtc, &dev->mode_config.crtc_list, head) {
> + list_for_each_entry(possible_crtc, &config->crtc_list, head) {
> i++;
> if (!(encoder->possible_crtcs & (1 << i)))
> continue;
> @@ -8032,10 +8041,12 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
> */
> if (!crtc) {
> DRM_DEBUG_KMS("no pipe available for load-detect\n");
> - goto fail_unlock_connector;
> + goto fail_unlock;
> }
>
> - mutex_lock(&crtc->mutex);
> + ret = drm_modeset_lock(&crtc->mutex, ctx);
> + if (ret)
> + goto fail_unlock;
> intel_encoder->new_crtc = to_intel_crtc(crtc);
> to_intel_connector(connector)->new_encoder = intel_encoder;
>
> @@ -8085,15 +8096,21 @@ bool intel_get_load_detect_pipe(struct drm_connector *connector,
> intel_crtc->new_config = &intel_crtc->config;
> else
> intel_crtc->new_config = NULL;
> - mutex_unlock(&crtc->mutex);
> -fail_unlock_connector:
> - mutex_unlock(&dev->mode_config.connection_mutex);
> +fail_unlock:
> + if (ret == -EDEADLK) {
> + drm_modeset_backoff(ctx);
> + goto retry;
> + }
> +
> + drm_modeset_drop_locks(ctx);
> + drm_modeset_acquire_fini(ctx);
>
> return false;
> }
>
> void intel_release_load_detect_pipe(struct drm_connector *connector,
> - struct intel_load_detect_pipe *old)
> + struct intel_load_detect_pipe *old,
> + struct drm_modeset_acquire_ctx *ctx)
> {
> struct intel_encoder *intel_encoder =
> intel_attached_encoder(connector);
> @@ -8117,8 +8134,7 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
> drm_framebuffer_unreference(old->release_fb);
> }
>
> - mutex_unlock(&crtc->mutex);
> - mutex_unlock(&connector->dev->mode_config.connection_mutex);
> + goto unlock;
> return;
> }
>
> @@ -8126,8 +8142,9 @@ void intel_release_load_detect_pipe(struct drm_connector *connector,
> if (old->dpms_mode != DRM_MODE_DPMS_ON)
> connector->funcs->dpms(connector, old->dpms_mode);
>
> - mutex_unlock(&crtc->mutex);
> - mutex_unlock(&connector->dev->mode_config.connection_mutex);
> +unlock:
> + drm_modeset_drop_locks(ctx);
> + drm_modeset_acquire_fini(ctx);
> }
>
> static int i9xx_pll_refclk(struct drm_device *dev,
> @@ -10586,7 +10603,7 @@ enum pipe intel_get_pipe_from_connector(struct intel_connector *connector)
> struct drm_encoder *encoder = connector->base.encoder;
> struct drm_device *dev = connector->base.dev;
>
> - WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
> + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
>
> if (!encoder)
> return INVALID_PIPE;
> @@ -11386,6 +11403,7 @@ static void intel_enable_pipe_a(struct drm_device *dev)
> struct intel_connector *connector;
> struct drm_connector *crt = NULL;
> struct intel_load_detect_pipe load_detect_temp;
> + struct drm_modeset_acquire_ctx ctx;
>
> /* We can't just switch on the pipe A, we need to set things up with a
> * proper mode and output configuration. As a gross hack, enable pipe A
> @@ -11402,8 +11420,8 @@ static void intel_enable_pipe_a(struct drm_device *dev)
> if (!crt)
> return;
>
> - if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp))
> - intel_release_load_detect_pipe(crt, &load_detect_temp);
> + if (intel_get_load_detect_pipe(crt, NULL, &load_detect_temp, &ctx))
> + intel_release_load_detect_pipe(crt, &load_detect_temp, &ctx);
>
>
> }
> diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
> index 89fd1dd..9926dc1 100644
> --- a/drivers/gpu/drm/i915/intel_dp.c
> +++ b/drivers/gpu/drm/i915/intel_dp.c
> @@ -1131,7 +1131,7 @@ static void edp_panel_vdd_off_sync(struct intel_dp *intel_dp)
> u32 pp;
> u32 pp_stat_reg, pp_ctrl_reg;
>
> - WARN_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
> + WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
>
> if (!intel_dp->want_panel_vdd && edp_have_panel_vdd(intel_dp)) {
> struct intel_digital_port *intel_dig_port =
> @@ -1168,9 +1168,9 @@ static void edp_panel_vdd_work(struct work_struct *__work)
> struct intel_dp, panel_vdd_work);
> struct drm_device *dev = intel_dp_to_dev(intel_dp);
>
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> edp_panel_vdd_off_sync(intel_dp);
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + drm_modeset_unlock(&dev->mode_config.connection_mutex);
> }
>
> static void edp_panel_vdd_off(struct intel_dp *intel_dp, bool sync)
> @@ -3384,9 +3384,9 @@ void intel_dp_encoder_destroy(struct drm_encoder *encoder)
> drm_encoder_cleanup(encoder);
> if (is_edp(intel_dp)) {
> cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> edp_panel_vdd_off_sync(intel_dp);
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + drm_modeset_unlock(&dev->mode_config.connection_mutex);
> }
> kfree(intel_dig_port);
> }
> @@ -3965,9 +3965,9 @@ intel_dp_init_connector(struct intel_digital_port *intel_dig_port,
> drm_dp_aux_unregister_i2c_bus(&intel_dp->aux);
> if (is_edp(intel_dp)) {
> cancel_delayed_work_sync(&intel_dp->panel_vdd_work);
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> edp_panel_vdd_off_sync(intel_dp);
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + drm_modeset_unlock(&dev->mode_config.connection_mutex);
> }
> drm_sysfs_connector_remove(connector);
> drm_connector_cleanup(connector);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
> index d8b540b..824f8ae 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -721,9 +721,11 @@ void vlv_wait_port_ready(struct drm_i915_private *dev_priv,
> struct intel_digital_port *dport);
> bool intel_get_load_detect_pipe(struct drm_connector *connector,
> struct drm_display_mode *mode,
> - struct intel_load_detect_pipe *old);
> + struct intel_load_detect_pipe *old,
> + struct drm_modeset_acquire_ctx *ctx);
> void intel_release_load_detect_pipe(struct drm_connector *connector,
> - struct intel_load_detect_pipe *old);
> + struct intel_load_detect_pipe *old,
> + struct drm_modeset_acquire_ctx *ctx);
> int intel_pin_and_fence_fb_obj(struct drm_device *dev,
> struct drm_i915_gem_object *obj,
> struct intel_ring_buffer *pipelined);
> diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
> index b812e9d..2e2c71f 100644
> --- a/drivers/gpu/drm/i915/intel_opregion.c
> +++ b/drivers/gpu/drm/i915/intel_opregion.c
> @@ -410,7 +410,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
> if (bclp > 255)
> return ASLC_BACKLIGHT_FAILED;
>
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
>
> /*
> * Update backlight on all connectors that support backlight (usually
> @@ -421,7 +421,7 @@ static u32 asle_set_backlight(struct drm_device *dev, u32 bclp)
> intel_panel_set_backlight(intel_connector, bclp, 255);
> iowrite32(DIV_ROUND_UP(bclp * 100, 255) | ASLE_CBLV_VALID, &asle->cblv);
>
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + drm_modeset_unlock(&dev->mode_config.connection_mutex);
>
>
> return 0;
> diff --git a/drivers/gpu/drm/i915/intel_overlay.c b/drivers/gpu/drm/i915/intel_overlay.c
> index 88249c4..961164d 100644
> --- a/drivers/gpu/drm/i915/intel_overlay.c
> +++ b/drivers/gpu/drm/i915/intel_overlay.c
> @@ -688,7 +688,7 @@ static int intel_overlay_do_put_image(struct intel_overlay *overlay,
> u32 swidth, swidthsw, sheight, ostride;
>
> BUG_ON(!mutex_is_locked(&dev->struct_mutex));
> - BUG_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
> + BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
> BUG_ON(!overlay);
>
> ret = intel_overlay_release_old_vid(overlay);
> @@ -793,7 +793,7 @@ int intel_overlay_switch_off(struct intel_overlay *overlay)
> int ret;
>
> BUG_ON(!mutex_is_locked(&dev->struct_mutex));
> - BUG_ON(!mutex_is_locked(&dev->mode_config.connection_mutex));
> + BUG_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
>
> ret = intel_overlay_recover_from_interrupt(overlay);
> if (ret != 0)
> diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
> index f3df527..f45d874 100644
> --- a/drivers/gpu/drm/i915/intel_panel.c
> +++ b/drivers/gpu/drm/i915/intel_panel.c
> @@ -823,12 +823,12 @@ static int intel_backlight_device_update_status(struct backlight_device *bd)
> struct intel_connector *connector = bl_get_data(bd);
> struct drm_device *dev = connector->base.dev;
>
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> DRM_DEBUG_KMS("updating intel_backlight, brightness=%d/%d\n",
> bd->props.brightness, bd->props.max_brightness);
> intel_panel_set_backlight(connector, bd->props.brightness,
> bd->props.max_brightness);
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + drm_modeset_unlock(&dev->mode_config.connection_mutex);
> return 0;
> }
>
> @@ -840,9 +840,9 @@ static int intel_backlight_device_get_brightness(struct backlight_device *bd)
> int ret;
>
> intel_runtime_pm_get(dev_priv);
> - mutex_lock(&dev->mode_config.connection_mutex);
> + drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
> ret = intel_panel_get_backlight(connector);
> - mutex_unlock(&dev->mode_config.connection_mutex);
> + drm_modeset_unlock(&dev->mode_config.connection_mutex);
> intel_runtime_pm_put(dev_priv);
>
> return ret;
> diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
> index 213cd58..c235546 100644
> --- a/drivers/gpu/drm/i915/intel_sprite.c
> +++ b/drivers/gpu/drm/i915/intel_sprite.c
> @@ -55,7 +55,7 @@ static bool intel_pipe_update_start(struct intel_crtc *crtc, uint32_t *start_vbl
> int scanline, min, max, vblank_start;
> DEFINE_WAIT(wait);
>
> - WARN_ON(!mutex_is_locked(&crtc->base.mutex));
> + WARN_ON(!drm_modeset_is_locked(&crtc->base.mutex));
>
> vblank_start = mode->crtc_vblank_start;
> if (mode->flags & DRM_MODE_FLAG_INTERLACE)
> diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
> index e0193e8..97d9fc9 100644
> --- a/drivers/gpu/drm/i915/intel_tv.c
> +++ b/drivers/gpu/drm/i915/intel_tv.c
> @@ -1321,10 +1321,11 @@ intel_tv_detect(struct drm_connector *connector, bool force)
>
> if (force) {
> struct intel_load_detect_pipe tmp;
> + struct drm_modeset_acquire_ctx ctx;
>
> - if (intel_get_load_detect_pipe(connector, &mode, &tmp)) {
> + if (intel_get_load_detect_pipe(connector, &mode, &tmp, &ctx)) {
> type = intel_tv_detect_type(intel_tv, connector);
> - intel_release_load_detect_pipe(connector, &tmp);
> + intel_release_load_detect_pipe(connector, &tmp, &ctx);
> } else
> return connector_status_unknown;
> } else
> diff --git a/drivers/gpu/drm/omapdrm/omap_crtc.c b/drivers/gpu/drm/omapdrm/omap_crtc.c
> index e3c47a8..2d28dc3 100644
> --- a/drivers/gpu/drm/omapdrm/omap_crtc.c
> +++ b/drivers/gpu/drm/omapdrm/omap_crtc.c
> @@ -319,13 +319,13 @@ static void page_flip_worker(struct work_struct *work)
> struct drm_display_mode *mode = &crtc->mode;
> struct drm_gem_object *bo;
>
> - mutex_lock(&crtc->mutex);
> + drm_modeset_lock(&crtc->mutex, NULL);
> omap_plane_mode_set(omap_crtc->plane, crtc, crtc->primary->fb,
> 0, 0, mode->hdisplay, mode->vdisplay,
> crtc->x << 16, crtc->y << 16,
> mode->hdisplay << 16, mode->vdisplay << 16,
> vblank_cb, crtc);
> - mutex_unlock(&crtc->mutex);
> + drm_modeset_unlock(&crtc->mutex);
>
> bo = omap_framebuffer_bo(crtc->primary->fb, 0);
> drm_gem_object_unreference_unlocked(bo);
> @@ -465,7 +465,7 @@ static void apply_worker(struct work_struct *work)
> * the callbacks and list modification all serialized
> * with respect to modesetting ioctls from userspace.
> */
> - mutex_lock(&crtc->mutex);
> + drm_modeset_lock(&crtc->mutex, NULL);
> dispc_runtime_get();
>
> /*
> @@ -510,7 +510,7 @@ static void apply_worker(struct work_struct *work)
>
> out:
> dispc_runtime_put();
> - mutex_unlock(&crtc->mutex);
> + drm_modeset_unlock(&crtc->mutex);
> }
>
> int omap_crtc_apply(struct drm_crtc *crtc,
> @@ -518,7 +518,7 @@ int omap_crtc_apply(struct drm_crtc *crtc,
> {
> struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
>
> - WARN_ON(!mutex_is_locked(&crtc->mutex));
> + WARN_ON(!drm_modeset_is_locked(&crtc->mutex));
>
> /* no need to queue it again if it is already queued: */
> if (apply->queued)
> diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> index e7199b4..8f3edc4 100644
> --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
> @@ -187,7 +187,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
> * can do this since the caller in the drm core doesn't check anything
> * which is protected by any looks.
> */
> - mutex_unlock(&crtc->mutex);
> + drm_modeset_unlock(&crtc->mutex);
> drm_modeset_lock_all(dev_priv->dev);
>
> /* A lot of the code assumes this */
> @@ -252,7 +252,7 @@ int vmw_du_crtc_cursor_set(struct drm_crtc *crtc, struct drm_file *file_priv,
> ret = 0;
> out:
> drm_modeset_unlock_all(dev_priv->dev);
> - mutex_lock(&crtc->mutex);
> + drm_modeset_lock(&crtc->mutex, NULL);
>
> return ret;
> }
> @@ -273,7 +273,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
> * can do this since the caller in the drm core doesn't check anything
> * which is protected by any looks.
> */
> - mutex_unlock(&crtc->mutex);
> + drm_modeset_unlock(&crtc->mutex);
> drm_modeset_lock_all(dev_priv->dev);
>
> vmw_cursor_update_position(dev_priv, shown,
> @@ -281,7 +281,7 @@ int vmw_du_crtc_cursor_move(struct drm_crtc *crtc, int x, int y)
> du->cursor_y + du->hotspot_y);
>
> drm_modeset_unlock_all(dev_priv->dev);
> - mutex_lock(&crtc->mutex);
> + drm_modeset_lock(&crtc->mutex, NULL);
>
> return 0;
> }
> diff --git a/include/drm/drmP.h b/include/drm/drmP.h
> index 12f10bc..a9b8a5d 100644
> --- a/include/drm/drmP.h
> +++ b/include/drm/drmP.h
> @@ -1184,11 +1184,6 @@ static inline int drm_device_is_unplugged(struct drm_device *dev)
> return ret;
> }
>
> -static inline bool drm_modeset_is_locked(struct drm_device *dev)
> -{
> - return mutex_is_locked(&dev->mode_config.mutex);
> -}
> -
> static inline bool drm_is_render_client(const struct drm_file *file_priv)
> {
> return file_priv->minor->type == DRM_MINOR_RENDER;
> diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
> index 56dffc6..3a3f7da 100644
> --- a/include/drm/drm_crtc.h
> +++ b/include/drm/drm_crtc.h
> @@ -33,6 +33,7 @@
> #include <linux/hdmi.h>
> #include <drm/drm_mode.h>
> #include <drm/drm_fourcc.h>
> +#include <drm/drm_modeset_lock.h>
>
> struct drm_device;
> struct drm_mode_set;
> @@ -205,6 +206,10 @@ struct drm_property {
> struct list_head enum_blob_list;
> };
>
> +void drm_modeset_lock_all(struct drm_device *dev);
> +void drm_modeset_unlock_all(struct drm_device *dev);
> +void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
> +
> struct drm_crtc;
> struct drm_connector;
> struct drm_encoder;
> @@ -280,6 +285,7 @@ struct drm_crtc_funcs {
> * drm_crtc - central CRTC control structure
> * @dev: parent DRM device
> * @head: list management
> + * @mutex: per-CRTC locking
> * @base: base KMS object for ID tracking etc.
> * @primary: primary plane for this CRTC
> * @cursor: cursor plane for this CRTC
> @@ -314,7 +320,7 @@ struct drm_crtc {
> * state, ...) and a write lock for everything which can be update
> * without a full modeset (fb, cursor data, ...)
> */
> - struct mutex mutex;
> + struct drm_modeset_lock mutex;
>
> struct drm_mode_object base;
>
> @@ -738,7 +744,8 @@ struct drm_mode_group {
> */
> struct drm_mode_config {
> struct mutex mutex; /* protects configuration (mode lists etc.) */
> - struct mutex connection_mutex; /* protects connector->encoder and encoder->crtc links */
> + struct drm_modeset_lock connection_mutex; /* protects connector->encoder and encoder->crtc links */
> + struct drm_modeset_acquire_ctx *acquire_ctx; /* for legacy _lock_all() / _unlock_all() */
> struct mutex idr_mutex; /* for IDR management */
> struct idr crtc_idr; /* use this idr for all IDs, fb, crtc, connector, modes - just makes life easier */
> /* this is limited to one for now */
> @@ -839,10 +846,6 @@ struct drm_prop_enum_list {
> char *name;
> };
>
> -extern void drm_modeset_lock_all(struct drm_device *dev);
> -extern void drm_modeset_unlock_all(struct drm_device *dev);
> -extern void drm_warn_on_modeset_not_all_locked(struct drm_device *dev);
> -
> extern int drm_crtc_init_with_planes(struct drm_device *dev,
> struct drm_crtc *crtc,
> struct drm_plane *primary,
> diff --git a/include/drm/drm_modeset_lock.h b/include/drm/drm_modeset_lock.h
> new file mode 100644
> index 0000000..cfb1dc1
> --- /dev/null
> +++ b/include/drm/drm_modeset_lock.h
> @@ -0,0 +1,103 @@
> +/*
> + * Copyright (C) 2014 Red Hat
> + * Author: Rob Clark <robdclark@gmail.com>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
> + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
> + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
> + * OTHER DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifndef DRM_MODESET_LOCK_H_
> +#define DRM_MODESET_LOCK_H_
> +
> +#include <linux/ww_mutex.h>
> +
> +struct drm_modeset_lock;
> +
> +struct drm_modeset_acquire_ctx {
> +
> + struct ww_acquire_ctx ww_ctx;
> +
> + /* contended lock: if a lock is contended you should only call
> + * drm_modeset_backoff() which drops locks and slow-locks the
> + * contended lock.
> + */
> + struct drm_modeset_lock *contended;
> +
> + /* list of 'struct drm_modeset_lock': */
> + struct list_head locked;
> +};
> +
> +/**
> + * drm_modeset_lock - used for locking modeset resources.
> + * @mutex: resource locking
> + * @atomic_pending: is this resource part of a still-pending
> + * atomic update
> + * @head: used to hold it's place on state->locked list when
> + * part of an atomic update
> + *
> + * Used for locking CRTCs and other modeset resources.
> + */
> +struct drm_modeset_lock {
> + /**
> + * modeset lock
> + */
> + struct ww_mutex mutex;
> +
> + /**
> + * Resources that are locked as part of an atomic update are added
> + * to a list (so we know what to unlock at the end).
> + */
> + struct list_head head;
> +};
> +
> +extern struct ww_class crtc_ww_class;
> +
> +void drm_modeset_acquire_init(struct drm_modeset_acquire_ctx *ctx,
> + uint32_t flags);
> +void drm_modeset_acquire_fini(struct drm_modeset_acquire_ctx *ctx);
> +void drm_modeset_drop_locks(struct drm_modeset_acquire_ctx *ctx);
> +void drm_modeset_backoff(struct drm_modeset_acquire_ctx *ctx);
> +int drm_modeset_backoff_interruptable(struct drm_modeset_acquire_ctx *ctx);
> +
> +static inline void drm_modeset_lock_init(struct drm_modeset_lock *lock)
> +{
> + ww_mutex_init(&lock->mutex, &crtc_ww_class);
> + INIT_LIST_HEAD(&lock->head);
> +}
> +
> +static inline void drm_modeset_lock_fini(struct drm_modeset_lock *lock)
> +{
> + WARN_ON(!list_empty(&lock->head));
> +}
> +
> +static inline bool drm_modeset_is_locked(struct drm_modeset_lock *lock)
> +{
> + return ww_mutex_is_locked(&lock->mutex);
> +}
> +
> +int drm_modeset_lock(struct drm_modeset_lock *lock,
> + struct drm_modeset_acquire_ctx *ctx);
> +int drm_modeset_lock_interruptible(struct drm_modeset_lock *lock,
> + struct drm_modeset_acquire_ctx *ctx);
> +void drm_modeset_unlock(struct drm_modeset_lock *lock);
> +
> +struct drm_device;
> +int drm_modeset_lock_all_crtcs(struct drm_device *dev,
> + struct drm_modeset_acquire_ctx *ctx);
> +
> +#endif /* DRM_MODESET_LOCK_H_ */
> --
> 1.9.3
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
2014-05-30 17:12 ` [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked() Rob Clark
@ 2014-06-03 13:33 ` Daniel Vetter
2014-06-03 14:44 ` Rob Clark
0 siblings, 1 reply; 21+ messages in thread
From: Daniel Vetter @ 2014-06-03 13:33 UTC (permalink / raw)
To: Rob Clark; +Cc: dri-devel
On Fri, May 30, 2014 at 01:12:10PM -0400, Rob Clark wrote:
> All drm_fb_helper_restore_fbdev_mode() call sites, save one, do the same
> locking. Simplify this into drm_fb_helper_restore_fbdev_mode_unlocked().
>
> Signed-off-by: Rob Clark <robdclark@gmail.com>
Presuming I'm not blind the last such user is in the fb helper itself for
the panic handler. Should we drop the EXPORT_SYMBOL for the helper?
If we do that we might as well drop the _unlocked prefix and just remove
locking from drivers ...
-Daniel
> ---
> drivers/gpu/drm/armada/armada_fbdev.c | 4 +--
> drivers/gpu/drm/drm_fb_cma_helper.c | 9 ++----
> drivers/gpu/drm/drm_fb_helper.c | 51 +++++++++++++++++++++++--------
> drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +--
> drivers/gpu/drm/gma500/psb_drv.c | 4 +--
> drivers/gpu/drm/i915/intel_fbdev.c | 6 +---
> drivers/gpu/drm/msm/msm_drv.c | 7 ++---
> drivers/gpu/drm/omapdrm/omap_drv.c | 4 +--
> drivers/gpu/drm/tegra/fb.c | 7 ++---
> include/drm/drm_fb_helper.h | 1 +
> 10 files changed, 50 insertions(+), 47 deletions(-)
>
> diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
> index 948cb14..fd166f5 100644
> --- a/drivers/gpu/drm/armada/armada_fbdev.c
> +++ b/drivers/gpu/drm/armada/armada_fbdev.c
> @@ -181,10 +181,8 @@ void armada_fbdev_lastclose(struct drm_device *dev)
> {
> struct armada_private *priv = dev->dev_private;
>
> - drm_modeset_lock_all(dev);
> if (priv->fbdev)
> - drm_fb_helper_restore_fbdev_mode(priv->fbdev);
> - drm_modeset_unlock_all(dev);
> + drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
> }
>
> void armada_fbdev_fini(struct drm_device *dev)
> diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
> index 61b5a47..f27c883 100644
> --- a/drivers/gpu/drm/drm_fb_cma_helper.c
> +++ b/drivers/gpu/drm/drm_fb_cma_helper.c
> @@ -429,13 +429,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);
> */
> void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma)
> {
> - if (fbdev_cma) {
> - struct drm_device *dev = fbdev_cma->fb_helper.dev;
> -
> - drm_modeset_lock_all(dev);
> - drm_fb_helper_restore_fbdev_mode(&fbdev_cma->fb_helper);
> - drm_modeset_unlock_all(dev);
> - }
> + if (fbdev_cma)
> + drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev_cma->fb_helper);
> }
> EXPORT_SYMBOL_GPL(drm_fbdev_cma_restore_mode);
>
> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
> index b891f4c..dc861a1 100644
> --- a/drivers/gpu/drm/drm_fb_helper.c
> +++ b/drivers/gpu/drm/drm_fb_helper.c
> @@ -273,15 +273,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
> }
> EXPORT_SYMBOL(drm_fb_helper_debug_leave);
>
> -/**
> - * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
> - * @fb_helper: fbcon to restore
> - *
> - * This should be called from driver's drm ->lastclose callback
> - * when implementing an fbcon on top of kms using this helper. This ensures that
> - * the user isn't greeted with a black screen when e.g. X dies.
> - */
> -bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
> +static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
> {
> struct drm_device *dev = fb_helper->dev;
> struct drm_plane *plane;
> @@ -311,8 +303,44 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
> }
> return error;
> }
> +/**
> + * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
> + * @fb_helper: fbcon to restore
> + * @lockless: true in drm_fb_helper_force_kernel_mode() path, to avoid
> + * blocking in panic case, everywhere else should use false
> + *
> + * This should be called from driver's drm ->lastclose callback
> + * when implementing an fbcon on top of kms using this helper. This ensures that
> + * the user isn't greeted with a black screen when e.g. X dies.
> + *
> + * Use this variant if you need to bypass locking (panic), or already
> + * hold all modeset locks. Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked()
> + */
> +bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
> +{
> + return restore_fbdev_mode(fb_helper);
> +}
> EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
>
> +/**
> + * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
> + * @fb_helper: fbcon to restore
> + *
> + * This should be called from driver's drm ->lastclose callback
> + * when implementing an fbcon on top of kms using this helper. This ensures that
> + * the user isn't greeted with a black screen when e.g. X dies.
> + */
> +bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
> +{
> + struct drm_device *dev = fb_helper->dev;
> + bool ret;
> + drm_modeset_lock_all(dev);
> + ret = restore_fbdev_mode(fb_helper);
> + drm_modeset_unlock_all(dev);
> + return ret;
> +}
> +EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
> +
> /*
> * restore fbcon display for all kms driver's using this helper, used for sysrq
> * and panic handling.
> @@ -824,7 +852,6 @@ EXPORT_SYMBOL(drm_fb_helper_check_var);
> int drm_fb_helper_set_par(struct fb_info *info)
> {
> struct drm_fb_helper *fb_helper = info->par;
> - struct drm_device *dev = fb_helper->dev;
> struct fb_var_screeninfo *var = &info->var;
>
> if (var->pixclock != 0) {
> @@ -832,9 +859,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
> return -EINVAL;
> }
>
> - drm_modeset_lock_all(dev);
> - drm_fb_helper_restore_fbdev_mode(fb_helper);
> - drm_modeset_unlock_all(dev);
> + drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
>
> if (fb_helper->delayed_hotplug) {
> fb_helper->delayed_hotplug = false;
> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
> index addbf75..93e7ba6 100644
> --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
> +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
> @@ -375,7 +375,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
> if (!private || !private->fb_helper)
> return;
>
> - drm_modeset_lock_all(dev);
> - drm_fb_helper_restore_fbdev_mode(private->fb_helper);
> - drm_modeset_unlock_all(dev);
> + drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper);
> }
> diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
> index 0a3101a..59ea45e 100644
> --- a/drivers/gpu/drm/gma500/psb_drv.c
> +++ b/drivers/gpu/drm/gma500/psb_drv.c
> @@ -112,11 +112,9 @@ static void psb_driver_lastclose(struct drm_device *dev)
> struct drm_psb_private *dev_priv = dev->dev_private;
> struct psb_fbdev *fbdev = dev_priv->fbdev;
>
> - drm_modeset_lock_all(dev);
> - ret = drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
> + ret = drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->psb_fb_helper);
> if (ret)
> DRM_DEBUG("failed to restore crtc mode\n");
> - drm_modeset_unlock_all(dev);
>
> return;
> }
> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
> index fce4a0d..f8258ab 100644
> --- a/drivers/gpu/drm/i915/intel_fbdev.c
> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
> @@ -683,11 +683,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
> if (!dev_priv->fbdev)
> return;
>
> - drm_modeset_lock_all(dev);
> -
> - ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
> + ret = drm_fb_helper_restore_fbdev_mode_unlocked(&dev_priv->fbdev->helper);
> if (ret)
> DRM_DEBUG("failed to restore crtc mode\n");
> -
> - drm_modeset_unlock_all(dev);
> }
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 50ec1be..afedd8b 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -382,11 +382,8 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
> static void msm_lastclose(struct drm_device *dev)
> {
> struct msm_drm_private *priv = dev->dev_private;
> - if (priv->fbdev) {
> - drm_modeset_lock_all(dev);
> - drm_fb_helper_restore_fbdev_mode(priv->fbdev);
> - drm_modeset_unlock_all(dev);
> - }
> + if (priv->fbdev)
> + drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
> }
>
> static irqreturn_t msm_irq(int irq, void *arg)
> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
> index c8270e4..002b972 100644
> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
> @@ -588,9 +588,7 @@ static void dev_lastclose(struct drm_device *dev)
> }
> }
>
> - drm_modeset_lock_all(dev);
> - ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
> - drm_modeset_unlock_all(dev);
> + ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
> if (ret)
> DBG("failed to restore crtc mode");
> }
> diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
> index f7fca09..9798a70 100644
> --- a/drivers/gpu/drm/tegra/fb.c
> +++ b/drivers/gpu/drm/tegra/fb.c
> @@ -346,11 +346,8 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
>
> void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
> {
> - if (fbdev) {
> - drm_modeset_lock_all(fbdev->base.dev);
> - drm_fb_helper_restore_fbdev_mode(&fbdev->base);
> - drm_modeset_unlock_all(fbdev->base.dev);
> - }
> + if (fbdev)
> + drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->base);
> }
>
> static void tegra_fb_output_poll_changed(struct drm_device *drm)
> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
> index 6e622f7..0630b51 100644
> --- a/include/drm/drm_fb_helper.h
> +++ b/include/drm/drm_fb_helper.h
> @@ -109,6 +109,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
> struct fb_info *info);
>
> bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper);
> +bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
> void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
> uint32_t fb_width, uint32_t fb_height);
> void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
> --
> 1.9.3
>
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked()
2014-06-03 13:33 ` Daniel Vetter
@ 2014-06-03 14:44 ` Rob Clark
0 siblings, 0 replies; 21+ messages in thread
From: Rob Clark @ 2014-06-03 14:44 UTC (permalink / raw)
To: Daniel Vetter; +Cc: dri-devel@lists.freedesktop.org
On Tue, Jun 3, 2014 at 9:33 AM, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Fri, May 30, 2014 at 01:12:10PM -0400, Rob Clark wrote:
>> All drm_fb_helper_restore_fbdev_mode() call sites, save one, do the same
>> locking. Simplify this into drm_fb_helper_restore_fbdev_mode_unlocked().
>>
>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>
> Presuming I'm not blind the last such user is in the fb helper itself for
> the panic handler. Should we drop the EXPORT_SYMBOL for the helper?
only reason I could think of for leaving (and for keeping the
_unlocked suffix) was to catch merge issues.. leaving same name but
with locking removed, it would compile fine and fail at runtime ;-)
I can remove the prototype and EXPORT_SYMBOL I suppose just to be
extra sure we catch everything (because once we start doing things
atomically, it won't work if drivers still wrap it with their own
_lock_all())
BR,
-R
> If we do that we might as well drop the _unlocked prefix and just remove
> locking from drivers ...
> -Daniel
>
>> ---
>> drivers/gpu/drm/armada/armada_fbdev.c | 4 +--
>> drivers/gpu/drm/drm_fb_cma_helper.c | 9 ++----
>> drivers/gpu/drm/drm_fb_helper.c | 51 +++++++++++++++++++++++--------
>> drivers/gpu/drm/exynos/exynos_drm_fbdev.c | 4 +--
>> drivers/gpu/drm/gma500/psb_drv.c | 4 +--
>> drivers/gpu/drm/i915/intel_fbdev.c | 6 +---
>> drivers/gpu/drm/msm/msm_drv.c | 7 ++---
>> drivers/gpu/drm/omapdrm/omap_drv.c | 4 +--
>> drivers/gpu/drm/tegra/fb.c | 7 ++---
>> include/drm/drm_fb_helper.h | 1 +
>> 10 files changed, 50 insertions(+), 47 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/armada/armada_fbdev.c b/drivers/gpu/drm/armada/armada_fbdev.c
>> index 948cb14..fd166f5 100644
>> --- a/drivers/gpu/drm/armada/armada_fbdev.c
>> +++ b/drivers/gpu/drm/armada/armada_fbdev.c
>> @@ -181,10 +181,8 @@ void armada_fbdev_lastclose(struct drm_device *dev)
>> {
>> struct armada_private *priv = dev->dev_private;
>>
>> - drm_modeset_lock_all(dev);
>> if (priv->fbdev)
>> - drm_fb_helper_restore_fbdev_mode(priv->fbdev);
>> - drm_modeset_unlock_all(dev);
>> + drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
>> }
>>
>> void armada_fbdev_fini(struct drm_device *dev)
>> diff --git a/drivers/gpu/drm/drm_fb_cma_helper.c b/drivers/gpu/drm/drm_fb_cma_helper.c
>> index 61b5a47..f27c883 100644
>> --- a/drivers/gpu/drm/drm_fb_cma_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_cma_helper.c
>> @@ -429,13 +429,8 @@ EXPORT_SYMBOL_GPL(drm_fbdev_cma_fini);
>> */
>> void drm_fbdev_cma_restore_mode(struct drm_fbdev_cma *fbdev_cma)
>> {
>> - if (fbdev_cma) {
>> - struct drm_device *dev = fbdev_cma->fb_helper.dev;
>> -
>> - drm_modeset_lock_all(dev);
>> - drm_fb_helper_restore_fbdev_mode(&fbdev_cma->fb_helper);
>> - drm_modeset_unlock_all(dev);
>> - }
>> + if (fbdev_cma)
>> + drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev_cma->fb_helper);
>> }
>> EXPORT_SYMBOL_GPL(drm_fbdev_cma_restore_mode);
>>
>> diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
>> index b891f4c..dc861a1 100644
>> --- a/drivers/gpu/drm/drm_fb_helper.c
>> +++ b/drivers/gpu/drm/drm_fb_helper.c
>> @@ -273,15 +273,7 @@ int drm_fb_helper_debug_leave(struct fb_info *info)
>> }
>> EXPORT_SYMBOL(drm_fb_helper_debug_leave);
>>
>> -/**
>> - * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
>> - * @fb_helper: fbcon to restore
>> - *
>> - * This should be called from driver's drm ->lastclose callback
>> - * when implementing an fbcon on top of kms using this helper. This ensures that
>> - * the user isn't greeted with a black screen when e.g. X dies.
>> - */
>> -bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
>> +static bool restore_fbdev_mode(struct drm_fb_helper *fb_helper)
>> {
>> struct drm_device *dev = fb_helper->dev;
>> struct drm_plane *plane;
>> @@ -311,8 +303,44 @@ bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
>> }
>> return error;
>> }
>> +/**
>> + * drm_fb_helper_restore_fbdev_mode - restore fbdev configuration
>> + * @fb_helper: fbcon to restore
>> + * @lockless: true in drm_fb_helper_force_kernel_mode() path, to avoid
>> + * blocking in panic case, everywhere else should use false
>> + *
>> + * This should be called from driver's drm ->lastclose callback
>> + * when implementing an fbcon on top of kms using this helper. This ensures that
>> + * the user isn't greeted with a black screen when e.g. X dies.
>> + *
>> + * Use this variant if you need to bypass locking (panic), or already
>> + * hold all modeset locks. Otherwise use drm_fb_helper_restore_fbdev_mode_unlocked()
>> + */
>> +bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
>> +{
>> + return restore_fbdev_mode(fb_helper);
>> +}
>> EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
>>
>> +/**
>> + * drm_fb_helper_restore_fbdev_mode_unlocked - restore fbdev configuration
>> + * @fb_helper: fbcon to restore
>> + *
>> + * This should be called from driver's drm ->lastclose callback
>> + * when implementing an fbcon on top of kms using this helper. This ensures that
>> + * the user isn't greeted with a black screen when e.g. X dies.
>> + */
>> +bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper)
>> +{
>> + struct drm_device *dev = fb_helper->dev;
>> + bool ret;
>> + drm_modeset_lock_all(dev);
>> + ret = restore_fbdev_mode(fb_helper);
>> + drm_modeset_unlock_all(dev);
>> + return ret;
>> +}
>> +EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode_unlocked);
>> +
>> /*
>> * restore fbcon display for all kms driver's using this helper, used for sysrq
>> * and panic handling.
>> @@ -824,7 +852,6 @@ EXPORT_SYMBOL(drm_fb_helper_check_var);
>> int drm_fb_helper_set_par(struct fb_info *info)
>> {
>> struct drm_fb_helper *fb_helper = info->par;
>> - struct drm_device *dev = fb_helper->dev;
>> struct fb_var_screeninfo *var = &info->var;
>>
>> if (var->pixclock != 0) {
>> @@ -832,9 +859,7 @@ int drm_fb_helper_set_par(struct fb_info *info)
>> return -EINVAL;
>> }
>>
>> - drm_modeset_lock_all(dev);
>> - drm_fb_helper_restore_fbdev_mode(fb_helper);
>> - drm_modeset_unlock_all(dev);
>> + drm_fb_helper_restore_fbdev_mode_unlocked(fb_helper);
>>
>> if (fb_helper->delayed_hotplug) {
>> fb_helper->delayed_hotplug = false;
>> diff --git a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
>> index addbf75..93e7ba6 100644
>> --- a/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
>> +++ b/drivers/gpu/drm/exynos/exynos_drm_fbdev.c
>> @@ -375,7 +375,5 @@ void exynos_drm_fbdev_restore_mode(struct drm_device *dev)
>> if (!private || !private->fb_helper)
>> return;
>>
>> - drm_modeset_lock_all(dev);
>> - drm_fb_helper_restore_fbdev_mode(private->fb_helper);
>> - drm_modeset_unlock_all(dev);
>> + drm_fb_helper_restore_fbdev_mode_unlocked(private->fb_helper);
>> }
>> diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
>> index 0a3101a..59ea45e 100644
>> --- a/drivers/gpu/drm/gma500/psb_drv.c
>> +++ b/drivers/gpu/drm/gma500/psb_drv.c
>> @@ -112,11 +112,9 @@ static void psb_driver_lastclose(struct drm_device *dev)
>> struct drm_psb_private *dev_priv = dev->dev_private;
>> struct psb_fbdev *fbdev = dev_priv->fbdev;
>>
>> - drm_modeset_lock_all(dev);
>> - ret = drm_fb_helper_restore_fbdev_mode(&fbdev->psb_fb_helper);
>> + ret = drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->psb_fb_helper);
>> if (ret)
>> DRM_DEBUG("failed to restore crtc mode\n");
>> - drm_modeset_unlock_all(dev);
>>
>> return;
>> }
>> diff --git a/drivers/gpu/drm/i915/intel_fbdev.c b/drivers/gpu/drm/i915/intel_fbdev.c
>> index fce4a0d..f8258ab 100644
>> --- a/drivers/gpu/drm/i915/intel_fbdev.c
>> +++ b/drivers/gpu/drm/i915/intel_fbdev.c
>> @@ -683,11 +683,7 @@ void intel_fbdev_restore_mode(struct drm_device *dev)
>> if (!dev_priv->fbdev)
>> return;
>>
>> - drm_modeset_lock_all(dev);
>> -
>> - ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
>> + ret = drm_fb_helper_restore_fbdev_mode_unlocked(&dev_priv->fbdev->helper);
>> if (ret)
>> DRM_DEBUG("failed to restore crtc mode\n");
>> -
>> - drm_modeset_unlock_all(dev);
>> }
>> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
>> index 50ec1be..afedd8b 100644
>> --- a/drivers/gpu/drm/msm/msm_drv.c
>> +++ b/drivers/gpu/drm/msm/msm_drv.c
>> @@ -382,11 +382,8 @@ static void msm_preclose(struct drm_device *dev, struct drm_file *file)
>> static void msm_lastclose(struct drm_device *dev)
>> {
>> struct msm_drm_private *priv = dev->dev_private;
>> - if (priv->fbdev) {
>> - drm_modeset_lock_all(dev);
>> - drm_fb_helper_restore_fbdev_mode(priv->fbdev);
>> - drm_modeset_unlock_all(dev);
>> - }
>> + if (priv->fbdev)
>> + drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
>> }
>>
>> static irqreturn_t msm_irq(int irq, void *arg)
>> diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
>> index c8270e4..002b972 100644
>> --- a/drivers/gpu/drm/omapdrm/omap_drv.c
>> +++ b/drivers/gpu/drm/omapdrm/omap_drv.c
>> @@ -588,9 +588,7 @@ static void dev_lastclose(struct drm_device *dev)
>> }
>> }
>>
>> - drm_modeset_lock_all(dev);
>> - ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
>> - drm_modeset_unlock_all(dev);
>> + ret = drm_fb_helper_restore_fbdev_mode_unlocked(priv->fbdev);
>> if (ret)
>> DBG("failed to restore crtc mode");
>> }
>> diff --git a/drivers/gpu/drm/tegra/fb.c b/drivers/gpu/drm/tegra/fb.c
>> index f7fca09..9798a70 100644
>> --- a/drivers/gpu/drm/tegra/fb.c
>> +++ b/drivers/gpu/drm/tegra/fb.c
>> @@ -346,11 +346,8 @@ static void tegra_fbdev_free(struct tegra_fbdev *fbdev)
>>
>> void tegra_fbdev_restore_mode(struct tegra_fbdev *fbdev)
>> {
>> - if (fbdev) {
>> - drm_modeset_lock_all(fbdev->base.dev);
>> - drm_fb_helper_restore_fbdev_mode(&fbdev->base);
>> - drm_modeset_unlock_all(fbdev->base.dev);
>> - }
>> + if (fbdev)
>> + drm_fb_helper_restore_fbdev_mode_unlocked(&fbdev->base);
>> }
>>
>> static void tegra_fb_output_poll_changed(struct drm_device *drm)
>> diff --git a/include/drm/drm_fb_helper.h b/include/drm/drm_fb_helper.h
>> index 6e622f7..0630b51 100644
>> --- a/include/drm/drm_fb_helper.h
>> +++ b/include/drm/drm_fb_helper.h
>> @@ -109,6 +109,7 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
>> struct fb_info *info);
>>
>> bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper);
>> +bool drm_fb_helper_restore_fbdev_mode_unlocked(struct drm_fb_helper *fb_helper);
>> void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helper,
>> uint32_t fb_width, uint32_t fb_height);
>> void drm_fb_helper_fill_fix(struct fb_info *info, uint32_t pitch,
>> --
>> 1.9.3
>>
>
> --
> Daniel Vetter
> Software Engineer, Intel Corporation
> +41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3)
2014-06-03 13:29 ` Daniel Vetter
@ 2014-06-04 3:38 ` Dave Airlie
2014-06-04 9:21 ` Daniel Vetter
0 siblings, 1 reply; 21+ messages in thread
From: Dave Airlie @ 2014-06-04 3:38 UTC (permalink / raw)
To: Daniel Vetter; +Cc: dri-devel
On 3 June 2014 23:29, Daniel Vetter <daniel@ffwll.ch> wrote:
> On Fri, May 30, 2014 at 01:12:09PM -0400, Rob Clark wrote:
>> For atomic, it will be quite necessary to not need to care so much
>> about locking order. And 'state' gives us a convenient place to stash a
>> ww_ctx for any sort of update that needs to grab multiple crtc locks.
>>
>> Because we will want to eventually make locking even more fine grained
>> (giving locks to planes, connectors, etc), split out drm_modeset_lock
>> and drm_modeset_acquire_ctx to track acquired locks.
>>
>> Atomic will use this to keep track of which locks have been acquired
>> in a transaction.
>>
>> v1: original
>> v2: remove a few things not needed until atomic, for now
>> v3: update for v3 of connection_mutex patch..
>>
>> Signed-off-by: Rob Clark <robdclark@gmail.com>
>
> Still meh about the lock_all_crtcs helper, imo that one should die. But
> one todo you've missed from my fixup patch is to add kerneldoc for all the
> locking helpers (maybe that convinces you to inline lock_all_crtcs ;-) and
> pull it into the drm docbook template. Otherwise nothing stuck out any
> more.
I'm happy to apply this one if we get some kerneldoc into it.
I've applied the previous patches to drm-next, there was one conflict in i915,
but I think I fixed it up okay, f7ef3fa77fa85b3a8a15b464efd56d0314a3231c
was what it was conflicting with.
Dave.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3)
2014-06-04 3:38 ` Dave Airlie
@ 2014-06-04 9:21 ` Daniel Vetter
0 siblings, 0 replies; 21+ messages in thread
From: Daniel Vetter @ 2014-06-04 9:21 UTC (permalink / raw)
To: Dave Airlie; +Cc: dri-devel
On Wed, Jun 04, 2014 at 01:38:38PM +1000, Dave Airlie wrote:
> On 3 June 2014 23:29, Daniel Vetter <daniel@ffwll.ch> wrote:
> > On Fri, May 30, 2014 at 01:12:09PM -0400, Rob Clark wrote:
> >> For atomic, it will be quite necessary to not need to care so much
> >> about locking order. And 'state' gives us a convenient place to stash a
> >> ww_ctx for any sort of update that needs to grab multiple crtc locks.
> >>
> >> Because we will want to eventually make locking even more fine grained
> >> (giving locks to planes, connectors, etc), split out drm_modeset_lock
> >> and drm_modeset_acquire_ctx to track acquired locks.
> >>
> >> Atomic will use this to keep track of which locks have been acquired
> >> in a transaction.
> >>
> >> v1: original
> >> v2: remove a few things not needed until atomic, for now
> >> v3: update for v3 of connection_mutex patch..
> >>
> >> Signed-off-by: Rob Clark <robdclark@gmail.com>
> >
> > Still meh about the lock_all_crtcs helper, imo that one should die. But
> > one todo you've missed from my fixup patch is to add kerneldoc for all the
> > locking helpers (maybe that convinces you to inline lock_all_crtcs ;-) and
> > pull it into the drm docbook template. Otherwise nothing stuck out any
> > more.
>
> I'm happy to apply this one if we get some kerneldoc into it.
>
> I've applied the previous patches to drm-next, there was one conflict in i915,
> but I think I fixed it up okay, f7ef3fa77fa85b3a8a15b464efd56d0314a3231c
> was what it was conflicting with.
Yeah, I've done the modeset_lock_all specifically because of that
conflict, so looks good. Could have dropped the braces too ;-)
-Daniel
--
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2014-06-04 9:21 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-05-30 17:12 [PATCH 0/8] prepare for preparing for atomic (v2) Rob Clark
2014-05-30 17:12 ` [PATCH 1/8] drm: helpers to find mode objects Rob Clark
2014-06-03 13:22 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 2/8] drm: add extended property types Rob Clark
2014-06-03 13:25 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 3/8] drm: add object property type Rob Clark
2014-06-03 13:24 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 4/8] drm: add signed-range " Rob Clark
2014-05-30 17:12 ` [PATCH 5/8] drm: spiff out FB refcnting traces Rob Clark
2014-05-30 17:12 ` [PATCH 6/8] drm: Split connection_mutex out of mode_config.mutex (v3) Rob Clark
2014-05-30 17:12 ` [PATCH 7/8] drm: convert crtc and connection_mutex to ww_mutex (v3) Rob Clark
2014-06-03 13:29 ` Daniel Vetter
2014-06-04 3:38 ` Dave Airlie
2014-06-04 9:21 ` Daniel Vetter
2014-05-30 17:12 ` [PATCH 8/8] drm: add drm_fb_helper_restore_fbdev_mode_unlocked() Rob Clark
2014-06-03 13:33 ` Daniel Vetter
2014-06-03 14:44 ` Rob Clark
2014-06-02 8:11 ` [PATCH 0/8] prepare for preparing for atomic (v2) Daniel Vetter
2014-06-02 15:33 ` Rob Clark
-- strict thread matches above, loose matches on Subject: below --
2014-05-28 23:57 [PATCH 0/8] prepare for preparing for atomic Rob Clark
2014-05-28 23:57 ` [PATCH 5/8] drm: spiff out FB refcnting traces Rob Clark
2014-05-29 8:36 ` David Herrmann
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox