drm/i915: Sanitize shared dpll state

There seems to be no limit to the amount of gunk the firmware can
leave behind. Some platforms leave pch dplls on which are not in
active use at all. The example in the bug report is a Apple Macbook
Pro.

Note that this escape scrunity of the hw state checker until we've
tried to use this enabled, but unused pll since we did only check for
the inverse case of a in-used, but disabled pll.

v2: Add a WARN in the pll state checker which would have caught this
case.

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=66952
Reported-and-tested-by: shui yangwei <yangweix.shui@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
Daniel Vetter 2013-07-17 06:55:04 +02:00
parent 7dcd2677ea
commit 35c95375f6

View File

@ -8314,6 +8314,8 @@ check_shared_dpll_state(struct drm_device *dev)
pll->active, pll->refcount);
WARN(pll->active && !pll->on,
"pll in active use but not on in sw tracking\n");
WARN(pll->on && !pll->active,
"pll in on but not on in use in sw tracking\n");
WARN(pll->on != active,
"pll on state mismatch (expected %i, found %i)\n",
pll->on, active);
@ -9814,8 +9816,8 @@ static void intel_modeset_readout_hw_state(struct drm_device *dev)
}
pll->refcount = pll->active;
DRM_DEBUG_KMS("%s hw state readout: refcount %i\n",
pll->name, pll->refcount);
DRM_DEBUG_KMS("%s hw state readout: refcount %i, on %i\n",
pll->name, pll->refcount, pll->on);
}
list_for_each_entry(encoder, &dev->mode_config.encoder_list,
@ -9866,6 +9868,7 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
struct drm_plane *plane;
struct intel_crtc *crtc;
struct intel_encoder *encoder;
int i;
intel_modeset_readout_hw_state(dev);
@ -9881,6 +9884,18 @@ void intel_modeset_setup_hw_state(struct drm_device *dev,
intel_dump_pipe_config(crtc, &crtc->config, "[setup_hw_state]");
}
for (i = 0; i < dev_priv->num_shared_dpll; i++) {
struct intel_shared_dpll *pll = &dev_priv->shared_dplls[i];
if (!pll->on || pll->active)
continue;
DRM_DEBUG_KMS("%s enabled but not in use, disabling\n", pll->name);
pll->disable(dev_priv, pll);
pll->on = false;
}
if (force_restore) {
/*
* We need to use raw interfaces for restoring state to avoid