Commit c1132367 authored by Andi Shyti's avatar Andi Shyti Committed by Chris Wilson
Browse files

drm/i915: Extract GT render sleep (rc6) management



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: default avatarAndi Shyti <andi.shyti@intel.com>
Cc: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarChris 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
parent a3f56e7d
Loading
Loading
Loading
Loading
+1 −0
Original line number Original line Diff line number Diff line
@@ -85,6 +85,7 @@ gt-y += \
	gt/intel_gt_pm_irq.o \
	gt/intel_gt_pm_irq.o \
	gt/intel_hangcheck.o \
	gt/intel_hangcheck.o \
	gt/intel_lrc.o \
	gt/intel_lrc.o \
	gt/intel_rc6.o \
	gt/intel_renderstate.o \
	gt/intel_renderstate.o \
	gt/intel_reset.o \
	gt/intel_reset.o \
	gt/intel_ringbuffer.o \
	gt/intel_ringbuffer.o \
+1 −1
Original line number Original line Diff line number Diff line
@@ -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)
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);
	return switch_to_kernel_context_sync(&i915->gt);
}
}


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


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


static struct drm_i915_gem_object *first_mm_object(struct list_head *list)
static struct drm_i915_gem_object *first_mm_object(struct list_head *list)
+1 −0
Original line number Original line Diff line number Diff line
@@ -11,6 +11,7 @@
#include "intel_engine_pool.h"
#include "intel_engine_pool.h"
#include "intel_gt.h"
#include "intel_gt.h"
#include "intel_gt_pm.h"
#include "intel_gt_pm.h"
#include "intel_rc6.h"


static int __engine_unpark(struct intel_wakeref *wf)
static int __engine_unpark(struct intel_wakeref *wf)
{
{
+4 −1
Original line number Original line Diff line number Diff line
@@ -7,6 +7,7 @@
#include "intel_gt.h"
#include "intel_gt.h"
#include "intel_gt_pm.h"
#include "intel_gt_pm.h"
#include "intel_mocs.h"
#include "intel_mocs.h"
#include "intel_rc6.h"
#include "intel_uncore.h"
#include "intel_uncore.h"
#include "intel_pm.h"
#include "intel_pm.h"


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


	intel_gt_pm_init(gt);

	return 0;
	return 0;
}
}


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


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


+62 −30
Original line number Original line Diff line number Diff line
@@ -11,6 +11,7 @@
#include "intel_gt.h"
#include "intel_gt.h"
#include "intel_gt_pm.h"
#include "intel_gt_pm.h"
#include "intel_pm.h"
#include "intel_pm.h"
#include "intel_rc6.h"
#include "intel_wakeref.h"
#include "intel_wakeref.h"


static void pm_notify(struct intel_gt *gt, int state)
static void pm_notify(struct intel_gt *gt, int state)
@@ -90,6 +91,16 @@ void intel_gt_pm_init_early(struct intel_gt *gt)
	BLOCKING_INIT_NOTIFIER_HEAD(&gt->pm_notifications);
	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)
static bool reset_engines(struct intel_gt *gt)
{
{
	if (INTEL_INFO(gt->i915)->gpu_reset_clobbers_display)
	if (INTEL_INFO(gt->i915)->gpu_reset_clobbers_display)
@@ -124,40 +135,14 @@ void intel_gt_sanitize(struct intel_gt *gt, bool force)
		__intel_engine_reset(engine, false);
		__intel_engine_reset(engine, false);
}
}


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

void intel_gt_pm_enable(struct intel_gt *gt)
{
{
	struct intel_engine_cs *engine;
	intel_sanitize_gt_powersave(gt->i915);
	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);
}
}


void intel_gt_pm_disable(struct intel_gt *gt)
void intel_gt_pm_fini(struct intel_gt *gt)
{
{
	if (is_mock_device(gt))
	intel_rc6_fini(&gt->rc6);
		return;

	intel_sanitize_gt_powersave(gt->i915);
}
}


int intel_gt_resume(struct intel_gt *gt)
int intel_gt_resume(struct intel_gt *gt)
@@ -173,6 +158,9 @@ int intel_gt_resume(struct intel_gt *gt)
	 * allowing us to fixup the user contexts on their first pin.
	 * allowing us to fixup the user contexts on their first pin.
	 */
	 */
	intel_gt_pm_get(gt);
	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) {
	for_each_engine(engine, gt->i915, id) {
		struct intel_context *ce;
		struct intel_context *ce;


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

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


	return err;
	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)
void intel_gt_runtime_suspend(struct intel_gt *gt)
{
{
	intel_uc_runtime_suspend(&gt->uc);
	intel_uc_runtime_suspend(&gt->uc);
@@ -213,3 +241,7 @@ int intel_gt_runtime_resume(struct intel_gt *gt)


	return intel_uc_runtime_resume(&gt->uc);
	return intel_uc_runtime_resume(&gt->uc);
}
}

#if IS_ENABLED(CONFIG_DRM_I915_SELFTEST)
#include "selftest_gt_pm.c"
#endif
Loading