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

Commit 51fd371b authored by Rob Clark's avatar Rob Clark Committed by Dave Airlie
Browse files

drm: convert crtc and connection_mutex to ww_mutex (v5)



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..
v4: squash in docbook
v5: doc tweaks/fixes

Signed-off-by: default avatarRob Clark <robdclark@gmail.com>
Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 4f71d0cb
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -1791,6 +1791,12 @@ void intel_crt_init(struct drm_device *dev)
      <title>KMS API Functions</title>
      <title>KMS API Functions</title>
!Edrivers/gpu/drm/drm_crtc.c
!Edrivers/gpu/drm/drm_crtc.c
    </sect2>
    </sect2>
    <sect2>
      <title>KMS Locking</title>
!Pdrivers/gpu/drm/drm_modeset_lock.c kms locking
!Iinclude/drm/drm_modeset_lock.h
!Edrivers/gpu/drm/drm_modeset_lock.c
    </sect2>
  </sect1>
  </sect1>


  <!-- Internals: kms helper functions -->
  <!-- Internals: kms helper functions -->
+2 −1
Original line number Original line Diff line number Diff line
@@ -13,7 +13,8 @@ drm-y := drm_auth.o drm_buffer.o drm_bufs.o drm_cache.o \
		drm_crtc.o drm_modes.o drm_edid.o \
		drm_crtc.o drm_modes.o drm_edid.o \
		drm_info.o drm_debugfs.o drm_encoder_slave.o \
		drm_info.o drm_debugfs.o drm_encoder_slave.o \
		drm_trace_points.o drm_global.o drm_prime.o \
		drm_trace_points.o drm_global.o drm_prime.o \
		drm_rect.o drm_vma_manager.o drm_flip_work.o
		drm_rect.o drm_vma_manager.o drm_flip_work.o \
		drm_modeset_lock.o


drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_COMPAT) += drm_ioc32.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
drm-$(CONFIG_DRM_GEM_CMA_HELPER) += drm_gem_cma_helper.o
+63 −22
Original line number Original line Diff line number Diff line
@@ -37,6 +37,7 @@
#include <drm/drm_crtc.h>
#include <drm/drm_crtc.h>
#include <drm/drm_edid.h>
#include <drm/drm_edid.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_modeset_lock.h>


#include "drm_crtc_internal.h"
#include "drm_crtc_internal.h"


@@ -50,14 +51,42 @@
 */
 */
void drm_modeset_lock_all(struct drm_device *dev)
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)
	drm_modeset_acquire_init(ctx, 0);
		mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.mutex);

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);
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)
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)
	if (WARN_ON(!ctx))
		mutex_unlock(&crtc->mutex);
		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);
	mutex_unlock(&dev->mode_config.mutex);
}
}
@@ -95,9 +129,9 @@ void drm_warn_on_modeset_not_all_locked(struct drm_device *dev)
		return;
		return;


	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
	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));
	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
}
}
EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
EXPORT_SYMBOL(drm_warn_on_modeset_not_all_locked);
@@ -671,6 +705,8 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
}
}
EXPORT_SYMBOL(drm_framebuffer_remove);
EXPORT_SYMBOL(drm_framebuffer_remove);


DEFINE_WW_CLASS(crtc_ww_class);

/**
/**
 * drm_crtc_init_with_planes - Initialise a new CRTC object with
 * drm_crtc_init_with_planes - Initialise a new CRTC object with
 *    specified primary and cursor planes.
 *    specified primary and cursor planes.
@@ -690,6 +726,7 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
			      void *cursor,
			      void *cursor,
			      const struct drm_crtc_funcs *funcs)
			      const struct drm_crtc_funcs *funcs)
{
{
	struct drm_mode_config *config = &dev->mode_config;
	int ret;
	int ret;


	crtc->dev = dev;
	crtc->dev = dev;
@@ -697,8 +734,9 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,
	crtc->invert_dimensions = false;
	crtc->invert_dimensions = false;


	drm_modeset_lock_all(dev);
	drm_modeset_lock_all(dev);
	mutex_init(&crtc->mutex);
	drm_modeset_lock_init(&crtc->mutex);
	mutex_lock_nest_lock(&crtc->mutex, &dev->mode_config.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);
	ret = drm_mode_object_get(dev, &crtc->base, DRM_MODE_OBJECT_CRTC);
	if (ret)
	if (ret)
@@ -706,8 +744,8 @@ int drm_crtc_init_with_planes(struct drm_device *dev, struct drm_crtc *crtc,


	crtc->base.properties = &crtc->properties;
	crtc->base.properties = &crtc->properties;


	list_add_tail(&crtc->head, &dev->mode_config.crtc_list);
	list_add_tail(&crtc->head, &config->crtc_list);
	dev->mode_config.num_crtc++;
	config->num_crtc++;


	crtc->primary = primary;
	crtc->primary = primary;
	if (primary)
	if (primary)
@@ -735,6 +773,8 @@ void drm_crtc_cleanup(struct drm_crtc *crtc)
	kfree(crtc->gamma_store);
	kfree(crtc->gamma_store);
	crtc->gamma_store = NULL;
	crtc->gamma_store = NULL;


	drm_modeset_lock_fini(&crtc->mutex);

	drm_mode_object_put(dev, &crtc->base);
	drm_mode_object_put(dev, &crtc->base);
	list_del(&crtc->head);
	list_del(&crtc->head);
	dev->mode_config.num_crtc--;
	dev->mode_config.num_crtc--;
@@ -1798,7 +1838,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);


	mutex_lock(&dev->mode_config.mutex);
	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);
	connector = drm_connector_find(dev, out_resp->connector_id);
	if (!connector) {
	if (!connector) {
@@ -1897,7 +1937,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
	out_resp->count_encoders = encoders_count;
	out_resp->count_encoders = encoders_count;


out:
out:
	mutex_unlock(&dev->mode_config.connection_mutex);
	drm_modeset_unlock(&dev->mode_config.connection_mutex);
	mutex_unlock(&dev->mode_config.mutex);
	mutex_unlock(&dev->mode_config.mutex);


	return ret;
	return ret;
@@ -2481,7 +2521,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
		return -ENOENT;
		return -ENOENT;
	}
	}


	mutex_lock(&crtc->mutex);
	drm_modeset_lock(&crtc->mutex, NULL);
	if (req->flags & DRM_MODE_CURSOR_BO) {
	if (req->flags & DRM_MODE_CURSOR_BO) {
		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
		if (!crtc->funcs->cursor_set && !crtc->funcs->cursor_set2) {
			ret = -ENXIO;
			ret = -ENXIO;
@@ -2505,7 +2545,7 @@ static int drm_mode_cursor_common(struct drm_device *dev,
		}
		}
	}
	}
out:
out:
	mutex_unlock(&crtc->mutex);
	drm_modeset_unlock(&crtc->mutex);


	return ret;
	return ret;


@@ -4198,7 +4238,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
	if (!crtc)
	if (!crtc)
		return -ENOENT;
		return -ENOENT;


	mutex_lock(&crtc->mutex);
	drm_modeset_lock(&crtc->mutex, NULL);
	if (crtc->primary->fb == NULL) {
	if (crtc->primary->fb == NULL) {
		/* The framebuffer is currently unbound, presumably
		/* The framebuffer is currently unbound, presumably
		 * due to a hotplug event, that userspace has not
		 * due to a hotplug event, that userspace has not
@@ -4282,7 +4322,7 @@ int drm_mode_page_flip_ioctl(struct drm_device *dev,
		drm_framebuffer_unreference(fb);
		drm_framebuffer_unreference(fb);
	if (old_fb)
	if (old_fb)
		drm_framebuffer_unreference(old_fb);
		drm_framebuffer_unreference(old_fb);
	mutex_unlock(&crtc->mutex);
	drm_modeset_unlock(&crtc->mutex);


	return ret;
	return ret;
}
}
@@ -4647,7 +4687,7 @@ EXPORT_SYMBOL(drm_format_vert_chroma_subsampling);
void drm_mode_config_init(struct drm_device *dev)
void drm_mode_config_init(struct drm_device *dev)
{
{
	mutex_init(&dev->mode_config.mutex);
	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.idr_mutex);
	mutex_init(&dev->mode_config.fb_lock);
	mutex_init(&dev->mode_config.fb_lock);
	INIT_LIST_HEAD(&dev->mode_config.fb_list);
	INIT_LIST_HEAD(&dev->mode_config.fb_list);
@@ -4747,5 +4787,6 @@ void drm_mode_config_cleanup(struct drm_device *dev)
	}
	}


	idr_destroy(&dev->mode_config.crtc_idr);
	idr_destroy(&dev->mode_config.crtc_idr);
	drm_modeset_lock_fini(&dev->mode_config.connection_mutex);
}
}
EXPORT_SYMBOL(drm_mode_config_cleanup);
EXPORT_SYMBOL(drm_mode_config_cleanup);
+1 −2
Original line number Original line Diff line number Diff line
@@ -89,8 +89,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
	struct drm_device *dev = encoder->dev;
	struct drm_device *dev = encoder->dev;


	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
	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)
	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
		if (connector->encoder == encoder)
		if (connector->encoder == encoder)
			return true;
			return true;
+4 −0
Original line number Original line Diff line number Diff line
@@ -331,6 +331,10 @@ static bool drm_fb_helper_force_kernel_mode(void)
		if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
		if (dev->switch_power_state == DRM_SWITCH_POWER_OFF)
			continue;
			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)) {
		if (!mutex_trylock(&dev->mode_config.mutex)) {
			error = true;
			error = true;
			continue;
			continue;
Loading