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

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

drm/modes: add connector reference counting. (v2)



This uses the previous changes to add reference counts
to drm connector objects.

v2: move fbdev changes to their own patch.
add some kerneldoc

Reviewed-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
Reviewed-by: default avatarDaniel Stone <daniels@collabora.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent e76d399f
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -156,6 +156,7 @@ void drm_atomic_state_default_clear(struct drm_atomic_state *state)
						       state->connector_states[i]);
		state->connectors[i] = NULL;
		state->connector_states[i] = NULL;
		drm_connector_unreference(connector);
	}

	for (i = 0; i < config->num_crtc; i++) {
@@ -932,6 +933,7 @@ drm_atomic_get_connector_state(struct drm_atomic_state *state,
	if (!connector_state)
		return ERR_PTR(-ENOMEM);

	drm_connector_reference(connector);
	state->connector_states[index] = connector_state;
	state->connectors[index] = connector;
	connector_state->state = state;
@@ -1622,12 +1624,19 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
		}

		obj = drm_mode_object_find(dev, obj_id, DRM_MODE_OBJECT_ANY);
		if (!obj || !obj->properties) {
		if (!obj) {
			ret = -ENOENT;
			goto out;
		}

		if (!obj->properties) {
			drm_mode_object_unreference(obj);
			ret = -ENOENT;
			goto out;
		}

		if (get_user(count_props, count_props_ptr + copied_objs)) {
			drm_mode_object_unreference(obj);
			ret = -EFAULT;
			goto out;
		}
@@ -1640,12 +1649,14 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
			struct drm_property *prop;

			if (get_user(prop_id, props_ptr + copied_props)) {
				drm_mode_object_unreference(obj);
				ret = -EFAULT;
				goto out;
			}

			prop = drm_property_find(dev, prop_id);
			if (!prop) {
				drm_mode_object_unreference(obj);
				ret = -ENOENT;
				goto out;
			}
@@ -1653,13 +1664,16 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
			if (copy_from_user(&prop_value,
					   prop_values_ptr + copied_props,
					   sizeof(prop_value))) {
				drm_mode_object_unreference(obj);
				ret = -EFAULT;
				goto out;
			}

			ret = atomic_set_prop(state, obj, prop, prop_value);
			if (ret)
			if (ret) {
				drm_mode_object_unreference(obj);
				goto out;
			}

			copied_props++;
		}
@@ -1670,6 +1684,7 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
			plane_mask |= (1 << drm_plane_index(plane));
			plane->old_fb = plane->fb;
		}
		drm_mode_object_unreference(obj);
	}

	if (arg->flags & DRM_MODE_PAGE_FLIP_EVENT) {
+24 −4
Original line number Diff line number Diff line
@@ -864,6 +864,16 @@ static void drm_connector_get_cmdline_mode(struct drm_connector *connector)
		      mode->interlace ?  " interlaced" : "");
}

static void drm_connector_free(struct kref *kref)
{
	struct drm_connector *connector =
		container_of(kref, struct drm_connector, base.refcount);
	struct drm_device *dev = connector->dev;

	drm_mode_object_unregister(dev, &connector->base);
	connector->funcs->destroy(connector);
}

/**
 * drm_connector_init - Init a preallocated connector
 * @dev: DRM device
@@ -889,7 +899,9 @@ int drm_connector_init(struct drm_device *dev,

	drm_modeset_lock_all(dev);

	ret = drm_mode_object_get_reg(dev, &connector->base, DRM_MODE_OBJECT_CONNECTOR, false, NULL);
	ret = drm_mode_object_get_reg(dev, &connector->base,
				      DRM_MODE_OBJECT_CONNECTOR,
				      false, drm_connector_free);
	if (ret)
		goto out_unlock;

@@ -2137,7 +2149,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,

	mutex_lock(&dev->mode_config.mutex);

	connector = drm_connector_find(dev, out_resp->connector_id);
	connector = drm_connector_lookup(dev, out_resp->connector_id);
	if (!connector) {
		ret = -ENOENT;
		goto out_unlock;
@@ -2221,6 +2233,7 @@ int drm_mode_getconnector(struct drm_device *dev, void *data,
out:
	drm_modeset_unlock(&dev->mode_config.connection_mutex);

	drm_connector_unreference(connector);
out_unlock:
	mutex_unlock(&dev->mode_config.mutex);

@@ -2865,13 +2878,14 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
		}

		for (i = 0; i < crtc_req->count_connectors; i++) {
			connector_set[i] = NULL;
			set_connectors_ptr = (uint32_t __user *)(unsigned long)crtc_req->set_connectors_ptr;
			if (get_user(out_id, &set_connectors_ptr[i])) {
				ret = -EFAULT;
				goto out;
			}

			connector = drm_connector_find(dev, out_id);
			connector = drm_connector_lookup(dev, out_id);
			if (!connector) {
				DRM_DEBUG_KMS("Connector id %d unknown\n",
						out_id);
@@ -2899,6 +2913,12 @@ int drm_mode_setcrtc(struct drm_device *dev, void *data,
	if (fb)
		drm_framebuffer_unreference(fb);

	if (connector_set) {
		for (i = 0; i < crtc_req->count_connectors; i++) {
			if (connector_set[i])
				drm_connector_unreference(connector_set[i]);
		}
	}
	kfree(connector_set);
	drm_mode_destroy(dev, mode);
	drm_modeset_unlock_all(dev);
@@ -4989,7 +5009,7 @@ int drm_mode_obj_set_property_ioctl(struct drm_device *dev, void *data,
	property = obj_to_property(prop_obj);

	if (!drm_property_change_valid_get(property, arg->value, &ref))
		goto out;
		goto out_unref;

	switch (arg_obj->type) {
	case DRM_MODE_OBJECT_CONNECTOR:
+31 −1
Original line number Diff line number Diff line
@@ -2571,7 +2571,15 @@ 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,
/**
 * drm_connector_lookup - lookup connector object
 * @dev: DRM device
 * @id: connector object id
 *
 * This function looks up the connector object specified by id
 * add takes a reference to it.
 */
static inline struct drm_connector *drm_connector_lookup(struct drm_device *dev,
		uint32_t id)
{
	struct drm_mode_object *mo;
@@ -2639,6 +2647,28 @@ static inline uint32_t drm_framebuffer_read_refcount(struct drm_framebuffer *fb)
	return atomic_read(&fb->base.refcount.refcount);
}

/**
 * drm_connector_reference - incr the connector refcnt
 * @connector: connector
 *
 * This function increments the connector's refcount.
 */
static inline void drm_connector_reference(struct drm_connector *connector)
{
	drm_mode_object_reference(&connector->base);
}

/**
 * drm_connector_unreference - unref a connector
 * @connector: connector to unref
 *
 * This function decrements the connector's refcount and frees it if it drops to zero.
 */
static inline void drm_connector_unreference(struct drm_connector *connector)
{
	drm_mode_object_unreference(&connector->base);
}

/* Plane list iterator for legacy (overlay only) planes. */
#define drm_for_each_legacy_plane(plane, dev) \
	list_for_each_entry(plane, &(dev)->mode_config.plane_list, head) \