Skip to content

Commit

Permalink
drm/i915: Lift intel_engines_resume() to callers
Browse files Browse the repository at this point in the history
Since the reset path wants to recover the engines itself, it only wants
to reinitialise the hardware using i915_gem_init_hw(). Pull the call to
intel_engines_resume() to the module init/resume path so we can avoid it
during reset.

Fixes: 79ffac8 ("drm/i915: Invert the GEM wakeref hierarchy")
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Cc: Imre Deak <imre.deak@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20190626154549.10066-3-chris@chris-wilson.co.uk
  • Loading branch information
Chris Wilson committed Jun 26, 2019
1 parent 1839890 commit 092be38
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 83 deletions.
7 changes: 4 additions & 3 deletions drivers/gpu/drm/i915/gem/i915_gem_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,14 +254,15 @@ void i915_gem_resume(struct drm_i915_private *i915)
i915_gem_restore_gtt_mappings(i915);
i915_gem_restore_fences(i915);

if (i915_gem_init_hw(i915))
goto err_wedged;

/*
* As we didn't flush the kernel context before suspend, we cannot
* guarantee that the context image is complete. So let's just reset
* it and start again.
*/
intel_gt_resume(&i915->gt);

if (i915_gem_init_hw(i915))
if (intel_gt_resume(&i915->gt))
goto err_wedged;

intel_uc_resume(i915);
Expand Down
24 changes: 0 additions & 24 deletions drivers/gpu/drm/i915/gt/intel_engine_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -142,27 +142,3 @@ void intel_engine_init__pm(struct intel_engine_cs *engine)
{
intel_wakeref_init(&engine->wakeref);
}

int intel_engines_resume(struct drm_i915_private *i915)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
int err = 0;

intel_gt_pm_get(&i915->gt);
for_each_engine(engine, i915, id) {
intel_engine_pm_get(engine);
engine->serial++; /* kernel context lost */
err = engine->resume(engine);
intel_engine_pm_put(engine);
if (err) {
dev_err(i915->drm.dev,
"Failed to restart %s (%d)\n",
engine->name, err);
break;
}
}
intel_gt_pm_put(&i915->gt);

return err;
}
2 changes: 0 additions & 2 deletions drivers/gpu/drm/i915/gt/intel_engine_pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,4 @@ void intel_engine_park(struct intel_engine_cs *engine);

void intel_engine_init__pm(struct intel_engine_cs *engine);

int intel_engines_resume(struct drm_i915_private *i915);

#endif /* INTEL_ENGINE_PM_H */
21 changes: 20 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_gt_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
*/

#include "i915_drv.h"
#include "intel_engine_pm.h"
#include "intel_gt_pm.h"
#include "intel_pm.h"
#include "intel_wakeref.h"
Expand Down Expand Up @@ -122,26 +123,44 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force)
intel_engine_reset(engine, false);
}

void intel_gt_resume(struct intel_gt *gt)
int intel_gt_resume(struct intel_gt *gt)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
int err = 0;

/*
* After resume, we may need to poke into the pinned kernel
* contexts to paper over any damage caused by the sudden suspend.
* Only the kernel contexts should remain pinned over suspend,
* allowing us to fixup the user contexts on their first pin.
*/
intel_gt_pm_get(gt);
for_each_engine(engine, gt->i915, id) {
struct intel_context *ce;

intel_engine_pm_get(engine);

ce = engine->kernel_context;
if (ce)
ce->ops->reset(ce);

ce = engine->preempt_context;
if (ce)
ce->ops->reset(ce);

engine->serial++; /* kernel context lost */
err = engine->resume(engine);

intel_engine_pm_put(engine);
if (err) {
dev_err(gt->i915->drm.dev,
"Failed to restart %s (%d)\n",
engine->name, err);
break;
}
}
intel_gt_pm_put(gt);

return err;
}
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/gt/intel_gt_pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,6 @@ void intel_gt_pm_put(struct intel_gt *gt);
void intel_gt_pm_init_early(struct intel_gt *gt);

void intel_gt_sanitize(struct intel_gt *gt, bool force);
void intel_gt_resume(struct intel_gt *gt);
int intel_gt_resume(struct intel_gt *gt);

#endif /* INTEL_GT_PM_H */
21 changes: 20 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -949,6 +949,21 @@ static int do_reset(struct drm_i915_private *i915,
return gt_reset(i915, stalled_mask);
}

static int resume(struct drm_i915_private *i915)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;
int ret;

for_each_engine(engine, i915, id) {
ret = engine->resume(engine);
if (ret)
return ret;
}

return 0;
}

/**
* i915_reset - reset chip after a hang
* @i915: #drm_i915_private to reset
Expand Down Expand Up @@ -1023,9 +1038,13 @@ void i915_reset(struct drm_i915_private *i915,
if (ret) {
DRM_ERROR("Failed to initialise HW following reset (%d)\n",
ret);
goto error;
goto taint;
}

ret = resume(i915);
if (ret)
goto taint;

i915_queue_hangcheck(i915);

finish:
Expand Down
71 changes: 20 additions & 51 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@
#include "gem/i915_gem_ioctls.h"
#include "gem/i915_gem_pm.h"
#include "gem/i915_gemfs.h"
#include "gt/intel_engine_pm.h"
#include "gt/intel_gt.h"
#include "gt/intel_gt_pm.h"
#include "gt/intel_mocs.h"
Expand Down Expand Up @@ -1192,12 +1191,17 @@ static void init_unused_rings(struct intel_gt *gt)
}
}

static int init_hw(struct intel_gt *gt)
int i915_gem_init_hw(struct drm_i915_private *i915)
{
struct drm_i915_private *i915 = gt->i915;
struct intel_uncore *uncore = gt->uncore;
struct intel_uncore *uncore = &i915->uncore;
struct intel_gt *gt = &i915->gt;
int ret;

BUG_ON(!i915->kernel_context);
ret = i915_terminally_wedged(i915);
if (ret)
return ret;

gt->last_init_time = ktime_get();

/* Double layer security blanket, see i915_gem_init() */
Expand Down Expand Up @@ -1248,51 +1252,10 @@ static int init_hw(struct intel_gt *gt)

intel_mocs_init_l3cc_table(gt);

intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);

return 0;

out:
intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);

return ret;
}

int i915_gem_init_hw(struct drm_i915_private *i915)
{
struct intel_uncore *uncore = &i915->uncore;
int ret;

BUG_ON(!i915->kernel_context);
ret = i915_terminally_wedged(i915);
if (ret)
return ret;

/* Double layer security blanket, see i915_gem_init() */
intel_uncore_forcewake_get(uncore, FORCEWAKE_ALL);

ret = init_hw(&i915->gt);
if (ret)
goto err_init;

/* Only when the HW is re-initialised, can we replay the requests */
ret = intel_engines_resume(i915);
if (ret)
goto err_engines;

intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);

intel_engines_set_scheduler_caps(i915);

return 0;

err_engines:
intel_uc_fini_hw(i915);
err_init:
out:
intel_uncore_forcewake_put(uncore, FORCEWAKE_ALL);

intel_engines_set_scheduler_caps(i915);

return ret;
}

Expand Down Expand Up @@ -1524,6 +1487,11 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
if (ret)
goto err_uc_init;

/* Only when the HW is re-initialised, can we replay the requests */
ret = intel_gt_resume(&dev_priv->gt);
if (ret)
goto err_init_hw;

/*
* Despite its name intel_init_clock_gating applies both display
* clock gating workarounds; GT mmio workarounds and the occasional
Expand All @@ -1537,20 +1505,20 @@ int i915_gem_init(struct drm_i915_private *dev_priv)

ret = intel_engines_verify_workarounds(dev_priv);
if (ret)
goto err_init_hw;
goto err_gt;

ret = __intel_engines_record_defaults(dev_priv);
if (ret)
goto err_init_hw;
goto err_gt;

if (i915_inject_load_failure()) {
ret = -ENODEV;
goto err_init_hw;
goto err_gt;
}

if (i915_inject_load_failure()) {
ret = -EIO;
goto err_init_hw;
goto err_gt;
}

intel_uncore_forcewake_put(&dev_priv->uncore, FORCEWAKE_ALL);
Expand All @@ -1564,7 +1532,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
* HW as irrevisibly wedged, but keep enough state around that the
* driver doesn't explode during runtime.
*/
err_init_hw:
err_gt:
mutex_unlock(&dev_priv->drm.struct_mutex);

i915_gem_set_wedged(dev_priv);
Expand All @@ -1574,6 +1542,7 @@ int i915_gem_init(struct drm_i915_private *dev_priv)
i915_gem_drain_workqueue(dev_priv);

mutex_lock(&dev_priv->drm.struct_mutex);
err_init_hw:
intel_uc_fini_hw(dev_priv);
err_uc_init:
intel_uc_fini(dev_priv);
Expand Down

0 comments on commit 092be38

Please sign in to comment.