Skip to content

Commit

Permalink
drm/i915: Extract GT render sleep (rc6) management
Browse files Browse the repository at this point in the history
Continuing the theme of breaking intel_pm.c up in a reasonable chunk of
powermanagement utilities, pull out the rc6 setup into its GT handler.

Based on a patch by Chris Wilson.

Signed-off-by: Andi Shyti <andi.shyti@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Link: https://patchwork.freedesktop.org/patch/msgid/20190919143840.20384-1-andi.shyti@intel.com
Link: https://patchwork.freedesktop.org/patch/msgid/20190927110849.28734-1-chris@chris-wilson.co.uk
  • Loading branch information
Andi Shyti authored and Chris Wilson committed Sep 27, 2019
1 parent a3f56e7 commit c113236
Show file tree
Hide file tree
Showing 18 changed files with 916 additions and 843 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ gt-y += \
gt/intel_gt_pm_irq.o \
gt/intel_hangcheck.o \
gt/intel_lrc.o \
gt/intel_rc6.o \
gt/intel_renderstate.o \
gt/intel_reset.o \
gt/intel_ringbuffer.o \
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/i915/gem/i915_gem_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,6 @@ static bool switch_to_kernel_context_sync(struct intel_gt *gt)

bool i915_gem_load_power_context(struct drm_i915_private *i915)
{
intel_gt_pm_enable(&i915->gt);
return switch_to_kernel_context_sync(&i915->gt);
}

Expand Down Expand Up @@ -188,6 +187,7 @@ void i915_gem_suspend(struct drm_i915_private *i915)
i915_gem_drain_freed_objects(i915);

intel_uc_suspend(&i915->gt.uc);
intel_gt_suspend(&i915->gt);
}

static struct drm_i915_gem_object *first_mm_object(struct list_head *list)
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/gt/intel_engine_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "intel_engine_pool.h"
#include "intel_gt.h"
#include "intel_gt_pm.h"
#include "intel_rc6.h"

static int __engine_unpark(struct intel_wakeref *wf)
{
Expand Down
5 changes: 4 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_gt.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "intel_gt.h"
#include "intel_gt_pm.h"
#include "intel_mocs.h"
#include "intel_rc6.h"
#include "intel_uncore.h"
#include "intel_pm.h"

Expand Down Expand Up @@ -369,6 +370,8 @@ int intel_gt_init(struct intel_gt *gt)
if (err)
return err;

intel_gt_pm_init(gt);

return 0;
}

Expand All @@ -387,8 +390,8 @@ void intel_gt_driver_release(struct intel_gt *gt)
{
/* Paranoia: make sure we have disabled everything before we exit. */
intel_gt_pm_disable(gt);
intel_gt_pm_fini(gt);

intel_cleanup_gt_powersave(gt->i915);
intel_gt_fini_scratch(gt);
}

Expand Down
92 changes: 62 additions & 30 deletions drivers/gpu/drm/i915/gt/intel_gt_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "intel_gt.h"
#include "intel_gt_pm.h"
#include "intel_pm.h"
#include "intel_rc6.h"
#include "intel_wakeref.h"

static void pm_notify(struct intel_gt *gt, int state)
Expand Down Expand Up @@ -90,6 +91,16 @@ void intel_gt_pm_init_early(struct intel_gt *gt)
BLOCKING_INIT_NOTIFIER_HEAD(&gt->pm_notifications);
}

void intel_gt_pm_init(struct intel_gt *gt)
{
/*
* Enabling power-management should be "self-healing". If we cannot
* enable a feature, simply leave it disabled with a notice to the
* user.
*/
intel_rc6_init(&gt->rc6);
}

static bool reset_engines(struct intel_gt *gt)
{
if (INTEL_INFO(gt->i915)->gpu_reset_clobbers_display)
Expand Down Expand Up @@ -124,40 +135,14 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force)
__intel_engine_reset(engine, false);
}

static bool is_mock_device(const struct intel_gt *gt)
{
return I915_SELFTEST_ONLY(gt->awake == -1);
}

void intel_gt_pm_enable(struct intel_gt *gt)
void intel_gt_pm_disable(struct intel_gt *gt)
{
struct intel_engine_cs *engine;
enum intel_engine_id id;

/* Powersaving is controlled by the host when inside a VM */
if (intel_vgpu_active(gt->i915))
return;

if (is_mock_device(gt))
return;

intel_gt_pm_get(gt);

for_each_engine(engine, gt->i915, id) {
intel_engine_pm_get(engine);
engine->serial++; /* force kernel context reload */
intel_engine_pm_put(engine);
}

intel_gt_pm_put(gt);
intel_sanitize_gt_powersave(gt->i915);
}

void intel_gt_pm_disable(struct intel_gt *gt)
void intel_gt_pm_fini(struct intel_gt *gt)
{
if (is_mock_device(gt))
return;

intel_sanitize_gt_powersave(gt->i915);
intel_rc6_fini(&gt->rc6);
}

int intel_gt_resume(struct intel_gt *gt)
Expand All @@ -173,6 +158,9 @@ int intel_gt_resume(struct intel_gt *gt)
* allowing us to fixup the user contexts on their first pin.
*/
intel_gt_pm_get(gt);
intel_uncore_forcewake_get(gt->uncore, FORCEWAKE_ALL);
intel_rc6_sanitize(&gt->rc6);

for_each_engine(engine, gt->i915, id) {
struct intel_context *ce;

Expand All @@ -197,11 +185,51 @@ int intel_gt_resume(struct intel_gt *gt)
break;
}
}

intel_rc6_enable(&gt->rc6);
intel_uncore_forcewake_put(gt->uncore, FORCEWAKE_ALL);
intel_gt_pm_put(gt);

return err;
}

static void wait_for_idle(struct intel_gt *gt)
{
mutex_lock(&gt->i915->drm.struct_mutex); /* XXX */
do {
if (i915_gem_wait_for_idle(gt->i915,
I915_WAIT_LOCKED,
I915_GEM_IDLE_TIMEOUT) == -ETIME) {
/* XXX hide warning from gem_eio */
if (i915_modparams.reset) {
dev_err(gt->i915->drm.dev,
"Failed to idle engines, declaring wedged!\n");
GEM_TRACE_DUMP();
}

/*
* Forcibly cancel outstanding work and leave
* the gpu quiet.
*/
intel_gt_set_wedged(gt);
}
} while (i915_retire_requests(gt->i915));
mutex_unlock(&gt->i915->drm.struct_mutex);

intel_gt_pm_wait_for_idle(gt);
}

void intel_gt_suspend(struct intel_gt *gt)
{
intel_wakeref_t wakeref;

/* We expect to be idle already; but also want to be independent */
wait_for_idle(gt);

with_intel_runtime_pm(&gt->i915->runtime_pm, wakeref)
intel_rc6_disable(&gt->rc6);
}

void intel_gt_runtime_suspend(struct intel_gt *gt)
{
intel_uc_runtime_suspend(&gt->uc);
Expand All @@ -213,3 +241,7 @@ int intel_gt_runtime_resume(struct intel_gt *gt)

return intel_uc_runtime_resume(&gt->uc);
}

#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftest_gt_pm.c"
#endif
11 changes: 10 additions & 1 deletion drivers/gpu/drm/i915/gt/intel_gt_pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,21 @@ static inline int intel_gt_pm_wait_for_idle(struct intel_gt *gt)
}

void intel_gt_pm_init_early(struct intel_gt *gt);
void intel_gt_pm_enable(struct intel_gt *gt);
void intel_gt_pm_init(struct intel_gt *gt);
void intel_gt_pm_disable(struct intel_gt *gt);
void intel_gt_pm_fini(struct intel_gt *gt);

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

int intel_gt_resume(struct intel_gt *gt);
void intel_gt_suspend(struct intel_gt *gt);

void intel_gt_runtime_suspend(struct intel_gt *gt);
int intel_gt_runtime_resume(struct intel_gt *gt);

static inline bool is_mock_gt(const struct intel_gt *gt)
{
return I915_SELFTEST_ONLY(gt->awake == -1);
}

#endif /* INTEL_GT_PM_H */
3 changes: 3 additions & 0 deletions drivers/gpu/drm/i915/gt/intel_gt_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "i915_vma.h"
#include "intel_engine_types.h"
#include "intel_reset_types.h"
#include "intel_rc6_types.h"
#include "intel_wakeref.h"

struct drm_i915_private;
Expand Down Expand Up @@ -67,6 +68,8 @@ struct intel_gt {
*/
intel_wakeref_t awake;

struct intel_rc6 rc6;

struct blocking_notifier_head pm_notifications;

ktime_t last_init_time;
Expand Down
Loading

0 comments on commit c113236

Please sign in to comment.