diff options
| -rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 4 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_gem_context.c | 48 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 18 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 3 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_pm.c | 28 | ||||
| -rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 3 |
6 files changed, 82 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index f990ab4c3efb..fc8cfddbf232 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
| @@ -811,6 +811,8 @@ int i915_reset(struct drm_device *dev) | |||
| 811 | if (!i915.reset) | 811 | if (!i915.reset) |
| 812 | return 0; | 812 | return 0; |
| 813 | 813 | ||
| 814 | intel_reset_gt_powersave(dev); | ||
| 815 | |||
| 814 | mutex_lock(&dev->struct_mutex); | 816 | mutex_lock(&dev->struct_mutex); |
| 815 | 817 | ||
| 816 | i915_gem_reset(dev); | 818 | i915_gem_reset(dev); |
| @@ -880,7 +882,7 @@ int i915_reset(struct drm_device *dev) | |||
| 880 | * of re-init after reset. | 882 | * of re-init after reset. |
| 881 | */ | 883 | */ |
| 882 | if (INTEL_INFO(dev)->gen > 5) | 884 | if (INTEL_INFO(dev)->gen > 5) |
| 883 | intel_reset_gt_powersave(dev); | 885 | intel_enable_gt_powersave(dev); |
| 884 | } else { | 886 | } else { |
| 885 | mutex_unlock(&dev->struct_mutex); | 887 | mutex_unlock(&dev->struct_mutex); |
| 886 | } | 888 | } |
diff --git a/drivers/gpu/drm/i915/i915_gem_context.c b/drivers/gpu/drm/i915/i915_gem_context.c index d17ff435f276..d011ec82ef1e 100644 --- a/drivers/gpu/drm/i915/i915_gem_context.c +++ b/drivers/gpu/drm/i915/i915_gem_context.c | |||
| @@ -473,7 +473,12 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 473 | u32 hw_flags) | 473 | u32 hw_flags) |
| 474 | { | 474 | { |
| 475 | u32 flags = hw_flags | MI_MM_SPACE_GTT; | 475 | u32 flags = hw_flags | MI_MM_SPACE_GTT; |
| 476 | int ret; | 476 | const int num_rings = |
| 477 | /* Use an extended w/a on ivb+ if signalling from other rings */ | ||
| 478 | i915_semaphore_is_enabled(ring->dev) ? | ||
| 479 | hweight32(INTEL_INFO(ring->dev)->ring_mask) - 1 : | ||
| 480 | 0; | ||
| 481 | int len, i, ret; | ||
| 477 | 482 | ||
| 478 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB | 483 | /* w/a: If Flush TLB Invalidation Mode is enabled, driver must do a TLB |
| 479 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value | 484 | * invalidation prior to MI_SET_CONTEXT. On GEN6 we don't set the value |
| @@ -490,15 +495,31 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 490 | if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) | 495 | if (!IS_HASWELL(ring->dev) && INTEL_INFO(ring->dev)->gen < 8) |
| 491 | flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); | 496 | flags |= (MI_SAVE_EXT_STATE_EN | MI_RESTORE_EXT_STATE_EN); |
| 492 | 497 | ||
| 493 | ret = intel_ring_begin(ring, 6); | 498 | |
| 499 | len = 4; | ||
| 500 | if (INTEL_INFO(ring->dev)->gen >= 7) | ||
| 501 | len += 2 + (num_rings ? 4*num_rings + 2 : 0); | ||
| 502 | |||
| 503 | ret = intel_ring_begin(ring, len); | ||
| 494 | if (ret) | 504 | if (ret) |
| 495 | return ret; | 505 | return ret; |
| 496 | 506 | ||
| 497 | /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ | 507 | /* WaProgramMiArbOnOffAroundMiSetContext:ivb,vlv,hsw,bdw,chv */ |
| 498 | if (INTEL_INFO(ring->dev)->gen >= 7) | 508 | if (INTEL_INFO(ring->dev)->gen >= 7) { |
| 499 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); | 509 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_DISABLE); |
| 500 | else | 510 | if (num_rings) { |
| 501 | intel_ring_emit(ring, MI_NOOP); | 511 | struct intel_engine_cs *signaller; |
| 512 | |||
| 513 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); | ||
| 514 | for_each_ring(signaller, to_i915(ring->dev), i) { | ||
| 515 | if (signaller == ring) | ||
| 516 | continue; | ||
| 517 | |||
| 518 | intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); | ||
| 519 | intel_ring_emit(ring, _MASKED_BIT_ENABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); | ||
| 520 | } | ||
| 521 | } | ||
| 522 | } | ||
| 502 | 523 | ||
| 503 | intel_ring_emit(ring, MI_NOOP); | 524 | intel_ring_emit(ring, MI_NOOP); |
| 504 | intel_ring_emit(ring, MI_SET_CONTEXT); | 525 | intel_ring_emit(ring, MI_SET_CONTEXT); |
| @@ -510,10 +531,21 @@ mi_set_context(struct intel_engine_cs *ring, | |||
| 510 | */ | 531 | */ |
| 511 | intel_ring_emit(ring, MI_NOOP); | 532 | intel_ring_emit(ring, MI_NOOP); |
| 512 | 533 | ||
| 513 | if (INTEL_INFO(ring->dev)->gen >= 7) | 534 | if (INTEL_INFO(ring->dev)->gen >= 7) { |
| 535 | if (num_rings) { | ||
| 536 | struct intel_engine_cs *signaller; | ||
| 537 | |||
| 538 | intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(num_rings)); | ||
| 539 | for_each_ring(signaller, to_i915(ring->dev), i) { | ||
| 540 | if (signaller == ring) | ||
| 541 | continue; | ||
| 542 | |||
| 543 | intel_ring_emit(ring, RING_PSMI_CTL(signaller->mmio_base)); | ||
| 544 | intel_ring_emit(ring, _MASKED_BIT_DISABLE(GEN6_PSMI_SLEEP_MSG_DISABLE)); | ||
| 545 | } | ||
| 546 | } | ||
| 514 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); | 547 | intel_ring_emit(ring, MI_ARB_ON_OFF | MI_ARB_ENABLE); |
| 515 | else | 548 | } |
| 516 | intel_ring_emit(ring, MI_NOOP); | ||
| 517 | 549 | ||
| 518 | intel_ring_advance(ring); | 550 | intel_ring_advance(ring); |
| 519 | 551 | ||
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index 981834b0f9b6..996c2931c499 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
| @@ -281,10 +281,14 @@ void gen6_enable_rps_interrupts(struct drm_device *dev) | |||
| 281 | struct drm_i915_private *dev_priv = dev->dev_private; | 281 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 282 | 282 | ||
| 283 | spin_lock_irq(&dev_priv->irq_lock); | 283 | spin_lock_irq(&dev_priv->irq_lock); |
| 284 | |||
| 284 | WARN_ON(dev_priv->rps.pm_iir); | 285 | WARN_ON(dev_priv->rps.pm_iir); |
| 285 | WARN_ON(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); | 286 | WARN_ON(I915_READ(gen6_pm_iir(dev_priv)) & dev_priv->pm_rps_events); |
| 286 | dev_priv->rps.interrupts_enabled = true; | 287 | dev_priv->rps.interrupts_enabled = true; |
| 288 | I915_WRITE(gen6_pm_ier(dev_priv), I915_READ(gen6_pm_ier(dev_priv)) | | ||
| 289 | dev_priv->pm_rps_events); | ||
| 287 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); | 290 | gen6_enable_pm_irq(dev_priv, dev_priv->pm_rps_events); |
| 291 | |||
| 288 | spin_unlock_irq(&dev_priv->irq_lock); | 292 | spin_unlock_irq(&dev_priv->irq_lock); |
| 289 | } | 293 | } |
| 290 | 294 | ||
| @@ -3307,8 +3311,10 @@ static void gen5_gt_irq_postinstall(struct drm_device *dev) | |||
| 3307 | GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); | 3311 | GEN5_IRQ_INIT(GT, dev_priv->gt_irq_mask, gt_irqs); |
| 3308 | 3312 | ||
| 3309 | if (INTEL_INFO(dev)->gen >= 6) { | 3313 | if (INTEL_INFO(dev)->gen >= 6) { |
| 3310 | pm_irqs |= dev_priv->pm_rps_events; | 3314 | /* |
| 3311 | 3315 | * RPS interrupts will get enabled/disabled on demand when RPS | |
| 3316 | * itself is enabled/disabled. | ||
| 3317 | */ | ||
| 3312 | if (HAS_VEBOX(dev)) | 3318 | if (HAS_VEBOX(dev)) |
| 3313 | pm_irqs |= PM_VEBOX_USER_INTERRUPT; | 3319 | pm_irqs |= PM_VEBOX_USER_INTERRUPT; |
| 3314 | 3320 | ||
| @@ -3520,7 +3526,11 @@ static void gen8_gt_irq_postinstall(struct drm_i915_private *dev_priv) | |||
| 3520 | dev_priv->pm_irq_mask = 0xffffffff; | 3526 | dev_priv->pm_irq_mask = 0xffffffff; |
| 3521 | GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); | 3527 | GEN8_IRQ_INIT_NDX(GT, 0, ~gt_interrupts[0], gt_interrupts[0]); |
| 3522 | GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); | 3528 | GEN8_IRQ_INIT_NDX(GT, 1, ~gt_interrupts[1], gt_interrupts[1]); |
| 3523 | GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, dev_priv->pm_rps_events); | 3529 | /* |
| 3530 | * RPS interrupts will get enabled/disabled on demand when RPS itself | ||
| 3531 | * is enabled/disabled. | ||
| 3532 | */ | ||
| 3533 | GEN8_IRQ_INIT_NDX(GT, 2, dev_priv->pm_irq_mask, 0); | ||
| 3524 | GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); | 3534 | GEN8_IRQ_INIT_NDX(GT, 3, ~gt_interrupts[3], gt_interrupts[3]); |
| 3525 | } | 3535 | } |
| 3526 | 3536 | ||
| @@ -3609,7 +3619,7 @@ static void vlv_display_irq_uninstall(struct drm_i915_private *dev_priv) | |||
| 3609 | 3619 | ||
| 3610 | vlv_display_irq_reset(dev_priv); | 3620 | vlv_display_irq_reset(dev_priv); |
| 3611 | 3621 | ||
| 3612 | dev_priv->irq_mask = 0; | 3622 | dev_priv->irq_mask = ~0; |
| 3613 | } | 3623 | } |
| 3614 | 3624 | ||
| 3615 | static void valleyview_irq_uninstall(struct drm_device *dev) | 3625 | static void valleyview_irq_uninstall(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index eefdc238f70b..172de3b3433b 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
| @@ -395,6 +395,7 @@ | |||
| 395 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) | 395 | #define PIPE_CONTROL_STORE_DATA_INDEX (1<<21) |
| 396 | #define PIPE_CONTROL_CS_STALL (1<<20) | 396 | #define PIPE_CONTROL_CS_STALL (1<<20) |
| 397 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) | 397 | #define PIPE_CONTROL_TLB_INVALIDATE (1<<18) |
| 398 | #define PIPE_CONTROL_MEDIA_STATE_CLEAR (1<<16) | ||
| 398 | #define PIPE_CONTROL_QW_WRITE (1<<14) | 399 | #define PIPE_CONTROL_QW_WRITE (1<<14) |
| 399 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) | 400 | #define PIPE_CONTROL_POST_SYNC_OP_MASK (3<<14) |
| 400 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) | 401 | #define PIPE_CONTROL_DEPTH_STALL (1<<13) |
| @@ -1128,6 +1129,7 @@ enum punit_power_well { | |||
| 1128 | #define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) | 1129 | #define GEN6_VERSYNC (RING_SYNC_1(VEBOX_RING_BASE)) |
| 1129 | #define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) | 1130 | #define GEN6_VEVSYNC (RING_SYNC_2(VEBOX_RING_BASE)) |
| 1130 | #define GEN6_NOSYNC 0 | 1131 | #define GEN6_NOSYNC 0 |
| 1132 | #define RING_PSMI_CTL(base) ((base)+0x50) | ||
| 1131 | #define RING_MAX_IDLE(base) ((base)+0x54) | 1133 | #define RING_MAX_IDLE(base) ((base)+0x54) |
| 1132 | #define RING_HWS_PGA(base) ((base)+0x80) | 1134 | #define RING_HWS_PGA(base) ((base)+0x80) |
| 1133 | #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) | 1135 | #define RING_HWS_PGA_GEN6(base) ((base)+0x2080) |
| @@ -1458,6 +1460,7 @@ enum punit_power_well { | |||
| 1458 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) | 1460 | #define GEN6_BLITTER_FBC_NOTIFY (1<<3) |
| 1459 | 1461 | ||
| 1460 | #define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050 | 1462 | #define GEN6_RC_SLEEP_PSMI_CONTROL 0x2050 |
| 1463 | #define GEN6_PSMI_SLEEP_MSG_DISABLE (1 << 0) | ||
| 1461 | #define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12) | 1464 | #define GEN8_RC_SEMA_IDLE_MSG_DISABLE (1 << 12) |
| 1462 | #define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10) | 1465 | #define GEN8_FF_DOP_CLOCK_GATE_DISABLE (1<<10) |
| 1463 | 1466 | ||
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 1f4b56e273c8..964b28e3c630 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c | |||
| @@ -6191,6 +6191,20 @@ void intel_cleanup_gt_powersave(struct drm_device *dev) | |||
| 6191 | valleyview_cleanup_gt_powersave(dev); | 6191 | valleyview_cleanup_gt_powersave(dev); |
| 6192 | } | 6192 | } |
| 6193 | 6193 | ||
| 6194 | static void gen6_suspend_rps(struct drm_device *dev) | ||
| 6195 | { | ||
| 6196 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
| 6197 | |||
| 6198 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); | ||
| 6199 | |||
| 6200 | /* | ||
| 6201 | * TODO: disable RPS interrupts on GEN9+ too once RPS support | ||
| 6202 | * is added for it. | ||
| 6203 | */ | ||
| 6204 | if (INTEL_INFO(dev)->gen < 9) | ||
| 6205 | gen6_disable_rps_interrupts(dev); | ||
| 6206 | } | ||
| 6207 | |||
| 6194 | /** | 6208 | /** |
| 6195 | * intel_suspend_gt_powersave - suspend PM work and helper threads | 6209 | * intel_suspend_gt_powersave - suspend PM work and helper threads |
| 6196 | * @dev: drm device | 6210 | * @dev: drm device |
| @@ -6206,14 +6220,7 @@ void intel_suspend_gt_powersave(struct drm_device *dev) | |||
| 6206 | if (INTEL_INFO(dev)->gen < 6) | 6220 | if (INTEL_INFO(dev)->gen < 6) |
| 6207 | return; | 6221 | return; |
| 6208 | 6222 | ||
| 6209 | flush_delayed_work(&dev_priv->rps.delayed_resume_work); | 6223 | gen6_suspend_rps(dev); |
| 6210 | |||
| 6211 | /* | ||
| 6212 | * TODO: disable RPS interrupts on GEN9+ too once RPS support | ||
| 6213 | * is added for it. | ||
| 6214 | */ | ||
| 6215 | if (INTEL_INFO(dev)->gen < 9) | ||
| 6216 | gen6_disable_rps_interrupts(dev); | ||
| 6217 | 6224 | ||
| 6218 | /* Force GPU to min freq during suspend */ | 6225 | /* Force GPU to min freq during suspend */ |
| 6219 | gen6_rps_idle(dev_priv); | 6226 | gen6_rps_idle(dev_priv); |
| @@ -6316,8 +6323,11 @@ void intel_reset_gt_powersave(struct drm_device *dev) | |||
| 6316 | { | 6323 | { |
| 6317 | struct drm_i915_private *dev_priv = dev->dev_private; | 6324 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 6318 | 6325 | ||
| 6326 | if (INTEL_INFO(dev)->gen < 6) | ||
| 6327 | return; | ||
| 6328 | |||
| 6329 | gen6_suspend_rps(dev); | ||
| 6319 | dev_priv->rps.enabled = false; | 6330 | dev_priv->rps.enabled = false; |
| 6320 | intel_enable_gt_powersave(dev); | ||
| 6321 | } | 6331 | } |
| 6322 | 6332 | ||
| 6323 | static void ibx_init_clock_gating(struct drm_device *dev) | 6333 | static void ibx_init_clock_gating(struct drm_device *dev) |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 9f445e9a75d1..c7bc93d28d84 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
| @@ -362,12 +362,15 @@ gen7_render_ring_flush(struct intel_engine_cs *ring, | |||
| 362 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; | 362 | flags |= PIPE_CONTROL_VF_CACHE_INVALIDATE; |
| 363 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; | 363 | flags |= PIPE_CONTROL_CONST_CACHE_INVALIDATE; |
| 364 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; | 364 | flags |= PIPE_CONTROL_STATE_CACHE_INVALIDATE; |
| 365 | flags |= PIPE_CONTROL_MEDIA_STATE_CLEAR; | ||
| 365 | /* | 366 | /* |
| 366 | * TLB invalidate requires a post-sync write. | 367 | * TLB invalidate requires a post-sync write. |
| 367 | */ | 368 | */ |
| 368 | flags |= PIPE_CONTROL_QW_WRITE; | 369 | flags |= PIPE_CONTROL_QW_WRITE; |
| 369 | flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; | 370 | flags |= PIPE_CONTROL_GLOBAL_GTT_IVB; |
| 370 | 371 | ||
| 372 | flags |= PIPE_CONTROL_STALL_AT_SCOREBOARD; | ||
| 373 | |||
| 371 | /* Workaround: we must issue a pipe_control with CS-stall bit | 374 | /* Workaround: we must issue a pipe_control with CS-stall bit |
| 372 | * set before a pipe_control command that has the state cache | 375 | * set before a pipe_control command that has the state cache |
| 373 | * invalidate bit set. */ | 376 | * invalidate bit set. */ |
