[PATCH] pmu read delayed timer

Tvrtko Ursulin tursulin at ursulin.net
Wed Jun 6 09:05:37 UTC 2018


From: Tvrtko Ursulin <tvrtko.ursulin at intel.com>

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin at intel.com>
---
 drivers/gpu/drm/i915/i915_pmu.c | 53 ++++++++++++++++++++++++++-------
 1 file changed, 42 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_pmu.c b/drivers/gpu/drm/i915/i915_pmu.c
index c39541ed2219..2c9bd446cc6b 100644
--- a/drivers/gpu/drm/i915/i915_pmu.c
+++ b/drivers/gpu/drm/i915/i915_pmu.c
@@ -69,6 +69,20 @@ static unsigned int event_enabled_bit(struct perf_event *event)
 	return config_enabled_bit(event->attr.config);
 }
 
+static u64 __sampling_events_mask(struct drm_i915_private *i915)
+{
+	u64 mask;
+
+	mask = config_enabled_mask(I915_PMU_ACTUAL_FREQUENCY) |
+	       config_enabled_mask(I915_PMU_REQUESTED_FREQUENCY) |
+	       ENGINE_SAMPLE_MASK;
+
+	if (intel_engine_supports_stats(i915->engine[RCS]))
+		mask &= ~BIT(I915_SAMPLE_BUSY);
+
+	return mask;
+}
+
 static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
 {
 	u64 enable;
@@ -84,9 +98,7 @@ static bool pmu_needs_timer(struct drm_i915_private *i915, 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) |
-		  ENGINE_SAMPLE_MASK;
+	enable &= __sampling_events_mask(i915);
 
 	/*
 	 * When the GPU is idle per-engine counters do not need to be
@@ -94,14 +106,6 @@ static bool pmu_needs_timer(struct drm_i915_private *i915, bool gpu_active)
 	 */
 	if (!gpu_active)
 		enable &= ~ENGINE_SAMPLE_MASK;
-	/*
-	 * Also there is software busyness tracking available we do not
-	 * need the timer for I915_SAMPLE_BUSY counter.
-	 *
-	 * Use RCS as proxy for all engines.
-	 */
-	else if (intel_engine_supports_stats(i915->engine[RCS]))
-		enable &= ~BIT(I915_SAMPLE_BUSY);
 
 	/*
 	 * If some bits remain it means we need the sampling timer running.
@@ -519,12 +523,39 @@ static u64 get_rc6(struct drm_i915_private *i915)
 #endif
 }
 
+static bool
+event_is_sampled(struct drm_i915_private *i915, struct perf_event *event)
+{
+	return __sampling_events_mask(i915) & event_enabled_bit(event);
+}
+
 static u64 __i915_pmu_event_read(struct perf_event *event)
 {
 	struct drm_i915_private *i915 =
 		container_of(event->pmu, typeof(*i915), pmu.base);
 	u64 val = 0;
 
+	if (i915->pmu.timer_enabled && event_is_sampled(i915, event)) {
+		unsigned int delay_ns;
+		unsigned long flags;
+
+		spin_lock_irqsave(&i915->pmu.lock, flags);
+
+		delay_ns = ktime_to_ns(ktime_sub(ktime_get(),
+						 i915->pmu.timer_last));
+
+		if (delay_ns > 105 * PERIOD / 100) {
+			DRM_WARN("[%llx] nudging delayed timer (%uns)",
+				 event->attr.config,
+				 delay_ns);
+			hrtimer_cancel(&i915->pmu.timer);
+			i915_sample(&i915->pmu.timer);
+			hrtimer_restart(&i915->pmu.timer);
+		}
+
+		spin_unlock_irqrestore(&i915->pmu.lock, flags);
+	}
+
 	if (is_engine_event(event)) {
 		u8 sample = engine_event_sample(event);
 		struct intel_engine_cs *engine;
-- 
2.17.1



More information about the Intel-gfx-trybot mailing list