diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2012-04-28 03:56:39 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-05-24 11:54:00 -0400 |
commit | 7b9e0ae6da0a7eaf2680a1a788f08df123724f3b (patch) | |
tree | 34098c8670c181ac16210d7647057cbc22ceb6f1 /drivers/gpu/drm/i915/intel_pm.c | |
parent | 59d92bfa5f0cdf57f82f5181b0ad6af75c3fdf41 (diff) |
drm/i915: Always update RPS interrupts thresholds along with frequency
In order to avoid missed down-interrupts when coming out of RC6, it is
advised that we always reset the down-threshold upon a PM event. This is
due to that the PM unit goes through a little dance when coming out of
RC6, it first brings the GPU up at the lowest frequency then a short
time later it restores the thresholds. During that interval, the
down-interval may expire and the interrupt be suppressed.
Now aware of the dance taking place within the GPU when coming out of
RC6, one wonders what other writes need to be queued in the fifo buffer
in order to be properly sequenced; setting the RP state appears to be
one.
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=44006
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Acked-by: Ben Widawsky <ben@bwidawsk.net>
Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'drivers/gpu/drm/i915/intel_pm.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 57 |
1 files changed, 40 insertions, 17 deletions
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 8e79ff67ec98..bbca4e403b84 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
@@ -2270,10 +2270,33 @@ void ironlake_disable_drps(struct drm_device *dev) | |||
2270 | void gen6_set_rps(struct drm_device *dev, u8 val) | 2270 | void gen6_set_rps(struct drm_device *dev, u8 val) |
2271 | { | 2271 | { |
2272 | struct drm_i915_private *dev_priv = dev->dev_private; | 2272 | struct drm_i915_private *dev_priv = dev->dev_private; |
2273 | u32 swreq; | 2273 | u32 limits; |
2274 | 2274 | ||
2275 | swreq = (val & 0x3ff) << 25; | 2275 | limits = 0; |
2276 | I915_WRITE(GEN6_RPNSWREQ, swreq); | 2276 | if (val >= dev_priv->max_delay) |
2277 | val = dev_priv->max_delay; | ||
2278 | else | ||
2279 | limits |= dev_priv->max_delay << 24; | ||
2280 | |||
2281 | if (val <= dev_priv->min_delay) | ||
2282 | val = dev_priv->min_delay; | ||
2283 | else | ||
2284 | limits |= dev_priv->min_delay << 16; | ||
2285 | |||
2286 | if (val == dev_priv->cur_delay) | ||
2287 | return; | ||
2288 | |||
2289 | I915_WRITE(GEN6_RPNSWREQ, | ||
2290 | GEN6_FREQUENCY(val) | | ||
2291 | GEN6_OFFSET(0) | | ||
2292 | GEN6_AGGRESSIVE_TURBO); | ||
2293 | |||
2294 | /* Make sure we continue to get interrupts | ||
2295 | * until we hit the minimum or maximum frequencies. | ||
2296 | */ | ||
2297 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, limits); | ||
2298 | |||
2299 | dev_priv->cur_delay = val; | ||
2277 | } | 2300 | } |
2278 | 2301 | ||
2279 | void gen6_disable_rps(struct drm_device *dev) | 2302 | void gen6_disable_rps(struct drm_device *dev) |
@@ -2327,11 +2350,10 @@ int intel_enable_rc6(const struct drm_device *dev) | |||
2327 | void gen6_enable_rps(struct drm_i915_private *dev_priv) | 2350 | void gen6_enable_rps(struct drm_i915_private *dev_priv) |
2328 | { | 2351 | { |
2329 | struct intel_ring_buffer *ring; | 2352 | struct intel_ring_buffer *ring; |
2330 | u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | 2353 | u32 rp_state_cap; |
2331 | u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | 2354 | u32 gt_perf_status; |
2332 | u32 pcu_mbox, rc6_mask = 0; | 2355 | u32 pcu_mbox, rc6_mask = 0; |
2333 | u32 gtfifodbg; | 2356 | u32 gtfifodbg; |
2334 | int cur_freq, min_freq, max_freq; | ||
2335 | int rc6_mode; | 2357 | int rc6_mode; |
2336 | int i; | 2358 | int i; |
2337 | 2359 | ||
@@ -2352,6 +2374,14 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2352 | 2374 | ||
2353 | gen6_gt_force_wake_get(dev_priv); | 2375 | gen6_gt_force_wake_get(dev_priv); |
2354 | 2376 | ||
2377 | rp_state_cap = I915_READ(GEN6_RP_STATE_CAP); | ||
2378 | gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS); | ||
2379 | |||
2380 | /* In units of 100MHz */ | ||
2381 | dev_priv->max_delay = rp_state_cap & 0xff; | ||
2382 | dev_priv->min_delay = (rp_state_cap & 0xff0000) >> 16; | ||
2383 | dev_priv->cur_delay = 0; | ||
2384 | |||
2355 | /* disable the counters and set deterministic thresholds */ | 2385 | /* disable the counters and set deterministic thresholds */ |
2356 | I915_WRITE(GEN6_RC_CONTROL, 0); | 2386 | I915_WRITE(GEN6_RC_CONTROL, 0); |
2357 | 2387 | ||
@@ -2399,8 +2429,8 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2399 | 2429 | ||
2400 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); | 2430 | I915_WRITE(GEN6_RP_DOWN_TIMEOUT, 1000000); |
2401 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, | 2431 | I915_WRITE(GEN6_RP_INTERRUPT_LIMITS, |
2402 | 18 << 24 | | 2432 | dev_priv->max_delay << 24 | |
2403 | 6 << 16); | 2433 | dev_priv->min_delay << 16); |
2404 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); | 2434 | I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000); |
2405 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); | 2435 | I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000); |
2406 | I915_WRITE(GEN6_RP_UP_EI, 100000); | 2436 | I915_WRITE(GEN6_RP_UP_EI, 100000); |
@@ -2426,10 +2456,6 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2426 | 500)) | 2456 | 500)) |
2427 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); | 2457 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); |
2428 | 2458 | ||
2429 | min_freq = (rp_state_cap & 0xff0000) >> 16; | ||
2430 | max_freq = rp_state_cap & 0xff; | ||
2431 | cur_freq = (gt_perf_status & 0xff00) >> 8; | ||
2432 | |||
2433 | /* Check for overclock support */ | 2459 | /* Check for overclock support */ |
2434 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, | 2460 | if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0, |
2435 | 500)) | 2461 | 500)) |
@@ -2440,14 +2466,11 @@ void gen6_enable_rps(struct drm_i915_private *dev_priv) | |||
2440 | 500)) | 2466 | 500)) |
2441 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); | 2467 | DRM_ERROR("timeout waiting for pcode mailbox to finish\n"); |
2442 | if (pcu_mbox & (1<<31)) { /* OC supported */ | 2468 | if (pcu_mbox & (1<<31)) { /* OC supported */ |
2443 | max_freq = pcu_mbox & 0xff; | 2469 | dev_priv->max_delay = pcu_mbox & 0xff; |
2444 | DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); | 2470 | DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50); |
2445 | } | 2471 | } |
2446 | 2472 | ||
2447 | /* In units of 100MHz */ | 2473 | gen6_set_rps(dev_priv->dev, (gt_perf_status & 0xff00) >> 8); |
2448 | dev_priv->max_delay = max_freq; | ||
2449 | dev_priv->min_delay = min_freq; | ||
2450 | dev_priv->cur_delay = cur_freq; | ||
2451 | 2474 | ||
2452 | /* requires MSI enabled */ | 2475 | /* requires MSI enabled */ |
2453 | I915_WRITE(GEN6_PMIER, | 2476 | I915_WRITE(GEN6_PMIER, |