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

Commit 7b334fcb authored by Chris Wilson's avatar Chris Wilson Committed by Dave Airlie
Browse files

drm: Use a nondestructive mode for output detect when polling

Destructive load-detection is very expensive and due to failings
elsewhere can trigger system wide stalls of up to 600ms. A simple
first step to correcting this is not to invoke such an expensive
and destructive load-detection operation automatically.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=29536
Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=16265


Reported-by: default avatarBruno Prémont <bonbons@linux-vserver.org>
Tested-by: default avatarSitsofe Wheeler <sitsofe@yahoo.com>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Cc: stable@kernel.org
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 27849044
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -103,7 +103,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
		if (connector->funcs->force)
		if (connector->funcs->force)
			connector->funcs->force(connector);
			connector->funcs->force(connector);
	} else {
	} else {
		connector->status = connector->funcs->detect(connector);
		connector->status = connector->funcs->detect(connector, false);
		drm_kms_helper_poll_enable(dev);
		drm_kms_helper_poll_enable(dev);
	}
	}


@@ -866,7 +866,7 @@ static void output_poll_execute(struct work_struct *work)
		    !(connector->polled & DRM_CONNECTOR_POLL_HPD))
		    !(connector->polled & DRM_CONNECTOR_POLL_HPD))
			continue;
			continue;


		status = connector->funcs->detect(connector);
		status = connector->funcs->detect(connector, true);
		if (old_status != status)
		if (old_status != status)
			changed = true;
			changed = true;
	}
	}
+1 −1
Original line number Original line Diff line number Diff line
@@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device,
	struct drm_connector *connector = to_drm_connector(device);
	struct drm_connector *connector = to_drm_connector(device);
	enum drm_connector_status status;
	enum drm_connector_status status;


	status = connector->funcs->detect(connector);
	status = connector->funcs->detect(connector, true);
	return snprintf(buf, PAGE_SIZE, "%s\n",
	return snprintf(buf, PAGE_SIZE, "%s\n",
			drm_get_connector_status_name(status));
			drm_get_connector_status_name(status));
}
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -400,7 +400,9 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder
	return status;
	return status;
}
}


static enum drm_connector_status intel_crt_detect(struct drm_connector *connector)
static enum drm_connector_status
intel_crt_detect(struct drm_connector *connector,
		 bool nondestructive)
{
{
	struct drm_device *dev = connector->dev;
	struct drm_device *dev = connector->dev;
	struct drm_encoder *encoder = intel_attached_encoder(connector);
	struct drm_encoder *encoder = intel_attached_encoder(connector);
@@ -419,6 +421,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto
	if (intel_crt_detect_ddc(encoder))
	if (intel_crt_detect_ddc(encoder))
		return connector_status_connected;
		return connector_status_connected;


	if (nondestructive)
		return connector->status;

	/* for pre-945g platforms use load detect */
	/* for pre-945g platforms use load detect */
	if (encoder->crtc && encoder->crtc->enabled) {
	if (encoder->crtc && encoder->crtc->enabled) {
		status = intel_crt_load_detect(encoder->crtc, intel_encoder);
		status = intel_crt_load_detect(encoder->crtc, intel_encoder);
+2 −1
Original line number Original line Diff line number Diff line
@@ -1386,7 +1386,8 @@ ironlake_dp_detect(struct drm_connector *connector)
 * \return false if DP port is disconnected.
 * \return false if DP port is disconnected.
 */
 */
static enum drm_connector_status
static enum drm_connector_status
intel_dp_detect(struct drm_connector *connector)
intel_dp_detect(struct drm_connector *connector,
		bool nondestructive)
{
{
	struct drm_encoder *encoder = intel_attached_encoder(connector);
	struct drm_encoder *encoder = intel_attached_encoder(connector);
	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
+3 −1
Original line number Original line Diff line number Diff line
@@ -221,7 +221,9 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
 *
 *
 * Unimplemented.
 * Unimplemented.
 */
 */
static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector)
static enum drm_connector_status
intel_dvo_detect(struct drm_connector *connector,
		 bool nondestructive)
{
{
	struct drm_encoder *encoder = intel_attached_encoder(connector);
	struct drm_encoder *encoder = intel_attached_encoder(connector);
	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
	struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
Loading