History

drm/i915/pmu: Prepare for multi-tile non-engine counters

Reserve some bits in the counter config namespace which will carry the tile id and prepare the code to handle this. No per tile counters have been added yet. v2: - Fix checkpatch issues - Use 4 bits for gt id in non-engine counters. Drop FIXME. - Set MAX GTs to 4. Drop FIXME. v3: (Ashutosh, Tvrtko) - Drop BUG_ON that would never fire - Make enable u64 - Pull in some code from next patch v4: Set I915_PMU_MAX_GTS to 2 (Tvrtko) v5: s/u64/u32 where needed (Ashutosh)

Tvrtko Ursulin committed 3 years ago

Commit bc4be0a1 parent b319cc53 files · +127 −45Browse files

Unified · Split

3 files
  1. drivers/gpu/drm/i915/i915_pmu.c +105 −41
  2. drivers/gpu/drm/i915/i915_pmu.h +6 −3
  3. include/uapi/drm/i915_drm.h +16 −1
drivers/gpu/drm/i915/i915_pmu.c+105−41
@@ -56,11 +56,21 @@ static bool is_engine_config(const u64 config) · 55 unmodified lines
56 return config < __I915_PMU_OTHER(0);56 return config < __I915_PMU_OTHER(0);
57}57}
58 58
59static unsigned int config_gt_id(const u64 config)
60{
61 return config >> __I915_PMU_GT_SHIFT;
62}
63
64static u64 config_counter(const u64 config)
65{
66 return config & ~(~0ULL << __I915_PMU_GT_SHIFT);
67}
68
59static unsigned int other_bit(const u64 config)69static unsigned int other_bit(const u64 config)
60{70{
61 unsigned int val;71 unsigned int val;
62 72
63 switch (config) {73 switch (config_counter(config)) {
64 case I915_PMU_ACTUAL_FREQUENCY:74 case I915_PMU_ACTUAL_FREQUENCY:
65 val = __I915_PMU_ACTUAL_FREQUENCY_ENABLED;75 val = __I915_PMU_ACTUAL_FREQUENCY_ENABLED;
66 break;76 break;
@@ -78,7 +88,9 @@ static unsigned int other_bit(const u64 config) · 11 unmodified lines
78 return -1;88 return -1;
79 }89 }
80 90
81 return I915_ENGINE_SAMPLE_COUNT + val;91 return I915_ENGINE_SAMPLE_COUNT +
92 config_gt_id(config) * __I915_PMU_TRACKED_EVENT_COUNT +
93 val;
82}94}
83 95
84static unsigned int config_bit(const u64 config)96static unsigned int config_bit(const u64 config)
@@ -115,6 +127,18 @@ static unsigned int event_bit(struct perf_event *event) · 30 unmodified lines
115 return config_bit(event->attr.config);127 return config_bit(event->attr.config);
116}128}
117 129
130static u32 frequency_enabled_mask(void)
131{
132 unsigned int i;
133 u32 mask = 0;
134
135 for (i = 0; i < I915_PMU_MAX_GTS; i++)
136 mask |= config_mask(__I915_PMU_ACTUAL_FREQUENCY(i)) |
137 config_mask(__I915_PMU_REQUESTED_FREQUENCY(i));
138
139 return mask;
140}
141
118static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)142static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active)
119{143{
120 struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);144 struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
@@ -131,9 +155,7 @@ static bool pmu_needs_timer(struct i915_pmu *pmu, bool gpu_active) · 10 unmodified lines
131 * Mask out all the ones which do not need the timer, or in155 * Mask out all the ones which do not need the timer, or in
132 * other words keep all the ones that could need the timer.156 * other words keep all the ones that could need the timer.
133 */157 */
134 enable &= config_mask(I915_PMU_ACTUAL_FREQUENCY) |158 enable &= frequency_enabled_mask() | ENGINE_SAMPLE_MASK;
135 config_mask(I915_PMU_REQUESTED_FREQUENCY) |
136 ENGINE_SAMPLE_MASK;
137 159
138 /*160 /*
139 * When the GPU is idle per-engine counters do not need to be161 * When the GPU is idle per-engine counters do not need to be
@@ -175,9 +197,37 @@ static inline s64 ktime_since_raw(const ktime_t kt) · 35 unmodified lines
175 return ktime_to_ns(ktime_sub(ktime_get_raw(), kt));197 return ktime_to_ns(ktime_sub(ktime_get_raw(), kt));
176}198}
177 199
200static unsigned int
201__sample_idx(struct i915_pmu *pmu, unsigned int gt_id, int sample)
202{
203 unsigned int idx = gt_id * __I915_NUM_PMU_SAMPLERS + sample;
204
205 GEM_BUG_ON(idx >= ARRAY_SIZE(pmu->sample));
206
207 return idx;
208}
209
210static u64 read_sample(struct i915_pmu *pmu, unsigned int gt_id, int sample)
211{
212 return pmu->sample[__sample_idx(pmu, gt_id, sample)].cur;
213}
214
215static void
216store_sample(struct i915_pmu *pmu, unsigned int gt_id, int sample, u64 val)
217{
218 pmu->sample[__sample_idx(pmu, gt_id, sample)].cur = val;
219}
220
221static void
222add_sample_mult(struct i915_pmu *pmu, unsigned int gt_id, int sample, u32 val, u32 mul)
223{
224 pmu->sample[__sample_idx(pmu, gt_id, sample)].cur += mul_u32_u32(val, mul);
225}
226
178static u64 get_rc6(struct intel_gt *gt)227static u64 get_rc6(struct intel_gt *gt)
179{228{
180 struct drm_i915_private *i915 = gt->i915;229 struct drm_i915_private *i915 = gt->i915;
230 const unsigned int gt_id = gt->info.id;
181 struct i915_pmu *pmu = &i915->pmu;231 struct i915_pmu *pmu = &i915->pmu;
182 unsigned long flags;232 unsigned long flags;
183 bool awake = false;233 bool awake = false;
@@ -192,7 +242,7 @@ static u64 get_rc6(struct intel_gt *gt) · 8 unmodified lines
192 spin_lock_irqsave(&pmu->lock, flags);242 spin_lock_irqsave(&pmu->lock, flags);
193 243
194 if (awake) {244 if (awake) {
195 pmu->sample[__I915_SAMPLE_RC6].cur = val;245 store_sample(pmu, gt_id, __I915_SAMPLE_RC6, val);
196 } else {246 } else {
197 /*247 /*
198 * We think we are runtime suspended.248 * We think we are runtime suspended.
@@ -201,14 +251,14 @@ static u64 get_rc6(struct intel_gt *gt) · 2 unmodified lines
201 * on top of the last known real value, as the approximated RC6251 * on top of the last known real value, as the approximated RC6
202 * counter value.252 * counter value.
203 */253 */
204 val = ktime_since_raw(pmu->sleep_last);254 val = ktime_since_raw(pmu->sleep_last[gt_id]);
205 val += pmu->sample[__I915_SAMPLE_RC6].cur;255 val += read_sample(pmu, gt_id, __I915_SAMPLE_RC6);
206 }256 }
207 257
208 if (val < pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur)258 if (val < read_sample(pmu, gt_id, __I915_SAMPLE_RC6_LAST_REPORTED))
209 val = pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur;259 val = read_sample(pmu, gt_id, __I915_SAMPLE_RC6_LAST_REPORTED);
210 else260 else
211 pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur = val;261 store_sample(pmu, gt_id, __I915_SAMPLE_RC6_LAST_REPORTED, val);
212 262
213 spin_unlock_irqrestore(&pmu->lock, flags);263 spin_unlock_irqrestore(&pmu->lock, flags);
214 264
@@ -218,13 +268,20 @@ static u64 get_rc6(struct intel_gt *gt) · 3 unmodified lines
218static void init_rc6(struct i915_pmu *pmu)268static void init_rc6(struct i915_pmu *pmu)
219{269{
220 struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);270 struct drm_i915_private *i915 = container_of(pmu, typeof(*i915), pmu);
221 intel_wakeref_t wakeref;271 struct intel_gt *gt;
272 unsigned int i;
273
274 for_each_gt(gt, i915, i) {
275 intel_wakeref_t wakeref;
276
277 with_intel_runtime_pm(gt->uncore->rpm, wakeref) {
278 u64 val = __get_rc6(gt);
222 279
223 with_intel_runtime_pm(to_gt(i915)->uncore->rpm, wakeref) {280 store_sample(pmu, i, __I915_SAMPLE_RC6, val);
224 pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(to_gt(i915));281 store_sample(pmu, i, __I915_SAMPLE_RC6_LAST_REPORTED,
225 pmu->sample[__I915_SAMPLE_RC6_LAST_REPORTED].cur =282 val);
226 pmu->sample[__I915_SAMPLE_RC6].cur;283 pmu->sleep_last[i] = ktime_get_raw();
227 pmu->sleep_last = ktime_get_raw();284 }
228 }285 }
229}286}
230 287
@@ -232,8 +289,8 @@ static void park_rc6(struct intel_gt *gt) · 1 unmodified line
232{289{
233 struct i915_pmu *pmu = &gt->i915->pmu;290 struct i915_pmu *pmu = &gt->i915->pmu;
234 291
235 pmu->sample[__I915_SAMPLE_RC6].cur = __get_rc6(gt);292 store_sample(pmu, gt->info.id, __I915_SAMPLE_RC6, __get_rc6(gt));
236 pmu->sleep_last = ktime_get_raw();293 pmu->sleep_last[gt->info.id] = ktime_get_raw();
237}294}
238 295
239static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)296static void __i915_pmu_maybe_start_timer(struct i915_pmu *pmu)
@@ -373,34 +430,30 @@ engines_sample(struct intel_gt *gt, unsigned int period_ns) · 133 unmodified lines
373 }430 }
374}431}
375 432
376static void433static bool
377add_sample_mult(struct i915_pmu_sample *sample, u32 val, u32 mul)434frequency_sampling_enabled(struct i915_pmu *pmu, unsigned int gt)
378{
379 sample->cur += mul_u32_u32(val, mul);
380}
381
382static bool frequency_sampling_enabled(struct i915_pmu *pmu)
383{435{
384 return pmu->enable &436 return pmu->enable &
385 (config_mask(I915_PMU_ACTUAL_FREQUENCY) |437 (config_mask(__I915_PMU_ACTUAL_FREQUENCY(gt)) |
386 config_mask(I915_PMU_REQUESTED_FREQUENCY));438 config_mask(__I915_PMU_REQUESTED_FREQUENCY(gt)));
387}439}
388 440
389static void441static void
390frequency_sample(struct intel_gt *gt, unsigned int period_ns)442frequency_sample(struct intel_gt *gt, unsigned int period_ns)
391{443{
392 struct drm_i915_private *i915 = gt->i915;444 struct drm_i915_private *i915 = gt->i915;
445 const unsigned int gt_id = gt->info.id;
393 struct i915_pmu *pmu = &i915->pmu;446 struct i915_pmu *pmu = &i915->pmu;
394 struct intel_rps *rps = &gt->rps;447 struct intel_rps *rps = &gt->rps;
395 448
396 if (!frequency_sampling_enabled(pmu))449 if (!frequency_sampling_enabled(pmu, gt_id))
397 return;450 return;
398 451
399 /* Report 0/0 (actual/requested) frequency while parked. */452 /* Report 0/0 (actual/requested) frequency while parked. */
400 if (!intel_gt_pm_get_if_awake(gt))453 if (!intel_gt_pm_get_if_awake(gt))
401 return;454 return;
402 455
403 if (pmu->enable & config_mask(I915_PMU_ACTUAL_FREQUENCY)) {456 if (pmu->enable & config_mask(__I915_PMU_ACTUAL_FREQUENCY(gt_id))) {
404 u32 val;457 u32 val;
405 458
406 /*459 /*
@@ -416,12 +469,12 @@ frequency_sample(struct intel_gt *gt, unsigned int period_ns) · 9 unmodified lines
416 if (!val)469 if (!val)
417 val = intel_gpu_freq(rps, rps->cur_freq);470 val = intel_gpu_freq(rps, rps->cur_freq);
418 471
419 add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_ACT],472 add_sample_mult(pmu, gt_id, __I915_SAMPLE_FREQ_ACT,
420 val, period_ns / 1000);473 val, period_ns / 1000);
421 }474 }
422 475
423 if (pmu->enable & config_mask(I915_PMU_REQUESTED_FREQUENCY)) {476 if (pmu->enable & config_mask(__I915_PMU_REQUESTED_FREQUENCY(gt_id))) {
424 add_sample_mult(&pmu->sample[__I915_SAMPLE_FREQ_REQ],477 add_sample_mult(pmu, gt_id, __I915_SAMPLE_FREQ_REQ,
425 intel_rps_get_requested_frequency(rps),478 intel_rps_get_requested_frequency(rps),
426 period_ns / 1000);479 period_ns / 1000);
427 }480 }
@@ -458,9 +511,7 @@ static enum hrtimer_restart i915_sample(struct hrtimer *hrtimer) · 30 unmodified lines
458 continue;511 continue;
459 512
460 engines_sample(gt, period_ns);513 engines_sample(gt, period_ns);
461 514 frequency_sample(gt, period_ns);
462 if (i == 0) /* FIXME */
463 frequency_sample(gt, period_ns);
464 }515 }
465 516
466 hrtimer_forward(hrtimer, now, ns_to_ktime(PERIOD));517 hrtimer_forward(hrtimer, now, ns_to_ktime(PERIOD));
@@ -502,7 +553,13 @@ config_status(struct drm_i915_private *i915, u64 config) · 35 unmodified lines
502{553{
503 struct intel_gt *gt = to_gt(i915);554 struct intel_gt *gt = to_gt(i915);
504 555
505 switch (config) {556 unsigned int gt_id = config_gt_id(config);
557 unsigned int max_gt_id = HAS_EXTRA_GT_LIST(i915) ? 1 : 0;
558
559 if (gt_id > max_gt_id)
560 return -ENOENT;
561
562 switch (config_counter(config)) {
506 case I915_PMU_ACTUAL_FREQUENCY:563 case I915_PMU_ACTUAL_FREQUENCY:
507 if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))564 if (IS_VALLEYVIEW(i915) || IS_CHERRYVIEW(i915))
508 /* Requires a mutex for sampling! */565 /* Requires a mutex for sampling! */
@@ -513,6 +570,8 @@ config_status(struct drm_i915_private *i915, u64 config) · 4 unmodified lines
513 return -ENODEV;570 return -ENODEV;
514 break;571 break;
515 case I915_PMU_INTERRUPTS:572 case I915_PMU_INTERRUPTS:
573 if (gt_id)
574 return -ENOENT;
516 break;575 break;
517 case I915_PMU_RC6_RESIDENCY:576 case I915_PMU_RC6_RESIDENCY:
518 if (!gt->rc6.supported)577 if (!gt->rc6.supported)
@@ -610,22 +669,27 @@ static u64 __i915_pmu_event_read(struct perf_event *event) · 91 unmodified lines
610 val = engine->pmu.sample[sample].cur;669 val = engine->pmu.sample[sample].cur;
611 }670 }
612 } else {671 } else {
613 switch (event->attr.config) {672 const unsigned int gt_id = config_gt_id(event->attr.config);
673 const u64 config = config_counter(event->attr.config);
674
675 switch (config) {
614 case I915_PMU_ACTUAL_FREQUENCY:676 case I915_PMU_ACTUAL_FREQUENCY:
615 val =677 val =
616 div_u64(pmu->sample[__I915_SAMPLE_FREQ_ACT].cur,678 div_u64(read_sample(pmu, gt_id,
679 __I915_SAMPLE_FREQ_ACT),
617 USEC_PER_SEC /* to MHz */);680 USEC_PER_SEC /* to MHz */);
618 break;681 break;
619 case I915_PMU_REQUESTED_FREQUENCY:682 case I915_PMU_REQUESTED_FREQUENCY:
620 val =683 val =
621 div_u64(pmu->sample[__I915_SAMPLE_FREQ_REQ].cur,684 div_u64(read_sample(pmu, gt_id,
685 __I915_SAMPLE_FREQ_REQ),
622 USEC_PER_SEC /* to MHz */);686 USEC_PER_SEC /* to MHz */);
623 break;687 break;
624 case I915_PMU_INTERRUPTS:688 case I915_PMU_INTERRUPTS:
625 val = READ_ONCE(pmu->irq_count);689 val = READ_ONCE(pmu->irq_count);
626 break;690 break;
627 case I915_PMU_RC6_RESIDENCY:691 case I915_PMU_RC6_RESIDENCY:
628 val = get_rc6(to_gt(i915));692 val = get_rc6(i915->gt[gt_id]);
629 break;693 break;
630 case I915_PMU_SOFTWARE_GT_AWAKE_TIME:694 case I915_PMU_SOFTWARE_GT_AWAKE_TIME:
631 val = ktime_to_ns(intel_gt_get_awake_time(to_gt(i915)));695 val = ktime_to_ns(intel_gt_get_awake_time(to_gt(i915)));
drivers/gpu/drm/i915/i915_pmu.h+6−3
@@ -38,13 +38,16 @@ enum { · 37 unmodified lines
38 __I915_NUM_PMU_SAMPLERS38 __I915_NUM_PMU_SAMPLERS
39};39};
40 40
41#define I915_PMU_MAX_GTS 2
42
41/*43/*
42 * How many different events we track in the global PMU mask.44 * How many different events we track in the global PMU mask.
43 *45 *
44 * It is also used to know to needed number of event reference counters.46 * It is also used to know to needed number of event reference counters.
45 */47 */
46#define I915_PMU_MASK_BITS \48#define I915_PMU_MASK_BITS \
47 (I915_ENGINE_SAMPLE_COUNT + __I915_PMU_TRACKED_EVENT_COUNT)49 (I915_ENGINE_SAMPLE_COUNT + \
50 I915_PMU_MAX_GTS * __I915_PMU_TRACKED_EVENT_COUNT)
48 51
49#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)52#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
50 53
@@ -124,11 +127,11 @@ struct i915_pmu { · 73 unmodified lines
124 * Only global counters are held here, while the per-engine ones are in127 * Only global counters are held here, while the per-engine ones are in
125 * struct intel_engine_cs.128 * struct intel_engine_cs.
126 */129 */
127 struct i915_pmu_sample sample[__I915_NUM_PMU_SAMPLERS];130 struct i915_pmu_sample sample[I915_PMU_MAX_GTS * __I915_NUM_PMU_SAMPLERS];
128 /**131 /**
129 * @sleep_last: Last time GT parked for RC6 estimation.132 * @sleep_last: Last time GT parked for RC6 estimation.
130 */133 */
131 ktime_t sleep_last;134 ktime_t sleep_last[I915_PMU_MAX_GTS];
132 /**135 /**
133 * @irq_count: Number of interrupts136 * @irq_count: Number of interrupts
134 *137 *
include/uapi/drm/i915_drm.h+16−1
@@ -280,7 +280,16 @@ enum drm_i915_pmu_engine_sample { · 279 unmodified lines
280#define I915_PMU_ENGINE_SEMA(class, instance) \280#define I915_PMU_ENGINE_SEMA(class, instance) \
281 __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)281 __I915_PMU_ENGINE(class, instance, I915_SAMPLE_SEMA)
282 282
283#define __I915_PMU_OTHER(x) (__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x))283/*
284 * Top 4 bits of every non-engine counter are GT id.
285 */
286#define __I915_PMU_GT_SHIFT (60)
287
288#define ___I915_PMU_OTHER(gt, x) \
289 (((__u64)__I915_PMU_ENGINE(0xff, 0xff, 0xf) + 1 + (x)) | \
290 ((__u64)(gt) << __I915_PMU_GT_SHIFT))
291
292#define __I915_PMU_OTHER(x) ___I915_PMU_OTHER(0, x)
284 293
285#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0)294#define I915_PMU_ACTUAL_FREQUENCY __I915_PMU_OTHER(0)
286#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1)295#define I915_PMU_REQUESTED_FREQUENCY __I915_PMU_OTHER(1)
@@ -290,6 +299,12 @@ enum drm_i915_pmu_engine_sample { · 3 unmodified lines
290 299
291#define I915_PMU_LAST /* Deprecated - do not use */ I915_PMU_RC6_RESIDENCY300#define I915_PMU_LAST /* Deprecated - do not use */ I915_PMU_RC6_RESIDENCY
292 301
302#define __I915_PMU_ACTUAL_FREQUENCY(gt) ___I915_PMU_OTHER(gt, 0)
303#define __I915_PMU_REQUESTED_FREQUENCY(gt) ___I915_PMU_OTHER(gt, 1)
304#define __I915_PMU_INTERRUPTS(gt) ___I915_PMU_OTHER(gt, 2)
305#define __I915_PMU_RC6_RESIDENCY(gt) ___I915_PMU_OTHER(gt, 3)
306#define __I915_PMU_SOFTWARE_GT_AWAKE_TIME(gt) ___I915_PMU_OTHER(gt, 4)
307
293/* Each region is a minimum of 16k, and there are at most 255 of them.308/* Each region is a minimum of 16k, and there are at most 255 of them.
294 */309 */
295#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use310#define I915_NR_TEX_REGIONS 255 /* table size 2k - maximum due to use