diff options
Diffstat (limited to 'drivers/gpu/drm/i915/gt/intel_rps.c')
-rw-r--r-- | drivers/gpu/drm/i915/gt/intel_rps.c | 123 |
1 files changed, 77 insertions, 46 deletions
diff --git a/drivers/gpu/drm/i915/gt/intel_rps.c b/drivers/gpu/drm/i915/gt/intel_rps.c index 20d6ee148afc..d2a3d935d186 100644 --- a/drivers/gpu/drm/i915/gt/intel_rps.c +++ b/drivers/gpu/drm/i915/gt/intel_rps.c @@ -37,6 +37,11 @@ static u32 rps_pm_sanitize_mask(struct intel_rps *rps, u32 mask) return mask & ~rps->pm_intrmsk_mbz; } +static inline void set(struct intel_uncore *uncore, i915_reg_t reg, u32 val) +{ + intel_uncore_write_fw(uncore, reg, val); +} + static u32 rps_pm_mask(struct intel_rps *rps, u8 val) { u32 mask = 0; @@ -78,8 +83,7 @@ static void rps_enable_interrupts(struct intel_rps *rps) gen6_gt_pm_enable_irq(gt, rps->pm_events); spin_unlock_irq(>->irq_lock); - intel_uncore_write(gt->uncore, GEN6_PMINTRMSK, - rps_pm_mask(rps, rps->cur_freq)); + set(gt->uncore, GEN6_PMINTRMSK, rps_pm_mask(rps, rps->cur_freq)); } static void gen6_rps_reset_interrupts(struct intel_rps *rps) @@ -113,8 +117,7 @@ static void rps_disable_interrupts(struct intel_rps *rps) rps->pm_events = 0; - intel_uncore_write(gt->uncore, GEN6_PMINTRMSK, - rps_pm_sanitize_mask(rps, ~0u)); + set(gt->uncore, GEN6_PMINTRMSK, rps_pm_sanitize_mask(rps, ~0u)); spin_lock_irq(>->irq_lock); gen6_gt_pm_disable_irq(gt, GEN6_PM_RPS_EVENTS); @@ -573,25 +576,21 @@ static void rps_set_power(struct intel_rps *rps, int new_power) if (IS_VALLEYVIEW(i915)) goto skip_hw_write; - intel_uncore_write(uncore, GEN6_RP_UP_EI, - GT_INTERVAL_FROM_US(i915, ei_up)); - intel_uncore_write(uncore, GEN6_RP_UP_THRESHOLD, - GT_INTERVAL_FROM_US(i915, - ei_up * threshold_up / 100)); - - intel_uncore_write(uncore, GEN6_RP_DOWN_EI, - GT_INTERVAL_FROM_US(i915, ei_down)); - intel_uncore_write(uncore, GEN6_RP_DOWN_THRESHOLD, - GT_INTERVAL_FROM_US(i915, - ei_down * threshold_down / 100)); - - intel_uncore_write(uncore, GEN6_RP_CONTROL, - (INTEL_GEN(i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) | - GEN6_RP_MEDIA_HW_NORMAL_MODE | - GEN6_RP_MEDIA_IS_GFX | - GEN6_RP_ENABLE | - GEN6_RP_UP_BUSY_AVG | - GEN6_RP_DOWN_IDLE_AVG); + set(uncore, GEN6_RP_UP_EI, GT_INTERVAL_FROM_US(i915, ei_up)); + set(uncore, GEN6_RP_UP_THRESHOLD, + GT_INTERVAL_FROM_US(i915, ei_up * threshold_up / 100)); + + set(uncore, GEN6_RP_DOWN_EI, GT_INTERVAL_FROM_US(i915, ei_down)); + set(uncore, GEN6_RP_DOWN_THRESHOLD, + GT_INTERVAL_FROM_US(i915, ei_down * threshold_down / 100)); + + set(uncore, GEN6_RP_CONTROL, + (INTEL_GEN(i915) > 9 ? 0 : GEN6_RP_MEDIA_TURBO) | + GEN6_RP_MEDIA_HW_NORMAL_MODE | + GEN6_RP_MEDIA_IS_GFX | + GEN6_RP_ENABLE | + GEN6_RP_UP_BUSY_AVG | + GEN6_RP_DOWN_IDLE_AVG); skip_hw_write: rps->power.mode = new_power; @@ -666,7 +665,7 @@ static int gen6_rps_set(struct intel_rps *rps, u8 val) swreq = (GEN6_FREQUENCY(val) | GEN6_OFFSET(0) | GEN6_AGGRESSIVE_TURBO); - intel_uncore_write(uncore, GEN6_RPNSWREQ, swreq); + set(uncore, GEN6_RPNSWREQ, swreq); return 0; } @@ -683,7 +682,7 @@ static int vlv_rps_set(struct intel_rps *rps, u8 val) return err; } -static int rps_set(struct intel_rps *rps, u8 val) +static int rps_set(struct intel_rps *rps, u8 val, bool update) { struct drm_i915_private *i915 = rps_to_i915(rps); int err; @@ -701,7 +700,8 @@ static int rps_set(struct intel_rps *rps, u8 val) if (err) return err; - gen6_rps_set_thresholds(rps, val); + if (update) + gen6_rps_set_thresholds(rps, val); rps->last_freq = val; return 0; @@ -761,7 +761,7 @@ void intel_rps_park(struct intel_rps *rps) * power than the render powerwell. */ intel_uncore_forcewake_get(rps_to_uncore(rps), FORCEWAKE_MEDIA); - rps_set(rps, rps->idle_freq); + rps_set(rps, rps->idle_freq, false); intel_uncore_forcewake_put(rps_to_uncore(rps), FORCEWAKE_MEDIA); } @@ -777,7 +777,7 @@ void intel_rps_boost(struct i915_request *rq) spin_lock_irqsave(&rq->lock, flags); if (!i915_request_has_waitboost(rq) && !dma_fence_is_signaled_locked(&rq->fence)) { - rq->flags |= I915_REQUEST_WAITBOOST; + set_bit(I915_FENCE_FLAG_BOOST, &rq->fence.flags); if (!atomic_fetch_inc(&rps->num_waiters) && READ_ONCE(rps->cur_freq) < rps->boost_freq) @@ -790,14 +790,16 @@ void intel_rps_boost(struct i915_request *rq) int intel_rps_set(struct intel_rps *rps, u8 val) { - int err = 0; + int err; lockdep_assert_held(&rps->lock); GEM_BUG_ON(val > rps->max_freq); GEM_BUG_ON(val < rps->min_freq); if (rps->active) { - err = rps_set(rps, val); + err = rps_set(rps, val, true); + if (err) + return err; /* * Make sure we continue to get interrupts @@ -806,18 +808,15 @@ int intel_rps_set(struct intel_rps *rps, u8 val) if (INTEL_GEN(rps_to_i915(rps)) >= 6) { struct intel_uncore *uncore = rps_to_uncore(rps); - intel_uncore_write(uncore, GEN6_RP_INTERRUPT_LIMITS, - rps_limits(rps, val)); + set(uncore, + GEN6_RP_INTERRUPT_LIMITS, rps_limits(rps, val)); - intel_uncore_write(uncore, GEN6_PMINTRMSK, - rps_pm_mask(rps, val)); + set(uncore, GEN6_PMINTRMSK, rps_pm_mask(rps, val)); } } - if (err == 0) - rps->cur_freq = val; - - return err; + rps->cur_freq = val; + return 0; } static void gen6_rps_init(struct intel_rps *rps) @@ -878,7 +877,7 @@ static bool rps_reset(struct intel_rps *rps) rps->power.mode = -1; rps->last_freq = -1; - if (rps_set(rps, rps->min_freq)) { + if (rps_set(rps, rps->min_freq, true)) { DRM_ERROR("Failed to reset RPS to initial values\n"); return false; } @@ -1201,7 +1200,7 @@ void intel_rps_enable(struct intel_rps *rps) static void gen6_rps_disable(struct intel_rps *rps) { - intel_uncore_write(rps_to_uncore(rps), GEN6_RP_CONTROL, 0); + set(rps_to_uncore(rps), GEN6_RP_CONTROL, 0); } void intel_rps_disable(struct intel_rps *rps) @@ -1566,7 +1565,7 @@ void gen6_rps_irq_handler(struct intel_rps *rps, u32 pm_iir) return; if (pm_iir & PM_VEBOX_USER_INTERRUPT) - intel_engine_breadcrumbs_irq(gt->engine[VECS0]); + intel_engine_signal_breadcrumbs(gt->engine[VECS0]); if (pm_iir & PM_VEBOX_CS_ERROR_INTERRUPT) DRM_DEBUG("Command parser error, pm_iir 0x%08x\n", pm_iir); @@ -1663,23 +1662,53 @@ void intel_rps_init(struct intel_rps *rps) if (INTEL_GEN(i915) <= 7) rps->pm_intrmsk_mbz |= GEN6_PM_RP_UP_EI_EXPIRED; - if (INTEL_GEN(i915) >= 8) + if (INTEL_GEN(i915) >= 8 && INTEL_GEN(i915) < 11) rps->pm_intrmsk_mbz |= GEN8_PMINTR_DISABLE_REDIRECT_TO_GUC; } -u32 intel_get_cagf(struct intel_rps *rps, u32 rpstat) +u32 intel_rps_get_cagf(struct intel_rps *rps, u32 rpstat) { struct drm_i915_private *i915 = rps_to_i915(rps); u32 cagf; - if (INTEL_GEN(i915) >= 9) + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) + cagf = (rpstat >> 8) & 0xff; + else if (INTEL_GEN(i915) >= 9) cagf = (rpstat & GEN9_CAGF_MASK) >> GEN9_CAGF_SHIFT; else if (IS_HASWELL(i915) || IS_BROADWELL(i915)) cagf = (rpstat & HSW_CAGF_MASK) >> HSW_CAGF_SHIFT; else cagf = (rpstat & GEN6_CAGF_MASK) >> GEN6_CAGF_SHIFT; - return cagf; + return cagf; +} + +static u32 read_cagf(struct intel_rps *rps) +{ + struct drm_i915_private *i915 = rps_to_i915(rps); + u32 freq; + + if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915)) { + vlv_punit_get(i915); + freq = vlv_punit_read(i915, PUNIT_REG_GPU_FREQ_STS); + vlv_punit_put(i915); + } else { + freq = intel_uncore_read(rps_to_gt(rps)->uncore, GEN6_RPSTAT1); + } + + return intel_rps_get_cagf(rps, freq); +} + +u32 intel_rps_read_actual_frequency(struct intel_rps *rps) +{ + struct intel_runtime_pm *rpm = rps_to_gt(rps)->uncore->rpm; + intel_wakeref_t wakeref; + u32 freq = 0; + + with_intel_runtime_pm_if_in_use(rpm, wakeref) + freq = intel_gpu_freq(rps, read_cagf(rps)); + + return freq; } /* External interface for intel_ips.ko */ @@ -1715,6 +1744,7 @@ void intel_rps_driver_register(struct intel_rps *rps) * set up, to avoid intel-ips sneaking in and reading bogus values. */ if (IS_GEN(gt->i915, 5)) { + GEM_BUG_ON(ips_mchdev); rcu_assign_pointer(ips_mchdev, gt->i915); ips_ping_for_i915_load(); } @@ -1722,7 +1752,8 @@ void intel_rps_driver_register(struct intel_rps *rps) void intel_rps_driver_unregister(struct intel_rps *rps) { - rcu_assign_pointer(ips_mchdev, NULL); + if (rcu_access_pointer(ips_mchdev) == rps_to_i915(rps)) + rcu_assign_pointer(ips_mchdev, NULL); } static struct drm_i915_private *mchdev_get(void) |