Commit 3490ea5de6ac4af309c3df8a26a5cca61306334c

Authored by Chris Wilson
Committed by Daniel Vetter
1 parent 48e858340d

drm/i915: Treat crtc->mode.clock == 0 as disabled

Prevent a divide-by-zero by consistently treating an 'active' CRTC
without a mode set as actually disabled.

This looks to have been first introduced with

commit 24929352481f085c5f85d4d4cbc919ddf106d381
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Mon Jul 2 20:28:59 2012 +0200

    drm/i915: read out the modeset hw state at load and resume time

but then combined with

commit b0a2658acb5bf9ca86b4aab011b7106de3af0add
Author: Daniel Vetter <daniel.vetter@ffwll.ch>
Date:   Tue Dec 18 09:37:54 2012 +0100

    drm/i915: don't disable disconnected outputs

it finally started oopsing.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reported-and-tested-by: Alexey Zaytsev <alexey.zaytsev@gmail.com>
Tested-by: Sedat Dilek <sedat.dilek@gmail.com>
Cc: Daniel Vetter <daniel.vetter@ffwll.ch>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: stable@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>

Showing 1 changed file with 16 additions and 9 deletions Side-by-side Diff

drivers/gpu/drm/i915/intel_pm.c
... ... @@ -44,6 +44,14 @@
44 44 * i915.i915_enable_fbc parameter
45 45 */
46 46  
  47 +static bool intel_crtc_active(struct drm_crtc *crtc)
  48 +{
  49 + /* Be paranoid as we can arrive here with only partial
  50 + * state retrieved from the hardware during setup.
  51 + */
  52 + return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock;
  53 +}
  54 +
47 55 static void i8xx_disable_fbc(struct drm_device *dev)
48 56 {
49 57 struct drm_i915_private *dev_priv = dev->dev_private;
... ... @@ -405,9 +413,8 @@
405 413 * - going to an unsupported config (interlace, pixel multiply, etc.)
406 414 */
407 415 list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
408   - if (to_intel_crtc(tmp_crtc)->active &&
409   - !to_intel_crtc(tmp_crtc)->primary_disabled &&
410   - tmp_crtc->fb) {
  416 + if (intel_crtc_active(tmp_crtc) &&
  417 + !to_intel_crtc(tmp_crtc)->primary_disabled) {
411 418 if (crtc) {
412 419 DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
413 420 dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
... ... @@ -992,7 +999,7 @@
992 999 struct drm_crtc *crtc, *enabled = NULL;
993 1000  
994 1001 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
995   - if (to_intel_crtc(crtc)->active && crtc->fb) {
  1002 + if (intel_crtc_active(crtc)) {
996 1003 if (enabled)
997 1004 return NULL;
998 1005 enabled = crtc;
... ... @@ -1086,7 +1093,7 @@
1086 1093 int entries, tlb_miss;
1087 1094  
1088 1095 crtc = intel_get_crtc_for_plane(dev, plane);
1089   - if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) {
  1096 + if (!intel_crtc_active(crtc)) {
1090 1097 *cursor_wm = cursor->guard_size;
1091 1098 *plane_wm = display->guard_size;
1092 1099 return false;
... ... @@ -1215,7 +1222,7 @@
1215 1222 int entries;
1216 1223  
1217 1224 crtc = intel_get_crtc_for_plane(dev, plane);
1218   - if (crtc->fb == NULL || !to_intel_crtc(crtc)->active)
  1225 + if (!intel_crtc_active(crtc))
1219 1226 return false;
1220 1227  
1221 1228 clock = crtc->mode.clock; /* VESA DOT Clock */
... ... @@ -1476,7 +1483,7 @@
1476 1483  
1477 1484 fifo_size = dev_priv->display.get_fifo_size(dev, 0);
1478 1485 crtc = intel_get_crtc_for_plane(dev, 0);
1479   - if (to_intel_crtc(crtc)->active && crtc->fb) {
  1486 + if (intel_crtc_active(crtc)) {
1480 1487 int cpp = crtc->fb->bits_per_pixel / 8;
1481 1488 if (IS_GEN2(dev))
1482 1489 cpp = 4;
... ... @@ -1490,7 +1497,7 @@
1490 1497  
1491 1498 fifo_size = dev_priv->display.get_fifo_size(dev, 1);
1492 1499 crtc = intel_get_crtc_for_plane(dev, 1);
1493   - if (to_intel_crtc(crtc)->active && crtc->fb) {
  1500 + if (intel_crtc_active(crtc)) {
1494 1501 int cpp = crtc->fb->bits_per_pixel / 8;
1495 1502 if (IS_GEN2(dev))
1496 1503 cpp = 4;
... ... @@ -2044,7 +2051,7 @@
2044 2051 int entries, tlb_miss;
2045 2052  
2046 2053 crtc = intel_get_crtc_for_plane(dev, plane);
2047   - if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) {
  2054 + if (!intel_crtc_active(crtc)) {
2048 2055 *sprite_wm = display->guard_size;
2049 2056 return false;
2050 2057 }