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

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
...@@ -525,6 +525,8 @@ static int i915_drm_thaw(struct drm_device *dev) ...@@ -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);
......
...@@ -1264,6 +1264,7 @@ void i915_handle_error(struct drm_device *dev, bool wedged); ...@@ -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);
......
...@@ -3965,6 +3965,12 @@ static void __gen6_gt_wait_for_thread_c0(struct drm_i915_private *dev_priv) ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment