drm/i915: Cleanup instdone collection

Consolidate the instdone logic so we can get a bit fancier. This patch also
removes the duplicated print of INSTDONE[0].

v2: (Imre)
- Rebased on top of hangcheck INSTDONE changes.
- Move all INSTDONE registers into a single struct, store it within the
  engine error struct during error capturing.

Signed-off-by: Ben Widawsky <ben@bwidawsk.net>
Signed-off-by: Imre Deak <imre.deak@intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1474379673-28326-1-git-send-email-imre.deak@intel.com
This commit is contained in:
Ben Widawsky
2016-09-20 16:54:32 +03:00
committed by Imre Deak
parent 51f592050a
commit d636951ec0
6 changed files with 150 additions and 61 deletions

View File

@@ -2545,18 +2545,36 @@ static void i915_reset_and_wakeup(struct drm_i915_private *dev_priv)
wake_up_all(&dev_priv->gpu_error.reset_queue);
}
static inline void
i915_err_print_instdone(struct drm_i915_private *dev_priv,
struct intel_instdone *instdone)
{
pr_err(" INSTDONE: 0x%08x\n", instdone->instdone);
if (INTEL_GEN(dev_priv) <= 3)
return;
pr_err(" SC_INSTDONE: 0x%08x\n", instdone->slice_common);
if (INTEL_GEN(dev_priv) <= 6)
return;
pr_err(" SAMPLER_INSTDONE: 0x%08x\n", instdone->sampler);
pr_err(" ROW_INSTDONE: 0x%08x\n", instdone->row);
}
static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv)
{
uint32_t instdone[I915_NUM_INSTDONE_REG];
struct intel_instdone instdone;
u32 eir = I915_READ(EIR);
int pipe, i;
int pipe;
if (!eir)
return;
pr_err("render error detected, EIR: 0x%08x\n", eir);
i915_get_extra_instdone(dev_priv, instdone);
i915_get_engine_instdone(dev_priv, RCS, &instdone);
if (IS_G4X(dev_priv)) {
if (eir & (GM45_ERROR_MEM_PRIV | GM45_ERROR_CP_PRIV)) {
@@ -2564,8 +2582,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv)
pr_err(" IPEIR: 0x%08x\n", I915_READ(IPEIR_I965));
pr_err(" IPEHR: 0x%08x\n", I915_READ(IPEHR_I965));
for (i = 0; i < ARRAY_SIZE(instdone); i++)
pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]);
i915_err_print_instdone(dev_priv, &instdone);
pr_err(" INSTPS: 0x%08x\n", I915_READ(INSTPS));
pr_err(" ACTHD: 0x%08x\n", I915_READ(ACTHD_I965));
I915_WRITE(IPEIR_I965, ipeir);
@@ -2600,8 +2617,7 @@ static void i915_report_and_clear_eir(struct drm_i915_private *dev_priv)
if (eir & I915_ERROR_INSTRUCTION) {
pr_err("instruction error\n");
pr_err(" INSTPM: 0x%08x\n", I915_READ(INSTPM));
for (i = 0; i < ARRAY_SIZE(instdone); i++)
pr_err(" INSTDONE_%d: 0x%08x\n", i, instdone[i]);
i915_err_print_instdone(dev_priv, &instdone);
if (INTEL_GEN(dev_priv) < 4) {
u32 ipeir = I915_READ(IPEIR);
@@ -2948,31 +2964,42 @@ static void semaphore_clear_deadlocks(struct drm_i915_private *dev_priv)
engine->hangcheck.deadlock = 0;
}
static bool instdone_unchanged(u32 current_instdone, u32 *old_instdone)
{
u32 tmp = current_instdone | *old_instdone;
bool unchanged;
unchanged = tmp == *old_instdone;
*old_instdone |= tmp;
return unchanged;
}
static bool subunits_stuck(struct intel_engine_cs *engine)
{
u32 instdone[I915_NUM_INSTDONE_REG];
struct drm_i915_private *dev_priv = engine->i915;
struct intel_instdone instdone;
struct intel_instdone *accu_instdone = &engine->hangcheck.instdone;
bool stuck;
int i;
if (engine->id != RCS)
return true;
i915_get_extra_instdone(engine->i915, instdone);
i915_get_engine_instdone(dev_priv, RCS, &instdone);
/* There might be unstable subunit states even when
* actual head is not moving. Filter out the unstable ones by
* accumulating the undone -> done transitions and only
* consider those as progress.
*/
stuck = true;
for (i = 0; i < I915_NUM_INSTDONE_REG; i++) {
const u32 tmp = instdone[i] | engine->hangcheck.instdone[i];
if (tmp != engine->hangcheck.instdone[i])
stuck = false;
engine->hangcheck.instdone[i] |= tmp;
}
stuck = instdone_unchanged(instdone.instdone,
&accu_instdone->instdone);
stuck &= instdone_unchanged(instdone.slice_common,
&accu_instdone->slice_common);
stuck &= instdone_unchanged(instdone.sampler,
&accu_instdone->sampler);
stuck &= instdone_unchanged(instdone.row,
&accu_instdone->row);
return stuck;
}
@@ -2983,7 +3010,7 @@ head_stuck(struct intel_engine_cs *engine, u64 acthd)
if (acthd != engine->hangcheck.acthd) {
/* Clear subunit states on head movement */
memset(engine->hangcheck.instdone, 0,
memset(&engine->hangcheck.instdone, 0,
sizeof(engine->hangcheck.instdone));
return HANGCHECK_ACTIVE;
@@ -3153,7 +3180,7 @@ static void i915_hangcheck_elapsed(struct work_struct *work)
/* Clear head and subunit states on seqno movement */
acthd = 0;
memset(engine->hangcheck.instdone, 0,
memset(&engine->hangcheck.instdone, 0,
sizeof(engine->hangcheck.instdone));
}