mirror of
https://github.com/Fishwaldo/linux-bl808.git
synced 2025-06-08 07:35:04 +00:00
drm/i915: Block enabling FBC until flips have been completed
There is a small race window in which FBC can be enabled after pre_plane_update is called, but before the page flip has been queued or completed. Signed-off-by: Maarten Lankhorst <maarten.lankhorst@linux.intel.com> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=103167 Link: https://patchwork.freedesktop.org/patch/msgid/20180625163758.10871-1-maarten.lankhorst@linux.intel.com Reviewed-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
This commit is contained in:
parent
9512f985c3
commit
c9855a561a
2 changed files with 12 additions and 24 deletions
|
@ -512,6 +512,7 @@ struct intel_fbc {
|
||||||
|
|
||||||
bool enabled;
|
bool enabled;
|
||||||
bool active;
|
bool active;
|
||||||
|
bool flip_pending;
|
||||||
|
|
||||||
bool underrun_detected;
|
bool underrun_detected;
|
||||||
struct work_struct underrun_work;
|
struct work_struct underrun_work;
|
||||||
|
|
|
@ -924,13 +924,6 @@ static void intel_fbc_get_reg_params(struct intel_crtc *crtc,
|
||||||
32 * fbc->threshold) * 8;
|
32 * fbc->threshold) * 8;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool intel_fbc_reg_params_equal(struct intel_fbc_reg_params *params1,
|
|
||||||
struct intel_fbc_reg_params *params2)
|
|
||||||
{
|
|
||||||
/* We can use this since intel_fbc_get_reg_params() does a memset. */
|
|
||||||
return memcmp(params1, params2, sizeof(*params1)) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void intel_fbc_pre_update(struct intel_crtc *crtc,
|
void intel_fbc_pre_update(struct intel_crtc *crtc,
|
||||||
struct intel_crtc_state *crtc_state,
|
struct intel_crtc_state *crtc_state,
|
||||||
struct intel_plane_state *plane_state)
|
struct intel_plane_state *plane_state)
|
||||||
|
@ -953,6 +946,7 @@ void intel_fbc_pre_update(struct intel_crtc *crtc,
|
||||||
goto unlock;
|
goto unlock;
|
||||||
|
|
||||||
intel_fbc_update_state_cache(crtc, crtc_state, plane_state);
|
intel_fbc_update_state_cache(crtc, crtc_state, plane_state);
|
||||||
|
fbc->flip_pending = true;
|
||||||
|
|
||||||
deactivate:
|
deactivate:
|
||||||
intel_fbc_deactivate(dev_priv, reason);
|
intel_fbc_deactivate(dev_priv, reason);
|
||||||
|
@ -988,13 +982,15 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc)
|
||||||
{
|
{
|
||||||
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
struct drm_i915_private *dev_priv = to_i915(crtc->base.dev);
|
||||||
struct intel_fbc *fbc = &dev_priv->fbc;
|
struct intel_fbc *fbc = &dev_priv->fbc;
|
||||||
struct intel_fbc_reg_params old_params;
|
|
||||||
|
|
||||||
WARN_ON(!mutex_is_locked(&fbc->lock));
|
WARN_ON(!mutex_is_locked(&fbc->lock));
|
||||||
|
|
||||||
if (!fbc->enabled || fbc->crtc != crtc)
|
if (!fbc->enabled || fbc->crtc != crtc)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
fbc->flip_pending = false;
|
||||||
|
WARN_ON(fbc->active);
|
||||||
|
|
||||||
if (!i915_modparams.enable_fbc) {
|
if (!i915_modparams.enable_fbc) {
|
||||||
intel_fbc_deactivate(dev_priv, "disabled at runtime per module param");
|
intel_fbc_deactivate(dev_priv, "disabled at runtime per module param");
|
||||||
__intel_fbc_disable(dev_priv);
|
__intel_fbc_disable(dev_priv);
|
||||||
|
@ -1002,25 +998,16 @@ static void __intel_fbc_post_update(struct intel_crtc *crtc)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!intel_fbc_can_activate(crtc)) {
|
|
||||||
WARN_ON(fbc->active);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
old_params = fbc->params;
|
|
||||||
intel_fbc_get_reg_params(crtc, &fbc->params);
|
intel_fbc_get_reg_params(crtc, &fbc->params);
|
||||||
|
|
||||||
/* If the scanout has not changed, don't modify the FBC settings.
|
if (!intel_fbc_can_activate(crtc))
|
||||||
* Note that we make the fundamental assumption that the fb->obj
|
|
||||||
* cannot be unpinned (and have its GTT offset and fence revoked)
|
|
||||||
* without first being decoupled from the scanout and FBC disabled.
|
|
||||||
*/
|
|
||||||
if (fbc->active &&
|
|
||||||
intel_fbc_reg_params_equal(&old_params, &fbc->params))
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (!fbc->busy_bits) {
|
||||||
intel_fbc_deactivate(dev_priv, "FBC enabled (active or scheduled)");
|
intel_fbc_deactivate(dev_priv, "FBC enabled (active or scheduled)");
|
||||||
intel_fbc_schedule_activation(crtc);
|
intel_fbc_schedule_activation(crtc);
|
||||||
|
} else
|
||||||
|
intel_fbc_deactivate(dev_priv, "frontbuffer write");
|
||||||
}
|
}
|
||||||
|
|
||||||
void intel_fbc_post_update(struct intel_crtc *crtc)
|
void intel_fbc_post_update(struct intel_crtc *crtc)
|
||||||
|
@ -1085,7 +1072,7 @@ void intel_fbc_flush(struct drm_i915_private *dev_priv,
|
||||||
(frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) {
|
(frontbuffer_bits & intel_fbc_get_frontbuffer_bit(fbc))) {
|
||||||
if (fbc->active)
|
if (fbc->active)
|
||||||
intel_fbc_recompress(dev_priv);
|
intel_fbc_recompress(dev_priv);
|
||||||
else
|
else if (!fbc->flip_pending)
|
||||||
__intel_fbc_post_update(fbc->crtc);
|
__intel_fbc_post_update(fbc->crtc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue