[PATCH 5/7] drm/i915: fix FBC buffer size checks

Paulo Zanoni
2015-09-23T15:52:44Z

According to my experiments, the maximum sizes mentioned in the
specification delimit how far in the buffer the hardware tracking can
go. And the hardware seems to calculate the size based on the plane
address and x/y offsets we specify to it. So adjust the code to do the
proper checks.

On platforms that do the x/y offset adjustment trick it will be really
hard to reproduce a bug, but on the current SKL we can reproduce the
bug with igt/kms_frontbuffer_tracking/fbc-farfromfence. With this
patch, we'll go from "CRC assertion failure" to "FBC unexpectedly
disabled", which is still a failure on the test suite but is not a
perceived user bug - you will just not save as much power as you could
be if FBC is disabled.

Testcase: igt/kms_frontbuffer_tracking/fbc-farfromfence (SKL)
Signed-off-by: Paulo Zanoni <paulo.r.zanoni@intel.com>
---
drivers/gpu/drm/i915/intel_fbc.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_fbc.c b/drivers/gpu/drm/i915/intel_fbc.c
index 0c7b59b..2cc2528 100644
--- a/drivers/gpu/drm/i915/intel_fbc.c
+++ b/drivers/gpu/drm/i915/intel_fbc.c
@@ -758,7 +758,7 @@ static bool pixel_format_is_valid(struct drm_framebuffer *fb)
static bool size_is_valid(struct intel_crtc *crtc)
{
struct drm_i915_private *dev_priv = crtc->base.dev->dev_private;
- unsigned int max_w, max_h;
+ unsigned int tracked_w, tracked_h, max_w, max_h;

if (INTEL_INFO(dev_priv)->gen >= 8 || IS_HASWELL(dev_priv)) {
max_w = 4096;
@@ -771,8 +771,10 @@ static bool size_is_valid(struct intel_crtc *crtc)
max_h = 1536;
}

- return crtc->config->pipe_src_w <= max_w &&
- crtc->config->pipe_src_h <= max_h;
+ tracked_w = (crtc->base.primary->state->src_w >> 16) + crtc->adjusted_x;
+ tracked_h = (crtc->base.primary->state->src_h >> 16) + crtc->adjusted_y;
+
+ return tracked_w <= max_w && tracked_h <= max_h;
}

/**
--
2.5.1