diff options
author | Jeff McGee <jeff.mcgee@intel.com> | 2014-02-04 12:32:31 -0500 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2014-02-07 04:25:10 -0500 |
commit | dd0a1aa19bd3d7203e58157b84cea78bbac605ac (patch) | |
tree | b59d3c4fc62b0c0b0a0757868167e31d17b19bf1 | |
parent | 1f70999f9052f5a1b0ce1a55aff3808f2ec9fe42 (diff) |
drm/i915: Restore rps/rc6 on reset
A check of rps/rc6 state after i915_reset determined that the ring
MAX_IDLE registers were returned to their hardware defaults and that
the GEN6_PMIMR register was set to mask all interrupts. This change
restores those values to their pre-reset states by re-initializing
rps/rc6 in i915_reset. A full re-initialization was opted for versus
a targeted set of restore operations for simplicity and maintain-
ability. Note that the re-initialization is not done for Ironlake,
due to a past comment that it causes problems.
Also updated the rps initialization sequence to preserve existing
min/max values in the case of a re-init. We assume the values were
validated upon being set and do not do further range checking. The
debugfs interface for changing min/max was updated with range
checking to ensure this condition (already present in sysfs
interface).
v2: fix rps logging to output hw_max and hw_min, not rps.max_delay
and rps.min_delay which don't strictly represent hardware limits.
Add igt testcase to signed-off-by section.
Testcase: igt/pm_rps/reset
Signed-off-by: Jeff McGee <jeff.mcgee@intel.com>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/i915_debugfs.c | 49 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 35 |
3 files changed, 76 insertions, 19 deletions
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c index bc8707f9656f..2dc05c30b800 100644 --- a/drivers/gpu/drm/i915/i915_debugfs.c +++ b/drivers/gpu/drm/i915/i915_debugfs.c | |||
@@ -3223,6 +3223,7 @@ i915_max_freq_set(void *data, u64 val) | |||
3223 | { | 3223 | { |
3224 | struct drm_device *dev = data; | 3224 | struct drm_device *dev = data; |
3225 | struct drm_i915_private *dev_priv = dev->dev_private; | 3225 | struct drm_i915_private *dev_priv = dev->dev_private; |
3226 | u32 rp_state_cap, hw_max, hw_min; | ||
3226 | int ret; | 3227 | int ret; |
3227 | 3228 | ||
3228 | if (!(IS_GEN6(dev) || IS_GEN7(dev))) | 3229 | if (!(IS_GEN6(dev) || IS_GEN7(dev))) |
@@ -3241,14 +3242,29 @@ i915_max_freq_set(void *data, u64 val) | |||
3241 | */ | 3242 | */ |
3242 | if (IS_VALLEYVIEW(dev)) { | 3243 | if (IS_VALLEYVIEW(dev)) { |
3243 | val = vlv_freq_opcode(dev_priv, val); | 3244 | val = vlv_freq_opcode(dev_priv, val); |
3244 | dev_priv->rps.max_delay = val; | 3245 | |
3245 | valleyview_set_rps(dev, val); | 3246 | hw_max = valleyview_rps_max_freq(dev_priv); |
3247 | hw_min = valleyview_rps_min_freq(dev_priv); | ||
3246 | } else { | 3248 | } else { |
3247 | do_div(val, GT_FREQUENCY_MULTIPLIER); | 3249 | do_div(val, GT_FREQUENCY_MULTIPLIER); |
3248 | dev_priv->rps.max_delay = val; | 3250 | |
3249 | gen6_set_rps(dev, val); | 3251 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); |
3252 | hw_max = dev_priv->rps.hw_max; | ||
3253 | hw_min = (rp_state_cap >> 16) & 0xff; | ||
3254 | } | ||
3255 | |||
3256 | if (val < hw_min || val > hw_max || val < dev_priv->rps.min_delay) { | ||
3257 | mutex_unlock(&dev_priv->rps.hw_lock); | ||
3258 | return -EINVAL; | ||
3250 | } | 3259 | } |
3251 | 3260 | ||
3261 | dev_priv->rps.max_delay = val; | ||
3262 | |||
3263 | if (IS_VALLEYVIEW(dev)) | ||
3264 | valleyview_set_rps(dev, val); | ||
3265 | else | ||
3266 | gen6_set_rps(dev, val); | ||
3267 | |||
3252 | mutex_unlock(&dev_priv->rps.hw_lock); | 3268 | mutex_unlock(&dev_priv->rps.hw_lock); |
3253 | 3269 | ||
3254 | return 0; | 3270 | return 0; |
@@ -3288,6 +3304,7 @@ i915_min_freq_set(void *data, u64 val) | |||
3288 | { | 3304 | { |
3289 | struct drm_device *dev = data; | 3305 | struct drm_device *dev = data; |
3290 | struct drm_i915_private *dev_priv = dev->dev_private; | 3306 | struct drm_i915_private *dev_priv = dev->dev_private; |
3307 | u32 rp_state_cap, hw_max, hw_min; | ||
3291 | int ret; | 3308 | int ret; |
3292 | 3309 | ||
3293 | if (!(IS_GEN6(dev) || IS_GEN7(dev))) | 3310 | if (!(IS_GEN6(dev) || IS_GEN7(dev))) |
@@ -3306,13 +3323,29 @@ i915_min_freq_set(void *data, u64 val) | |||
3306 | */ | 3323 | */ |
3307 | if (IS_VALLEYVIEW(dev)) { | 3324 | if (IS_VALLEYVIEW(dev)) { |
3308 | val = vlv_freq_opcode(dev_priv, val); | 3325 | val = vlv_freq_opcode(dev_priv, val); |
3309 | dev_priv->rps.min_delay = val; | 3326 | |
3310 | valleyview_set_rps(dev, val); | 3327 | hw_max = valleyview_rps_max_freq(dev_priv); |
3328 | hw_min = valleyview_rps_min_freq(dev_priv); | ||
3311 | } else { | 3329 | } else { |
3312 | do_div(val, GT_FREQUENCY_MULTIPLIER); | 3330 | do_div(val, GT_FREQUENCY_MULTIPLIER); |
3313 | dev_priv->rps.min_delay = val; | 3331 | |
3314 | gen6_set_rps(dev, val); | 3332 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); |
3333 | hw_max = dev_priv->rps.hw_max; | ||
3334 | hw_min = (rp_state_cap >> 16) & 0xff; | ||
3335 | } | ||
3336 | |||
3337 | if (val < hw_min || val > hw_max || val > dev_priv->rps.max_delay) { | ||
3338 | mutex_unlock(&dev_priv->rps.hw_lock); | ||
3339 | return -EINVAL; | ||
3315 | } | 3340 | } |
3341 | |||
3342 | dev_priv->rps.min_delay = val; | ||
3343 | |||
3344 | if (IS_VALLEYVIEW(dev)) | ||
3345 | valleyview_set_rps(dev, val); | ||
3346 | else | ||
3347 | gen6_set_rps(dev, val); | ||
3348 | |||
3316 | mutex_unlock(&dev_priv->rps.hw_lock); | 3349 | mutex_unlock(&dev_priv->rps.hw_lock); |
3317 | 3350 | ||
3318 | return 0; | 3351 | return 0; |
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 05072cf5a008..2d05d7ce4c29 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -728,6 +728,17 @@ int i915_reset(struct drm_device *dev) | |||
728 | 728 | ||
729 | drm_irq_uninstall(dev); | 729 | drm_irq_uninstall(dev); |
730 | drm_irq_install(dev); | 730 | drm_irq_install(dev); |
731 | |||
732 | /* rps/rc6 re-init is necessary to restore state lost after the | ||
733 | * reset and the re-install of drm irq. Skip for ironlake per | ||
734 | * previous concerns that it doesn't respond well to some forms | ||
735 | * of re-init after reset. */ | ||
736 | if (INTEL_INFO(dev)->gen > 5) { | ||
737 | mutex_lock(&dev->struct_mutex); | ||
738 | intel_enable_gt_powersave(dev); | ||
739 | mutex_unlock(&dev->struct_mutex); | ||
740 | } | ||
741 | |||
731 | intel_hpd_init(dev); | 742 | intel_hpd_init(dev); |
732 | } else { | 743 | } else { |
733 | mutex_unlock(&dev->struct_mutex); | 744 | mutex_unlock(&dev->struct_mutex); |
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 9ab388313d3d..6af58cd6d77c 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -3322,7 +3322,7 @@ static void gen6_enable_rps(struct drm_device *dev) | |||
3322 | { | 3322 | { |
3323 | struct drm_i915_private *dev_priv = dev->dev_private; | 3323 | struct drm_i915_private *dev_priv = dev->dev_private; |
3324 | struct intel_ring_buffer *ring; | 3324 | struct intel_ring_buffer *ring; |
3325 | u32 rp_state_cap; | 3325 | u32 rp_state_cap, hw_max, hw_min; |
3326 | u32 gt_perf_status; | 3326 | u32 gt_perf_status; |
3327 | u32 rc6vids, pcu_mbox, rc6_mask = 0; | 3327 | u32 rc6vids, pcu_mbox, rc6_mask = 0; |
3328 | u32 gtfifodbg; | 3328 | u32 gtfifodbg; |
@@ -3351,13 +3351,20 @@ static void gen6_enable_rps(struct drm_device *dev) | |||
3351 | gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | 3351 | gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); |
3352 | 3352 | ||
3353 | /* In units of 50MHz */ | 3353 | /* In units of 50MHz */ |
3354 | dev_priv->rps.hw_max = dev_priv->rps.max_delay = rp_state_cap & 0xff; | 3354 | dev_priv->rps.hw_max = hw_max = rp_state_cap & 0xff; |
3355 | dev_priv->rps.min_delay = (rp_state_cap >> 16) & 0xff; | 3355 | hw_min = (rp_state_cap >> 16) & 0xff; |
3356 | dev_priv->rps.rp1_delay = (rp_state_cap >> 8) & 0xff; | 3356 | dev_priv->rps.rp1_delay = (rp_state_cap >> 8) & 0xff; |
3357 | dev_priv->rps.rp0_delay = (rp_state_cap >> 0) & 0xff; | 3357 | dev_priv->rps.rp0_delay = (rp_state_cap >> 0) & 0xff; |
3358 | dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay; | 3358 | dev_priv->rps.rpe_delay = dev_priv->rps.rp1_delay; |
3359 | dev_priv->rps.cur_delay = 0; | 3359 | dev_priv->rps.cur_delay = 0; |
3360 | 3360 | ||
3361 | /* Preserve min/max settings in case of re-init */ | ||
3362 | if (dev_priv->rps.max_delay == 0) | ||
3363 | dev_priv->rps.max_delay = hw_max; | ||
3364 | |||
3365 | if (dev_priv->rps.min_delay == 0) | ||
3366 | dev_priv->rps.min_delay = hw_min; | ||
3367 | |||
3361 | /* disable the counters and set deterministic thresholds */ | 3368 | /* disable the counters and set deterministic thresholds */ |
3362 | I915_WRITE(GEN6_RC_CONTROL, 0); | 3369 | I915_WRITE(GEN6_RC_CONTROL, 0); |
3363 | 3370 | ||
@@ -3586,7 +3593,7 @@ static void valleyview_enable_rps(struct drm_device *dev) | |||
3586 | { | 3593 | { |
3587 | struct drm_i915_private *dev_priv = dev->dev_private; | 3594 | struct drm_i915_private *dev_priv = dev->dev_private; |
3588 | struct intel_ring_buffer *ring; | 3595 | struct intel_ring_buffer *ring; |
3589 | u32 gtfifodbg, val, rc6_mode = 0; | 3596 | u32 gtfifodbg, val, hw_max, hw_min, rc6_mode = 0; |
3590 | int i; | 3597 | int i; |
3591 | 3598 | ||
3592 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); | 3599 | WARN_ON(!mutex_is_locked(&dev_priv->rps.hw_lock)); |
@@ -3648,21 +3655,27 @@ static void valleyview_enable_rps(struct drm_device *dev) | |||
3648 | vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), | 3655 | vlv_gpu_freq(dev_priv, dev_priv->rps.cur_delay), |
3649 | dev_priv->rps.cur_delay); | 3656 | dev_priv->rps.cur_delay); |
3650 | 3657 | ||
3651 | dev_priv->rps.max_delay = valleyview_rps_max_freq(dev_priv); | 3658 | dev_priv->rps.hw_max = hw_max = valleyview_rps_max_freq(dev_priv); |
3652 | dev_priv->rps.hw_max = dev_priv->rps.max_delay; | ||
3653 | DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", | 3659 | DRM_DEBUG_DRIVER("max GPU freq: %d MHz (%u)\n", |
3654 | vlv_gpu_freq(dev_priv, dev_priv->rps.max_delay), | 3660 | vlv_gpu_freq(dev_priv, hw_max), |
3655 | dev_priv->rps.max_delay); | 3661 | hw_max); |
3656 | 3662 | ||
3657 | dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv); | 3663 | dev_priv->rps.rpe_delay = valleyview_rps_rpe_freq(dev_priv); |
3658 | DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n", | 3664 | DRM_DEBUG_DRIVER("RPe GPU freq: %d MHz (%u)\n", |
3659 | vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), | 3665 | vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), |
3660 | dev_priv->rps.rpe_delay); | 3666 | dev_priv->rps.rpe_delay); |
3661 | 3667 | ||
3662 | dev_priv->rps.min_delay = valleyview_rps_min_freq(dev_priv); | 3668 | hw_min = valleyview_rps_min_freq(dev_priv); |
3663 | DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", | 3669 | DRM_DEBUG_DRIVER("min GPU freq: %d MHz (%u)\n", |
3664 | vlv_gpu_freq(dev_priv, dev_priv->rps.min_delay), | 3670 | vlv_gpu_freq(dev_priv, hw_min), |
3665 | dev_priv->rps.min_delay); | 3671 | hw_min); |
3672 | |||
3673 | /* Preserve min/max settings in case of re-init */ | ||
3674 | if (dev_priv->rps.max_delay == 0) | ||
3675 | dev_priv->rps.max_delay = hw_max; | ||
3676 | |||
3677 | if (dev_priv->rps.min_delay == 0) | ||
3678 | dev_priv->rps.min_delay = hw_min; | ||
3666 | 3679 | ||
3667 | DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n", | 3680 | DRM_DEBUG_DRIVER("setting GPU freq to %d MHz (%u)\n", |
3668 | vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), | 3681 | vlv_gpu_freq(dev_priv, dev_priv->rps.rpe_delay), |