Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16995a9f authored by Chris Wilson's avatar Chris Wilson Committed by Daniel Vetter
Browse files

drm/i915: Clear FORCEWAKE when taking over from BIOS



Some BIOSes may forcibly suspend RC6 during their operation which
trigger a warning as we find the hardware in a perplexing state upon
first use. So far that appears to be the worst symptom as fortuituously
we use the same values as the BIOS for programming the FORCEWAKE register.

Reported-by: default avatarOleksij Rempel <bug-track@fisher-privat.net>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarDaniel Vetter <daniel.vetter@ffwll.ch>
parent 7fdd74ab
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -525,6 +525,8 @@ static int i915_drm_thaw(struct drm_device *dev)
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_private *dev_priv = dev->dev_private;
	int error = 0;
	int error = 0;


	intel_gt_reset(dev);

	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
	if (drm_core_check_feature(dev, DRIVER_MODESET)) {
		mutex_lock(&dev->struct_mutex);
		mutex_lock(&dev->struct_mutex);
		i915_gem_restore_gtt_mappings(dev);
		i915_gem_restore_gtt_mappings(dev);
+1 −0
Original line number Original line Diff line number Diff line
@@ -1264,6 +1264,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged);


extern void intel_irq_init(struct drm_device *dev);
extern void intel_irq_init(struct drm_device *dev);
extern void intel_gt_init(struct drm_device *dev);
extern void intel_gt_init(struct drm_device *dev);
extern void intel_gt_reset(struct drm_device *dev);


void i915_error_state_free(struct kref *error_ref);
void i915_error_state_free(struct kref *error_ref);


+32 −0
Original line number Original line Diff line number Diff line
@@ -3965,6 +3965,12 @@ static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv)
		DRM_ERROR("GT thread status wait timed out\n");
		DRM_ERROR("GT thread status wait timed out\n");
}
}


static void __gen6_gt_force_wake_reset(struct drm_i915_private *dev_priv)
{
	I915_WRITE_NOTRACE(FORCEWAKE, 0);
	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
}

static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
{
{
	u32 forcewake_ack;
	u32 forcewake_ack;
@@ -3988,6 +3994,12 @@ static void __gen6_gt_force_wake_get(struct drm_i915_private *dev_priv)
	__gen6_gt_wait_for_thread_c0(dev_priv);
	__gen6_gt_wait_for_thread_c0(dev_priv);
}
}


static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
{
	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
}

static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
{
{
	u32 forcewake_ack;
	u32 forcewake_ack;
@@ -4083,6 +4095,11 @@ int __gen6_gt_wait_for_fifo(struct drm_i915_private *dev_priv)
	return ret;
	return ret;
}
}


static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
{
	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
}

static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
{
{
	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0,
	if (wait_for_atomic((I915_READ_NOTRACE(FORCEWAKE_ACK_VLV) & 1) == 0,
@@ -4105,12 +4122,27 @@ static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
	gen6_gt_check_fifodbg(dev_priv);
	gen6_gt_check_fifodbg(dev_priv);
}
}


void intel_gt_reset(struct drm_device *dev)
{
	struct drm_i915_private *dev_priv = dev->dev_private;

	if (IS_VALLEYVIEW(dev)) {
		vlv_force_wake_reset(dev_priv);
	} else if (INTEL_INFO(dev)->gen >= 6) {
		__gen6_gt_force_wake_reset(dev_priv);
		if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
			__gen6_gt_force_wake_mt_reset(dev_priv);
	}
}

void intel_gt_init(struct drm_device *dev)
void intel_gt_init(struct drm_device *dev)
{
{
	struct drm_i915_private *dev_priv = dev->dev_private;
	struct drm_i915_private *dev_priv = dev->dev_private;


	spin_lock_init(&dev_priv->gt_lock);
	spin_lock_init(&dev_priv->gt_lock);


	intel_gt_reset(dev);

	if (IS_VALLEYVIEW(dev)) {
	if (IS_VALLEYVIEW(dev)) {
		dev_priv->gt.force_wake_get = vlv_force_wake_get;
		dev_priv->gt.force_wake_get = vlv_force_wake_get;
		dev_priv->gt.force_wake_put = vlv_force_wake_put;
		dev_priv->gt.force_wake_put = vlv_force_wake_put;