aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-09-09 18:51:02 -0400
committerDave Airlie <airlied@redhat.com>2010-09-13 06:29:11 -0400
commit7b334fcb45b757ffb093696ca3de1b0c8b4a33f1 (patch)
treefe56259639b9f1c993d742e27468087c46e51f05
parent27849044ca6ff9c52f63271b511282acf6d1c251 (diff)
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: Bruno Prémont <bonbons@linux-vserver.org> Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk> Cc: stable@kernel.org Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/drm_crtc_helper.c4
-rw-r--r--drivers/gpu/drm/drm_sysfs.c2
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c7
-rw-r--r--drivers/gpu/drm/i915/intel_dp.c3
-rw-r--r--drivers/gpu/drm/i915/intel_dvo.c4
-rw-r--r--drivers/gpu/drm/i915/intel_hdmi.c3
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c8
-rw-r--r--drivers/gpu/drm/i915/intel_sdvo.c6
-rw-r--r--drivers/gpu/drm/i915/intel_tv.c12
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_connector.c8
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c20
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c3
-rw-r--r--include/drm/drm_crtc.h3
13 files changed, 56 insertions, 27 deletions
diff --git a/drivers/gpu/drm/drm_crtc_helper.c b/drivers/gpu/drm/drm_crtc_helper.c
index de152a58967d..fb6b70fc6572 100644
--- a/drivers/gpu/drm/drm_crtc_helper.c
+++ b/drivers/gpu/drm/drm_crtc_helper.c
@@ -103,7 +103,7 @@ int drm_helper_probe_single_connector_modes(struct drm_connector *connector,
103 if (connector->funcs->force) 103 if (connector->funcs->force)
104 connector->funcs->force(connector); 104 connector->funcs->force(connector);
105 } else { 105 } else {
106 connector->status = connector->funcs->detect(connector); 106 connector->status = connector->funcs->detect(connector, false);
107 drm_kms_helper_poll_enable(dev); 107 drm_kms_helper_poll_enable(dev);
108 } 108 }
109 109
@@ -866,7 +866,7 @@ static void output_poll_execute(struct work_struct *work)
866 !(connector->polled & DRM_CONNECTOR_POLL_HPD)) 866 !(connector->polled & DRM_CONNECTOR_POLL_HPD))
867 continue; 867 continue;
868 868
869 status = connector->funcs->detect(connector); 869 status = connector->funcs->detect(connector, true);
870 if (old_status != status) 870 if (old_status != status)
871 changed = true; 871 changed = true;
872 } 872 }
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 86118a742231..85da4c40694c 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -159,7 +159,7 @@ static ssize_t status_show(struct device *device,
159 struct drm_connector *connector = to_drm_connector(device); 159 struct drm_connector *connector = to_drm_connector(device);
160 enum drm_connector_status status; 160 enum drm_connector_status status;
161 161
162 status = connector->funcs->detect(connector); 162 status = connector->funcs->detect(connector, true);
163 return snprintf(buf, PAGE_SIZE, "%s\n", 163 return snprintf(buf, PAGE_SIZE, "%s\n",
164 drm_get_connector_status_name(status)); 164 drm_get_connector_status_name(status));
165} 165}
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index 4b7735196cd5..0350e5d711f8 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -400,7 +400,9 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder
400 return status; 400 return status;
401} 401}
402 402
403static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) 403static enum drm_connector_status
404intel_crt_detect(struct drm_connector *connector,
405 bool nondestructive)
404{ 406{
405 struct drm_device *dev = connector->dev; 407 struct drm_device *dev = connector->dev;
406 struct drm_encoder *encoder = intel_attached_encoder(connector); 408 struct drm_encoder *encoder = intel_attached_encoder(connector);
@@ -419,6 +421,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto
419 if (intel_crt_detect_ddc(encoder)) 421 if (intel_crt_detect_ddc(encoder))
420 return connector_status_connected; 422 return connector_status_connected;
421 423
424 if (nondestructive)
425 return connector->status;
426
422 /* for pre-945g platforms use load detect */ 427 /* for pre-945g platforms use load detect */
423 if (encoder->crtc && encoder->crtc->enabled) { 428 if (encoder->crtc && encoder->crtc->enabled) {
424 status = intel_crt_load_detect(encoder->crtc, intel_encoder); 429 status = intel_crt_load_detect(encoder->crtc, intel_encoder);
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 51d142939a26..e1a2a05fb838 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -1386,7 +1386,8 @@ ironlake_dp_detect(struct drm_connector *connector)
1386 * \return false if DP port is disconnected. 1386 * \return false if DP port is disconnected.
1387 */ 1387 */
1388static enum drm_connector_status 1388static enum drm_connector_status
1389intel_dp_detect(struct drm_connector *connector) 1389intel_dp_detect(struct drm_connector *connector,
1390 bool nondestructive)
1390{ 1391{
1391 struct drm_encoder *encoder = intel_attached_encoder(connector); 1392 struct drm_encoder *encoder = intel_attached_encoder(connector);
1392 struct intel_dp *intel_dp = enc_to_intel_dp(encoder); 1393 struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
diff --git a/drivers/gpu/drm/i915/intel_dvo.c b/drivers/gpu/drm/i915/intel_dvo.c
index a399f4b2c1c5..f0de1addf8a4 100644
--- a/drivers/gpu/drm/i915/intel_dvo.c
+++ b/drivers/gpu/drm/i915/intel_dvo.c
@@ -221,7 +221,9 @@ static void intel_dvo_mode_set(struct drm_encoder *encoder,
221 * 221 *
222 * Unimplemented. 222 * Unimplemented.
223 */ 223 */
224static enum drm_connector_status intel_dvo_detect(struct drm_connector *connector) 224static enum drm_connector_status
225intel_dvo_detect(struct drm_connector *connector,
226 bool nondestructive)
225{ 227{
226 struct drm_encoder *encoder = intel_attached_encoder(connector); 228 struct drm_encoder *encoder = intel_attached_encoder(connector);
227 struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder); 229 struct intel_dvo *intel_dvo = enc_to_intel_dvo(encoder);
diff --git a/drivers/gpu/drm/i915/intel_hdmi.c b/drivers/gpu/drm/i915/intel_hdmi.c
index ccd4c97e6524..2ea123d8d22b 100644
--- a/drivers/gpu/drm/i915/intel_hdmi.c
+++ b/drivers/gpu/drm/i915/intel_hdmi.c
@@ -139,7 +139,8 @@ static bool intel_hdmi_mode_fixup(struct drm_encoder *encoder,
139} 139}
140 140
141static enum drm_connector_status 141static enum drm_connector_status
142intel_hdmi_detect(struct drm_connector *connector) 142intel_hdmi_detect(struct drm_connector *connector,
143 bool nondestructive)
143{ 144{
144 struct drm_encoder *encoder = intel_attached_encoder(connector); 145 struct drm_encoder *encoder = intel_attached_encoder(connector);
145 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder); 146 struct intel_hdmi *intel_hdmi = enc_to_intel_hdmi(encoder);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 4fbb0165b26f..fb1bed8f4071 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -445,7 +445,9 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
445 * connected and closed means disconnected. We also send hotplug events as 445 * connected and closed means disconnected. We also send hotplug events as
446 * needed, using lid status notification from the input layer. 446 * needed, using lid status notification from the input layer.
447 */ 447 */
448static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) 448static enum drm_connector_status
449intel_lvds_detect(struct drm_connector *connector,
450 bool nondestructive)
449{ 451{
450 struct drm_device *dev = connector->dev; 452 struct drm_device *dev = connector->dev;
451 enum drm_connector_status status = connector_status_connected; 453 enum drm_connector_status status = connector_status_connected;
@@ -540,7 +542,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val,
540 * the LID nofication event. 542 * the LID nofication event.
541 */ 543 */
542 if (connector) 544 if (connector)
543 connector->status = connector->funcs->detect(connector); 545 connector->status = connector->funcs->detect(connector,
546 true);
547
544 /* Don't force modeset on machines where it causes a GPU lockup */ 548 /* Don't force modeset on machines where it causes a GPU lockup */
545 if (dmi_check_system(intel_no_modeset_on_lid)) 549 if (dmi_check_system(intel_no_modeset_on_lid))
546 return NOTIFY_OK; 550 return NOTIFY_OK;
diff --git a/drivers/gpu/drm/i915/intel_sdvo.c b/drivers/gpu/drm/i915/intel_sdvo.c
index e3b7a7ee39cb..db6b6d4b8fae 100644
--- a/drivers/gpu/drm/i915/intel_sdvo.c
+++ b/drivers/gpu/drm/i915/intel_sdvo.c
@@ -1417,7 +1417,7 @@ intel_analog_is_connected(struct drm_device *dev)
1417 if (!analog_connector) 1417 if (!analog_connector)
1418 return false; 1418 return false;
1419 1419
1420 if (analog_connector->funcs->detect(analog_connector) == 1420 if (analog_connector->funcs->detect(analog_connector, true) ==
1421 connector_status_disconnected) 1421 connector_status_disconnected)
1422 return false; 1422 return false;
1423 1423
@@ -1486,7 +1486,9 @@ intel_sdvo_hdmi_sink_detect(struct drm_connector *connector)
1486 return status; 1486 return status;
1487} 1487}
1488 1488
1489static enum drm_connector_status intel_sdvo_detect(struct drm_connector *connector) 1489static enum drm_connector_status
1490intel_sdvo_detect(struct drm_connector *connector,
1491 bool nondestructive)
1490{ 1492{
1491 uint16_t response; 1493 uint16_t response;
1492 struct drm_encoder *encoder = intel_attached_encoder(connector); 1494 struct drm_encoder *encoder = intel_attached_encoder(connector);
diff --git a/drivers/gpu/drm/i915/intel_tv.c b/drivers/gpu/drm/i915/intel_tv.c
index c671f60ce80b..d20b550c0f55 100644
--- a/drivers/gpu/drm/i915/intel_tv.c
+++ b/drivers/gpu/drm/i915/intel_tv.c
@@ -1341,7 +1341,8 @@ static void intel_tv_find_better_format(struct drm_connector *connector)
1341 * we have a pipe programmed in order to probe the TV. 1341 * we have a pipe programmed in order to probe the TV.
1342 */ 1342 */
1343static enum drm_connector_status 1343static enum drm_connector_status
1344intel_tv_detect(struct drm_connector *connector) 1344intel_tv_detect(struct drm_connector *connector,
1345 bool nondestructive)
1345{ 1346{
1346 struct drm_display_mode mode; 1347 struct drm_display_mode mode;
1347 struct drm_encoder *encoder = intel_attached_encoder(connector); 1348 struct drm_encoder *encoder = intel_attached_encoder(connector);
@@ -1353,7 +1354,7 @@ intel_tv_detect(struct drm_connector *connector)
1353 1354
1354 if (encoder->crtc && encoder->crtc->enabled) { 1355 if (encoder->crtc && encoder->crtc->enabled) {
1355 type = intel_tv_detect_type(intel_tv); 1356 type = intel_tv_detect_type(intel_tv);
1356 } else { 1357 } else if (nondestructive) {
1357 struct drm_crtc *crtc; 1358 struct drm_crtc *crtc;
1358 int dpms_mode; 1359 int dpms_mode;
1359 1360
@@ -1364,10 +1365,9 @@ intel_tv_detect(struct drm_connector *connector)
1364 intel_release_load_detect_pipe(&intel_tv->base, connector, 1365 intel_release_load_detect_pipe(&intel_tv->base, connector,
1365 dpms_mode); 1366 dpms_mode);
1366 } else 1367 } else
1367 type = -1; 1368 return connector_status_unknown;
1368 } 1369 } else
1369 1370 return connector->status;
1370 intel_tv->type = type;
1371 1371
1372 if (type < 0) 1372 if (type < 0)
1373 return connector_status_disconnected; 1373 return connector_status_disconnected;
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index a1473fff06ac..67d515cb67e0 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -168,7 +168,8 @@ nouveau_connector_set_encoder(struct drm_connector *connector,
168} 168}
169 169
170static enum drm_connector_status 170static enum drm_connector_status
171nouveau_connector_detect(struct drm_connector *connector) 171nouveau_connector_detect(struct drm_connector *connector,
172 bool nondestructive)
172{ 173{
173 struct drm_device *dev = connector->dev; 174 struct drm_device *dev = connector->dev;
174 struct nouveau_connector *nv_connector = nouveau_connector(connector); 175 struct nouveau_connector *nv_connector = nouveau_connector(connector);
@@ -246,7 +247,8 @@ detect_analog:
246} 247}
247 248
248static enum drm_connector_status 249static enum drm_connector_status
249nouveau_connector_detect_lvds(struct drm_connector *connector) 250nouveau_connector_detect_lvds(struct drm_connector *connector,
251 bool nondestructive)
250{ 252{
251 struct drm_device *dev = connector->dev; 253 struct drm_device *dev = connector->dev;
252 struct drm_nouveau_private *dev_priv = dev->dev_private; 254 struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -267,7 +269,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector)
267 269
268 /* Try retrieving EDID via DDC */ 270 /* Try retrieving EDID via DDC */
269 if (!dev_priv->vbios.fp_no_ddc) { 271 if (!dev_priv->vbios.fp_no_ddc) {
270 status = nouveau_connector_detect(connector); 272 status = nouveau_connector_detect(connector, nondestructive);
271 if (status == connector_status_connected) 273 if (status == connector_status_connected)
272 goto out; 274 goto out;
273 } 275 }
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index a9dd7847d96e..31d309a8e75b 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -481,7 +481,9 @@ static int radeon_lvds_mode_valid(struct drm_connector *connector,
481 return MODE_OK; 481 return MODE_OK;
482} 482}
483 483
484static enum drm_connector_status radeon_lvds_detect(struct drm_connector *connector) 484static enum drm_connector_status
485radeon_lvds_detect(struct drm_connector *connector,
486 bool nondestructive)
485{ 487{
486 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 488 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
487 struct drm_encoder *encoder = radeon_best_single_encoder(connector); 489 struct drm_encoder *encoder = radeon_best_single_encoder(connector);
@@ -594,7 +596,9 @@ static int radeon_vga_mode_valid(struct drm_connector *connector,
594 return MODE_OK; 596 return MODE_OK;
595} 597}
596 598
597static enum drm_connector_status radeon_vga_detect(struct drm_connector *connector) 599static enum drm_connector_status
600radeon_vga_detect(struct drm_connector *connector,
601 bool nondestructive)
598{ 602{
599 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 603 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
600 struct drm_encoder *encoder; 604 struct drm_encoder *encoder;
@@ -691,7 +695,9 @@ static int radeon_tv_mode_valid(struct drm_connector *connector,
691 return MODE_OK; 695 return MODE_OK;
692} 696}
693 697
694static enum drm_connector_status radeon_tv_detect(struct drm_connector *connector) 698static enum drm_connector_status
699radeon_tv_detect(struct drm_connector *connector,
700 bool nondestructive)
695{ 701{
696 struct drm_encoder *encoder; 702 struct drm_encoder *encoder;
697 struct drm_encoder_helper_funcs *encoder_funcs; 703 struct drm_encoder_helper_funcs *encoder_funcs;
@@ -748,7 +754,9 @@ static int radeon_dvi_get_modes(struct drm_connector *connector)
748 * we have to check if this analog encoder is shared with anyone else (TV) 754 * we have to check if this analog encoder is shared with anyone else (TV)
749 * if its shared we have to set the other connector to disconnected. 755 * if its shared we have to set the other connector to disconnected.
750 */ 756 */
751static enum drm_connector_status radeon_dvi_detect(struct drm_connector *connector) 757static enum drm_connector_status
758radeon_dvi_detect(struct drm_connector *connector,
759 bool nondestructive)
752{ 760{
753 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 761 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
754 struct drm_encoder *encoder = NULL; 762 struct drm_encoder *encoder = NULL;
@@ -972,7 +980,9 @@ static int radeon_dp_get_modes(struct drm_connector *connector)
972 return ret; 980 return ret;
973} 981}
974 982
975static enum drm_connector_status radeon_dp_detect(struct drm_connector *connector) 983static enum drm_connector_status
984radeon_dp_detect(struct drm_connector *connector,
985 bool nondestructive)
976{ 986{
977 struct radeon_connector *radeon_connector = to_radeon_connector(connector); 987 struct radeon_connector *radeon_connector = to_radeon_connector(connector);
978 enum drm_connector_status ret = connector_status_disconnected; 988 enum drm_connector_status ret = connector_status_disconnected;
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
index 2ff5cf78235f..a527c91c0ba6 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
@@ -335,7 +335,8 @@ static void vmw_ldu_connector_restore(struct drm_connector *connector)
335} 335}
336 336
337static enum drm_connector_status 337static enum drm_connector_status
338 vmw_ldu_connector_detect(struct drm_connector *connector) 338 vmw_ldu_connector_detect(struct drm_connector *connector,
339 bool nondestructive)
339{ 340{
340 if (vmw_connector_to_ldu(connector)->pref_active) 341 if (vmw_connector_to_ldu(connector)->pref_active)
341 return connector_status_connected; 342 return connector_status_connected;
diff --git a/include/drm/drm_crtc.h b/include/drm/drm_crtc.h
index c9f3cc5949a8..5536223fbac8 100644
--- a/include/drm/drm_crtc.h
+++ b/include/drm/drm_crtc.h
@@ -386,7 +386,8 @@ struct drm_connector_funcs {
386 void (*dpms)(struct drm_connector *connector, int mode); 386 void (*dpms)(struct drm_connector *connector, int mode);
387 void (*save)(struct drm_connector *connector); 387 void (*save)(struct drm_connector *connector);
388 void (*restore)(struct drm_connector *connector); 388 void (*restore)(struct drm_connector *connector);
389 enum drm_connector_status (*detect)(struct drm_connector *connector); 389 enum drm_connector_status (*detect)(struct drm_connector *connector,
390 bool nondestructive);
390 int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height); 391 int (*fill_modes)(struct drm_connector *connector, uint32_t max_width, uint32_t max_height);
391 int (*set_property)(struct drm_connector *connector, struct drm_property *property, 392 int (*set_property)(struct drm_connector *connector, struct drm_property *property,
392 uint64_t val); 393 uint64_t val);