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

Commit 1309a091 authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman
Browse files

Revert "drm/atomic_helper: Stop modesets on unregistered connectors harder"



This reverts commit 72289dc2 which is
commit de9f8eea5a44b0b756d3d6345af7f8e630a3c8c0 upstream.

It breaks the current drm abi and for Android devices, should not be an
issue as modesetting isn't a big deal for them.

Bug: 161946584
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
Change-Id: I74a8e98a755dcd68a79a9fe6c50d92806cb7a1f2
parent 08bed51f
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1706,6 +1706,27 @@ drm_atomic_set_crtc_for_connector(struct drm_connector_state *conn_state,
	struct drm_connector *connector = conn_state->connector;
	struct drm_crtc_state *crtc_state;

	/*
	 * For compatibility with legacy users, we want to make sure that
	 * we allow DPMS On<->Off modesets on unregistered connectors, since
	 * legacy modesetting users will not be expecting these to fail. We do
	 * not however, want to allow legacy users to assign a connector
	 * that's been unregistered from sysfs to another CRTC, since doing
	 * this with a now non-existent connector could potentially leave us
	 * in an invalid state.
	 *
	 * Since the connector can be unregistered at any point during an
	 * atomic check or commit, this is racy. But that's OK: all we care
	 * about is ensuring that userspace can't use this connector for new
	 * configurations after it's been notified that the connector is no
	 * longer present.
	 */
	if (!READ_ONCE(connector->registered) && crtc) {
		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n",
				 connector->base.id, connector->name);
		return -EINVAL;
	}

	if (conn_state->crtc == crtc)
		return 0;

+1 −20
Original line number Diff line number Diff line
@@ -307,26 +307,6 @@ update_connector_routing(struct drm_atomic_state *state,
		return 0;
	}

	crtc_state = drm_atomic_get_new_crtc_state(state,
						   new_connector_state->crtc);
	/*
	 * For compatibility with legacy users, we want to make sure that
	 * we allow DPMS On->Off modesets on unregistered connectors. Modesets
	 * which would result in anything else must be considered invalid, to
	 * avoid turning on new displays on dead connectors.
	 *
	 * Since the connector can be unregistered at any point during an
	 * atomic check or commit, this is racy. But that's OK: all we care
	 * about is ensuring that userspace can't do anything but shut off the
	 * display on a connector that was destroyed after its been notified,
	 * not before.
	 */
	if (drm_connector_is_unregistered(connector) && crtc_state->active) {
		DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] is not registered\n",
				 connector->base.id, connector->name);
		return -EINVAL;
	}

	funcs = connector->helper_private;

	if (funcs->atomic_best_encoder)
@@ -371,6 +351,7 @@ update_connector_routing(struct drm_atomic_state *state,

	set_best_encoder(state, new_connector_state, new_encoder);

	crtc_state = drm_atomic_get_new_crtc_state(state, new_connector_state->crtc);
	crtc_state->connectors_changed = true;

	DRM_DEBUG_ATOMIC("[CONNECTOR:%d:%s] using [ENCODER:%d:%s] on [CRTC:%d:%s]\n",
+5 −6
Original line number Diff line number Diff line
@@ -391,8 +391,7 @@ void drm_connector_cleanup(struct drm_connector *connector)
	/* The connector should have been removed from userspace long before
	 * it is finally destroyed.
	 */
	if (WARN_ON(connector->registration_state ==
		    DRM_CONNECTOR_REGISTERED))
	if (WARN_ON(connector->registered))
		drm_connector_unregister(connector);

	if (connector->tile_group) {
@@ -449,7 +448,7 @@ int drm_connector_register(struct drm_connector *connector)
		return 0;

	mutex_lock(&connector->mutex);
	if (connector->registration_state != DRM_CONNECTOR_INITIALIZING)
	if (connector->registered)
		goto unlock;

	ret = drm_sysfs_connector_add(connector);
@@ -469,7 +468,7 @@ int drm_connector_register(struct drm_connector *connector)

	drm_mode_object_register(connector->dev, &connector->base);

	connector->registration_state = DRM_CONNECTOR_REGISTERED;
	connector->registered = true;
	goto unlock;

err_debugfs:
@@ -491,7 +490,7 @@ EXPORT_SYMBOL(drm_connector_register);
void drm_connector_unregister(struct drm_connector *connector)
{
	mutex_lock(&connector->mutex);
	if (connector->registration_state != DRM_CONNECTOR_REGISTERED) {
	if (!connector->registered) {
		mutex_unlock(&connector->mutex);
		return;
	}
@@ -502,7 +501,7 @@ void drm_connector_unregister(struct drm_connector *connector)
	drm_sysfs_connector_remove(connector);
	drm_debugfs_connector_remove(connector);

	connector->registration_state = DRM_CONNECTOR_UNREGISTERED;
	connector->registered = false;
	mutex_unlock(&connector->mutex);
}
EXPORT_SYMBOL(drm_connector_unregister);
+4 −4
Original line number Diff line number Diff line
@@ -77,7 +77,7 @@ static bool intel_dp_mst_compute_config(struct intel_encoder *encoder,
	pipe_config->pbn = mst_pbn;

	/* Zombie connectors can't have VCPI slots */
	if (!drm_connector_is_unregistered(connector)) {
	if (READ_ONCE(connector->registered)) {
		slots = drm_dp_atomic_find_vcpi_slots(state,
						      &intel_dp->mst_mgr,
						      port,
@@ -317,7 +317,7 @@ static int intel_dp_mst_get_ddc_modes(struct drm_connector *connector)
	struct edid *edid;
	int ret;

	if (drm_connector_is_unregistered(connector))
	if (!READ_ONCE(connector->registered))
		return intel_connector_update_modes(connector, NULL);

	edid = drm_dp_mst_get_edid(connector, &intel_dp->mst_mgr, intel_connector->port);
@@ -333,7 +333,7 @@ intel_dp_mst_detect(struct drm_connector *connector, bool force)
	struct intel_connector *intel_connector = to_intel_connector(connector);
	struct intel_dp *intel_dp = intel_connector->mst_port;

	if (drm_connector_is_unregistered(connector))
	if (!READ_ONCE(connector->registered))
		return connector_status_disconnected;
	return drm_dp_mst_detect_port(connector, &intel_dp->mst_mgr,
				      intel_connector->port);
@@ -376,7 +376,7 @@ intel_dp_mst_mode_valid(struct drm_connector *connector,
	int bpp = 24; /* MST uses fixed bpp */
	int max_rate, mode_rate, max_lanes, max_link_clock;

	if (drm_connector_is_unregistered(connector))
	if (!READ_ONCE(connector->registered))
		return MODE_ERROR;

	if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
+2 −69
Original line number Diff line number Diff line
@@ -82,53 +82,6 @@ enum drm_connector_status {
	connector_status_unknown = 3,
};

/**
 * enum drm_connector_registration_status - userspace registration status for
 * a &drm_connector
 *
 * This enum is used to track the status of initializing a connector and
 * registering it with userspace, so that DRM can prevent bogus modesets on
 * connectors that no longer exist.
 */
enum drm_connector_registration_state {
	/**
	 * @DRM_CONNECTOR_INITIALIZING: The connector has just been created,
	 * but has yet to be exposed to userspace. There should be no
	 * additional restrictions to how the state of this connector may be
	 * modified.
	 */
	DRM_CONNECTOR_INITIALIZING = 0,

	/**
	 * @DRM_CONNECTOR_REGISTERED: The connector has been fully initialized
	 * and registered with sysfs, as such it has been exposed to
	 * userspace. There should be no additional restrictions to how the
	 * state of this connector may be modified.
	 */
	DRM_CONNECTOR_REGISTERED = 1,

	/**
	 * @DRM_CONNECTOR_UNREGISTERED: The connector has either been exposed
	 * to userspace and has since been unregistered and removed from
	 * userspace, or the connector was unregistered before it had a chance
	 * to be exposed to userspace (e.g. still in the
	 * @DRM_CONNECTOR_INITIALIZING state). When a connector is
	 * unregistered, there are additional restrictions to how its state
	 * may be modified:
	 *
	 * - An unregistered connector may only have its DPMS changed from
	 *   On->Off. Once DPMS is changed to Off, it may not be switched back
	 *   to On.
	 * - Modesets are not allowed on unregistered connectors, unless they
	 *   would result in disabling its assigned CRTCs. This means
	 *   disabling a CRTC on an unregistered connector is OK, but enabling
	 *   one is not.
	 * - Removing a CRTC from an unregistered connector is OK, but new
	 *   CRTCs may never be assigned to an unregistered connector.
	 */
	DRM_CONNECTOR_UNREGISTERED = 2,
};

enum subpixel_order {
	SubPixelUnknown = 0,
	SubPixelHorizontalRGB,
@@ -941,12 +894,10 @@ struct drm_connector {
	bool ycbcr_420_allowed;

	/**
	 * @registration_state: Is this connector initializing, exposed
	 * (registered) with userspace, or unregistered?
	 *
	 * @registered: Is this connector exposed (registered) with userspace?
	 * Protected by @mutex.
	 */
	enum drm_connector_registration_state registration_state;
	bool registered;

	/**
	 * @modes:
@@ -1325,24 +1276,6 @@ static inline void drm_connector_unreference(struct drm_connector *connector)
	drm_connector_put(connector);
}

/**
 * drm_connector_is_unregistered - has the connector been unregistered from
 * userspace?
 * @connector: DRM connector
 *
 * Checks whether or not @connector has been unregistered from userspace.
 *
 * Returns:
 * True if the connector was unregistered, false if the connector is
 * registered or has not yet been registered with userspace.
 */
static inline bool
drm_connector_is_unregistered(struct drm_connector *connector)
{
	return READ_ONCE(connector->registration_state) ==
		DRM_CONNECTOR_UNREGISTERED;
}

const char *drm_get_connector_status_name(enum drm_connector_status status);
const char *drm_get_subpixel_order_name(enum subpixel_order order);
const char *drm_get_dpms_name(int val);