Merge tag 'drm-intel-gt-next-2021-01-14' of git://anongit.freedesktop.org/drm/drm...
[sfrench/cifs-2.6.git] / drivers / gpu / drm / i915 / i915_pmu.c
index d76685ce03998143a090a52e787f799bcfc19a5b..2b88c0baa1bf5e684faf4f409cc14a6967279372 100644 (file)
@@ -26,8 +26,6 @@
         BIT(I915_SAMPLE_WAIT) | \
         BIT(I915_SAMPLE_SEMA))
 
-#define ENGINE_SAMPLE_BITS (1 << I915_PMU_SAMPLE_BITS)
-
 static cpumask_t i915_pmu_cpumask;
 static unsigned int i915_pmu_target_cpu = -1;
 
@@ -56,17 +54,42 @@ static bool is_engine_config(u64 config)
        return config < __I915_PMU_OTHER(0);
 }
 
-static unsigned int config_enabled_bit(u64 config)
+static unsigned int other_bit(const u64 config)
+{
+       unsigned int val;
+
+       switch (config) {
+       case I915_PMU_ACTUAL_FREQUENCY:
+               val =  __I915_PMU_ACTUAL_FREQUENCY_ENABLED;
+               break;
+       case I915_PMU_REQUESTED_FREQUENCY:
+               val = __I915_PMU_REQUESTED_FREQUENCY_ENABLED;
+               break;
+       case I915_PMU_RC6_RESIDENCY:
+               val = __I915_PMU_RC6_RESIDENCY_ENABLED;
+               break;
+       default:
+               /*
+                * Events that do not require sampling, or tracking state
+                * transitions between enabled and disabled can be ignored.
+                */
+               return -1;
+       }
+
+       return I915_ENGINE_SAMPLE_COUNT + val;
+}
+
+static unsigned int config_bit(const u64 config)
 {
        if (is_engine_config(config))
                return engine_config_sample(config);
        else
-               return ENGINE_SAMPLE_BITS + (config - __I915_PMU_OTHER(0));
+               return other_bit(config);
 }
 
-static u64 config_enabled_mask(u64 config)
+static u64 config_mask(u64 config)
 {
-       return BIT_ULL(config_enabled_bit(config));
+       return BIT_ULL(config_bit(config));
 }
 
 static bool is_engine_event(struct perf_event *event)
@@ -74,15 +97,15 @@ static bool is_engine_event(struct perf_event *event)
        return is_engine_config(event->attr.config);
 }
 
-static unsigned int event_enabled_bit(struct perf_event *event)
+static unsigned int event_bit(struct perf_event *event)
 {
-       return config_enabled_bit(event->attr.config);
+       return config_bit(event->attr.config);
 }
 
 static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
 {
        struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
-       u64 enable;
+       u32 enable;
 
        /*
         * Only some counters need the sampling timer.
@@ -95,8 +118,8 @@ static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
         * Mask out all the ones which do not need the timer, or in
         * other words keep all the ones that could need the timer.
         */
-       enable &= config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
-                 config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) |
+       enable &= config_mask(I915_PMU_ACTUAL_FREQUENCY) |
+                 config_mask(I915_PMU_REQUESTED_FREQUENCY) |
                  ENGINE_SAMPLE_MASK;
 
        /*
@@ -137,11 +160,9 @@ static u64 __get_rc6(struct intel_gt *gt)
        return val;
 }
 
-#if IS_ENABLED(CONFIG_PM)
-
-static inline s64 ktime_since(const ktime_t kt)
+static inline s64 ktime_since_raw(const ktime_t kt)
 {
-       return ktime_to_ns(ktime_sub(ktime_get(), kt));
+       return ktime_to_ns(ktime_sub(ktime_get_raw(), kt));
 }
 
 static u64 get_rc6(struct intel_gt *gt)
@@ -170,7 +191,7 @@ static u64 get_rc6(struct intel_gt *gt)
                 * on top of the last known real value, as the approximated RC6
                 * counter value.
                 */
-               val = ktime_since(pmu->sleep_last);
+               val = ktime_since_raw(pmu->sleep_last);
                val += pmu->sample[__I915_SAMPLE_RC6].cur;
        }
 
@@ -184,26 +205,26 @@ static u64 get_rc6(struct intel_gt *gt)
        return val;
 }
 
-static void park_rc6(struct drm_i915_private *i915)
+static void init_rc6(struct i915_pmu *pmu)
 {
-       struct i915_pmu *pmu = &i915->pmu;
+       struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
+       intel_wakeref_t wakeref;
 
-       if (pmu->enable & config_enabled_mask(I915_PMU_RC6_RESIDENCY))
+       with_intel_runtime_pm(i915->gt.uncore->rpm, wakeref) {
                pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
-
-       pmu->sleep_last = ktime_get();
+               pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur =
+                                       pmu->sample[__I915_SAMPLE_RC6].cur;
+               pmu->sleep_last = ktime_get_raw();
+       }
 }
 
-#else
-
-static u64 get_rc6(struct intel_gt *gt)
+static void park_rc6(struct drm_i915_private *i915)
 {
-       return __get_rc6(gt);
-}
-
-static void park_rc6(struct drm_i915_private *i915) {}
+       struct i915_pmu *pmu = &i915->pmu;
 
-#endif
+       pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
+       pmu->sleep_last = ktime_get_raw();
+}
 
 static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)
 {
@@ -343,8 +364,8 @@ add_sample_mult(struct i915_pmu_sample *sample, u32 val, u32 mul)
 static bool frequency_sampling_enabled(struct i915_pmu *pmu)
 {
        return pmu->enable &
-              (config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
-               config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY));
+              (config_mask(I915_PMU_ACTUAL_FREQUENCY) |
+               config_mask(I915_PMU_REQUESTED_FREQUENCY));
 }
 
 static void
@@ -362,7 +383,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
        if (!intel_gt_pm_get_if_awake(gt))
                return;
 
-       if (pmu->enable & config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY)) {
+       if (pmu->enable & config_mask(I915_PMU_ACTUAL_FREQUENCY)) {
                u32 val;
 
                /*
@@ -384,7 +405,7 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns)
                                intel_gpu_freq(rps, val), period_ns / 1000);
        }
 
-       if (pmu->enable & config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY)) {
+       if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {
                add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],
                                intel_gpu_freq(rps, rps->cur_freq),
                                period_ns / 1000);
@@ -471,6 +492,8 @@ config_status(struct drm_i915_private *i915, u64 config)
                if (!HAS_RC6(i915))
                        return -ENODEV;
                break;
+       case I915_PMU_SOFTWARE_GT_AWAKE_TIME:
+               break;
        default:
                return -ENOENT;
        }
@@ -578,6 +601,9 @@ static u64 __i915_pmu_event_read(struct perf_event *event)
                case I915_PMU_RC6_RESIDENCY:
                        val = get_rc6(&i915->gt);
                        break;
+               case I915_PMU_SOFTWARE_GT_AWAKE_TIME:
+                       val = ktime_to_ns(intel_gt_get_awake_time(&i915->gt));
+                       break;
                }
        }
 
@@ -610,12 +636,14 @@ static void i915_pmu_enable(struct perf_event *event)
 {
        struct drm_i915_private *i915 =
                container_of(event->pmu, typeof(*i915), pmu.base);
-       unsigned int bit = event_enabled_bit(event);
        struct i915_pmu *pmu = &i915->pmu;
-       intel_wakeref_t wakeref;
        unsigned long flags;
+       unsigned int bit;
+
+       bit = event_bit(event);
+       if (bit == -1)
+               goto update;
 
-       wakeref = intel_runtime_pm_get(&i915->runtime_pm);
        spin_lock_irqsave(&pmu->lock, flags);
 
        /*
@@ -626,13 +654,6 @@ static void i915_pmu_enable(struct perf_event *event)
        GEM_BUG_ON(bit >= ARRAY_SIZE(pmu->enable_count));
        GEM_BUG_ON(pmu->enable_count[bit] == ~0);
 
-       if (pmu->enable_count[bit] == 0 &&
-           config_enabled_mask(I915_PMU_RC6_RESIDENCY) & BIT_ULL(bit)) {
-               pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = 0;
-               pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(&i915->gt);
-               pmu->sleep_last = ktime_get();
-       }
-
        pmu->enable |= BIT_ULL(bit);
        pmu->enable_count[bit]++;
 
@@ -667,24 +688,26 @@ static void i915_pmu_enable(struct perf_event *event)
 
        spin_unlock_irqrestore(&pmu->lock, flags);
 
+update:
        /*
         * Store the current counter value so we can report the correct delta
         * for all listeners. Even when the event was already enabled and has
         * an existing non-zero value.
         */
        local64_set(&event->hw.prev_count, __i915_pmu_event_read(event));
-
-       intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 }
 
 static void i915_pmu_disable(struct perf_event *event)
 {
        struct drm_i915_private *i915 =
                container_of(event->pmu, typeof(*i915), pmu.base);
-       unsigned int bit = event_enabled_bit(event);
+       unsigned int bit = event_bit(event);
        struct i915_pmu *pmu = &i915->pmu;
        unsigned long flags;
 
+       if (bit == -1)
+               return;
+
        spin_lock_irqsave(&pmu->lock, flags);
 
        if (is_engine_event(event)) {
@@ -881,6 +904,7 @@ create_event_attributes(struct i915_pmu *pmu)
                __event(I915_PMU_REQUESTED_FREQUENCY, "requested-frequency", "M"),
                __event(I915_PMU_INTERRUPTS, "interrupts", NULL),
                __event(I915_PMU_RC6_RESIDENCY, "rc6-residency", "ns"),
+               __event(I915_PMU_SOFTWARE_GT_AWAKE_TIME, "software-gt-awake-time", "ns"),
        };
        static const struct {
                enum drm_i915_pmu_engine_sample sample;
@@ -1130,6 +1154,7 @@ void i915_pmu_register(struct drm_i915_private *i915)
        hrtimer_init(&pmu->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
        pmu->timer.function = i915_sample;
        pmu->cpuhp.cpu = -1;
+       init_rc6(pmu);
 
        if (!is_igp(i915)) {
                pmu->name = kasprintf(GFP_KERNEL,