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

Commit dcd14dd9 authored by Dave Airlie's avatar Dave Airlie
Browse files

Merge tag 'topic/connector-locking-2015-07-23' of...

Merge tag 'topic/connector-locking-2015-07-23' of git://anongit.freedesktop.org/drm-intel into drm-next

connector hotplug locking cleanup and fixes to make it save against
atomic. Note that because of depencies this is based on top of the
drm-intel-next pull, so that one needs to go in before this one.

I've also thrown in the mode_group removal on top since it's defunct,
never worked really, no one seems to care and the code can be resurrected
easily.

* tag 'topic/connector-locking-2015-07-23' of git://anongit.freedesktop.org/drm-intel:
  drm: gc now dead mode_group code
  drm: Stop filtering according to mode_group in getresources
  drm: Roll out drm_for_each_{plane,crtc,encoder}
  drm/cma-helper: Fix locking in drm_fb_cma_debugfs_show
  drm: Roll out drm_for_each_connector more
  drm: Amend connector list locking rules
  drm/radeon: Take all modeset locks for DP MST hotplug
  drm/i915: Take all modeset locks for DP MST hotplug
  drm: Check locking in drm_for_each_fb
  drm/i915: Use drm_for_each_fb in i915_debugfs.c
  drm: Check locking in drm_for_each_connector
  drm/fbdev-helper: Grab mode_config.mutex in drm_fb_helper_single_add_all_connectors
  drm/probe-helper: Grab mode_config.mutex in poll_init/enable
  drm: Add modeset object iterators
  drm: Simplify drm_for_each_legacy_plane arguments
parents ce4c464b 3fdefa39
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -1063,7 +1063,7 @@ drm_atomic_add_affected_connectors(struct drm_atomic_state *state,
	 * Changed connectors are already in @state, so only need to look at the
	 * current configuration.
	 */
	list_for_each_entry(connector, &config->connector_list, head) {
	drm_for_each_connector(connector, state->dev) {
		if (connector->state->crtc != crtc)
			continue;

+2 −2
Original line number Diff line number Diff line
@@ -89,7 +89,7 @@ get_current_crtc_for_encoder(struct drm_device *dev,

	WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));

	list_for_each_entry(connector, &config->connector_list, head) {
	drm_for_each_connector(connector, dev) {
		if (connector->state->best_encoder != encoder)
			continue;

@@ -1988,7 +1988,7 @@ void drm_atomic_helper_connector_dpms(struct drm_connector *connector,

	WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));

	list_for_each_entry(tmp_connector, &config->connector_list, head) {
	drm_for_each_connector(tmp_connector, connector->dev) {
		if (tmp_connector->state->crtc != crtc)
			continue;

+45 −161
Original line number Diff line number Diff line
@@ -615,7 +615,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
	if (atomic_read(&fb->refcount.refcount) > 1) {
		drm_modeset_lock_all(dev);
		/* remove from any CRTC */
		list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
		drm_for_each_crtc(crtc, dev) {
			if (crtc->primary->fb == fb) {
				/* should turn off the crtc */
				memset(&set, 0, sizeof(struct drm_mode_set));
@@ -627,7 +627,7 @@ void drm_framebuffer_remove(struct drm_framebuffer *fb)
			}
		}

		list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
		drm_for_each_plane(plane, dev) {
			if (plane->fb == fb)
				drm_plane_force_disable(plane);
		}
@@ -736,7 +736,7 @@ unsigned int drm_crtc_index(struct drm_crtc *crtc)
	unsigned int index = 0;
	struct drm_crtc *tmp;

	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
	drm_for_each_crtc(tmp, crtc->dev) {
		if (tmp == crtc)
			return index;

@@ -988,7 +988,7 @@ unsigned int drm_connector_index(struct drm_connector *connector)

	WARN_ON(!drm_modeset_is_locked(&config->connection_mutex));

	list_for_each_entry(tmp, &connector->dev->mode_config.connector_list, head) {
	drm_for_each_connector(tmp, connector->dev) {
		if (tmp == connector)
			return index;

@@ -1054,7 +1054,7 @@ void drm_connector_unplug_all(struct drm_device *dev)
{
	struct drm_connector *connector;

	/* taking the mode config mutex ends up in a clash with sysfs */
	/* FIXME: taking the mode config mutex ends up in a clash with sysfs */
	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
		drm_connector_unregister(connector);

@@ -1280,7 +1280,7 @@ unsigned int drm_plane_index(struct drm_plane *plane)
	unsigned int index = 0;
	struct drm_plane *tmp;

	list_for_each_entry(tmp, &plane->dev->mode_config.plane_list, head) {
	drm_for_each_plane(tmp, plane->dev) {
		if (tmp == plane)
			return index;

@@ -1305,7 +1305,7 @@ drm_plane_from_index(struct drm_device *dev, int idx)
	struct drm_plane *plane;
	unsigned int i = 0;

	list_for_each_entry(plane, &dev->mode_config.plane_list, head) {
	drm_for_each_plane(plane, dev) {
		if (i == idx)
			return plane;
		i++;
@@ -1679,70 +1679,6 @@ int drm_mode_create_suggested_offset_properties(struct drm_device *dev)
}
EXPORT_SYMBOL(drm_mode_create_suggested_offset_properties);

static int drm_mode_group_init(struct drm_device *dev, struct drm_mode_group *group)
{
	uint32_t total_objects = 0;

	total_objects += dev->mode_config.num_crtc;
	total_objects += dev->mode_config.num_connector;
	total_objects += dev->mode_config.num_encoder;

	group->id_list = kcalloc(total_objects, sizeof(uint32_t), GFP_KERNEL);
	if (!group->id_list)
		return -ENOMEM;

	group->num_crtcs = 0;
	group->num_connectors = 0;
	group->num_encoders = 0;
	return 0;
}

void drm_mode_group_destroy(struct drm_mode_group *group)
{
	kfree(group->id_list);
	group->id_list = NULL;
}

/*
 * NOTE: Driver's shouldn't ever call drm_mode_group_init_legacy_group - it is
 * the drm core's responsibility to set up mode control groups.
 */
int drm_mode_group_init_legacy_group(struct drm_device *dev,
				     struct drm_mode_group *group)
{
	struct drm_crtc *crtc;
	struct drm_encoder *encoder;
	struct drm_connector *connector;
	int ret;

	ret = drm_mode_group_init(dev, group);
	if (ret)
		return ret;

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
		group->id_list[group->num_crtcs++] = crtc->base.id;

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
		group->id_list[group->num_crtcs + group->num_encoders++] =
		encoder->base.id;

	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
		group->id_list[group->num_crtcs + group->num_encoders +
			       group->num_connectors++] = connector->base.id;

	return 0;
}
EXPORT_SYMBOL(drm_mode_group_init_legacy_group);

void drm_reinit_primary_mode_group(struct drm_device *dev)
{
	drm_modeset_lock_all(dev);
	drm_mode_group_destroy(&dev->primary->mode_group);
	drm_mode_group_init_legacy_group(dev, &dev->primary->mode_group);
	drm_modeset_unlock_all(dev);
}
EXPORT_SYMBOL(drm_reinit_primary_mode_group);

/**
 * drm_mode_getresources - get graphics configuration
 * @dev: drm device for the ioctl
@@ -1771,12 +1707,11 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
	int crtc_count = 0;
	int fb_count = 0;
	int encoder_count = 0;
	int copied = 0, i;
	int copied = 0;
	uint32_t __user *fb_id;
	uint32_t __user *crtc_id;
	uint32_t __user *connector_id;
	uint32_t __user *encoder_id;
	struct drm_mode_group *mode_group;

	if (!drm_core_check_feature(dev, DRIVER_MODESET))
		return -EINVAL;
@@ -1809,24 +1744,14 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
	/* mode_config.mutex protects the connector list against e.g. DP MST
	 * connector hot-adding. CRTC/Plane lists are invariant. */
	mutex_lock(&dev->mode_config.mutex);
	if (!drm_is_primary_client(file_priv)) {

		mode_group = NULL;
		list_for_each(lh, &dev->mode_config.crtc_list)
	drm_for_each_crtc(crtc, dev)
		crtc_count++;

		list_for_each(lh, &dev->mode_config.connector_list)
	drm_for_each_connector(connector, dev)
		connector_count++;

		list_for_each(lh, &dev->mode_config.encoder_list)
	drm_for_each_encoder(encoder, dev)
		encoder_count++;
	} else {

		mode_group = &file_priv->master->minor->mode_group;
		crtc_count = mode_group->num_crtcs;
		connector_count = mode_group->num_connectors;
		encoder_count = mode_group->num_encoders;
	}

	card_res->max_height = dev->mode_config.max_height;
	card_res->min_height = dev->mode_config.min_height;
@@ -1837,9 +1762,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
	if (card_res->count_crtcs >= crtc_count) {
		copied = 0;
		crtc_id = (uint32_t __user *)(unsigned long)card_res->crtc_id_ptr;
		if (!mode_group) {
			list_for_each_entry(crtc, &dev->mode_config.crtc_list,
					    head) {
		drm_for_each_crtc(crtc, dev) {
			DRM_DEBUG_KMS("[CRTC:%d]\n", crtc->base.id);
			if (put_user(crtc->base.id, crtc_id + copied)) {
				ret = -EFAULT;
@@ -1847,16 +1770,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
			}
			copied++;
		}
		} else {
			for (i = 0; i < mode_group->num_crtcs; i++) {
				if (put_user(mode_group->id_list[i],
					     crtc_id + copied)) {
					ret = -EFAULT;
					goto out;
				}
				copied++;
			}
		}
	}
	card_res->count_crtcs = crtc_count;

@@ -1864,10 +1777,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
	if (card_res->count_encoders >= encoder_count) {
		copied = 0;
		encoder_id = (uint32_t __user *)(unsigned long)card_res->encoder_id_ptr;
		if (!mode_group) {
			list_for_each_entry(encoder,
					    &dev->mode_config.encoder_list,
					    head) {
		drm_for_each_encoder(encoder, dev) {
			DRM_DEBUG_KMS("[ENCODER:%d:%s]\n", encoder->base.id,
					encoder->name);
			if (put_user(encoder->base.id, encoder_id +
@@ -1877,17 +1787,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
			}
			copied++;
		}
		} else {
			for (i = mode_group->num_crtcs; i < mode_group->num_crtcs + mode_group->num_encoders; i++) {
				if (put_user(mode_group->id_list[i],
					     encoder_id + copied)) {
					ret = -EFAULT;
					goto out;
				}
				copied++;
			}

		}
	}
	card_res->count_encoders = encoder_count;

@@ -1895,10 +1794,7 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
	if (card_res->count_connectors >= connector_count) {
		copied = 0;
		connector_id = (uint32_t __user *)(unsigned long)card_res->connector_id_ptr;
		if (!mode_group) {
			list_for_each_entry(connector,
					    &dev->mode_config.connector_list,
					    head) {
		drm_for_each_connector(connector, dev) {
			DRM_DEBUG_KMS("[CONNECTOR:%d:%s]\n",
				connector->base.id,
				connector->name);
@@ -1909,18 +1805,6 @@ int drm_mode_getresources(struct drm_device *dev, void *data,
			}
			copied++;
		}
		} else {
			int start = mode_group->num_crtcs +
				mode_group->num_encoders;
			for (i = start; i < start + mode_group->num_connectors; i++) {
				if (put_user(mode_group->id_list[i],
					     connector_id + copied)) {
					ret = -EFAULT;
					goto out;
				}
				copied++;
			}
		}
	}
	card_res->count_connectors = connector_count;

@@ -2187,7 +2071,7 @@ static struct drm_crtc *drm_encoder_get_crtc(struct drm_encoder *encoder)

	/* For atomic drivers only state objects are synchronously updated and
	 * protected by modeset locks, so check those first. */
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_for_each_connector(connector, dev) {
		if (!connector->state)
			continue;

@@ -2291,7 +2175,7 @@ int drm_mode_getplane_res(struct drm_device *dev, void *data,
		plane_ptr = (uint32_t __user *)(unsigned long)plane_resp->plane_id_ptr;

		/* Plane lists are invariant, no locking needed. */
		list_for_each_entry(plane, &config->plane_list, head) {
		drm_for_each_plane(plane, dev) {
			/*
			 * Unless userspace set the 'universal planes'
			 * capability bit, only advertise overlays.
@@ -2596,7 +2480,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
	 * connectors from it), hence we need to refcount the fbs across all
	 * crtcs. Atomic modeset will have saner semantics ...
	 */
	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head)
	drm_for_each_crtc(tmp, crtc->dev)
		tmp->primary->old_fb = tmp->primary->fb;

	fb = set->fb;
@@ -2607,7 +2491,7 @@ int drm_mode_set_config_internal(struct drm_mode_set *set)
		crtc->primary->fb = fb;
	}

	list_for_each_entry(tmp, &crtc->dev->mode_config.crtc_list, head) {
	drm_for_each_crtc(tmp, crtc->dev) {
		if (tmp->primary->fb)
			drm_framebuffer_reference(tmp->primary->fb);
		if (tmp->primary->old_fb)
@@ -5377,19 +5261,19 @@ void drm_mode_config_reset(struct drm_device *dev)
	struct drm_encoder *encoder;
	struct drm_connector *connector;

	list_for_each_entry(plane, &dev->mode_config.plane_list, head)
	drm_for_each_plane(plane, dev)
		if (plane->funcs->reset)
			plane->funcs->reset(plane);

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head)
	drm_for_each_crtc(crtc, dev)
		if (crtc->funcs->reset)
			crtc->funcs->reset(crtc);

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
	drm_for_each_encoder(encoder, dev)
		if (encoder->funcs->reset)
			encoder->funcs->reset(encoder);

	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_for_each_connector(connector, dev) {
		connector->status = connector_status_unknown;

		if (connector->funcs->reset)
+21 −21
Original line number Diff line number Diff line
@@ -121,7 +121,7 @@ bool drm_helper_encoder_in_use(struct drm_encoder *encoder)
		WARN_ON(!drm_modeset_is_locked(&dev->mode_config.connection_mutex));
	}

	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
	drm_for_each_connector(connector, dev)
		if (connector->encoder == encoder)
			return true;
	return false;
@@ -151,7 +151,7 @@ bool drm_helper_crtc_in_use(struct drm_crtc *crtc)
	if (!oops_in_progress)
		WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head)
	drm_for_each_encoder(encoder, dev)
		if (encoder->crtc == crtc && drm_helper_encoder_in_use(encoder))
			return true;
	return false;
@@ -180,7 +180,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)

	drm_warn_on_modeset_not_all_locked(dev);

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {
		if (!drm_helper_encoder_in_use(encoder)) {
			drm_encoder_disable(encoder);
			/* disconnect encoder from any connector */
@@ -188,7 +188,7 @@ static void __drm_helper_disable_unused_functions(struct drm_device *dev)
		}
	}

	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
	drm_for_each_crtc(crtc, dev) {
		const struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
		crtc->enabled = drm_helper_crtc_in_use(crtc);
		if (!crtc->enabled) {
@@ -230,7 +230,7 @@ drm_crtc_prepare_encoders(struct drm_device *dev)
	const struct drm_encoder_helper_funcs *encoder_funcs;
	struct drm_encoder *encoder;

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {
		encoder_funcs = encoder->helper_private;
		/* Disable unused encoders */
		if (encoder->crtc == NULL)
@@ -305,7 +305,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
	 * adjust it according to limitations or connector properties, and also
	 * a chance to reject the mode entirely.
	 */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {

		if (encoder->crtc != crtc)
			continue;
@@ -334,7 +334,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
	crtc->hwmode = *adjusted_mode;

	/* Prepare the encoders and CRTCs before setting the mode. */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {

		if (encoder->crtc != crtc)
			continue;
@@ -359,7 +359,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
	if (!ret)
	    goto done;

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {

		if (encoder->crtc != crtc)
			continue;
@@ -376,7 +376,7 @@ bool drm_crtc_helper_set_mode(struct drm_crtc *crtc,
	/* Now enable the clocks, plane, pipe, and connectors that we set up. */
	crtc_funcs->commit(crtc);

	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {

		if (encoder->crtc != crtc)
			continue;
@@ -418,11 +418,11 @@ drm_crtc_helper_disable(struct drm_crtc *crtc)
	struct drm_encoder *encoder;

	/* Decouple all encoders and their attached connectors from this crtc */
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {
		if (encoder->crtc != crtc)
			continue;

		list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
		drm_for_each_connector(connector, dev) {
			if (connector->encoder != encoder)
				continue;

@@ -519,12 +519,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
	 * restored, not the drivers personal bookkeeping.
	 */
	count = 0;
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {
		save_encoders[count++] = *encoder;
	}

	count = 0;
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_for_each_connector(connector, dev) {
		save_connectors[count++] = *connector;
	}

@@ -562,7 +562,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)

	/* a) traverse passed in connector list and get encoders for them */
	count = 0;
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_for_each_connector(connector, dev) {
		const struct drm_connector_helper_funcs *connector_funcs =
			connector->helper_private;
		new_encoder = connector->encoder;
@@ -602,7 +602,7 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
	}

	count = 0;
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_for_each_connector(connector, dev) {
		if (!connector->encoder)
			continue;

@@ -685,12 +685,12 @@ int drm_crtc_helper_set_config(struct drm_mode_set *set)
fail:
	/* Restore all previous data. */
	count = 0;
	list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
	drm_for_each_encoder(encoder, dev) {
		*encoder = save_encoders[count++];
	}

	count = 0;
	list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
	drm_for_each_connector(connector, dev) {
		*connector = save_connectors[count++];
	}

@@ -712,7 +712,7 @@ static int drm_helper_choose_encoder_dpms(struct drm_encoder *encoder)
	struct drm_connector *connector;
	struct drm_device *dev = encoder->dev;

	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
	drm_for_each_connector(connector, dev)
		if (connector->encoder == encoder)
			if (connector->dpms < dpms)
				dpms = connector->dpms;
@@ -746,7 +746,7 @@ static int drm_helper_choose_crtc_dpms(struct drm_crtc *crtc)
	struct drm_connector *connector;
	struct drm_device *dev = crtc->dev;

	list_for_each_entry(connector, &dev->mode_config.connector_list, head)
	drm_for_each_connector(connector, dev)
		if (connector->encoder && connector->encoder->crtc == crtc)
			if (connector->dpms < dpms)
				dpms = connector->dpms;
@@ -862,7 +862,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev)
	bool ret;

	drm_modeset_lock_all(dev);
	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
	drm_for_each_crtc(crtc, dev) {

		if (!crtc->enabled)
			continue;
@@ -876,7 +876,7 @@ void drm_helper_resume_force_mode(struct drm_device *dev)

		/* Turn off outputs that were already powered off */
		if (drm_helper_choose_crtc_dpms(crtc)) {
			list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
			drm_for_each_encoder(encoder, dev) {

				if(encoder->crtc != crtc)
					continue;
+0 −12
Original line number Diff line number Diff line
@@ -285,7 +285,6 @@ static void drm_minor_free(struct drm_device *dev, unsigned int type)
	if (!minor)
		return;

	drm_mode_group_destroy(&minor->mode_group);
	put_device(minor->kdev);

	spin_lock_irqsave(&drm_minor_lock, flags);
@@ -700,20 +699,9 @@ int drm_dev_register(struct drm_device *dev, unsigned long flags)
			goto err_minors;
	}

	/* setup grouping for legacy outputs */
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		ret = drm_mode_group_init_legacy_group(dev,
				&dev->primary->mode_group);
		if (ret)
			goto err_unload;
	}

	ret = 0;
	goto out_unlock;

err_unload:
	if (dev->driver->unload)
		dev->driver->unload(dev);
err_minors:
	drm_minor_unregister(dev, DRM_MINOR_LEGACY);
	drm_minor_unregister(dev, DRM_MINOR_RENDER);
Loading