[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