aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-02-09 11:15:32 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-02-09 12:04:54 -0500
commitac66808814036b4c33dd98091b2176ae6157f1a8 (patch)
treefe50cbfadd2ee322b0eed6c8c0bdf17970e7c3a8 /drivers
parent72389a33b8878e6091f7ab8080f5ed07054c7c39 (diff)
drm/i915: Disable RC6 on Ironlake
The automatic powersaving feature is once again causing havoc, with 100% reliable hangs on boot and resume on affected machines. Reported-by: Francesco Allertsen <fallertsen@gmail.com> Reported-by: Gui Rui <chaos.proton@gmail.com> Bugzilla: https://bugzilla.kernel.org/show_bug.cgi?id=28582 Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_drv.c5
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/intel_display.c92
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
4 files changed, 55 insertions, 44 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index cfb56d0ff367..0ad533f06af9 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -46,6 +46,9 @@ module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
46unsigned int i915_powersave = 1; 46unsigned int i915_powersave = 1;
47module_param_named(powersave, i915_powersave, int, 0600); 47module_param_named(powersave, i915_powersave, int, 0600);
48 48
49unsigned int i915_enable_rc6 = 0;
50module_param_named(i915_enable_rc6, i915_enable_rc6, int, 0600);
51
49unsigned int i915_lvds_downclock = 0; 52unsigned int i915_lvds_downclock = 0;
50module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400); 53module_param_named(lvds_downclock, i915_lvds_downclock, int, 0400);
51 54
@@ -360,7 +363,7 @@ static int i915_drm_thaw(struct drm_device *dev)
360 /* Resume the modeset for every activated CRTC */ 363 /* Resume the modeset for every activated CRTC */
361 drm_helper_resume_force_mode(dev); 364 drm_helper_resume_force_mode(dev);
362 365
363 if (dev_priv->renderctx && dev_priv->pwrctx) 366 if (IS_IRONLAKE_M(dev))
364 ironlake_enable_rc6(dev); 367 ironlake_enable_rc6(dev);
365 } 368 }
366 369
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index a0149c619cdd..65dfe81d0035 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -958,6 +958,7 @@ extern unsigned int i915_fbpercrtc;
958extern unsigned int i915_powersave; 958extern unsigned int i915_powersave;
959extern unsigned int i915_lvds_downclock; 959extern unsigned int i915_lvds_downclock;
960extern unsigned int i915_panel_use_ssc; 960extern unsigned int i915_panel_use_ssc;
961extern unsigned int i915_enable_rc6;
961 962
962extern int i915_suspend(struct drm_device *dev, pm_message_t state); 963extern int i915_suspend(struct drm_device *dev, pm_message_t state);
963extern int i915_resume(struct drm_device *dev); 964extern int i915_resume(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 7e42aa586504..94622e3a202e 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -6463,52 +6463,60 @@ void intel_enable_clock_gating(struct drm_device *dev)
6463 } 6463 }
6464} 6464}
6465 6465
6466void intel_disable_clock_gating(struct drm_device *dev) 6466static void ironlake_teardown_rc6(struct drm_device *dev)
6467{ 6467{
6468 struct drm_i915_private *dev_priv = dev->dev_private; 6468 struct drm_i915_private *dev_priv = dev->dev_private;
6469 6469
6470 if (dev_priv->renderctx) { 6470 if (dev_priv->renderctx) {
6471 struct drm_i915_gem_object *obj = dev_priv->renderctx; 6471 i915_gem_object_unpin(dev_priv->renderctx);
6472 6472 drm_gem_object_unreference(&dev_priv->renderctx->base);
6473 I915_WRITE(CCID, 0);
6474 POSTING_READ(CCID);
6475
6476 i915_gem_object_unpin(obj);
6477 drm_gem_object_unreference(&obj->base);
6478 dev_priv->renderctx = NULL; 6473 dev_priv->renderctx = NULL;
6479 } 6474 }
6480 6475
6481 if (dev_priv->pwrctx) { 6476 if (dev_priv->pwrctx) {
6482 struct drm_i915_gem_object *obj = dev_priv->pwrctx; 6477 i915_gem_object_unpin(dev_priv->pwrctx);
6478 drm_gem_object_unreference(&dev_priv->pwrctx->base);
6479 dev_priv->pwrctx = NULL;
6480 }
6481}
6482
6483static void ironlake_disable_rc6(struct drm_device *dev)
6484{
6485 struct drm_i915_private *dev_priv = dev->dev_private;
6486
6487 if (I915_READ(PWRCTXA)) {
6488 /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */
6489 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT);
6490 wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON),
6491 50);
6483 6492
6484 I915_WRITE(PWRCTXA, 0); 6493 I915_WRITE(PWRCTXA, 0);
6485 POSTING_READ(PWRCTXA); 6494 POSTING_READ(PWRCTXA);
6486 6495
6487 i915_gem_object_unpin(obj); 6496 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
6488 drm_gem_object_unreference(&obj->base); 6497 POSTING_READ(RSTDBYCTL);
6489 dev_priv->pwrctx = NULL;
6490 } 6498 }
6499
6500 ironlake_disable_rc6(dev);
6491} 6501}
6492 6502
6493static void ironlake_disable_rc6(struct drm_device *dev) 6503static int ironlake_setup_rc6(struct drm_device *dev)
6494{ 6504{
6495 struct drm_i915_private *dev_priv = dev->dev_private; 6505 struct drm_i915_private *dev_priv = dev->dev_private;
6496 6506
6497 /* Wake the GPU, prevent RC6, then restore RSTDBYCTL */ 6507 if (dev_priv->renderctx == NULL)
6498 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) | RCX_SW_EXIT); 6508 dev_priv->renderctx = intel_alloc_context_page(dev);
6499 wait_for(((I915_READ(RSTDBYCTL) & RSX_STATUS_MASK) == RSX_STATUS_ON), 6509 if (!dev_priv->renderctx)
6500 10); 6510 return -ENOMEM;
6501 POSTING_READ(CCID); 6511
6502 I915_WRITE(PWRCTXA, 0); 6512 if (dev_priv->pwrctx == NULL)
6503 POSTING_READ(PWRCTXA); 6513 dev_priv->pwrctx = intel_alloc_context_page(dev);
6504 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); 6514 if (!dev_priv->pwrctx) {
6505 POSTING_READ(RSTDBYCTL); 6515 ironlake_teardown_rc6(dev);
6506 i915_gem_object_unpin(dev_priv->renderctx); 6516 return -ENOMEM;
6507 drm_gem_object_unreference(&dev_priv->renderctx->base); 6517 }
6508 dev_priv->renderctx = NULL; 6518
6509 i915_gem_object_unpin(dev_priv->pwrctx); 6519 return 0;
6510 drm_gem_object_unreference(&dev_priv->pwrctx->base);
6511 dev_priv->pwrctx = NULL;
6512} 6520}
6513 6521
6514void ironlake_enable_rc6(struct drm_device *dev) 6522void ironlake_enable_rc6(struct drm_device *dev)
@@ -6516,15 +6524,26 @@ void ironlake_enable_rc6(struct drm_device *dev)
6516 struct drm_i915_private *dev_priv = dev->dev_private; 6524 struct drm_i915_private *dev_priv = dev->dev_private;
6517 int ret; 6525 int ret;
6518 6526
6527 /* rc6 disabled by default due to repeated reports of hanging during
6528 * boot and resume.
6529 */
6530 if (!i915_enable_rc6)
6531 return;
6532
6533 ret = ironlake_setup_rc6(dev);
6534 if (ret)
6535 return;
6536
6519 /* 6537 /*
6520 * GPU can automatically power down the render unit if given a page 6538 * GPU can automatically power down the render unit if given a page
6521 * to save state. 6539 * to save state.
6522 */ 6540 */
6523 ret = BEGIN_LP_RING(6); 6541 ret = BEGIN_LP_RING(6);
6524 if (ret) { 6542 if (ret) {
6525 ironlake_disable_rc6(dev); 6543 ironlake_teardown_rc6(dev);
6526 return; 6544 return;
6527 } 6545 }
6546
6528 OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN); 6547 OUT_RING(MI_SUSPEND_FLUSH | MI_SUSPEND_FLUSH_EN);
6529 OUT_RING(MI_SET_CONTEXT); 6548 OUT_RING(MI_SET_CONTEXT);
6530 OUT_RING(dev_priv->renderctx->gtt_offset | 6549 OUT_RING(dev_priv->renderctx->gtt_offset |
@@ -6541,6 +6560,7 @@ void ironlake_enable_rc6(struct drm_device *dev)
6541 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT); 6560 I915_WRITE(RSTDBYCTL, I915_READ(RSTDBYCTL) & ~RCX_SW_EXIT);
6542} 6561}
6543 6562
6563
6544/* Set up chip specific display functions */ 6564/* Set up chip specific display functions */
6545static void intel_init_display(struct drm_device *dev) 6565static void intel_init_display(struct drm_device *dev)
6546{ 6566{
@@ -6783,21 +6803,9 @@ void intel_modeset_init(struct drm_device *dev)
6783 if (IS_GEN6(dev)) 6803 if (IS_GEN6(dev))
6784 gen6_enable_rps(dev_priv); 6804 gen6_enable_rps(dev_priv);
6785 6805
6786 if (IS_IRONLAKE_M(dev)) { 6806 if (IS_IRONLAKE_M(dev))
6787 dev_priv->renderctx = intel_alloc_context_page(dev);
6788 if (!dev_priv->renderctx)
6789 goto skip_rc6;
6790 dev_priv->pwrctx = intel_alloc_context_page(dev);
6791 if (!dev_priv->pwrctx) {
6792 i915_gem_object_unpin(dev_priv->renderctx);
6793 drm_gem_object_unreference(&dev_priv->renderctx->base);
6794 dev_priv->renderctx = NULL;
6795 goto skip_rc6;
6796 }
6797 ironlake_enable_rc6(dev); 6807 ironlake_enable_rc6(dev);
6798 }
6799 6808
6800skip_rc6:
6801 INIT_WORK(&dev_priv->idle_work, intel_idle_update); 6809 INIT_WORK(&dev_priv->idle_work, intel_idle_update);
6802 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer, 6810 setup_timer(&dev_priv->idle_timer, intel_gpu_idle_timer,
6803 (unsigned long)dev); 6811 (unsigned long)dev);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 74db2557d644..2c431049963c 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -298,7 +298,6 @@ extern void intel_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
298extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green, 298extern void intel_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
299 u16 *blue, int regno); 299 u16 *blue, int regno);
300extern void intel_enable_clock_gating(struct drm_device *dev); 300extern void intel_enable_clock_gating(struct drm_device *dev);
301extern void intel_disable_clock_gating(struct drm_device *dev);
302extern void ironlake_enable_drps(struct drm_device *dev); 301extern void ironlake_enable_drps(struct drm_device *dev);
303extern void ironlake_disable_drps(struct drm_device *dev); 302extern void ironlake_disable_drps(struct drm_device *dev);
304extern void gen6_enable_rps(struct drm_i915_private *dev_priv); 303extern void gen6_enable_rps(struct drm_i915_private *dev_priv);